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