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