Scippy

SCIP

Solving Constraint Integer Programs

cons_abspower.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_abspower.c
17  * @brief Constraint handler for absolute power constraints \f$\textrm{lhs} \leq \textrm{sign}(x+a) |x+a|^n + c z \leq \textrm{rhs}\f$
18  * @author Stefan Vigerske
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 #include <ctype.h>
26 
27 #include "scip/cons_abspower.h"
28 #include "scip/cons_nonlinear.h"
29 #include "scip/cons_indicator.h"
30 #include "scip/cons_quadratic.h"
31 #include "scip/cons_linear.h"
32 #include "scip/cons_varbound.h"
33 #include "scip/intervalarith.h"
34 #include "scip/heur_subnlp.h"
35 #include "scip/heur_trysol.h"
36 #include "scip/debug.h"
37 
38 /* constraint handler properties */
39 #define CONSHDLR_NAME "abspower"
40 #define CONSHDLR_DESC "constraint handler for absolute power constraints lhs <= sign(x+offset)abs(x+offset)^n + c*z <= rhs"
41 #define CONSHDLR_SEPAPRIORITY 0 /**< priority of the constraint handler for separation */
42 #define CONSHDLR_ENFOPRIORITY -30 /**< priority of the constraint handler for constraint enforcing */
43 #define CONSHDLR_CHECKPRIORITY -3500000 /**< priority of the constraint handler for checking feasibility */
44 #define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
45 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
46 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
47  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
48 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
49 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
50 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
51 #define CONSHDLR_DELAYPRESOL FALSE /**< should presolving method be delayed, if other presolvers found reductions? */
52 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
53 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_ALWAYS /**< when should the constraint handlers propagation routines be called? */
54 
55 #define QUADCONSUPGD_PRIORITY 50000 /**< priority of the constraint handler for upgrading of quadratic constraints */
56 #define NONLINCONSUPGD_PRIORITY 50000 /**< priority of the constraint handler for upgrading of nonlinear constraints and reformulating expression graph nodes */
57 
58 /*
59  * Local defines
60  */
61 
62 #define PROPVARTOL SCIPepsilon(scip) /**< tolerance to add to variable bounds in domain propagation */
63 #define PROPSIDETOL SCIPepsilon(scip) /**< tolerance to add to constraint sides in domain propagation */
64 #define INITLPMAXVARVAL 1000.0 /**< maximal absolute value of variable for still generating a linearization cut at that point in initlp */
65 
66 /** power function type to be used by a constraint instead of the general pow */
67 #define DECL_MYPOW(x) SCIP_Real x (SCIP_Real base, SCIP_Real exponent)
68 
69 /** sign of a value (-1 or +1)
70  *
71  * 0.0 has sign +1
72  */
73 #define SIGN(x) ((x) >= 0.0 ? 1.0 : -1.0)
74 
75 
76 /*
77  * Data structures
78  */
79 
80 #define ROOTS_KNOWN 10 /**< up to which (integer) exponents precomputed roots have been stored */
81 
82 /** The positive root of the polynomial (n-1) y^n + n y^(n-1) - 1 is needed in separation.
83  * Here we store these roots for small integer values of n.
84  */
85 static
87  -1.0, /* no root for n=0 */
88  -1.0, /* no root for n=1 */
89  0.41421356237309504880, /* root for n=2 (-1+sqrt(2)) */
90  0.5, /* root for n=3 */
91  0.56042566045031785945, /* root for n=4 */
92  0.60582958618826802099, /* root for n=5 */
93  0.64146546982884663257, /* root for n=6 */
94  0.67033204760309682774, /* root for n=7 */
95  0.69428385661425826738, /* root for n=8 */
96  0.71453772716733489700, /* root for n=9 */
97  0.73192937842370733350 /* root for n=10 */
98 };
99 
100 /** constraint data for absolute power constraints */
101 struct SCIP_ConsData
102 {
103  SCIP_VAR* x; /**< variable x in sign(x+offset)|x+offset|^n term */
104  SCIP_VAR* z; /**< linear variable in constraint */
105  SCIP_Real exponent; /**< exponent n of |x+offset| */
106  SCIP_Real xoffset; /**< offset in x+offset */
107  SCIP_Real zcoef; /**< coefficient of linear variable z */
108  SCIP_Real lhs; /**< left hand side of constraint */
109  SCIP_Real rhs; /**< right hand side of constraint */
110 
111  SCIP_Real root; /**< root of polynomial */
112  DECL_MYPOW ((*power)); /**< function for computing power*/
113 
114  SCIP_Real lhsviol; /**< current (scaled) violation of left hand side */
115  SCIP_Real rhsviol; /**< current (scaled) violation of right hand side */
116 
117  SCIP_Bool isxpropagated; /**< have all bound tightenings on x been propagated? */
118  SCIP_Bool iszpropagated; /**< have all bound tightenings on z been propagated? */
119  int xeventfilterpos; /**< position of x var event in SCIP event filter */
120  int zeventfilterpos; /**< position of z var event in SCIP event filter */
121  unsigned int propvarbounds:1; /**< have variable bounds been propagated? */
122 
123  SCIP_NLROW* nlrow; /**< nonlinear row representation of constraint */
124 };
125 
126 /** constraint handler data */
127 struct SCIP_ConshdlrData
128 {
129  SCIP_Real mincutefficacysepa; /**< minimal efficacy of a cut in order to add it to relaxation during separation */
130  SCIP_Real mincutefficacyenfofac;/**< minimal target efficacy of a cut in order to add it to relaxation during enforcement as factor of feasibility tolerance (may be ignored) */
131  char scaling; /**< scaling method of constraints in feasibility check */
132  SCIP_Real cutmaxrange; /**< maximal coef range (maximal abs coef / minimal abs coef) of a cut in order to be added to LP */
133  SCIP_Bool projectrefpoint; /**< whether to project the reference point when linearizing a absolute power constraint in a convex region */
134  int preferzerobranch; /**< how much we prefer to branch on 0.0 first */
135  SCIP_Bool branchminconverror; /**< whether to compute branching point such that the convexification error is minimized after branching on 0.0 */
136  SCIP_Bool addvarboundcons; /**< should variable bound constraints be added? */
137  SCIP_Bool linfeasshift; /**< try linear feasibility shift heuristic in CONSCHECK */
138  SCIP_Bool dualpresolve; /**< should dual presolve be applied? */
139  SCIP_Bool sepainboundsonly; /**< should tangents only be generated in variable bounds during separation? */
140  SCIP_Real sepanlpmincont; /**< minimal required fraction of continuous variables in problem to use solution of NLP relaxation in root for separation */
141  SCIP_Bool enfocutsremovable; /**< are cuts added during enforcement removable from the LP in the same node? */
142 
143  SCIP_HEUR* subnlpheur; /**< a pointer to the subnlp heuristic */
144  SCIP_HEUR* trysolheur; /**< a pointer to the trysol heuristic */
145  SCIP_EVENTHDLR* eventhdlr; /**< our handler for bound change events on variable x */
146  SCIP_CONSHDLR* conshdlrindicator; /**< a pointer to the indicator constraint handler */
147  int newsoleventfilterpos;/**< filter position of new solution event handler, if catched */
148  SCIP_Bool comparedpairwise; /**< did we compare absolute power constraints pairwise in this run? */
149  SCIP_Bool sepanlp; /**< where linearization of the NLP relaxation solution added? */
150  SCIP_NODE* lastenfolpnode; /**< the node for which enforcement was called the last time (and some constraint was violated) */
151  int nenfolprounds; /**< counter on number of enforcement rounds for the current node */
152  unsigned int nsecantcuts; /**< number of secant cuts created so far */
153  unsigned int ncuts; /**< number of linearization cuts created so far */
154 };
155 
156 /*
157  * Propagation rules
158  */
159 
160 enum Proprule
161 {
162  PROPRULE_1, /**< left hand side and bounds on z -> lower bound on x */
163  PROPRULE_2, /**< left hand side and upper bound on x -> bound on z */
164  PROPRULE_3, /**< right hand side and bounds on z -> upper bound on x */
165  PROPRULE_4, /**< right hand side and lower bound on x -> bound on z */
166  PROPRULE_INVALID /**< propagation was applied without a specific propagation rule */
167 };
168 typedef enum Proprule PROPRULE;
170 /*
171  * Local methods
172  */
173 
174 /** power function for square, that should be faster than using pow(x, 2.0) */
175 static
177 {
178  assert(exponent == 2.0);
179  return base*base;
180 }
181 
182 /** process variable event */
183 static
184 SCIP_DECL_EVENTEXEC(processVarEvent)
185 {
186  SCIP_Bool* ispropagated;
187 
188  assert(scip != NULL);
189  assert(event != NULL);
191 
192  ispropagated = (SCIP_Bool*)eventdata;
193  assert(ispropagated != NULL);
194 
195  *ispropagated = FALSE;
196 
197  return SCIP_OKAY;
198 } /*lint !e715*/
199 
200 /** catch variable bound tightening events */
201 static
203  SCIP* scip, /**< SCIP data structure */
204  SCIP_EVENTHDLR* eventhdlr, /**< event handler for variables */
205  SCIP_CONS* cons /**< constraint for which to catch bound change events */
206  )
207 {
208  SCIP_CONSDATA* consdata;
209  SCIP_EVENTTYPE eventtype;
210 
211  assert(scip != NULL);
212  assert(cons != NULL);
213  assert(eventhdlr != NULL);
214 
215  consdata = SCIPconsGetData(cons);
216  assert(consdata != NULL);
217 
218  /* if z is multiaggregated, then bound changes on x could not be propagated, so we do not need to catch them */
219  if( SCIPvarGetStatus(consdata->z) != SCIP_VARSTATUS_MULTAGGR )
220  {
221  eventtype = SCIP_EVENTTYPE_DISABLED;
222  if( !SCIPisInfinity(scip, -consdata->lhs) )
223  eventtype |= SCIP_EVENTTYPE_UBTIGHTENED;
224  if( !SCIPisInfinity(scip, consdata->rhs) )
225  eventtype |= SCIP_EVENTTYPE_LBTIGHTENED;
226 
227  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->x, eventtype, eventhdlr, (SCIP_EVENTDATA*)&consdata->isxpropagated, &consdata->xeventfilterpos) );
228 
229  consdata->isxpropagated = FALSE;
230  }
231  else
232  consdata->isxpropagated = TRUE;
233 
234  /* if x is multiaggregated, then bound changes on z could not be propagated, so we do not need to catch them */
235  if( SCIPvarGetStatus(consdata->x) != SCIP_VARSTATUS_MULTAGGR )
236  {
237  eventtype = SCIP_EVENTTYPE_DISABLED;
238  if( consdata->zcoef > 0.0 )
239  {
240  if( !SCIPisInfinity(scip, -consdata->lhs) )
241  eventtype |= SCIP_EVENTTYPE_UBTIGHTENED;
242  if( !SCIPisInfinity(scip, consdata->rhs) )
243  eventtype |= SCIP_EVENTTYPE_LBTIGHTENED;
244  }
245  else
246  {
247  if( !SCIPisInfinity(scip, -consdata->lhs) )
248  eventtype |= SCIP_EVENTTYPE_LBTIGHTENED;
249  if( !SCIPisInfinity(scip, consdata->rhs) )
250  eventtype |= SCIP_EVENTTYPE_UBTIGHTENED;
251  }
252 
253  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->z, eventtype, eventhdlr, (SCIP_EVENTDATA*)&consdata->iszpropagated, &consdata->zeventfilterpos) );
254  consdata->iszpropagated = FALSE;
255  }
256  else
257  consdata->iszpropagated = TRUE;
258 
259  return SCIP_OKAY;
260 }
261 
262 /** drop variable bound tightening events */
263 static
265  SCIP* scip, /**< SCIP data structure */
266  SCIP_EVENTHDLR* eventhdlr, /**< event handler for variables */
267  SCIP_CONS* cons /**< constraint for which to drop bound change events */
268  )
269 {
270  SCIP_CONSDATA* consdata;
271  SCIP_EVENTTYPE eventtype;
272 
273  assert(scip != NULL);
274  assert(cons != NULL);
275  assert(eventhdlr != NULL);
276 
277  consdata = SCIPconsGetData(cons);
278  assert(consdata != NULL);
279 
280  if( SCIPvarGetStatus(consdata->z) != SCIP_VARSTATUS_MULTAGGR )
281  {
282  eventtype = SCIP_EVENTTYPE_DISABLED;
283  if( !SCIPisInfinity(scip, -consdata->lhs) )
284  eventtype |= SCIP_EVENTTYPE_UBTIGHTENED;
285  if( !SCIPisInfinity(scip, consdata->rhs) )
286  eventtype |= SCIP_EVENTTYPE_LBTIGHTENED;
287 
288  SCIP_CALL( SCIPdropVarEvent(scip, consdata->x, eventtype, eventhdlr, (SCIP_EVENTDATA*)&consdata->isxpropagated, consdata->xeventfilterpos) );
289  consdata->xeventfilterpos = -1;
290  }
291 
292  if( SCIPvarGetStatus(consdata->x) != SCIP_VARSTATUS_MULTAGGR )
293  {
294  eventtype = SCIP_EVENTTYPE_DISABLED;
295  if( consdata->zcoef > 0.0 )
296  {
297  if( !SCIPisInfinity(scip, -consdata->lhs) )
298  eventtype |= SCIP_EVENTTYPE_UBTIGHTENED;
299  if( !SCIPisInfinity(scip, consdata->rhs) )
300  eventtype |= SCIP_EVENTTYPE_LBTIGHTENED;
301  }
302  else
303  {
304  if( !SCIPisInfinity(scip, -consdata->lhs) )
305  eventtype |= SCIP_EVENTTYPE_LBTIGHTENED;
306  if( !SCIPisInfinity(scip, consdata->rhs) )
307  eventtype |= SCIP_EVENTTYPE_UBTIGHTENED;
308  }
309 
310  SCIP_CALL( SCIPdropVarEvent(scip, consdata->z, eventtype, eventhdlr, (SCIP_EVENTDATA*)&consdata->iszpropagated, consdata->zeventfilterpos) );
311  consdata->zeventfilterpos = -1;
312  }
313 
314  assert(consdata->xeventfilterpos == -1);
315  assert(consdata->zeventfilterpos == -1);
316 
317  return SCIP_OKAY;
318 }
319 
320 /** get key of hash element */
321 static
322 SCIP_DECL_HASHGETKEY(presolveFindDuplicatesGetKey)
323 {
324  return elem;
325 } /*lint !e715*/
326 
327 /** checks if two constraints have the same x variable, the same exponent, and either the same offset or the same linear variable and are both equality constraint */
328 static
329 SCIP_DECL_HASHKEYEQ(presolveFindDuplicatesKeyEQ)
330 {
331  SCIP_CONSDATA* consdata1;
332  SCIP_CONSDATA* consdata2;
333 
334  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
335  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
336  assert(consdata1 != NULL);
337  assert(consdata2 != NULL);
338 
339  if( consdata1->x != consdata2->x )
340  return FALSE;
341 
342  if( consdata1->exponent != consdata2->exponent ) /*lint !e777*/
343  return FALSE;
344 
345  if( consdata1->xoffset != consdata2->xoffset && consdata1->z != consdata2->z ) /*lint !e777*/
346  return FALSE;
347 
348  return TRUE;
349 } /*lint !e715*/
350 
351 /** get value of hash element when comparing on x */
352 static
353 SCIP_DECL_HASHKEYVAL(presolveFindDuplicatesKeyVal)
354 {
355  SCIP_CONSDATA* consdata;
356 
357  consdata = SCIPconsGetData((SCIP_CONS*)key);
358  assert(consdata != NULL);
359 
360  return ((unsigned int)(size_t)consdata->x << 16) + (unsigned int)(consdata->exponent*0x80);
361 } /*lint !e715*/
362 
363 /** checks if two constraints have the same z variable and the same exponent */
364 static
365 SCIP_DECL_HASHKEYEQ(presolveFindDuplicatesKeyEQ2)
366 {
367  SCIP_CONSDATA* consdata1;
368  SCIP_CONSDATA* consdata2;
369 
370  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
371  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
372  assert(consdata1 != NULL);
373  assert(consdata2 != NULL);
374 
375  if( consdata1->z != consdata2->z )
376  return FALSE;
377 
378  if( consdata1->exponent != consdata2->exponent ) /*lint !e777*/
379  return FALSE;
380 
381  return TRUE;
382 } /*lint !e715*/
383 
384 /** get value of hash element when comparing on z */
385 static
386 SCIP_DECL_HASHKEYVAL(presolveFindDuplicatesKeyVal2)
387 {
388  SCIP_CONSDATA* consdata;
389 
390  consdata = SCIPconsGetData((SCIP_CONS*)key);
391  assert(consdata != NULL);
392 
393  return ((unsigned int)(size_t)consdata->z << 16) + (unsigned int)(consdata->exponent*0x80);
394 } /*lint !e715*/
395 
396 /** upgrades a signpower constraint to a linear constraint if a second signpower constraint with same nonlinear term is available */
397 static
399  SCIP* scip, /**< SCIP data structure */
400  SCIP_CONS* cons1, /**< constraint to upgrade to a linear constraint */
401  SCIP_CONS* cons2, /**< constraint which defines a relation for x|x|^{n-1} */
402  SCIP_Bool* infeas, /**< buffer where to indicate if infeasibility has been detected */
403  int* nupgdconss, /**< buffer where to add number of upgraded conss */
404  int* ndelconss, /**< buffer where to add number of deleted conss */
405  int* naggrvars /**< buffer where to add number of aggregated variables */
406  )
407 {
408  SCIP_CONSDATA* consdata1;
409  SCIP_CONSDATA* consdata2;
410  SCIP_CONS* lincons;
411  SCIP_Real lhs;
412  SCIP_Real rhs;
413  SCIP_VAR* vars[2];
414  SCIP_Real coefs[2];
415 
416  assert(scip != NULL);
417  assert(cons1 != NULL);
418  assert(cons2 != NULL);
419  assert(infeas != NULL);
420  assert(nupgdconss != NULL);
421  assert(ndelconss != NULL);
422  assert(naggrvars != NULL);
423 
424  consdata1 = SCIPconsGetData(cons1);
425  consdata2 = SCIPconsGetData(cons2);
426  assert(consdata1 != NULL);
427  assert(consdata2 != NULL);
428 
429  assert(SCIPisEQ(scip, consdata2->lhs, consdata2->rhs));
430  assert(!SCIPisInfinity(scip, consdata2->lhs));
431  assert(consdata1->x == consdata2->x);
432  assert(consdata1->exponent == consdata2->exponent); /*lint !e777*/
433  assert(consdata1->xoffset == consdata2->xoffset); /*lint !e777*/
434 
435  lhs = consdata1->lhs;
436  if( !SCIPisInfinity(scip, -lhs) )
437  lhs -= consdata2->lhs;
438  rhs = consdata1->rhs;
439  if( !SCIPisInfinity(scip, rhs) )
440  rhs -= consdata2->lhs;
441 
442  vars[0] = consdata1->z;
443  vars[1] = consdata2->z;
444 
445  coefs[0] = consdata1->zcoef;
446  coefs[1] = -consdata2->zcoef;
447 
448  if( SCIPisEQ(scip, lhs, rhs) )
449  {
450  SCIP_Bool redundant;
451  SCIP_Bool aggregated;
452 
453  /* try aggregation */
454  SCIP_CALL( SCIPaggregateVars(scip, consdata1->z, consdata2->z, consdata1->zcoef, -consdata2->zcoef, rhs, infeas, &redundant, &aggregated) );
455 
456  /* if infeasibility has been detected, stop here */
457  if( *infeas )
458  return SCIP_OKAY;
459 
460  if( redundant )
461  {
462  /* if redundant is TRUE, then either the aggregation has been done, or it was redundant */
463  if( aggregated )
464  ++*naggrvars;
465 
466  ++*ndelconss;
467 
468  SCIP_CALL( SCIPdelCons(scip, cons1) );
469  return SCIP_OKAY;
470  }
471  }
472 
473  /* if aggregation did not succeed, then either because some variable is multi-aggregated or due to numerics or because lhs != rhs
474  * we then add a linear constraint instead
475  */
476  vars[0] = consdata1->z;
477  vars[1] = consdata2->z;
478  coefs[0] = consdata1->zcoef;
479  coefs[1] = -consdata2->zcoef;
480 
481  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons1), 2, vars, coefs, lhs, rhs,
485  SCIPconsIsStickingAtNode(cons1)) );
486  SCIP_CALL( SCIPaddCons(scip, lincons) );
487  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
488 
489  SCIP_CALL( SCIPdelCons(scip, cons1) );
490  ++*nupgdconss;
491 
492  return SCIP_OKAY;
493 }
494 
495 /** solves a system of two absolute power equations
496  * Given: (x+xoffset1)|x+xoffset1|^{exponent-1} + zcoef1 * z == rhs1
497  * and (x+xoffset2)|x+xoffset2|^{exponent-1} + zcoef2 * z == rhs2
498  * with xoffset1 != xoffset2 and zcoef1 * rhs2 == zcoef2 * rhs1 and exponent == 2,
499  * finds values for x and z that satisfy these equations, or reports infeasibility if no solution exists.
500  *
501  * Multiplying the second equation by -zcoef1/zcoef2 and adding it to the first one gives
502  * (x+xoffset1)|x+xoffset1| - zcoef1/zcoef2 (x+offset2)|x+offset2| == 0
503  *
504  * If zcoef1 == zcoef2, then there exists, due to monotonicity of x|x|, no x such that
505  * (x+xoffset1)|x+xoffset1| == (x+xoffset2)|x+xoffset2|.
506  *
507  * In general, for zcoef1 / zcoef2 > 0.0, we get
508  * x = (xoffset2 - xoffset1) / (sqrt(zcoef2 / zcoef1) - 1.0) - xoffset1,
509  * and for zcoef1 / zcoef2 < 0.0, we get
510  * x = (xoffset2 - xoffset1) / (-sqrt(-zcoef2 / zcoef1) - 1.0) - xoffset1.
511  *
512  * This then yields z = (rhs1 - (x+xoffset1)|x+xoffset1|) / zcoef1.
513  */
514 static
516  SCIP* scip, /**< SCIP data structure */
517  SCIP_Bool* infeas, /**< buffer to indicate if the system of equations has no solution */
518  SCIP_Real* xval, /**< buffer to store value of x in the solution, if any */
519  SCIP_Real* zval, /**< buffer to store value of z in the solution, if any */
520  SCIP_Real exponent, /**< exponent in absolute power equations */
521  SCIP_Real xoffset1, /**< offset for x in first absolute power equation */
522  SCIP_Real zcoef1, /**< coefficient of z in first absolute power equation */
523  SCIP_Real rhs1, /**< right-hand-side in first absolute power equation */
524  SCIP_Real xoffset2, /**< offset for x in second absolute power equation */
525  SCIP_Real zcoef2, /**< coefficient of z in second absolute power equation */
526  SCIP_Real rhs2 /**< right-hand-side in second absolute power equation */
527  )
528 {
529  assert(scip != NULL);
530  assert(infeas != NULL);
531  assert(xval != NULL);
532  assert(zval != NULL);
533  assert(exponent == 2.0);
534  assert(!SCIPisEQ(scip, xoffset1, xoffset2));
535  assert(SCIPisEQ(scip, zcoef1 * rhs2, zcoef2 * rhs1));
536  assert(zcoef1 != 0.0);
537  assert(zcoef2 != 0.0);
538 
539  if( xoffset2 < xoffset1 )
540  {
541  presolveFindDuplicatesSolveEquations(scip, infeas, xval, zval, exponent, xoffset2, zcoef2, rhs2, xoffset1, zcoef1, rhs1);
542  return;
543  }
544 
545  if( SCIPisEQ(scip, zcoef1, zcoef2) )
546  {
547  *infeas = TRUE;
548  return;
549  }
550 
551  *infeas = FALSE;
552 
553  if( SCIPisEQ(scip, zcoef1, -zcoef2) )
554  {
555  *xval = - (xoffset1 + xoffset2) / 2.0;
556  }
557  else if( zcoef2 * zcoef1 > 0.0 )
558  {
559  *xval = (xoffset2 - xoffset1) / (sqrt(zcoef2 / zcoef1) - 1.0) - xoffset1;
560  }
561  else
562  {
563  assert(zcoef2 * zcoef1 < 0.0);
564  *xval = (xoffset2 - xoffset1) / (-sqrt(-zcoef2 / zcoef1) - 1.0) - xoffset1;
565  }
566 
567  *zval = rhs1 - (*xval + xoffset1) * REALABS(*xval + xoffset1);
568  *zval /= zcoef1;
569 
570  assert(SCIPisFeasEQ(scip, (*xval + xoffset1) * REALABS(*xval + xoffset1) + zcoef1 * *zval, rhs1));
571  assert(SCIPisFeasEQ(scip, (*xval + xoffset2) * REALABS(*xval + xoffset2) + zcoef2 * *zval, rhs2));
572 }
573 
574 /** finds and removes duplicates in a set of absolute power constraints */
575 static
577  SCIP* scip, /**< SCIP data structure */
578  SCIP_CONSHDLR* conshdlr, /**< constraint handler for absolute power constraints */
579  SCIP_CONS** conss, /**< constraints */
580  int nconss, /**< number of constraints */
581  int* nupgdconss, /**< pointer where to add number of upgraded constraints */
582  int* ndelconss, /**< pointer where to add number of deleted constraints */
583  int* naddconss, /**< pointer where to add number of added constraints */
584  int* nfixedvars, /**< pointer where to add number of fixed variables */
585  int* naggrvars, /**< pointer where to add number of aggregated variables */
586  SCIP_Bool* success, /**< pointer to store whether a duplicate was found (and removed) */
587  SCIP_Bool* infeas /**< pointer to store whether infeasibility was detected */
588  )
589 {
590  SCIP_HASHTABLE* hashtable;
591  SCIP_HASHTABLELIST* hashtablelist;
592  SCIP_CONSHDLRDATA* conshdlrdata;
593  int c;
594 
595  assert(scip != NULL);
596  assert(conshdlr != NULL);
597  assert(conss != NULL || nconss == 0);
598  assert(nupgdconss != NULL);
599  assert(ndelconss != NULL);
600  assert(naddconss != NULL);
601  assert(nfixedvars != NULL);
602  assert(naggrvars != NULL);
603  assert(success != NULL);
604  assert(infeas != NULL);
605 
606  *success = FALSE;
607  *infeas = FALSE;
608 
609  if( nconss <= 1 )
610  return SCIP_OKAY;
611 
612  conshdlrdata = SCIPconshdlrGetData(conshdlr);
613  assert(conshdlrdata != NULL);
614 
615  /* check all constraints in the given set for duplicates, dominance, or possible simplifications w.r.t. the x variable */
616 
618  presolveFindDuplicatesGetKey, presolveFindDuplicatesKeyEQ, presolveFindDuplicatesKeyVal, (void*)scip) );
619 
620  for( c = 0; c < nconss && !*infeas; ++c )
621  {
622  SCIP_CONS* cons0;
623  SCIP_CONS* cons1;
624 
625  cons0 = conss[c]; /*lint !e613*/
626 
627  assert(!SCIPconsIsModifiable(cons0)); /* absolute power constraints aren't modifiable */
628  assert(!SCIPconsIsLocal(cons0)); /* shouldn't have local constraints in presolve */
629  assert(SCIPconsIsActive(cons0)); /* shouldn't get inactive constraints here */
630 
631  hashtablelist = NULL;
632 
633  do
634  {
635  SCIP_CONSDATA* consdata0;
636  SCIP_CONSDATA* consdata1;
637 
638  /* get constraint from current hash table with same x variable as cons0 and same exponent */
639  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieveNext(hashtable, &hashtablelist, (void*)cons0));
640  if( cons1 == NULL )
641  {
642  /* processed all constraints like cons0 from hash table, so insert cons0 and go to conss[c+1] */
643  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
644  break;
645  }
646 
647  assert(cons0 != cons1);
648 
649  consdata0 = SCIPconsGetData(cons0);
650  consdata1 = SCIPconsGetData(cons1);
651  assert(consdata0 != NULL);
652  assert(consdata1 != NULL);
653 
654  SCIPdebugPrintCons(scip, cons0, NULL);
655  SCIPdebugPrintCons(scip, cons1, NULL);
656 
657  assert(consdata0->x == consdata1->x);
658  assert(consdata0->exponent == consdata1->exponent); /*lint !e777*/
659 
660  if( SCIPisEQ(scip, consdata0->xoffset, consdata1->xoffset) )
661  {
662  /* we have two constraints with the same (x+offset)|x+offset|^n term */
663 
664  /* if both constraints have the same functions; strengthen sides of cons1 and throw cons0 away */
665  if( consdata0->z == consdata1->z && SCIPisEQ(scip, consdata0->zcoef, consdata1->zcoef) )
666  {
667  /* check if side strenghtening would result in inconsistency */
668  if( SCIPisGT(scip, consdata0->lhs, consdata1->rhs) || SCIPisGT(scip, consdata1->lhs, consdata0->rhs) )
669  {
670  SCIPdebugMessage("<%s> and <%s> are contradictory; declare infeasibility\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
671  *infeas = TRUE;
672  break;
673  }
674 
675  SCIPdebugMessage("<%s> and <%s> are equivalent; dropping the first\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
676 
677  /* if a side of cons1 gets finite via merging with cons0, then this changes locks and events */
678  if( (SCIPisInfinity(scip, -consdata1->lhs) && !SCIPisInfinity(scip, -consdata0->lhs)) ||
679  ( SCIPisInfinity(scip, consdata1->rhs) && !SCIPisInfinity(scip, consdata0->rhs)) )
680  {
681  SCIP_CALL( dropVarEvents(scip, conshdlrdata->eventhdlr, cons1) );
682  SCIP_CALL( SCIPunlockVarCons(scip, consdata1->x, cons1, !SCIPisInfinity(scip, -consdata1->lhs), !SCIPisInfinity(scip, consdata1->rhs)) );
683  if( consdata1->zcoef > 0.0 )
684  SCIP_CALL( SCIPunlockVarCons(scip, consdata1->z, cons1, !SCIPisInfinity(scip, -consdata1->lhs), !SCIPisInfinity(scip, consdata1->rhs)) );
685  else
686  SCIP_CALL( SCIPunlockVarCons(scip, consdata1->z, cons1, !SCIPisInfinity(scip, consdata1->rhs), !SCIPisInfinity(scip, -consdata1->lhs)) );
687 
688  consdata1->lhs = MAX(consdata0->lhs, consdata1->lhs);
689  consdata1->rhs = MIN(consdata0->rhs, consdata1->rhs);
690 
691  SCIP_CALL( catchVarEvents(scip, conshdlrdata->eventhdlr, cons1) );
692  SCIP_CALL( SCIPlockVarCons(scip, consdata1->x, cons1, !SCIPisInfinity(scip, -consdata1->lhs), !SCIPisInfinity(scip, consdata1->rhs)) );
693  if( consdata1->zcoef > 0.0 )
694  SCIP_CALL( SCIPlockVarCons(scip, consdata1->z, cons1, !SCIPisInfinity(scip, -consdata1->lhs), !SCIPisInfinity(scip, consdata1->rhs)) );
695  else
696  SCIP_CALL( SCIPlockVarCons(scip, consdata1->z, cons1, !SCIPisInfinity(scip, consdata1->rhs), !SCIPisInfinity(scip, -consdata1->lhs)) );
697  }
698  else
699  {
700  consdata1->lhs = MAX(consdata0->lhs, consdata1->lhs);
701  consdata1->rhs = MIN(consdata0->rhs, consdata1->rhs);
702  }
703 
704  SCIP_CALL( SCIPdelCons(scip, cons0) );
705  ++*ndelconss;
706  *success = TRUE;
707 
708  break;
709  }
710 
711  /* if cons1 defines a linear expression for sign(x+offset)|x+offset|^n, use it to replace cons0 by a linear constraint */
712  if( SCIPisEQ(scip, consdata1->lhs, consdata1->rhs) )
713  {
714  SCIPdebugMessage("substitute <%s> in <%s> to make linear constraint\n", SCIPconsGetName(cons1), SCIPconsGetName(cons0));
715  SCIP_CALL( presolveFindDuplicatesUpgradeCons(scip, cons0, cons1, infeas, nupgdconss, ndelconss, naggrvars) );
716 
717  *success = TRUE;
718  break;
719  }
720 
721  /* if cons0 defines a linear expression for sign(x+offset)|x+offset|^n, use it to replace cons1 by a linear constraint */
722  if( SCIPisEQ(scip, consdata0->lhs, consdata0->rhs) )
723  {
724  SCIPdebugMessage("substitute <%s> in <%s> to make linear constraint\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
725  SCIP_CALL( presolveFindDuplicatesUpgradeCons(scip, cons1, cons0, infeas, nupgdconss, ndelconss, naggrvars) );
726 
727  SCIP_CALL( SCIPhashtableRemove(hashtable, cons1) );
728  *success = TRUE;
729 
730  if( *infeas )
731  break;
732  }
733  else
734  {
735  /* introduce a new equality constraint for sign(x+offset)|x+offset|^n and use it to replace cons0 and cons1 */
736  /* @todo maybe we could be more clever by looking which constraint sides are finite */
737  SCIP_VAR* auxvar;
738  SCIP_CONS* auxcons;
739  char name[SCIP_MAXSTRLEN];
740  SCIP_VAR* vars[2];
741  SCIP_Real coefs[2];
742 
743  SCIPdebugMessage("introduce new auxvar for signpower(%s+%g, %g) to make <%s> and <%s> linear constraint\n", SCIPvarGetName(consdata0->x), consdata0->exponent, consdata0->xoffset, SCIPconsGetName(cons0), SCIPconsGetName(cons1));
744 
745  /* create auxiliary variable to represent sign(x+offset)|x+offset|^n */
746  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "auxvar_abspower%s_%g_%g", SCIPvarGetName(consdata0->x), consdata0->exponent, consdata0->xoffset);
747  SCIP_CALL( SCIPcreateVar(scip, &auxvar, name, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
748  TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
749  SCIP_CALL( SCIPaddVar(scip, auxvar) );
750 
751  /* create auxiliary constraint auxvar = sign(x+offset)|x+offset|^n */
752  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "auxcons_abspower%s_%g_%g", SCIPvarGetName(consdata0->x), consdata0->exponent, consdata0->xoffset);
753  SCIP_CALL( SCIPcreateConsAbspower(scip, &auxcons, name, consdata0->x, auxvar, consdata0->exponent, consdata0->xoffset, -1.0, 0.0, 0.0,
754  SCIPconsIsInitial(cons0) || SCIPconsIsInitial(cons1),
755  SCIPconsIsSeparated(cons0) || SCIPconsIsSeparated(cons1),
756  SCIPconsIsEnforced(cons0) || SCIPconsIsEnforced(cons1),
757  SCIPconsIsChecked(cons0) || SCIPconsIsChecked(cons1),
759  FALSE,
760  FALSE,
761  SCIPconsIsDynamic(cons0) || SCIPconsIsDynamic(cons1),
762  SCIPconsIsRemovable(cons0) || SCIPconsIsRemovable(cons1),
764  ) );
765  SCIP_CALL( SCIPaddCons(scip, auxcons) );
766  SCIP_CALL( SCIPreleaseCons(scip, &auxcons) );
767  ++*naddconss;
768 
769 #ifdef SCIP_DEBUG_SOLUTION
770  if( SCIPdebugIsMainscip(scip) )
771  {
772  SCIP_Real xval;
773 
774  SCIP_CALL( SCIPdebugGetSolVal(scip, consdata0->x, &xval) );
775  SCIP_CALL( SCIPdebugAddSolVal(scip, auxvar, SIGN(xval + consdata0->xoffset) * pow(REALABS(xval + consdata0->xoffset), consdata0->exponent)) );
776  }
777 #endif
778 
779  /* create linear constraint equivalent for cons0 */
780  vars[0] = auxvar;
781  vars[1] = consdata0->z;
782  coefs[0] = 1.0;
783  coefs[1] = consdata0->zcoef;
784  SCIP_CALL( SCIPcreateConsLinear(scip, &auxcons, SCIPconsGetName(cons0), 2, vars, coefs, consdata0->lhs, consdata0->rhs,
788  SCIPconsIsStickingAtNode(cons0)) );
789  SCIP_CALL( SCIPaddCons(scip, auxcons) );
790  SCIP_CALL( SCIPreleaseCons(scip, &auxcons) );
791  ++*nupgdconss;
792 
793  /* create linear constraint equivalent for cons1 */
794  vars[1] = consdata1->z;
795  coefs[1] = consdata1->zcoef;
796  SCIP_CALL( SCIPcreateConsLinear(scip, &auxcons, SCIPconsGetName(cons1), 2, vars, coefs, consdata1->lhs, consdata1->rhs,
800  SCIPconsIsStickingAtNode(cons1)) );
801  SCIP_CALL( SCIPaddCons(scip, auxcons) );
802  SCIP_CALL( SCIPreleaseCons(scip, &auxcons) );
803  ++*nupgdconss;
804 
805  SCIP_CALL( SCIPreleaseVar(scip, &auxvar) );
806 
807  SCIP_CALL( SCIPdelCons(scip, cons0) );
808  SCIP_CALL( SCIPdelCons(scip, cons1) );
809  SCIP_CALL( SCIPhashtableRemove(hashtable, cons1) );
810  *success = TRUE;
811 
812  break;
813  }
814  }
815  else if( consdata0->z == consdata1->z &&
816  consdata0->exponent == 2.0 &&
817  !SCIPisZero(scip, consdata0->zcoef) &&
818  !SCIPisZero(scip, consdata1->zcoef) &&
819  SCIPisEQ(scip, consdata0->lhs, consdata0->rhs) &&
820  SCIPisEQ(scip, consdata1->lhs, consdata1->rhs) &&
821  SCIPisEQ(scip, consdata0->lhs * consdata1->zcoef, consdata1->lhs * consdata0->zcoef) )
822  {
823  /* If we have two equality constraints with the same variables and the same exponent and compatible constants,
824  * then this system of equations should have either no or a single solution.
825  * Thus, we can report cutoff or fix the variables to this solution, and forget about the constraints.
826  * @todo think about inequalities, differing exponents, and exponents != 2
827  */
828 
829  SCIP_Real xval;
830  SCIP_Real zval;
831 
832  assert(consdata0->x == consdata1->x);
833  assert(consdata0->exponent == consdata1->exponent); /*lint !e777*/
834  assert(!SCIPisEQ(scip, consdata0->xoffset, consdata1->xoffset));
835 
836  presolveFindDuplicatesSolveEquations(scip, infeas, &xval, &zval,
837  consdata0->exponent,
838  consdata0->xoffset, consdata0->zcoef, consdata0->lhs,
839  consdata1->xoffset, consdata1->zcoef, consdata1->lhs);
840 
841  if( *infeas )
842  {
843  SCIPdebugMessage("infeasibility detected while solving the equations, no solution exists\n");
844  SCIPdebugPrintCons(scip, cons0, NULL);
845  SCIPdebugPrintCons(scip, cons1, NULL);
846  break;
847  }
848 
849  SCIPdebugMessage("fixing variables <%s>[%g, %g] to %g and <%s>[%g, %g] to %g due to equations\n",
850  SCIPvarGetName(consdata0->x), SCIPvarGetLbLocal(consdata0->x), SCIPvarGetUbLocal(consdata0->x), xval,
851  SCIPvarGetName(consdata0->z), SCIPvarGetLbLocal(consdata0->z), SCIPvarGetUbLocal(consdata0->z), zval);
852  SCIPdebugPrintCons(scip, cons0, NULL);
853  SCIPdebugPrintCons(scip, cons1, NULL);
854 
856  {
857  SCIP_Bool fixed;
858 
859  SCIP_CALL( SCIPfixVar(scip, consdata0->x, xval, infeas, &fixed) );
860  ++*ndelconss;
861 
862  if( fixed )
863  ++*nfixedvars;
864 
865  if( *infeas )
866  {
867  SCIPdebugMessage("infeasibility detected after fixing <%s>\n", SCIPvarGetName(consdata0->x));
868  break;
869  }
870  }
871  else
872  {
873  SCIP_CONS* lincons;
874  SCIP_Real one;
875 
876  one = 1.0;
877  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons0), 1, &consdata0->x, &one, xval, xval,
879  SCIP_CALL( SCIPaddCons(scip, lincons) );
880  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
881  ++*nupgdconss;
882  }
883 
885  {
886  SCIP_Bool fixed;
887 
888  SCIP_CALL( SCIPfixVar(scip, consdata0->z, zval, infeas, &fixed) );
889  ++*ndelconss;
890 
891  if( fixed )
892  ++*nfixedvars;
893 
894  if( *infeas )
895  {
896  SCIPdebugMessage("infeasibility detected after fixing <%s>\n", SCIPvarGetName(consdata0->z));
897  break;
898  }
899  }
900  else
901  {
902  SCIP_CONS* lincons;
903  SCIP_Real one;
904 
905  one = 1.0;
906  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons1), 1, &consdata0->z, &one, zval, zval,
908  SCIP_CALL( SCIPaddCons(scip, lincons) );
909  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
910  ++*nupgdconss;
911  }
912 
913  SCIP_CALL( SCIPdelCons(scip, cons0) );
914  SCIP_CALL( SCIPdelCons(scip, cons1) );
915  SCIP_CALL( SCIPhashtableRemove(hashtable, cons1) );
916  *success = TRUE;
917 
918  break;
919  }
920 
921  if( hashtablelist == NULL )
922  {
923  /* processed all constraints like cons0 from hash table, but cons0 could not be removed, so insert cons0 into hashmap and go to conss[c+1] */
924  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
925  break;
926  }
927  }
928  while( TRUE ); /*lint !e506*/
929  }
930 
931  /* free hash table */
932  SCIPhashtableFree(&hashtable);
933 
934  if( *infeas )
935  return SCIP_OKAY;
936 
937 
938  /* check all constraints in the given set for duplicates, dominance, or possible simplifications w.r.t. the z variable */
939 
941  presolveFindDuplicatesGetKey, presolveFindDuplicatesKeyEQ2, presolveFindDuplicatesKeyVal2, (void*) scip) );
942 
943  for( c = 0; c < nconss && !*infeas; ++c )
944  {
945  SCIP_CONS* cons0;
946  SCIP_CONS* cons1;
947  SCIP_CONSDATA* consdata0;
948 
949  cons0 = conss[c]; /*lint !e613*/
950 
951  assert(!SCIPconsIsModifiable(cons0)); /* absolute power constraints aren't modifiable */
952  assert(!SCIPconsIsLocal(cons0)); /* shouldn't have local constraints in presolve */
953 
954  /* do not consider constraints that we have deleted in the above loop */
955  if( SCIPconsIsDeleted(cons0) )
956  continue;
957  assert(SCIPconsIsActive(cons0)); /* shouldn't get inactive constraints here */
958 
959  consdata0 = SCIPconsGetData(cons0);
960  assert(consdata0 != NULL);
961 
962  /* consider only equality constraints so far
963  * @todo do also something with inequalities
964  */
965  if( !SCIPisEQ(scip, consdata0->lhs, consdata0->rhs) )
966  continue;
967 
968  hashtablelist = NULL;
969 
970  do
971  {
972  SCIP_CONSDATA* consdata1;
973 
974  /* get constraint from current hash table with same z variable as cons0 and same exponent */
975  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieveNext(hashtable, &hashtablelist, (void*)cons0));
976  if( cons1 == NULL )
977  {
978  /* processed all constraints like cons0 from hash table, so insert cons0 and go to conss[c+1] */
979  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
980  break;
981  }
982 
983  assert(cons0 != cons1);
984  assert(!SCIPconsIsDeleted(cons1));
985 
986  consdata1 = SCIPconsGetData(cons1);
987  assert(consdata1 != NULL);
988 
989  SCIPdebugPrintCons(scip, cons0, NULL);
990  SCIPdebugPrintCons(scip, cons1, NULL);
991 
992  assert(consdata0->z == consdata1->z);
993  assert(consdata0->exponent == consdata1->exponent); /*lint !e777*/
994  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
995  assert(!SCIPisZero(scip, consdata1->zcoef));
996 
997  if( SCIPisEQ(scip, consdata0->lhs*consdata1->zcoef, consdata1->lhs*consdata0->zcoef) )
998  {
999  /* have two absolute power equations with same z and compatible constants
1000  * we can then reduce this to one absolute power and one linear equation
1001  * -> x0 + xoffset0 = signpower(zcoef0/zcoef1, 1/exponent) (x1 + xoffset1)
1002  * -> keep cons1
1003  * the latter can be realized as an aggregation (if x0 and x1 are not multiaggregated) or linear constraint
1004  */
1005  SCIP_Bool redundant;
1006  SCIP_Bool aggregated;
1007  SCIP_Real coef;
1008  SCIP_Real rhs;
1009 
1010  SCIPdebugMessage("<%s> and <%s> can be reformulated to one abspower and one aggregation\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
1011  SCIPdebugPrintCons(scip, cons0, NULL);
1012  SCIPdebugPrintCons(scip, cons1, NULL);
1013 
1014  if( consdata0->exponent == 2.0 )
1015  coef = SIGN(consdata0->zcoef / consdata1->zcoef) * sqrt(REALABS(consdata0->zcoef / consdata1->zcoef));
1016  else
1017  coef = SIGN(consdata0->zcoef / consdata1->zcoef) * pow(REALABS(consdata0->zcoef / consdata1->zcoef), 1.0/consdata0->exponent);
1018  rhs = coef * consdata1->xoffset - consdata0->xoffset;
1019 
1020  /* try aggregation */
1021  SCIP_CALL( SCIPaggregateVars(scip, consdata0->x, consdata1->x, 1.0, -coef, rhs, infeas, &redundant, &aggregated) );
1022  if( *infeas )
1023  {
1024  /* if infeasibility has been detected, stop here */
1025  break;
1026  }
1027  else if( redundant )
1028  {
1029  /* if redundant is TRUE, then either the aggregation has been done, or it was redundant */
1030  if( aggregated )
1031  ++*naggrvars;
1032 
1033  ++*ndelconss;
1034  }
1035  else
1036  {
1037  /* if aggregation did not succeed, then either because some variable is multi-aggregated or due to numerics
1038  * we then add a linear constraint instead
1039  */
1040  SCIP_CONS* auxcons;
1041  SCIP_VAR* vars[2];
1042  SCIP_Real coefs[2];
1043 
1044  vars[0] = consdata0->x;
1045  vars[1] = consdata1->x;
1046  coefs[0] = 1.0;
1047  coefs[1] = -coef;
1048 
1049  /* create linear constraint equivalent for cons0 */
1050  SCIP_CALL( SCIPcreateConsLinear(scip, &auxcons, SCIPconsGetName(cons0), 2, vars, coefs, rhs, rhs,
1054  SCIPconsIsStickingAtNode(cons0)) );
1055  SCIP_CALL( SCIPaddCons(scip, auxcons) );
1056  SCIPdebugPrintCons(scip, auxcons, NULL);
1057  SCIP_CALL( SCIPreleaseCons(scip, &auxcons) );
1058 
1059  ++*nupgdconss;
1060  }
1061  SCIP_CALL( SCIPdelCons(scip, cons0) );
1062 
1063  *success = TRUE;
1064  break;
1065  }
1066 
1067  if( hashtablelist == NULL )
1068  {
1069  /* processed all constraints like cons0 from hash table, but cons0 could not be removed, so insert cons0 into hashmap and go to conss[c+1] */
1070  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
1071  break;
1072  }
1073  }
1074  while( TRUE ); /*lint !e506*/
1075  }
1076 
1077  /* free hash table */
1078  SCIPhashtableFree(&hashtable);
1079 
1080  return SCIP_OKAY;
1081 }
1082 
1083 /** fix variables not appearing in any other constraint
1084  *
1085  * @todo generalize to inequalities
1086  * @todo generalize to support discrete variables
1087  * @todo generalize to arbitrary exponents also if z is in objective
1088  */
1089 static
1091  SCIP* scip, /**< SCIP data structure */
1092  SCIP_CONS* cons, /**< constraint */
1093  SCIP_Bool* cutoff, /**< buffer to indicate whether a cutoff was detected */
1094  int* ndelconss, /**< buffer to increase with the number of deleted constraint */
1095  int* nfixedvars /**< buffer to increase with the number of fixed variables */
1096  )
1097 {
1098  SCIP_CONSDATA* consdata;
1099  SCIP_Bool lhsexists;
1100  SCIP_Bool rhsexists;
1101 
1102  assert(scip != NULL);
1103  assert(cons != NULL);
1104  assert(cutoff != NULL);
1105  assert(nfixedvars != NULL);
1106  assert(ndelconss != NULL);
1107 
1108  /* only process checked constraints (for which the locks are increased);
1109  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
1110  * dualfix presolver
1111  */
1112  if( !SCIPconsIsChecked(cons) )
1113  return SCIP_OKAY;
1114 
1115  consdata = SCIPconsGetData(cons);
1116  assert(consdata != NULL);
1117 
1118  /* skip dual presolve if multiaggregated variables are present for now (bounds are not updated, difficult to fix) */
1119  if( SCIPvarGetStatus(consdata->x) == SCIP_VARSTATUS_MULTAGGR )
1120  return SCIP_OKAY;
1121  if( SCIPvarGetStatus(consdata->z) == SCIP_VARSTATUS_MULTAGGR )
1122  return SCIP_OKAY;
1123 
1124  /* skip dual presolve if discrete variables are present for now (more difficult to compute fixing value) */
1125  if( SCIPvarGetType(consdata->x) <= SCIP_VARTYPE_INTEGER )
1126  return SCIP_OKAY;
1127  if( SCIPvarGetType(consdata->z) <= SCIP_VARTYPE_INTEGER )
1128  return SCIP_OKAY;
1129 
1130  /* we assume that domain propagation has been run and fixed variables were removed if possible */
1131  assert(consdata->isxpropagated);
1132  assert(consdata->iszpropagated);
1133  assert(consdata->zcoef != 0.0);
1134 
1135  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
1136  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
1137 
1138  if( SCIPvarGetNLocksDown(consdata->x) == (lhsexists ? 1 : 0) &&
1139  SCIPvarGetNLocksUp(consdata->x) == (rhsexists ? 1 : 0) &&
1140  (consdata->zcoef > 0.0 ? SCIPvarGetNLocksDown(consdata->z) : SCIPvarGetNLocksUp(consdata->z)) == (lhsexists ? 1 : 0) &&
1141  (consdata->zcoef > 0.0 ? SCIPvarGetNLocksUp(consdata->z) : SCIPvarGetNLocksDown(consdata->z)) == (rhsexists ? 1 : 0) )
1142  {
1143  /* x and z are only locked by cons, so we can fix them to an optimal solution of
1144  * min xobj * x + zobj * z
1145  * s.t. lhs <= sign(x+offset)*abs(x+offset)^exponent + zcoef * z <= rhs
1146  * xlb <= x <= xub
1147  * zlb <= z <= zub
1148  */
1149  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1150  {
1151  /* much simpler case where we can substitute z:
1152  * min xobj * x + zobj/zcoef * (rhs - sign(x+offset)*abs(x+offset)^exponent)
1153  * s.t. xlb <= x <= xub
1154  *
1155  * Since domain propagation had been applied, we can assume that for any valid value for x,
1156  * also the corresponding z value is valid.
1157  */
1158  SCIP_Real xfix;
1159  SCIP_Real xlb;
1160  SCIP_Real xub;
1161  SCIP_Real zfix;
1162  SCIP_Bool fixed;
1163 
1164  xlb = SCIPvarGetLbGlobal(consdata->x);
1165  xub = SCIPvarGetUbGlobal(consdata->x);
1166 
1167  if( SCIPisZero(scip, SCIPvarGetObj(consdata->z)) )
1168  {
1169  /* even simpler case where objective is linear in x */
1170  if( SCIPisZero(scip, SCIPvarGetObj(consdata->x)) )
1171  {
1172  /* simplest case where objective is zero:
1173  * if zero is within bounds, fix to zero, otherwise
1174  * fix x to middle of bounds for numerical stability. */
1175  if(SCIPisLT(scip, xlb, 0.0) && SCIPisGT(scip, xub, 0.0))
1176  xfix = 0.0;
1177  else
1178  xfix = 0.5 * (xlb + xub);
1179  }
1180  else
1181  {
1182  /* fix x to best bound */
1183  xfix = SCIPvarGetBestBoundGlobal(consdata->x);
1184  }
1185  }
1186  else if( consdata->exponent == 2.0 )
1187  {
1188  /* consider cases x <= -offset and x >= -offset separately */
1189  SCIP_Real a;
1190  SCIP_Real b;
1191  SCIP_Real c;
1192  SCIP_Real cand;
1193  SCIP_Real xfixobjval;
1194 
1195  xfix = SCIP_INVALID;
1196  xfixobjval = SCIP_INVALID;
1197 
1198  if( SCIPisLT(scip, xlb, -consdata->xoffset) )
1199  {
1200  /* For x <= -offset, the objective is equivalent to
1201  * zobj/zcoef * x^2 + (xobj + 2 offset zobj/zcoef) * x + offset^2 * zobj/zcoef + other constant
1202  * <-> a * x^2 + b * x + c
1203  *
1204  * critical values for x are xlb, MIN(xub,-offset), and -b/(2*a)
1205  */
1206  a = SCIPvarGetObj(consdata->z) / consdata->zcoef;
1207  b = SCIPvarGetObj(consdata->x) + 2 * consdata->xoffset * SCIPvarGetObj(consdata->z) / consdata->zcoef;
1208  c = consdata->xoffset * consdata->xoffset * SCIPvarGetObj(consdata->z) / consdata->zcoef;
1209 
1210  if( a < 0.0 && SCIPisInfinity(scip, -xlb) )
1211  {
1212  /* if a < 0.0, then a*x^2 is unbounded for x -> -infinity, thus fix x to -infinity */
1213  xfix = -SCIPinfinity(scip);
1214  xfixobjval = -SCIPinfinity(scip);
1215  }
1216  else
1217  {
1218  /* initialize with value for x=xlb */
1219  xfix = xlb;
1220  xfixobjval = a * xlb * xlb + b * xlb + c;
1221 
1222  /* compare with value for x=MIN(-offset,xub) */
1223  cand = MIN(-consdata->xoffset, xub);
1224  if( xfixobjval > a * cand * cand + b * cand + c )
1225  {
1226  xfix = cand;
1227  xfixobjval = a * cand * cand + b * cand + c;
1228  }
1229 
1230  /* compare with value for x=-b/(2*a), if within bounds */
1231  cand = -b/(2.0*a);
1232  if( cand > xlb && cand < -consdata->xoffset && cand < xub && xfixobjval > -b*b/(4.0*a) + c )
1233  {
1234  xfix = cand;
1235  xfixobjval = -b*b/(4.0*a) + c;
1236  }
1237  }
1238  }
1239 
1240  if( SCIPisGT(scip, xub, -consdata->xoffset) )
1241  {
1242  /* For x >= -offset, the objective is equivalent to
1243  * -zobj/zcoef * x^2 + (xobj - 2 offset zobj/zcoef) * x - offset^2 * zobj/zcoef + constants
1244  * <-> a * x^2 + b * x + c
1245  *
1246  * critical values for x are xub, MAX(xlb,-offset), and -b/(2*a)
1247  */
1248  a = -SCIPvarGetObj(consdata->z) / consdata->zcoef;
1249  b = SCIPvarGetObj(consdata->x) - 2 * consdata->xoffset * SCIPvarGetObj(consdata->z) / consdata->zcoef;
1250  c = -consdata->xoffset * consdata->xoffset * SCIPvarGetObj(consdata->z) / consdata->zcoef;
1251 
1252  if( a < 0.0 && SCIPisInfinity(scip, xub) )
1253  {
1254  /* if a < 0.0, then a*x^2 is unbounded for x -> infinity, thus fix x to infinity */
1255  xfix = SCIPinfinity(scip);
1256  /* not needed: xfixobjval = SCIPinfinity(scip); */
1257  }
1258  else
1259  {
1260  if( xfix == SCIP_INVALID ) /*lint !e777*/
1261  {
1262  /* initialize with value for x=xub */
1263  xfix = xub;
1264  xfixobjval = a * xub * xub + b * xub + c;
1265  }
1266  else
1267  {
1268  /* compare with value for x=xub */
1269  cand = xub;
1270  if( xfixobjval > a * cand * cand + b * cand + c )
1271  {
1272  xfix = cand;
1273  xfixobjval = a * cand * cand + b * cand + c;
1274  }
1275  }
1276 
1277  /* compare with value for x=MAX(xlb,-offset) */
1278  cand = MAX(xlb, -consdata->xoffset);
1279  if( xfixobjval > a * cand * cand + b * cand + c )
1280  {
1281  xfix = cand;
1282  xfixobjval = a * cand * cand + b * cand + c;
1283  }
1284 
1285  /* compare with value for x=-b/(2*a), if within bounds */
1286  cand = -b/(2.0*a);
1287  if( cand > xlb && cand > -consdata->xoffset && cand < xub && xfixobjval > -b*b/(4.0*a) + c )
1288  {
1289  xfix = cand;
1290  /* not needed: xfixobjval = -b*b/(4.0*a) + c; */
1291  }
1292  }
1293  }
1294  assert(xfix != SCIP_INVALID); /*lint !e777*/
1295  assert(SCIPisInfinity(scip, -xlb) || SCIPisLE(scip, xlb, xfix));
1296  assert(SCIPisInfinity(scip, xub) || SCIPisGE(scip, xub, xfix));
1297  }
1298  else
1299  {
1300  /* skip dual presolve for exponents != 2 and z in objective for now */
1301  return SCIP_OKAY;
1302  }
1303 
1304  /* compute fixing value for z */
1305  if( SCIPisInfinity(scip, xfix) )
1306  {
1307  if( consdata->zcoef > 0.0 )
1308  {
1309  assert(SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->z)));
1310  zfix = -SCIPinfinity(scip);
1311  }
1312  else
1313  {
1314  assert(SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->z)));
1315  zfix = SCIPinfinity(scip);
1316  }
1317  }
1318  else if( SCIPisInfinity(scip, -xfix) )
1319  {
1320  if( consdata->zcoef > 0.0 )
1321  {
1322  assert(SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->z)));
1323  zfix = SCIPinfinity(scip);
1324  }
1325  else
1326  {
1327  assert(SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->z)));
1328  zfix = -SCIPinfinity(scip);
1329  }
1330  }
1331  else
1332  {
1333  SCIP_Real zlb;
1334  SCIP_Real zub;
1335 
1336  zlb = SCIPvarGetLbGlobal(consdata->z);
1337  zub = SCIPvarGetUbGlobal(consdata->z);
1338  zfix = consdata->rhs - SIGN(xfix + consdata->xoffset) * consdata->power(ABS(xfix + consdata->xoffset), consdata->exponent);
1339  zfix /= consdata->zcoef;
1340 
1341  /* project zfix into box, it should be at least very close */
1342  assert(SCIPisFeasLE(scip, zlb, zfix));
1343  assert(SCIPisFeasGE(scip, zub, zfix));
1344  zfix = MAX(zlb, MIN(zub, zfix));
1345  }
1346 
1347  /* fix variables according to x=xfix */
1348  SCIPdebugMessage("dual presolve fixes x=<%s>[%g,%g] to %g and z=<%s>[%g,%g] to %g in cons <%s>\n",
1349  SCIPvarGetName(consdata->x), xlb, xub, xfix,
1350  SCIPvarGetName(consdata->z), SCIPvarGetLbGlobal(consdata->z), SCIPvarGetUbGlobal(consdata->z), zfix,
1351  SCIPconsGetName(cons));
1352  SCIPdebugPrintCons(scip, cons, NULL);
1353 
1354  /* fix x */
1355  SCIP_CALL( SCIPfixVar(scip, consdata->x, xfix, cutoff, &fixed) );
1356  if( *cutoff )
1357  return SCIP_OKAY;
1358  if( fixed )
1359  ++*nfixedvars;
1360 
1361  /* fix z */
1362  SCIP_CALL( SCIPfixVar(scip, consdata->z, zfix, cutoff, &fixed) );
1363  if( *cutoff )
1364  return SCIP_OKAY;
1365  if( fixed )
1366  ++*nfixedvars;
1367 
1368  /* delete constraint */
1369  SCIP_CALL( SCIPdelCons(scip, cons) );
1370  ++*ndelconss;
1371  }
1372  }
1373 
1374  return SCIP_OKAY;
1375 }
1376 
1377 /** given a variable and an interval, tightens the local bounds of this variable to the given interval */
1378 static
1380  SCIP* scip, /**< SCIP data structure */
1381  SCIP_VAR* var, /**< variable which bounds to tighten */
1382  SCIP_INTERVAL bounds, /**< new bounds */
1383  SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */
1384  SCIP_CONS* cons, /**< constraint that is propagated */
1385  SCIP_RESULT* result, /**< pointer to store the result of the propagation call */
1386  int* nchgbds, /**< buffer where to add the number of changed bounds */
1387  int* nfixedvars, /**< buffer where to add the number of fixed variables, can be equal to nchgbds */
1388  int* naddconss /**< buffer where to add the number of added constraints, can be NULL if force is FALSE */
1389  )
1390 {
1391  SCIP_Bool infeas;
1392  SCIP_Bool tightened;
1393 
1394  assert(scip != NULL);
1395  assert(var != NULL);
1396  assert(cons != NULL);
1397  assert(result != NULL);
1398  assert(nchgbds != NULL);
1399  assert(nfixedvars != NULL);
1400 
1401  *result = SCIP_DIDNOTFIND;
1402 
1403  if( SCIPisInfinity(scip, SCIPintervalGetInf(bounds)) || SCIPisInfinity(scip, -SCIPintervalGetSup(bounds)) )
1404  {
1405  /* domain outside [-infty, +infty] -> declare as infeasible */
1406  *result = SCIP_CUTOFF;
1407  return SCIP_OKAY;
1408  }
1409 
1410  /* if variable is not multiaggregated (or aggregated to a multiaggregated), then try SCIPfixVar or SCIPtightenVarLb/Ub
1411  * otherwise, if bound tightening is forced, add a linear constraint
1412  * otherwise, forget about the bound tightening
1413  */
1415  {
1416  /* check if variable can be fixed */
1417  if( SCIPisEQ(scip, bounds.inf, bounds.sup) )
1418  {
1419  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) )
1420  {
1421  /* if variable not fixed yet, then do so now */
1422  SCIP_Real fixval;
1423 
1424  if( bounds.inf != bounds.sup ) /*lint !e777*/
1425  fixval = (bounds.inf + bounds.sup) / 2.0;
1426  else
1427  fixval = bounds.inf;
1428  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeas, &tightened) );
1429 
1430  if( infeas )
1431  {
1432  SCIPdebugMessage("found <%s> infeasible due to fixing variable <%s>\n", SCIPconsGetName(cons), SCIPvarGetName(var));
1433  *result = SCIP_CUTOFF;
1434  return SCIP_OKAY;
1435  }
1436  if( tightened )
1437  {
1438  SCIPdebugMessage("fixed variable <%s> in constraint <%s> to %g\n", SCIPvarGetName(var), SCIPconsGetName(cons), SCIPvarGetLbLocal(var));
1439  ++*nfixedvars;
1440  *result = SCIP_REDUCEDDOM;
1441  }
1442  }
1443  else
1444  {
1445  /* only check if new fixing value is consistent with variable bounds, otherwise cutoff */
1446  if( SCIPisLT(scip, bounds.sup, SCIPvarGetUbLocal(var)) || SCIPisGT(scip, bounds.inf, SCIPvarGetLbLocal(var)) )
1447  {
1448  SCIPdebugMessage("found <%s> infeasible due to fixing fixed variable <%s>[%.20g,%.20g] to [%.20g,%.20g]\n",
1449  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), bounds.inf, bounds.sup);
1450  *result = SCIP_CUTOFF;
1451  return SCIP_OKAY;
1452  }
1453  }
1454 
1455  return SCIP_OKAY;
1456  }
1457 
1458  /* check if lower bound can be tightened */
1459  if( SCIPintervalGetInf(bounds) > SCIPvarGetLbLocal(var) )
1460  {
1461  assert(!SCIPisInfinity(scip, -SCIPintervalGetInf(bounds)));
1462  SCIP_CALL( SCIPtightenVarLb(scip, var, SCIPintervalGetInf(bounds), force, &infeas, &tightened) );
1463  if( infeas )
1464  {
1465  SCIPdebugMessage("found %s infeasible due to domain propagation for variable %s in constraint %s\n", SCIPconsGetName(cons), SCIPvarGetName(var), SCIPconsGetName(cons));
1466  *result = SCIP_CUTOFF;
1467  return SCIP_OKAY;
1468  }
1469  if( tightened )
1470  {
1471  SCIPdebugMessage("tightened lower bound of variable %s in constraint %s to %g\n", SCIPvarGetName(var), SCIPconsGetName(cons), SCIPvarGetLbLocal(var));
1472  ++*nchgbds;
1473  *result = SCIP_REDUCEDDOM;
1474  }
1475  }
1476 
1477  /* check if upper bound can be tightened */
1478  if( SCIPintervalGetSup(bounds) < SCIPvarGetUbLocal(var) )
1479  {
1480  assert(!SCIPisInfinity(scip, SCIPintervalGetSup(bounds)));
1481  SCIP_CALL( SCIPtightenVarUb(scip, var, SCIPintervalGetSup(bounds), force, &infeas, &tightened) );
1482  if( infeas )
1483  {
1484  SCIPdebugMessage("found %s infeasible due to domain propagation for linear variable %s in constraint %s\n", SCIPconsGetName(cons), SCIPvarGetName(var), SCIPconsGetName(cons));
1485  *result = SCIP_CUTOFF;
1486  return SCIP_OKAY;
1487  }
1488  if( tightened )
1489  {
1490  SCIPdebugMessage("tightened upper bound of variable %s in constraint %s to %g\n", SCIPvarGetName(var), SCIPconsGetName(cons), SCIPvarGetUbLocal(var));
1491  ++*nchgbds;
1492  *result = SCIP_REDUCEDDOM;
1493  }
1494  }
1495  }
1496  else if( force && (SCIPisLT(scip, SCIPvarGetLbLocal(var), bounds.inf) || SCIPisGT(scip, SCIPvarGetUbLocal(var), bounds.sup)) )
1497  {
1498  /* add a linear constraint bounds.inf <= x <= bounds.sup */
1499  SCIP_CONS* auxcons;
1500  SCIP_Bool local;
1501  SCIP_Real one;
1502 
1503  assert(naddconss != NULL);
1504 
1505  /* we add constraint as local constraint if we are during probing or if we are during solve and not at the root node */
1506  local = SCIPinProbing(scip) || (SCIPgetStage(scip) == SCIP_STAGE_SOLVING && (SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) > 0));
1507 
1508  one = 1.0;
1509  SCIP_CALL( SCIPcreateConsLinear(scip, &auxcons, SCIPconsGetName(cons), 1, &var, &one, bounds.inf, bounds.sup,
1511  SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), local,
1512  FALSE, FALSE, TRUE, FALSE) );
1513 
1514  if( local )
1515  {
1516  SCIP_CALL( SCIPaddConsLocal(scip, auxcons, NULL) );
1517  }
1518  else
1519  {
1520  SCIP_CALL( SCIPaddCons(scip, auxcons) );
1521  }
1522  SCIP_CALL( SCIPreleaseCons(scip, &auxcons) );
1523 
1524  ++*naddconss;
1525  *result = SCIP_CONSADDED;
1526  }
1527 
1528  return SCIP_OKAY;
1529 }
1530 
1531 /** computes bounds on z in a absolute power constraints for given bounds on x */
1532 static
1533 void computeBoundsZ(
1534  SCIP* scip, /**< SCIP data structure */
1535  SCIP_CONS* cons, /**< constraint */
1536  SCIP_INTERVAL xbnds, /**< bounds on x that are to be propagated */
1537  SCIP_INTERVAL* zbnds /**< buffer to store corresponding bounds on z */
1538  )
1539 {
1540  SCIP_CONSDATA* consdata;
1541  SCIP_Real bnd;
1542  SCIP_Real x;
1543 
1544  assert(scip != NULL);
1545  assert(cons != NULL);
1546  assert(zbnds != NULL);
1547  assert(!SCIPintervalIsEmpty(xbnds));
1548 
1549  consdata = SCIPconsGetData(cons);
1550  assert(consdata != NULL);
1551 
1552  SCIPintervalSetEntire(SCIPinfinity(scip), zbnds);
1553 
1554  /* apply zcoef*z <= rhs - signedpow(xbnds.inf + offset, n) */
1555  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -xbnds.inf) )
1556  {
1557  x = xbnds.inf - PROPVARTOL + consdata->xoffset;
1558  bnd = consdata->rhs + PROPSIDETOL - SIGN(x) * consdata->power(REALABS(x), consdata->exponent);
1559 
1560  if( consdata->zcoef > 0.0 )
1561  zbnds->sup = bnd / consdata->zcoef;
1562  else
1563  zbnds->inf = bnd / consdata->zcoef;
1564  }
1565 
1566  /* apply zcoef*z >= lhs - signedpow(xbnds.sup + offset, n) */
1567  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, xbnds.sup) )
1568  {
1569  x = xbnds.sup + PROPVARTOL + consdata->xoffset;
1570  bnd = consdata->lhs - PROPSIDETOL - SIGN(x) * consdata->power(REALABS(x), consdata->exponent);
1571 
1572  if( consdata->zcoef > 0.0 )
1573  zbnds->inf = bnd / consdata->zcoef;
1574  else
1575  zbnds->sup = bnd / consdata->zcoef;
1576  }
1577 
1578  SCIPdebugMessage("given x = [%.20g, %.20g], computed z = [%.20g, %.20g] via", xbnds.inf, xbnds.sup, zbnds->inf, zbnds->sup);
1579  SCIPdebugPrintCons(scip, cons, NULL);
1580 
1581  assert(!SCIPintervalIsEmpty(*zbnds));
1582 }
1583 
1584 /** computes bounds on x in a absolute power constraints for given bounds on z */
1585 static
1586 void computeBoundsX(
1587  SCIP* scip, /**< SCIP data structure */
1588  SCIP_CONS* cons, /**< constraint */
1589  SCIP_INTERVAL zbnds, /**< bounds on x that are to be propagated */
1590  SCIP_INTERVAL* xbnds /**< buffer to store corresponding bounds on z */
1591  )
1592 {
1593  SCIP_CONSDATA* consdata;
1594  SCIP_Real bnd;
1595  SCIP_Real z;
1596 
1597  assert(scip != NULL);
1598  assert(cons != NULL);
1599  assert(xbnds != NULL);
1600  assert(!SCIPintervalIsEmpty(zbnds));
1601 
1602  consdata = SCIPconsGetData(cons);
1603  assert(consdata != NULL);
1604 
1605  SCIPintervalSetEntire(SCIPinfinity(scip), xbnds);
1606 
1607  /* apply signedpow(x+offset, n) <= rhs - (zcoef * zbnds).inf */
1608  z = (consdata->zcoef > 0.0 ? zbnds.inf : zbnds.sup);
1609  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, REALABS(z)) )
1610  {
1611  bnd = consdata->rhs + PROPSIDETOL - consdata->zcoef * z + REALABS(consdata->zcoef) * PROPVARTOL;
1612  if( consdata->exponent == 2.0 )
1613  bnd = SIGN(bnd) * sqrt(REALABS(bnd));
1614  else
1615  bnd = SIGN(bnd) * pow(REALABS(bnd), 1.0/consdata->exponent);
1616  xbnds->sup = bnd - consdata->xoffset;
1617  }
1618 
1619  /* apply signedpow(x+offset, n) >= lhs - (zcoef * zbnds).sup */
1620  z = (consdata->zcoef > 0.0 ? zbnds.sup : zbnds.inf);
1621  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, REALABS(z)) )
1622  {
1623  bnd = consdata->lhs - PROPSIDETOL - consdata->zcoef * z - REALABS(consdata->zcoef) * PROPVARTOL;
1624  if( consdata->exponent == 2.0 )
1625  bnd = SIGN(bnd) * sqrt(REALABS(bnd));
1626  else
1627  bnd = SIGN(bnd) * pow(REALABS(bnd), 1.0/consdata->exponent);
1628  xbnds->inf = bnd - consdata->xoffset;
1629  }
1630 
1631  SCIPdebugMessage("given z = [%.20g, %.20g], computed x = [%.20g, %.20g] via", zbnds.inf, zbnds.sup, xbnds->inf, xbnds->sup);
1632  SCIPdebugPrintCons(scip, cons, NULL);
1633 
1634  assert(!SCIPintervalIsEmpty(*xbnds));
1635 }
1636 
1637 /** checks if x or z is fixed and replaces them or deletes constraint */
1638 static
1640  SCIP* scip, /**< SCIP data structure */
1641  SCIP_CONSHDLR* conshdlr, /**< constraint handler for absolute power constraints */
1642  SCIP_CONS* cons, /**< constraint */
1643  int* ndelconss, /**< counter for number of deleted constraints */
1644  int* nupgdconss, /**< counter for number of upgraded constraints */
1645  int* nchgbds, /**< counter for number of variable bound changes */
1646  int* nfixedvars, /**< counter for number of variable fixations */
1647  SCIP_RESULT* result /**< to store result if we detect infeasibility or remove constraint */
1648  )
1649 {
1650  SCIP_CONSHDLRDATA* conshdlrdata;
1651  SCIP_CONSDATA* consdata;
1652  SCIP_Real scalar;
1653  SCIP_Real constant;
1654  SCIP_Real factor;
1655  SCIP_VAR* var;
1656 
1657  assert(scip != NULL);
1658  assert(cons != NULL);
1659  assert(ndelconss != NULL);
1660  assert(nupgdconss != NULL);
1661  assert(nchgbds != NULL);
1662  assert(nfixedvars != NULL);
1663 
1664  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1665  assert(conshdlrdata != NULL);
1666 
1667  consdata = SCIPconsGetData(cons);
1668  assert(consdata != NULL);
1669 
1670  *result = SCIP_DIDNOTFIND;
1671 
1672  if( !SCIPvarIsActive(consdata->x) && SCIPvarGetStatus(consdata->x) != SCIP_VARSTATUS_MULTAGGR )
1673  {
1674  /* replace x variable */
1675 
1676  /* get relation x = scalar * var + constant */
1677  var = consdata->x;
1678  scalar = 1.0;
1679  constant = 0.0;
1680  SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
1681 
1682  if( scalar == 0.0 )
1683  {
1684  SCIP_INTERVAL xbnds;
1685  SCIP_INTERVAL zbnds;
1686  int naddconss;
1687 
1688  naddconss = 0;
1689 
1690  /* x has been fixed to constant */
1691  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->x), constant));
1692  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(consdata->x), constant));
1693 
1694  /* compute corresponding bounds on z */
1695  SCIPintervalSet(&xbnds, constant);
1696  computeBoundsZ(scip, cons, xbnds, &zbnds);
1697 
1698  SCIPdebugMessage("in cons <%s>: x = <%s> fixed to %g -> tighten <%s> to [%g, %g]\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->x), constant, SCIPvarGetName(consdata->z), zbnds.inf, zbnds.sup);
1699 
1700  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1701  {
1702  /* if sides are equal, then we should either fix z, or declare infeasibility */
1703  if( SCIPisFeasLT(scip, SCIPvarGetUbGlobal(consdata->z), zbnds.inf) || SCIPisFeasGT(scip, SCIPvarGetLbGlobal(consdata->z), zbnds.sup) )
1704  {
1705  SCIPdebugMessage("bounds inconsistent -> cutoff\n");
1706  *result = SCIP_CUTOFF;
1707  return SCIP_OKAY;
1708  }
1709  else
1710  {
1711  /* compute fixing value for z as value corresponding to fixing of x, projected onto bounds of z */
1712  SCIP_Real zfix;
1713 
1714  zfix = consdata->rhs - SIGN(constant + consdata->xoffset) * consdata->power(REALABS(constant + consdata->xoffset), consdata->exponent);
1715  zfix /= consdata->zcoef;
1716  assert(SCIPisLE(scip, zbnds.inf, zfix));
1717  assert(SCIPisGE(scip, zbnds.sup, zfix));
1718  zfix = MIN(SCIPvarGetUbGlobal(consdata->z), MAX(SCIPvarGetLbGlobal(consdata->z), zfix)); /*lint !e666*/
1719 
1720  zbnds.inf = zfix;
1721  zbnds.sup = zfix;
1722  SCIP_CALL( tightenBounds(scip, consdata->z, zbnds, TRUE, cons, result, nchgbds, nfixedvars, &naddconss) );
1723  }
1724  }
1725  else
1726  {
1727  /* tighten bounds on z accordingly */
1728  SCIP_CALL( tightenBounds(scip, consdata->z, zbnds, TRUE, cons, result, nchgbds, nfixedvars, &naddconss) );
1729  }
1730 
1731  /* delete constraint */
1732  SCIP_CALL( SCIPdelCons(scip, cons) );
1733 
1734  /* if tightenBounds added a constraint (because z was multiaggregated), then count this as constraint upgrade, otherwise as constraint deletion */
1735  if( naddconss > 0 )
1736  ++*nupgdconss;
1737  else
1738  ++*ndelconss;
1739 
1740  return SCIP_OKAY;
1741  }
1742 
1743  SCIPdebugMessage("in cons <%s>: x = <%s> replaced by %g*<%s> + %g\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->x), scalar, SCIPvarGetName(var), constant);
1744 
1745  /* constraint will be divided by scalar*pow(|scalar|,exponent-1), if scalar is not 1.0 */
1746  if( scalar == 1.0 )
1747  factor = 1.0;
1748  else if( scalar > 0.0 )
1749  factor = consdata->power( scalar, consdata->exponent);
1750  else
1751  factor = -consdata->power(-scalar, consdata->exponent);
1752 
1753  /* aggregate only if this would not lead to a vanishing or infinite coefficient for z */
1754  if( !SCIPisZero(scip, consdata->zcoef / factor) && !SCIPisInfinity(scip, REALABS(consdata->zcoef / factor)) )
1755  {
1756  /* we drop here the events for both variables, because if x is replaced by a multiaggregated variable here, then we do not need to catch bound tightenings on z anymore */
1757  SCIP_CALL( dropVarEvents(scip, conshdlrdata->eventhdlr, cons) );
1758  SCIP_CALL( SCIPunlockVarCons(scip, consdata->x, cons, !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
1759 
1760  consdata->x = var;
1761  if( SCIPvarIsActive(consdata->x) )
1762  {
1763  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, consdata->x) );
1764  }
1765 
1766  /* add constant to offset */
1767  consdata->xoffset += constant;
1768 
1769  /* divide constraint by factor */
1770  if( scalar == 1.0 ) ;
1771  else if( scalar > 0.0 )
1772  {
1773  if( !SCIPisInfinity(scip, -consdata->lhs) )
1774  consdata->lhs /= factor;
1775  if( !SCIPisInfinity(scip, consdata->rhs) )
1776  consdata->rhs /= factor;
1777  consdata->zcoef /= factor;
1778  consdata->xoffset /= scalar;
1779  }
1780  else
1781  {
1782  SCIP_Real oldlhs;
1783 
1784  assert(scalar < 0.0);
1785  assert(factor < 0.0);
1786 
1787  oldlhs = consdata->lhs;
1788 
1789  if( !SCIPisInfinity(scip, consdata->rhs) )
1790  consdata->lhs = consdata->rhs / factor;
1791  else
1792  consdata->lhs = -SCIPinfinity(scip);
1793  if( !SCIPisInfinity(scip, -oldlhs) )
1794  consdata->rhs = oldlhs / factor;
1795  else
1796  consdata->rhs = SCIPinfinity(scip);
1797  consdata->zcoef /= factor;
1798  consdata->xoffset /= scalar;
1799  /* since we flip both constraint sides and the sign of zcoef, the events catched for z remain the same, so update necessary there */
1800  }
1801 
1802  SCIP_CALL( SCIPlockVarCons(scip, consdata->x, cons, !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
1803  SCIP_CALL( catchVarEvents(scip, conshdlrdata->eventhdlr, cons) );
1804 
1805  SCIPdebugPrintCons(scip, cons, NULL);
1806 
1807  /* rerun constraint comparison */
1808  conshdlrdata->comparedpairwise = FALSE;
1809  }
1810  else
1811  {
1812  SCIPwarningMessage(scip, "Skip resolving aggregation of variable <%s> in abspower constraint <%s> to avoid zcoef = %g\n",
1813  SCIPvarGetName(consdata->x), SCIPconsGetName(cons), consdata->zcoef / factor);
1814  }
1815  }
1816 
1817  if( !SCIPvarIsActive(consdata->z) && SCIPvarGetStatus(consdata->z) != SCIP_VARSTATUS_MULTAGGR )
1818  {
1819  /* replace z variable */
1820 
1821  /* get relation z = scalar * var + constant */
1822  var = consdata->z;
1823  scalar = 1.0;
1824  constant = 0.0;
1825  SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
1826 
1827  if( scalar == 0.0 )
1828  {
1829  SCIP_INTERVAL xbnds;
1830  SCIP_INTERVAL zbnds;
1831  int naddconss;
1832 
1833  naddconss = 0;
1834 
1835  /* z has been fixed to constant */
1836  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->z), constant));
1837  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(consdata->z), constant));
1838 
1839  /* compute corresponding bounds on x */
1840  SCIPintervalSet(&zbnds, constant);
1841  computeBoundsX(scip, cons, zbnds, &xbnds);
1842 
1843  SCIPdebugMessage("in cons <%s>: z = <%s> fixed to %g -> tighten <%s> to [%g, %g]\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->z), constant, SCIPvarGetName(consdata->x), xbnds.inf, xbnds.sup);
1844 
1845  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1846  {
1847  /* if sides are equal, then we should either fix x, or declare infeasibility */
1848  if( SCIPisFeasLT(scip, SCIPvarGetUbGlobal(consdata->x), xbnds.inf) || SCIPisFeasGT(scip, SCIPvarGetLbGlobal(consdata->x), xbnds.sup) )
1849  {
1850  SCIPdebugMessage("bounds inconsistent -> cutoff\n");
1851  *result = SCIP_CUTOFF;
1852  return SCIP_OKAY;
1853  }
1854  else
1855  {
1856  /* compute fixing value for x as value corresponding to fixing of z, projected onto bounds of x */
1857  SCIP_Real xfix;
1858 
1859  xfix = consdata->rhs - consdata->zcoef * constant;
1860  if( consdata->exponent == 2.0 )
1861  xfix = SIGN(xfix) * sqrt(REALABS(xfix)) - consdata->xoffset;
1862  else
1863  xfix = SIGN(xfix) * pow(REALABS(xfix), 1.0/consdata->exponent) - consdata->xoffset;
1864  assert(SCIPisLE(scip, xbnds.inf, xfix));
1865  assert(SCIPisGE(scip, xbnds.sup, xfix));
1866  xfix = MIN(SCIPvarGetUbGlobal(consdata->x), MAX(SCIPvarGetLbGlobal(consdata->x), xfix)); /*lint !e666*/
1867 
1868  xbnds.inf = xfix;
1869  xbnds.sup = xfix;
1870  SCIP_CALL( tightenBounds(scip, consdata->x, xbnds, TRUE, cons, result, nchgbds, nfixedvars, &naddconss) );
1871  }
1872  }
1873  else
1874  {
1875  /* tighten bounds on x accordingly */
1876  SCIP_CALL( tightenBounds(scip, consdata->x, xbnds, TRUE, cons, result, nchgbds, nfixedvars, &naddconss) );
1877  }
1878 
1879  /* delete constraint */
1880  SCIP_CALL( SCIPdelCons(scip, cons) );
1881 
1882  /* if tightenBounds added a constraint (because x was multiaggregated), then count this as constraint upgrade, otherwise as constraint deletion */
1883  if( naddconss > 0 )
1884  ++*nupgdconss;
1885  else
1886  ++*ndelconss;
1887 
1888  return SCIP_OKAY;
1889  }
1890 
1891  SCIPdebugMessage("in cons <%s>: z = <%s> replaced by %g*<%s> + %g\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->z), scalar, SCIPvarGetName(var), constant);
1892 
1893  /* we drop here the events for both variables, because if z is replaced by a multiaggregated variable here, then we do not need to catch bound tightenings on x anymore */
1894  SCIP_CALL( dropVarEvents(scip, conshdlrdata->eventhdlr, cons) );
1895  if( consdata->zcoef > 0.0 )
1896  SCIP_CALL( SCIPunlockVarCons(scip, consdata->z, cons, !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
1897  else
1898  SCIP_CALL( SCIPunlockVarCons(scip, consdata->z, cons, !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
1899 
1900  consdata->z = var;
1901  if( SCIPvarIsActive(consdata->z) )
1902  {
1903  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, consdata->z) );
1904  }
1905 
1906  /* substract constant from constraint sides */
1907  if( !SCIPisInfinity(scip, -consdata->lhs) )
1908  consdata->lhs -= consdata->zcoef * constant;
1909  if( !SCIPisInfinity(scip, consdata->rhs) )
1910  consdata->rhs -= consdata->zcoef * constant;
1911 
1912  /* multiply zcoef by scalar */
1913  consdata->zcoef *= scalar;
1914 
1915  if( consdata->zcoef > 0.0 )
1916  SCIP_CALL( SCIPlockVarCons(scip, consdata->z, cons, !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
1917  else
1918  SCIP_CALL( SCIPlockVarCons(scip, consdata->z, cons, !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
1919  SCIP_CALL( catchVarEvents(scip, conshdlrdata->eventhdlr, cons) );
1920 
1921  /* rerun constraint comparison */
1922  conshdlrdata->comparedpairwise = FALSE;
1923  }
1924 
1925  assert(SCIPvarIsActive(consdata->z) || SCIPvarGetStatus(consdata->z) == SCIP_VARSTATUS_MULTAGGR);
1926 
1927  return SCIP_OKAY;
1928 }
1929 
1930 /** gets maximal absolute value in gradient of quadratic function
1931  * thus, gives \f$max(n |x+offset|^{n-1}, |zcoef|)\f$.
1932  */
1933 static
1935  SCIP* scip, /**< SCIP data structure */
1936  SCIP_CONS* cons, /**< constraint */
1937  SCIP_SOL* sol /**< solution or NULL if LP solution should be used */
1938  )
1939 {
1940  SCIP_CONSDATA* consdata;
1941  SCIP_Real xval;
1942  SCIP_Real val;
1943 
1944  assert(scip != NULL);
1945  assert(cons != NULL);
1946 
1947  consdata = SCIPconsGetData(cons);
1948  assert(consdata != NULL);
1949 
1950  xval = SCIPgetSolVal(scip, sol, consdata->x);
1951  assert(!SCIPisInfinity(scip, REALABS(xval)));
1952 
1953  if( consdata->exponent == 2.0 )
1954  val = consdata->exponent * REALABS(xval + consdata->xoffset);
1955  else
1956  val = consdata->exponent * pow(REALABS(xval + consdata->xoffset), consdata->exponent - 1.0);
1957 
1958  return MAX(val, REALABS(consdata->zcoef)); /*lint !e666*/
1959 }
1960 
1961 /** computes violation of a constraint */
1962 static
1964  SCIP* scip, /**< SCIP data structure */
1965  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1966  SCIP_CONS* cons, /**< constraint */
1967  SCIP_SOL* sol, /**< solution or NULL if LP solution should be used */
1968  SCIP_Real* viol /**< pointer to store absolute (unscaled) constraint violation */
1969  )
1970 {
1971  SCIP_CONSHDLRDATA* conshdlrdata;
1972  SCIP_CONSDATA* consdata;
1973  SCIP_Real val;
1974  SCIP_Real xval;
1975  SCIP_Real zval;
1976 
1977  assert(scip != NULL);
1978  assert(conshdlr != NULL);
1979  assert(cons != NULL);
1980  assert(viol != NULL);
1981 
1982  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1983  assert(conshdlrdata != NULL);
1984 
1985  consdata = SCIPconsGetData(cons);
1986  assert(consdata != NULL);
1987 
1988  xval = SCIPgetSolVal(scip, sol, consdata->x);
1989  zval = SCIPgetSolVal(scip, sol, consdata->z);
1990 
1991  if( SCIPisInfinity(scip, REALABS(xval)) )
1992  {
1993  consdata->lhsviol = (SCIPisInfinity(scip, -consdata->lhs) ? 0.0 : SCIPinfinity(scip));
1994  consdata->rhsviol = (SCIPisInfinity(scip, consdata->rhs) ? 0.0 : SCIPinfinity(scip));
1995 
1996  return SCIP_OKAY;
1997  }
1998  /* project onto local box, in case the LP solution is slightly outside the bounds (which is not our job to enforce) */
1999  if( sol == NULL )
2000  {
2001  SCIP_Real lb;
2002  SCIP_Real ub;
2003  SCIP_Real minval;
2004 
2005  lb = SCIPvarGetLbLocal(consdata->x);
2006  ub = SCIPvarGetUbLocal(consdata->x);
2007  minval = MIN(ub, xval);
2008 
2009 #if 0 /* with non-initial columns, this might fail because variables can shortly be a column variable before entering the LP and have value 0.0 in this case */
2010  assert(SCIPisFeasGE(scip, xval, lb));
2011  assert(SCIPisFeasLE(scip, xval, ub));
2012 #endif
2013  xval = MAX(lb, minval);
2014 
2015  lb = SCIPvarGetLbLocal(consdata->z);
2016  ub = SCIPvarGetUbLocal(consdata->z);
2017  minval = MIN(ub, zval);
2018 
2019 #if 0 /* with non-initial columns, this might fail because variables can shortly be a column variable before entering the LP and have value 0.0 in this case */
2020  assert(SCIPisFeasGE(scip, zval, lb));
2021  assert(SCIPisFeasLE(scip, zval, ub));
2022 #endif
2023  zval = MAX(lb, minval);
2024  }
2025 
2026  xval += consdata->xoffset;
2027 
2028  val = SIGN(xval) * consdata->power(REALABS(xval), consdata->exponent);
2029  val += consdata->zcoef * zval;
2030 
2031  if( val < consdata->lhs && !SCIPisInfinity(scip, -consdata->lhs) )
2032  consdata->lhsviol = *viol = consdata->lhs - val;
2033  else
2034  consdata->lhsviol = 0.0;
2035 
2036  if( val > consdata->rhs && !SCIPisInfinity(scip, consdata->rhs) )
2037  consdata->rhsviol = *viol = val - consdata->rhs;
2038  else
2039  consdata->rhsviol = 0.0;
2040 
2041  switch( conshdlrdata->scaling )
2042  {
2043  case 'o' :
2044  /* no scaling */
2045  break;
2046 
2047  case 'g' :
2048  /* scale by sup-norm of gradient in current point */
2049  if( consdata->lhsviol > 0.0 || consdata->rhsviol > 0.0 )
2050  {
2051  SCIP_Real norm;
2052  norm = getGradientMaxElement(scip, cons, sol);
2053  if( norm > 1.0 )
2054  {
2055  consdata->lhsviol /= norm;
2056  consdata->rhsviol /= norm;
2057  }
2058  }
2059  break;
2060 
2061  case 's' :
2062  {
2063  SCIP_Real absval;
2064 
2065  /* scale by left/right hand side of constraint */
2066  if( consdata->lhsviol > 0.0 )
2067  {
2068  absval = REALABS(consdata->lhs);
2069  consdata->lhsviol /= MAX(1.0, absval);
2070  }
2071 
2072  if( consdata->rhsviol > 0.0 )
2073  {
2074  absval = REALABS(consdata->rhs);
2075  consdata->rhsviol /= MAX(1.0, absval);
2076  }
2077 
2078  break;
2079  }
2080 
2081  default :
2082  SCIPerrorMessage("Unknown scaling method '%c'.", conshdlrdata->scaling);
2083  SCIPABORT();
2084  return SCIP_INVALIDDATA; /*lint !e527*/
2085  }
2086 
2087  return SCIP_OKAY;
2088 }
2089 
2090 /** computes violation of a set of constraints */
2091 static
2093  SCIP* scip, /**< SCIP data structure */
2094  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2095  SCIP_CONS** conss, /**< constraints */
2096  int nconss, /**< number of constraints */
2097  SCIP_SOL* sol, /**< solution or NULL if LP solution should be used */
2098  SCIP_CONS** maxviolcon /**< buffer to store constraint with largest violation, or NULL if solution is feasible */
2099  )
2100 {
2101  SCIP_CONSDATA* consdata;
2102  SCIP_Real viol;
2103  SCIP_Real maxviol;
2104  int c;
2105 
2106  assert(scip != NULL);
2107  assert(conss != NULL || nconss == 0);
2108  assert(maxviolcon != NULL);
2109 
2110  *maxviolcon = NULL;
2111 
2112  maxviol = 0.0;
2113 
2114  for( c = 0; c < nconss; ++c )
2115  {
2116  assert(conss != NULL);
2117  assert(conss[c] != NULL);
2118 
2119  SCIP_CALL( computeViolation(scip, conshdlr, conss[c], sol, &viol) );
2120 
2121  consdata = SCIPconsGetData(conss[c]);
2122  assert(consdata != NULL);
2123 
2124  viol = MAX(consdata->lhsviol, consdata->rhsviol);
2125  if( viol > maxviol && SCIPisGT(scip, viol, SCIPfeastol(scip)) )
2126  {
2127  maxviol = viol;
2128  *maxviolcon = conss[c];
2129  }
2130  }
2131 
2132  return SCIP_OKAY;
2133 }
2134 
2135 /** proposes branching point for constraint */
2136 static
2138  SCIP* scip, /**< SCIP data structure */
2139  SCIP_CONS* cons, /**< constraint which variable to get branching point for */
2140  int preferzero, /**< how much we prefer branching on -xoffset (0, 1, or 2) if sign is not fixed */
2141  SCIP_Bool branchminconverror /**< whether to minimize convexification error if sign is fixed */
2142  )
2143 {
2144  SCIP_CONSDATA* consdata;
2145  SCIP_VAR* x;
2146  SCIP_Real xref;
2147  SCIP_Real xlb;
2148  SCIP_Real xub;
2149 
2150  assert(scip != NULL);
2151  assert(cons != NULL);
2152 
2153  consdata = SCIPconsGetData(cons);
2154  assert(consdata != NULL);
2155 
2156  x = consdata->x;
2157  xlb = SCIPvarGetLbLocal(x);
2158  xub = SCIPvarGetUbLocal(x);
2159 
2160  /* check if sign of x is not fixed yet */
2161  if( SCIPisLT(scip, xlb, -consdata->xoffset) && SCIPisGT(scip, xub, -consdata->xoffset) )
2162  {
2163  /* if preferzero is 0, just return SCIP_INVALID
2164  * if preferzero is 1, then propose -xoffset if branching on -xoffset would cut off solution in both child nodes, otherwise return SCIP_INVALID
2165  * if preferzero is >1, then always propose -xoffset
2166  */
2167  assert(preferzero >= 0);
2168 
2169  if( preferzero == 0 )
2170  return SCIP_INVALID;
2171 
2172  if( preferzero > 1 || SCIPisInfinity(scip, -xlb) || SCIPisInfinity(scip, xub) )
2173  return -consdata->xoffset;
2174 
2175  xlb += consdata->xoffset;
2176  xub += consdata->xoffset;
2177 
2178  xref = SCIPgetVarSol(scip, x) + consdata->xoffset;
2179  if( SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
2180  {
2181  /* signpow(x,n,offset) + c*z <= 0 is violated
2182  * if we are close to or right of -offset, then branching on -offset gives a convex function on the right branch, this is good
2183  * otherwise if branching on -offset yields a violated secant cut in left branch, then current solution would be cutoff there, this is also still good
2184  */
2185  if( !SCIPisFeasNegative(scip, xref) || SCIPisFeasPositive(scip, -consdata->power(-xlb, consdata->exponent)*xref/xlb + consdata->zcoef * SCIPgetVarSol(scip, consdata->z)) )
2186  return -consdata->xoffset;
2187  return SCIP_INVALID;
2188  }
2189 
2190  assert(SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) );
2191  /* signpow(x,n) + c*z >= 0 is violated
2192  * if we are close to or left of zero, then branching on 0.0 gives a concave function on the left branch, this is good
2193  * otherwise if branching on 0.0 yields a violated secant cut in right branch, then current solution would be cutoff there, this is also still good
2194  */
2195  if( !SCIPisFeasPositive(scip, xref) || SCIPisFeasNegative(scip, -consdata->power(xub, consdata->exponent)*xref/xub + consdata->zcoef * SCIPgetVarSol(scip, consdata->z)) )
2196  return -consdata->xoffset;
2197  return SCIP_INVALID;
2198  }
2199 
2200  if( branchminconverror )
2201  {
2202  /* given x^n with xlb <= x <= xub, then the sum of the integrals between the function and its secant on the left and right branches are minimized
2203  * for branching on ( (ub^n - lb^n) / (n*(ub - lb)) ) ^ (1/(n-1))
2204  */
2205  if( SCIPisGE(scip, xlb, -consdata->xoffset) )
2206  {
2207  SCIP_Real ref;
2208  xlb = MAX(0.0, xlb + consdata->xoffset);
2209  xub = MAX(0.0, xub + consdata->xoffset);
2210 
2211  ref = (consdata->power(xub, consdata->exponent) - consdata->power(xlb, consdata->exponent)) / (consdata->exponent * (xub - xlb));
2212  ref = pow(ref, 1.0/(consdata->exponent-1.0));
2213  ref -= consdata->xoffset;
2214  assert(SCIPisGE(scip, ref, SCIPvarGetLbLocal(x)));
2215  assert(SCIPisLE(scip, ref, SCIPvarGetUbLocal(x)));
2216 
2217  return ref;
2218  }
2219  else
2220  {
2221  SCIP_Real ref;
2222 
2223  assert(SCIPisLE(scip, xub, -consdata->xoffset));
2224 
2225  xlb = MIN(0.0, xlb + consdata->xoffset);
2226  xub = MIN(0.0, xub + consdata->xoffset);
2227 
2228  ref = (consdata->power(-xlb, consdata->exponent) - consdata->power(-xub, consdata->exponent)) / (consdata->exponent * (-xlb + xub));
2229  ref = -pow(ref, 1.0/(consdata->exponent-1.0));
2230  ref -= consdata->xoffset;
2231  assert(SCIPisGE(scip, ref, SCIPvarGetLbLocal(x)));
2232  assert(SCIPisLE(scip, ref, SCIPvarGetUbLocal(x)));
2233 
2234  return ref;
2235  }
2236  }
2237 
2238  return SCIP_INVALID;
2239 }
2240 
2241 /** registers branching variable candidates
2242  * registers x for all violated absolute power constraints where x is not in convex region
2243  */
2244 static
2246  SCIP* scip, /**< SCIP data structure */
2247  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2248  SCIP_CONS** conss, /**< constraints to check */
2249  int nconss, /**< number of constraints to check */
2250  int* nnotify /**< counter for number of notifications performed */
2251  )
2252 {
2253  SCIP_CONSHDLRDATA* conshdlrdata;
2254  SCIP_CONSDATA* consdata;
2255  SCIP_Bool onlynonfixedsign;
2256  int c;
2257 
2258  assert(scip != NULL);
2259  assert(conshdlr != NULL);
2260  assert(conss != NULL || nconss == 0);
2261 
2262  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2263  assert(conshdlrdata != NULL);
2264 
2265  *nnotify = 0;
2266 
2267  onlynonfixedsign = conshdlrdata->preferzerobranch == 3;
2268 
2269  do
2270  {
2271  for( c = 0; c < nconss; ++c )
2272  {
2273  assert(conss[c] != NULL); /*lint !e613*/
2274 
2275  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
2276  assert(consdata != NULL);
2277 
2278  SCIPdebugMessage("cons <%s> violation: %g %g\n", SCIPconsGetName(conss[c]), consdata->lhsviol, consdata->rhsviol); /*lint !e613*/
2279 
2280  /* skip variables which sign is already fixed, if we are only interested in variables with unfixed sign here */
2281  if( onlynonfixedsign &&
2282  ( !SCIPisLT(scip, SCIPvarGetLbLocal(consdata->x), -consdata->xoffset) ||
2283  !SCIPisGT(scip, SCIPvarGetUbLocal(consdata->x), consdata->xoffset)) )
2284  continue;
2285 
2286  /* if the value of x lies in a concave range (i.e., where a secant approximation is used), then register x as branching variable */
2287  if( (SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) && (SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->x)) || SCIPgetSolVal(scip, NULL, consdata->x) + consdata->xoffset <= -consdata->root * (SCIPvarGetLbLocal(consdata->x) + consdata->xoffset))) ||
2288  ( SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) && (SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->x)) || SCIPgetSolVal(scip, NULL, consdata->x) + consdata->xoffset >= -consdata->root * (SCIPvarGetUbLocal(consdata->x) + consdata->xoffset))) )
2289  {
2290  /* domain propagation should have removed constraints with fixed x, at least for violated constraints */
2291  assert(!SCIPisRelEQ(scip, SCIPvarGetLbLocal(consdata->x), SCIPvarGetUbLocal(consdata->x)));
2292 
2293  SCIPdebugMessage("register var <%s> in cons <%s> with violation %g %g\n", SCIPvarGetName(consdata->x), SCIPconsGetName(conss[c]), consdata->lhsviol, consdata->rhsviol); /*lint !e613*/
2294  SCIP_CALL( SCIPaddExternBranchCand(scip, consdata->x, MAX(consdata->lhsviol, consdata->rhsviol), proposeBranchingPoint(scip, conss[c], conshdlrdata->preferzerobranch, conshdlrdata->branchminconverror)) ); /*lint !e613*/
2295  ++*nnotify;
2296  }
2297  }
2298 
2299  if( onlynonfixedsign && *nnotify == 0 )
2300  {
2301  /* if we could not a variable in a violated constraint which sign is not already fixed, do another round where we consider all variables again */
2302  onlynonfixedsign = FALSE;
2303  continue;
2304  }
2305  }
2306  while( FALSE );
2307 
2308  return SCIP_OKAY;
2309 }
2310 
2311 /** registers a variable from a violated constraint as branching candidate that has a large absolute value in the LP relaxation */
2312 static
2314  SCIP* scip, /**< SCIP data structure */
2315  SCIP_CONS** conss, /**< constraints */
2316  int nconss, /**< number of constraints */
2317  SCIP_VAR** brvar /**< buffer to store branching variable */
2318  )
2319 {
2320  SCIP_CONSDATA* consdata;
2321  SCIP_Real val;
2322  SCIP_Real brvarval;
2323  int c;
2324 
2325  assert(scip != NULL);
2326  assert(conss != NULL || nconss == 0);
2327 
2328  *brvar = NULL;
2329  brvarval = -1.0;
2330 
2331  for( c = 0; c < nconss; ++c )
2332  {
2333  assert(conss != NULL);
2334  consdata = SCIPconsGetData(conss[c]);
2335  assert(consdata != NULL);
2336 
2337  if( !SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) && !SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
2338  continue;
2339 
2340  val = SCIPgetSolVal(scip, NULL, consdata->x) + consdata->xoffset;
2341  if( REALABS(val) > brvarval )
2342  {
2343  brvarval = ABS(val);
2344  *brvar = consdata->x;
2345  }
2346  }
2347 
2348  if( *brvar != NULL )
2349  {
2350  SCIP_CALL( SCIPaddExternBranchCand(scip, *brvar, brvarval, SCIP_INVALID) );
2351  }
2352 
2353  return SCIP_OKAY;
2354 }
2355 
2356 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
2357  * propagation rule (see propagateCons()):
2358  * see cons_varbound
2359  */
2360 static
2362  SCIP* scip, /**< SCIP data structure */
2363  SCIP_CONS* cons, /**< constraint that inferred the bound change */
2364  SCIP_VAR* infervar, /**< variable that was deduced */
2365  PROPRULE proprule, /**< propagation rule that deduced the bound change */
2366  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
2367  SCIP_BDCHGIDX* bdchgidx /**< bound change index (time stamp of bound change), or NULL for current time */
2368  )
2369 {
2370  SCIP_CONSDATA* consdata;
2371 
2372  assert(scip != NULL);
2373  assert(cons != NULL);
2374  assert(infervar != NULL);
2375 
2376  consdata = SCIPconsGetData(cons);
2377  assert(consdata != NULL);
2378  assert(consdata->zcoef != 0.0);
2379 
2380  switch( proprule )
2381  {
2382  case PROPRULE_1:
2383  /* lhs <= sign(x+offset)|x+offset|^n + c*z: left hand side and bounds on z -> lower bound on x */
2384  assert(infervar == consdata->x);
2385  assert(boundtype == SCIP_BOUNDTYPE_LOWER);
2386  assert(!SCIPisInfinity(scip, -consdata->lhs));
2387  if( consdata->zcoef > 0.0 )
2388  {
2389  SCIP_CALL( SCIPaddConflictUb(scip, consdata->z, bdchgidx) );
2390  }
2391  else
2392  {
2393  SCIP_CALL( SCIPaddConflictLb(scip, consdata->z, bdchgidx) );
2394  }
2395  break;
2396 
2397  case PROPRULE_2:
2398  /* lhs <= sign(x+offset)|x+offset|^n + c*z: left hand side and upper bound on x -> bound on z */
2399  assert(infervar == consdata->z);
2400  assert(!SCIPisInfinity(scip, -consdata->lhs));
2401  SCIP_CALL( SCIPaddConflictUb(scip, consdata->x, bdchgidx) );
2402  break;
2403 
2404  case PROPRULE_3:
2405  /* sign(x+offset)|x+offset|^n + c*z <= rhs: right hand side and bounds on z -> upper bound on x */
2406  assert(infervar == consdata->x);
2407  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
2408  assert(!SCIPisInfinity(scip, consdata->rhs));
2409  if( consdata->zcoef > 0.0 )
2410  {
2411  SCIP_CALL( SCIPaddConflictLb(scip, consdata->z, bdchgidx) );
2412  }
2413  else
2414  {
2415  SCIP_CALL( SCIPaddConflictUb(scip, consdata->z, bdchgidx) );
2416  }
2417  break;
2418 
2419  case PROPRULE_4:
2420  /* sign(x+offset)|x+offset|^n + c*z <= rhs: right hand side and lower bound on x -> bound on z */
2421  assert(infervar == consdata->z);
2422  assert(!SCIPisInfinity(scip, consdata->rhs));
2423  SCIP_CALL( SCIPaddConflictLb(scip, consdata->x, bdchgidx) );
2424  break;
2425 
2426  case PROPRULE_INVALID:
2427  default:
2428  SCIPerrorMessage("invalid inference information %d in absolute power constraint <%s>\n", proprule, SCIPconsGetName(cons));
2429  return SCIP_INVALIDDATA;
2430  }
2431 
2432  return SCIP_OKAY;
2433 }
2434 
2435 /** analyze infeasibility */
2436 static
2438  SCIP* scip, /**< SCIP data structure */
2439  SCIP_CONS* cons, /**< variable bound constraint */
2440  SCIP_VAR* infervar, /**< variable that was deduced */
2441  PROPRULE proprule, /**< propagation rule that deduced the bound change */
2442  SCIP_BOUNDTYPE boundtype /**< the type of the changed bound (lower or upper bound) */
2443  )
2444 {
2445  /* conflict analysis can only be applied in solving stage and if it turned on */
2447  return SCIP_OKAY;
2448 
2449  /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
2451 
2452  /* add the bound which got violated */
2453  if( boundtype == SCIP_BOUNDTYPE_LOWER )
2454  {
2455  SCIP_CALL( SCIPaddConflictUb(scip, infervar, NULL) );
2456  }
2457  else
2458  {
2459  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
2460  SCIP_CALL( SCIPaddConflictLb(scip, infervar, NULL) );
2461  }
2462 
2463  /* add the reason for the violated of the bound */
2464  SCIP_CALL( resolvePropagation(scip, cons, infervar, proprule, boundtype, NULL) );
2465 
2466  /* analyze the conflict */
2467  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
2468 
2469  return SCIP_OKAY;
2470 }
2471 
2472 /** propagation method for absolute power constraint
2473  * SCIPinferVarXbCons to allow for repropagation
2474  */
2475 static
2477  SCIP* scip, /**< SCIP data structure */
2478  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2479  SCIP_CONS* cons, /**< variable bound constraint */
2480  SCIP_Bool canaddcons, /**< are we allowed to add a linear constraint when enforcing bounds for a multiaggregated variable? */
2481  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
2482  int* nchgbds, /**< pointer to count number of bound changes */
2483  int* naddconss /**< pointer to count number of added constraints */
2484  )
2485 {
2486  SCIP_CONSDATA* consdata;
2487  SCIP_Real xlb;
2488  SCIP_Real xub;
2489  SCIP_Real zlb;
2490  SCIP_Real zub;
2491  SCIP_Real newlb;
2492  SCIP_Real newub;
2493  SCIP_Bool tightened;
2494  SCIP_Bool tightenedround;
2495  SCIP_Real minact;
2496  SCIP_Real maxact;
2497 
2498  assert(conshdlr != NULL);
2499  assert(cutoff != NULL);
2500  assert(nchgbds != NULL);
2501  assert(naddconss != NULL);
2502 
2503  consdata = SCIPconsGetData(cons);
2504  assert(consdata != NULL);
2505 
2506  SCIPdebugMessage("propagating absolute power constraint <%s>\n", SCIPconsGetName(cons));
2507 
2508  *cutoff = FALSE;
2509 
2510  /* get current bounds of variables */
2511  xlb = SCIPvarGetLbLocal(consdata->x);
2512  xub = SCIPvarGetUbLocal(consdata->x);
2513  zlb = SCIPvarGetLbLocal(consdata->z);
2514  zub = SCIPvarGetUbLocal(consdata->z);
2515 
2516  /* if some bound is not tightened, tighten bounds of variables as long as possible */
2517  tightenedround = !consdata->isxpropagated || !consdata->iszpropagated;
2518  while( tightenedround )
2519  {
2520  tightenedround = FALSE;
2521 
2522  /* propagate left hand side inequality: lhs <= (x+offset)*|x+offset|^n + c*z */
2523  if( !SCIPisInfinity(scip, -consdata->lhs) )
2524  {
2525  assert(!*cutoff);
2526 
2527  /* propagate bounds on x (if not multiaggregated):
2528  * (1) left hand side and bounds on z -> lower bound on x
2529  */
2530  if( SCIPvarIsActive(SCIPvarGetProbvar(consdata->x)) && (!SCIPisFeasEQ(scip, zlb, zub) || !SCIPisInfinity(scip, REALABS(zlb))) )
2531  {
2532  /* if z is fixed, first compute new lower bound on x without tolerances
2533  * if that is feasible, project new lower bound onto current bounds
2534  * otherwise, recompute with tolerances and continue as usual
2535  */
2536  if( SCIPisFeasEQ(scip, zlb, zub) )
2537  {
2538  assert(!SCIPisInfinity(scip, -zlb));
2539  assert(!SCIPisInfinity(scip, zub));
2540 
2541  newlb = consdata->lhs - consdata->zcoef * (consdata->zcoef > 0.0 ? zub : zlb);
2542 
2543  /* invert sign(x+offset)|x+offset|^(n-1) = y -> x = sign(y)|y|^(1/n) - offset */
2544  if( consdata->exponent == 2.0 )
2545  newlb = SIGN(newlb) * sqrt(ABS(newlb));
2546  else
2547  newlb = SIGN(newlb) * pow(ABS(newlb), 1.0/consdata->exponent);
2548  newlb -= consdata->xoffset;
2549 
2550  if( SCIPisFeasGT(scip, newlb, xub) )
2551  {
2552  /* if new lower bound for x would yield cutoff, recompute with tolerances */
2553  newlb = consdata->lhs - PROPSIDETOL - consdata->zcoef * (consdata->zcoef > 0.0 ? (zub + PROPVARTOL) : (zlb - PROPVARTOL));
2554 
2555  /* invert sign(x+offset)|x+offset|^(n-1) = y -> x = sign(y)|y|^(1/n) - offset */
2556  if( consdata->exponent == 2.0 )
2557  newlb = SIGN(newlb) * sqrt(ABS(newlb));
2558  else
2559  newlb = SIGN(newlb) * pow(ABS(newlb), 1.0/consdata->exponent);
2560  newlb -= consdata->xoffset;
2561  }
2562  else
2563  {
2564  /* project new lower bound onto current bounds */
2565  newlb = MIN(newlb, xub);
2566  }
2567  }
2568  else
2569  {
2570  if( consdata->zcoef > 0.0 )
2571  {
2572  if( !SCIPisInfinity(scip, zub) )
2573  newlb = consdata->lhs - PROPSIDETOL - consdata->zcoef * (zub + PROPVARTOL);
2574  else
2575  newlb = -SCIPinfinity(scip);
2576  }
2577  else
2578  {
2579  if( !SCIPisInfinity(scip, -zlb) )
2580  newlb = consdata->lhs - PROPSIDETOL - consdata->zcoef * (zlb - PROPVARTOL);
2581  else
2582  newlb = -SCIPinfinity(scip);
2583  }
2584 
2585  if( !SCIPisInfinity(scip, -newlb) )
2586  {
2587  /* invert sign(x+offset)|x+offset|^(n-1) = y -> x = sign(y)|y|^(1/n) - offset */
2588  if( consdata->exponent == 2.0 )
2589  newlb = SIGN(newlb) * sqrt(ABS(newlb));
2590  else
2591  newlb = SIGN(newlb) * pow(ABS(newlb), 1.0/consdata->exponent);
2592  newlb -= consdata->xoffset;
2593  }
2594  }
2595 
2596  if( SCIPisInfinity(scip, newlb) )
2597  {
2598  /* we cannot fix a variable to +infinity, so let's report cutoff (there is no solution within SCIPs limitations to infinity) */
2599  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g] -> cutoff\n", SCIPvarGetName(consdata->x), xlb, xub, newlb, xub);
2600 
2601  *cutoff = TRUE;
2602 
2603  /* analyze infeasibility */
2604  SCIP_CALL( analyzeConflict(scip, cons, consdata->x, PROPRULE_1, SCIP_BOUNDTYPE_LOWER) );
2605  break;
2606  }
2607 
2608  if( !SCIPisInfinity(scip, -newlb) )
2609  {
2610  if( SCIPisLbBetter(scip, newlb, xlb, xub) )
2611  {
2612  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n",
2613  SCIPvarGetName(consdata->x), xlb, xub, newlb, xub);
2614  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->x, newlb, cons, (int)PROPRULE_1, FALSE, cutoff, &tightened) );
2615 
2616  if( *cutoff )
2617  {
2618  assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->x)));
2619 
2620  /* analyze infeasibility */
2621  SCIP_CALL( analyzeConflict(scip, cons, consdata->x, PROPRULE_1, SCIP_BOUNDTYPE_LOWER) );
2622  break;
2623  }
2624 
2625  if( tightened )
2626  {
2627  tightenedround = TRUE;
2628  (*nchgbds)++;
2629  }
2630  xlb = SCIPvarGetLbLocal(consdata->x);
2631  }
2632  }
2633  }
2634 
2635  assert(!*cutoff);
2636 
2637  /* propagate bounds on z:
2638  * (2) left hand side and upper bound on x -> bound on z
2639  */
2640  if( SCIPvarGetStatus(consdata->z) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, xub) ) /* cannot change bounds of multaggr vars */
2641  {
2642  SCIP_Real newbd;
2643 
2644  /* if x is fixed, first compute new bound on z without tolerances
2645  * if that is feasible, project new bound onto current bounds
2646  * otherwise, recompute with tolerances and continue as usual
2647  */
2648  if( SCIPisFeasEQ(scip, xlb, xub) )
2649  {
2650  newbd = xub + consdata->xoffset;
2651  newbd = consdata->lhs - SIGN(newbd) * consdata->power(REALABS(newbd), consdata->exponent);
2652  newbd /= consdata->zcoef;
2653 
2654  if( SCIPisInfinity(scip, newbd) )
2655  newbd = SCIPinfinity(scip);
2656  else if( SCIPisInfinity(scip, -newbd) )
2657  newbd = -SCIPinfinity(scip);
2658 
2659  if( (consdata->zcoef > 0.0 && SCIPisFeasGT(scip, newbd, zub)) || (consdata->zcoef < 0.0 && SCIPisFeasLT(scip, newbd, zlb)) )
2660  {
2661  /* if infeasible, recompute with tolerances */
2662  newbd = xub + PROPVARTOL + consdata->xoffset;
2663  newbd = consdata->lhs - PROPSIDETOL - SIGN(newbd) * consdata->power(REALABS(newbd), consdata->exponent);
2664  newbd /= consdata->zcoef;
2665  }
2666  else
2667  {
2668  /* project onto current bounds of z */
2669  newbd = MIN(zub, MAX(zlb, newbd) );
2670  }
2671  }
2672  else
2673  {
2674  newbd = xub + PROPVARTOL + consdata->xoffset;
2675  newbd = consdata->lhs - PROPSIDETOL - SIGN(newbd) * consdata->power(REALABS(newbd), consdata->exponent);
2676  newbd /= consdata->zcoef;
2677  }
2678 
2679  if( consdata->zcoef > 0.0 )
2680  {
2681  newlb = newbd;
2682 
2683  if( SCIPisInfinity(scip, newlb) )
2684  {
2685  /* we cannot fix a variable to +infinity, so let's report cutoff (there is no solution within SCIPs limitations to infinity) */
2686  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g] -> cutoff\n", SCIPvarGetName(consdata->z), zlb, zub, newlb, zub);
2687 
2688  *cutoff = TRUE;
2689 
2690  /* analyze infeasibility */
2691  SCIP_CALL( analyzeConflict(scip, cons, consdata->z, PROPRULE_2, SCIP_BOUNDTYPE_LOWER) );
2692  break;
2693  }
2694 
2695  if( SCIPisLbBetter(scip, newlb, zlb, zub) )
2696  {
2697  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n",
2698  SCIPvarGetName(consdata->z), zlb, zub, newlb, zub);
2699  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->z, newlb, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
2700 
2701  if( *cutoff )
2702  {
2703  assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->z)));
2704 
2705  /* analyze infeasibility */
2706  SCIP_CALL( analyzeConflict(scip, cons, consdata->z, PROPRULE_2, SCIP_BOUNDTYPE_LOWER) );
2707  break;
2708  }
2709 
2710  if( tightened )
2711  {
2712  tightenedround = TRUE;
2713  (*nchgbds)++;
2714  }
2715  zlb = SCIPvarGetLbLocal(consdata->z);
2716  }
2717  }
2718  else
2719  {
2720  newub = newbd;
2721 
2722  if( SCIPisInfinity(scip, -newub) )
2723  {
2724  /* we cannot fix a variable to -infinity, so let's report cutoff (there is no solution within SCIPs limitations to infinity) */
2725  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g] -> cutoff\n", SCIPvarGetName(consdata->z), zlb, zub, zlb, newub);
2726 
2727  *cutoff = TRUE;
2728 
2729  /* analyze infeasibility */
2730  SCIP_CALL( analyzeConflict(scip, cons, consdata->z, PROPRULE_2, SCIP_BOUNDTYPE_UPPER) );
2731  break;
2732  }
2733 
2734  if( SCIPisUbBetter(scip, newub, zlb, zub) )
2735  {
2736  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n",
2737  SCIPvarGetName(consdata->z), zlb, zub, zlb, newub);
2738  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->z, newub, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
2739 
2740  if( *cutoff )
2741  {
2742  assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->z)));
2743 
2744  /* analyze infeasibility */
2745  SCIP_CALL( analyzeConflict(scip, cons, consdata->z, PROPRULE_2, SCIP_BOUNDTYPE_UPPER) );
2746  break;
2747  }
2748 
2749  if( tightened )
2750  {
2751  tightenedround = TRUE;
2752  (*nchgbds)++;
2753  }
2754  zub = SCIPvarGetUbLocal(consdata->z);
2755  }
2756  }
2757  }
2758  }
2759 
2760  assert(!*cutoff);
2761 
2762  /* propagate right hand side inequality: sign(x+offset)|x+offset|^n + c*z <= rhs */
2763  if( !SCIPisInfinity(scip, consdata->rhs) )
2764  {
2765  /* propagate bounds on x:
2766  * (3) right hand side and bounds on z -> upper bound on x
2767  */
2768  if( SCIPvarIsActive(SCIPvarGetProbvar(consdata->x)) && (!SCIPisFeasEQ(scip, zlb, zub) || !SCIPisInfinity(scip, REALABS(zlb))) ) /* cannot change bounds of multaggr or fixed vars */
2769  {
2770  /* if z is fixed, first compute new upper bound on x without tolerances
2771  * if that is feasible, project new upper bound onto current bounds
2772  * otherwise, recompute with tolerances and continue as usual
2773  */
2774  if( SCIPisFeasEQ(scip, zlb, zub) )
2775  {
2776  assert(!SCIPisInfinity(scip, -zlb));
2777  assert(!SCIPisInfinity(scip, zub));
2778 
2779  newub = consdata->rhs - consdata->zcoef * (consdata->zcoef > 0.0 ? zlb : zub);
2780 
2781  /* invert sign(x+offset)|x+offset|^(n-1) = y -> x = sign(y)|y|^(1/n) - offset */
2782  if( consdata->exponent == 2.0 )
2783  newub = SIGN(newub) * sqrt(ABS(newub));
2784  else
2785  newub = SIGN(newub) * pow(ABS(newub), 1.0/consdata->exponent);
2786  newub -= consdata->xoffset;
2787 
2788  if( SCIPisFeasLT(scip, newub, xlb) )
2789  {
2790  /* if new lower bound for x would yield cutoff, recompute with tolerances */
2791  newub = consdata->rhs + PROPSIDETOL - consdata->zcoef * (consdata->zcoef > 0.0 ? (zlb - PROPVARTOL) : (zub + PROPVARTOL));
2792 
2793  /* invert sign(x+offset)|x+offset|^(n-1) = y -> x = sign(y)|y|^(1/n) - offset */
2794  if( consdata->exponent == 2.0 )
2795  newub = SIGN(newub) * sqrt(ABS(newub));
2796  else
2797  newub = SIGN(newub) * pow(ABS(newub), 1.0/consdata->exponent);
2798  newub -= consdata->xoffset;
2799  }
2800  else
2801  {
2802  /* project new upper bound onto current bounds */
2803  newub = MAX(newub, xlb);
2804  }
2805  }
2806  else
2807  {
2808  if( consdata->zcoef > 0.0 )
2809  {
2810  if( !SCIPisInfinity(scip, -zlb) )
2811  newub = consdata->rhs + PROPSIDETOL - consdata->zcoef * (zlb - PROPVARTOL);
2812  else
2813  newub = SCIPinfinity(scip);
2814  }
2815  else
2816  {
2817  if( !SCIPisInfinity(scip, zub) )
2818  newub = consdata->rhs + PROPSIDETOL - consdata->zcoef * (zub + PROPVARTOL);
2819  else
2820  newub = SCIPinfinity(scip);
2821  }
2822  if( !SCIPisInfinity(scip, newub) )
2823  {
2824  /* invert sign(x+offset)|x+offset|^(n-1) = y -> x = sign(y)|y|^(1/n) - offset */
2825  if( consdata->exponent == 2.0 )
2826  newub = SIGN(newub) * sqrt(ABS(newub));
2827  else
2828  newub = SIGN(newub) * pow(ABS(newub), 1.0/consdata->exponent);
2829  newub -= consdata->xoffset;
2830  }
2831  }
2832 
2833  if( SCIPisInfinity(scip, -newub) )
2834  {
2835  /* we cannot fix a variable to -infinity, so let's report cutoff (there is no solution within SCIPs limitations to infinity) */
2836  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g] -> cutoff\n", SCIPvarGetName(consdata->x), xlb, xub, xlb, newub);
2837 
2838  *cutoff = TRUE;
2839 
2840  /* analyze infeasibility */
2841  SCIP_CALL( analyzeConflict(scip, cons, consdata->x, PROPRULE_3, SCIP_BOUNDTYPE_UPPER) );
2842  break;
2843  }
2844 
2845  if( !SCIPisInfinity(scip, newub) )
2846  {
2847  if( SCIPisUbBetter(scip, newub, xlb, xub) )
2848  {
2849  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n",
2850  SCIPvarGetName(consdata->x), xlb, xub, xlb, newub);
2851  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->x, newub, cons, (int)PROPRULE_3, FALSE, cutoff, &tightened) );
2852 
2853  if( *cutoff )
2854  {
2855  assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->x)));
2856 
2857  /* analyze infeasibility */
2858  SCIP_CALL( analyzeConflict(scip, cons, consdata->x, PROPRULE_3, SCIP_BOUNDTYPE_UPPER) );
2859  break;
2860  }
2861 
2862  if( tightened )
2863  {
2864  tightenedround = TRUE;
2865  (*nchgbds)++;
2866  }
2867  xub = SCIPvarGetUbLocal(consdata->x);
2868  }
2869  }
2870  }
2871 
2872  assert(!*cutoff);
2873 
2874  /* propagate bounds on z:
2875  * (4) right hand side and lower bound on x -> bound on z
2876  */
2877  if( SCIPvarGetStatus(consdata->z) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, -xlb) ) /* cannot change bounds of multaggr vars */
2878  {
2879  SCIP_Real newbd;
2880 
2881  /* if x is fixed, first compute new bound on z without tolerances
2882  * if that is feasible, project new bound onto current bounds
2883  * otherwise, recompute with tolerances and continue as usual
2884  */
2885  if( SCIPisFeasEQ(scip, xlb, xub) )
2886  {
2887  newbd = xlb + consdata->xoffset;
2888  newbd = consdata->rhs - SIGN(newbd) * consdata->power(REALABS(newbd), consdata->exponent);
2889  newbd /= consdata->zcoef;
2890 
2891  if( SCIPisInfinity(scip, newbd) )
2892  newbd = SCIPinfinity(scip);
2893  else if( SCIPisInfinity(scip, -newbd) )
2894  newbd = -SCIPinfinity(scip);
2895 
2896  if( (consdata->zcoef > 0.0 && SCIPisFeasLT(scip, newbd, zlb)) || (consdata->zcoef < 0.0 && SCIPisFeasGT(scip, newbd, zub)) )
2897  {
2898  /* if infeasible, recompute with tolerances */
2899  newbd = xlb - PROPVARTOL + consdata->xoffset;
2900  newbd = consdata->rhs + PROPSIDETOL - SIGN(newbd) * consdata->power(REALABS(newbd), consdata->exponent);
2901  newbd /= consdata->zcoef;
2902  }
2903  else
2904  {
2905  /* project onto current bounds of z */
2906  newbd = MIN(zub, MAX(zlb, newbd) );
2907  }
2908  }
2909  else
2910  {
2911  newbd = xlb - PROPVARTOL + consdata->xoffset;
2912  newbd = consdata->rhs + PROPSIDETOL - SIGN(newbd) * consdata->power(REALABS(newbd), consdata->exponent);
2913  newbd /= consdata->zcoef;
2914  }
2915 
2916  if( consdata->zcoef > 0.0 )
2917  {
2918  newub = newbd;
2919 
2920  if( SCIPisInfinity(scip, -newub) )
2921  {
2922  /* we cannot fix a variable to -infinity, so let's report cutoff (there is no solution within SCIPs limitations to infinity) */
2923  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g] -> cutoff\n", SCIPvarGetName(consdata->z), zlb, zub, zlb, newub);
2924 
2925  *cutoff = TRUE;
2926 
2927  /* analyze infeasibility */
2928  SCIP_CALL( analyzeConflict(scip, cons, consdata->z, PROPRULE_4, SCIP_BOUNDTYPE_UPPER) );
2929  break;
2930  }
2931 
2932  if( SCIPisUbBetter(scip, newub, zlb, zub) )
2933  {
2934  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n",
2935  SCIPvarGetName(consdata->z), zlb, zub, zlb, newub);
2936  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->z, newub, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
2937 
2938  if( *cutoff )
2939  {
2940  assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->z)));
2941 
2942  /* analyze infeasibility */
2943  SCIP_CALL( analyzeConflict(scip, cons, consdata->z, PROPRULE_4, SCIP_BOUNDTYPE_UPPER) );
2944  break;
2945  }
2946 
2947  if( tightened )
2948  {
2949  tightenedround = TRUE;
2950  (*nchgbds)++;
2951  }
2952  zub = SCIPvarGetUbLocal(consdata->z);
2953  }
2954  }
2955  else
2956  {
2957  newlb = newbd;
2958 
2959  if( SCIPisInfinity(scip, newlb) )
2960  {
2961  /* we cannot fix a variable to +infinity, so let's report cutoff (there is no solution within SCIPs limitations to infinity) */
2962  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g] -> cutoff\n", SCIPvarGetName(consdata->z), zlb, zub, newlb, zub);
2963 
2964  *cutoff = TRUE;
2965 
2966  /* analyze infeasibility */
2967  SCIP_CALL( analyzeConflict(scip, cons, consdata->z, PROPRULE_4, SCIP_BOUNDTYPE_LOWER) );
2968  break;
2969  }
2970 
2971  if( SCIPisLbBetter(scip, newlb, zlb, zub) )
2972  {
2973  SCIPdebugMessage(" -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n",
2974  SCIPvarGetName(consdata->z), zlb, zub, newlb, zub);
2975  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->z, newlb, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
2976 
2977  if( *cutoff )
2978  {
2979  assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->z)));
2980 
2981  /* analyze infeasibility */
2982  SCIP_CALL( analyzeConflict(scip, cons, consdata->z, PROPRULE_4, SCIP_BOUNDTYPE_LOWER) );
2983  break;
2984  }
2985 
2986  if( tightened )
2987  {
2988  tightenedround = TRUE;
2989  (*nchgbds)++;
2990  }
2991  zlb = SCIPvarGetLbLocal(consdata->z);
2992  }
2993  }
2994  }
2995  }
2996 
2997  assert(!*cutoff);
2998  }
2999 
3000  /* mark the constraint propagated */
3001  consdata->isxpropagated = TRUE;
3002  consdata->iszpropagated = TRUE;
3003 
3004  if( *cutoff )
3005  return SCIP_OKAY;
3006 
3007  /* check for redundancy */
3008  if( !SCIPisInfinity(scip, -xlb) && !SCIPisInfinity(scip, consdata->zcoef > 0.0 ? -zlb : zub) )
3009  minact = SIGN(xlb + consdata->xoffset) * consdata->power(REALABS(xlb + consdata->xoffset), consdata->exponent) + consdata->zcoef * (consdata->zcoef > 0.0 ? zlb : zub);
3010  else
3011  minact = -SCIPinfinity(scip);
3012 
3013  if( !SCIPisInfinity(scip, xub) && !SCIPisInfinity(scip, consdata->zcoef > 0.0 ? zub : -zlb) )
3014  maxact = SIGN(xub + consdata->xoffset) * consdata->power(REALABS(xub + consdata->xoffset), consdata->exponent) + consdata->zcoef * (consdata->zcoef > 0.0 ? zub : zlb);
3015  else
3016  maxact = SCIPinfinity(scip);
3017 
3018  if( SCIPisFeasGE(scip, minact, consdata->lhs) && SCIPisFeasLE(scip, maxact, consdata->rhs) )
3019  {
3020  SCIPdebugMessage("absolute power constraint <%s> is redundant: <%s>[%.15g,%.15g], <%s>[%.15g,%.15g]\n",
3021  SCIPconsGetName(cons),
3022  SCIPvarGetName(consdata->x), SCIPvarGetLbLocal(consdata->x), SCIPvarGetUbLocal(consdata->x),
3023  SCIPvarGetName(consdata->z), SCIPvarGetLbLocal(consdata->z), SCIPvarGetUbLocal(consdata->z));
3024 
3025  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
3026 
3027  return SCIP_OKAY;
3028  }
3029 
3030  /* delete constraint if x has been fixed */
3031  if( SCIPisRelEQ(scip, xlb, xub) && (SCIPvarIsActive(consdata->z) || canaddcons) )
3032  {
3033  SCIP_RESULT tightenresult;
3034  SCIP_INTERVAL xbnds;
3035  SCIP_INTERVAL zbnds;
3036 
3037  SCIPdebugMessage("x-variable in constraint <%s> is fixed: x = <%s>[%.15g,%.15g], z = <%s>[%.15g,%.15g]\n",
3038  SCIPconsGetName(cons), SCIPvarGetName(consdata->x), xlb, xub, SCIPvarGetName(consdata->z), zlb, zub);
3039 
3040  SCIPintervalSetBounds(&xbnds, MIN(xlb, xub), MAX(xlb, xub));
3041  computeBoundsZ(scip, cons, xbnds, &zbnds);
3042 
3043  /* in difference to the loop above, here we enforce a possible bound tightening on z, and may add a linear cons if z is multiaggregated */
3044  SCIP_CALL( tightenBounds(scip, consdata->z, zbnds, TRUE, cons, &tightenresult, nchgbds, nchgbds, naddconss) );
3045  if( tightenresult == SCIP_CUTOFF )
3046  *cutoff = TRUE;
3047 
3048  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
3049 
3050  return SCIP_OKAY;
3051  }
3052 
3053  /* delete constraint if z has been fixed */
3054  if( SCIPisRelEQ(scip, zlb, zub) && (SCIPvarIsActive(consdata->x) || canaddcons) )
3055  {
3056  SCIP_RESULT tightenresult;
3057  SCIP_INTERVAL xbnds;
3058  SCIP_INTERVAL zbnds;
3059 
3060  SCIPdebugMessage("z-variable in constraint <%s> is fixed: x = <%s>[%.15g,%.15g], z = <%s>[%.15g,%.15g]\n",
3061  SCIPconsGetName(cons), SCIPvarGetName(consdata->x), xlb, xub, SCIPvarGetName(consdata->z), zlb, zub);
3062 
3063  SCIPintervalSetBounds(&zbnds, MIN(zlb, zub), MAX(zlb, zub));
3064  computeBoundsX(scip, cons, zbnds, &xbnds);
3065 
3066  /* in difference to the loop above, here we enforce a possible bound tightening on x, and may add a linear cons if x is multiaggregated */
3067  SCIP_CALL( tightenBounds(scip, consdata->x, xbnds, TRUE, cons, &tightenresult, nchgbds, nchgbds, naddconss) );
3068  if( tightenresult == SCIP_CUTOFF )
3069  *cutoff = TRUE;
3070 
3071  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
3072 
3073  return SCIP_OKAY;
3074  }
3075 
3076  return SCIP_OKAY;
3077 }
3078 
3079 /** notifies SCIP about a variable bound lhs <= x + c*y <= rhs */
3080 static
3082  SCIP* scip, /**< SCIP data structure */
3083  SCIP_CONS* cons, /**< absolute power constraint this variable bound is derived form */
3084  SCIP_Bool addcons, /**< should the variable bound be added as constraint to SCIP? */
3085  SCIP_VAR* var, /**< variable x for which we want to add a variable bound */
3086  SCIP_VAR* vbdvar, /**< variable y which makes the bound a variable bound */
3087  SCIP_Real vbdcoef, /**< coefficient c of bounding variable vbdvar */
3088  SCIP_Real lhs, /**< left hand side of varbound constraint */
3089  SCIP_Real rhs, /**< right hand side of varbound constraint */
3090  SCIP_Bool* infeas, /**< pointer to store whether an infeasibility was detected */
3091  int* nbdchgs, /**< pointer where to add number of performed bound changes */
3092  int* naddconss /**< pointer where to add number of added constraints */
3093  )
3094 {
3095  int nbdchgs_local;
3096 
3097  assert(scip != NULL);
3098  assert(cons != NULL);
3099  assert(var != NULL);
3100  assert(vbdvar != NULL);
3101  assert(!SCIPisZero(scip, vbdcoef));
3102  assert(!SCIPisInfinity(scip, ABS(vbdcoef)));
3103  assert(infeas != NULL);
3104 
3105  *infeas = FALSE;
3106 
3107  /* make sure vbdvar is active, so we can search for it in SCIPvarGetVxbdVars() */
3108  if( !SCIPvarIsActive(vbdvar) )
3109  {
3110  SCIP_Real constant;
3111 
3112  constant = 0.0;
3113  SCIP_CALL( SCIPgetProbvarSum(scip, &vbdvar, &vbdcoef, &constant) );
3114  if( !SCIPvarIsActive(vbdvar) || (vbdcoef == 0.0) )
3115  return SCIP_OKAY;
3116 
3117  if( !SCIPisInfinity(scip, -lhs) )
3118  lhs -= constant;
3119  if( !SCIPisInfinity(scip, rhs) )
3120  rhs -= constant;
3121  }
3122 
3123  /* vbdvar should be a non-fixed binary variable */
3124  assert(SCIPvarIsIntegral(vbdvar));
3125  assert(SCIPisZero(scip, SCIPvarGetLbGlobal(vbdvar)));
3126  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(vbdvar), 1.0));
3127 
3128  SCIPdebugMessage("-> %g <= <%s> + %g*<%s> <= %g\n", lhs, SCIPvarGetName(var), vbdcoef, SCIPvarGetName(vbdvar), rhs);
3129 
3130  if( addcons && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
3131  {
3132  SCIP_CONS* vbdcons;
3133  char name[SCIP_MAXSTRLEN];
3134 
3135  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_vbnd", SCIPconsGetName(cons));
3136 
3137  SCIP_CALL( SCIPcreateConsVarbound(scip, &vbdcons, name, var, vbdvar, vbdcoef, lhs, rhs,
3139  SCIP_CALL( SCIPaddCons(scip, vbdcons) );
3140  SCIP_CALL( SCIPreleaseCons(scip, &vbdcons) );
3141 
3142  ++*naddconss;
3143 
3144  return SCIP_OKAY;
3145  }
3146 
3147 
3148  if( !SCIPisInfinity(scip, -lhs) )
3149  {
3150  SCIP_CALL( SCIPaddVarVlb(scip, var, vbdvar, -vbdcoef, lhs, infeas, &nbdchgs_local) );
3151  if( *infeas )
3152  return SCIP_OKAY;
3153  *nbdchgs += nbdchgs_local;
3154  }
3155 
3156  if( !SCIPisInfinity(scip, rhs) )
3157  {
3158  SCIP_CALL( SCIPaddVarVub(scip, var, vbdvar, -vbdcoef, rhs, infeas, &nbdchgs_local) );
3159  if( *infeas )
3160  return SCIP_OKAY;
3161  *nbdchgs += nbdchgs_local;
3162  }
3163 
3164  return SCIP_OKAY;
3165 }
3166 
3167 /** propagates varbounds of variables
3168  * Let f(x) = sign(x+offset)|x+offset|^n, f^{-1}(y) = sign(y)|y|^(1/n) - offset.
3169  * Thus, constraint is lhs <= f(x) + c*z <= rhs.
3170  *
3171  * Given a variable bound constraint x <= a*y + b with y a binary variable, one obtains
3172  * y = 0 -> f(x) <= f(b) -> lhs <= f(b) + c*z
3173  * y = 1 -> f(x) <= f(a+b) -> lhs <= f(a+b) + c*z
3174  * => lhs <= f(b) + y * (f(a+b)-f(b)) + c*z
3175  *
3176  * Given a variable bound constraint x >= a*y + b with y a binary variable, one obtains analogously
3177  * f(b) + y * (f(a+b)-f(b)) + c*z <= rhs
3178  *
3179  * Given a variable bound constraint c*z <= a*y + b with y a binary variable, one obtains
3180  * y = 0 -> lhs <= f(x) + b -> x >= f^{-1}(lhs - b)
3181  * y = 1 -> lhs <= f(x) + a+b -> x >= f^{-1}(lhs - (a+b))
3182  * => x >= f^{-1}(lhs - b) + y * (f^{-1}(lhs - (a+b)) - f^{-1}(lhs - b))
3183  *
3184  * Given a variable bound constraint c*z >= a*y + b with y a binary variable, one obtains analogously
3185  * x <= f^{-1}(rhs - b) + y * (f^{-1}(rhs - (a+b)) - f^{-1}(rhs - b))
3186  */
3187 static
3189  SCIP* scip, /**< SCIP data structure */
3190  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3191  SCIP_CONS* cons, /**< absolute power constraint */
3192  SCIP_Bool* infeas, /**< pointer to store whether an infeasibility was detected */
3193  int* nbdchgs, /**< pointer where to add number of performed bound changes */
3194  int* naddconss /**< pointer where to add number of added constraints */
3195  )
3196 {
3197  SCIP_CONSHDLRDATA* conshdlrdata;
3198  SCIP_CONSDATA* consdata;
3199  SCIP_VAR* y;
3200  SCIP_Real a;
3201  SCIP_Real b;
3202  SCIP_Real fb;
3203  SCIP_Real fab;
3204  SCIP_Real vbcoef;
3205  SCIP_Real vbconst;
3206  int i;
3207 
3208  assert(scip != NULL);
3209  assert(conshdlr != NULL);
3210  assert(cons != NULL);
3211  assert(infeas != NULL);
3212  assert(nbdchgs != NULL);
3213  assert(naddconss != NULL);
3214 
3215  *infeas = FALSE;
3216 
3217  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3218  assert(conshdlrdata != NULL);
3219 
3220  consdata = SCIPconsGetData(cons);
3221  assert(consdata != NULL);
3222  assert(consdata->z != NULL);
3223 
3224  /* don't do anything if it looks like we have numerical troubles */
3225  if( SCIPisZero(scip, consdata->zcoef) )
3226  return SCIP_OKAY;
3227 
3228  if( !SCIPisInfinity(scip, -consdata->lhs) )
3229  {
3230  /* propagate varbounds x <= a*y+b onto z
3231  * lhs <= f(b) + y * (f(a+b)-f(b)) + c*z
3232  * -> c*z >= lhs-f(b) + y * (f(b)-f(a+b))
3233  */
3234  for( i = 0; i < SCIPvarGetNVubs(consdata->x); ++i )
3235  {
3236  y = SCIPvarGetVubVars(consdata->x)[i];
3237  a = SCIPvarGetVubCoefs(consdata->x)[i];
3238  b = SCIPvarGetVubConstants(consdata->x)[i];
3239 
3240  /* skip variable bound if y is not integer or its valid values are not {0,1}
3241  * @todo extend to arbitrary integer variables
3242  */
3243  if( !SCIPvarIsBinary(y) || SCIPvarGetLbGlobal(y) > 0.5 || SCIPvarGetUbGlobal(y) < 0.5 )
3244  continue;
3245 
3246  /* skip variable bound if coefficient is very small */
3247  if( SCIPisFeasZero(scip, consdata->power(a, consdata->exponent)) )
3248  continue;
3249 
3250  SCIPdebugMessage("propagate variable bound <%s> <= %g*<%s> + %g\n", SCIPvarGetName(consdata->x), a, SCIPvarGetName(y), b);
3251 
3252  fb = SIGN( b + consdata->xoffset) * consdata->power( b + consdata->xoffset, consdata->exponent); /* f( b) = sign( b) | b|^n */
3253  fab = SIGN(a+b + consdata->xoffset) * consdata->power(a+b + consdata->xoffset, consdata->exponent); /* f(a+b) = sign(a+b) |a+b|^n */
3254 
3255  vbcoef = (fb - fab) / consdata->zcoef;
3256  vbconst = (consdata->lhs - fb) / consdata->zcoef;
3257 
3258  if( consdata->zcoef > 0.0 )
3259  {
3260  /* add varbound z >= (lhs-f(b))/c + y * (f(b)-f(a+b))/c */
3261  SCIP_CALL( addVarbound(scip, cons, conshdlrdata->addvarboundcons, consdata->z, y, -vbcoef, vbconst, SCIPinfinity(scip), infeas, nbdchgs, naddconss) );
3262  }
3263  else
3264  {
3265  /* add varbound z <= (lhs-f(b))/c + y * (f(b)-f(a+b))/c */
3266  SCIP_CALL( addVarbound(scip, cons, conshdlrdata->addvarboundcons, consdata->z, y, -vbcoef, -SCIPinfinity(scip), vbconst, infeas, nbdchgs, naddconss) );
3267  }
3268  if( *infeas )
3269  return SCIP_OKAY;
3270  }
3271  }
3272 
3273  /* propagate varbounds x >= a*y+b onto z
3274  * f(b) + y * (f(a+b)-f(b)) + c*z <= rhs
3275  * -> c*z <= rhs-f(b) + y * (f(b)-f(a+b))
3276  */
3277  if( !SCIPisInfinity(scip, consdata->rhs) )
3278  {
3279  for( i = 0; i < SCIPvarGetNVlbs(consdata->x); ++i )
3280  {
3281  y = SCIPvarGetVlbVars(consdata->x)[i];
3282  a = SCIPvarGetVlbCoefs(consdata->x)[i];
3283  b = SCIPvarGetVlbConstants(consdata->x)[i];
3284 
3285  /* skip variable bound if y is not integer or its valid values are not {0,1}
3286  * @todo extend to arbitrary integer variables
3287  */
3288  if( !SCIPvarIsBinary(y) || SCIPvarGetLbGlobal(y) > 0.5 || SCIPvarGetUbGlobal(y) < 0.5 )
3289  continue;
3290 
3291  /* skip variable bound if coefficient is very small */
3292  if( SCIPisFeasZero(scip, consdata->power(a, consdata->exponent)) )
3293  continue;
3294 
3295  SCIPdebugMessage("propagate variable bound <%s> >= %g*<%s> + %g\n", SCIPvarGetName(consdata->x), a, SCIPvarGetName(y), b);
3296 
3297  fb = SIGN( b + consdata->xoffset) * consdata->power( b + consdata->xoffset, consdata->exponent); /* f( b) = sign( b) | b|^n */
3298  fab = SIGN(a+b + consdata->xoffset) * consdata->power(a+b + consdata->xoffset, consdata->exponent); /* f(a+b) = sign(a+b) |a+b|^n */
3299 
3300  vbcoef = (fb - fab) / consdata->zcoef;
3301  vbconst = (consdata->rhs - fb) / consdata->zcoef;
3302 
3303  if( consdata->zcoef > 0.0 )
3304  {
3305  /* add varbound z <= (rhs-f(b))/c + y * (f(b)-f(a+b))/c */
3306  SCIP_CALL( addVarbound(scip, cons, conshdlrdata->addvarboundcons, consdata->z, y, -vbcoef, -SCIPinfinity(scip), vbconst, infeas, nbdchgs, naddconss) );
3307  }
3308  else
3309  {
3310  /* add varbound z >= (rhs-f(b))/c + y * (f(b)-f(a+b))/c */
3311  SCIP_CALL( addVarbound(scip, cons, conshdlrdata->addvarboundcons, consdata->z, y, -vbcoef, vbconst, SCIPinfinity(scip), infeas, nbdchgs, naddconss) );
3312  }
3313  if( *infeas )
3314  return SCIP_OKAY;
3315  }
3316  }
3317 
3318  /* propagate variable upper bounds on z onto x
3319  * c*z <= a*y+b -> x >= f^{-1}(lhs - b) + y * (f^{-1}(lhs - (a+b)) - f^{-1}(lhs - b))
3320  * c*z >= a*y+b -> x <= f^{-1}(rhs - b) + y * (f^{-1}(rhs - (a+b)) - f^{-1}(rhs - b))
3321  */
3322  if( (consdata->zcoef > 0.0 && !SCIPisInfinity(scip, -consdata->lhs)) ||
3323  ( consdata->zcoef < 0.0 && !SCIPisInfinity(scip, consdata->rhs)) )
3324  for( i = 0; i < SCIPvarGetNVubs(consdata->z); ++i )
3325  {
3326  y = SCIPvarGetVubVars(consdata->z)[i];
3327  a = SCIPvarGetVubCoefs(consdata->z)[i] * consdata->zcoef;
3328  b = SCIPvarGetVubConstants(consdata->z)[i] * consdata->zcoef;
3329 
3330  SCIPdebugMessage("propagate variable bound %g*<%s> %c= %g*<%s> + %g\n", consdata->zcoef, SCIPvarGetName(consdata->z), consdata->zcoef > 0 ? '<' : '>', a, SCIPvarGetName(y), b);
3331 
3332  /* skip variable bound if y is not integer or its valid values are not {0,1}
3333  * @todo extend to arbitrary integer variables
3334  */
3335  if( !SCIPvarIsBinary(y) || SCIPvarGetLbGlobal(y) > 0.5 || SCIPvarGetUbGlobal(y) < 0.5 )
3336  continue;
3337 
3338  if( consdata->zcoef > 0.0 )
3339  {
3340  fb = consdata->lhs - b;
3341  fb = SIGN(fb) * pow(ABS(fb), 1.0/consdata->exponent);
3342  fab = consdata->lhs - (a+b);
3343  fab = SIGN(fab) * pow(ABS(fab), 1.0/consdata->exponent);
3344  SCIP_CALL( addVarbound(scip, cons, conshdlrdata->addvarboundcons, consdata->x, y, fb - fab, fb - consdata->xoffset, SCIPinfinity(scip), infeas, nbdchgs, naddconss) );
3345  }
3346  else
3347  {
3348  fb = consdata->rhs - b;
3349  fb = SIGN(fb) * pow(ABS(fb), 1.0/consdata->exponent);
3350  fab = consdata->rhs - (a+b);
3351  fab = SIGN(fab) * pow(ABS(fab), 1.0/consdata->exponent);
3352  SCIP_CALL( addVarbound(scip, cons, conshdlrdata->addvarboundcons, consdata->x, y, fb - fab, -SCIPinfinity(scip), fb - consdata->xoffset, infeas, nbdchgs, naddconss) );
3353  }
3354  if( *infeas )
3355  return SCIP_OKAY;
3356  }
3357 
3358  /* propagate variable lower bounds on z onto x
3359  * c*z <= a*y+b -> x >= f^{-1}(lhs - b) + y * (f^{-1}(lhs - (a+b)) - f^{-1}(lhs - b))
3360  * c*z >= a*y+b -> x <= f^{-1}(rhs - b) + y * (f^{-1}(rhs - (a+b)) - f^{-1}(rhs - b))
3361  */
3362  if( (consdata->zcoef < 0.0 && !SCIPisInfinity(scip, -consdata->lhs)) ||
3363  ( consdata->zcoef > 0.0 && !SCIPisInfinity(scip, consdata->rhs)) )
3364  for( i = 0; i < SCIPvarGetNVlbs(consdata->z); ++i )
3365  {
3366  y = SCIPvarGetVlbVars(consdata->z)[i];
3367  a = SCIPvarGetVlbCoefs(consdata->z)[i] * consdata->zcoef;
3368  b = SCIPvarGetVlbConstants(consdata->z)[i] * consdata->zcoef;
3369 
3370  SCIPdebugMessage("propagate variable bound %g*<%s> %c= %g*<%s> + %g\n", consdata->zcoef, SCIPvarGetName(consdata->z), consdata->zcoef > 0 ? '>' : '<', a, SCIPvarGetName(y), b);
3371 
3372  /* skip variable bound if y is not integer or its valid values are not {0,1}
3373  * @todo extend to arbitrary integer variables
3374  */
3375  if( !SCIPvarIsBinary(y) || SCIPvarGetLbGlobal(y) > 0.5 || SCIPvarGetUbGlobal(y) < 0.5 )
3376  continue;
3377 
3378  if( consdata->zcoef > 0.0 )
3379  {
3380  fb = consdata->rhs - b;
3381  fb = SIGN(fb) * pow(ABS(fb), 1.0/consdata->exponent);
3382  fab = consdata->rhs - (a+b);
3383  fab = SIGN(fab) * pow(ABS(fab), 1.0/consdata->exponent);
3384  SCIP_CALL( addVarbound(scip, cons, conshdlrdata->addvarboundcons, consdata->x, y, fb - fab, -SCIPinfinity(scip), fb - consdata->xoffset, infeas, nbdchgs, naddconss) );
3385  }
3386  else
3387  {
3388  fb = consdata->lhs - b;
3389  fb = SIGN(fb) * pow(ABS(fb), 1.0/consdata->exponent);
3390  fab = consdata->lhs - (a+b);
3391  fab = SIGN(fab) * pow(ABS(fab), 1.0/consdata->exponent);
3392  SCIP_CALL( addVarbound(scip, cons, conshdlrdata->addvarboundcons, consdata->x, y, fb - fab, fb - consdata->xoffset, SCIPinfinity(scip), infeas, nbdchgs, naddconss) );
3393  }
3394  if( *infeas )
3395  return SCIP_OKAY;
3396  }
3397 
3398  return SCIP_OKAY;
3399 }
3400 
3401 /** computes linear underestimator for (x+offset)^n + c*z <= rhs by linearization in x
3402  *
3403  * the generated cut is xmul * n * (refpoint+offset)^(n-1) * x + c*z <= rhs + ((n-1)*refpoint-offset) * (refpoint+offset)^(n-1)
3404  */
3405 static
3407  SCIP* scip, /**< SCIP data structure */
3408  SCIP_ROW** row, /**< buffer to store row */
3409  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3410  SCIP_Real refpoint, /**< base point for linearization */
3411  SCIP_Real exponent, /**< exponent n in sign(x)abs(x)^n */
3412  SCIP_Real xoffset, /**< offset of x */
3413  SCIP_Real xmult, /**< multiplier for coefficient of x */
3414  SCIP_Real zcoef, /**< coefficient of z */
3415  SCIP_Real rhs, /**< right hand side */
3416  SCIP_VAR* x, /**< variable x */
3417  SCIP_VAR* z, /**< variable z */
3418  SCIP_Bool islocal /**< whether the cut is valid only locally */
3419  )
3420 {
3421  char rowname[SCIP_MAXSTRLEN];
3422  SCIP_CONSHDLRDATA* conshdlrdata;
3423  SCIP_Real tmp;
3424 
3425  assert(scip != NULL);
3426  assert(!SCIPisFeasNegative(scip, refpoint+xoffset));
3427  assert(!SCIPisInfinity(scip, refpoint));
3428 
3429  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3430  assert(conshdlrdata != NULL);
3431 
3432  if( refpoint < -xoffset )
3433  refpoint = -xoffset;
3434 
3435  tmp = exponent == 2.0 ? refpoint+xoffset : pow(refpoint+xoffset, exponent-1);
3436  if( SCIPisInfinity(scip, tmp) )
3437  {
3438  SCIPdebugMessage("skip linearization cut because (refpoint+offset)^(exponent-1) > infinity\n");
3439  *row = NULL;
3440  return SCIP_OKAY;
3441  }
3442 
3443  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "signpowlinearizecut_%u", ++(conshdlrdata->ncuts));
3444 
3445  SCIP_CALL( SCIPcreateEmptyRowCons(scip, row, conshdlr, rowname, -SCIPinfinity(scip), SCIPinfinity(scip), islocal,
3446  FALSE /* modifiable */, TRUE /* removable */ ) );
3447 
3448  SCIP_CALL( SCIPaddVarToRow(scip, *row, x, xmult*exponent*tmp) );
3449  SCIP_CALL( SCIPaddVarToRow(scip, *row, z, zcoef) );
3450  SCIP_CALL( SCIPchgRowRhs(scip, *row, rhs + ((exponent-1)*refpoint-xoffset)*tmp) );
3451 
3452  return SCIP_OKAY;
3453 }
3454 
3455 /** computes linear underestimator for (x+xoffset)^n + c*z <= rhs by linearization in x
3456  *
3457  * the generated cut is xmul * n * (refpoint+offset)^(n-1) * x + c*z <= rhs + ((n-1)*refpoint-offset) * (refpoint+offset)^(n-1)
3458  * where refpoint is computed by projecting (xref, zref) onto the graph of (x+offset)^n w.r.t. euclidean norm
3459  *
3460  * Thus, the projection is computed by minimizing 1/2(x-xref)^2 + 1/2(((x+offset)^n-rhs)/(-c) - zref)^2.
3461  * I.e., we aim to find a root of
3462  * g(x) = x - xref + n/c (x+offset)^(n-1) (zref - rhs/c) + n/c^2 (x+offset)^(2n-1)
3463  * We do this numerically by executing up to five newton iterations. It is
3464  * g'(x) = 1 + n(n-1)/c (x+offset)^(n-2) (zref - rhs/c) + n(2n-1)/c^2 (x+offset)^(2n-2)
3465  */
3466 static
3468  SCIP* scip, /**< SCIP data structure */
3469  SCIP_ROW** row, /**< buffer to store row */
3470  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3471  SCIP_Real xref, /**< reference point for x */
3472  SCIP_Real zref, /**< reference point for z */
3473  SCIP_Real xmin, /**< minimal value x is allowed to take */
3474  SCIP_Real exponent, /**< exponent n in sign(x+offset)abs(x+offset)^n */
3475  SCIP_Real xoffset, /**< offset of x */
3476  SCIP_Real xmult, /**< multiplier for coefficient of x */
3477  SCIP_Real zcoef, /**< coefficient of z */
3478  SCIP_Real rhs, /**< right hand side */
3479  SCIP_VAR* x, /**< variable x */
3480  SCIP_VAR* z, /**< variable z */
3481  SCIP_Bool islocal /**< whether the cut is valid only locally */
3482  )
3483 {
3484  SCIP_Real tmp;
3485  SCIP_Real xproj;
3486  SCIP_Real gval;
3487  SCIP_Real gderiv;
3488  int iter;
3489 
3490  assert(scip != NULL);
3491  assert(!SCIPisFeasNegative(scip, xref+xoffset));
3492  assert(!SCIPisInfinity(scip, xref));
3493 
3494  if( xref < xmin )
3495  xref = xmin;
3496 
3497  xproj = xref;
3498  iter = 0;
3499  if( exponent == 2.0 )
3500  do
3501  {
3502  tmp = (xproj+xoffset) * (xproj+xoffset);
3503  gval = xproj - xref + 2*(xproj+xoffset) / zcoef * ((tmp-rhs)/zcoef + zref);
3504  if( !SCIPisFeasPositive(scip, ABS(gval)) )
3505  break;
3506 
3507  gderiv = 1 + 6 * tmp / (zcoef*zcoef) + 2 / zcoef * (zref - rhs/zcoef);
3508  xproj -= gval / gderiv;
3509 
3510  }
3511  while( ++iter <= 5 );
3512  else
3513  do
3514  {
3515  tmp = pow(xproj + xoffset, exponent-1);
3516  gval = xproj - xref + exponent / zcoef * (pow(xproj+xoffset, 2*exponent-1)/zcoef + tmp * (zref-rhs/zcoef));
3517  if( !SCIPisFeasPositive(scip, ABS(gval)) )
3518  break;
3519 
3520  gderiv = 1 + exponent / zcoef * ( (2*exponent-1)*tmp*tmp/zcoef + (exponent-1)*pow(xproj+xoffset, exponent-2) * (zref-rhs/zcoef) );
3521  xproj -= gval / gderiv;
3522 
3523  }
3524  while( ++iter <= 5 );
3525 
3526  if( xproj < xmin )
3527  xproj = xmin;
3528 
3529  SCIP_CALL( generateLinearizationCut(scip, row, conshdlr, xproj, exponent, xoffset, xmult, zcoef, rhs, x, z, islocal) );
3530 
3531  return SCIP_OKAY;
3532 }
3533 
3534 /** computes secant underestimator for sign(x+offset)abs(x+offset)^n + c*z <= rhs
3535  *
3536  * the generated cut is slope*xmult*x + c*z <= rhs + (-xlb-offset)^n + slope*xlb,
3537  * where slope = (sign(xub+offset)*abs(xub+offset)^n + (-xlb-offset)^n) / (xub - xlb).
3538  *
3539  * the cut is not generated if the given solution (or the LP solution) would not be cutoff
3540  */
3541 static
3543  SCIP* scip, /**< SCIP data structure */
3544  SCIP_ROW** row, /**< buffer to store row */
3545  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3546  SCIP_SOL* sol, /**< point we want to cut off, or NULL for LP solution */
3547  SCIP_Real xlb, /**< lower bound of x */
3548  SCIP_Real xub, /**< upper bound of x */
3549  SCIP_Real exponent, /**< exponent n in sign(x+offset)abs(x+offset)^n */
3550  SCIP_Real xoffset, /**< offset of x */
3551  DECL_MYPOW ((*mypow)), /**< function to use for computing power */
3552  SCIP_Real xmult, /**< multiplier for coefficient of x */
3553  SCIP_Real zcoef, /**< coefficient of z */
3554  SCIP_Real rhs, /**< right hand side */
3555  SCIP_VAR* x, /**< variable x */
3556  SCIP_VAR* z /**< variable z */
3557  )
3558 {
3559  char rowname[SCIP_MAXSTRLEN];
3560  SCIP_CONSHDLRDATA* conshdlrdata;
3561  SCIP_Real slope, tmp, val;
3562 
3563  assert(scip != NULL);
3564  assert(SCIPisLE(scip, xlb, xub));
3565  assert(!SCIPisPositive(scip, xlb+xoffset));
3566 
3567  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3568  assert(conshdlrdata != NULL);
3569 
3570  /* ignore constraints with fixed x (should be removed soon) */
3571  if( SCIPisRelEQ(scip, xlb, xub) )
3572  return SCIP_OKAY;
3573 
3574  if( xlb > -xoffset )
3575  xlb = -xoffset;
3576 
3577  tmp = mypow(-xlb-xoffset, exponent);
3578  slope = SIGN(xub+xoffset) * mypow(ABS(xub+xoffset), exponent) + tmp;
3579  slope /= xub - xlb;
3580 
3581  /* check if cut would violated solution, check that slope is not above value of infinity */
3582  val = -tmp + slope * (xmult * SCIPgetSolVal(scip, sol, x) - xlb) + zcoef * SCIPgetSolVal(scip, sol, z) - rhs;
3583  if( !SCIPisFeasPositive(scip, val) || SCIPisInfinity(scip, REALABS(slope)) )
3584  {
3585  *row = NULL;
3586  return SCIP_OKAY;
3587  }
3588 
3589  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "signpowsecantcut_%u", ++(conshdlrdata->nsecantcuts));
3590 
3591  SCIP_CALL( SCIPcreateEmptyRowCons(scip, row, conshdlr, rowname, -SCIPinfinity(scip), SCIPinfinity(scip),
3592  SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) > 0 /* local */, FALSE /* modifiable */, TRUE /* removable */ ) );
3593  SCIP_CALL( SCIPaddVarToRow(scip, *row, x, xmult*slope) );
3594  SCIP_CALL( SCIPaddVarToRow(scip, *row, z, zcoef) );
3595  SCIP_CALL( SCIPchgRowRhs(scip, *row, rhs + tmp + slope*xlb) );
3596 
3597  return SCIP_OKAY;
3598 }
3599 
3600 /** computes secant underestimator for sign(x+xoffset)abs(x+xoffset)^n + c*z <= rhs
3601  *
3602  * The generated cut is slope*xmult*x + c*z <= rhs + (-xlb-xoffset)^n + slope*xlb,
3603  * where slope = (sign(xub+xoffset)*abs(xub+xoffset)^n + (-xlb-xoffset)^n) / (xub - xlb).
3604  */
3605 static
3607  SCIP* scip, /**< SCIP data structure */
3608  SCIP_ROW** row, /**< buffer to store row */
3609  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3610  SCIP_Real xlb, /**< lower bound of x */
3611  SCIP_Real xub, /**< upper bound of x */
3612  SCIP_Real exponent, /**< exponent n in sign(x)abs(x)^n */
3613  SCIP_Real xoffset, /**< offset of x */
3614  DECL_MYPOW ((*mypow)), /**< function to use for computing power */
3615  SCIP_Real xmult, /**< multiplier for coefficient of x */
3616  SCIP_Real zcoef, /**< coefficient of z */
3617  SCIP_Real rhs, /**< right hand side */
3618  SCIP_VAR* x, /**< variable x */
3619  SCIP_VAR* z /**< variable z */
3620  )
3621 {
3622  SCIP_Real slope, tmp;
3623 
3624  assert(scip != NULL);
3625  assert(SCIPisLE(scip, xlb, xub));
3626  assert(!SCIPisPositive(scip, xlb + xoffset));
3627 
3628  /* ignore constraints with fixed x (should be removed soon) */
3629  if( SCIPisRelEQ(scip, xlb, xub) )
3630  return SCIP_OKAY;
3631 
3632  if( xlb > -xoffset )
3633  xlb = -xoffset;
3634 
3635  tmp = mypow(-xlb-xoffset, exponent);
3636  slope = SIGN(xub+xoffset) * mypow(ABS(xub+xoffset), exponent) + tmp;
3637  slope /= xub - xlb;
3638 
3639  if( SCIPisInfinity(scip, REALABS(slope)) )
3640  return SCIP_OKAY;
3641 
3642  SCIP_CALL( SCIPcreateEmptyRowCons(scip, row, conshdlr, "signpowcut", -SCIPinfinity(scip), SCIPinfinity(scip),
3643  SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) > 0 /* local */, FALSE /* modifiable */, TRUE /* removable */ ) );
3644  SCIP_CALL( SCIPaddVarToRow(scip, *row, x, xmult*slope) );
3645  SCIP_CALL( SCIPaddVarToRow(scip, *row, z, zcoef) );
3646  SCIP_CALL( SCIPchgRowRhs(scip, *row, rhs + tmp + slope*xlb) );
3647 
3648  return SCIP_OKAY;
3649 }
3650 
3651 /** generates a cut
3652  * based on Liberti and Pantelides, Convex Envelopes of Monomials of Odd Degree, J. Global Optimization 25, 157-168, 2003, and previous publications
3653  */
3654 static
3656  SCIP* scip, /**< SCIP data structure */
3657  SCIP_CONS* cons, /**< constraint */
3658  SCIP_SOL* sol, /**< solution to separate, or NULL if LP solution should be used */
3659  SCIP_ROW** row, /**< storage for cut */
3660  SCIP_Bool onlyinbounds /**< whether linearization is allowed only in variable bounds */
3661  )
3662 {
3663  SCIP_CONSHDLRDATA* conshdlrdata;
3664  SCIP_CONSDATA* consdata;
3665  SCIP_SIDETYPE violside;
3666  SCIP_Real c;
3667  SCIP_Real xlb;
3668  SCIP_Real xglb;
3669  SCIP_Real xub;
3670  SCIP_Real xval;
3671  SCIP_Real xoffset;
3672  SCIP_Real xmult;
3673  SCIP_Real zcoef;
3674  SCIP_Real rhs;
3675 
3676  assert(scip != NULL);
3677  assert(cons != NULL);
3678  assert(row != NULL);
3679 
3680  conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
3681  assert(conshdlrdata != NULL);
3682 
3683  consdata = SCIPconsGetData(cons);
3684  assert(consdata != NULL);
3685 
3686  assert(SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) || SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)));
3687 
3688  violside = SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) ? SCIP_SIDETYPE_LEFT : SCIP_SIDETYPE_RIGHT;
3689  *row = NULL;
3690 
3691  SCIPdebugMessage("generate cut for constraint <%s> with violated side %d\n", SCIPconsGetName(cons), violside);
3692  SCIPdebugPrintCons(scip, cons, NULL);
3693  SCIPdebugMessage("xlb = %g xub = %g xval = %g\n", SCIPvarGetLbLocal(consdata->x), SCIPvarGetUbLocal(consdata->x), SCIPgetSolVal(scip, sol, consdata->x));
3694 
3695  if( violside == SCIP_SIDETYPE_RIGHT )
3696  {
3697  xglb = SCIPvarGetLbGlobal(consdata->x);
3698  xlb = SCIPvarGetLbLocal(consdata->x);
3699  xub = SCIPvarGetUbLocal(consdata->x);
3700  xval = SCIPgetSolVal(scip, sol, consdata->x);
3701  xoffset = consdata->xoffset;
3702  xmult = 1.0;
3703  zcoef = consdata->zcoef;
3704  rhs = consdata->rhs;
3705  }
3706  else
3707  {
3708  xglb = -SCIPvarGetUbGlobal(consdata->x);
3709  xlb = -SCIPvarGetUbLocal(consdata->x);
3710  xub = -SCIPvarGetLbLocal(consdata->x);
3711  xval = -SCIPgetSolVal(scip, sol, consdata->x);
3712  xoffset = -consdata->xoffset;
3713  xmult = -1.0;
3714  zcoef = -consdata->zcoef;
3715  rhs = -consdata->lhs;
3716  }
3717 
3718  if( SCIPisInfinity(scip, REALABS(xval)) )
3719  {
3720  SCIPdebugMessage("skip separation since x is at infinity\n");
3721  return SCIP_OKAY;
3722  }
3723 
3724  if( !SCIPisNegative(scip, xlb+xoffset) )
3725  {
3726  /* [xlb, xub] completely in positive orthant -> function is convex on whole domain */
3727  SCIP_Bool islocal;
3728 
3729  islocal = (!SCIPconsIsGlobal(cons) || SCIPisNegative(scip, xglb+xoffset)) && SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) > 0;
3730  if( conshdlrdata->projectrefpoint && !onlyinbounds )
3731  {
3732  SCIP_CALL( generateLinearizationCutProject(scip, row, SCIPconsGetHdlr(cons), xval, SCIPgetSolVal(scip, sol, consdata->z), -xoffset, consdata->exponent,
3733  xoffset, xmult, zcoef, rhs, consdata->x, consdata->z, islocal) );
3734  }
3735  else if( !onlyinbounds )
3736  {
3737  SCIP_CALL( generateLinearizationCut(scip, row, SCIPconsGetHdlr(cons), xval, consdata->exponent, xoffset, xmult, zcoef, rhs,
3738  consdata->x, consdata->z, islocal) );
3739  }
3740  else
3741  {
3742  SCIP_CALL( generateLinearizationCut(scip, row, SCIPconsGetHdlr(cons), 2.0*xval > xlb + xub ? xub : xlb, consdata->exponent, xoffset, xmult, zcoef, rhs,
3743  consdata->x, consdata->z, islocal) );
3744  }
3745  }
3746  else if( !SCIPisPositive(scip, xub+xoffset) )
3747  {
3748  /* [xlb, xub] completely in negative orthant -> function is concave on whole domain */
3749  if( SCIPisInfinity(scip, -xlb) )
3750  return SCIP_OKAY;
3751  SCIP_CALL( generateSecantCut(scip, row, SCIPconsGetHdlr(cons), sol, xlb, xub, consdata->exponent, xoffset, consdata->power, xmult, zcoef, rhs, consdata->x, consdata->z) );
3752  }
3753  else if( (c = - consdata->root * (xlb+xoffset) - xoffset) > xub )
3754  {
3755  /* c is right of xub -> use secant */
3756  if( SCIPisInfinity(scip, -xlb) || SCIPisInfinity(scip, xub) )
3757  return SCIP_OKAY;
3758  SCIP_CALL( generateSecantCut(scip, row, SCIPconsGetHdlr(cons), sol, xlb, xub, consdata->exponent, xoffset, consdata->power, xmult, zcoef, rhs, consdata->x, consdata->z) );
3759  }
3760  else if( xval >= c )
3761  {
3762  /* xval is right of c -> use linearization */
3763  if( conshdlrdata->projectrefpoint && !onlyinbounds )
3764  SCIP_CALL( generateLinearizationCutProject(scip, row, SCIPconsGetHdlr(cons), xval, SCIPgetSolVal(scip, sol, consdata->z), c, consdata->exponent,
3765  xoffset, xmult, zcoef, rhs, consdata->x, consdata->z, SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) > 0) );
3766  else if( !onlyinbounds )
3767  SCIP_CALL( generateLinearizationCut(scip, row, SCIPconsGetHdlr(cons), xval, consdata->exponent, xoffset, xmult, zcoef, rhs,
3768  consdata->x, consdata->z, xval+xoffset < - consdata->root * (xglb+xoffset) && SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) > 0) );
3769  else
3770  SCIP_CALL( generateLinearizationCut(scip, row, SCIPconsGetHdlr(cons), xub, consdata->exponent, xoffset, xmult, zcoef, rhs,
3771  consdata->x, consdata->z, xval+xoffset < - consdata->root * (xglb+xoffset) && SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) > 0) );
3772  }
3773  else
3774  {
3775  /* xval between xlb and c -> use secant */
3776  if( SCIPisInfinity(scip, -xlb) || SCIPisInfinity(scip, c) )
3777  return SCIP_OKAY;
3778  SCIP_CALL( generateSecantCut(scip, row, SCIPconsGetHdlr(cons), sol, xlb, c, consdata->exponent, xoffset, consdata->power, xmult, zcoef, rhs, consdata->x, consdata->z) );
3779  }
3780 
3781  /* check numerics */
3782  if( *row != NULL )
3783  {
3784  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *row, NULL) ) );
3785 
3786  /* check range of coefficients */
3787  SCIPdebugMessage(" -> found cut rhs=%f, min=%f, max=%f range=%g\n",
3788  SCIProwGetRhs(*row),
3789  SCIPgetRowMinCoef(scip, *row), SCIPgetRowMaxCoef(scip, *row),
3790  SCIPgetRowMaxCoef(scip, *row)/SCIPgetRowMinCoef(scip, *row));
3791 
3792  if( SCIPisInfinity(scip, REALABS(SCIProwGetRhs(*row))) )
3793  {
3794  SCIPdebugMessage("skip cut for constraint <%s> because of very large right hand side: %g\n", SCIPconsGetName(cons), SCIProwGetRhs(*row));
3795  SCIP_CALL( SCIPreleaseRow(scip, row) );
3796  return SCIP_OKAY;
3797  }
3798 
3799  if( SCIPgetRowMaxCoef(scip, *row) / SCIPgetRowMinCoef(scip, *row) >= conshdlrdata->cutmaxrange )
3800  {
3801  SCIPdebugMessage("skip cut for constraint <%s> because of very large range: %g\n", SCIPconsGetName(cons), SCIPgetRowMaxCoef(scip, *row)/SCIPgetRowMinCoef(scip, *row));
3802  SCIP_CALL( SCIPreleaseRow(scip, row) );
3803  return SCIP_OKAY;
3804  }
3805  }
3806 
3807  return SCIP_OKAY;
3808 }
3809 
3810 /** tries to separate solution or LP solution by a linear cut
3811  * assumes that constraint violations have been computed
3812  */
3813 static
3815  SCIP* scip, /**< SCIP data structure */
3816  SCIP_CONSHDLR* conshdlr, /**< quadratic constraints handler */
3817  SCIP_CONS** conss, /**< constraints */
3818  int nconss, /**< number of constraints */
3819  int nusefulconss, /**< number of constraints that seem to be useful */
3820  SCIP_SOL* sol, /**< solution to separate, or NULL if LP solution should be used */
3821  SCIP_Real minefficacy, /**< minimal efficacy of a cut if it should be added to the LP */
3822  SCIP_Bool inenforcement, /**< whether we are in constraint enforcement */
3823  SCIP_Bool onlyinbounds, /**< whether linearization is allowed only in variable bounds */
3824  SCIP_Bool* success, /**< result of separation: separated point (TRUE) or not (FALSE) */
3825  SCIP_Bool* cutoff, /**< whether a cutoff has been detected */
3826  SCIP_Real* bestefficacy /**< buffer to store best efficacy of a cut that was added to the LP, if found; or NULL if not of interest */
3827  )
3828 {
3829  SCIP_CONSHDLRDATA* conshdlrdata;
3830  SCIP_CONSDATA* consdata;
3831  SCIP_Real efficacy;
3832  SCIP_Real feasibility;
3833  SCIP_Real norm;
3834  SCIP_Bool convex;
3835  int c;
3836  SCIP_ROW* row;
3837 
3838  assert(scip != NULL);
3839  assert(conshdlr != NULL);
3840  assert(conss != NULL || nconss == 0);
3841  assert(success != NULL);
3842  assert(cutoff != NULL);
3843 
3844  *success = FALSE;
3845  *cutoff = FALSE;
3846 
3847  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3848  assert(conshdlrdata != NULL);
3849 
3850  if( bestefficacy != NULL )
3851  *bestefficacy = 0.0;
3852 
3853  for( c = 0; c < nconss && ! (*cutoff); ++c )
3854  {
3855  assert(conss[c] != NULL); /*lint !e613*/
3856 
3857  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
3858  assert(consdata != NULL);
3859 
3860  if( SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) || SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
3861  {
3862  /* try to generate a cut */
3863  SCIP_CALL( generateCut(scip, conss[c], sol, &row, onlyinbounds) ); /*lint !e613*/
3864  if( row == NULL ) /* failed to generate cut */
3865  continue;
3866 
3867  /* check if we separate in convex area */
3868  if( SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
3869  {
3870  convex = !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->x))
3871  && (!SCIPisNegative(scip, SCIPvarGetLbLocal(consdata->x)+consdata->xoffset)
3872  || SCIPgetSolVal(scip, NULL, consdata->x)+consdata->xoffset >= -consdata->root*(SCIPvarGetLbLocal(consdata->x)+consdata->xoffset));
3873  }
3874  else
3875  {
3876  convex = !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->x))
3877  && (!SCIPisPositive(scip, SCIPvarGetUbLocal(consdata->x)+consdata->xoffset)
3878  || SCIPgetSolVal(scip, NULL, consdata->x)+consdata->xoffset <= -consdata->root*(SCIPvarGetUbLocal(consdata->x)+consdata->xoffset));
3879  }
3880 
3881  feasibility = SCIPgetRowSolFeasibility(scip, row, sol);
3882 
3883  switch( conshdlrdata->scaling )
3884  {
3885  case 'o' :
3886  efficacy = -feasibility;
3887  break;
3888 
3889  case 'g' :
3890  /* in difference to SCIPgetCutEfficacy, we scale by norm only if the norm is > 1.0 this avoid finding cuts
3891  * efficient which are only very slightly violated CPLEX does not seem to scale row coefficients up too
3892  * also we use infinity norm, since that seem to be the usual scaling strategy in LP solvers (equilibrium
3893  * scaling) */
3894  norm = SCIPgetRowMaxCoef(scip, row);
3895  efficacy = -feasibility / MAX(1.0, norm);
3896  break;
3897 
3898  case 's' :
3899  {
3900  SCIP_Real abslhs = REALABS(SCIProwGetLhs(row));
3901  SCIP_Real absrhs = REALABS(SCIProwGetRhs(row));
3902  SCIP_Real minval = MIN(abslhs, absrhs);
3903 
3904  efficacy = -feasibility / MAX(1.0, minval);
3905  break;
3906  }
3907 
3908  default:
3909  SCIPerrorMessage("Unknown scaling method '%c'.", conshdlrdata->scaling);
3910  SCIPABORT();
3911  return SCIP_INVALIDDATA; /*lint !e527*/
3912  }
3913 
3914  /* if cut is strong or it's weak but we are convex and desperate (speak, in enforcement), then add,
3915  * unless it corresponds to a bound change that is too weak (<eps) to be added
3916  */
3917  if( (efficacy > minefficacy || (inenforcement && convex && (SCIPgetRelaxFeastolFactor(scip) > 0.0 ? SCIPisPositive(scip, efficacy) : SCIPisFeasPositive(scip, efficacy)))) &&
3918  SCIPisCutApplicable(scip, row) )
3919  {
3920  SCIP_Bool infeasible;
3921 
3922  SCIP_CALL( SCIPaddCut(scip, sol, row, FALSE, &infeasible) );
3923  if ( infeasible )
3924  *cutoff = TRUE;
3925  else
3926  *success = TRUE;
3927  if( bestefficacy != NULL && efficacy > *bestefficacy )
3928  *bestefficacy = efficacy;
3929 
3930  /* notify indicator constraint handler about this cut */
3931  if( conshdlrdata->conshdlrindicator != NULL && !SCIProwIsLocal(row) )
3932  {
3933  SCIP_CALL( SCIPaddRowIndicator(scip, conshdlrdata->conshdlrindicator, row) );
3934  }
3935 
3936  /* mark row as not removable from LP for current node, if in enforcement */
3937  if( inenforcement && !conshdlrdata->enfocutsremovable )
3938  SCIPmarkRowNotRemovableLocal(scip, row);
3939  }
3940 
3941  SCIP_CALL( SCIPreleaseRow (scip, &row) );
3942  }
3943 
3944  /* enforce only useful constraints
3945  * others are only checked and enforced if we are still feasible or have not found a separating cut yet
3946  */
3947  if( c >= nusefulconss && *success )
3948  break;
3949  }
3950 
3951  return SCIP_OKAY;
3952 }
3953 
3954 /** adds linearizations cuts for convex constraints w.r.t. a given reference point to cutpool and sepastore
3955  * if separatedlpsol is not NULL, then a cut that separates the LP solution is added to the sepastore and is forced to enter the LP
3956  * if separatedlpsol is not NULL, but cut does not separate the LP solution, then it is added to the cutpool only
3957  * if separatedlpsol is NULL, then cut is added to cutpool only
3958  */
3959 static
3961  SCIP* scip, /**< SCIP data structure */
3962  SCIP_CONSHDLR* conshdlr, /**< quadratic constraints handler */
3963  SCIP_CONS** conss, /**< constraints */
3964  int nconss, /**< number of constraints */
3965  SCIP_SOL* ref, /**< reference point where to linearize, or NULL for LP solution */
3966  SCIP_Bool* separatedlpsol, /**< buffer to store whether a cut that separates the current LP solution was found and added to LP, or NULL if adding to cutpool only */
3967  SCIP_Real minefficacy /**< minimal efficacy of a cut when checking for separation of LP solution */
3968  )
3969 {
3970  SCIP_CONSDATA* consdata;
3971  SCIP_Bool addedtolp;
3972  SCIP_ROW* row;
3973  int c;
3974 
3975  assert(scip != NULL);
3976  assert(conshdlr != NULL);
3977  assert(conss != NULL || nconss == 0);
3978 
3979  if( separatedlpsol != NULL )
3980  *separatedlpsol = FALSE;
3981 
3982  for( c = 0; c < nconss; ++c )
3983  {
3984  assert(conss[c] != NULL); /*lint !e613*/
3985 
3986  if( SCIPconsIsLocal(conss[c]) ) /*lint !e613*/
3987  continue;
3988 
3989  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
3990  assert(consdata != NULL);
3991 
3992  if( !SCIPisGT(scip, SCIPvarGetUbGlobal(consdata->x), -consdata->xoffset) && !SCIPisInfinity(scip, -consdata->lhs) )
3993  {
3994  /* constraint function is concave for x+offset <= 0.0, so can linearize w.r.t. lhs */
3995  consdata->lhsviol = 1.0;
3996  consdata->rhsviol = 0.0;
3997  SCIP_CALL( generateCut(scip, conss[c], ref, &row, FALSE) ); /*lint !e613*/
3998  }
3999  else if( !SCIPisLT(scip, SCIPvarGetLbGlobal(consdata->x), -consdata->xoffset) && !SCIPisInfinity(scip, -consdata->rhs) )
4000  {
4001  /* constraint function is convex for x+offset >= 0.0, so can linearize w.r.t. rhs */
4002  consdata->lhsviol = 0.0;
4003  consdata->rhsviol = 1.0;
4004  SCIP_CALL( generateCut(scip, conss[c], ref, &row, FALSE) ); /*lint !e613*/
4005  }
4006  else
4007  {
4008  /* sign not fixed or nothing to linearize */
4009  continue;
4010  }
4011 
4012  if( row == NULL )
4013  continue;
4014 
4015  addedtolp = FALSE;
4016 
4017  assert(!SCIProwIsLocal(row));
4018 
4019  /* if caller wants, then check if cut separates LP solution and add to sepastore if so */
4020  if( separatedlpsol != NULL )
4021  {
4022  SCIP_CONSHDLRDATA* conshdlrdata;
4023  SCIP_Real efficacy;
4024  SCIP_Real norm;
4025 
4026  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4027  assert(conshdlrdata != NULL);
4028 
4029  efficacy = -SCIPgetRowLPFeasibility(scip, row);
4030  switch( conshdlrdata->scaling )
4031  {
4032  case 'o' :
4033  break;
4034 
4035  case 'g' :
4036  /* in difference to SCIPgetCutEfficacy, we scale by norm only if the norm is > 1.0 this avoid finding cuts
4037  * efficient which are only very slightly violated CPLEX does not seem to scale row coefficients up too
4038  * also we use infinity norm, since that seem to be the usual scaling strategy in LP solvers (equilibrium
4039  * scaling) */
4040  norm = SCIPgetRowMaxCoef(scip, row);
4041  efficacy /= MAX(1.0, norm);
4042  break;
4043 
4044  case 's' :
4045  {
4046  SCIP_Real abslhs = REALABS(SCIProwGetLhs(row));
4047  SCIP_Real absrhs = REALABS(SCIProwGetRhs(row));
4048  SCIP_Real minval = MIN(abslhs, absrhs);
4049 
4050  efficacy /= MAX(1.0, minval);
4051  break;
4052  }
4053 
4054  default:
4055  SCIPerrorMessage("Unknown scaling method '%c'.", conshdlrdata->scaling);
4056  SCIPABORT();
4057  return SCIP_INVALIDDATA; /*lint !e527*/
4058  }
4059 
4060  if( efficacy >= minefficacy )
4061  {
4062  SCIP_Bool infeasible;
4063 
4064  *separatedlpsol = TRUE;
4065  addedtolp = TRUE;
4066  SCIP_CALL( SCIPaddCut(scip, NULL, row, TRUE, &infeasible) );
4067  assert( ! infeasible );
4068  }
4069  }
4070 
4071  if( !addedtolp )
4072  {
4073  SCIP_CALL( SCIPaddPoolCut(scip, row) );
4074  }
4075 
4076  SCIP_CALL( SCIPreleaseRow(scip, &row) );
4077  }
4078 
4079  return SCIP_OKAY;
4080 }
4081 
4082 /** processes the event that a new primal solution has been found */
4083 static
4084 SCIP_DECL_EVENTEXEC(processNewSolutionEvent)
4086  SCIP_CONSHDLRDATA* conshdlrdata;
4087  SCIP_CONSHDLR* conshdlr;
4088  SCIP_CONS** conss;
4089  int nconss;
4090  SCIP_SOL* sol;
4091 
4092  assert(scip != NULL);
4093  assert(event != NULL);
4094  assert(eventdata != NULL);
4095  assert(eventhdlr != NULL);
4096 
4097  assert((SCIPeventGetType(event) & SCIP_EVENTTYPE_SOLFOUND) != 0);
4098 
4099  conshdlr = (SCIP_CONSHDLR*)eventdata;
4100 
4101  nconss = SCIPconshdlrGetNConss(conshdlr);
4102 
4103  if( nconss == 0 )
4104  return SCIP_OKAY;
4105 
4106  sol = SCIPeventGetSol(event);
4107  assert(sol != NULL);
4108 
4109  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4110  assert(conshdlrdata != NULL);
4111 
4112  /* we are only interested in solution coming from some heuristic other than trysol, but not from the tree
4113  * the reason for ignoring trysol solutions is that they may come from an NLP solve in sepalp, where we already added linearizations,
4114  * or are from the tree, but postprocessed via proposeFeasibleSolution
4115  */
4116  if( SCIPsolGetHeur(sol) == NULL || SCIPsolGetHeur(sol) == conshdlrdata->trysolheur )
4117  return SCIP_OKAY;
4118 
4119  conss = SCIPconshdlrGetConss(conshdlr);
4120  assert(conss != NULL);
4121 
4122  SCIPdebugMessage("catched new sol event %x from heur <%s>; have %d conss\n", SCIPeventGetType(event), SCIPheurGetName(SCIPsolGetHeur(sol)), nconss);
4123 
4124  SCIP_CALL( addLinearizationCuts(scip, conshdlr, conss, nconss, sol, NULL, 0.0) );
4125 
4126  return SCIP_OKAY;
4127 }
4128 
4129 /** given a solution, try to make absolute power constraints feasible by shifting the linear variable z and pass this solution to the trysol heuristic */
4130 static
4132  SCIP* scip, /**< SCIP data structure */
4133  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4134  SCIP_CONS** conss, /**< constraints to process */
4135  int nconss, /**< number of constraints */
4136  SCIP_SOL* sol /**< solution to process */
4137  )
4138 {
4139  SCIP_CONSDATA* consdata;
4140  SCIP_SOL* newsol;
4141  SCIP_Real xtermval;
4142  SCIP_Real zval;
4143  SCIP_Real viol;
4144  int c;
4145 
4146  assert(scip != NULL);
4147  assert(conshdlr != NULL);
4148  assert(conss != NULL || nconss == 0);
4149 
4150  if( sol != NULL )
4151  {
4152  SCIP_CALL( SCIPcreateSolCopy(scip, &newsol, sol) );
4153  }
4154  else
4155  {
4156  SCIP_CALL( SCIPcreateLPSol(scip, &newsol, NULL) );
4157  }
4158  SCIP_CALL( SCIPunlinkSol(scip, newsol) );
4159 
4160  for( c = 0; c < nconss; ++c )
4161  {
4162  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
4163  assert(consdata != NULL);
4164  assert(consdata->z != NULL);
4165  assert(consdata->zcoef != 0.0);
4166 
4167  /* recompute violation w.r.t. current solution */
4168  SCIP_CALL( computeViolation(scip, conshdlr, conss[c], newsol, &viol) ); /*lint !e613*/
4169 
4170  /* do nothing if constraint is satisfied */
4171  if( !SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) && !SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
4172  continue;
4173 
4174  /* if violation is at infinity, give up */
4175  if( SCIPisInfinity(scip, MAX(consdata->lhsviol, consdata->rhsviol)) )
4176  break;
4177 
4178  /* @todo could also adjust x while keeping z fixed */
4179 
4180  /* if variable is multiaggregated, then cannot set its solution value, so give up */
4181  if( SCIPvarGetStatus(consdata->z) == SCIP_VARSTATUS_MULTAGGR )
4182  break;
4183 
4184  /* compute value of x-term */
4185  xtermval = SCIPgetSolVal(scip, newsol, consdata->x);
4186  xtermval += consdata->xoffset;
4187  xtermval = SIGN(xtermval) * consdata->power(ABS(xtermval), consdata->exponent);
4188 
4189  /* if left hand side is violated, try to set z such that lhs is active */
4190  if( SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) )
4191  {
4192  assert(!SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip))); /* should only have one side violated (otherwise some variable is at infinity) */
4193 
4194  zval = (consdata->lhs - xtermval)/consdata->zcoef;
4195  /* bad luck: z would get value outside of its domain */
4196  if( SCIPisInfinity(scip, REALABS(zval)) || SCIPisFeasLT(scip, zval, SCIPvarGetLbGlobal(consdata->z)) || SCIPisFeasGT(scip, zval, SCIPvarGetUbGlobal(consdata->z)) )
4197  break;
4198  SCIP_CALL( SCIPsetSolVal(scip, newsol, consdata->z, zval) );
4199  }
4200 
4201  /* if right hand side is violated, try to set z such that rhs is active */
4202  if( SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
4203  {
4204  zval = (consdata->rhs - xtermval)/consdata->zcoef;
4205  /* bad luck: z would get value outside of its domain */
4206  if( SCIPisInfinity(scip, REALABS(zval)) || SCIPisFeasLT(scip, zval, SCIPvarGetLbGlobal(consdata->z)) || SCIPisFeasGT(scip, zval, SCIPvarGetUbGlobal(consdata->z)) )
4207  break;
4208  SCIP_CALL( SCIPsetSolVal(scip, newsol, consdata->z, zval) );
4209  }
4210  }
4211 
4212  /* if we have a solution that should satisfy all absolute power constraints and has a better objective than the current upper bound, then pass it to the trysol heuristic */
4213  if( c == nconss )
4214  {
4215  SCIP_CONSHDLRDATA* conshdlrdata;
4216 
4217  SCIPdebugMessage("pass solution with objective val %g to trysol heuristic\n", SCIPgetSolTransObj(scip, newsol));
4218 
4219  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4220  assert(conshdlrdata != NULL);
4221  assert(conshdlrdata->trysolheur != NULL);
4222 
4223  SCIP_CALL( SCIPheurPassSolTrySol(scip, conshdlrdata->trysolheur, newsol) );
4224  }
4225 
4226  SCIP_CALL( SCIPfreeSol(scip, &newsol) );
4227 
4228  return SCIP_OKAY;
4229 }
4230 
4231 /** create a nonlinear row representation of the constraint and stores them in consdata */
4232 static
4234  SCIP* scip, /**< SCIP data structure */
4235  SCIP_CONS* cons /**< absolute power constraint */
4236  )
4237 {
4238  SCIP_CONSDATA* consdata;
4239  SCIP_EXPRTREE* exprtree;
4240  SCIP_QUADELEM quadelem;
4241  SCIP_VAR* linvars[2];
4242  SCIP_Real lincoefs[2];
4243  SCIP_VAR* quadvar;
4244  SCIP_Real constant;
4245  SCIP_Bool expisint;
4246  int sign;
4247  int nlinvars;
4248  int nquadvars;
4249  int nquadelems;
4250  int n;
4251 
4252  assert(scip != NULL);
4253  assert(cons != NULL);
4254 
4255  consdata = SCIPconsGetData(cons);
4256  assert(consdata != NULL);
4257 
4258  if( consdata->nlrow != NULL )
4259  {
4260  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
4261  }
4262 
4263  nlinvars = 0;
4264  nquadvars = 0;
4265  nquadelems = 0;
4266  exprtree = NULL;
4267  constant = 0.0;
4268 
4269  /* check if sign of x is fixed */
4270  if( !SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->x)+consdata->xoffset) )
4271  sign = 1;
4272  else if( !SCIPisPositive(scip, SCIPvarGetUbGlobal(consdata->x)+consdata->xoffset) )
4273  sign = -1;
4274  else
4275  sign = 0;
4276 
4277  /* check if exponent is integral */
4278  expisint = SCIPisIntegral(scip, consdata->exponent);
4279  n = (int)SCIPround(scip, consdata->exponent);
4280 
4281  /* create quadelem or expression tree for nonlinear part sign(x+offset)abs(x+offset)^n */
4282  if( sign != 0 || (expisint && (n % 2 == 1)) )
4283  {
4284  /* sign is fixes or exponent is odd integer */
4285  if( expisint && n == 2 )
4286  {
4287  /* sign of x is clear and exponent is 2.0 -> generate quadratic, linear, and constant term for +/- (x+offset)^n */
4288  assert(sign == -1 || sign == 1);
4289  nquadelems = 1;
4290  quadelem.idx1 = 0;
4291  quadelem.idx2 = 0;
4292  quadelem.coef = (SCIP_Real)sign;
4293  nquadvars = 1;
4294  quadvar = consdata->x;
4295 
4296  if( consdata->xoffset != 0.0 )
4297  {
4298  linvars[0] = consdata->x;
4299  lincoefs[0] = sign * 2.0 * consdata->xoffset;
4300  nlinvars = 1;
4301  constant = sign * consdata->xoffset * consdata->xoffset;
4302  }
4303  }
4304  else
4305  {
4306  /* exponent is odd or sign of x is clear, generate expression tree for +/- (+/-(x+offset))^exponent */
4307  SCIP_EXPR* expr;
4308  SCIP_EXPR* expr2;
4309 
4310  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) ); /* x */
4311  if( consdata->xoffset != 0.0 )
4312  {
4313  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, consdata->xoffset) );
4314  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_PLUS, expr, expr2) ); /* x + offset */
4315  }
4316  if( sign == -1 && !expisint )
4317  {
4318  /* if exponent is not integer and x is negative, then negate */
4319  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, -1.0) ); /* -1 */
4320  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_MUL, expr, expr2) ); /* -(x+offset) */
4321  }
4322  /* use intpower for integer exponent and realpower for fractional exponent */
4323  if( expisint )
4324  {
4325  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_INTPOWER, expr, n) ); /* (x+offset)^n */
4326  }
4327  else
4328  {
4329  assert(sign == 1 || sign == -1);
4330  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_REALPOWER, expr, consdata->exponent) ); /* abs(x+offset)^exponent */
4331  }
4332  /* if exponent is even integer, then negate result; if it's an odd integer, then intpower already takes care of correct sign */
4333  if( sign == -1 && !(expisint && n % 2 == 1) )
4334  {
4335  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, -1.0) ); /* -1 */
4336  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_MUL, expr, expr2) ); /* -abs(x+offset)^exponent */
4337  }
4338  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, 1, 0, NULL) );
4339  }
4340  }
4341  else
4342  {
4343  /* exponent is not odd integer and sign of x is not fixed -> generate expression tree for signpower(x+offset, n) */
4344  SCIP_EXPR* expr;
4345  SCIP_EXPR* expr2;
4346 
4347  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, 0) ); /* x */
4348  if( consdata->xoffset != 0.0 )
4349  {
4350  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, consdata->xoffset) );
4351  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_PLUS, expr, expr2) ); /* x + offset */
4352  }
4353  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_SIGNPOWER, expr, (SCIP_Real)consdata->exponent) ); /* signpower(x+offset, n) */
4354 
4355  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, 1, 0, NULL) );
4356  }
4357  assert(exprtree != NULL || nquadelems > 0);
4358 
4359  /* tell expression tree, which is its variable */
4360  if( exprtree != NULL )
4361  {
4362  SCIP_CALL( SCIPexprtreeSetVars(exprtree, 1, &consdata->x) );
4363  }
4364 
4365  assert(nlinvars < 2);
4366  linvars[nlinvars] = consdata->z;
4367  lincoefs[nlinvars] = consdata->zcoef;
4368  ++nlinvars;
4369 
4370  /* create nlrow */
4371  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons), constant,
4372  nlinvars, linvars, lincoefs,
4373  nquadvars, &quadvar, nquadelems, &quadelem,
4374  exprtree, consdata->lhs, consdata->rhs
4375  ) );
4376 
4377  if( exprtree != NULL )
4378  {
4379  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
4380  }
4381 
4382  return SCIP_OKAY;
4383 }
4384 
4385 /** upgrades a quadratic constraint where the quadratic part is only a single square term and the quadratic variable sign is fixed to a signpower constraint */
4386 static
4387 SCIP_DECL_QUADCONSUPGD(quadconsUpgdAbspower)
4388 { /*lint --e{715}*/
4389  SCIP_QUADVARTERM quadvarterm;
4390  SCIP_VAR* x;
4391  SCIP_VAR* z;
4392  SCIP_Real xoffset;
4393  SCIP_Real zcoef;
4394  SCIP_Real signpowcoef;
4395  SCIP_Real lhs;
4396  SCIP_Real rhs;
4397 
4398  *nupgdconss = 0;
4399 
4400  /* need at least one linear variable */
4401  if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
4402  return SCIP_OKAY;
4403 
4404  /* consider only quadratic constraints with a single square term */
4405  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) != 1 )
4406  return SCIP_OKAY;
4407  assert(SCIPgetNBilinTermsQuadratic(scip, cons) == 0);
4408 
4409  quadvarterm = SCIPgetQuadVarTermsQuadratic(scip, cons)[0];
4410  if( SCIPisZero(scip, quadvarterm.sqrcoef) )
4411  return SCIP_OKAY;
4412 
4413  x = quadvarterm.var;
4414  xoffset = quadvarterm.lincoef / (2.0 * quadvarterm.sqrcoef);
4415 
4416  /* check that x has fixed sign */
4417  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(x) + xoffset) && SCIPisPositive(scip, SCIPvarGetUbGlobal(x) + xoffset) )
4418  return SCIP_OKAY;
4419 
4420  /* check whether upgdconss array has enough space to store 1 or 2 constraints */
4421  if( SCIPgetNLinearVarsQuadratic(scip, cons) > 1 )
4422  *nupgdconss = -2;
4423  else
4424  *nupgdconss = -1;
4425  if( -*nupgdconss > upgdconsssize )
4426  return SCIP_OKAY;
4427 
4428  *nupgdconss = 0;
4429 
4430  SCIPdebugMessage("upgrade quadratic constraint <%s> to absolute power, x = [%g,%g], offset = %g\n", SCIPconsGetName(cons), SCIPvarGetLbGlobal(x), SCIPvarGetUbGlobal(x), xoffset);
4431  SCIPdebugPrintCons(scip, cons, NULL);
4432 
4433  lhs = SCIPgetLhsQuadratic(scip, cons);
4434  rhs = SCIPgetRhsQuadratic(scip, cons);
4435 
4436  /* get z and its coefficient */
4437  if( SCIPgetNLinearVarsQuadratic(scip, cons) > 1 )
4438  {
4439  /* create auxiliary variable and constraint for linear part, since we can handle only at most one variable in cons_signpower */
4440  char name[SCIP_MAXSTRLEN];
4441  SCIP_VAR* auxvar;
4442 
4443  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_linpart", SCIPconsGetName(cons));
4444  SCIP_CALL( SCIPcreateVar(scip, &auxvar, name, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
4446  SCIP_CALL( SCIPaddVar(scip, auxvar) );
4447 
4448  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], name, SCIPgetNLinearVarsQuadratic(scip, cons),
4450  SCIPisInfinity(scip, -lhs) ? -SCIPinfinity(scip) : 0.0,
4451  SCIPisInfinity(scip, rhs) ? SCIPinfinity(scip) : 0.0,
4455  SCIPconsIsStickingAtNode(cons)) );
4456  SCIP_CALL( SCIPaddCoefLinear(scip, upgdconss[*nupgdconss], auxvar, -1.0) );
4457 
4458  z = auxvar;
4459  zcoef = 1.0;
4460 
4461  ++*nupgdconss;
4462 
4463  /* compute and set value of auxvar in debug solution */
4464 #ifdef SCIP_DEBUG_SOLUTION
4465  if( SCIPdebugIsMainscip(scip) )
4466  {
4467  SCIP_Real debugval;
4468  SCIP_Real debugvarval;
4469  int i;
4470 
4471  debugval = 0.0;
4472  for( i = 0; i < SCIPgetNLinearVarsQuadratic(scip, cons); ++i )
4473  {
4474  SCIP_CALL( SCIPdebugGetSolVal(scip, SCIPgetLinearVarsQuadratic(scip, cons)[i], &debugvarval) );
4475  debugval += SCIPgetCoefsLinearVarsQuadratic(scip, cons)[i] * debugvarval;
4476  }
4477 
4478  SCIP_CALL( SCIPdebugAddSolVal(scip, auxvar, debugval) );
4479  }
4480 #endif
4481 
4482  SCIP_CALL( SCIPreleaseVar(scip, &auxvar) );
4483  }
4484  else
4485  {
4486  assert(SCIPgetNLinearVarsQuadratic(scip, cons) == 1);
4487  z = SCIPgetLinearVarsQuadratic(scip, cons)[0];
4488  zcoef = SCIPgetCoefsLinearVarsQuadratic(scip, cons)[0];
4489  }
4490 
4491  /* we now have lhs <= sqrcoef * (x + offset)^2 - sqrcoef * offset^2 + zcoef * z <= rhs */
4492 
4493  /* move sqrcoef * offset^2 into lhs and rhs */
4494  if( !SCIPisInfinity(scip, -lhs) )
4495  lhs += quadvarterm.sqrcoef * xoffset * xoffset;
4496  if( !SCIPisInfinity(scip, rhs) )
4497  rhs += quadvarterm.sqrcoef * xoffset * xoffset;
4498 
4499  /* divide by sqrcoef if x+offset > 0 and by -sqrcoef if < 0 */
4500  signpowcoef = quadvarterm.sqrcoef;
4501  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(x) + xoffset) )
4502  signpowcoef = -signpowcoef;
4503  if( signpowcoef > 0.0 )
4504  {
4505  if( !SCIPisInfinity(scip, -lhs) )
4506  lhs /= signpowcoef;
4507  if( !SCIPisInfinity(scip, rhs) )
4508  rhs /= signpowcoef;
4509  }
4510  else
4511  {
4512  SCIP_Real newrhs;
4513 
4514  if( !SCIPisInfinity(scip, -lhs) )
4515  newrhs = lhs / signpowcoef;
4516  else
4517  newrhs = SCIPinfinity(scip);
4518  if( !SCIPisInfinity(scip, rhs) )
4519  lhs = rhs / signpowcoef;
4520  else
4521  lhs = -SCIPinfinity(scip);
4522  rhs = newrhs;
4523  }
4524  zcoef /= signpowcoef;
4525 
4526  /* create the absolute power constraint */
4527  SCIP_CALL( SCIPcreateConsAbspower(scip, &upgdconss[*nupgdconss], SCIPconsGetName(cons), x, z, 2.0,
4528  xoffset, zcoef, lhs, rhs,
4532  SCIPconsIsStickingAtNode(cons)) );
4533  SCIPdebugPrintCons(scip, upgdconss[*nupgdconss], NULL);
4534  ++*nupgdconss;
4535 
4536  return SCIP_OKAY;
4537 }
4538 
4539 /** tries to upgrade a nonlinear constraint into a absolute power constraint */
4540 static
4541 SCIP_DECL_NONLINCONSUPGD(nonlinconsUpgdAbspower)
4543  SCIP_EXPRGRAPH* exprgraph;
4544  SCIP_EXPRGRAPHNODE* node;
4545  SCIP_EXPRGRAPHNODE* child;
4546  SCIP_Real exponent;
4547  SCIP_VAR* x;
4548  SCIP_VAR* z;
4549  SCIP_Real signpowcoef;
4550  SCIP_Real zcoef;
4551  SCIP_Real xoffset;
4552  SCIP_Real constant;
4553  SCIP_Real lhs;
4554  SCIP_Real rhs;
4555 
4556  assert(nupgdconss != NULL);
4557  assert(upgdconss != NULL);
4558 
4559  *nupgdconss = 0;
4560 
4561  /* absolute power needs at least one linear variable (constraint is trivial, otherwise) */
4562  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
4563  return SCIP_OKAY;
4564 
4565  node = SCIPgetExprgraphNodeNonlinear(scip, cons);
4566 
4567  /* no interest in linear constraints */
4568  if( node == NULL )
4569  return SCIP_OKAY;
4570 
4571  /* need exactly one argument */
4572  if( SCIPexprgraphGetNodeNChildren(node) != 1 )
4573  return SCIP_OKAY;
4574 
4575  constant = 0.0;
4576  signpowcoef = 1.0; /* coefficient of sign(x)abs(x)^n term, to be reformulated away... */
4577 
4578  child = SCIPexprgraphGetNodeChildren(node)[0];
4579 
4580  /* check if node expression fits to absolute power constraint */
4581  switch( SCIPexprgraphGetNodeOperator(node) )
4582  {
4583  case SCIP_EXPR_REALPOWER:
4584  /* realpower with exponent > 1.0 can always be signpower, since it assumes that argument is >= 0.0 */
4585  exponent = SCIPexprgraphGetNodeRealPowerExponent(node);
4586  if( exponent <= 1.0 )
4587  return SCIP_OKAY;
4588 
4589  assert(SCIPexprgraphGetNodeBounds(child).inf >= 0.0);
4590  break;
4591 
4592  case SCIP_EXPR_INTPOWER:
4593  {
4594  /* check if exponent > 1.0 and either odd or even with child having fixed sign */
4595  SCIP_INTERVAL childbounds;
4596 
4598  if( exponent <= 1.0 )
4599  return SCIP_OKAY;
4600 
4601  childbounds = SCIPexprgraphGetNodeBounds(child);
4602  if( (int)exponent % 2 == 0 && childbounds.inf < 0.0 && childbounds.sup > 0.0 )
4603  return SCIP_OKAY;
4604 
4605  /* use x^exponent = -sign(x) |x|^exponent if exponent is even and x always negative */
4606  if( (int)exponent % 2 == 0 && childbounds.inf < 0.0 )
4607  signpowcoef = -1.0;
4608 
4609  break;
4610  }
4611 
4612  case SCIP_EXPR_SQUARE:
4613  {
4614  /* check if child has fixed sign */
4615  SCIP_INTERVAL childbounds;
4616 
4617  childbounds = SCIPexprgraphGetNodeBounds(child);
4618  if( childbounds.inf < 0.0 && childbounds.sup > 0.0 )
4619  return SCIP_OKAY;
4620 
4621  /* use x^2 = -sign(x) |x|^2 if x is always negative */
4622  if( childbounds.inf < 0.0 )
4623  signpowcoef = -1.0;
4624 
4625  exponent = 2.0;
4626  break;
4627  }
4628 
4629  case SCIP_EXPR_SIGNPOWER:
4630  /* check if exponent > 1.0 */
4631  exponent = SCIPexprgraphGetNodeSignPowerExponent(node);
4632  if( exponent <= 1.0 )
4633  return SCIP_OKAY;
4634  break;
4635 
4636  case SCIP_EXPR_POLYNOMIAL:
4637  {
4638  SCIP_EXPRDATA_MONOMIAL* monomial;
4639  SCIP_INTERVAL childbounds;
4640 
4641  /* check if only one univariate monomial with exponent > 1.0 */
4642 
4643  /* if sum of univariate monomials, then this should have been taken care of by exprgraphnodeReformSignpower */
4645  return SCIP_OKAY;
4646  assert(SCIPexprgraphGetNodePolynomialNMonomials(node) == 1); /* assume simplified, i.e., no constant polynomial */
4647 
4648  monomial = SCIPexprgraphGetNodePolynomialMonomials(node)[0];
4649  assert(SCIPexprGetMonomialNFactors(monomial) == 1); /* since we have only one children and assume simplified */
4650 
4651  exponent = SCIPexprGetMonomialExponents(monomial)[0];
4652  if( exponent <= 1.0 )
4653  return SCIP_OKAY;
4654 
4655  /* if exponent is even integer and child has mixed sign, then cannot do
4656  * if exponent is even integer and child is always negative, then can do via multiplication by -1.0 */
4657  childbounds = SCIPexprgraphGetNodeBounds(child);
4658  if( SCIPisIntegral(scip, exponent) && ((int)SCIPround(scip, exponent) % 2 == 0) && childbounds.inf < 0.0 )
4659  {
4660  if( childbounds.sup > 0.0 )
4661  return SCIP_OKAY;
4662  signpowcoef = -1.0;
4663  }
4664 
4665  constant = SCIPexprgraphGetNodePolynomialConstant(node);
4666  signpowcoef *= SCIPexprGetMonomialCoef(monomial);
4667 
4668  break;
4669  }
4670 
4671  default:
4672  return SCIP_OKAY;
4673  } /*lint !e788*/
4674  assert(SCIPexprgraphGetNodeNChildren(node) == 1);
4675 
4676  /* check magnitue of coefficient of z in signpower constraint */
4677  zcoef = 1.0;
4678  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 1 )
4679  zcoef = SCIPgetLinearCoefsNonlinear(scip, cons)[0];
4680  zcoef /= signpowcoef;
4682  {
4683  zcoef /= pow(REALABS(SCIPexprgraphGetNodeLinearCoefs(child)[0]), exponent);
4684  }
4685  if( SCIPisZero(scip, zcoef) )
4686  {
4687  SCIPdebugMessage("skip upgrade to signpower since |zcoef| = %g would be zero\n", zcoef);
4688  return SCIP_OKAY;
4689  }
4690 
4691  /* count how many constraints we need to add (use negative numbers, for convenience):
4692  * one constraint for absolute power,
4693  * plus one if we need to replace the linear part by single variable,
4694  * plus one if we need to replace the argument of absolute power by a single variable
4695  */
4696  *nupgdconss = -1;
4697 
4699  {
4700  /* if node has known curvature and we would add auxiliary var for child, then don't upgrade
4701  * it's not really necessary, but may introduce more numerical troubles
4702  * @todo maybe still do if child is linear?
4703  */
4705  {
4706  *nupgdconss = 0;
4707  return SCIP_OKAY;
4708  }
4709 
4710  --*nupgdconss;
4711  }
4712 
4713  if( SCIPgetNLinearVarsNonlinear(scip, cons) > 1 )
4714  --*nupgdconss;
4715 
4716  /* request larger upgdconss array */
4717  if( upgdconsssize < -*nupgdconss )
4718  return SCIP_OKAY;
4719 
4720  SCIPdebugMessage("upgrading constraint <%s>\n", SCIPconsGetName(cons));
4721 
4722  /* start counting at zero again */
4723  *nupgdconss = 0;
4724 
4725  exprgraph = SCIPgetExprgraphNonlinear(scip, SCIPconsGetHdlr(cons));
4726 
4727  lhs = SCIPgetLhsNonlinear(scip, cons);
4728  rhs = SCIPgetRhsNonlinear(scip, cons);
4729 
4730  /* get x and it's offset */
4732  {
4733  x = (SCIP_VAR*)SCIPexprgraphGetNodeVar(exprgraph, child);
4734  xoffset = 0.0;
4735  }
4737  {
4738  SCIP_Real xcoef;
4739 
4741  xcoef = SCIPexprgraphGetNodeLinearCoefs(child)[0];
4742  assert(!SCIPisZero(scip, xcoef));
4743 
4744  signpowcoef *= (xcoef < 0.0 ? -1.0 : 1.0) * pow(REALABS(xcoef), exponent);
4745  xoffset = SCIPexprgraphGetNodeLinearConstant(child) / xcoef;
4746  }
4747  else
4748  {
4749  /* reformulate by adding auxiliary variable and constraint for child */
4750  char name[SCIP_MAXSTRLEN];
4751  SCIP_INTERVAL bounds;
4752  SCIP_VAR* auxvar;
4753  SCIP_Real minusone;
4754 
4755  bounds = SCIPexprgraphGetNodeBounds(child);
4756  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_powerarg", SCIPconsGetName(cons));
4757 
4758  SCIPdebugMessage("add auxiliary variable and constraint %s for node %p(%d,%d)\n", name, (void*)child, SCIPexprgraphGetNodeDepth(child), SCIPexprgraphGetNodePosition(child));
4759 
4760  SCIP_CALL( SCIPcreateVar(scip, &auxvar, name, SCIPintervalGetInf(bounds), SCIPintervalGetSup(bounds), 0.0,
4762  SCIP_CALL( SCIPaddVar(scip, auxvar) );
4763 
4764  /* create new constraint child == auxvar
4765  * since signpower is monotonic, we need only child <= auxvar or child >= auxvar, if not both sides are finite, and depending on signpowcoef
4766  * i.e., we need child - auxvar <= 0.0 if rhs is finite and signpowcoef > 0.0 or lhs is finite and signpowcoef < 0.0
4767  * and we need 0.0 <= child - auxvar if lhs is finite and signpowcoef > 0.0 or rhs is finite and signpowcoef < 0.0
4768  */
4769  minusone = -1.0;
4770  assert(upgdconsssize > *nupgdconss);
4771  SCIP_CALL( SCIPcreateConsNonlinear2(scip, &upgdconss[*nupgdconss], name, 1, &auxvar, &minusone, child,
4772  ((signpowcoef > 0.0 && !SCIPisInfinity(scip, -lhs)) || (signpowcoef < 0.0 && !SCIPisInfinity(scip, rhs))) ? 0.0 : -SCIPinfinity(scip),
4773  ((signpowcoef > 0.0 && !SCIPisInfinity(scip, rhs)) || (signpowcoef < 0.0 && !SCIPisInfinity(scip, -lhs))) ? 0.0 : SCIPinfinity(scip),
4774  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
4775  ++*nupgdconss;
4776 
4777  /* use auxvar to setup absolute power constraint */
4778  x = auxvar;
4779  xoffset = 0.0;
4780 
4781  /* compute and set value of auxvar in debug solution, if debugging is enabled */
4782  SCIP_CALL( SCIPdebugAddSolVal(scip, auxvar, SCIPexprgraphGetNodeVal(child)) ); /*lint !e506 !e774*/
4783 
4784  SCIP_CALL( SCIPreleaseVar(scip, &auxvar) );
4785  }
4786 
4787  /* get z and its coefficient */
4788  if( SCIPgetNLinearVarsNonlinear(scip, cons) > 1 )
4789  {
4790  /* create auxiliary variable and constraint for linear part, since we can handle only at most one variable in cons_signpower */
4791  char name[SCIP_MAXSTRLEN];
4792  SCIP_VAR* auxvar;
4793 
4794  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_linpart", SCIPconsGetName(cons));
4795  SCIP_CALL( SCIPcreateVar(scip, &auxvar, name, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
4797  SCIP_CALL( SCIPaddVar(scip, auxvar) );
4798 
4799  assert(upgdconsssize > *nupgdconss);
4800  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[*nupgdconss], name, SCIPgetNLinearVarsNonlinear(scip, cons),
4802  SCIPisInfinity(scip, -lhs) ? -SCIPinfinity(scip) : 0.0,
4803  SCIPisInfinity(scip, rhs) ? SCIPinfinity(scip) : 0.0,
4807  SCIPconsIsStickingAtNode(cons)) );
4808  SCIP_CALL( SCIPaddCoefLinear(scip, upgdconss[*nupgdconss], auxvar, -1.0) );
4809 
4810  z = auxvar;
4811  zcoef = 1.0;
4812 
4813  ++*nupgdconss;
4814 
4815  /* compute and set value of auxvar in debug solution */
4816 #ifdef SCIP_DEBUG_SOLUTION
4817  if( SCIPdebugIsMainscip(scip) )
4818  {
4819  SCIP_Real debugval;
4820  SCIP_Real debugvarval;
4821  int i;
4822 
4823  debugval = 0.0;
4824  for( i = 0; i < SCIPgetNLinearVarsNonlinear(scip, cons); ++i )
4825  {
4826  SCIP_CALL( SCIPdebugGetSolVal(scip, SCIPgetLinearVarsNonlinear(scip, cons)[i], &debugvarval) );
4827  debugval += SCIPgetLinearCoefsNonlinear(scip, cons)[i] * debugvarval;
4828  }
4829 
4830  SCIP_CALL( SCIPdebugAddSolVal(scip, auxvar, debugval) );
4831  }
4832 #endif
4833 
4834  SCIP_CALL( SCIPreleaseVar(scip, &auxvar) );
4835  }
4836  else
4837  {
4838  assert(SCIPgetNLinearVarsNonlinear(scip, cons) == 1);
4839  z = SCIPgetLinearVarsNonlinear(scip, cons)[0];
4840  zcoef = SCIPgetLinearCoefsNonlinear(scip, cons)[0];
4841  }
4842 
4843  if( constant != 0.0 )
4844  {
4845  if( !SCIPisInfinity(scip, -lhs) )
4846  lhs -= constant;
4847  if( !SCIPisInfinity(scip, rhs) )
4848  rhs -= constant;
4849  }
4850 
4851  /* divide absolute power constraint by signpowcoef */
4852  if( signpowcoef != 1.0 )
4853  {
4854  zcoef /= signpowcoef;
4855  if( signpowcoef < 0.0 )
4856  {
4857  SCIP_Real newrhs;
4858 
4859  newrhs = SCIPisInfinity(scip, -lhs) ? SCIPinfinity(scip) : lhs/signpowcoef;
4860  lhs = SCIPisInfinity(scip, rhs) ? -SCIPinfinity(scip) : rhs/signpowcoef;
4861  rhs = newrhs;
4862  }
4863  else
4864  {
4865  if( !SCIPisInfinity(scip, -lhs) )
4866  lhs /= signpowcoef;
4867  if( !SCIPisInfinity(scip, rhs) )
4868  rhs /= signpowcoef;
4869  }
4870  }
4871 
4872  /* finally setup a absolute power constraint */
4873 
4874  assert(*nupgdconss < upgdconsssize);
4875  SCIP_CALL( SCIPcreateConsAbspower(scip, &upgdconss[*nupgdconss], SCIPconsGetName(cons),
4876  x, z, exponent, xoffset, zcoef, lhs, rhs,
4880  SCIPconsIsStickingAtNode(cons)) );
4881  ++*nupgdconss;
4882 
4883  return SCIP_OKAY;
4884 }
4885 
4886 /** tries to reformulate a expression graph node via introducing a absolute power constraint
4887  * if node fits to absolute power and has indefinte curvature and has no nonlinear parents and has siblings, then replace by auxvar and absolute power constraint
4888  * if it still has nonlinear parents, then we wait to see if reformulation code move node into auxiliary constraint,
4889  * so we do not add unnessary auxiliary variables for something like an x^2 in an exp(x^2)
4890  * if it has no siblings, then we let the upgrading for nonlinear constraints take care of it,
4891  * since it may be able to upgrade the constraint as a whole and can take the constraint sides into account too (may need only <=/>= auxcons)
4892  */
4893 static
4894 SCIP_DECL_EXPRGRAPHNODEREFORM(exprgraphnodeReformAbspower)
4896  SCIP_EXPRGRAPHNODE* child;
4897  char name[SCIP_MAXSTRLEN];
4898  SCIP_CONS* cons;
4899  SCIP_Real exponent;
4900  SCIP_VAR* x;
4901  SCIP_VAR* z;
4902  SCIP_Real signpowcoef;
4903  SCIP_Real xoffset;
4904  SCIP_Real constant;
4905 
4906  assert(scip != NULL);
4907  assert(exprgraph != NULL);
4908  assert(node != NULL);
4909  assert(naddcons != NULL);
4910  assert(reformnode != NULL);
4911 
4912  *reformnode = NULL;
4913 
4915  return SCIP_OKAY;
4916 
4917  constant = 0.0;
4918  signpowcoef = 1.0; /* coefficient of sign(x)abs(x)^n term, to be move in from of z... */
4919 
4920  /* check if node expression fits to absolute power constraint */
4921  switch( SCIPexprgraphGetNodeOperator(node) )
4922  {
4923  case SCIP_EXPR_REALPOWER:
4924  /* realpower with exponent > 1.0 can always be absolute power, since it assumes that argument is >= 0.0
4925  * @todo we should also ensure that argument is >= 0.0
4926  */
4927  exponent = SCIPexprgraphGetNodeRealPowerExponent(node);
4928  if( exponent <= 1.0 )
4929  return SCIP_OKAY;
4930 
4931  assert(SCIPexprgraphGetNodeBounds(SCIPexprgraphGetNodeChildren(node)[0]).inf >= 0.0);
4932  break;
4933 
4934  case SCIP_EXPR_INTPOWER:
4935  {
4936  /* check if exponent > 1.0 and either odd or even with child having fixed sign */
4937  SCIP_INTERVAL childbounds;
4938 
4940  if( exponent <= 1.0 )
4941  return SCIP_OKAY;
4942 
4944  if( (int)exponent % 2 == 0 && childbounds.inf < 0.0 && childbounds.sup > 0.0 )
4945  return SCIP_OKAY;
4946 
4947  /* use x^exponent = -sign(x) |x|^exponent if exponent is even and x always negative */
4948  if( (int)exponent % 2 == 0 && childbounds.inf < 0.0 )
4949  signpowcoef = -1.0;
4950 
4951  break;
4952  }
4953 
4954  case SCIP_EXPR_SQUARE:
4955  {
4956  /* check if child has fixed sign */
4957  SCIP_INTERVAL childbounds;
4958 
4960  if( childbounds.inf < 0.0 && childbounds.sup > 0.0 )
4961  return SCIP_OKAY;
4962 
4963  /* use x^2 = -sign(x) |x|^2 if x is always negative */
4964  if( childbounds.inf < 0.0 )
4965  signpowcoef = -1.0;
4966 
4967  exponent = 2.0;
4968  break;
4969  }
4970 
4971  case SCIP_EXPR_SIGNPOWER:
4972  /* check if exponent > 1.0 */
4973  exponent = SCIPexprgraphGetNodeSignPowerExponent(node);
4974  if( exponent <= 1.0 )
4975  return SCIP_OKAY;
4976  break;
4977 
4978  case SCIP_EXPR_POLYNOMIAL:
4979  {
4980  SCIP_EXPRDATA_MONOMIAL* monomial;
4981  SCIP_INTERVAL childbounds;
4982 
4983  /* check if only one univariate monomial with exponent > 1.0 */
4984  if( SCIPexprgraphGetNodeNChildren(node) > 1 )
4985  return SCIP_OKAY;
4986  assert(SCIPexprgraphGetNodeNChildren(node) == 1);
4987 
4989  return SCIP_OKAY;
4990  assert(SCIPexprgraphGetNodePolynomialNMonomials(node) == 1); /* assume simplified, i.e., no constant polynomial */
4991 
4992  monomial = SCIPexprgraphGetNodePolynomialMonomials(node)[0];
4993  assert(SCIPexprGetMonomialNFactors(monomial) == 1); /* since we have only one children and assume simplified */
4994 
4995  exponent = SCIPexprGetMonomialExponents(monomial)[0];
4996  if( exponent <= 1.0 )
4997  return SCIP_OKAY;
4998 
4999  /* if exponent is even integer and child has mixed sign, then cannot do
5000  * if exponent is even integer and child is always negative, then can do via multiplication by -1.0 */
5002  if( SCIPisIntegral(scip, exponent) && ((int)SCIPround(scip, exponent) % 2 == 0) && childbounds.inf < 0.0 )
5003  {
5004  if( childbounds.sup > 0.0 )
5005  return SCIP_OKAY;
5006  signpowcoef = -1.0;
5007  }
5008 
5009  constant = SCIPexprgraphGetNodePolynomialConstant(node);
5010  signpowcoef *= SCIPexprGetMonomialCoef(monomial);
5011 
5012  break;
5013  }
5014 
5015  default:
5016  return SCIP_OKAY;
5017  } /*lint !e788*/
5018  assert(SCIPexprgraphGetNodeNChildren(node) == 1);
5019 
5021  return SCIP_OKAY;
5022  if( !SCIPexprgraphHasNodeSibling(node) )
5023  return SCIP_OKAY;
5024 
5025  SCIPdebugMessage("reformulate node %p via signpower\n", (void*)node);
5026 
5027  /* get x and its offset */
5028  child = SCIPexprgraphGetNodeChildren(node)[0];
5030  {
5031  x = (SCIP_VAR*)SCIPexprgraphGetNodeVar(exprgraph, child);
5032  xoffset = 0.0;
5033  }
5035  {
5036  SCIP_Real xcoef;
5037 
5039  xcoef = SCIPexprgraphGetNodeLinearCoefs(child)[0];
5040  assert(!SCIPisZero(scip, xcoef));
5041 
5042  signpowcoef *= (xcoef < 0.0 ? -1.0 : 1.0) * pow(REALABS(xcoef), exponent);
5043  xoffset = SCIPexprgraphGetNodeLinearConstant(child) / xcoef;
5044  }
5045  else
5046  {
5047  /* reformulate by adding auxiliary variable and constraint for child */
5048  SCIP_INTERVAL bounds;
5049  SCIP_VAR* auxvar;
5050  SCIP_Real minusone;
5051 
5052  bounds = SCIPexprgraphGetNodeBounds(child);
5053  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "nlreform%dsp", *naddcons);
5054 
5055  SCIPdebugMessage("add auxiliary variable and constraint %s for node %p(%d,%d)\n", name, (void*)child, SCIPexprgraphGetNodeDepth(child), SCIPexprgraphGetNodePosition(child));
5056 
5057  SCIP_CALL( SCIPcreateVar(scip, &auxvar, name, SCIPintervalGetInf(bounds), SCIPintervalGetSup(bounds), 0.0, SCIP_VARTYPE_CONTINUOUS,
5058  TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
5059  SCIP_CALL( SCIPaddVar(scip, auxvar) );
5060 
5061  /* create new constraint child == auxvar */
5062  minusone = -1.0;
5063  SCIP_CALL( SCIPcreateConsNonlinear2(scip, &cons, name, 1, &auxvar, &minusone, child, 0.0, 0.0,
5064  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
5065  SCIP_CALL( SCIPaddCons(scip, cons) );
5066  ++*naddcons;
5067 
5068  /* use auxvar to setup signpower constraint */
5069  x = auxvar;
5070  xoffset = 0.0;
5071 
5072  SCIP_CALL( SCIPdebugAddSolVal(scip, auxvar, SCIPexprgraphGetNodeVal(child)) ); /*lint !e506 !e774*/
5073 
5074  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
5075  SCIP_CALL( SCIPreleaseVar(scip, &auxvar) );
5076  }
5077 
5078  /* create auxiliary variable z and add to expression graph */
5079  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "nlreform%dsp", *naddcons);
5080  SCIP_CALL( SCIPcreateVar(scip, &z, name, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS,
5081  TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
5082  SCIP_CALL( SCIPaddVar(scip, z) );
5083  SCIP_CALL( SCIPexprgraphAddVars(exprgraph, 1, (void**)&z, reformnode) );
5084 
5085  /* setup a absolute power constraint */
5086  if( REALABS(signpowcoef) * SCIPfeastol(scip) < 1.0 )
5087  {
5088  /* if signpowcoef is not huge (<10^6), then put it into absolute power constraint */
5089  SCIP_CALL( SCIPcreateConsAbspower(scip, &cons, name,
5090  x, z, exponent, xoffset, -1.0/signpowcoef, -constant/signpowcoef, -constant/signpowcoef,
5091  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
5092  SCIP_CALL( SCIPaddCons(scip, cons) );
5093  SCIPdebugPrintCons(scip, cons, NULL);
5094  ++*naddcons;
5095 
5096  /* compute value of z and reformnode and set in debug solution and expression graph, resp. */
5097 #ifdef SCIP_DEBUG_SOLUTION
5098  if( SCIPdebugIsMainscip(scip) )
5099  {
5100  SCIP_Real xval;
5101  SCIP_Real zval;
5102 
5103  SCIP_CALL( SCIPdebugGetSolVal(scip, x, &xval) );
5104  zval = signpowcoef * SIGN(xval + xoffset) * pow(REALABS(xval + xoffset), exponent) + constant;
5105 
5106  SCIP_CALL( SCIPdebugAddSolVal(scip, z, zval) );
5107  SCIPexprgraphSetVarNodeValue(*reformnode, zval);
5108  }
5109 #endif
5110  }
5111  else
5112  {
5113  /* if signpowcoef is huge, then avoid very small coefficient of z
5114  * instead create additional node on top of current reformnode */
5115  SCIP_EXPRGRAPHNODE* linnode;
5116 
5117  SCIP_CALL( SCIPcreateConsAbspower(scip, &cons, name,
5118  x, z, exponent, xoffset, -1.0, 0.0, 0.0,
5119  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
5120  SCIP_CALL( SCIPaddCons(scip, cons) );
5121  SCIPdebugPrintCons(scip, cons, NULL);
5122  ++*naddcons;
5123 
5124  /* compute value of z and reformnode and set in debug solution and expression graph, resp. */
5125 #ifdef SCIP_DEBUG_SOLUTION
5126  if( SCIPdebugIsMainscip(scip) )
5127  {
5128  SCIP_Real xval;
5129  SCIP_Real zval;
5130 
5131  SCIP_CALL( SCIPdebugGetSolVal(scip, x, &xval) );
5132  zval = SIGN(xval + xoffset) * pow(REALABS(xval + xoffset), exponent);
5133 
5134  SCIP_CALL( SCIPdebugAddSolVal(scip, z, zval) );
5135  SCIPexprgraphSetVarNodeValue(*reformnode, zval);
5136  }
5137 #endif
5138 
5139  SCIP_CALL( SCIPexprgraphCreateNodeLinear(SCIPblkmem(scip), &linnode, 1, &signpowcoef, constant) );
5140  SCIP_CALL( SCIPexprgraphAddNode(exprgraph, linnode, -1, 1, reformnode) );
5141 
5142  *reformnode = linnode;
5143  }
5144 
5145  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
5146  SCIP_CALL( SCIPreleaseVar(scip, &z) );
5147 
5148  return SCIP_OKAY;
5149 }
5150 
5151 /*
5152  * Callback methods of constraint handler
5153  */
5154 
5155 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
5156 static
5157 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyAbspower)
5158 { /*lint --e{715}*/
5159  assert(scip != NULL);
5160  assert(conshdlr != NULL);
5161  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5162 
5163  /* call inclusion method of constraint handler */
5165 
5166  *valid = TRUE;
5167 
5168  return SCIP_OKAY;
5169 }
5170 
5171 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
5172 static
5173 SCIP_DECL_CONSFREE(consFreeAbspower)
5174 { /*lint --e{715}*/
5175  SCIP_CONSHDLRDATA* conshdlrdata;
5176 
5177  assert(scip != NULL);
5178  assert(conshdlr != NULL);
5179 
5180  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5181  assert(conshdlrdata != NULL);
5182 
5183  SCIPfreeMemory(scip, &conshdlrdata);
5184 
5185  return SCIP_OKAY;
5186 }
5187 
5188 /** initialization method of constraint handler (called after problem was transformed) */
5189 static
5190 SCIP_DECL_CONSINIT(consInitAbspower)
5191 { /*lint --e{715}*/
5192  SCIP_CONSHDLRDATA* conshdlrdata;
5193 
5194  assert(scip != NULL);
5195  assert(conshdlr != NULL);
5196 
5197  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5198  assert(conshdlrdata != NULL);
5199 
5200  conshdlrdata->subnlpheur = SCIPfindHeur(scip, "subnlp");
5201  conshdlrdata->trysolheur = SCIPfindHeur(scip, "trysol");
5202  conshdlrdata->conshdlrindicator = SCIPfindConshdlr(scip, "indicator");
5203  conshdlrdata->nsecantcuts = 0;
5204  conshdlrdata->ncuts = 0;
5205 
5206  return SCIP_OKAY;
5207 }
5208 
5209 /** deinitialization method of constraint handler (called before transformed problem is freed) */
5210 static
5211 SCIP_DECL_CONSEXIT(consExitAbspower)
5212 { /*lint --e{715}*/
5213  SCIP_CONSHDLRDATA* conshdlrdata;
5214 
5215  assert(scip != NULL);
5216  assert(conshdlr != NULL);
5217 
5218  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5219  assert(conshdlrdata != NULL);
5220 
5221  conshdlrdata->subnlpheur = NULL;
5222  conshdlrdata->trysolheur = NULL;
5223  conshdlrdata->conshdlrindicator = NULL;
5224 
5225  return SCIP_OKAY;
5226 }
5227 
5228 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
5229 static
5230 SCIP_DECL_CONSINITPRE(consInitpreAbspower)
5231 { /*lint --e{715}*/
5232  SCIP_CONSHDLRDATA* conshdlrdata;
5233 
5234  assert(conshdlr != NULL);
5235 
5236  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5237  assert(conshdlrdata != NULL);
5238 
5239  /* initialize comparedpairwise flag to TRUE, if at most one constraint, otherwise 0 */
5240  conshdlrdata->comparedpairwise = (nconss <= 1);
5241 
5242  return SCIP_OKAY;
5243 }
5244 
5245 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
5246 static
5247 SCIP_DECL_CONSEXITPRE(consExitpreAbspower)
5248 { /*lint --e{715}*/
5249  int c;
5250 
5251  assert(scip != NULL);
5252  assert(conss != NULL || nconss == 0);
5253 
5254  /* tell SCIP that we have something nonlinear, and whether we are nonlinear in a continuous variable */
5255  for( c = 0; c < nconss; ++c )
5256  {
5257  assert(conss[c] != NULL); /*lint !e613*/
5258 
5259  if( SCIPconsIsAdded(conss[c]) ) /*lint !e613*/
5260  {
5261  SCIPenableNLP(scip);
5262  break;
5263  }
5264  }
5265 
5266  return SCIP_OKAY;
5267 }
5268 
5269 /** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
5270 static
5271 SCIP_DECL_CONSINITSOL(consInitsolAbspower)
5272 { /*lint --e{715}*/
5273  SCIP_CONSHDLRDATA* conshdlrdata;
5274  SCIP_CONSDATA* consdata;
5275  int c;
5276 
5277  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5278  assert(conshdlrdata != NULL);
5279 
5280  assert(scip != NULL);
5281  assert(conss != NULL || nconss == 0);
5282 
5283  for( c = 0; c < nconss; ++c )
5284  {
5285  assert(conss[c] != NULL); /*lint !e613*/
5286 
5287  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
5288  assert(consdata != NULL);
5289 
5290  assert(consdata->exponent > 1.0);
5291 
5292  /* setup root that corresponds to exponent */
5293  if( SCIPisIntegral(scip, consdata->exponent) && consdata->exponent-0.5 < ROOTS_KNOWN )
5294  {
5295  consdata->root = roots[(int)SCIPfloor(scip, consdata->exponent+0.5)];
5296  }
5297  else if( SCIPisEQ(scip, consdata->exponent, 1.852) )
5298  {
5299  consdata->root = 0.398217;
5300  }
5301  else
5302  {
5303  SCIP_Real root;
5304  SCIP_Real polyval;
5305  SCIP_Real gradval;
5306  int iter;
5307 
5308  /* search for a positive root of (n-1) y^n + n y^(n-1) - 1
5309  * use the closest precomputed root as starting value */
5310  if( consdata->exponent >= ROOTS_KNOWN )
5311  root = roots[ROOTS_KNOWN];
5312  else if( consdata->exponent <= 2.0 )
5313  root = roots[2];
5314  else
5315  root = roots[(int)SCIPfloor(scip, consdata->exponent)];
5316  iter = 0;
5317  do
5318  {
5319  polyval = (consdata->exponent - 1.0) * consdata->power(root, consdata->exponent) + consdata->exponent * pow(root, consdata->exponent-1.0) - 1.0;
5320  if( SCIPisZero(scip, polyval) )
5321  break;
5322 
5323  /* gradient of (n-1) y^n + n y^(n-1) - 1 is n(n-1)y^(n-1) + n(n-1)y^(n-2) */
5324  gradval = (consdata->exponent - 1.0) * consdata->exponent * (pow(root, consdata->exponent - 1.0) + pow(root, consdata->exponent - 2.0));
5325  if( SCIPisZero(scip, gradval) )
5326  break;
5327 
5328  /* update root by adding -polyval/gradval (Newton's method) */
5329  root -= polyval / gradval;
5330  if( root < 0.0 )
5331  root = 0.0;
5332  }
5333  while( ++iter < 1000 );
5334 
5335  if( !SCIPisZero(scip, polyval) )
5336  {
5337  SCIPerrorMessage("failed to compute root for exponent %g\n", consdata->exponent);
5338  return SCIP_ERROR;
5339  }
5340  SCIPdebugMessage("root for %g is %.20g, certainty = %g\n", consdata->exponent, root, polyval);
5341  /* @todo cache root value?? (they are actually really fast to compute...) */
5342 
5343  consdata->root = root;
5344  }
5345 
5346  /* add nlrow respresentation to NLP, if NLP had been constructed */
5347  if( SCIPisNLPConstructed(scip) && SCIPconsIsEnabled(conss[c]) ) /*lint !e613*/
5348  {
5349  if( consdata->nlrow == NULL )
5350  {
5351  SCIP_CALL( createNlRow(scip, conss[c]) ); /*lint !e613*/
5352  assert(consdata->nlrow != NULL);
5353  }
5354  SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
5355  }
5356  }
5357 
5358  conshdlrdata->newsoleventfilterpos = -1;
5359  if( nconss != 0 )
5360  {
5361  SCIP_EVENTHDLR* eventhdlr;
5362 
5363  eventhdlr = SCIPfindEventhdlr(scip, CONSHDLR_NAME"_newsolution");
5364  assert(eventhdlr != NULL);
5365 
5366  SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_SOLFOUND, eventhdlr, (SCIP_EVENTDATA*)conshdlr, &conshdlrdata->newsoleventfilterpos) );
5367  }
5368 
5369  /* reset flags and counters */
5370  conshdlrdata->sepanlp = FALSE;
5371  conshdlrdata->lastenfolpnode = NULL;
5372  conshdlrdata->nenfolprounds = 0;
5373 
5374  return SCIP_OKAY;
5375 }
5376 
5377 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
5378 static
5379 SCIP_DECL_CONSEXITSOL(consExitsolAbspower)
5380 { /*lint --e{715}*/
5381  SCIP_CONSHDLRDATA* conshdlrdata;
5382  SCIP_CONSDATA* consdata;
5383  int c;
5384 
5385  assert(scip != NULL);
5386  assert(conss != NULL || nconss == 0);
5387 
5388  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5389  assert(conshdlrdata != NULL);
5390 
5391  if( conshdlrdata->newsoleventfilterpos >= 0 )
5392  {
5393  SCIP_EVENTHDLR* eventhdlr;
5394 
5395  eventhdlr = SCIPfindEventhdlr(scip, CONSHDLR_NAME"_newsolution");
5396  assert(eventhdlr != NULL);
5397 
5398  SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_SOLFOUND, eventhdlr, (SCIP_EVENTDATA*)conshdlr, conshdlrdata->newsoleventfilterpos) );
5399  conshdlrdata->newsoleventfilterpos = -1;
5400  }
5401 
5402  for( c = 0; c < nconss; ++c )
5403  {
5404  assert(conss[c] != NULL); /*lint !e613*/
5405 
5406  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
5407  assert(consdata != NULL);
5408 
5409  /* free nonlinear row representation */
5410  if( consdata->nlrow != NULL )
5411  {
5412  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
5413  }
5414  }
5415 
5416  return SCIP_OKAY;
5417 }
5418 
5419 /** frees specific constraint data */
5420 static
5421 SCIP_DECL_CONSDELETE(consDeleteAbspower)
5422 { /*lint --e{715}*/
5423  assert(scip != NULL);
5424  assert(conshdlr != NULL);
5425  assert(cons != NULL);
5426  assert(consdata != NULL);
5427  assert((*consdata)->x != NULL);
5428  assert((*consdata)->z != NULL);
5429  assert((*consdata)->xeventfilterpos == -1);
5430  assert((*consdata)->zeventfilterpos == -1);
5431 
5432  if( (*consdata)->nlrow != NULL )
5433  {
5434  SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
5435  }
5436 
5437  SCIPfreeMemory(scip, consdata);
5438 
5439  return SCIP_OKAY;
5440 }
5441 
5442 /** transforms constraint data into data belonging to the transformed problem */
5443 static
5444 SCIP_DECL_CONSTRANS(consTransAbspower)
5445 { /*lint --e{715}*/
5446  SCIP_CONSDATA* sourcedata;
5447  SCIP_CONSDATA* targetdata;
5448 
5449  sourcedata = SCIPconsGetData(sourcecons);
5450  assert(sourcedata != NULL);
5451 
5452  SCIP_CALL( SCIPduplicateMemory(scip, &targetdata, sourcedata) );
5453  assert(targetdata->xeventfilterpos == -1);
5454  assert(targetdata->zeventfilterpos == -1);
5455 
5456  SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->x, &targetdata->x) );
5457  SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->z, &targetdata->z) );
5458 
5459  /* branching on multiaggregated variables does not seem to work well, so avoid multiagg. x */
5460  assert( SCIPvarIsActive(targetdata->x) );
5461  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, targetdata->x) );
5462 
5463  /* cannot propagate on multiaggregated vars, so avoid multiagg. z */
5464  assert( SCIPvarIsActive(targetdata->z) );
5465  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, targetdata->z) );
5466 
5467  /* create target constraint */
5468  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
5469  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
5470  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
5471  SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons),
5472  SCIPconsIsStickingAtNode(sourcecons)) );
5473 
5474  return SCIP_OKAY;
5475 }
5476 
5477 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved)
5478  *
5479  * we add secant underestimators
5480  */
5481 static
5482 SCIP_DECL_CONSINITLP(consInitlpAbspower)
5483 { /*lint --e{715}*/
5484  SCIP_CONSDATA* consdata;
5485  SCIP_CONSHDLRDATA* conshdlrdata;
5486  SCIP_Bool infeasible;
5487  SCIP_ROW* row;
5488  int c;
5489  SCIP_Real xlb;
5490  SCIP_Real xub;
5491 
5492  assert(scip != NULL);
5493  assert(conshdlr != NULL);
5494  assert(conss != NULL || nconss == 0);
5495 
5496  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5497  assert(conshdlrdata != NULL);
5498 
5499  for( c = 0; c < nconss; ++c )
5500  {
5501  assert(conss[c] != NULL); /*lint !e613*/
5502 
5503  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
5504  assert(consdata != NULL);
5505 
5506  xlb = SCIPvarGetLbGlobal(consdata->x);
5507  xub = SCIPvarGetUbGlobal(consdata->x);
5508 
5509  if( SCIPisRelEQ(scip, xlb, xub) )
5510  continue;
5511 
5512  if( !SCIPisInfinity(scip, consdata->rhs) )
5513  {
5514  if( !SCIPisInfinity(scip, -xlb) )
5515  {
5516  if( SCIPisNegative(scip, xlb + consdata->xoffset) )
5517  {
5518  /* generate secant between xlb and right changepoint */
5519  SCIP_CALL( generateSecantCutNoCheck(scip, &row, conshdlr, xlb, MIN(-consdata->root * (xlb+consdata->xoffset) - consdata->xoffset, xub),
5520  consdata->exponent, consdata->xoffset, consdata->power, 1.0, consdata->zcoef, consdata->rhs, consdata->x, consdata->z) );
5521  if( row != NULL )
5522  {
5523  if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) && SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row) < conshdlrdata->cutmaxrange )
5524  {
5525  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE /* forcecut */, &infeasible) );
5526  assert( ! infeasible );
5527 
5528  if( conshdlrdata->conshdlrindicator != NULL && !SCIProwIsLocal(row) )
5529  {
5530  SCIP_CALL( SCIPaddRowIndicator(scip, conshdlrdata->conshdlrindicator, row) );
5531  }
5532  }
5533  SCIP_CALL( SCIPreleaseRow(scip, &row) );
5534  }
5535  }
5536  else if( xlb < INITLPMAXVARVAL )
5537  {
5538  /* generate tangent in lower bound */
5539  SCIP_CALL( generateLinearizationCut(scip, &row, conshdlr, xlb, consdata->exponent, consdata->xoffset, 1.0, consdata->zcoef, consdata->rhs,
5540  consdata->x, consdata->z, FALSE) );
5541  assert(row != NULL);
5542  if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) && SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row) < conshdlrdata->cutmaxrange )
5543  {
5544  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE /* forcecut */, &infeasible) );
5545  assert( ! infeasible );
5546 
5547  if( conshdlrdata->conshdlrindicator != NULL )
5548  {
5549  SCIP_CALL( SCIPaddRowIndicator(scip, conshdlrdata->conshdlrindicator, row) );
5550  }
5551  }
5552  SCIP_CALL( SCIPreleaseRow(scip, &row) );
5553  }
5554  }
5555 
5556  if( !SCIPisInfinity(scip, xub) )
5557  {
5558  /* generate tangent in upper bound */
5559  if( -consdata->root * (xlb+consdata->xoffset) - consdata->xoffset < xub && xub <= INITLPMAXVARVAL )
5560  {
5561  SCIP_CALL( generateLinearizationCut(scip, &row, conshdlr, xub, consdata->exponent, consdata->xoffset, 1.0, consdata->zcoef, consdata->rhs,
5562  consdata->x, consdata->z, FALSE) );
5563  assert(row != NULL);
5564  if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) && SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row) < conshdlrdata->cutmaxrange )
5565  {
5566  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE /* forcecut */, &infeasible) );
5567  assert( ! infeasible );
5568 
5569  if( conshdlrdata->conshdlrindicator != NULL )
5570  {
5571  SCIP_CALL( SCIPaddRowIndicator(scip, conshdlrdata->conshdlrindicator, row) );
5572  }
5573  }
5574  SCIP_CALL( SCIPreleaseRow(scip, &row) );
5575  }
5576  }
5577  }
5578 
5579  if( !SCIPisInfinity(scip, -consdata->lhs) )
5580  {
5581  if( !SCIPisInfinity(scip, xub) )
5582  {
5583  if( SCIPisPositive(scip, xub + consdata->xoffset) )
5584  {
5585  /* generate secant between left change point and upper bound */
5586  SCIP_CALL( generateSecantCutNoCheck(scip, &row, conshdlr, -xub, MIN(consdata->root * (xub+consdata->xoffset) + consdata->xoffset, -xlb),
5587  consdata->exponent, -consdata->xoffset, consdata->power, -1.0, -consdata->zcoef, -consdata->lhs, consdata->x, consdata->z) );
5588  if( row != NULL )
5589  {
5590  if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) && SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row) < conshdlrdata->cutmaxrange )
5591  {
5592  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE /* forcecut */, &infeasible) );
5593  assert( ! infeasible );
5594 
5595  if( conshdlrdata->conshdlrindicator != NULL && !SCIProwIsLocal(row) )
5596  {
5597  SCIP_CALL( SCIPaddRowIndicator(scip, conshdlrdata->conshdlrindicator, row) );
5598  }
5599  }
5600  SCIP_CALL( SCIPreleaseRow(scip, &row) );
5601  }
5602  }
5603  else if( xub >= -INITLPMAXVARVAL )
5604  {
5605  /* generate tangent in upper bound */
5606  SCIP_CALL( generateLinearizationCut(scip, &row, conshdlr, -xub, consdata->exponent, -consdata->xoffset, -1.0, -consdata->zcoef, -consdata->lhs,
5607  consdata->x, consdata->z, FALSE) );
5608  assert(row != NULL);
5609  if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) && SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row) < conshdlrdata->cutmaxrange )
5610  {
5611  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE /* forcecut */, &infeasible) );
5612  assert( ! infeasible );
5613 
5614  if( conshdlrdata->conshdlrindicator != NULL )
5615  {
5616  SCIP_CALL( SCIPaddRowIndicator(scip, conshdlrdata->conshdlrindicator, row) );
5617  }
5618  }
5619  SCIP_CALL( SCIPreleaseRow(scip, &row) );
5620  }
5621  }
5622 
5623  if( !SCIPisInfinity(scip, -xlb) )
5624  {
5625  /* generate tangent in lower bound */
5626  if( -consdata->root * (xub+consdata->xoffset) - consdata->xoffset > xlb && xlb >= -INITLPMAXVARVAL )
5627  {
5628  SCIP_CALL( generateLinearizationCut(scip, &row, conshdlr, -xlb, consdata->exponent, -consdata->xoffset, -1.0, -consdata->zcoef, -consdata->lhs,
5629  consdata->x, consdata->z, FALSE) );
5630  assert(row != NULL);
5631  if( !SCIPisInfinity(scip, SCIProwGetRhs(row)) && SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row) < conshdlrdata->cutmaxrange )
5632  {
5633  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE /* forcecut */, &infeasible) );
5634  assert( ! infeasible );
5635 
5636  if( conshdlrdata->conshdlrindicator != NULL )
5637  {
5638  SCIP_CALL( SCIPaddRowIndicator(scip, conshdlrdata->conshdlrindicator, row) );
5639  }
5640  }
5641  SCIP_CALL( SCIPreleaseRow(scip, &row) );
5642  }
5643  }
5644  }
5645  }
5646 
5647  return SCIP_OKAY;
5648 }
5649 
5650 /** separation method of constraint handler for LP solutions */
5651 static
5652 SCIP_DECL_CONSSEPALP(consSepalpAbspower)
5653 { /*lint --e{715}*/
5654  SCIP_CONSHDLRDATA* conshdlrdata;
5655  SCIP_CONS* maxviolcon;
5656  SCIP_Bool success;
5657  SCIP_Bool cutoff;
5658 
5659  assert(scip != NULL);
5660  assert(conshdlr != NULL);
5661  assert(conss != NULL || nconss == 0);
5662  assert(result != NULL);
5663 
5664  *result = SCIP_DIDNOTFIND;
5665 
5666  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5667  assert(conshdlrdata != NULL);
5668 
5669  SCIP_CALL( computeViolations(scip, conshdlr, conss, nconss, NULL, &maxviolcon) );
5670  if( maxviolcon == NULL )
5671  return SCIP_OKAY;
5672 
5673  /* at root, check if we want to solve the NLP relaxation and use its solutions as reference point
5674  * if there is something convex, then linearizing in the solution of the NLP relaxation can be very useful
5675  */
5676  if( SCIPgetDepth(scip) == 0 && !conshdlrdata->sepanlp &&
5677  (SCIPgetNContVars(scip) >= conshdlrdata->sepanlpmincont * SCIPgetNVars(scip) || (SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_UNBOUNDEDRAY && conshdlrdata->sepanlpmincont <= 1.0)) &&
5678  SCIPisNLPConstructed(scip) && SCIPgetNNlpis(scip) > 0 )
5679  {
5680  SCIP_CONSDATA* consdata;
5681  SCIP_NLPSOLSTAT solstat;
5682  SCIP_Bool solvednlp;
5683  int c;
5684 
5685  solstat = SCIPgetNLPSolstat(scip);
5686  solvednlp = FALSE;
5687  if( solstat == SCIP_NLPSOLSTAT_UNKNOWN )
5688  {
5689  /* NLP is not solved yet, so we might want to do this
5690  * but first check whether there is a violated constraint side which corresponds to a convex function
5691  * @todo put this check into initsol and update via consenable/consdisable
5692  */
5693  for( c = 0; c < nconss; ++c )
5694  {
5695  assert(conss[c] != NULL); /*lint !e613*/
5696 
5697  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
5698  assert(consdata != NULL);
5699 
5700  /* skip feasible constraints */
5701  if( !SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) && !SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
5702  continue;
5703 
5704  if( (!SCIPisGT(scip, SCIPvarGetUbGlobal(consdata->x), -consdata->xoffset) && !SCIPisInfinity(scip, -consdata->lhs)) ||
5705  ( !SCIPisLT(scip, SCIPvarGetLbGlobal(consdata->x), -consdata->xoffset) && !SCIPisInfinity(scip, -consdata->rhs)) )
5706  break;
5707  }
5708 
5709  if( c < nconss )
5710  {
5711  /* try to solve NLP and update solstat */
5712 
5713  /* ensure linear conss are in NLP */
5714  if( conshdlrdata->subnlpheur != NULL )
5715  {
5716  SCIP_CALL( SCIPaddLinearConsToNlpHeurSubNlp(scip, conshdlrdata->subnlpheur, TRUE, TRUE) );
5717  }
5718 
5719  /* set LP solution as starting values, if available */
5721  {
5723  }
5724 
5725  /* SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_VERBLEVEL, 1) ); */
5726  SCIP_CALL( SCIPsolveNLP(scip) );
5727 
5728  solstat = SCIPgetNLPSolstat(scip);
5729  SCIPdebugMessage("solved NLP relax, solution status: %d\n", solstat);
5730 
5731  solvednlp = TRUE;
5732  }
5733  }
5734 
5735  conshdlrdata->sepanlp = TRUE;
5736 
5737  if( solstat == SCIP_NLPSOLSTAT_GLOBINFEASIBLE )
5738  {
5739  SCIPdebugMessage("NLP relaxation is globally infeasible, thus can cutoff node\n");
5740  *result = SCIP_CUTOFF;
5741  return SCIP_OKAY;
5742  }
5743 
5744  if( solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
5745  {
5746  /* if we have feasible NLP solution, generate linearization cuts there */
5747  SCIP_Bool lpsolseparated;
5748  SCIP_SOL* nlpsol;
5749 
5750  SCIP_CALL( SCIPcreateNLPSol(scip, &nlpsol, NULL) );
5751  assert(nlpsol != NULL);
5752 
5753  /* if we solved the NLP and solution is integral, then pass it to trysol heuristic */
5754  if( solvednlp && conshdlrdata->trysolheur != NULL )
5755  {
5756  int nfracvars;
5757 
5758  nfracvars = 0;
5759  if( SCIPgetNBinVars(scip) > 0 || SCIPgetNIntVars(scip) > 0 )
5760  {
5761  SCIP_CALL( SCIPgetNLPFracVars(scip, NULL, NULL, NULL, &nfracvars, NULL) );
5762  }
5763 
5764  if( nfracvars == 0 )
5765  {
5766  SCIP_CALL( SCIPheurPassSolTrySol(scip, conshdlrdata->trysolheur, nlpsol) );
5767  }
5768  }
5769 
5770  SCIP_CALL( addLinearizationCuts(scip, conshdlr, conss, nconss, nlpsol, &lpsolseparated, conshdlrdata->mincutefficacysepa) );
5771 
5772  SCIP_CALL( SCIPfreeSol(scip, &nlpsol) );
5773 
5774  /* if a cut that separated the LP solution was added, then return, otherwise continue with usual separation in LP solution */
5775  if( lpsolseparated )
5776  {
5777  SCIPdebugMessage("linearization cuts separate LP solution\n");
5778 
5779  *result = SCIP_SEPARATED;
5780 
5781  return SCIP_OKAY;
5782  }
5783  }
5784  }
5785  /* if we do not want to try solving the NLP, or have no NLP, or have no NLP solver, or solving the NLP failed,
5786  * or separating with NLP solution as reference point failed, then try (again) with LP solution as reference point
5787  */
5788 
5789  SCIP_CALL( separatePoint(scip, conshdlr, conss, nconss, nusefulconss, NULL, conshdlrdata->mincutefficacysepa, FALSE, conshdlrdata->sepainboundsonly, &success, &cutoff, NULL) );
5790  if( cutoff )
5791  *result = SCIP_CUTOFF;
5792  else if( success )
5793  *result = SCIP_SEPARATED;
5794 
5795  return SCIP_OKAY;
5796 }
5797 
5798 /** separation method of constraint handler for arbitrary primal solutions */
5799 static
5800 SCIP_DECL_CONSSEPASOL(consSepasolAbspower)
5801 { /*lint --e{715}*/
5802  SCIP_CONSHDLRDATA* conshdlrdata;
5803  SCIP_CONS* maxviolcon;
5804  SCIP_Bool success;
5805  SCIP_Bool cutoff;
5806 
5807  assert(scip != NULL);
5808  assert(conshdlr != NULL);
5809  assert(conss != NULL || nconss == 0);
5810  assert(sol != NULL);
5811  assert(result != NULL);
5812 
5813  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5814  assert(conshdlrdata != NULL);
5815 
5816  *result = SCIP_DIDNOTFIND;
5817 
5818  SCIP_CALL( computeViolations(scip, conshdlr, conss, nconss, sol, &maxviolcon) );
5819  if( maxviolcon == NULL )
5820  return SCIP_OKAY;
5821 
5822  SCIP_CALL( separatePoint(scip, conshdlr, conss, nconss, nusefulconss, sol, conshdlrdata->mincutefficacysepa, FALSE, FALSE, &success, &cutoff, NULL) );
5823  if( cutoff )
5824  *result = SCIP_CUTOFF;
5825  else if( success )
5826  *result = SCIP_SEPARATED;
5827 
5828  return SCIP_OKAY;
5829 }
5830 
5831 /** constraint enforcing method of constraint handler for LP solutions */
5832 static
5833 SCIP_DECL_CONSENFOLP(consEnfolpAbspower)
5834 { /*lint --e{715}*/
5835  SCIP_CONSHDLRDATA* conshdlrdata;
5836  SCIP_CONS* maxviolcons;
5837  SCIP_CONSDATA* consdata;
5838  SCIP_Bool success;
5839  SCIP_Bool cutoff;
5840  SCIP_Real minefficacy;
5841  SCIP_Real sepaefficacy;
5842  SCIP_Real leastpossibleefficacy;
5843  SCIP_Real maxviol;
5844  int nnotify;
5845  int c;
5846 
5847  assert(scip != NULL);
5848  assert(conshdlr != NULL);
5849  assert(conss != NULL || nconss == 0);
5850  assert(result != NULL);
5851 
5852  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5853  assert(conshdlrdata != NULL);
5854 
5855  SCIP_CALL( computeViolations(scip, conshdlr, conss, nconss, NULL, &maxviolcons) );
5856 
5857  if( maxviolcons == NULL )
5858  {
5859  *result = SCIP_FEASIBLE;
5860  return SCIP_OKAY;
5861  }
5862 
5863  *result = SCIP_INFEASIBLE;
5864 
5865  /* if we are above the 100'th enforcement round for this node, something is strange
5866  * (maybe the LP does not think that the cuts we add are violated, or we do ECP on a high-dimensional convex function)
5867  * in this case, check if some limit is hit or SCIP should stop for some other reason and terminate enforcement by creating a dummy node
5868  * (in optimized more, returning SCIP_INFEASIBLE in *result would be sufficient, but in debug mode this would give an assert in scip.c)
5869  * the reason to wait for 100 rounds is to avoid calls to SCIPisStopped in normal runs, which may be expensive
5870  * we only increment nenfolprounds until 101 to avoid an overflow
5871  */
5872  if( conshdlrdata->lastenfolpnode == SCIPgetCurrentNode(scip) )
5873  {
5874  if( conshdlrdata->nenfolprounds > 100 )
5875  {
5876  if( SCIPisStopped(scip) )
5877  {
5878  SCIP_NODE* child;
5879 
5880  SCIP_CALL( SCIPcreateChild(scip, &child, 1.0, SCIPnodeGetEstimate(SCIPgetCurrentNode(scip))) );
5881  *result = SCIP_BRANCHED;
5882 
5883  return SCIP_OKAY;
5884  }
5885  }
5886  else
5887  ++conshdlrdata->nenfolprounds;
5888  }
5889  else
5890  {
5891  conshdlrdata->lastenfolpnode = SCIPgetCurrentNode(scip);
5892  conshdlrdata->nenfolprounds = 0;
5893  }
5894 
5895  /* run domain propagation for violated constraints */
5896  for( c = 0; c < nconss; ++c )
5897  {
5898  int nchgbds;
5899  int naddconss;
5900 
5901  assert(conss[c] != NULL); /*lint !e613*/
5902 
5903  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
5904  assert(consdata != NULL);
5905 
5906  if( !SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) && !SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
5907  continue;
5908 
5909  nchgbds = 0;
5910  naddconss = 0;
5911  SCIP_CALL( propagateCons(scip, conshdlr, conss[c], TRUE, &cutoff, &nchgbds, &naddconss) ); /*lint !e613*/
5912  if( cutoff )
5913  {
5914  *result = SCIP_CUTOFF;
5915  return SCIP_OKAY;
5916  }
5917  if( nchgbds )
5918  *result = SCIP_REDUCEDDOM;
5919  if( naddconss )
5920  *result = SCIP_CONSADDED;
5921  }
5922  if( *result == SCIP_REDUCEDDOM || *result == SCIP_CONSADDED )
5923  return SCIP_OKAY;
5924 
5925  consdata = SCIPconsGetData(maxviolcons);
5926  assert(consdata != NULL);
5927  maxviol = consdata->lhsviol + consdata->rhsviol;
5928  assert(SCIPisGT(scip, maxviol, SCIPfeastol(scip)));
5929 
5930  /* we would like a cut that is efficient enough that it is not redundant in the LP (>feastol)
5931  * however, if the maximal violation is very small, also the best cut efficacy cannot be large
5932  * thus, in the latter case, we are also happy if the efficacy is at least, say, 75% of the maximal violation
5933  * but in any case we need an efficacy that is at least feastol
5934  */
5935  minefficacy = MIN(0.75*maxviol, conshdlrdata->mincutefficacyenfofac * SCIPfeastol(scip)); /*lint !e666*/
5936  minefficacy = MAX(minefficacy, SCIPfeastol(scip)); /*lint !e666*/
5937  SCIP_CALL( separatePoint(scip, conshdlr, conss, nconss, nusefulconss, NULL, minefficacy, TRUE, FALSE, &success, &cutoff, &sepaefficacy) );
5938  if( cutoff )
5939  {
5940  SCIPdebugMessage("separation detected cutoff.\n");
5941  *result = SCIP_CUTOFF;
5942  return SCIP_OKAY;
5943  }
5944  if( success )
5945  {
5946  SCIPdebugMessage("separation succeeded (bestefficacy = %g, minefficacy = %g)\n", sepaefficacy, minefficacy);
5947  *result = SCIP_SEPARATED;
5948  return SCIP_OKAY;
5949  }
5950  SCIPdebugMessage("separation failed (bestefficacy = %g < %g = minefficacy ); max viol: %g\n", sepaefficacy, minefficacy, maxviol);
5951 
5952  /* we are not feasible, the whole node is not infeasible, and we cannot find a reasonable cut
5953  * -> collect variables for branching
5954  */
5955  SCIP_CALL( registerBranchingCandidates(scip, conshdlr, conss, nconss, &nnotify) );
5956 
5957  /* if sepastore can decrease LP feasibility tolerance, we can add cuts with efficacy in [eps, feastol] */
5958  leastpossibleefficacy = SCIPgetRelaxFeastolFactor(scip) > 0.0 ? SCIPepsilon(scip) : SCIPfeastol(scip);
5959  if( nnotify == 0 && !solinfeasible && minefficacy > leastpossibleefficacy )
5960  {
5961  /* fallback 1: we also have no branching candidates, so try to find a weak cut */
5962  SCIP_CALL( separatePoint(scip, conshdlr, conss, nconss, nusefulconss, NULL, leastpossibleefficacy, TRUE, FALSE, &success, &cutoff, &sepaefficacy) );
5963  if( cutoff )
5964  {
5965  SCIPdebugMessage("separation detected cutoff.\n");
5966  *result = SCIP_CUTOFF;
5967  return SCIP_OKAY;
5968  }
5969  if( success )
5970  {
5971  *result = SCIP_SEPARATED;
5972  return SCIP_OKAY;
5973  }
5974  }
5975 
5976  if( nnotify == 0 && !solinfeasible )
5977  {
5978  /* fallback 2: separation probably failed because of numerical difficulties with a convex constraint;
5979  if noone declared solution infeasible yet and we had not even found a weak cut, try to resolve by branching */
5980  SCIP_VAR* brvar = NULL;
5981  SCIP_CALL( registerLargeLPValueVariableForBranching(scip, conss, nconss, &brvar) );
5982  if( brvar == NULL )
5983  {
5984  SCIPwarningMessage(scip, "Could not find any branching variable candidate. Cutting off node. Max viol = %g.\n", SCIPconsGetData(maxviolcons)->lhsviol+SCIPconsGetData(maxviolcons)->rhsviol);
5985  *result = SCIP_CUTOFF;
5986  return SCIP_OKAY;
5987  }
5988  else
5989  {
5990  SCIPdebugMessage("Could not find any usual branching variable candidate. Proposed variable %s with LP value %g for branching. Max. viol. cons. <%s>: %g+%g\n", SCIPvarGetName(brvar), SCIPgetSolVal(scip, NULL, brvar), SCIPconsGetName(maxviolcons), SCIPconsGetData(maxviolcons)->lhsviol, SCIPconsGetData(maxviolcons)->rhsviol);
5991  nnotify = 1;
5992  }
5993  }
5994 
5995  assert(*result == SCIP_INFEASIBLE && (solinfeasible || nnotify > 0));
5996  return SCIP_OKAY;
5997 }
5998 
5999 
6000 /** constraint enforcing method of constraint handler for pseudo solutions */
6001 static
6002 SCIP_DECL_CONSENFOPS(consEnfopsAbspower)
6003 { /*lint --e{715}*/
6004  SCIP_CONSHDLRDATA* conshdlrdata;
6005  SCIP_CONS* maxviolcon;
6006  SCIP_CONSDATA* consdata;
6007  int c;
6008  int nnotify;
6009 
6010  assert(scip != NULL);
6011  assert(conshdlr != NULL);
6012  assert(conss != NULL || nconss == 0);
6013 
6014  conshdlrdata = SCIPconshdlrGetData(conshdlr);
6015  assert(conshdlrdata != NULL);
6016 
6017  SCIP_CALL( computeViolations(scip, conshdlr, conss, nconss, NULL, &maxviolcon) );
6018  if( maxviolcon == NULL )
6019  {
6020  *result = SCIP_FEASIBLE;
6021  return SCIP_OKAY;
6022  }
6023 
6024  *result = SCIP_INFEASIBLE;
6025 
6026  /* run domain propagation for violated constraints */
6027  for( c = 0; c < nconss; ++c )
6028  {
6029  SCIP_Bool cutoff;
6030  int nchgbds;
6031  int naddconss;
6032 
6033  assert(conss[c] != NULL); /*lint !e613*/
6034 
6035  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
6036  assert(consdata != NULL);
6037 
6038  if( !SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) && !SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
6039  continue;
6040 
6041  nchgbds = 0;
6042  naddconss = 0;
6043  SCIP_CALL( propagateCons(scip, conshdlr, conss[c], TRUE, &cutoff, &nchgbds, &naddconss) ); /*lint !e613*/
6044  if( cutoff )
6045  {
6046  *result = SCIP_CUTOFF;
6047  return SCIP_OKAY;
6048  }
6049  if( nchgbds )
6050  *result = SCIP_REDUCEDDOM;
6051  if( naddconss )
6052  *result = SCIP_CONSADDED;
6053  }
6054  if( *result == SCIP_REDUCEDDOM || *result == SCIP_CONSADDED )
6055  return SCIP_OKAY;
6056 
6057  /* we are not feasible and we cannot proof that the whole node is infeasible
6058  * -> branch on all unfixed variables in violated constraints
6059  */
6060  nnotify = 0;
6061  for( c = 0; c < nconss; ++c )
6062  {
6063  assert(conss != NULL);
6064  consdata = SCIPconsGetData(conss[c]);
6065  assert(consdata != NULL);
6066  SCIPdebugMessage("cons <%s> violation: %g %g\n", SCIPconsGetName(conss[c]), consdata->lhsviol, consdata->rhsviol);
6067 
6068  if( !SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) && !SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
6069  continue;
6070 
6071  SCIPdebugMessage("cons <%s> violation: %g %g\n", SCIPconsGetName(conss[c]), consdata->lhsviol, consdata->rhsviol);
6072 
6073  /* domain propagation should have removed cons when x is fixed */
6074  assert(!SCIPisRelEQ(scip, SCIPvarGetLbLocal(consdata->x), SCIPvarGetUbLocal(consdata->x)));
6075 
6076  SCIP_CALL( SCIPaddExternBranchCand(scip, consdata->x, consdata->lhsviol + consdata->rhsviol, proposeBranchingPoint(scip, conss[c], conshdlrdata->preferzerobranch, conshdlrdata->branchminconverror)) );
6077  ++nnotify;
6078  }
6079 
6080  if( nnotify == 0 )
6081  {
6082  SCIPdebugMessage("All variables in violated constraints fixed (up to epsilon). Cannot find branching candidate. Forcing solution of LP.\n");
6083  *result = SCIP_SOLVELP;
6084  }
6085 
6086  assert(*result == SCIP_SOLVELP || (*result == SCIP_INFEASIBLE && nnotify > 0));
6087  return SCIP_OKAY;
6088 }
6089 
6090 
6091 /** domain propagation method of constraint handler */
6092 static
6093 SCIP_DECL_CONSPROP(consPropAbspower)
6094 { /*lint --e{715}*/
6095  int c;
6096  int nchgbds;
6097  int naddconss;
6098  SCIP_Bool cutoff = FALSE;
6099 
6100  assert(scip != NULL);
6101  assert(conshdlr != NULL);
6102  assert(conss != NULL || nconss == 0);
6103  assert(result != NULL);
6104 
6105  *result = SCIP_DIDNOTFIND;
6106 
6107  for( c = 0; c < nconss; ++c )
6108  {
6109  assert(conss != NULL);
6110 
6111  /* propagate constraint, but do not allow to add a constraint for tightening a multiaggregated variable (not allowed in CONSPROP) */
6112  nchgbds = 0;
6113  naddconss = 0;
6114  SCIP_CALL( propagateCons(scip, conshdlr, conss[c], FALSE, &cutoff, &nchgbds, &naddconss) );
6115  assert(naddconss == 0);
6116 
6117  if( cutoff )
6118  {
6119  *result = SCIP_CUTOFF;
6120  break;
6121  }
6122 
6123  if( nchgbds )
6124  *result = SCIP_REDUCEDDOM;
6125 
6126  if( c >= nusefulconss && *result != SCIP_DIDNOTFIND )
6127  break;
6128  }
6129 
6130  return SCIP_OKAY;
6131 }
6132 
6133 /** presolving method of constraint handler */
6134 static
6135 SCIP_DECL_CONSPRESOL(consPresolAbspower)
6136 { /*lint --e{715}*/
6137  SCIP_CONSHDLRDATA* conshdlrdata;
6138  SCIP_CONSDATA* consdata;
6139  SCIP_RESULT replaceresult;
6140  SCIP_Bool success;
6141  SCIP_Bool infeas;
6142  int localnchgbds;
6143  int localnaddconss;
6144  int c;
6145 
6146  assert(scip != NULL);
6147  assert(conss != NULL || nconss == 0);
6148  assert(result != NULL);
6149 
6150  conshdlrdata = SCIPconshdlrGetData(conshdlr);
6151  assert(conshdlrdata != NULL);
6152 
6153  *result = SCIP_DIDNOTFIND;
6154 
6155  /* check for duplicates, if not done yet or if absolute power constraints were modified (variable fixings) or new absolute power constraints had been added */
6156  if( !conshdlrdata->comparedpairwise )
6157  {
6158  SCIP_CALL( presolveFindDuplicates(scip, conshdlr, conss, nconss, nupgdconss, ndelconss, naddconss, nfixedvars, naggrvars, &success, &infeas) );
6159  if( infeas )
6160  {
6161  *result = SCIP_CUTOFF;
6162  return SCIP_OKAY;
6163  }
6164  if( success )
6165  {
6166  *result = SCIP_SUCCESS;
6167  }
6168  }
6169 
6170  for( c = 0; c < nconss; ++c )
6171  {
6172  assert(conss[c] != NULL); /*lint !e613*/
6173 
6174  if( SCIPconsIsDeleted(conss[c]) ) /*lint !e613*/
6175  continue;
6176 
6177  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
6178  assert(consdata != NULL);
6179 
6180  SCIPdebugMessage("presolving constraint <%s>\n", SCIPconsGetName(conss[c])); /*lint !e613*/
6181  SCIPdebugPrintCons(scip, conss[c], NULL); /*lint !e613*/
6182 
6183  /* check if we can upgrade to a linear constraint */
6184  if( consdata->exponent == 1.0 )
6185  {
6186  SCIP_VAR* vars[2];
6187  SCIP_Real coefs[2];
6188  SCIP_CONS* lincons;
6189  SCIP_Real lhs;
6190  SCIP_Real rhs;
6191 
6192  vars[0] = consdata->x;
6193  vars[1] = consdata->z;
6194  coefs[0] = 1.0;
6195  coefs[1] = consdata->zcoef;
6196  lhs = consdata->lhs;
6197  rhs = consdata->rhs;
6198  if( !SCIPisInfinity(scip, -lhs) )
6199  lhs -= consdata->xoffset;
6200  if( !SCIPisInfinity(scip, rhs) )
6201  rhs -= consdata->xoffset;
6202 
6203  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(conss[c]), 2, vars, coefs, lhs, rhs,
6204  SCIPconsIsInitial(conss[c]), SCIPconsIsSeparated(conss[c]), SCIPconsIsEnforced(conss[c]),
6205  SCIPconsIsChecked(conss[c]), SCIPconsIsPropagated(conss[c]), SCIPconsIsLocal(conss[c]),
6206  SCIPconsIsModifiable(conss[c]), SCIPconsIsDynamic(conss[c]), SCIPconsIsRemovable(conss[c]),
6207  SCIPconsIsStickingAtNode(conss[c])) ); /*lint !e613*/
6208  SCIP_CALL( SCIPaddCons(scip, lincons) );
6209  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
6210 
6211  SCIP_CALL( SCIPdelCons(scip, conss[c]) ); /*lint !e613*/
6212  ++*nupgdconss;
6213  continue;
6214  }
6215 
6216  /* check for fixed variables */
6217  replaceresult = SCIP_DIDNOTFIND;
6218  SCIP_CALL( checkFixedVariables(scip, conshdlr, conss[c], ndelconss, nupgdconss, nchgbds, nfixedvars, &replaceresult) ); /*lint !e613*/
6219  switch( replaceresult )
6220  {
6221  case SCIP_DIDNOTFIND:
6222  break;
6223 
6224  case SCIP_CUTOFF:
6225  *result = SCIP_CUTOFF;
6226  return SCIP_OKAY;
6227 
6228  case SCIP_REDUCEDDOM:
6229  case SCIP_CONSADDED:
6230  *result = SCIP_SUCCESS;
6231  break;
6232 
6233  default:
6234  SCIPerrorMessage("invalid result from checkFixedVariables\n");
6235  SCIPABORT();
6236  return SCIP_INVALIDDATA; /*lint !e527*/
6237  } /*lint !e788*/
6238 
6239  if( SCIPconsIsDeleted(conss[c]) ) /*lint !e613*/
6240  {
6241  *result = SCIP_SUCCESS;
6242  continue;
6243  }
6244 
6245  /* another check for upgrading to a varbound constraint */
6246  if( SCIPvarIsBinary(consdata->x) )
6247  {
6248  SCIP_CONS* lincons;
6249  SCIP_Real lhs;
6250  SCIP_Real rhs;
6251  SCIP_Real zcoef;
6252 
6253  /* for binary variable x,
6254  * sign(x+offset)|x+offset|^n = sign(offset)|offset|^n * (1-x) + sign(offset+1) |offset+1|^n x
6255  * = sign(offset)|offset|^n + (sign(offset+1) |offset+1|^n - sign(offset)|offset|^n) * x
6256  * => constraint is lhs <= sign(offset)|offset|^n + (sign(offset+1) |offset+1|^n - sign(offset)|offset|^n) * x + c*z <= rhs
6257  * upgrade to varbound constraint if z is not continuous, otherwise linear
6258  */
6259  if( consdata->xoffset != 0.0 )
6260  {
6261  SCIP_Real xcoef;
6262 
6263  xcoef = SIGN(consdata->xoffset + 1.0) * consdata->power(ABS(consdata->xoffset + 1.0), consdata->exponent)
6264  -SIGN(consdata->xoffset) * consdata->power(ABS(consdata->xoffset), consdata->exponent);
6265 
6266  if( xcoef < 0.0 )
6267  {
6268  if( SCIPisInfinity(scip, consdata->rhs) )
6269  lhs = -SCIPinfinity(scip);
6270  else
6271  lhs = (consdata->rhs - SIGN(consdata->xoffset) * consdata->power(ABS(consdata->xoffset), consdata->exponent)) / xcoef;
6272  if( SCIPisInfinity(scip, -consdata->lhs) )
6273  rhs = SCIPinfinity(scip);
6274  else
6275  rhs = (consdata->lhs - SIGN(consdata->xoffset) * consdata->power(ABS(consdata->xoffset), consdata->exponent)) / xcoef;
6276  }
6277  else
6278  {
6279  if( SCIPisInfinity(scip, -consdata->lhs) )
6280  lhs = -SCIPinfinity(scip);
6281  else
6282  lhs = (consdata->lhs - SIGN(consdata->xoffset) * consdata->power(ABS(consdata->xoffset), consdata->exponent)) / xcoef;
6283  if( SCIPisInfinity(scip, consdata->rhs) )
6284  rhs = SCIPinfinity(scip);
6285  else
6286  rhs = (consdata->rhs - SIGN(consdata->xoffset) * consdata->power(ABS(consdata->xoffset), consdata->exponent)) / xcoef;
6287  }
6288  zcoef = consdata->zcoef / xcoef;
6289  }
6290  else
6291  {
6292  lhs = consdata->lhs;
6293  rhs = consdata->rhs;
6294  zcoef = consdata->zcoef;
6295  }
6296 
6297  if( SCIPvarGetType(consdata->z) < SCIP_VARTYPE_CONTINUOUS )
6298  {
6299  SCIP_CALL( SCIPcreateConsVarbound(scip, &lincons, SCIPconsGetName(conss[c]),
6300  consdata->x, consdata->z, zcoef, lhs, rhs,
6301  SCIPconsIsInitial(conss[c]), SCIPconsIsSeparated(conss[c]), SCIPconsIsEnforced(conss[c]),
6302  SCIPconsIsChecked(conss[c]), SCIPconsIsPropagated(conss[c]), SCIPconsIsLocal(conss[c]),
6303  SCIPconsIsModifiable(conss[c]), SCIPconsIsDynamic(conss[c]), SCIPconsIsRemovable(conss[c]),
6304  SCIPconsIsStickingAtNode(conss[c])) ); /*lint !e613*/
6305  }
6306  else
6307  {
6308  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(conss[c]),
6309  1, &consdata->z, &zcoef, lhs, rhs,
6310  SCIPconsIsInitial(conss[c]), SCIPconsIsSeparated(conss[c]), SCIPconsIsEnforced(conss[c]),
6311  SCIPconsIsChecked(conss[c]), SCIPconsIsPropagated(conss[c]), SCIPconsIsLocal(conss[c]),
6312  SCIPconsIsModifiable(conss[c]), SCIPconsIsDynamic(conss[c]), SCIPconsIsRemovable(conss[c]),
6313  SCIPconsIsStickingAtNode(conss[c])) ); /*lint !e613*/
6314  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->x, 1.0) );
6315  }
6316  SCIP_CALL( SCIPaddCons(scip, lincons) );
6317 
6318  SCIPdebugMessage("upgraded constraint <%s> to linear constraint due to binary x-variable\n", SCIPconsGetName(conss[c])); /*lint !e613*/
6319  SCIPdebugPrintCons(scip, conss[c], NULL); /*lint !e613*/
6320  SCIPdebugPrintCons(scip, lincons, NULL);
6321 
6322  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
6323 
6324  SCIP_CALL( SCIPdelCons(scip, conss[c]) ); /*lint !e613*/
6325  ++*nupgdconss;
6326  continue;
6327  }
6328 
6329  /* run domain propagation, also checks for redundancy */
6330  localnchgbds = 0;
6331  localnaddconss = 0;
6332  SCIP_CALL( propagateCons(scip, conshdlr, conss[c], TRUE, &infeas, &localnchgbds, &localnaddconss) ); /*lint !e613*/
6333  if( infeas )
6334  {
6335  SCIPdebugMessage("propagation on constraint <%s> says problem is infeasible in presolve\n", SCIPconsGetName(conss[c])); /*lint !e613*/
6336  *result = SCIP_CUTOFF;
6337  return SCIP_OKAY;
6338  }
6339  if( localnchgbds > 0 || localnaddconss > 0 )
6340  {
6341  *nchgbds += localnchgbds;
6342  *naddconss += localnaddconss;
6343  *result = SCIP_SUCCESS;
6344  }
6345  if( SCIPconsIsDeleted(conss[c]) ) /*lint !e613*/
6346  {
6347  ++*ndelconss;
6348  *result = SCIP_SUCCESS;
6349  continue;
6350  }
6351 
6352  if( conshdlrdata->dualpresolve )
6353  {
6354  /* check if a variable can be fixed because it appears in no other constraint */
6355  SCIP_CALL( presolveDual(scip, conss[c], &infeas, ndelconss, nfixedvars) ); /*lint !e613*/
6356  if( infeas )
6357  {
6358  SCIPdebugMessage("dual presolve on constraint <%s> says problem is infeasible in presolve\n", SCIPconsGetName(conss[c])); /*lint !e613*/
6359  *result = SCIP_CUTOFF;
6360  return SCIP_OKAY;
6361  }
6362  if( SCIPconsIsDeleted(conss[c]) ) /*lint !e613*/
6363  {
6364  *result = SCIP_SUCCESS;
6365  continue;
6366  }
6367  }
6368 
6369  /* propagate variable bound constraints */
6370  if( !consdata->propvarbounds )
6371  {
6372  SCIP_CALL( propagateVarbounds(scip, conshdlr, conss[c], &infeas, nchgbds, naddconss) ); /*lint !e613*/
6373 
6374  if( infeas )
6375  {
6376  *result = SCIP_CUTOFF;
6377  return SCIP_OKAY;
6378  }
6379 
6380  consdata->propvarbounds = TRUE;
6381  }
6382 
6383  /* check if we can make z implicit integer
6384  * if constraint is signpow(x,n) + c*z = rhs with x integer, |c| = 1, rhs and n integral, then z is implicit integral
6385  */
6386  if( SCIPvarGetType(consdata->z) == SCIP_VARTYPE_CONTINUOUS && SCIPvarGetType(consdata->x) != SCIP_VARTYPE_CONTINUOUS &&
6387  SCIPisEQ(scip, consdata->lhs, consdata->rhs) && SCIPisIntegral(scip, consdata->rhs) && SCIPisEQ(scip, REALABS(consdata->zcoef), 1.0) && SCIPisIntegral(scip, consdata->exponent)
6388  )
6389  {
6390  SCIPdebugMessage("make z = <%s> implicit integer in cons <%s>\n", SCIPvarGetName(consdata->z), SCIPconsGetName(conss[c])); /*lint !e613*/
6391  SCIPdebugPrintCons(scip, conss[c], NULL); /*lint !e613*/
6392  SCIP_CALL( SCIPchgVarType(scip, consdata->z, SCIP_VARTYPE_IMPLINT, &infeas) );
6393  if( infeas )
6394  {
6395  SCIPdebugMessage("problem found infeasible in presolve when making <%s> implicit integer\n", SCIPvarGetName(consdata->z));
6396  *result = SCIP_CUTOFF;
6397  return SCIP_OKAY;
6398  }
6399  else
6400  {
6401  ++*nchgvartypes;
6402  }
6403  }
6404  }
6405 
6406  /* ensure we are called again if we are about to finish, since another presolver may still fix some variable and we cannot remove these fixations in exitpre anymore */
6408  *result = SCIP_DELAYED;
6409 
6410  return SCIP_OKAY;
6411 }
6412 
6413 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
6414  * propagation rule (see propagateCons()):
6415  * (1) left hand side and bounds on z -> lower bound on x
6416  * (2) left hand side and upper bound on x -> bound on z
6417  * (3) right hand side and bounds on z -> upper bound on x
6418  * (4) right hand side and lower bound on x -> bound on z
6419  */
6420 static
6421 SCIP_DECL_CONSRESPROP(consRespropAbspower)
6423  assert(result != NULL);
6424 
6425  SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, boundtype, bdchgidx) );
6426 
6427  *result = SCIP_SUCCESS;
6428 
6429  return SCIP_OKAY;
6430 } /*lint !e715*/
6431 
6432 /** variable rounding lock method of constraint handler */
6433 static
6434 SCIP_DECL_CONSLOCK(consLockAbspower)
6435 { /*lint --e{715}*/
6436  SCIP_CONSDATA* consdata;
6437  SCIP_Bool haslb;
6438  SCIP_Bool hasub;
6439 
6440  assert(scip != NULL);
6441  assert(cons != NULL);
6442 
6443  consdata = SCIPconsGetData(cons);
6444  assert(consdata != NULL);
6445 
6446  haslb = !SCIPisInfinity(scip, -consdata->lhs);
6447  hasub = !SCIPisInfinity(scip, consdata->rhs);
6448 
6449  if( consdata->x != NULL )
6450  {
6451  if( haslb )
6452  {
6453  SCIP_CALL( SCIPaddVarLocks(scip, consdata->x, nlockspos, nlocksneg) );
6454  }
6455  if( hasub )
6456  {
6457  SCIP_CALL( SCIPaddVarLocks(scip, consdata->x, nlocksneg, nlockspos) );
6458  }
6459  }
6460 
6461  if( consdata->z != NULL )
6462  {
6463  if( consdata->zcoef > 0 )
6464  {
6465  if( haslb )
6466  {
6467  SCIP_CALL( SCIPaddVarLocks(scip, consdata->z, nlockspos, nlocksneg) );
6468  }
6469  if( hasub )
6470  {
6471  SCIP_CALL( SCIPaddVarLocks(scip, consdata->z, nlocksneg, nlockspos) );
6472  }
6473  }
6474  else
6475  {
6476  if( haslb )
6477  {
6478  SCIP_CALL( SCIPaddVarLocks(scip, consdata->z, nlocksneg, nlockspos) );
6479  }
6480  if( hasub )
6481  {
6482  SCIP_CALL( SCIPaddVarLocks(scip, consdata->z, nlockspos, nlocksneg) );
6483  }
6484  }
6485  }
6486 
6487  return SCIP_OKAY;
6488 }
6489 
6490 /** constraint activation notification method of constraint handler */
6491 static
6492 SCIP_DECL_CONSACTIVE(consActiveAbspower)
6493 { /*lint --e{715}*/
6494  SCIP_CONSHDLRDATA* conshdlrdata;
6495 
6496  assert(conshdlr != NULL);
6497 
6498  conshdlrdata = SCIPconshdlrGetData(conshdlr);
6499  assert(conshdlrdata != NULL);
6500 
6501  /* (re)run constraint comparison, since new constraint is added */
6502  conshdlrdata->comparedpairwise = FALSE;
6503 
6504  return SCIP_OKAY;
6505 }
6506 
6507 /** constraint enabling notification method of constraint handler */
6508 static
6509 SCIP_DECL_CONSENABLE(consEnableAbspower)
6510 { /*lint --e{715}*/
6511  SCIP_CONSHDLRDATA* conshdlrdata;
6512 
6513  assert(scip != NULL);
6514  assert(cons != NULL);
6515  assert(conshdlr != NULL);
6516 
6517  conshdlrdata = SCIPconshdlrGetData(conshdlr);
6518  assert(conshdlrdata != NULL);
6519  assert(conshdlrdata->eventhdlr != NULL);
6520 
6521  SCIP_CALL( catchVarEvents(scip, conshdlrdata->eventhdlr, cons) );
6522 
6523  return SCIP_OKAY;
6524 }
6525 
6526 /** constraint disabling notification method of constraint handler */
6527 static
6528 SCIP_DECL_CONSDISABLE(consDisableAbspower)
6529 { /*lint --e{715}*/
6530  SCIP_CONSHDLRDATA* conshdlrdata;
6531 
6532  assert(scip != NULL);
6533  assert(cons != NULL);
6534  assert(conshdlr != NULL);
6535 
6536  conshdlrdata = SCIPconshdlrGetData(conshdlr);
6537  assert(conshdlrdata != NULL);
6538  assert(conshdlrdata->eventhdlr != NULL);
6539 
6540  SCIP_CALL( dropVarEvents(scip, conshdlrdata->eventhdlr, cons) );
6541 
6542  return SCIP_OKAY;
6543 }
6544 
6545 /** constraint display method of constraint handler */
6546 static
6547 SCIP_DECL_CONSPRINT(consPrintAbspower)
6548 { /*lint --e{715}*/
6549  SCIP_CONSDATA* consdata;
6550 
6551  assert(scip != NULL);
6552  assert(cons != NULL);
6553 
6554  consdata = SCIPconsGetData(cons);
6555  assert(consdata != NULL);
6556 
6557  /* print left hand side for ranged rows */
6558  if( !SCIPisInfinity(scip, -consdata->lhs)
6559  && !SCIPisInfinity(scip, consdata->rhs)
6560  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
6561  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
6562 
6563  /* print coefficients and variables */
6564  SCIPinfoMessage(scip, file, "signpower(");
6565  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->x, TRUE) );
6566  SCIPinfoMessage(scip, file, " %+.15g, %.15g) ", consdata->xoffset, consdata->exponent);
6567 
6568  SCIPinfoMessage(scip, file, "%+.15g", consdata->zcoef);
6569  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->z, TRUE) );
6570 
6571  /* print right hand side */
6572  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
6573  {
6574  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
6575  }
6576  else if( !SCIPisInfinity(scip, consdata->rhs) )
6577  {
6578  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
6579  }
6580  else if( !SCIPisInfinity(scip, -consdata->lhs) )
6581  {
6582  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
6583  }
6584  else
6585  {
6586  SCIPinfoMessage(scip, file, " [free]");
6587  }
6588 
6589  return SCIP_OKAY;
6590 }
6591 
6592 /** feasibility check method of constraint handler for integral solutions */
6593 static
6594 SCIP_DECL_CONSCHECK(consCheckAbspower)
6595 { /*lint --e{715}*/
6596  SCIP_CONSHDLRDATA* conshdlrdata;
6597  SCIP_CONSDATA* consdata;
6598  SCIP_Bool dolinfeasshift;
6599  SCIP_Real maxviol;
6600  SCIP_Real viol;
6601  int c;
6602 
6603  assert(scip != NULL);
6604  assert(conss != NULL || nconss == 0);
6605  assert(result != NULL);
6606 
6607  conshdlrdata = SCIPconshdlrGetData(conshdlr);
6608  assert(conshdlrdata != NULL);
6609 
6610  *result = SCIP_FEASIBLE;
6611 
6612  maxviol = 0.0;
6613  viol = SCIP_INVALID;
6614 
6615  dolinfeasshift = conshdlrdata->linfeasshift && (conshdlrdata->trysolheur != NULL) && SCIPgetStage(scip) > SCIP_STAGE_PROBLEM && SCIPgetStage(scip) < SCIP_STAGE_SOLVED;
6616  for( c = 0; c < nconss; ++c )
6617  {
6618  assert(conss != NULL);
6619  SCIP_CALL( computeViolation(scip, conshdlr, conss[c], sol, &viol) );
6620 
6621  consdata = SCIPconsGetData(conss[c]);
6622  assert(consdata != NULL);
6623 
6624  if( SCIPisGT(scip, consdata->lhsviol, SCIPfeastol(scip)) || SCIPisGT(scip, consdata->rhsviol, SCIPfeastol(scip)) )
6625  {
6626  *result = SCIP_INFEASIBLE;
6627 
6628  if( printreason )
6629  {
6630  SCIPinfoMessage(scip, NULL, "absolute power constraint <%s> violated by %g (scaled = %g)\n\t",
6631  SCIPconsGetName(conss[c]), viol, MAX(consdata->lhsviol, consdata->rhsviol));
6632  SCIP_CALL( consPrintAbspower(scip, conshdlr, conss[c], NULL) );
6633  SCIPinfoMessage(scip, NULL, ";\n");
6634  }
6635 
6636  if( conshdlrdata->subnlpheur == NULL && !dolinfeasshift )
6637  return SCIP_OKAY;
6638  if( consdata->lhsviol > maxviol || consdata->rhsviol > maxviol )
6639  maxviol = MAX(consdata->lhsviol, consdata->rhsviol);
6640  }
6641  }
6642 
6643  if( *result == SCIP_INFEASIBLE && dolinfeasshift )
6644  {
6645  SCIP_CALL( proposeFeasibleSolution(scip, conshdlr, conss, nconss, sol) );
6646  }
6647 
6648  if( *result == SCIP_INFEASIBLE && conshdlrdata->subnlpheur != NULL && sol != NULL )
6649  {
6650  SCIP_CALL( SCIPupdateStartpointHeurSubNlp(scip, conshdlrdata->subnlpheur, sol, maxviol) );
6651  }
6652 
6653  return SCIP_OKAY;
6654 }
6655 
6656 /** constraint copying method of constraint handler */
6657 static
6658 SCIP_DECL_CONSCOPY(consCopyAbspower)
6659 { /*lint --e{715}*/
6660  SCIP_CONSDATA* consdata;
6661  SCIP_VAR* x;
6662  SCIP_VAR* z;
6663 
6664  assert(scip != NULL);
6665  assert(cons != NULL);
6666  assert(sourcescip != NULL);
6667  assert(sourcecons != NULL);
6668  assert(varmap != NULL);
6669  assert(valid != NULL);
6670 
6671  consdata = SCIPconsGetData(sourcecons);
6672  assert(consdata != NULL);
6673 
6674  *valid = TRUE;
6675  *cons = NULL;
6676 
6677  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, consdata->x, &x, varmap, consmap, global, valid) );
6678 
6679  if( *valid )
6680  {
6681  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, consdata->z, &z, varmap, consmap, global, valid) );
6682  }
6683 
6684  if( *valid )
6685  {
6686  SCIP_CALL( SCIPcreateConsAbspower(scip, cons, name != NULL ? name : SCIPconsGetName(sourcecons),
6687  x, z, consdata->exponent, consdata->xoffset, consdata->zcoef, consdata->lhs, consdata->rhs,
6688  initial, separate, enforce, check, propagate, local, FALSE, dynamic, removable, stickingatnode) ); /*lint !e644*/
6689  }
6690 
6691  return SCIP_OKAY;
6692 }
6693 
6694 /** constraint parsing method of constraint handler */
6695 static
6696 SCIP_DECL_CONSPARSE(consParseAbspower)
6698  SCIP_Real lhs;
6699  SCIP_Real rhs;
6700  SCIP_Real xoffset;
6701  SCIP_Real exponent;
6702  SCIP_Real zcoef;
6703  SCIP_Real value;
6704  char* endptr;
6705  char sense;
6706  SCIP_VAR* x;
6707  SCIP_VAR* z;
6708 
6709  *success = TRUE;
6710 
6711  /* set right hand and left side to their default values */
6712  lhs = -SCIPinfinity(scip);
6713  rhs = SCIPinfinity(scip);
6714 
6715  SCIPdebugMessage("start parsing absolute power constraint expression %s\n", str);
6716 
6717  if( strncmp(str, "signpower(", 10) != 0 )
6718  {
6719  /* str does not start with signpower string, so may be left-hand-side of ranged constraint */
6720  if( !SCIPstrToRealValue(str, &lhs, &endptr) )
6721  {
6722  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error: left-hand-side or 'signpower(' expected at begin on '%s'\n", str);
6723  *success = FALSE;
6724  return SCIP_OKAY;
6725  }
6726  str = endptr;
6727  }
6728  else
6729  {
6730  str += 10;
6731  }
6732 
6733  /* parse (x +offset, exponent) +coef z */
6734 
6735  /* parse variable name */
6736  SCIP_CALL( SCIPparseVarName(scip, str, &x, &endptr) );
6737  if( x == NULL )
6738  {
6739  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable name at '%s'\n", str);
6740  *success = FALSE;
6741  return SCIP_OKAY;
6742  }
6743  str = endptr;
6744 
6745  /* skip whitespace */
6746  while( isspace((int)*str) )
6747  ++str;
6748 
6749  /* parse offset */
6750  if( !SCIPstrToRealValue(str, &xoffset, &endptr) )
6751  {
6752  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected coefficient at begin of '%s'\n", str);
6753  *success = FALSE;
6754  return SCIP_OKAY;
6755  }
6756  str = endptr;
6757 
6758  if( *str != ',' )
6759  {
6760  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected ',' at begin of '%s'\n", str);
6761  *success = FALSE;
6762  return SCIP_OKAY;
6763  }
6764  ++str;
6765 
6766  /* skip whitespace */
6767  while( isspace((int)*str) )
6768  ++str;
6769 
6770  /* parse exponent */
6771  if( !SCIPstrToRealValue(str, &exponent, &endptr) )
6772  {
6773  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected coefficient at begin of '%s'\n", str);
6774  *success = FALSE;
6775  return SCIP_OKAY;
6776  }
6777  str = endptr;
6778 
6779  if( *str != ')' )
6780  {
6781  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected ')' at begin of '%s'\n", str);
6782  *success = FALSE;
6783  return SCIP_OKAY;
6784  }
6785  ++str;
6786 
6787  /* skip whitespace */
6788  while( isspace((int)*str) )
6789  ++str;
6790 
6791  /* parse coefficient */
6792  if( !SCIPstrToRealValue(str, &zcoef, &endptr) )
6793  {
6794  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected coefficient at begin of '%s'\n", str);
6795  *success = FALSE;
6796  return SCIP_OKAY;
6797  }
6798  str = endptr;
6799 
6800  /* parse variable name */
6801  SCIP_CALL( SCIPparseVarName(scip, str, &z, &endptr) );
6802  if( z == NULL )
6803  {
6804  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable name at '%s'\n", str);
6805  *success = FALSE;
6806  return SCIP_OKAY;
6807  }
6808  str = endptr;
6809 
6810  /* skip whitespace */
6811  while( isspace((int)*str) )
6812  ++str;
6813 
6814  if( strncmp(str, "[free]", 6) != 0 )
6815  {
6816  /* parse sense */
6817  if( (*str != '<' && *str != '>' && *str != '=') || str[1] != '=' )
6818  {
6819  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected sense at begin of '%s'\n", str);
6820  *success = FALSE;
6821  return SCIP_OKAY;
6822  }
6823  sense = *str;
6824  str += 2;
6825 
6826  /* parse value at rhs */
6827  if( !SCIPstrToRealValue(str, &value, &endptr) )
6828  {
6829  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected rhs value at begin of '%s'\n", str);
6830  *success = FALSE;
6831  return SCIP_OKAY;
6832  }
6833 
6834  switch( sense )
6835  {
6836  case '<' :
6837  rhs = value;
6838  break;
6839  case '>' :
6840  lhs = value;
6841  break;
6842  case '=' :
6843  lhs = rhs = value;
6844  break;
6845  default:
6846  SCIPABORT(); /* checked above that this cannot happen */
6847  return SCIP_INVALIDDATA; /*lint !e527*/
6848  }
6849  }
6850 
6851  SCIP_CALL( SCIPcreateConsAbspower(scip, cons, name, x, z, exponent, xoffset, zcoef, lhs, rhs,
6852  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
6853 
6854  return SCIP_OKAY;
6855 } /*lint !e715*/
6856 
6857 /** constraint method of constraint handler which returns the variables (if possible) */
6858 static
6859 SCIP_DECL_CONSGETVARS(consGetVarsAbspower)
6860 { /*lint --e{715}*/
6861 
6862  if( varssize < 2 )
6863  (*success) = FALSE;
6864  else
6865  {
6866  SCIP_CONSDATA* consdata;
6867  assert(cons != NULL);
6868  assert(vars != NULL);
6869 
6870  consdata = SCIPconsGetData(cons);
6871  assert(consdata != NULL);
6872 
6873  vars[0] = consdata->x;
6874  vars[1] = consdata->z;
6875  (*success) = TRUE;
6876  }
6877 
6878  return SCIP_OKAY;
6879 }
6880 
6881 /** constraint method of constraint handler which returns the number of variables (if possible) */
6882 static
6883 SCIP_DECL_CONSGETNVARS(consGetNVarsAbspower)
6884 { /*lint --e{715}*/
6885  (*nvars) = 2;
6886  (*success) = TRUE;
6887 
6888  return SCIP_OKAY;
6889 }
6890 
6891 /*
6892  * constraint specific interface methods
6893  */
6894 
6895 /** creates the handler for absolute power constraints and includes it in SCIP */
6897  SCIP* scip /**< SCIP data structure */
6898  )
6899 {
6900  SCIP_CONSHDLRDATA* conshdlrdata;
6901  SCIP_CONSHDLR* conshdlr;
6902  SCIP_EVENTHDLR* eventhdlr;
6903 
6904  /* create absolute power constraint handler data */
6905  SCIP_CALL( SCIPallocMemory(scip, &conshdlrdata) );
6906  BMSclearMemory(conshdlrdata);
6907 
6908  /* include constraint handler */
6911  consEnfolpAbspower, consEnfopsAbspower, consCheckAbspower, consLockAbspower,
6912  conshdlrdata) );
6913 
6914  assert(conshdlr != NULL);
6915 
6916 
6917  /* set non-fundamental callbacks via specific setter functions */
6918  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveAbspower) );
6919  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyAbspower, consCopyAbspower) );
6920  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteAbspower) );
6921  SCIP_CALL( SCIPsetConshdlrDisable(scip, conshdlr, consDisableAbspower) );
6922  SCIP_CALL( SCIPsetConshdlrEnable(scip, conshdlr, consEnableAbspower) );
6923  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitAbspower) );
6924  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreAbspower) );
6925  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolAbspower) );
6926  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeAbspower) );
6927  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsAbspower) );
6928  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsAbspower) );
6929  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitAbspower) );
6930  SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreAbspower) );
6931  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolAbspower) );
6932  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpAbspower) );
6933  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseAbspower) );
6934  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolAbspower, CONSHDLR_MAXPREROUNDS, CONSHDLR_DELAYPRESOL) );
6935  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintAbspower) );
6936  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropAbspower, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
6938  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropAbspower) );
6939  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpAbspower, consSepasolAbspower, CONSHDLR_SEPAFREQ,
6941  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransAbspower) );
6942 
6943  /* include the quadratic constraint upgrade in the quadratic constraint handler */
6945 
6946  /* include the absolute power constraint upgrade and node reform in the nonlinear constraint handler
6947  * we give it higher priority as quadratic, so it also takes care of x^2 constraints, if possible
6948  */
6949  SCIP_CALL( SCIPincludeNonlinconsUpgrade(scip, nonlinconsUpgdAbspower, exprgraphnodeReformAbspower, NONLINCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) );
6950 
6951  /* add absolute power constraint handler parameters */
6952  SCIP_CALL( SCIPaddRealParam(scip, "constraints/"CONSHDLR_NAME"/minefficacysepa",
6953  "minimal efficacy for a cut to be added to the LP during separation; overwrites separating/efficacy",
6954  &conshdlrdata->mincutefficacysepa, FALSE, 0.0001, 0.0, SCIPinfinity(scip), NULL, NULL) );
6955 
6956  SCIP_CALL( SCIPaddRealParam(scip, "constraints/"CONSHDLR_NAME"/minefficacyenfofac",
6957  "minimal target efficacy of a cut in order to add it to relaxation during enforcement as factor of feasibility tolerance (may be ignored)",
6958  &conshdlrdata->mincutefficacyenfofac, FALSE, 2.0, 1.0, SCIPinfinity(scip), NULL, NULL) );
6959 
6960  SCIP_CALL( SCIPaddCharParam(scip, "constraints/"CONSHDLR_NAME"/scaling",
6961  "whether scaling of infeasibility is 'o'ff, by sup-norm of function 'g'radient, or by left/right hand 's'ide",
6962  &conshdlrdata->scaling, TRUE, 'o', "ogs", NULL, NULL) );
6963 
6964  SCIP_CALL( SCIPaddRealParam(scip, "constraints/"CONSHDLR_NAME"/cutmaxrange",
6965  "maximal coef range of a cut (maximal coefficient divided by minimal coefficient) in order to be added to LP relaxation",
6966  &conshdlrdata->cutmaxrange, FALSE, 1e+7, 0.0, SCIPinfinity(scip), NULL, NULL) );
6967 
6968  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/"CONSHDLR_NAME"/projectrefpoint",
6969  "whether to project the reference point when linearizing an absolute power constraint in a convex region",
6970  &conshdlrdata->projectrefpoint, FALSE, TRUE, NULL, NULL) );
6971 
6972  SCIP_CALL( SCIPaddIntParam(scip, "constraints/"CONSHDLR_NAME"/preferzerobranch",
6973  "how much to prefer branching on 0.0 when sign of variable is not fixed yet: 0 no preference, 1 prefer if LP solution will be cutoff in both child nodes, 2 prefer always, 3 ensure always",
6974  &conshdlrdata->preferzerobranch, FALSE, 1, 0, 3, NULL, NULL) );
6975 
6976  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/"CONSHDLR_NAME"/branchminconverror",
6977  "whether to compute branching point such that the convexification error is minimized (after branching on 0.0)",
6978  &conshdlrdata->branchminconverror, FALSE, FALSE, NULL, NULL) );
6979 
6980  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/"CONSHDLR_NAME"/addvarboundcons",
6981  "should variable bound constraints be added for derived variable bounds?",
6982  &conshdlrdata->addvarboundcons, TRUE, TRUE, NULL, NULL) );
6983 
6984  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/"CONSHDLR_NAME"/linfeasshift",
6985  "whether to try to make solutions in check function feasible by shifting the linear variable z",
6986  &conshdlrdata->linfeasshift, FALSE, TRUE, NULL, NULL) );
6987 
6988  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/"CONSHDLR_NAME"/dualpresolve",
6989  "should dual presolve be applied?",
6990  &conshdlrdata->dualpresolve, FALSE, TRUE, NULL, NULL) );
6991 
6992  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/"CONSHDLR_NAME"/sepainboundsonly",
6993  "whether to separate linearization cuts only in the variable bounds (does not affect enforcement)",
6994  &conshdlrdata->sepainboundsonly, FALSE, FALSE, NULL, NULL) );
6995 
6996  SCIP_CALL( SCIPaddRealParam(scip, "constraints/"CONSHDLR_NAME"/sepanlpmincont",
6997  "minimal required fraction of continuous variables in problem to use solution of NLP relaxation in root for separation",
6998  &conshdlrdata->sepanlpmincont, FALSE, 1.0, 0.0, 2.0, NULL, NULL) );
6999 
7000  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/"CONSHDLR_NAME"/enfocutsremovable",
7001  "are cuts added during enforcement removable from the LP in the same node?",
7002  &conshdlrdata->enfocutsremovable, TRUE, FALSE, NULL, NULL) );
7003 
7004  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, CONSHDLR_NAME, "signals a bound change on a variable to an absolute power constraint",
7005  processVarEvent, NULL) );
7006  conshdlrdata->eventhdlr = eventhdlr;
7007 
7008  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, NULL, CONSHDLR_NAME"_newsolution", "handles the event that a new primal solution has been found",
7009  processNewSolutionEvent, NULL) );
7010 
7011  return SCIP_OKAY;
7012 }
7013 
7014 /** creates and captures a absolute power constraint
7015  *
7016  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
7017  */
7019  SCIP* scip, /**< SCIP data structure */
7020  SCIP_CONS** cons, /**< pointer to hold the created constraint */
7021  const char* name, /**< name of constraint */
7022  SCIP_VAR* x, /**< nonlinear variable x in constraint */
7023  SCIP_VAR* z, /**< linear variable z in constraint */
7024  SCIP_Real exponent, /**< exponent n of |x+offset|^n term in constraint */
7025  SCIP_Real xoffset, /**< offset in |x+offset|^n term in constraint */
7026  SCIP_Real zcoef, /**< coefficient of z in constraint */
7027  SCIP_Real lhs, /**< left hand side of constraint */
7028  SCIP_Real rhs, /**< right hand side of constraint */
7029  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
7030  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
7031  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
7032  * Usually set to TRUE. */
7033  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
7034  * TRUE for model constraints, FALSE for additional, redundant constraints. */
7035  SCIP_Bool check, /**< should the constraint be checked for feasibility?
7036  * TRUE for model constraints, FALSE for additional, redundant constraints. */
7037  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
7038  * Usually set to TRUE. */
7039  SCIP_Bool local, /**< is constraint only valid locally?
7040  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7041  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
7042  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
7043  * adds coefficients to this constraint. */
7044  SCIP_Bool dynamic, /**< is constraint subject to aging?
7045  * Usually set to FALSE. Set to TRUE for own cuts which
7046  * are seperated as constraints. */
7047  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
7048  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7049  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
7050  * if it may be moved to a more global node?
7051  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7052  )
7053 {
7054  SCIP_CONSHDLR* conshdlr;
7055  SCIP_CONSDATA* consdata;
7056 
7057  assert(x != NULL);
7058  assert(z != NULL);
7059  assert(exponent > 1.0);
7060  assert(!SCIPisZero(scip, zcoef));
7061  assert(!SCIPisInfinity(scip, REALABS(zcoef)));
7062  assert(!modifiable); /* we do not support column generation */
7063 
7064  /* find the absolute power constraint handler */
7065  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
7066  if( conshdlr == NULL )
7067  {
7068  SCIPerrorMessage("absolute power constraint handler not found\n");
7069  return SCIP_PLUGINNOTFOUND;
7070  }
7071 
7072  /* create constraint data */
7073  SCIP_CALL( SCIPallocMemory( scip, &consdata) );
7074  BMSclearMemory(consdata);
7075  consdata->xeventfilterpos = -1;
7076  consdata->zeventfilterpos = -1;
7077 
7078  consdata->x = x;
7079  consdata->z = z;
7080  consdata->xoffset = xoffset;
7081  consdata->zcoef = zcoef;
7082  consdata->lhs = lhs;
7083  consdata->rhs = rhs;
7084 
7085  if( SCIPisEQ(scip, exponent, 2.0) )
7086  {
7087  consdata->exponent = 2.0;
7088  consdata->power = square;
7089  }
7090  else
7091  {
7092  consdata->exponent = exponent;
7093  consdata->power = pow;
7094  }
7095 
7096  /* branching on multiaggregated variables does not seem to work well, so try to avoid multiagg. x */
7097  if( SCIPvarIsActive(x) )
7098  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, x) );
7099 
7100  /* cannot propagate on multiaggregated vars, so avoid multiagg. z */
7101  if( SCIPvarIsActive(z) )
7102  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, z) );
7103 
7104  /* create constraint */
7105  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
7106  local, modifiable, dynamic, removable, stickingatnode) );
7107 
7108  return SCIP_OKAY;
7109 }
7110 
7111 /** creates and captures an absolute power constraint
7112  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
7113  * method SCIPcreateConsAbspower(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
7114  *
7115  * @see SCIPcreateConsAbspower() for information about the basic constraint flag configuration
7116  *
7117  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
7118  */
7120  SCIP* scip, /**< SCIP data structure */
7121  SCIP_CONS** cons, /**< pointer to hold the created constraint */
7122  const char* name, /**< name of constraint */
7123  SCIP_VAR* x, /**< nonlinear variable x in constraint */
7124  SCIP_VAR* z, /**< linear variable z in constraint */
7125  SCIP_Real exponent, /**< exponent n of |x+offset|^n term in constraint */
7126  SCIP_Real xoffset, /**< offset in |x+offset|^n term in constraint */
7127  SCIP_Real zcoef, /**< coefficient of z in constraint */
7128  SCIP_Real lhs, /**< left hand side of constraint */
7129  SCIP_Real rhs /**< right hand side of constraint */
7130  )
7131 {
7132  assert(scip != NULL);
7133 
7134  SCIP_CALL( SCIPcreateConsAbspower(scip, cons, name, x, z, exponent, xoffset, zcoef, lhs, rhs,
7135  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
7136 
7137  return SCIP_OKAY;
7138 }
7139 
7140 /** gets the absolute power constraint as a nonlinear row representation */
7142  SCIP* scip, /**< SCIP data structure */
7143  SCIP_CONS* cons, /**< constraint */
7144  SCIP_NLROW** nlrow /**< a buffer where to store pointer to nonlinear row */
7145  )
7146 {
7147  SCIP_CONSDATA* consdata;
7148 
7149  assert(cons != NULL);
7150  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7151  assert(nlrow != NULL);
7152 
7153  consdata = SCIPconsGetData(cons);
7154  assert(consdata != NULL);
7155 
7156  if( consdata->nlrow == NULL )
7157  {
7158  SCIP_CALL( createNlRow(scip, cons) );
7159  }
7160  assert(consdata->nlrow != NULL);
7161  *nlrow = consdata->nlrow;
7162 
7163  return SCIP_OKAY;
7164 }
7165 
7166 /** gets nonlinear variable x in absolute power constraint */
7168  SCIP* scip, /**< SCIP data structure */
7169  SCIP_CONS* cons /**< absolute power constraint */
7170  )
7171 {
7172  SCIP_CONSDATA* consdata;
7173 
7174  assert(cons != NULL);
7175  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7176 
7177  consdata = SCIPconsGetData(cons);
7178  assert(consdata != NULL);
7179 
7180  return consdata->x;
7181 }
7182 
7183 /** gets linear variable z in absolute power constraint */
7185  SCIP* scip, /**< SCIP data structure */
7186  SCIP_CONS* cons /**< absolute power constraint */
7187  )
7188 {
7189  SCIP_CONSDATA* consdata;
7190 
7191  assert(cons != NULL);
7192  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7193 
7194  consdata = SCIPconsGetData(cons);
7195  assert(consdata != NULL);
7196 
7197  return consdata->z;
7198 }
7199 
7200 /** gets exponent in power term in absolute power constraint */
7202  SCIP* scip, /**< SCIP data structure */
7203  SCIP_CONS* cons /**< absolute power constraint */
7204  )
7205 {
7206  SCIP_CONSDATA* consdata;
7207 
7208  assert(cons != NULL);
7209  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7210 
7211  consdata = SCIPconsGetData(cons);
7212  assert(consdata != NULL);
7213 
7214  return consdata->exponent;
7215 }
7216 
7217 /** gets offset in power term in absolute power constraint */
7219  SCIP* scip, /**< SCIP data structure */
7220  SCIP_CONS* cons /**< absolute power constraint */
7221  )
7222 {
7223  SCIP_CONSDATA* consdata;
7224 
7225  assert(cons != NULL);
7226  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7227 
7228  consdata = SCIPconsGetData(cons);
7229  assert(consdata != NULL);
7230 
7231  return consdata->xoffset;
7232 }
7233 
7234 /** gets coefficient of linear variable in absolute power constraint */
7236  SCIP* scip, /**< SCIP data structure */
7237  SCIP_CONS* cons /**< absolute power constraint */
7238  )
7239 {
7240  SCIP_CONSDATA* consdata;
7241 
7242  assert(cons != NULL);
7243  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7244 
7245  consdata = SCIPconsGetData(cons);
7246  assert(consdata != NULL);
7247 
7248  return consdata->zcoef;
7249 }
7250 
7251 /** gets left hand side in absolute power constraint */
7253  SCIP* scip, /**< SCIP data structure */
7254  SCIP_CONS* cons /**< absolute power constraint */
7255  )
7256 {
7257  SCIP_CONSDATA* consdata;
7258 
7259  assert(cons != NULL);
7260  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7261 
7262  consdata = SCIPconsGetData(cons);
7263  assert(consdata != NULL);
7264 
7265  return consdata->lhs;
7266 }
7267 
7268 /** gets right hand side in absolute power constraint */
7270  SCIP* scip, /**< SCIP data structure */
7271  SCIP_CONS* cons /**< absolute power constraint */
7272  )
7273 {
7274  SCIP_CONSDATA* consdata;
7275 
7276  assert(cons != NULL);
7277  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7278 
7279  consdata = SCIPconsGetData(cons);
7280  assert(consdata != NULL);
7281 
7282  return consdata->rhs;
7283 }
7284 
7285 /** gets the absolute violation of a absolute power constraint by a solution */
7287  SCIP* scip, /**< SCIP data structure */
7288  SCIP_CONS* cons, /**< absolute power constraint */
7289  SCIP_SOL* sol /**< LP solution */
7290  )
7291 {
7292  SCIP_CONSDATA* consdata;
7293  SCIP_Real z_val;
7294  SCIP_Real x_val;
7295  SCIP_Real rhs;
7296  SCIP_Real proj_val;
7297 
7298  assert(cons != NULL);
7299  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
7300 
7301  consdata = SCIPconsGetData(cons);
7302  assert(consdata != NULL);
7303  assert(consdata->lhs == 0.0);
7304  assert(consdata->rhs == 0.0);
7305 
7306  z_val = SCIPgetSolVal(scip, sol, consdata->z);
7307  x_val = SCIPgetSolVal(scip, sol, consdata->x);
7308 
7309  rhs = -1.0 * consdata->zcoef * z_val;
7310  proj_val = SIGN(rhs) * pow(REALABS(rhs), 1.0 / consdata->exponent) - consdata->xoffset;
7311 
7312  SCIPdebugMessage("computing slack: linear: %f, power: %f, projected: %f\n", z_val, x_val, proj_val);
7313 
7314  return x_val - proj_val;
7315 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31608
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:20784
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38254
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_Real SCIPexprgraphGetNodeVal(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12506
#define INITLPMAXVARVAL
Definition: cons_abspower.c:65
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:14102
static SCIP_DECL_HASHGETKEY(presolveFindDuplicatesGetKey)
SCIPInterval square(const SCIPInterval &x)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:38397
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:25984
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10071
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5600
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:5332
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip.c:5401
void SCIPexprgraphSetVarNodeValue(SCIP_EXPRGRAPHNODE *varnode, SCIP_Real value)
Definition: expr.c:14087
SCIP_RETCODE SCIPexprgraphAddNode(SCIP_EXPRGRAPH *exprgraph, SCIP_EXPRGRAPHNODE *node, int mindepth, int nchildren, SCIP_EXPRGRAPHNODE **children)
Definition: expr.c:14287
SCIP_EXPRGRAPH * SCIPgetExprgraphNonlinear(SCIP *scip, SCIP_CONSHDLR *conshdlr)
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2192
primal heuristic that tries a given solution
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
static SCIP_DECL_CONSPROP(consPropAbspower)
#define PROPSIDETOL
Definition: cons_abspower.c:64
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPexprgraphAddVars(SCIP_EXPRGRAPH *exprgraph, int nvars, void **vars, SCIP_EXPRGRAPHNODE **varnodes)
Definition: expr.c:14371
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:20892
static SCIP_RETCODE generateSecantCut(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, SCIP_SOL *sol, SCIP_Real xlb, SCIP_Real xub, SCIP_Real exponent, SCIP_Real xoffset, DECL_MYPOW((*mypow)), SCIP_Real xmult, SCIP_Real zcoef, SCIP_Real rhs, SCIP_VAR *x, SCIP_VAR *z)
Constraint handler for variable bound constraints .
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:38360
static SCIP_RETCODE dropVarEvents(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons)
#define PROPVARTOL
Definition: cons_abspower.c:63
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:591
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1374
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:30926
#define SCIPduplicateMemory(scip, ptr, source)
Definition: scip.h:19171
int SCIPexprgraphGetNodeNChildren(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12169
SCIP_Real SCIPgetRowMinCoef(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:25721
SCIP_QUADVARTERM * SCIPgetQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:9751
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:10913
static SCIP_DECL_CONSDISABLE(consDisableAbspower)
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:15968
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1206
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:13986
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38667
SCIP_Real SCIPgetRelaxFeastolFactor(SCIP *scip)
Definition: scip.c:28836
#define SCIP_MAXSTRLEN
Definition: def.h:196
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:5378
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:4990
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4239
SCIPInterval pow(const SCIPInterval &x, const SCIPInterval &y)
#define NULL
Definition: lpi_spx.cpp:129
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:16426
SCIP_Bool SCIPconshdlrWasPresolvingDelayed(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4812
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4209
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1111
static SCIP_DECL_CONSINITPRE(consInitpreAbspower)
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadvars, SCIP_VAR **quadvars, int nquadelems, SCIP_QUADELEM *quadelems, SCIP_EXPRTREE *expression, SCIP_Real lhs, SCIP_Real rhs)
Definition: scip.c:27037
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:16636
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:7786
static SCIP_RETCODE addLinearizationCuts(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *ref, SCIP_Bool *separatedlpsol, SCIP_Real minefficacy)
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18637
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:16574
static SCIP_DECL_CONSPARSE(consParseAbspower)
SCIP_Bool SCIPintervalIsEmpty(SCIP_INTERVAL operand)
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:7618
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5078
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16380
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:6709
SCIP_RETCODE SCIPheurPassSolTrySol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol)
Definition: heur_trysol.c:236
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:31639
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:16604
constraint handler for indicator constraints
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:22044
SCIP_Real SCIPgetExponentAbspower(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip.c:15670
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:5562
SCIP_RETCODE SCIPsetConshdlrEnable(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENABLE((*consenable)))
Definition: scip.c:5447
SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition: scip.c:7110
#define FALSE
Definition: def.h:52
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31902
static SCIP_DECL_CONSINITSOL(consInitsolAbspower)
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:10116
static SCIP_DECL_CONSINITLP(consInitlpAbspower)
SCIP_RETCODE SCIPexprtreeSetVars(SCIP_EXPRTREE *tree, int nvars, SCIP_VAR **vars)
Definition: nlp.c:111
static SCIP_DECL_CONSEXITPRE(consExitpreAbspower)
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7209
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:7579
SCIP_Real SCIPexprgraphGetNodeSignPowerExponent(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12298
static SCIP_RETCODE generateLinearizationCutProject(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, SCIP_Real xref, SCIP_Real zref, SCIP_Real xmin, SCIP_Real exponent, SCIP_Real xoffset, SCIP_Real xmult, SCIP_Real zcoef, SCIP_Real rhs, SCIP_VAR *x, SCIP_VAR *z, SCIP_Bool islocal)
#define TRUE
Definition: def.h:51
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7577
SCIP_RETCODE SCIPaddExternBranchCand(SCIP *scip, SCIP_VAR *var, SCIP_Real score, SCIP_Real solval)
Definition: scip.c:30273
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
enum Proprule PROPRULE
SCIP_RETCODE SCIPsolveNLP(SCIP *scip)
Definition: scip.c:26443
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip.c:26466
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_VAR *var, SCIP_INTERVAL bounds, SCIP_Bool force, SCIP_CONS *cons, SCIP_RESULT *result, int *nchgbds, int *nfixedvars, int *naddconss)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:5539
SCIP_INTERVAL SCIPexprgraphGetNodeBounds(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12496
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:38743
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_Bool delaypresol)
Definition: scip.c:5271
static SCIP_DECL_CONSENFOPS(consEnfopsAbspower)
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisCutApplicable(SCIP *scip, SCIP_ROW *cut)
Definition: scip.c:28238
#define CONSHDLR_CHECKPRIORITY
Definition: cons_abspower.c:43
static SCIP_RETCODE checkFixedVariables(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, int *ndelconss, int *nupgdconss, int *nchgbds, int *nfixedvars, SCIP_RESULT *result)
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:24136
static SCIP_DECL_HASHKEYVAL(presolveFindDuplicatesKeyVal)
#define SCIPdebugMessage
Definition: pub_message.h:77
#define SIGN(x)
Definition: cons_abspower.c:74
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:31775
static SCIP_RETCODE generateCut(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_ROW **row, SCIP_Bool onlyinbounds)
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16227
static SCIP_DECL_HASHKEYEQ(presolveFindDuplicatesKeyEQ)
static SCIP_Real proposeBranchingPoint(SCIP *scip, SCIP_CONS *cons, int preferzero, SCIP_Bool branchminconverror)
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSTRANS(consTransAbspower)
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE separatePoint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_Real minefficacy, SCIP_Bool inenforcement, SCIP_Bool onlyinbounds, SCIP_Bool *success, SCIP_Bool *cutoff, SCIP_Real *bestefficacy)
static SCIP_DECL_CONSGETVARS(consGetVarsAbspower)
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:10251
SCIP_RETCODE SCIPexprtreeCreate(BMS_BLKMEM *blkmem, SCIP_EXPRTREE **tree, SCIP_EXPR *root, int nvars, int nparams, SCIP_Real *params)
Definition: expr.c:8133
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING timingmask)
Definition: scip.c:5036
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip.c:25459
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:7776
static SCIP_DECL_NONLINCONSUPGD(nonlinconsUpgdAbspower)
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:7716
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:28256
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:22651
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_RETCODE SCIPcreateConsAbspower(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *x, SCIP_VAR *z, SCIP_Real exponent, SCIP_Real xoffset, SCIP_Real zcoef, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
#define NONLINCONSUPGD_PRIORITY
Definition: cons_abspower.c:57
SCIP_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:25739
static SCIP_DECL_CONSENABLE(consEnableAbspower)
SCIP_RETCODE SCIPgetNLPFracVars(SCIP *scip, SCIP_VAR ***fracvars, SCIP_Real **fracvarssol, SCIP_Real **fracvarsfrac, int *nfracvars, int *npriofracvars)
Definition: scip.c:26586
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSEXIT(consExitAbspower)
#define CONSHDLR_DELAYSEPA
Definition: cons_abspower.c:50
int SCIPexprgraphGetNodePolynomialNMonomials(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12392
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:39054
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:5103
static SCIP_DECL_QUADCONSUPGD(quadconsUpgdAbspower)
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:7706
SCIP_RETCODE SCIPcreateConsVarbound(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:18686
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1287
SCIP_EVENTHDLR * SCIPfindEventhdlr(SCIP *scip, const char *name)
Definition: scip.c:7339
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:22424
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip.c:26334
int SCIPexprGetMonomialNFactors(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5567
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip.c:5127
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3388
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:15907
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3414
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip.c:14405
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:15979
SCIP_VAR * SCIPgetLinearVarAbspower(SCIP *scip, SCIP_CONS *cons)
SCIP_EXPROP SCIPexprgraphGetNodeOperator(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12229
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3893
SCIP_EXPRDATA_MONOMIAL ** SCIPexprgraphGetNodePolynomialMonomials(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12380
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:33378
SCIP_Real coef
Definition: type_expr.h:101
#define SCIP_EVENTTYPE_SOLFOUND
Definition: type_event.h:118
SCIP_Real inf
Definition: intervalarith.h:38
void * SCIPhashtableRetrieveNext(SCIP_HASHTABLE *hashtable, SCIP_HASHTABLELIST **hashtablelist, void *key)
Definition: misc.c:1463
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:22066
SCIP_RETCODE SCIPincludeNonlinconsUpgrade(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nonlinconsupgd)), SCIP_DECL_EXPRGRAPHNODEREFORM((*nodereform)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38273
#define CONSHDLR_ENFOPRIORITY
Definition: cons_abspower.c:42
static SCIP_RETCODE createNlRow(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1690
SCIP_Real SCIPexprgraphGetNodeLinearConstant(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12320
SCIP_Real SCIPexprgraphGetNodePolynomialConstant(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12404
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:38755
SCIP_Bool SCIPexprgraphHasNodeNonlinearAncestor(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:13763
SCIP_EXPRCURV SCIPexprgraphGetNodeCurvature(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12516
static void computeBoundsX(SCIP *scip, SCIP_CONS *cons, SCIP_INTERVAL zbnds, SCIP_INTERVAL *xbnds)
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:16616
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:38421
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:15319
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:7816
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:19159
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define CONSHDLR_EAGERFREQ
Definition: cons_abspower.c:46
static void computeBoundsZ(SCIP *scip, SCIP_CONS *cons, SCIP_INTERVAL xbnds, SCIP_INTERVAL *zbnds)
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18647
interval arithmetics for provable bounds
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:17713
#define QUADCONSUPGD_PRIORITY
Definition: cons_abspower.c:56
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition: type_nlpi.h:69
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
static void presolveFindDuplicatesSolveEquations(SCIP *scip, SCIP_Bool *infeas, SCIP_Real *xval, SCIP_Real *zval, SCIP_Real exponent, SCIP_Real xoffset1, SCIP_Real zcoef1, SCIP_Real rhs1, SCIP_Real xoffset2, SCIP_Real zcoef2, SCIP_Real rhs2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:38767
#define DECL_MYPOW(x)
Definition: cons_abspower.c:68
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3873
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:964
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:37705
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:26083
static SCIP_RETCODE proposeFeasibleSolution(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38292
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:25827
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28351
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:37940
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7557
#define CONSHDLR_NEEDSCONS
Definition: cons_abspower.c:53
static SCIP_RETCODE catchVarEvents(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons)
SCIPInterval sign(const SCIPInterval &x)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38648
static SCIP_DECL_CONSACTIVE(consActiveAbspower)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:38470
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:18746
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
static SCIP_RETCODE presolveFindDuplicates(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int *nupgdconss, int *ndelconss, int *naddconss, int *nfixedvars, int *naggrvars, SCIP_Bool *success, SCIP_Bool *infeas)
constraint handler for quadratic constraints
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip.c:5247
static SCIP_DECL_CONSFREE(consFreeAbspower)
static SCIP_RETCODE computeViolation(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Real *viol)
SCIP_Bool SCIPconsIsGlobal(SCIP_CONS *cons)
Definition: cons.c:7766
#define REALABS(x)
Definition: def.h:146
static SCIP_RETCODE presolveDual(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *ndelconss, int *nfixedvars)
void SCIPenableNLP(SCIP *scip)
Definition: scip.c:26068
SCIP_Real SCIPgetViolationAbspower(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3214
static SCIP_Real getGradientMaxElement(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
static SCIP_DECL_EVENTEXEC(processVarEvent)
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:38349
SCIP_RETCODE SCIPexprgraphCreateNodeLinear(BMS_BLKMEM *blkmem, SCIP_EXPRGRAPHNODE **node, int ncoefs, SCIP_Real *coefs, SCIP_Real constant)
Definition: expr.c:12609
#define SCIP_CALL(x)
Definition: def.h:258
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:55
#define CONSHDLR_SEPAPRIORITY
Definition: cons_abspower.c:41
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:4936
static SCIP_RETCODE computeViolations(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_CONS **maxviolcon)
SCIP_Real sup
Definition: intervalarith.h:39
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1526
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
SCIP_RETCODE SCIPaddLinearConsToNlpHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:2224
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:29454
SCIP_VAR ** SCIPgetLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSDELETE(consDeleteAbspower)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38705
SCIP_RETCODE SCIPaddRowIndicator(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_ROW *row)
static SCIP_RETCODE generateSecantCutNoCheck(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, SCIP_Real xlb, SCIP_Real xub, SCIP_Real exponent, SCIP_Real xoffset, DECL_MYPOW((*mypow)), SCIP_Real xmult, SCIP_Real zcoef, SCIP_Real rhs, SCIP_VAR *x, SCIP_VAR *z)
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:246
SCIP_EXPRGRAPHNODE * SCIPgetExprgraphNodeNonlinear(SCIP *scip, SCIP_CONS *cons)
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:49
#define CONSHDLR_PROP_TIMING
Definition: cons_abspower.c:54
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:97
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7587
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:15130
SCIP_RETCODE SCIPcreateConsBasicAbspower(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *x, SCIP_VAR *z, SCIP_Real exponent, SCIP_Real xoffset, SCIP_Real zcoef, SCIP_Real lhs, SCIP_Real rhs)
SCIP_Bool SCIPexprgraphHasNodeSibling(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:13728
SCIP_RETCODE SCIPsetConshdlrDisable(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDISABLE((*consdisable)))
Definition: scip.c:5470
static SCIP_DECL_CONSGETNVARS(consGetNVarsAbspower)
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11453
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38311
static SCIP_DECL_CONSPRINT(consPrintAbspower)
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:21099
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip.c:20694
SCIP_SOL * SCIPeventGetSol(SCIP_EVENT *event)
Definition: event.c:1181
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:18371
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:16436
static SCIP_RETCODE registerLargeLPValueVariableForBranching(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_VAR **brvar)
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
Definition: scip.c:5223
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip.c:1020
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:22476
static SCIP_RETCODE presolveFindDuplicatesUpgradeCons(SCIP *scip, SCIP_CONS *cons1, SCIP_CONS *cons2, SCIP_Bool *infeas, int *nupgdconss, int *ndelconss, int *naggrvars)
#define SCIP_Bool
Definition: def.h:49
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:16400
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:16626
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:790
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:7796
#define CONSHDLR_DELAYPRESOL
Definition: cons_abspower.c:52
constraint handler for nonlinear constraints
static SCIP_DECL_CONSSEPALP(consSepalpAbspower)
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:7650
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:22093
SCIP_RETCODE SCIPincludeConshdlrAbspower(SCIP *scip)
static SCIP_RETCODE propagateVarbounds(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_Bool *infeas, int *nbdchgs, int *naddconss)
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:31124
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:16594
methods for debugging
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:7806
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:7906
static SCIP_DECL_CONSSEPASOL(consSepasolAbspower)
static SCIP_DECL_CONSCHECK(consCheckAbspower)
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:7676
static SCIP_DECL_EXPRGRAPHNODEREFORM(exprgraphnodeReformAbspower)
SCIP_RETCODE SCIPexprCreate(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_EXPROP op,...)
Definition: expr.c:5597
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPexprtreeFree(SCIP_EXPRTREE **tree)
Definition: expr.c:8214
SCIP_RETCODE SCIPaddVarVlb(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:19547
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSRESPROP(consRespropAbspower)
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:5355
void SCIPmarkRowNotRemovableLocal(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:25703
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:16562
static SCIP_RETCODE addVarbound(SCIP *scip, SCIP_CONS *cons, SCIP_Bool addcons, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *infeas, int *nbdchgs, int *naddconss)
static SCIP_DECL_CONSINIT(consInitAbspower)
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:57
Constraint handler for linear constraints in their most general form, .
#define BMSclearMemory(ptr)
Definition: memory.h:97
SCIP_Real SCIPexprGetMonomialCoef(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5557
Constraint handler for absolute power constraints .
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:33535
SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
Definition: tree.c:6729
#define ROOTS_KNOWN
Definition: cons_abspower.c:81
Proprule
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:34833
void * SCIPexprgraphGetNodeVar(SCIP_EXPRGRAPH *exprgraph, SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12261
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1256
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38330
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:1317
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
#define SCIP_EVENTTYPE_DISABLED
Definition: type_event.h:43
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:18583
int SCIPexprgraphGetNodeIntPowerExponent(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12287
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:33424
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:5309
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_Bool canaddcons, SCIP_Bool *cutoff, int *nchgbds, int *naddconss)
#define CONSHDLR_NAME
Definition: cons_abspower.c:39
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:10850
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:15953
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip.c:5175
SCIP_RETCODE SCIPupdateStartpointHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *solcand, SCIP_Real violation)
Definition: heur_subnlp.c:2258
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:16584
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:19176
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16370
SCIP_Real SCIPgetLhsAbspower(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:33344
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:5516
SCIP_Real * SCIPexprgraphGetNodeLinearCoefs(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12309
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip.c:27144
#define CONSHDLR_SEPAFREQ
Definition: cons_abspower.c:44
void SCIPintervalSetEntire(SCIP_Real infinity, SCIP_INTERVAL *resultant)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1239
int SCIPexprgraphGetNodePosition(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12219
static SCIP_DECL_CONSLOCK(consLockAbspower)
int SCIPgetNBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:10161
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:38433
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_DECL_CONSPRESOL(consPresolAbspower)
SCIP_RETCODE SCIPcreateConsNonlinear2(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPRGRAPHNODE *exprgraphnode, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
#define CONSHDLR_MAXPREROUNDS
Definition: cons_abspower.c:49
static SCIP_DECL_CONSENFOLP(consEnfolpAbspower)
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:5199
NLP local search primal heuristic using sub-SCIPs.
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38686
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:17642
static SCIP_Real roots[ROOTS_KNOWN+1]
Definition: cons_abspower.c:87
#define SCIP_Real
Definition: def.h:123
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:7736
SCIP_Real SCIPgetOffsetAbspower(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BOUNDTYPE boundtype)
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3498
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:18477
#define MIN(x, y)
Definition: memory.c:59
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:25276
SCIP_RETCODE SCIPcreateLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:30898
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:26010
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38724
SCIP_RETCODE SCIPincludeQuadconsUpgrade(SCIP *scip, SCIP_DECL_QUADCONSUPGD((*quadconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_EXPRGRAPHNODE ** SCIPexprgraphGetNodeChildren(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12179
#define SCIP_INVALID
Definition: def.h:142
static SCIP_DECL_CONSCOPY(consCopyAbspower)
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:37733
SCIP_Real * SCIPexprGetMonomialExponents(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5587
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:25414
SCIP_VAR * SCIPgetNonlinearVarAbspower(SCIP *scip, SCIP_CONS *cons)
#define CONSHDLR_PROPFREQ
Definition: cons_abspower.c:45
SCIP_RETCODE SCIPsetNLPInitialGuessSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:26411
int SCIPgetNNlpis(SCIP *scip)
Definition: scip.c:8116
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:917
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:245
SCIP_Real SCIPgetVarSol(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:15863
SCIP_Real SCIPgetRhsAbspower(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip.c:5151
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
Definition: scip.c:38494
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:17590
SCIP_Bool SCIPisRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:39080
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:48
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16052
#define CONSHDLR_DESC
Definition: cons_abspower.c:40
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip.c:30565
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11372
SCIP_Real SCIPexprgraphGetNodeRealPowerExponent(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12276
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:22156
static SCIP_DECL_CONSEXITSOL(consExitsolAbspower)
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE registerBranchingCandidates(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int *nnotify)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:38409
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3470
#define CONSHDLR_DELAYPROP
Definition: cons_abspower.c:51
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:5585
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:7644
static SCIP_RETCODE generateLinearizationCut(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, SCIP_Real refpoint, SCIP_Real exponent, SCIP_Real xoffset, SCIP_Real xmult, SCIP_Real zcoef, SCIP_Real rhs, SCIP_VAR *x, SCIP_VAR *z, SCIP_Bool islocal)
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11452
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:25540
#define SCIPABORT()
Definition: def.h:230
SCIP_RETCODE SCIPaddVarVub(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:19606
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:7726
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:7756
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3159
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetCoefLinearAbspower(SCIP *scip, SCIP_CONS *cons)
int SCIPexprgraphGetNodeDepth(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12209
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:39067
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:33310
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:31403
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyAbspower)
SCIP_RETCODE SCIPgetNlRowAbspower(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)
enum SCIP_SideType SCIP_SIDETYPE
Definition: type_lp.h:58