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