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