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