Scippy

SCIP

Solving Constraint Integer Programs

cons_soc.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_soc.c
17  * @brief constraint handler for second order cone constraints \f$\sqrt{\gamma + \sum_{i=1}^{n} (\alpha_i\, (x_i + \beta_i))^2} \leq \alpha_{n+1}\, (x_{n+1}+\beta_{n+1})\f$
18  * @author Stefan Vigerske
19  * @author Marc Pfetsch
20  * @author Felipe Serrano
21  * @author Benjamin Mueller
22  *
23  * @todo rhsvar == NULL is supported in some routines, but not everywhere
24  * @todo merge square terms with same variables in presol/exitpre
25  */
26 
27 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
28 
29 #define _USE_MATH_DEFINES /* to get M_PI on Windows */ /*lint !750 */
30 
31 #include <assert.h>
32 #include <string.h>
33 #include <math.h>
34 #include <ctype.h>
35 
36 #define SCIP_PRIVATE_ROWPREP
37 
38 #include "scip/cons_soc.h"
39 #include "scip/cons_quadratic.h"
40 #include "scip/cons_linear.h"
41 #include "scip/heur_subnlp.h"
42 #include "scip/heur_trysol.h"
43 #include "scip/intervalarith.h"
44 #include "nlpi/nlpi.h"
45 #include "nlpi/exprinterpret.h"
46 #include "nlpi/nlpi_ipopt.h"
47 
48 
49 /* constraint handler properties */
50 #define CONSHDLR_NAME "soc"
51 #define CONSHDLR_DESC "constraint handler for second order cone constraints"
52 #define CONSHDLR_SEPAPRIORITY 10 /**< priority of the constraint handler for separation */
53 #define CONSHDLR_ENFOPRIORITY -40 /**< priority of the constraint handler for constraint enforcing */
54 #define CONSHDLR_CHECKPRIORITY -10 /**< priority of the constraint handler for checking feasibility */
55 #define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
56 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
57 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
58  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
59 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
60 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
61 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
62 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
63 
64 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
65 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_ALWAYS /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
66 
67 #define QUADCONSUPGD_PRIORITY 10000 /**< priority of the constraint handler for upgrading of quadratic constraints */
68 
69 #define UPGSCALE 10 /* scale factor used in general upgrades of quadratic cons to soc */
70 
71 /*
72  * Data structures
73  */
74 
75 /** Eventdata for variable bound change events. */
76 struct VarEventData
77 {
78  SCIP_CONS* cons; /**< the constraint */
79  int varidx; /**< the index of a variable on the left hand side which bound change is caught, or -1 for variable on right hand side */
80  int filterpos; /**< position of corresponding event in event filter */
81 };
82 typedef struct VarEventData VAREVENTDATA;
83 
84 /** constraint data for soc constraints */
85 struct SCIP_ConsData
86 {
87  int nvars; /**< number of variables on left hand side (n) */
88  SCIP_VAR** vars; /**< variables on left hand side (x_i) */
89  SCIP_Real* coefs; /**< coefficients for variables on left hand side (alpha_i) */
90  SCIP_Real* offsets; /**< offsets for variables on left hand side (beta_i) */
91  SCIP_Real constant; /**< constant on left hand side (gamma) */
92 
93  SCIP_VAR* rhsvar; /**< variable on right hand side (x_{n+1}) */
94  SCIP_Real rhscoeff; /**< coefficient of square term on right hand side (alpha_{n+1}) */
95  SCIP_Real rhsoffset; /**< offset for variable on right hand side (beta_{n+1}) */
96 
97  SCIP_NLROW* nlrow; /**< nonlinear row representation of constraint */
98 
99  SCIP_Real lhsval; /**< value of left hand side in current point */
100  SCIP_Real violation; /**< violation of constraint in current point */
101 
102  VAREVENTDATA* lhsbndchgeventdata; /**< eventdata for bound change events on left hand side variables */
103  VAREVENTDATA rhsbndchgeventdata; /**< eventdata for bound change event on right hand side variable */
104  SCIP_Bool isapproxadded; /**< has a linear outer approximation be added? */
105 };
106 
107 /** constraint handler data */
108 struct SCIP_ConshdlrData
109 {
110  SCIP_HEUR* subnlpheur; /**< a pointer to the subNLP heuristic, if available */
111  SCIP_HEUR* trysolheur; /**< a pointer to the trysol heuristic, if available */
112  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
113  int newsoleventfilterpos;/**< filter position of new solution event handler, if caught */
114  SCIP_Bool haveexprint; /**< indicates whether an expression interpreter is available */
115  SCIP_Bool sepanlp; /**< where linearization of the NLP relaxation solution added? */
116 
117  SCIP_Bool glineur; /**< is the Glineur outer approx preferred to Ben-Tal Nemirovski? */
118  SCIP_Bool projectpoint; /**< is the point in which a cut is generated projected onto the feasible set? */
119  int nauxvars; /**< number of auxiliary variables to use when creating a linear outer approx. of a SOC3 constraint */
120  SCIP_Bool sparsify; /**< whether to sparsify cuts */
121  SCIP_Real sparsifymaxloss; /**< maximal loss in cut efficacy by sparsification */
122  SCIP_Real sparsifynzgrowth; /**< growth rate of maximal allowed nonzeros in cuts in sparsification */
123  SCIP_Bool linfeasshift; /**< whether to try to make solutions feasible in check by shifting the variable on the right hand side */
124  char nlpform; /**< formulation of SOC constraint in NLP */
125  SCIP_Real sepanlpmincont; /**< minimal required fraction of continuous variables in problem to use solution of NLP relaxation in root for separation */
126  SCIP_Bool enfocutsremovable; /**< are cuts added during enforcement removable from the LP in the same node? */
127  SCIP_Bool generalsocupg; /**< try to upgrade more general quadratics to soc? */
128  SCIP_Bool disaggregate; /**< try to completely disaggregate soc? */
129 
130  SCIP_NODE* lastenfonode; /**< the node for which enforcement was called the last time (and some constraint was violated) */
131  int nenforounds; /**< counter on number of enforcement rounds for the current node */
132 };
133 
134 
135 /*
136  * Local methods
137  */
138 
139 /** catch left hand side variable events */
140 static
142  SCIP* scip, /**< SCIP data structure */
143  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
144  SCIP_CONS* cons, /**< constraint for which to catch bound change events */
145  int varidx /**< index of the variable which events to catch */
146  )
147 {
148  SCIP_CONSDATA* consdata;
149 
150  assert(scip != NULL);
151  assert(cons != NULL);
152  assert(eventhdlr != NULL);
153 
154  consdata = SCIPconsGetData(cons);
155  assert(consdata != NULL);
156  assert(varidx >= 0);
157  assert(varidx < consdata->nvars);
158  assert(consdata->lhsbndchgeventdata != NULL);
159 
160  consdata->lhsbndchgeventdata[varidx].cons = cons;
161  consdata->lhsbndchgeventdata[varidx].varidx = varidx;
162  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[varidx], SCIP_EVENTTYPE_BOUNDTIGHTENED, eventhdlr,
163  (SCIP_EVENTDATA*)&consdata->lhsbndchgeventdata[varidx], &consdata->lhsbndchgeventdata[varidx].filterpos) );
164 
165  /* since bound changes were not catched before, a possibly stored activity may have become outdated */
166  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
167 
168  return SCIP_OKAY;
169 }
170 
171 /** catch right hand side variable events */
172 static
174  SCIP* scip, /**< SCIP data structure */
175  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
176  SCIP_CONS* cons /**< constraint for which to catch bound change events */
177  )
178 {
179  SCIP_CONSDATA* consdata;
180 
181  assert(scip != NULL);
182  assert(cons != NULL);
183  assert(eventhdlr != NULL);
184 
185  consdata = SCIPconsGetData(cons);
186  assert(consdata != NULL);
187 
188  consdata->rhsbndchgeventdata.cons = cons;
189  consdata->rhsbndchgeventdata.varidx = -1;
190  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->rhsvar, SCIP_EVENTTYPE_UBTIGHTENED, eventhdlr,
191  (SCIP_EVENTDATA*)&consdata->rhsbndchgeventdata, &consdata->rhsbndchgeventdata.filterpos) );
192 
193  /* since bound changes were not catched before, a possibly stored activity may have become outdated */
194  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
195 
196  return SCIP_OKAY;
197 }
198 
199 /** catch variables events */
200 static
202  SCIP* scip, /**< SCIP data structure */
203  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
204  SCIP_CONS* cons /**< constraint for which to catch bound change events */
205  )
206 {
207  SCIP_CONSDATA* consdata;
208  int i;
209 
210  assert(scip != NULL);
211  assert(cons != NULL);
212  assert(eventhdlr != NULL);
213 
214  consdata = SCIPconsGetData(cons);
215  assert(consdata != NULL);
216  assert(consdata->lhsbndchgeventdata == NULL);
217 
218  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->lhsbndchgeventdata, consdata->nvars) );
219 
220  for( i = 0; i < consdata->nvars; ++i )
221  {
222  if( consdata->vars[i] != NULL )
223  {
224  SCIP_CALL( catchLhsVarEvents(scip, eventhdlr, cons, i) );
225  }
226  }
227 
228  if( consdata->rhsvar != NULL )
229  {
230  SCIP_CALL( catchRhsVarEvents(scip, eventhdlr, cons) );
231  }
232 
233  return SCIP_OKAY;
234 }
235 
236 /** drop left hand side variable events */
237 static
239  SCIP* scip, /**< SCIP data structure */
240  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
241  SCIP_CONS* cons, /**< constraint for which to catch bound change events */
242  int varidx /**< index of the variable which events to catch */
243  )
244 {
245  SCIP_CONSDATA* consdata;
246 
247  assert(scip != NULL);
248  assert(cons != NULL);
249  assert(eventhdlr != NULL);
250 
251  consdata = SCIPconsGetData(cons);
252  assert(consdata != NULL);
253  assert(varidx >= 0);
254  assert(varidx < consdata->nvars);
255  assert(consdata->lhsbndchgeventdata != NULL);
256  assert(consdata->lhsbndchgeventdata[varidx].varidx == varidx);
257 
258  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[varidx], SCIP_EVENTTYPE_BOUNDTIGHTENED, eventhdlr,
259  (SCIP_EVENTDATA*)&consdata->lhsbndchgeventdata[varidx], consdata->lhsbndchgeventdata[varidx].filterpos) );
260 
261  return SCIP_OKAY;
262 }
263 
264 /** drop right hand side variable events */
265 static
267  SCIP* scip, /**< SCIP data structure */
268  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
269  SCIP_CONS* cons /**< constraint for which to catch bound change events */
270  )
271 {
272  SCIP_CONSDATA* consdata;
273 
274  assert(scip != NULL);
275  assert(cons != NULL);
276  assert(eventhdlr != NULL);
277 
278  consdata = SCIPconsGetData(cons);
279  assert(consdata != NULL);
280  assert(consdata->rhsbndchgeventdata.varidx == -1);
281 
282  SCIP_CALL( SCIPdropVarEvent(scip, consdata->rhsvar, SCIP_EVENTTYPE_UBTIGHTENED, eventhdlr,
283  (SCIP_EVENTDATA*)&consdata->rhsbndchgeventdata, consdata->rhsbndchgeventdata.filterpos) );
284 
285  return SCIP_OKAY;
286 }
287 
288 /** drop variable events */
289 static
291  SCIP* scip, /**< SCIP data structure */
292  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
293  SCIP_CONS* cons /**< constraint for which to catch bound change events */
294  )
295 {
296  SCIP_CONSDATA* consdata;
297  int i;
298 
299  assert(scip != NULL);
300  assert(eventhdlr != NULL);
301  assert(cons != NULL);
302 
303  consdata = SCIPconsGetData(cons);
304  assert(consdata != NULL);
305 
306  for( i = 0; i < consdata->nvars; ++i )
307  {
308  if( consdata->vars[i] != NULL )
309  {
310  SCIP_CALL( dropLhsVarEvents(scip, eventhdlr, cons, i) );
311  }
312  }
313 
314  SCIPfreeBlockMemoryArray(scip, &consdata->lhsbndchgeventdata, consdata->nvars);
315 
316  if( consdata->rhsvar != NULL )
317  {
318  SCIP_CALL( dropRhsVarEvents(scip, eventhdlr, cons) );
319  }
320 
321  return SCIP_OKAY;
322 }
323 
324 /** process variable bound tightening event */
325 static
326 SCIP_DECL_EVENTEXEC(processVarEvent)
327 {
328  SCIP_CONS* cons;
329 
330  assert(scip != NULL);
331  assert(event != NULL);
332  assert(eventdata != NULL);
333  assert(eventhdlr != NULL);
334 
335  cons = ((VAREVENTDATA*)eventdata)->cons;
336  assert(cons != NULL);
337 
338  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
339  /* @todo look at bounds on x_i to decide whether propagation makes sense */
340 
341  return SCIP_OKAY;
342 }
343 
344 /** create a nonlinear row representation of the constraint and stores them in consdata */
345 static
347  SCIP* scip, /**< SCIP data structure */
348  SCIP_CONSHDLR* conshdlr, /**< SOC constraint handler */
349  SCIP_CONS* cons /**< SOC constraint */
350  )
351 {
352  SCIP_CONSHDLRDATA* conshdlrdata;
353  SCIP_CONSDATA* consdata;
354  char nlpform;
355  int i;
356 
357  assert(scip != NULL);
358  assert(cons != NULL);
359 
360  conshdlrdata = SCIPconshdlrGetData(conshdlr);
361  assert(conshdlrdata != NULL);
362 
363  consdata = SCIPconsGetData(cons);
364  assert(consdata != NULL);
365 
366  if( consdata->nlrow != NULL )
367  {
368  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
369  }
370 
371  nlpform = conshdlrdata->nlpform;
372  if( nlpform == 'a' )
373  {
374  /* if the user let us choose, then we take 's' for "small" SOC constraints, but 'q' for large ones,
375  * since the 's' form leads to nvars^2 elements in Hessian, while the 'q' form yields only n elements
376  * however, if there is no expression interpreter, then the NLPI may have trouble, so we always use 'q' in this case
377  */
378  if( consdata->nvars < 100 && conshdlrdata->haveexprint )
379  nlpform = 's';
380  else
381  nlpform = 'q';
382  }
383 
384  switch( nlpform )
385  {
386  case 'e':
387  {
388  /* construct expression exp(\sqrt{\gamma + \sum_{i=1}^{n} (\alpha_i\, (x_i + \beta_i))^2} - alpha_{n+1}(x_{n+1} + beta_{n+1})) */
389 
390  if( consdata->nvars > 0 )
391  {
392  SCIP_EXPR* expr;
393  SCIP_EXPR* exprterm;
394  SCIP_EXPR* expr2;
395  SCIP_EXPRTREE* exprtree;
396 
397  if( consdata->constant != 0.0 )
398  {
399  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprterm, SCIP_EXPR_CONST, consdata->constant) ); /* gamma */
400  }
401  else
402  {
403  exprterm = NULL;
404  }
405 
406  for( i = 0; i < consdata->nvars; ++i )
407  {
408  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, i) ); /* x_i */
409  if( consdata->offsets[i] != 0.0 )
410  {
411  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, consdata->offsets[i]) ); /* beta_i */
412  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_PLUS, expr, expr2) ); /* x_i + beta_i */
413  }
414  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_SQUARE, expr) ); /* (x_i + beta_i)^2 */
415  if( consdata->coefs[i] != 1.0 )
416  {
417  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, SQR(consdata->coefs[i])) ); /* (alpha_i)^2 */
418  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_MUL, expr, expr2) ); /* (alpha_i)^2 * (x_i + beta_i)^2 */
419  }
420  if( exprterm != NULL )
421  {
422  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprterm, SCIP_EXPR_PLUS, exprterm, expr) );
423  }
424  else
425  {
426  exprterm = expr;
427  }
428  }
429 
430  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprterm, SCIP_EXPR_SQRT, exprterm) ); /* sqrt(gamma + sum_i (...)^2) */
431 
432  if( consdata->rhsvar != NULL )
433  {
434  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, consdata->nvars) ); /* x_{n+1} */
435  if( consdata->rhsoffset != 0.0 )
436  {
437  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, consdata->rhsoffset) ); /* beta_{n+1} */
438  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_PLUS, expr, expr2) ); /* x_{n+1} + beta_{n+1} */
439  }
440  if( consdata->rhscoeff != 1.0 )
441  {
442  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, consdata->rhscoeff) ); /* alpha_{n+1} */
443  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_MUL, expr, expr2) ); /* alpha_{n+1} * (x_{n+1} + beta_{n+1}) */
444  }
445  }
446  else
447  {
448  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_CONST, consdata->rhscoeff * consdata->rhsoffset) );
449  }
450  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprterm, SCIP_EXPR_MINUS, exprterm, expr) ); /* sqrt(gamma + sum_i (...)^2) - alpha_{n+1} * (x_{n+1} + beta_{n+1}) */
451 
452  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprterm, SCIP_EXPR_EXP, exprterm) ); /* exp(sqrt(gamma + sum_i (...)^2) - alpha_{n+1} * (x_{n+1} + beta_{n+1})) */
453 
454  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, exprterm, consdata->nvars+1, 0, NULL) );
455 
456  SCIP_CALL( SCIPexprtreeSetVars(exprtree, consdata->nvars, consdata->vars) );
457  SCIP_CALL( SCIPexprtreeAddVars(exprtree, 1, &consdata->rhsvar) );
458 
459  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
460  0.0,
461  0, NULL, NULL,
462  0, NULL, 0, NULL,
463  exprtree, -SCIPinfinity(scip), 1.0,
465 
466  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
467 
468  break;
469  }
470  /* if there are no left-hand-side variables, then we let the 's' case handle it */
471  } /*lint -fallthrough */
472 
473  case 's':
474  {
475  /* construct expression \sqrt{\gamma + \sum_{i=1}^{n} (\alpha_i\, (x_i + \beta_i))^2} */
476 
477  SCIP_EXPR* expr;
478  SCIP_EXPR* exprterm;
479  SCIP_EXPR* expr2;
480  SCIP_EXPRTREE* exprtree;
481  SCIP_Real lincoef;
482 
483  if( consdata->constant != 0.0 )
484  {
485  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprterm, SCIP_EXPR_CONST, consdata->constant) ); /* gamma */
486  }
487  else
488  {
489  exprterm = NULL;
490  }
491 
492  for( i = 0; i < consdata->nvars; ++i )
493  {
494  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_VARIDX, i) ); /* x_i */
495  if( consdata->offsets[i] != 0.0 )
496  {
497  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, consdata->offsets[i]) ); /* beta_i */
498  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_PLUS, expr, expr2) ); /* x_i + beta_i */
499  }
500  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_SQUARE, expr) ); /* (x_i + beta_i)^2 */
501  if( consdata->coefs[i] != 1.0 )
502  {
503  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr2, SCIP_EXPR_CONST, SQR(consdata->coefs[i])) ); /* (alpha_i)^2 */
504  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_MUL, expr, expr2) ); /* (alpha_i)^2 * (x_i + beta_i)^2 */
505  }
506  if( exprterm != NULL )
507  {
508  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprterm, SCIP_EXPR_PLUS, exprterm, expr) );
509  }
510  else
511  {
512  exprterm = expr;
513  }
514  }
515 
516  if( exprterm != NULL )
517  {
518  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprterm, SCIP_EXPR_SQRT, exprterm) ); /* sqrt(gamma + sum_i (...)^2) */
519  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, exprterm, consdata->nvars, 0, NULL) );
520  SCIP_CALL( SCIPexprtreeSetVars(exprtree, consdata->nvars, consdata->vars) );
521  }
522  else
523  {
524  assert(consdata->nvars == 0);
525  assert(consdata->constant == 0.0);
526  exprtree = NULL;
527  }
528 
529  /* linear and constant part is -\alpha_{n+1} (x_{n+1}+\beta_{n+1}) */
530  lincoef = -consdata->rhscoeff;
531  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
532  -consdata->rhscoeff * consdata->rhsoffset,
533  1, &consdata->rhsvar, &lincoef,
534  0, NULL, 0, NULL,
535  exprtree, -SCIPinfinity(scip), 0.0,
537 
538  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
539 
540  break;
541  }
542 
543  case 'q':
544  {
545  /* construct quadratic form gamma + sum_{i=1}^{n} (alpha_i (x_i + beta_i))^2 <= (alpha_{n+1} (x_{n+1} + beta_{n+1})^2 */
546  SCIP_QUADELEM sqrterm;
547  SCIP_EXPRCURV curvature;
548  SCIP_Real rhs;
549  int rhsvarpos;
550 
551  /* the expression is convex if alpha_{n+1} is zero */
552  curvature = consdata->rhscoeff == 0.0 ? SCIP_EXPRCURV_CONVEX : SCIP_EXPRCURV_UNKNOWN;
553 
554  /* create initial empty row with left hand side variables */
555  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons), 0.0,
556  0, NULL, NULL,
557  consdata->nvars, consdata->vars, 0, NULL,
558  NULL, -SCIPinfinity(scip), 0.0,
559  curvature) );
560 
561  /* add gamma + sum_{i=1}^{n} (alpha_i x_i)^2 + 2 alpha_i beta_i x_i + beta_i^2 */
562  rhs = -consdata->constant;
563  for( i = 0; i < consdata->nvars; ++i )
564  {
565  sqrterm.idx1 = i;
566  sqrterm.idx2 = i;
567  sqrterm.coef = consdata->coefs[i] * consdata->coefs[i];
568  SCIP_CALL( SCIPaddQuadElementToNlRow(scip, consdata->nlrow, sqrterm) );
569 
570  if( ! SCIPisZero(scip, consdata->offsets[i]) )
571  {
572  rhs -= consdata->offsets[i] * consdata->offsets[i];
573  SCIP_CALL( SCIPaddLinearCoefToNlRow(scip, consdata->nlrow, consdata->vars[i], 2.0 * consdata->coefs[i] * consdata->offsets[i]) );
574  }
575  }
576 
577  /* add rhsvar to quadvars of nlrow, if not there yet */
578  rhsvarpos = SCIPnlrowSearchQuadVar(consdata->nlrow, consdata->rhsvar);
579  if( rhsvarpos == -1 )
580  {
581  SCIP_CALL( SCIPaddQuadVarToNlRow(scip, consdata->nlrow, consdata->rhsvar) );
582  rhsvarpos = SCIPnlrowSearchQuadVar(consdata->nlrow, consdata->rhsvar);
583  assert(rhsvarpos >= 0);
584  }
585 
586  /* add -(alpha_{n+1} x_{n+1))^2 - 2 alpha_{n+1} beta_{n+1} x_{n+1} - beta_{n+1}^2 */
587  sqrterm.idx1 = rhsvarpos;
588  sqrterm.idx2 = rhsvarpos;
589  sqrterm.coef = -consdata->rhscoeff * consdata->rhscoeff;
590  SCIP_CALL( SCIPaddQuadElementToNlRow(scip, consdata->nlrow, sqrterm) );
591 
592  if( consdata->rhsoffset != 0.0 )
593  {
594  rhs += consdata->rhsoffset * consdata->rhsoffset;
595  SCIP_CALL( SCIPaddLinearCoefToNlRow(scip, consdata->nlrow, consdata->rhsvar, -2.0 * consdata->rhscoeff * consdata->rhsoffset) );
596  }
597 
598  SCIP_CALL( SCIPchgNlRowRhs(scip, consdata->nlrow, rhs) );
599 
600  break;
601  }
602 
603  case 'd':
604  {
605  /* construct division form (gamma + sum_{i=1}^n (alpha_i(x_i+beta_i))^2)/(alpha_{n+1}(x_{n+1}+beta_{n+1})) <= alpha_{n+1}(x_{n+1}+beta_{n+1}) */
606  SCIP_EXPRTREE* exprtree;
607  SCIP_EXPR* expr;
608  SCIP_EXPR* nominator;
609  SCIP_EXPR* denominator;
610  SCIP_EXPR** exprs;
611  SCIP_EXPRDATA_MONOMIAL** monomials;
612  SCIP_Real lincoef;
613  SCIP_Real one;
614  SCIP_Real two;
615 
616  SCIP_CALL( SCIPallocBufferArray(scip, &exprs, consdata->nvars) );
617  SCIP_CALL( SCIPallocBufferArray(scip, &monomials, consdata->nvars) );
618  one = 1.0;
619  two = 2.0;
620 
621  for( i = 0; i < consdata->nvars; ++i )
622  {
623  /* put x_i + beta_i into exprs[i] */
624  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &exprs[i], SCIP_EXPR_VARIDX, i) );
625  if( consdata->offsets[i] != 0.0 )
626  {
627  SCIP_CALL( SCIPexprCreateLinear(SCIPblkmem(scip), &exprs[i], 1, &exprs[i], &one, consdata->offsets[i]) );
628  }
629 
630  /* create monomial alpha_i^2 y_i^2, where y_i will be x_i + beta_i */
631  SCIP_CALL( SCIPexprCreateMonomial(SCIPblkmem(scip), &monomials[i], consdata->coefs[i] * consdata->coefs[i], 1, &i, &two) );
632  }
633 
634  /* setup polynomial expression for gamma + sum_{i=1}^n alpha_i^2 (x_i+beta_i)^2 */
635  SCIP_CALL( SCIPexprCreatePolynomial(SCIPblkmem(scip), &nominator, consdata->nvars, exprs, consdata->nvars, monomials, consdata->constant, FALSE) ); /*lint !e850 */
636 
637  SCIPfreeBufferArray(scip, &monomials);
638  SCIPfreeBufferArray(scip, &exprs);
639 
640  /* setup alpha_{n+1}(x_{n+1}+beta_{n+1})
641  * assert that this term is >= 0.0 (otherwise constraint is infeasible anyway) */
642  assert(consdata->rhsvar != NULL);
643  assert((consdata->rhscoeff >= 0.0 && !SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->rhsvar) + consdata->rhsoffset)) ||
644  (consdata->rhscoeff <= 0.0 && !SCIPisPositive(scip, SCIPvarGetUbGlobal(consdata->rhsvar) + consdata->rhsoffset)));
645  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &denominator, SCIP_EXPR_VARIDX, consdata->nvars) );
646  if( consdata->rhscoeff != 1.0 || consdata->rhsoffset != 0.0 )
647  {
648  SCIP_CALL( SCIPexprCreateLinear(SCIPblkmem(scip), &denominator, 1, &denominator, &consdata->rhscoeff, consdata->rhscoeff * consdata->rhsoffset) );
649  }
650 
651  /* setup nominator/denominator */
652  SCIP_CALL( SCIPexprCreate(SCIPblkmem(scip), &expr, SCIP_EXPR_DIV, nominator, denominator) );
653 
654  SCIP_CALL( SCIPexprtreeCreate(SCIPblkmem(scip), &exprtree, expr, 0, 0, NULL) );
655  SCIP_CALL( SCIPexprtreeSetVars(exprtree, consdata->nvars, consdata->vars) );
656  SCIP_CALL( SCIPexprtreeAddVars(exprtree, 1, &consdata->rhsvar) );
657 
658  /* linear and constant part is -\alpha_{n+1} (x_{n+1}+\beta_{n+1}) */
659  lincoef = -consdata->rhscoeff;
660  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
661  -consdata->rhscoeff * consdata->rhsoffset,
662  1, &consdata->rhsvar, &lincoef,
663  0, NULL, 0, NULL,
664  exprtree, -SCIPinfinity(scip), 0.0,
666 
667  SCIP_CALL( SCIPexprtreeFree(&exprtree) );
668 
669  break;
670  }
671 
672  default:
673  SCIPerrorMessage("unknown value for nlp formulation parameter\n");
674  return SCIP_ERROR;
675  }
676 
677  SCIPdebugMsg(scip, "created nonlinear row representation of SOC constraint\n");
678  SCIPdebugPrintCons(scip, cons, NULL);
679  SCIPdebug( SCIP_CALL( SCIPprintNlRow(scip, consdata->nlrow, NULL) ) );
680 
681  return SCIP_OKAY;
682 }
683 
684 /** evaluates the left hand side of a SOC constraint */
685 static
687  SCIP* scip, /**< SCIP data structure */
688  SCIP_CONS* cons, /**< constraint to evaluate */
689  SCIP_SOL* sol /**< solution to evaluate, or NULL if LP solution should be used */
690  )
691 {
692  SCIP_CONSDATA* consdata;
693  SCIP_VAR* var;
694  SCIP_Real val;
695  int i;
696 
697  assert(scip != NULL);
698  assert(cons != NULL);
699 
700  consdata = SCIPconsGetData(cons);
701  assert(consdata != NULL);
702 
703  consdata->lhsval = consdata->constant;
704 
705  for( i = 0; i < consdata->nvars; ++i )
706  {
707  var = consdata->vars[i];
708  val = SCIPgetSolVal(scip, sol, var);
709 
710  if( SCIPisInfinity(scip, val) || SCIPisInfinity(scip, -val) )
711  {
712  consdata->lhsval = SCIPinfinity(scip);
713  return SCIP_OKAY;
714  }
715 
716  val = consdata->coefs[i] * (val + consdata->offsets[i]);
717  consdata->lhsval += val * val;
718  }
719  consdata->lhsval = sqrt(consdata->lhsval);
720 
721  return SCIP_OKAY;
722 }
723 
724 /** computes violation of a SOC constraint */
725 static
727  SCIP* scip, /**< SCIP data structure */
728  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
729  SCIP_CONS* cons, /**< constraint to evaluate */
730  SCIP_SOL* sol /**< solution to evaluate, or NULL if LP solution should be used */
731  )
732 {
733  SCIP_CONSDATA* consdata;
734  SCIP_Real rhsval;
735  SCIP_Real rhs;
736  SCIP_Real absviol;
737  SCIP_Real relviol;
738 
739  assert(scip != NULL);
740  assert(conshdlr != NULL);
741  assert(cons != NULL);
742 
743  consdata = SCIPconsGetData(cons);
744  assert(consdata != NULL);
745 
746  SCIP_CALL( evalLhs(scip, cons, sol) );
747 
748  if( SCIPisInfinity(scip, consdata->lhsval) )
749  {
750  /* infinity <= infinity is feasible
751  * infinity <= finite value is not feasible and has violation infinity
752  */
753  if( (consdata->rhscoeff > 0.0 && SCIPisInfinity(scip, SCIPgetSolVal(scip, sol, consdata->rhsvar))) ||
754  ( consdata->rhscoeff < 0.0 && SCIPisInfinity(scip, -SCIPgetSolVal(scip, sol, consdata->rhsvar))) )
755  consdata->violation = 0.0;
756  else
757  consdata->violation = SCIPinfinity(scip);
758  return SCIP_OKAY;
759  }
760 
761  rhsval = SCIPgetSolVal(scip, sol, consdata->rhsvar);
762  if( SCIPisInfinity(scip, rhsval) )
763  {
764  consdata->violation = consdata->rhscoeff > 0.0 ? 0.0 : SCIPinfinity(scip);
765  return SCIP_OKAY;
766  }
767  if( SCIPisInfinity(scip, -rhsval) )
768  {
769  consdata->violation = consdata->rhscoeff < 0.0 ? 0.0 : SCIPinfinity(scip);
770  return SCIP_OKAY;
771  }
772 
773  rhs = consdata->rhscoeff * (rhsval + consdata->rhsoffset);
774  consdata->violation = consdata->lhsval - rhs;
775  absviol = consdata->violation;
776  relviol = SCIPrelDiff(consdata->lhsval, rhs);
777  if( consdata->violation <= 0.0 )
778  {
779  /* constraint is not violated for sure */
780  consdata->violation = 0.0;
781  return SCIP_OKAY;
782  }
783 
784  if( sol != NULL )
785  SCIPupdateSolConsViolation(scip, sol, absviol, relviol);
786 
787  return SCIP_OKAY;
788 }
789 
790 /** computes violations for a set of constraints */
791 static
793  SCIP* scip, /**< SCIP data structure */
794  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
795  SCIP_CONS** conss, /**< constraints to evaluate */
796  int nconss, /**< number of constraints to evaluate */
797  SCIP_SOL* sol, /**< solution to evaluate, or NULL if LP solution should be used */
798  SCIP_CONS** maxviolcons /**< a buffer to store pointer to maximal violated constraint, or NULL if of no interest */
799  )
800 {
801  SCIP_CONSDATA* consdata;
802  SCIP_Real maxviol = 0.0;
803  int c;
804 
805  assert(scip != NULL);
806  assert(conss != NULL || nconss == 0);
807 
808  if( maxviolcons != NULL )
809  *maxviolcons = NULL;
810 
811  for( c = 0; c < nconss; ++c )
812  {
813  SCIP_CALL( computeViolation(scip, conshdlr, conss[c], sol) ); /*lint !e613*/
814  if( maxviolcons != NULL )
815  {
816  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
817  assert(consdata != NULL);
818  if( consdata->violation > maxviol && SCIPisGT(scip, consdata->violation, SCIPfeastol(scip)) )
819  {
820  maxviol = consdata->violation;
821  *maxviolcons = conss[c]; /*lint !e613*/
822  }
823  }
824  }
825 
826  return SCIP_OKAY;
827 }
828 
829 /** generate supporting hyperplane in a given solution */
830 static
832  SCIP* scip, /**< SCIP pointer */
833  SCIP_CONS* cons, /**< constraint */
834  SCIP_SOL* sol, /**< solution to separate, or NULL for LP solution */
835  SCIP_ROWPREP** rowprep /**< place to store cut */
836  )
837 {
838  SCIP_CONSDATA* consdata;
839  SCIP_Real val;
840  int i;
841 
842  assert(scip != NULL);
843  assert(cons != NULL);
844  assert(rowprep != NULL);
845 
846  consdata = SCIPconsGetData(cons);
847  assert(consdata != NULL);
848 
849  assert(SCIPisPositive(scip, consdata->lhsval)); /* do not like to linearize in 0 */
850  assert(!SCIPisInfinity(scip, consdata->lhsval));
851 
853  SCIP_CALL( SCIPensureRowprepSize(scip, *rowprep, consdata->nvars+1) );
854  (void) SCIPsnprintf((*rowprep)->name, SCIP_MAXSTRLEN, "%s_linearization_%d", SCIPconsGetName(cons), SCIPgetNLPs(scip));
855 
856  for( i = 0; i < consdata->nvars; ++i )
857  {
858  val = SCIPgetSolVal(scip, sol, consdata->vars[i]) + consdata->offsets[i];
859  val *= consdata->coefs[i] * consdata->coefs[i];
860 
861  SCIP_CALL( SCIPaddRowprepTerm(scip, *rowprep, consdata->vars[i], val / consdata->lhsval) );
862 
863  val *= SCIPgetSolVal(scip, sol, consdata->vars[i]);
864  SCIPaddRowprepSide(*rowprep, val);
865  }
866  (*rowprep)->side /= consdata->lhsval;
867  (*rowprep)->side -= consdata->lhsval - consdata->rhscoeff * consdata->rhsoffset;
868 
869  SCIP_CALL( SCIPaddRowprepTerm(scip, *rowprep, consdata->rhsvar, -consdata->rhscoeff) );
870 
871  return SCIP_OKAY;
872 }
873 
874 /** generate supporting hyperplane in a given point */
875 static
877  SCIP* scip, /**< SCIP pointer */
878  SCIP_CONS* cons, /**< constraint */
879  SCIP_Real* x, /**< point (lhs-vars) where to generate cut */
880  SCIP_ROWPREP** rowprep /**< place to store cut */
881  )
882 {
883  SCIP_CONSDATA* consdata;
884  SCIP_Real lhsval;
885  SCIP_Real val;
886  int i;
887 
888  assert(scip != NULL);
889  assert(cons != NULL);
890  assert(rowprep != NULL);
891 
892  consdata = SCIPconsGetData(cons);
893  assert(consdata != NULL);
894 
895  lhsval = consdata->constant;
896  for( i = 0; i < consdata->nvars; ++i )
897  {
898  assert(!SCIPisInfinity(scip, ABS(x[i])));
899 
900  val = consdata->coefs[i] * (x[i] + consdata->offsets[i]);
901  lhsval += val * val;
902  }
903  lhsval = sqrt(lhsval);
904 
905  if( SCIPisZero(scip, lhsval) )
906  { /* do not like to linearize in 0 */
907  return SCIP_OKAY;
908  }
909 
911  SCIP_CALL( SCIPensureRowprepSize(scip, *rowprep, consdata->nvars+1) );
912  (void) SCIPsnprintf((*rowprep)->name, SCIP_MAXSTRLEN, "%s_linearization_%d", SCIPconsGetName(cons), SCIPgetNLPs(scip));
913 
914  for( i = 0; i < consdata->nvars; ++i )
915  {
916  val = x[i] + consdata->offsets[i];
917  if( SCIPisZero(scip, val) )
918  continue;
919 
920  val *= consdata->coefs[i] * consdata->coefs[i];
921 
922  SCIP_CALL( SCIPaddRowprepTerm(scip, *rowprep, consdata->vars[i], val / lhsval) );
923 
924  val *= x[i];
925  SCIPaddRowprepSide(*rowprep, val);
926  }
927  (*rowprep)->side /= lhsval;
928  (*rowprep)->side -= lhsval - consdata->rhscoeff * consdata->rhsoffset;
929 
930  SCIP_CALL( SCIPaddRowprepTerm(scip, *rowprep, consdata->rhsvar, -consdata->rhscoeff) );
931 
932  return SCIP_OKAY;
933 }
934 
935 /** generate supporting hyperplane w.r.t. solution projected on feasible set
936  *
937  * Instead of linearizing the SOC constraint in the given solution point, this function projects the point
938  * first onto the feasible set of the SOC constraint (w.r.t. euclidean norm (scaled by alpha))
939  * and linearizes the SOC constraint there.
940  * The hope is that this produces somewhat tighter cuts.
941  *
942  * The projection has only be computed for the case gamma = 0.
943  * If gamma > 0, generateCut is called.
944  *
945  * Let \f$\hat x\f$ be sol or the LP solution if sol == NULL.
946  * Then the projected point \f$\tilde x\f$ is given by
947  * \f[
948  * \tilde x_i = \frac{\hat x_i + \lambda \beta_i}{1-\lambda}, \quad i=1,\ldots, n; \quad
949  * \tilde x_{n+1} = \frac{\hat x_{n+1} - \lambda \beta_{n+1}}{1+\lambda}
950  * \f]
951  * where
952  * \f[
953  * \lambda = \frac{1-A}{1+A}, \qquad
954  * A = \frac{\alpha_{n+1}(\hat x_{n+1}+\beta_{n+1})}{\sqrt{\sum_{i=1}^n (\alpha_i(\hat x_i+\beta_i))^2}}
955  * \f]
956  *
957  * If lambda is very close to 1, generateCut is called.
958  *
959  * The generated cut is very similar to the unprojected form.
960  * The only difference is in the right hand side, which is (in the case beta = 0) multiplied by 1/(1-lambda).
961  */
962 static
964  SCIP* scip, /**< SCIP pointer */
965  SCIP_CONS* cons, /**< constraint */
966  SCIP_SOL* sol, /**< solution to separate, or NULL for LP solution */
967  SCIP_ROWPREP** rowprep /**< place to store cut */
968  )
969 {
970  SCIP_CONSDATA* consdata;
971  SCIP_Real val;
972  SCIP_Real A, lambda;
973  int i;
974 
975  assert(scip != NULL);
976  assert(cons != NULL);
977  assert(rowprep != NULL);
978 
979  consdata = SCIPconsGetData(cons);
980  assert(consdata != NULL);
981 
982  assert(SCIPisPositive(scip, consdata->lhsval)); /* do not like to linearize in 0 */
983  assert(!SCIPisInfinity(scip, consdata->lhsval));
984 
985  if( !SCIPisZero(scip, consdata->constant) )
986  { /* have not thought about this case yet */
987  SCIP_CALL( generateCutSol(scip, cons, sol, rowprep) );
988  return SCIP_OKAY;
989  }
990 
991  A = consdata->rhscoeff * (SCIPgetSolVal(scip, sol, consdata->rhsvar) + consdata->rhsoffset);
992  A /= consdata->lhsval;
993 
994  lambda = (1.0 - A) / (1.0 + A);
995 
996  assert(!SCIPisNegative(scip, lambda)); /* otherwise A > 1, so constraint is not violated */
997 
998  SCIPdebugMsg(scip, "A = %g \t lambda = %g\n", A, lambda);
999 
1000  if( SCIPisFeasEQ(scip, lambda, 1.0) )
1001  { /* avoid numerical difficulties when dividing by (1-lambda) below */
1002  SCIP_CALL( generateCutSol(scip, cons, sol, rowprep) );
1003  return SCIP_OKAY;
1004  }
1005 
1007  SCIP_CALL( SCIPensureRowprepSize(scip, *rowprep, consdata->nvars+1) );
1008  (void) SCIPsnprintf((*rowprep)->name, SCIP_MAXSTRLEN, "%s_linearization_%d", SCIPconsGetName(cons), SCIPgetNLPs(scip));
1009 
1010  for( i = 0; i < consdata->nvars; ++i )
1011  {
1012  val = SCIPgetSolVal(scip, sol, consdata->vars[i]) + consdata->offsets[i];
1013  val *= consdata->coefs[i] * consdata->coefs[i];
1014 
1015  SCIP_CALL( SCIPaddRowprepTerm(scip, *rowprep, consdata->vars[i], val / consdata->lhsval) );
1016 
1017  val *= SCIPgetSolVal(scip, sol, consdata->vars[i]) + lambda * consdata->offsets[i];
1018  SCIPaddRowprepSide(*rowprep, val);
1019  }
1020  (*rowprep)->side /= consdata->lhsval;
1021  (*rowprep)->side-= consdata->lhsval;
1022  (*rowprep)->side /= 1.0 - lambda;
1023  (*rowprep)->side -= consdata->rhscoeff * consdata->rhsoffset;
1024 
1025  SCIP_CALL( SCIPaddRowprepTerm(scip, *rowprep, consdata->rhsvar, -consdata->rhscoeff) );
1026 
1027  return SCIP_OKAY;
1028 }
1029 
1030 /** generates sparsified supporting hyperplane */
1031 static
1033  SCIP* scip, /**< SCIP pointer */
1034  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1035  SCIP_CONS* cons, /**< constraint */
1036  SCIP_SOL* sol, /**< solution to separate, or NULL for LP solution */
1037  SCIP_ROWPREP** rowprep, /**< place to store cut */
1038  SCIP_Real minefficacy /**< minimal efficacy for a cut to be accepted */
1039  )
1040 {
1041  SCIP_CONSHDLRDATA* conshdlrdata;
1042  SCIP_CONSDATA* consdata;
1043  SCIP_Real* x;
1044  SCIP_Real* dist; /* distance to 0 */
1045  int* ind; /* indices */
1046  int i;
1047  int maxnz, nextmaxnz;
1048  SCIP_Real efficacy;
1049  SCIP_Real goodefficacy;
1050 
1051  assert(scip != NULL);
1052  assert(conshdlr != NULL);
1053  assert(cons != NULL);
1054  assert(rowprep != NULL);
1055 
1056  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1057  assert(conshdlrdata != NULL);
1058 
1059  consdata = SCIPconsGetData(cons);
1060  assert(consdata != NULL);
1061 
1062  assert(SCIPisPositive(scip, consdata->lhsval)); /* do not like to linearize in 0 */
1063  assert(!SCIPisInfinity(scip, consdata->lhsval));
1064 
1065  if( consdata->nvars <= 3 )
1066  {
1067  SCIP_CALL( generateCutSol(scip, cons, sol, rowprep) );
1068  return SCIP_OKAY;
1069  }
1070 
1071  goodefficacy = MAX((1.0-conshdlrdata->sparsifymaxloss) * consdata->violation, minefficacy);
1072 
1073  SCIP_CALL( SCIPallocBufferArray(scip, &x, consdata->nvars) );
1074  SCIP_CALL( SCIPallocBufferArray(scip, &dist, consdata->nvars) );
1075  SCIP_CALL( SCIPallocBufferArray(scip, &ind, consdata->nvars) );
1076 
1077  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nvars, consdata->vars, x) );
1078  /* distance to "-offset" * alpha_i^2 should indicate loss when moving refpoint to x[i] = -offset[i] */
1079  for( i = 0; i < consdata->nvars; ++i )
1080  {
1081  ind[i] = i;
1082  dist[i] = ABS(x[i] + consdata->offsets[i]);
1083  dist[i] *= consdata->coefs[i] * consdata->coefs[i];
1084  }
1085 
1086  /* sort variables according to dist */
1087  SCIPsortRealInt(dist, ind, consdata->nvars);
1088 
1089  maxnz = 2;
1090  /* set all except biggest maxnz entries in x to -offset */
1091  for( i = 0; i < consdata->nvars - maxnz; ++i )
1092  x[ind[i]] = -consdata->offsets[i];
1093 
1094  do
1095  {
1096  /* @todo speed up a bit by computing efficacy of new cut from efficacy of old cut
1097  * generate row only if efficient enough
1098  */
1099  SCIP_CALL( generateCutPoint(scip, cons, x, rowprep) );
1100 
1101  if( *rowprep != NULL )
1102  {
1103  efficacy = SCIPgetRowprepViolation(scip, *rowprep, sol);
1104  if( SCIPisGT(scip, efficacy, goodefficacy) ||
1105  (maxnz >= consdata->nvars && SCIPisGT(scip, efficacy, minefficacy)) )
1106  {
1107  /* cut cuts off solution and is efficient enough */
1108  SCIPdebugMsg(scip, "accepted cut with %d of %d nonzeros, efficacy = %g\n", maxnz, consdata->nvars, efficacy);
1109  break;
1110  }
1111 
1112  SCIPfreeRowprep(scip, rowprep);
1113  }
1114 
1115  /* cut also not efficient enough if generated in original refpoint (that's bad) */
1116  if( maxnz >= consdata->nvars )
1117  break;
1118 
1119  nextmaxnz = (int)(conshdlrdata->sparsifynzgrowth * maxnz);
1120  if( nextmaxnz == consdata->nvars - 1)
1121  nextmaxnz = consdata->nvars;
1122  else if( nextmaxnz == maxnz )
1123  ++nextmaxnz;
1124 
1125  /* restore entries of x that are nonzero in next attempt */
1126  for( i = MAX(0, consdata->nvars - nextmaxnz); i < consdata->nvars - maxnz; ++i )
1127  x[ind[i]] = SCIPgetSolVal(scip, sol, consdata->vars[ind[i]]);
1128 
1129  maxnz = nextmaxnz;
1130  }
1131  while( TRUE ); /*lint !e506*/
1132 
1133  SCIPfreeBufferArray(scip, &x);
1134  SCIPfreeBufferArray(scip, &dist);
1135  SCIPfreeBufferArray(scip, &ind);
1136 
1137  return SCIP_OKAY;
1138 }
1139 
1140 /** separates a point, if possible */
1141 static
1143  SCIP* scip, /**< SCIP data structure */
1144  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1145  SCIP_CONS** conss, /**< constraints */
1146  int nconss, /**< number of constraints */
1147  int nusefulconss, /**< number of constraints that seem to be useful */
1148  SCIP_SOL* sol, /**< solution to separate, or NULL for LP solution */
1149  SCIP_Bool inenforcement, /**< whether we are in constraint enforcement */
1150  SCIP_Bool* cutoff, /**< pointer to store whether a fixing leads to a cutoff */
1151  SCIP_Bool* success /**< buffer to store whether the point was separated */
1152  )
1153 {
1154  SCIP_CONSHDLRDATA* conshdlrdata;
1155  SCIP_CONSDATA* consdata;
1156  SCIP_Real minefficacy;
1157  int c;
1158  SCIP_ROW* row;
1159  SCIP_ROWPREP* rowprep;
1160 
1161  assert(scip != NULL);
1162  assert(conss != NULL || nconss == 0);
1163  assert(nusefulconss <= nconss);
1164  assert(cutoff != NULL);
1165  assert(success != NULL);
1166 
1167  *cutoff = FALSE;
1168 
1169  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1170  assert(conshdlrdata != NULL);
1171 
1172  *success = FALSE;
1173 
1174  minefficacy = inenforcement ? SCIPlpfeastol(scip) : SCIPgetSepaMinEfficacy(scip);
1175 
1176  for( c = 0; c < nconss; ++c )
1177  {
1178  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
1179  assert(consdata != NULL);
1180 
1181  if( SCIPisGT(scip, consdata->violation, SCIPfeastol(scip)) && !SCIPisInfinity(scip, consdata->violation) )
1182  {
1183  SCIP_Real efficacy;
1184 
1185  rowprep = NULL;
1186 
1187  /* generate cut */
1188  if( conshdlrdata->sparsify )
1189  {
1190  SCIP_CALL( generateSparseCut(scip, conshdlr, conss[c], sol, &rowprep, minefficacy) ); /*lint !e613*/
1191  }
1192  else if( conshdlrdata->projectpoint )
1193  {
1194  SCIP_CALL( generateCutProjectedPoint(scip, conss[c], sol, &rowprep) ); /*lint !e613*/
1195  }
1196  else
1197  {
1198  SCIP_CALL( generateCutSol(scip, conss[c], sol, &rowprep) ); /*lint !e613*/
1199  }
1200 
1201  if( rowprep == NULL )
1202  continue;
1203 
1204  /* NOTE: The way that rowprep was constructed, there should be no need to call SCIPmergeRowprep,
1205  * since no variable gets added twice. However, if rowprep were replacing multiaggregated variables
1206  * (as there can exist for soc cons), then SCIPmergeRowprep would be necessary.
1207  */
1208  /* cleanup rowprep (there is no limit on coefrange for cons_soc) TODO add a coefrange limit? */
1209  SCIP_CALL( SCIPcleanupRowprep(scip, rowprep, sol, SCIPinfinity(scip), minefficacy, NULL, &efficacy) );
1210 
1211  if( SCIPisLE(scip, efficacy, minefficacy) )
1212  {
1213  SCIPfreeRowprep(scip, &rowprep);
1214  continue;
1215  }
1216 
1217  /* cut cuts off solution and efficient enough */
1218  SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, conshdlr) );
1219  if( SCIPisCutApplicable(scip, row) )
1220  {
1221  SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
1222  SCIP_CALL( SCIPresetConsAge(scip, conss[c]) ); /*lint !e613*/
1223 
1224  *success = TRUE;
1225 
1226  SCIPdebugMsg(scip, "added cut with efficacy %g\n", SCIPgetCutEfficacy(scip, sol, row));
1227 
1228  /* mark row as not removable from LP for current node, if in enforcement */
1229  if( inenforcement && !conshdlrdata->enfocutsremovable )
1230  SCIPmarkRowNotRemovableLocal(scip, row);
1231  }
1232 
1233  SCIP_CALL( SCIPreleaseRow (scip, &row) );
1234  SCIPfreeRowprep(scip, &rowprep);
1235  }
1236 
1237  if( *cutoff )
1238  break;
1239 
1240  /* enforce only useful constraints
1241  * others are only checked and enforced if we are still feasible or have not found a separating cut yet
1242  */
1243  if( c >= nusefulconss && *success )
1244  break;
1245  }
1246 
1247  return SCIP_OKAY;
1248 }
1249 
1250 /** adds linearizations cuts for convex constraints w.r.t. a given reference point to cutpool and sepastore
1251  *
1252  * 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.
1253  * If separatedlpsol is not NULL, but cut does not separate the LP solution, then it is added to the cutpool only.
1254  * If separatedlpsol is NULL, then cut is added to cutpool only.
1255  */
1256 static
1258  SCIP* scip, /**< SCIP data structure */
1259  SCIP_CONSHDLR* conshdlr, /**< quadratic constraints handler */
1260  SCIP_CONS** conss, /**< constraints */
1261  int nconss, /**< number of constraints */
1262  SCIP_SOL* ref, /**< reference point where to linearize, or NULL for LP solution */
1263  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 */
1264  SCIP_Real minefficacy, /**< minimal efficacy of a cut when checking for separation of LP solution */
1265  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was detected */
1266  )
1267 {
1268  SCIP_CONSDATA* consdata;
1269  SCIP_Bool addedtolp;
1270  SCIP_ROWPREP* rowprep;
1271  int c;
1272 
1273  assert(scip != NULL);
1274  assert(conshdlr != NULL);
1275  assert(conss != NULL || nconss == 0);
1276  assert(cutoff != NULL);
1277  *cutoff = FALSE;
1278 
1279  if( separatedlpsol != NULL )
1280  *separatedlpsol = FALSE;
1281 
1282  for( c = 0; c < nconss && !(*cutoff); ++c )
1283  {
1284  assert(conss[c] != NULL); /*lint !e613 */
1285 
1286  if( SCIPconsIsLocal(conss[c]) ) /*lint !e613 */
1287  continue;
1288 
1289  consdata = SCIPconsGetData(conss[c]); /*lint !e613 */
1290  assert(consdata != NULL);
1291 
1292  SCIP_CALL( evalLhs(scip, conss[c], ref) ); /*lint !e613 */
1293  if( !SCIPisPositive(scip, consdata->lhsval) || SCIPisInfinity(scip, consdata->lhsval) )
1294  {
1295  SCIPdebugMsg(scip, "skip adding linearization for <%s> since lhs is %g\n", SCIPconsGetName(conss[c]), consdata->lhsval); /*lint !e613 */
1296  continue;
1297  }
1298 
1299  SCIP_CALL( generateCutSol(scip, conss[c], ref, &rowprep) ); /*lint !e613 */
1300 
1301  if( rowprep == NULL )
1302  continue;
1303 
1304  addedtolp = FALSE;
1305 
1306  /* if caller wants, then check if cut separates LP solution and add to sepastore if so */
1307  if( separatedlpsol != NULL )
1308  {
1309  if( SCIPgetRowprepViolation(scip, rowprep, NULL) >= minefficacy )
1310  {
1311  SCIP_ROW* row;
1312 
1313  SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, conshdlr) );
1314  SCIP_CALL( SCIPaddRow(scip, row, TRUE, cutoff) );
1315  SCIP_CALL( SCIPreleaseRow(scip, &row) );
1316 
1317  *separatedlpsol = TRUE;
1318  addedtolp = TRUE;
1319  }
1320  }
1321 
1322  if( !addedtolp && !rowprep->local )
1323  {
1324  SCIP_ROW* row;
1325 
1326  SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, conshdlr) );
1327  SCIP_CALL( SCIPaddPoolCut(scip, row) );
1328  SCIP_CALL( SCIPreleaseRow(scip, &row) );
1329  }
1330 
1331  SCIPfreeRowprep(scip, &rowprep);
1332  }
1333 
1334  return SCIP_OKAY;
1335 }
1336 
1337 /** processes the event that a new primal solution has been found */
1338 static
1339 SCIP_DECL_EVENTEXEC(processNewSolutionEvent)
1341  SCIP_CONSHDLRDATA* conshdlrdata;
1342  SCIP_CONSHDLR* conshdlr;
1343  SCIP_CONS** conss;
1344  int nconss;
1345  SCIP_SOL* sol;
1346  SCIP_Bool cutoff;
1347 
1348  assert(scip != NULL);
1349  assert(event != NULL);
1350  assert(eventdata != NULL);
1351  assert(eventhdlr != NULL);
1352 
1353  assert((SCIPeventGetType(event) & SCIP_EVENTTYPE_SOLFOUND) != 0);
1354 
1355  conshdlr = (SCIP_CONSHDLR*)eventdata;
1356 
1357  nconss = SCIPconshdlrGetNConss(conshdlr);
1358 
1359  if( nconss == 0 )
1360  return SCIP_OKAY;
1361 
1362  sol = SCIPeventGetSol(event);
1363  assert(sol != NULL);
1364 
1365  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1366  assert(conshdlrdata != NULL);
1367 
1368  /* we are only interested in solution coming from some heuristic other than trysol, but not from the tree
1369  * the reason for ignoring trysol solutions is that they may come from an NLP solve in sepalp, where we already added linearizations,
1370  * or are from the tree, but postprocessed via proposeFeasibleSolution
1371  */
1372  if( SCIPsolGetHeur(sol) == NULL || SCIPsolGetHeur(sol) == conshdlrdata->trysolheur )
1373  return SCIP_OKAY;
1374 
1375  conss = SCIPconshdlrGetConss(conshdlr);
1376  assert(conss != NULL);
1377 
1378  SCIPdebugMsg(scip, "caught new sol event %" SCIP_EVENTTYPE_FORMAT " from heur <%s>; have %d conss\n", SCIPeventGetType(event),
1379  SCIPheurGetName(SCIPsolGetHeur(sol)), nconss);
1380 
1381  SCIP_CALL( addLinearizationCuts(scip, conshdlr, conss, nconss, sol, NULL, 0.0, &cutoff) );
1382  /* ignore cutoff, cannot return status */
1383 
1384  return SCIP_OKAY;
1385 }
1386 
1387 /** removes fixed variables, replace aggregated and negated variables
1388  *
1389  * repeats replacements until no further change is found;
1390  * takes care of capture/release and locks, but not of variable events (assumes that var events are not caught yet)
1391  */
1392 static
1394  SCIP* scip, /**< SCIP data structure */
1395  SCIP_CONSHDLR* conshdlr, /**< constraint handler for signpower constraints */
1396  SCIP_CONS* cons, /**< constraint */
1397  int* ndelconss, /**< counter for number of deleted constraints */
1398  int* nupgdconss, /**< counter for number of upgraded constraints */
1399  int* nchgbds, /**< counter for number of bound changes */
1400  int* nfixedvars, /**< counter for number of fixed variables */
1401  SCIP_Bool* iscutoff, /**< to store whether constraint cannot be satisfied */
1402  SCIP_Bool* isdeleted /**< to store whether constraint is redundant and can be deleted */
1403  )
1404 {
1405  SCIP_CONSDATA* consdata;
1406  SCIP_CONSHDLRDATA* conshdlrdata;
1407  SCIP_Bool havechange;
1408  SCIP_Bool haveremovedvar;
1409  int i;
1410  SCIP_VAR* x;
1411  SCIP_Real coef;
1412  SCIP_Real offset;
1413 
1414  assert(scip != NULL);
1415  assert(conshdlr != NULL);
1416  assert(cons != NULL);
1417  assert(iscutoff != NULL);
1418  assert(isdeleted != NULL);
1419 
1420  *iscutoff = FALSE;
1421  *isdeleted = FALSE;
1422 
1423  consdata = SCIPconsGetData(cons);
1424  assert(consdata != NULL);
1425 
1426  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1427  assert(conshdlrdata != NULL);
1428 
1429  SCIPdebugMsg(scip, "remove fixed variables from constraint <%s>\n", SCIPconsGetName(cons));
1430  SCIPdebugPrintCons(scip, cons, NULL);
1431 
1432  havechange = FALSE;
1433  haveremovedvar = FALSE;
1434 
1435  /* process variables on left hand side */
1436  for( i = 0; i < consdata->nvars; ++i )
1437  {
1438  x = consdata->vars[i];
1439  assert(x != NULL);
1441 
1443  continue;
1444 
1445  havechange = TRUE;
1446 
1447  /* drop variable event and unlock and release variable */
1448  SCIP_CALL( dropLhsVarEvents(scip, conshdlrdata->eventhdlr, cons, i) );
1449  SCIP_CALL( SCIPunlockVarCons(scip, x, cons, TRUE, TRUE) );
1450  SCIP_CALL( SCIPreleaseVar(scip, &consdata->vars[i]) );
1451 
1452  coef = 1.0;
1453  offset = consdata->offsets[i];
1454  SCIP_CALL( SCIPgetProbvarSum(scip, &x, &coef, &offset) );
1455 
1456  SCIPdebugMsg(scip, " lhs term at position %d is replaced by %g * <%s> + %g\n",
1457  i, coef, SCIPvarGetName(x), offset);
1458 
1459  /* if variable has been fixed, add (alpha*offset)^2 to gamma and continue */
1460  if( coef == 0.0 || x == NULL )
1461  {
1462  consdata->constant += consdata->coefs[i] * consdata->coefs[i] * offset * offset;
1463  consdata->offsets[i] = 0.0;
1464  haveremovedvar = TRUE;
1465  continue;
1466  }
1467 
1469 
1470  /* replace coefs[i] * (vars[i] + offsets[i]) by coefs[i]*coef * (x + offsets[i]/coef) */
1471  consdata->offsets[i] = offset;
1472  if( coef != 1.0 )
1473  {
1474  consdata->coefs[i] = REALABS(coef * consdata->coefs[i]);
1475  consdata->offsets[i] /= coef;
1476  }
1477  consdata->vars[i] = x;
1478 
1479  /* capture and lock new variable, catch variable events */
1480  SCIP_CALL( SCIPcaptureVar(scip, consdata->vars[i]) );
1481  SCIP_CALL( SCIPlockVarCons(scip, consdata->vars[i], cons, TRUE, TRUE) );
1482  SCIP_CALL( catchLhsVarEvents(scip, conshdlrdata->eventhdlr, cons, i) );
1483  }
1484 
1485  /* process variable on right hand side */
1486  x = consdata->rhsvar;
1487  assert(x != NULL);
1489  {
1490  havechange = TRUE;
1491 
1492  /* drop variable event and unlock and release variable */
1493  SCIP_CALL( dropRhsVarEvents(scip, conshdlrdata->eventhdlr, cons) );
1494  SCIP_CALL( SCIPreleaseVar(scip, &consdata->rhsvar) );
1495  SCIP_CALL( SCIPunlockVarCons(scip, x, cons, consdata->rhscoeff > 0.0, consdata->rhscoeff < 0.0) );
1496 
1497  coef = 1.0;
1498  offset = 0.0;
1499  SCIP_CALL( SCIPgetProbvarSum(scip, &x, &coef, &offset) );
1500 
1501  SCIPdebugMsg(scip, " rhs variable is replaced by %g * <%s> + %g\n", coef, SCIPvarGetName(x), offset);
1502 
1503  if( coef == 0.0 || x == NULL )
1504  {
1505  /* if variable has been fixed, add offset to rhsoffset */
1506  consdata->rhsoffset += offset;
1507  }
1508  else
1509  {
1510  /* replace rhscoef * (rhsvar + rhsoffset) by rhscoef*coef * (x + offset/coef + rhsoffset/coef) */
1512 
1513  consdata->rhsoffset = (consdata->rhsoffset + offset) / coef;
1514  consdata->rhscoeff *= coef;
1515  consdata->rhsvar = x;
1516 
1517  /* capture and lock new variable, catch variable events */
1518  SCIP_CALL( SCIPcaptureVar(scip, consdata->rhsvar) );
1519  SCIP_CALL( SCIPlockVarCons(scip, consdata->rhsvar, cons, consdata->rhscoeff > 0.0, consdata->rhscoeff < 0.0) );
1520  SCIP_CALL( catchRhsVarEvents(scip, conshdlrdata->eventhdlr, cons) );
1521  }
1522  }
1523 
1524  if( !havechange )
1525  return SCIP_OKAY;
1526 
1527  /* free nonlinear row representation */
1528  if( consdata->nlrow != NULL )
1529  {
1530  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
1531  }
1532 
1533  /* if a variable has been removed, close gaps in vars array */
1534  if( haveremovedvar )
1535  {
1536  int oldnvars;
1537 
1538  /* due to the realloc of the block memory below and the way we store the eventdata in consdata, we best drop all events here and catch them again below */
1539  SCIP_CALL( dropVarEvents(scip, conshdlrdata->eventhdlr, cons) );
1540 
1541  oldnvars = consdata->nvars;
1542  for( i = 0; i < consdata->nvars; ++i )
1543  {
1544  /* forget about empty places at end of vars array */
1545  while( consdata->nvars && consdata->vars[consdata->nvars-1] == NULL )
1546  --consdata->nvars;
1547 
1548  /* all variables at index >= i have been removed */
1549  if( i == consdata->nvars )
1550  break;
1551 
1552  if( consdata->vars[i] != NULL )
1553  continue;
1554 
1555  /* move variable from position nvars-1 to position i */
1556 
1557  assert(consdata->nvars >= 1);
1558  assert(consdata->vars[consdata->nvars-1] != NULL);
1559 
1560  consdata->vars[i] = consdata->vars[consdata->nvars-1];
1561  consdata->offsets[i] = consdata->offsets[consdata->nvars-1];
1562  consdata->coefs[i] = consdata->coefs[consdata->nvars-1];
1563 
1564  --consdata->nvars;
1565  }
1566 
1567  assert(consdata->nvars < oldnvars);
1568 
1569  /* shrink arrays in consdata */
1570  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, oldnvars, consdata->nvars) );
1571  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->offsets, oldnvars, consdata->nvars) );
1572  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->coefs, oldnvars, consdata->nvars) );
1573 
1574  SCIP_CALL( catchVarEvents(scip, conshdlrdata->eventhdlr, cons) );
1575  }
1576 
1577  SCIPdebugMsg(scip, "\t-> ");
1578  SCIPdebugPrintCons(scip, cons, NULL);
1579 
1580  if( consdata->nvars == 0 )
1581  { /* all variables on left hand size have been removed, remaining constraint is sqrt(gamma) <= ... */
1582  assert(!SCIPisNegative(scip, consdata->constant));
1583  if( consdata->rhsvar == NULL )
1584  { /* also rhsvar has been removed, remaining constraint is sqrt(gamma) <= rhscoeff * rhsoffset */
1585  if( SCIPisFeasLE(scip, sqrt(consdata->constant), consdata->rhscoeff*consdata->rhsoffset) )
1586  {
1587  SCIPdebugMsg(scip, "remove redundant constraint <%s> after fixing all variables\n", SCIPconsGetName(cons));
1588  }
1589  else
1590  {
1591  SCIPdebugMsg(scip, "found problem infeasible after fixing all variables in <%s>\n", SCIPconsGetName(cons));
1592  *iscutoff = TRUE;
1593  }
1594  ++*ndelconss;
1595  }
1596  else if( !SCIPvarIsActive(consdata->rhsvar) )
1597  { /* remaining constraint is sqrt(gamma) - rhscoeff * rhsoffset <= rhscoeff * rhsvar, and rhsvar is probably multi-aggregated */
1598  SCIP_CONS* lincons;
1599 
1600  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons), 1, &consdata->rhsvar, &consdata->rhscoeff,
1601  sqrt(consdata->constant) - consdata->rhscoeff * consdata->rhsoffset, SCIPinfinity(scip),
1605  SCIPconsIsStickingAtNode(cons)) );
1606  SCIP_CALL( SCIPaddCons(scip, lincons) );
1607  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
1608  ++*nupgdconss;
1609  }
1610  else if( consdata->rhscoeff > 0.0 )
1611  { /* remaining constraint is sqrt(gamma) / rhscoeff - rhsoffset <= rhsvar */
1612  SCIP_Bool tightened;
1613  SCIP_CALL( SCIPtightenVarLb(scip, consdata->rhsvar, sqrt(consdata->constant) / consdata->rhscoeff - consdata->rhsoffset, TRUE, iscutoff, &tightened) );
1614  if( *iscutoff )
1615  {
1616  SCIPdebugMsg(scip, "found problem infeasible after fixing all lhs variables in <%s> and tightening lower bound of rhs var\n", SCIPconsGetName(cons));
1617  }
1618  else if( tightened )
1619  {
1620  SCIPdebugMsg(scip, "remove redundant constraint <%s> after fixing all lhs variables and tightening lower bound of rhs var\n", SCIPconsGetName(cons));
1621  ++*nchgbds;
1622  }
1623  else
1624  {
1625  SCIPdebugMsg(scip, "remove redundant constraint <%s> after fixing all lhs variables\n", SCIPconsGetName(cons));
1626  }
1627  ++*ndelconss;
1628  }
1629  else
1630  { /* remaining constraint is sqrt(gamma) / rhscoeff - rhsoffset >= rhsvar */
1631  SCIP_Bool tightened;
1632  SCIP_CALL( SCIPtightenVarUb(scip, consdata->rhsvar, sqrt(consdata->constant) / consdata->rhscoeff - consdata->rhsoffset, TRUE, iscutoff, &tightened) );
1633  if( *iscutoff )
1634  {
1635  SCIPdebugMsg(scip, "found problem infeasible after fixing all lhs variables in <%s> and tightening upper bound of rhs var\n", SCIPconsGetName(cons));
1636  }
1637  else if( tightened )
1638  {
1639  SCIPdebugMsg(scip, "remove redundant constraint <%s> after fixing all lhs variables and tightening upper bound of rhs var\n", SCIPconsGetName(cons));
1640  ++*nchgbds;
1641  }
1642  else
1643  {
1644  SCIPdebugMsg(scip, "remove redundant constraint <%s> after fixing all lhs variables\n", SCIPconsGetName(cons));
1645  }
1646  ++*ndelconss;
1647  }
1648  SCIP_CALL( SCIPdelCons(scip, cons) );
1649  *isdeleted = TRUE;
1650  return SCIP_OKAY;
1651  }
1652 
1653  if( consdata->rhsvar == NULL )
1654  { /* constraint becomes sum_i (alpha_i*(x_i+beta_i))^2 <= (rhscoeff*rhsoffset)^2 - gamma */
1655  if( consdata->nvars > 1 )
1656  { /* upgrade to quadratic constraint */
1657  SCIP_CONS* quadcons;
1658  SCIP_QUADVARTERM* quadvarterms;
1659  SCIP_Real rhs;
1660 
1661  SCIP_CALL( SCIPallocBufferArray(scip, &quadvarterms, consdata->nvars) );
1662  BMSclearMemoryArray(quadvarterms, consdata->nvars);
1663  rhs = consdata->rhscoeff * consdata->rhsoffset;
1664  rhs = rhs * rhs - consdata->constant;
1665 
1666  for( i = 0; i < consdata->nvars; ++i )
1667  {
1668  quadvarterms[i].var = consdata->vars[i];
1669  quadvarterms[i].sqrcoef = consdata->coefs[i] * consdata->coefs[i];
1670  if( consdata->offsets[i] != 0.0 )
1671  {
1672  quadvarterms[i].lincoef = 2 * consdata->offsets[i] * quadvarterms[i].sqrcoef;
1673  rhs -= quadvarterms[i].sqrcoef * consdata->offsets[i]*consdata->offsets[i];
1674  }
1675  }
1676 
1677  assert(!SCIPconsIsStickingAtNode(cons));
1678  SCIP_CALL( SCIPcreateConsQuadratic2(scip, &quadcons, SCIPconsGetName(cons), 0, NULL, NULL,
1679  consdata->nvars, quadvarterms, 0, NULL, -SCIPinfinity(scip), rhs,
1683  SCIP_CALL( SCIPaddCons(scip, quadcons) );
1684  SCIPdebugMsg(scip, "upgraded <%s> to quadratic constraint: ", SCIPconsGetName(cons));
1685  SCIPdebugPrintCons(scip, quadcons, NULL);
1686 
1687  SCIP_CALL( SCIPreleaseCons(scip, &quadcons) );
1688 
1689  SCIPfreeBufferArray(scip, &quadvarterms);
1690 
1691  ++*nupgdconss;
1692  }
1693  else if( !SCIPvarIsActive(consdata->vars[0]) )
1694  { /* constraint is |alpha*(x+beta)| <= sqrt((rhscoeff*rhsoffset)^2 - gamma), but x is probably multaggr. -> turn into ranged linear constraint */
1695  SCIP_CONS* lincons;
1696 
1697  /* create constraint alpha*x <= sqrt((rhscoeff*rhsoffset)^2 - gamma) - alpha*beta
1698  * alpha*x >= -sqrt((rhscoeff*rhsoffset)^2 - gamma) - alpha*beta */
1699  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons), 1, &consdata->vars[0], &consdata->coefs[0],
1700  -sqrt(consdata->rhscoeff * consdata->rhscoeff * consdata->rhsoffset * consdata->rhsoffset - consdata->constant) - consdata->coefs[0] * consdata->offsets[0],
1701  +sqrt(consdata->rhscoeff * consdata->rhscoeff * consdata->rhsoffset * consdata->rhsoffset - consdata->constant) - consdata->coefs[0] * consdata->offsets[0],
1705  SCIPconsIsStickingAtNode(cons)) );
1706  SCIP_CALL( SCIPaddCons(scip, lincons) );
1707  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
1708 
1709  ++*nupgdconss;
1710  }
1711  else
1712  { /* constraint is |alpha*(x+beta)| <= sqrt((rhscoeff*rhsoffset)^2 - gamma) -> propagate bounds */
1713  SCIP_Bool tightened;
1714  SCIP_Real rhs;
1715  assert(consdata->nvars == 1); /* case == 0 handled before */
1716  rhs = consdata->rhscoeff * consdata->rhsoffset;
1717  rhs = rhs * rhs;
1718  if( SCIPisNegative(scip, rhs - consdata->constant) )
1719  { /* take this as infeasible */
1720  SCIPdebugMsg(scip, "found problem infeasible after fixing rhs and all except one lhs variables in <%s>\n", SCIPconsGetName(cons));
1721  *iscutoff = TRUE;
1722  }
1723  else
1724  {
1725  rhs -= consdata->constant;
1726  rhs = rhs < 0.0 ? 0.0 : sqrt(rhs);
1727 
1728  if( SCIPisZero(scip, rhs) )
1729  { /* constraint is x = -beta */
1730  SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], -consdata->offsets[0], iscutoff, &tightened) );
1731  if( *iscutoff )
1732  {
1733  SCIPdebugMsg(scip, "found problem infeasible after fixing rhs and all except one lhs variables and fixing remaining lhs var in <%s>\n", SCIPconsGetName(cons));
1734  }
1735  else if( tightened )
1736  {
1737  SCIPdebugMsg(scip, "remove redundant constraint <%s> after fixing rhs and all except one lhs variables and fixing remaining lhs var\n", SCIPconsGetName(cons));
1738  ++*nfixedvars;
1739  }
1740  else
1741  {
1742  SCIPdebugMsg(scip, "remove redundant constraint <%s> after fixing rhs and all except one lhs variables and fixing remaining lhs var\n", SCIPconsGetName(cons));
1743  }
1744  }
1745  else
1746  { /* constraint is -rhs/|alpha| - beta <= x <= rhs/|alpha| - beta */
1747  rhs /= ABS(consdata->coefs[0]);
1748  SCIP_CALL( SCIPtightenVarLb(scip, consdata->vars[0], -rhs - consdata->offsets[0], TRUE, iscutoff, &tightened) );
1749  if( *iscutoff )
1750  {
1751  SCIPdebugMsg(scip, "found problem infeasible after fixing rhs and all except one lhs variables and tightening lower bound of remaining lhs var in <%s>\n", SCIPconsGetName(cons));
1752  }
1753  else
1754  {
1755  if( tightened )
1756  ++*nchgbds;
1757  SCIP_CALL( SCIPtightenVarUb(scip, consdata->vars[0], rhs - consdata->offsets[0], TRUE, iscutoff, &tightened) );
1758  if( *iscutoff )
1759  {
1760  SCIPdebugMsg(scip, "found problem infeasible after fixing rhs and all except one lhs variables and tightening upper bound of remaining lhs var in <%s>\n", SCIPconsGetName(cons));
1761  }
1762  else if( tightened )
1763  ++*nchgbds;
1764  }
1765  if( !*iscutoff )
1766  {
1767  SCIPdebugMsg(scip, "remove redundant constraint <%s> after fixing rhs and all except one lhs variables and tightening bounds on remaining lhs var\n", SCIPconsGetName(cons));
1768  }
1769  }
1770  }
1771  ++*ndelconss;
1772  }
1773  *isdeleted = TRUE;
1774  SCIP_CALL( SCIPdelCons(scip, cons) );
1775  return SCIP_OKAY;
1776  }
1777 
1778  if( consdata->nvars == 1 && SCIPisZero(scip, consdata->constant) )
1779  { /* one variable on lhs left and no constant, constraint becomes |alpha*(x+beta)| <= rhscoef*(rhsvar+rhsoffset) -> upgrade to two linear constraints */
1780  SCIP_CONS* lincons;
1781  SCIP_VAR* vars[2];
1782  SCIP_Real coefs[2];
1783  SCIP_Real rhs;
1784  assert(consdata->rhsvar != NULL); /* case == NULL has been handled before */
1785 
1786  vars[0] = consdata->vars[0];
1787  vars[1] = consdata->rhsvar;
1788  coefs[0] = consdata->coefs[0];
1789  coefs[1] = -consdata->rhscoeff;
1790  rhs = consdata->rhscoeff * consdata->rhsoffset - coefs[0] * consdata->offsets[0];
1791 
1792  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons), 2, vars, coefs, -SCIPinfinity(scip), rhs,
1796  SCIPconsIsStickingAtNode(cons)) );
1797  SCIP_CALL( SCIPaddCons(scip, lincons) );
1798  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
1799 
1800  coefs[0] = -coefs[0];
1801  rhs = consdata->rhscoeff * consdata->rhsoffset - coefs[0] * consdata->offsets[0];
1802 
1803  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons), 2, vars, coefs, -SCIPinfinity(scip), rhs,
1807  SCIPconsIsStickingAtNode(cons)) );
1808  SCIP_CALL( SCIPaddCons(scip, lincons) );
1809  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
1810 
1811  SCIPdebugMsg(scip, "upgraded <%s> to two linear constraint\n", SCIPconsGetName(cons));
1812 
1813  ++*nupgdconss;
1814  SCIP_CALL( SCIPdelCons(scip, cons) );
1815  *isdeleted = TRUE;
1816  return SCIP_OKAY;
1817  }
1818 
1819  return SCIP_OKAY;
1820 }
1821 
1822 
1823 /** adds the linear outer-approximation of Glineur et.al. for a SOC constraint of dimension 3
1824  *
1825  * Input is the data for a constraint \f$\sqrt{(\alpha_1(x_1+offset1))^2 + (\alpha_2(x_2+offset2))^2)} \leq \alpha_3(x_3+offset3)\f$.
1826  * Here \f$\alpha3 > 0\f$, and the lower bound of \f$x_3 \geq -offset3\f$.
1827  * Also x2 = NULL is allowed, in which case the second term is assumed to be constant, and \f$offset2 \neq 0\f$ is needed.
1828  */
1829 static
1831  SCIP* scip, /**< SCIP data structure */
1832  SCIP_CONS* cons, /**< original constraint */
1833  SCIP_VAR* x1, /**< variable x1 */
1834  SCIP_VAR* x2, /**< variable x2 */
1835  SCIP_VAR* x3, /**< variable x3 */
1836  SCIP_Real alpha1, /**< coefficient of x1 */
1837  SCIP_Real alpha2, /**< coefficient of x2 */
1838  SCIP_Real alpha3, /**< coefficient of x3 */
1839  SCIP_Real offset1, /**< offset of x1 */
1840  SCIP_Real offset2, /**< offset of x2 */
1841  SCIP_Real offset3, /**< offset of x3 */
1842  int N, /**< size of linear approximation, need to be >= 1 */
1843  const char* basename, /**< string to use for building variable and constraint names */
1844  int* naddconss /**< buffer where to add the number of added constraints */
1845  )
1846 {
1847  SCIP_CONS* lincons;
1848  SCIP_VAR* vars[3];
1849  SCIP_Real vals[3];
1850  char varname[255];
1851  char linname[255];
1852  int i;
1853  SCIP_VAR** avars;
1854  SCIP_VAR** bvars;
1855  SCIP_Real val;
1856 
1857  assert(scip != NULL);
1858  assert(cons != NULL);
1859  assert(x1 != NULL);
1860  assert(x2 != NULL || !SCIPisZero(scip, offset2));
1861  assert(x3 != NULL);
1862  assert(SCIPisPositive(scip, alpha3));
1863  assert(SCIPisGE(scip, SCIPconsIsLocal(cons) ? SCIPvarGetLbLocal(x3) : SCIPvarGetLbGlobal(x3), -offset3));
1864  assert(basename != NULL);
1865  assert(N >= 1);
1866  assert(naddconss != NULL);
1867 
1868  SCIPdebugMsg(scip, "Creating linear Glineur outer-approximation for <%s>.\n", basename);
1869  SCIPdebugMsg(scip, "sqr(%g(%s+%g)) + sqr(%g(%s+%g)) <= sqr(%g(%s+%g)).\n",
1870  alpha1, SCIPvarGetName(x1), offset1, alpha2, x2 ? SCIPvarGetName(x2) : "0", offset2, alpha3, SCIPvarGetName(x3), offset3);
1871 
1872  SCIP_CALL( SCIPallocBufferArray(scip, &avars, N+1) );
1873  SCIP_CALL( SCIPallocBufferArray(scip, &bvars, N+1) );
1874 
1875  /* create additional variables; we do not use avars[0] and bvars[0] */
1876  for( i = 1; i <= N; ++i )
1877  {
1878  (void) SCIPsnprintf(varname, 255, "soc#%s_a%d", basename, i);
1879  SCIP_CALL( SCIPcreateVar(scip, &avars[i], varname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
1880  SCIP_VARTYPE_CONTINUOUS, SCIPconsIsInitial(cons), FALSE, NULL, NULL, NULL, NULL, NULL) );
1881  SCIP_CALL( SCIPaddVar(scip, avars[i]) );
1882 
1883  (void) SCIPsnprintf(varname, 255, "soc#%s_b%d", basename, i);
1884  SCIP_CALL( SCIPcreateVar(scip, &bvars[i], varname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
1885  SCIP_VARTYPE_CONTINUOUS, SCIPconsIsInitial(cons), FALSE, NULL, NULL, NULL, NULL, NULL) );
1886  SCIP_CALL( SCIPaddVar(scip, bvars[i]) );
1887  }
1888 
1889  /* create linear constraints for the first case
1890  * cos(pi) = -1, sin(pi) = 0
1891  * -> a_1 = - alpha1 (x1 + offset1) -> -alpha1*x1 - a_1 = alpha1*offset1
1892  * -> b_1 >= | alpha2 (x2 + offset2) | -> alpha2*x2 - b_1 <= -alpha2*offset2
1893  * alpha2*x2 + b_1 >= -alpha2*offset2
1894  */
1895 
1896  vars[0] = x1;
1897  vals[0] = -alpha1;
1898  vars[1] = avars[1];
1899  vals[1] = -1.0;
1900 
1901  (void) SCIPsnprintf(linname, 255, "soc#%s#a%d", basename, 0);
1902  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, alpha1*offset1, alpha1*offset1,
1908  SCIP_CALL( SCIPaddCons(scip, lincons) );
1909  SCIPdebugPrintCons(scip, lincons, NULL);
1910  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
1911  ++(*naddconss);
1912 
1913  if( x2 != NULL )
1914  {
1915  vars[0] = x2;
1916  vals[0] = alpha2;
1917  vars[1] = bvars[1];
1918  vals[1] = -1.0;
1919 
1920  (void) SCIPsnprintf(linname, 255, "soc#%s#b%d", basename, 0);
1921  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, -SCIPinfinity(scip), -alpha2*offset2,
1927  SCIP_CALL( SCIPaddCons(scip, lincons) );
1928  SCIPdebugPrintCons(scip, lincons, NULL);
1929  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
1930  ++(*naddconss);
1931 
1932  vars[0] = x2;
1933  vals[0] = alpha2;
1934  vars[1] = bvars[1];
1935  vals[1] = 1.0;
1936 
1937  (void) SCIPsnprintf(linname, 255, "soc#%s#B%d", basename, 0);
1938  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, -alpha2*offset2, SCIPinfinity(scip),
1944  SCIP_CALL( SCIPaddCons(scip, lincons) );
1945  SCIPdebugPrintCons(scip, lincons, NULL);
1946  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
1947  ++(*naddconss);
1948  }
1949  else
1950  { /* x2 == NULL -> b_1 >= |alpha2*offset2| */
1951  SCIP_Bool infeas;
1952  SCIP_Bool tightened;
1953  SCIP_CALL( SCIPtightenVarLb(scip, bvars[1], ABS(alpha2 * offset2), TRUE, &infeas, &tightened) );
1954  if( infeas == TRUE )
1955  {
1956  SCIPwarningMessage(scip, "creating glineur outer approximation of SOC3 constraint found problem infeasible.\n");
1957  }
1958  }
1959 
1960  /* create intermediate linear constraints */
1961  val = M_PI;
1962  for( i = 1; i < N; ++i )
1963  {
1964  val /= 2.0;
1965 
1966  vars[0] = avars[i];
1967  vals[0] = cos(val);
1968  vars[1] = bvars[i];
1969  vals[1] = sin(val);
1970  vars[2] = avars[i+1]; /*lint !e679*/
1971  vals[2] = -1.0;
1972 
1973  (void) SCIPsnprintf(linname, 255, "soc#%s#a%d", basename, i);
1974  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 3, vars, vals, 0.0, 0.0,
1980  SCIP_CALL( SCIPaddCons(scip, lincons) );
1981  SCIPdebugPrintCons(scip, lincons, NULL);
1982  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
1983  ++(*naddconss);
1984 
1985  vars[0] = avars[i];
1986  vals[0] = -sin(val);
1987  vars[1] = bvars[i];
1988  vals[1] = cos(val);
1989  vars[2] = bvars[i+1]; /*lint !e679*/
1990  vals[2] = -1.0;
1991 
1992  (void) SCIPsnprintf(linname, 255, "soc#%s#b%d", basename, i);
1993  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 3, vars, vals, -SCIPinfinity(scip), 0.0,
1999  SCIP_CALL( SCIPaddCons(scip, lincons) );
2000  SCIPdebugPrintCons(scip, lincons, NULL);
2001  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2002  ++(*naddconss);
2003 
2004  vars[0] = avars[i];
2005  vals[0] = -sin(val);
2006  vars[1] = bvars[i];
2007  vals[1] = cos(val);
2008  vars[2] = bvars[i+1]; /*lint !e679*/
2009  vals[2] = 1.0;
2010 
2011  (void) SCIPsnprintf(linname, 255, "soc#%s#B%d", basename, i);
2012  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 3, vars, vals, 0.0, SCIPinfinity(scip),
2018  SCIP_CALL( SCIPaddCons(scip, lincons) );
2019  SCIPdebugPrintCons(scip, lincons, NULL);
2020  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2021  ++(*naddconss);
2022  }
2023 
2024  /* create last linear constraint */
2025  val /= 2.0;
2026  vars[0] = avars[N];
2027  vals[0] = -cos(val);
2028  vars[1] = bvars[N];
2029  vals[1] = -sin(val);
2030  vars[2] = x3;
2031  vals[2] = alpha3;
2032 
2033  (void) SCIPsnprintf(linname, 255, "soc#%s#a%d", basename, N);
2034  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 3, vars, vals, -alpha3*offset3, -alpha3*offset3,
2040  SCIP_CALL( SCIPaddCons(scip, lincons) );
2041  SCIPdebugPrintCons(scip, lincons, NULL);
2042  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2043  ++(*naddconss);
2044 
2045  for( i = 1; i <= N; ++i )
2046  {
2047  SCIP_CALL( SCIPreleaseVar(scip, &avars[i]) );
2048  SCIP_CALL( SCIPreleaseVar(scip, &bvars[i]) );
2049  }
2050  SCIPfreeBufferArray(scip, &avars);
2051  SCIPfreeBufferArray(scip, &bvars);
2052 
2053  return SCIP_OKAY;
2054 }
2055 
2056 /** adds the linear outer-approximation of Ben-Tal and Nemirovski for a SOC constraint of dimension 3
2057  *
2058  * Input is the data for a constraint \f$\sqrt{constant + (\alpha_1(x_1+offset1))^2 + (\alpha_2(x_2+offset2))^2)} \leq \alpha_3(x_3+offset3)\f$.
2059  * Here \f$\alpha3 > 0.0\f$, and the lower bound of \f$x_3 \geq -offset3\f$.
2060  * Also x2 = NULL is allowed, in which case the second term is assumed to be constant, and \f$offset2 \neq 0\f$ is needed.
2061  * */
2062 static
2064  SCIP* scip, /**< SCIP data structure */
2065  SCIP_CONS* cons, /**< original constraint */
2066  SCIP_VAR* x1, /**< variable x1 */
2067  SCIP_VAR* x2, /**< variable x2 */
2068  SCIP_VAR* x3, /**< variable x3 */
2069  SCIP_Real alpha1, /**< coefficient of x1 */
2070  SCIP_Real alpha2, /**< coefficient of x2 */
2071  SCIP_Real alpha3, /**< coefficient of x3 */
2072  SCIP_Real offset1, /**< offset of x1 */
2073  SCIP_Real offset2, /**< offset of x2 */
2074  SCIP_Real offset3, /**< offset of x3 */
2075  int N, /**< size of linear approximation, need to be >= 1 */
2076  const char* basename, /**< string to use for building variable and constraint names */
2077  int* naddconss /**< buffer where to add the number of added constraints */
2078  )
2079 {
2080  SCIP_CONS* lincons;
2081  SCIP_VAR* vars[3];
2082  SCIP_Real vals[3];
2083  char varname[255];
2084  char linname[255];
2085  int i;
2086  SCIP_VAR** avars;
2087  SCIP_VAR** bvars;
2088 
2089  assert(scip != NULL);
2090  assert(cons != NULL);
2091  assert(x1 != NULL);
2092  assert(x2 != NULL || !SCIPisZero(scip, offset2));
2093  assert(x3 != NULL);
2094  assert(SCIPisPositive(scip, alpha3));
2095  assert(SCIPisGE(scip, SCIPconsIsLocal(cons) ? SCIPvarGetLbLocal(x3) : SCIPvarGetLbGlobal(x3), -offset3));
2096  assert(basename != NULL);
2097  assert(N >= 1);
2098  assert(naddconss != NULL);
2099 
2100  SCIPdebugMsg(scip, "Creating linear Ben-Tal Nemirovski outer-approximation for <%s>.\n", basename);
2101 
2102  SCIP_CALL( SCIPallocBufferArray(scip, &avars, N+1) );
2103  SCIP_CALL( SCIPallocBufferArray(scip, &bvars, N+1) );
2104 
2105  /* create additional variables */
2106  for( i = 0; i <= N; ++i )
2107  {
2108  (void) SCIPsnprintf(varname, 255, "soc#%s_a%d", basename, i);
2109  SCIP_CALL( SCIPcreateVar(scip, &avars[i], varname, 0.0, SCIPinfinity(scip), 0.0,
2110  SCIP_VARTYPE_CONTINUOUS, SCIPconsIsLocal(cons), TRUE, NULL, NULL, NULL, NULL, NULL) );
2111  SCIP_CALL( SCIPaddVar(scip, avars[i]) );
2112 
2113  (void) SCIPsnprintf(varname, 255, "soc#%s_b%d", basename, i);
2114  SCIP_CALL( SCIPcreateVar(scip, &bvars[i], varname, 0.0, SCIPinfinity(scip), 0.0,
2115  SCIP_VARTYPE_CONTINUOUS, SCIPconsIsLocal(cons), TRUE, NULL, NULL, NULL, NULL, NULL) );
2116  SCIP_CALL( SCIPaddVar(scip, bvars[i]) );
2117  }
2118 
2119  /* create first linear constraints - split into two because of the absolute value */
2120  vars[0] = avars[0];
2121  vals[0] = 1.0;
2122  vars[1] = x1;
2123  vals[1] = -alpha1;
2124 
2125  (void) SCIPsnprintf(linname, 255, "soc#%s#a%d", basename, 0);
2126  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, alpha1 * offset1, SCIPinfinity(scip),
2131  TRUE /* removable */, SCIPconsIsStickingAtNode(cons)) );
2132  SCIP_CALL( SCIPaddCons(scip, lincons) );
2133  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2134  ++(*naddconss);
2135 
2136  vars[0] = avars[0];
2137  vals[0] = 1.0;
2138  vars[1] = x1;
2139  vals[1] = alpha1;
2140 
2141  (void) SCIPsnprintf(linname, 255, "soc#%s#A%d", basename, 0);
2142  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, -alpha1 * offset1, SCIPinfinity(scip),
2147  TRUE /* removable */, SCIPconsIsStickingAtNode(cons)) );
2148  SCIP_CALL( SCIPaddCons(scip, lincons) );
2149  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2150  ++(*naddconss);
2151 
2152  if( x2 != NULL )
2153  {
2154  vars[0] = bvars[0];
2155  vals[0] = 1.0;
2156  vars[1] = x2;
2157  vals[1] = -alpha2;
2158 
2159  (void) SCIPsnprintf(linname, 255, "soc#%s#b%d", basename, 0);
2160  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, alpha2 * offset2, SCIPinfinity(scip),
2165  TRUE /* removable */, SCIPconsIsStickingAtNode(cons)) );
2166  SCIP_CALL( SCIPaddCons(scip, lincons) );
2167  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2168  ++(*naddconss);
2169 
2170  vars[0] = bvars[0];
2171  vals[0] = 1.0;
2172  vars[1] = x2;
2173  vals[1] = alpha2;
2174 
2175  (void) SCIPsnprintf(linname, 255, "soc#%s#B%d", basename, 0);
2176  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, -alpha2 * offset2, SCIPinfinity(scip),
2181  TRUE /* removable */, SCIPconsIsStickingAtNode(cons)) );
2182  SCIP_CALL( SCIPaddCons(scip, lincons) );
2183  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2184  ++(*naddconss);
2185  }
2186  else
2187  { /* second summand is just a constant */
2188  if( SCIPconsIsLocal(cons) )
2189  {
2190  SCIP_CALL( SCIPchgVarLbNode(scip, NULL, bvars[0], ABS(alpha2 * offset2)) );
2191  }
2192  else
2193  {
2194  SCIP_CALL( SCIPchgVarLbGlobal(scip, bvars[0], ABS(alpha2 * offset2)) );
2195  }
2196  }
2197 
2198  /* create intermediate linear constraints */
2199  for( i = 1; i <= N; ++i )
2200  {
2201  SCIP_Real val;
2202 
2203  val = M_PI / pow(2.0, (double) (i+1));
2204 
2205  vars[0] = avars[i-1];
2206  vals[0] = cos(val);
2207  vars[1] = bvars[i-1];
2208  vals[1] = sin(val);
2209  vars[2] = avars[i];
2210  vals[2] = -1.0;
2211 
2212  (void) SCIPsnprintf(linname, 255, "soc#%s#a%d", basename, i);
2213  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 3, vars, vals, 0.0, 0.0,
2218  TRUE /* removable */, SCIPconsIsStickingAtNode(cons)) );
2219  SCIP_CALL( SCIPaddCons(scip, lincons) );
2220  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2221  ++(*naddconss);
2222 
2223  vars[0] = avars[i-1];
2224  vals[0] = sin(val);
2225  vars[1] = bvars[i-1];
2226  vals[1] = -cos(val);
2227  vars[2] = bvars[i];
2228  vals[2] = 1.0;
2229 
2230  (void) SCIPsnprintf(linname, 255, "soc#%s#b%d", basename, i);
2231  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 3, vars, vals, 0.0, SCIPinfinity(scip),
2236  TRUE /* removable */, SCIPconsIsStickingAtNode(cons)) );
2237  SCIP_CALL( SCIPaddCons(scip, lincons) );
2238  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2239  ++(*naddconss);
2240 
2241  vars[0] = avars[i-1];
2242  vals[0] = -sin(val);
2243  vars[1] = bvars[i-1];
2244  vals[1] = cos(val);
2245  vars[2] = bvars[i];
2246  vals[2] = 1.0;
2247 
2248  (void) SCIPsnprintf(linname, 255, "soc#%s#B%d", basename, i);
2249  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 3, vars, vals, 0.0, SCIPinfinity(scip),
2254  TRUE /* removable */, SCIPconsIsStickingAtNode(cons)) );
2255  SCIP_CALL( SCIPaddCons(scip, lincons) );
2256  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2257  ++(*naddconss);
2258  }
2259 
2260  /* create last linear constraints */
2261  vars[0] = x3;
2262  vals[0] = alpha3;
2263  vars[1] = avars[N];
2264  vals[1] = -1.0;
2265 
2266  (void) SCIPsnprintf(linname, 255, "soc#%s#a%d", basename, N);
2267  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, -alpha3 * offset3, SCIPinfinity(scip),
2273  SCIP_CALL( SCIPaddCons(scip, lincons) );
2274  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2275  ++(*naddconss);
2276 
2277  vars[0] = avars[N];
2278  vals[0] = tan( M_PI / pow(2.0, (double) (N+1)) );
2279  vars[1] = bvars[N];
2280  vals[1] = -1.0;
2281 
2282  (void) SCIPsnprintf(linname, 255, "soc#%s#b%d", basename, i);
2283  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, linname, 2, vars, vals, 0.0, SCIPinfinity(scip),
2288  TRUE /* removable */, SCIPconsIsStickingAtNode(cons)) );
2289  SCIP_CALL( SCIPaddCons(scip, lincons) );
2290  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2291  ++(*naddconss);
2292 
2293  for( i = 0; i <= N; ++i )
2294  {
2295  SCIP_CALL( SCIPreleaseVar(scip, &avars[i]) );
2296  SCIP_CALL( SCIPreleaseVar(scip, &bvars[i]) );
2297  }
2298  SCIPfreeBufferArray(scip, &avars);
2299  SCIPfreeBufferArray(scip, &bvars);
2300 
2301  return SCIP_OKAY;
2302 }
2303 
2304 /** adds a linear outer approx for a three dimensional SOC constraint
2305  *
2306  * chooses between Ben-Tan/Nemirovski and Glineur and calls the corresponding function
2307  */
2308 static
2310  SCIP* scip, /**< SCIP data structure */
2311  SCIP_CONS* cons, /**< original constraint */
2312  SCIP_VAR* x1, /**< variable x1 */
2313  SCIP_VAR* x2, /**< variable x2 */
2314  SCIP_VAR* x3, /**< variable x3 */
2315  SCIP_Real alpha1, /**< coefficient of x1 */
2316  SCIP_Real alpha2, /**< coefficient of x2 */
2317  SCIP_Real alpha3, /**< coefficient of x3 */
2318  SCIP_Real offset1, /**< offset of x1 */
2319  SCIP_Real offset2, /**< offset of x2 */
2320  SCIP_Real offset3, /**< offset of x3 */
2321  int N, /**< size of linear approximation, need to be >= 1 */
2322  SCIP_Bool glineur, /**< whether to prefer Glineur to Ben-Tal Nemirovski */
2323  const char* basename, /**< string to use for building variable and constraint names */
2324  int* naddconss /**< buffer where to add the number of added constraints */
2325  )
2326 {
2327  if( glineur )
2328  {
2329  SCIP_CALL( presolveCreateGlineurApproxDim3(scip, cons, x1, x2, x3, alpha1, alpha2, alpha3, offset1, offset2, offset3, N, basename, naddconss) );
2330  }
2331  else
2332  {
2333  SCIP_CALL( presolveCreateBenTalNemirovskiApproxDim3(scip, cons, x1, x2, x3, alpha1, alpha2, alpha3, offset1, offset2, offset3, N, basename, naddconss) );
2334  }
2335 
2336  return SCIP_OKAY;
2337 }
2338 
2339 /** adds linear outer approximation of Ben-Tal and Nemirovski for a constraint \f$\gamma + \sum_{i=1}^n (\alpha_i (x_i + \beta_i))^2 \leq (\alpha_{n+1} (x_{n+1} + \beta_{n+1}))^2\f$ to the LP
2340  *
2341  * if n > 2, calls same function recursively;
2342  * if n = 2, calls presolveCreateBenTalNemirovskiApproxDim3
2343  */
2344 static
2346  SCIP* scip, /**< SCIP data structure */
2347  int nlhsvars, /**< number of variables on left hand side (n) */
2348  SCIP_VAR** lhsvars, /**< variables on left hand side (x_i) */
2349  SCIP_Real* lhscoefs, /**< coefficients of variables on left hand side (alpha_i) */
2350  SCIP_Real* lhsoffsets, /**< offsets of variable on left hand side (beta_i) */
2351  SCIP_VAR* rhsvar, /**< variable on right hand side (y) */
2352  SCIP_Real rhscoeff, /**< coefficient of variable on right hand side (alpha_{n+1}) */
2353  SCIP_Real rhsoffset, /**< offset of variable on right hand side (beta_{n+1}) */
2354  SCIP_Real constant, /**< constant term (gamma) */
2355  const char* basename, /**< prefix for variable and constraint name */
2356  SCIP_CONS* origcons, /**< original constraint for which this SOC3 set is added */
2357  int soc3_nr_auxvars, /**< number of auxiliary variables to use for a SOC3 constraint, or 0 if automatic */
2358  SCIP_Bool glineur, /**< whether Glineur should be preferred to Ben-Tal Nemirovski */
2359  int* naddconss /**< buffer where to add the number of added constraints */
2360  )
2361 {
2362  char name[255];
2363  SCIP_VAR* auxvar1;
2364  SCIP_VAR* auxvar2;
2365 
2366  assert(scip != NULL);
2367  assert(lhsvars != NULL);
2368  assert(nlhsvars >= 1);
2369  assert(lhscoefs != NULL);
2370  assert(lhsoffsets != NULL);
2371  assert(rhsvar != NULL);
2372  assert(basename != NULL);
2373  assert(!SCIPisNegative(scip, constant));
2374  assert(naddconss != NULL);
2375 
2376  if( nlhsvars == 1 )
2377  { /* end of recursion */
2378  assert(SCIPisPositive(scip, constant));
2379  SCIP_CALL( presolveCreateOuterApproxDim3(scip, origcons,
2380  lhsvars[0], NULL, rhsvar,
2381  lhscoefs[0], 1.0, rhscoeff,
2382  lhsoffsets[0], sqrt(constant), rhsoffset,
2383  soc3_nr_auxvars, glineur, basename, naddconss) );
2384 
2385  return SCIP_OKAY;
2386  }
2387 
2388  if( nlhsvars == 2 && SCIPisZero(scip, constant) )
2389  { /* end of recursion */
2390  assert(lhsvars[0] != NULL);
2391  assert(lhsvars[1] != NULL);
2392  assert(rhsvar != NULL);
2393  SCIP_CALL( presolveCreateOuterApproxDim3(scip, origcons,
2394  lhsvars[0], lhsvars[1], rhsvar,
2395  lhscoefs[0], lhscoefs[1], rhscoeff,
2396  lhsoffsets[0], lhsoffsets[1], rhsoffset,
2397  soc3_nr_auxvars, glineur, basename, naddconss) );
2398 
2399  return SCIP_OKAY;
2400  }
2401 
2402  if( nlhsvars == 3 || (nlhsvars == 2 && !SCIPisZero(scip, constant)) )
2403  {
2404  /* a bit special case too */
2405  /* for first two variables on lhs, create a new aux.var and a new SOC3 */
2406  (void) SCIPsnprintf(name, 255, "%s#z1", basename);
2407  SCIP_CALL( SCIPcreateVar(scip, &auxvar1, name, 0.0, SCIPinfinity(scip), 0.0,
2408  SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
2409  SCIP_CALL( SCIPaddVar(scip, auxvar1) );
2410 
2411  /* constraint alpha_0 (x_0+beta0)^2 + alpha_1 (x_1+beta1)^2 <= auxvar^2 */
2412  SCIP_CALL( presolveCreateOuterApproxDim3(scip, origcons,
2413  lhsvars[0], lhsvars[1], auxvar1,
2414  lhscoefs[0], lhscoefs[1], 1.0,
2415  lhsoffsets[0], lhsoffsets[1], 0.0,
2416  soc3_nr_auxvars, glineur, name, naddconss) );
2417 
2418  (void) SCIPsnprintf(name, 255, "%s_soc3", basename);
2419  if( nlhsvars == 3 )
2420  { /* create new constraint alpha_2 (x_2+beta2)^2 + auxvar^2 <= (rhscoeff * (rhsvar+rhsoffset))^2 */
2421  SCIP_CALL( presolveCreateOuterApproxDim3(scip, origcons,
2422  lhsvars[2], auxvar1, rhsvar,
2423  lhscoefs[2], 1.0, rhscoeff,
2424  lhsoffsets[2], 0.0, rhsoffset,
2425  soc3_nr_auxvars, glineur, name, naddconss) );
2426  }
2427  else
2428  { /* create new constraint auxvar^2 + sqrt(constant)^2 <= (rhscoeff * (rhsvar+rhsoffset))^2 */
2429  SCIP_CALL( presolveCreateOuterApproxDim3(scip, origcons,
2430  auxvar1, NULL, rhsvar,
2431  1.0, 1.0, rhscoeff,
2432  0.0, sqrt(constant), rhsoffset,
2433  soc3_nr_auxvars, glineur, name, naddconss) );
2434  }
2435 
2436  SCIP_CALL( SCIPreleaseVar(scip, &auxvar1) );
2437 
2438  return SCIP_OKAY;
2439  }
2440 
2441  /* nlhsvars >= 4 */
2442 
2443  (void) SCIPsnprintf(name, 255, "%s#z1", basename);
2444  SCIP_CALL( SCIPcreateVar(scip, &auxvar1, name, 0.0, SCIPinfinity(scip), 0.0,
2445  SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
2446  SCIP_CALL( SCIPaddVar(scip, auxvar1) );
2447 
2448  /* approx for left half of lhs */
2450  nlhsvars/2, lhsvars, lhscoefs, lhsoffsets,
2451  auxvar1, 1.0, 0.0,
2452  constant, name, origcons, soc3_nr_auxvars, glineur, naddconss) );
2453 
2454  (void) SCIPsnprintf(name, 255, "%s#z2", basename);
2455  SCIP_CALL( SCIPcreateVar(scip, &auxvar2, name, 0., SCIPinfinity(scip), 0.0,
2456  SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
2457  SCIP_CALL( SCIPaddVar(scip, auxvar2) );
2458 
2459  /* approx for right half of lhs */
2461  nlhsvars-nlhsvars/2, &lhsvars[nlhsvars/2], &lhscoefs[nlhsvars/2], &lhsoffsets[nlhsvars/2],
2462  auxvar2, 1.0, 0.0,
2463  0.0, name, origcons, soc3_nr_auxvars, glineur, naddconss) );
2464 
2465  /* SOC constraint binding both auxvar's */
2466  (void)SCIPsnprintf(name, 255, "%s_soc3", basename);
2467  SCIP_CALL( presolveCreateOuterApproxDim3(scip, origcons,
2468  auxvar1, auxvar2, rhsvar,
2469  1.0, 1.0, rhscoeff,
2470  0.0, 0.0, rhsoffset,
2471  soc3_nr_auxvars, glineur, name, naddconss) );
2472 
2473  SCIP_CALL( SCIPreleaseVar(scip, &auxvar1) );
2474  SCIP_CALL( SCIPreleaseVar(scip, &auxvar2) );
2475 
2476  return SCIP_OKAY;
2477 }
2478 
2479 /** propagates variable bounds */
2480 static
2482  SCIP* scip, /**< SCIP data structure */
2483  SCIP_CONS* cons, /**< constraint */
2484  SCIP_RESULT* result, /**< buffer to store result of propagation */
2485  int* nchgbds, /**< buffer where to add number of tightened bounds */
2486  SCIP_Bool* redundant /**< buffer to indicate whether constraint was marked for deletion because of redundancy */
2487  )
2488 {
2489  SCIP_CONSDATA* consdata;
2490  SCIP_INTERVAL lhsrange;
2491  SCIP_INTERVAL* lhsranges;
2492  SCIP_INTERVAL rhsrange;
2493  SCIP_INTERVAL a, b, c;
2494  SCIP_ROUNDMODE roundmode;
2495  SCIP_Bool infeas, tightened;
2496  int i;
2497  SCIP_Real lb, ub;
2498 
2499  assert(scip != NULL);
2500  assert(cons != NULL);
2501  assert(result != NULL);
2502  assert(nchgbds != NULL);
2503  assert(redundant != NULL);
2504 
2505  consdata = SCIPconsGetData(cons);
2506  assert(consdata != NULL);
2507 
2508  *redundant = FALSE;
2509 
2510  if( !SCIPconsIsMarkedPropagate(cons) )
2511  {
2512  SCIPdebugMsg(scip, "skip propagation for constraint %s\n", SCIPconsGetName(cons));
2513  *result = SCIP_DIDNOTRUN;
2514  return SCIP_OKAY;
2515  }
2516  else
2517  {
2518  SCIPdebugMsg(scip, "try propagation for constraint %s\n", SCIPconsGetName(cons));
2519  }
2520 
2521  *result = SCIP_DIDNOTFIND;
2522  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
2523 
2524  /* @todo do something clever to decide whether propagation should be tried */
2525 
2526  /* compute activity on lhs */
2527  SCIPintervalSet(&lhsrange, consdata->constant);
2528  SCIP_CALL( SCIPallocBufferArray(scip, &lhsranges, consdata->nvars) );
2529  for( i = 0; i < consdata->nvars; ++i )
2530  {
2531  lb = SCIPcomputeVarLbLocal(scip, consdata->vars[i]) - SCIPepsilon(scip);
2532  ub = SCIPcomputeVarUbLocal(scip, consdata->vars[i]) + SCIPepsilon(scip);
2533  SCIPintervalSetBounds(&lhsranges[i], MIN(lb, ub), MAX(lb, ub));
2534  if( consdata->offsets[i] != 0.0 )
2535  SCIPintervalAddScalar(SCIPinfinity(scip), &lhsranges[i], lhsranges[i], consdata->offsets[i]);
2536  if( consdata->coefs[i] != 1.0 )
2537  SCIPintervalMulScalar(SCIPinfinity(scip), &lhsranges[i], lhsranges[i], consdata->coefs[i]);
2538  SCIPintervalSquare(SCIPinfinity(scip), &lhsranges[i], lhsranges[i]);
2539 
2540  SCIPintervalAdd(SCIPinfinity(scip), &lhsrange, lhsrange, lhsranges[i]);
2541  }
2542 
2543  /* compute activity on rhs: rhsrange = sqr(rhscoeff * (rhsvar + rhsoffset) ) */
2544  lb = SCIPcomputeVarLbLocal(scip, consdata->rhsvar) - SCIPepsilon(scip);
2545  ub = SCIPcomputeVarUbLocal(scip, consdata->rhsvar) + SCIPepsilon(scip);
2546  SCIPintervalSetBounds(&rhsrange, MIN(lb, ub), MAX(lb, ub));
2547 
2548  if( consdata->rhsoffset != 0.0 )
2549  SCIPintervalAddScalar(SCIPinfinity(scip), &rhsrange, rhsrange, consdata->rhsoffset);
2550  if( consdata->rhscoeff != 1.0 )
2551  SCIPintervalMulScalar(SCIPinfinity(scip), &rhsrange, rhsrange, consdata->rhscoeff);
2552  SCIPintervalSquare(SCIPinfinity(scip), &rhsrange, rhsrange);
2553 
2554  /* check for infeasibility */
2555  if( SCIPisGT(scip, lhsrange.inf-SCIPfeastol(scip), rhsrange.sup) )
2556  {
2557  SCIPdebugMsg(scip, "propagation found constraint <%s> infeasible: lhs = [%.15g,%.15g]-feastol-eps > rhs = [%.15g,%.15g]\n",
2558  SCIPconsGetName(cons), lhsrange.inf, lhsrange.sup, rhsrange.inf, rhsrange.sup);
2559  *result = SCIP_CUTOFF;
2560  goto TERMINATE;
2561  }
2562 
2563  /* check for redundancy: max(lhsrange) <= min(rhsrange) */
2564  if( SCIPisLE(scip, lhsrange.sup, rhsrange.inf) )
2565  {
2566  SCIPdebugMsg(scip, "propagation found constraint <%s> redundant: lhs = [%.15g,%.15g] <= rhs = [%.15g,%.15g]\n",
2567  SCIPconsGetName(cons), lhsrange.inf, lhsrange.sup, rhsrange.inf, rhsrange.sup);
2568  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2569  goto TERMINATE;
2570  }
2571 
2572  /* try to tighten variable on rhs */
2573  if( SCIPvarGetStatus(consdata->rhsvar) != SCIP_VARSTATUS_MULTAGGR )
2574  {
2575  SCIPintervalSquareRoot(SCIPinfinity(scip), &a, lhsrange);
2576  if( consdata->rhscoeff != 1.0 )
2577  SCIPintervalDivScalar(SCIPinfinity(scip), &a, a, consdata->rhscoeff);
2578  if( consdata->rhsoffset != 0.0 )
2579  SCIPintervalSubScalar(SCIPinfinity(scip), &a, a, consdata->rhsoffset);
2580  SCIP_CALL( SCIPtightenVarLb(scip, consdata->rhsvar, SCIPintervalGetInf(a), FALSE, &infeas, &tightened) );
2581  if( infeas )
2582  {
2583  SCIPdebugMsg(scip, "propagation found constraint <%s> infeasible\n", SCIPconsGetName(cons));
2584  *result = SCIP_CUTOFF;
2585  goto TERMINATE;
2586  }
2587  if( tightened )
2588  {
2589  SCIPdebugMsg(scip, "propagation tightened bounds of rhs variable <%s> in constraint <%s>\n", SCIPvarGetName(consdata->rhsvar), SCIPconsGetName(cons));
2590  *result = SCIP_REDUCEDDOM;
2591  ++*nchgbds;
2592  }
2593  }
2594 
2595  /* try to tighten variables on lhs */
2596  SCIPintervalSub(SCIPinfinity(scip), &b, rhsrange, lhsrange); /*lint !e644 */
2597  for( i = 0; i < consdata->nvars; ++i )
2598  {
2599  if( SCIPvarGetStatus(consdata->vars[i]) == SCIP_VARSTATUS_MULTAGGR )
2600  continue;
2601 
2602  roundmode = SCIPintervalGetRoundingMode();
2603  if( !SCIPisInfinity(scip, b.sup) )
2604  {
2606  a.sup = b.sup + lhsranges[i].inf;
2607  }
2608  else
2609  {
2610  a.sup = SCIPinfinity(scip);
2611  }
2612  if( !SCIPisInfinity(scip, -b.inf) )
2613  {
2615  a.inf = b.inf + lhsranges[i].sup;
2616  }
2617  else
2618  {
2619  a.inf = -SCIPinfinity(scip);
2620  }
2621  SCIPintervalSetRoundingMode(roundmode);
2622  SCIPintervalSquareRoot(SCIPinfinity(scip), &a, a);
2623 
2624  assert(consdata->coefs[i] >= 0.0); /* should be ensured in create and presolveRemoveFixed */
2625 
2626  c = a;
2627  if( consdata->coefs[i] != 1.0 )
2628  SCIPintervalDivScalar(SCIPinfinity(scip), &c, c, consdata->coefs[i]);
2629  if( consdata->offsets[i] != 0.0 )
2630  SCIPintervalSubScalar(SCIPinfinity(scip), &c, c, consdata->offsets[i]);
2631 
2632  SCIP_CALL( SCIPtightenVarUb(scip, consdata->vars[i], SCIPintervalGetSup(c), FALSE, &infeas, &tightened) );
2633  if( infeas )
2634  {
2635  SCIPdebugMsg(scip, "propagation found constraint <%s> infeasible\n", SCIPconsGetName(cons));
2636  *result = SCIP_CUTOFF;
2637  goto TERMINATE;
2638  }
2639  if( tightened )
2640  {
2641  SCIPdebugMsg(scip, "propagation tightened bounds of lhs variable <%s> in constraint <%s>\n", SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons));
2642  *result = SCIP_REDUCEDDOM;
2643  ++*nchgbds;
2644  }
2645 
2646  c = a;
2647  SCIPintervalDivScalar(SCIPinfinity(scip), &c, c, -consdata->coefs[i]);
2648  if( consdata->offsets[i] != 0.0 )
2649  SCIPintervalSubScalar(SCIPinfinity(scip), &c, c, consdata->offsets[i]);
2650 
2651  SCIP_CALL( SCIPtightenVarLb(scip, consdata->vars[i], SCIPintervalGetInf(c), FALSE, &infeas, &tightened) );
2652  if( infeas )
2653  {
2654  SCIPdebugMsg(scip, "propagation found constraint <%s> infeasible\n", SCIPconsGetName(cons));
2655  *result = SCIP_CUTOFF;
2656  goto TERMINATE;
2657  }
2658  if( tightened )
2659  {
2660  SCIPdebugMsg(scip, "propagation tightened bounds of lhs variable <%s> in constraint <%s>\n", SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons));
2661  *result = SCIP_REDUCEDDOM;
2662  ++*nchgbds;
2663  }
2664  }
2665 
2666 TERMINATE:
2667  SCIPfreeBufferArray(scip, &lhsranges);
2668 
2669  if( *result != SCIP_DIDNOTFIND )
2670  {
2671  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2672  }
2673 
2674  return SCIP_OKAY;
2675 }
2676 
2677 /** tries to adjust a solution such that it satisfies a given constraint by increasing the value for the constraints right hand side variable */
2678 static
2680  SCIP* scip, /**< SCIP data structure */
2681  SCIP_CONS* cons, /**< constraint */
2682  SCIP_SOL* sol, /**< solution to polish */
2683  SCIP_Bool* success /**< buffer to store whether polishing was successful */
2684  )
2685 {
2686  SCIP_CONSDATA* consdata;
2687  SCIP_Real rhsval;
2688 
2689  assert(scip != NULL);
2690  assert(cons != NULL);
2691  assert(sol != NULL);
2692  assert(success != NULL);
2693 
2694  consdata = SCIPconsGetData(cons);
2695  assert(consdata != NULL);
2696  assert(!SCIPisZero(scip, consdata->rhscoeff));
2697 
2698  /* compute minimal rhs variable value so that constraint is satisfied */
2699  if( !SCIPisInfinity(scip, consdata->lhsval) )
2700  rhsval = consdata->lhsval / consdata->rhscoeff - consdata->rhsoffset;
2701  else
2702  rhsval = consdata->rhscoeff > 0.0 ? SCIPinfinity(scip) : -SCIPinfinity(scip);
2703 
2704  if( consdata->rhscoeff > 0.0 )
2705  {
2706  assert(SCIPvarMayRoundUp(consdata->rhsvar));
2707 
2708  /* round rhsval up, if variable is integral */
2709  if( SCIPvarIsIntegral(consdata->rhsvar) && !SCIPisInfinity(scip, rhsval) )
2710  rhsval = SCIPceil(scip, rhsval);
2711 
2712  /* if new value is above upper bound, we are lost */
2713  if( SCIPisGT(scip, rhsval, SCIPvarGetUbGlobal(consdata->rhsvar)) )
2714  {
2715  *success = FALSE;
2716  }
2717  else
2718  {
2719  /* if new value is larger then current one, increase to new value */
2720  if( rhsval > SCIPgetSolVal(scip, sol, consdata->rhsvar) )
2721  {
2722  SCIPdebugMsg(scip, "increase <%s> to %g\n", SCIPvarGetName(consdata->rhsvar), rhsval);
2723  SCIP_CALL( SCIPsetSolVal(scip, sol, consdata->rhsvar, rhsval) );
2724  }
2725 
2726  *success = TRUE;
2727  }
2728  }
2729  else
2730  {
2731  assert(SCIPvarMayRoundDown(consdata->rhsvar));
2732 
2733  /* round rhsval down, if variable is integral */
2734  if( SCIPvarIsIntegral(consdata->rhsvar) )
2735  rhsval = SCIPfloor(scip, rhsval);
2736 
2737  /* if new value is below lower bound, we are lost */
2738  if( SCIPisLT(scip, rhsval, SCIPvarGetLbGlobal(consdata->rhsvar)) )
2739  {
2740  *success = FALSE;
2741  }
2742  else
2743  {
2744  /* if new value is below current one, decrease to new value */
2745  if( rhsval < SCIPgetSolVal(scip, sol, consdata->rhsvar) )
2746  {
2747  SCIPdebugMsg(scip, "decrease <%s> to %g\n", SCIPvarGetName(consdata->rhsvar), rhsval);
2748  SCIP_CALL( SCIPsetSolVal(scip, sol, consdata->rhsvar, rhsval) );
2749  }
2750 
2751  *success = TRUE;
2752  }
2753  }
2754 
2755  SCIPdebugMsg(scip, "polishing solution for constraint <%s> was %ssuccessful\n", SCIPconsGetName(cons), *success ? "" : "not ");
2756 
2757  return SCIP_OKAY;
2758 }
2759 
2760 /** disaggregates a (sufficiently large) SOC constraint into smaller ones; for each term on the lhs we add a quadratic
2761  * constraint \f$(\alpha_i * (x_i + \beta_i))^2 \leq \alpha_{n+1} (x_{n+1} + \beta_{n+1})\, z_i\f$ and a single linear constraint
2762  * \f$\sum_i z_i \leq \alpha_{n+1}\, (x_{n+1} + \beta_{n+1})\f$; each quadratic constraint might be upgraded to a SOC; since the
2763  * violations of all quadratic constraints sum up we scale each constraint by the number of lhs terms + 1
2764  *
2765  * @todo if rhsvar is NULL, then the disaggregation does not produce further cones. Should it then be upgraded
2766  * to a quadratic and let the quadratic desaggregate it?
2767  * The code assumes now that the rhsvar is not NULL in order build the direct SOC -> SOC disaggregation
2768  */
2769 static
2771  SCIP* scip, /**< SCIP data structure */
2772  SCIP_CONS* cons, /**< constraint */
2773  SCIP_CONSDATA* consdata, /**< constraint data */
2774  int* naddconss, /**< pointer to count total number of added constraints */
2775  int* ndelconss, /**< pointer to count total number of deleted constraints */
2776  SCIP_Bool* success /**< pointer to store whether disaggregation was successful */
2777  )
2778 {
2779  SCIP_CONS* discons;
2780  SCIP_VAR** disvars;
2781  SCIP_VAR** sumvars;
2782  SCIP_VAR** difvars;
2783  SCIP_Real* discoefs;
2784  SCIP_VAR* lhsvars[2];
2785  SCIP_VAR* aggvars[2];
2786  SCIP_Real coefs[2];
2787  SCIP_Real offsets[2];
2788  SCIP_Real scalars[2];
2789  char name[SCIP_MAXSTRLEN];
2790  SCIP_Real constant;
2791  SCIP_Real scale;
2792  SCIP_Bool infeas;
2793  int ndisvars;
2794  int i;
2795 
2796  assert(naddconss != NULL);
2797  assert(ndelconss != NULL);
2798  assert(success != NULL);
2799 
2800  *success = FALSE;
2801 
2802  /* disaggregation does not make much sense if there are too few variables */
2803  if( consdata->nvars < 3 )
2804  {
2805  SCIPdebugMsg(scip, "can not disaggregate too small soc constraint %s\n", SCIPconsGetName(cons));
2806  return SCIP_OKAY;
2807  }
2808 
2809  if( consdata->rhsvar == NULL )
2810  {
2811  SCIPdebugMsg(scip, "can not disaggregate directly into a soc without rhs var %s\n", SCIPconsGetName(cons));
2812  return SCIP_OKAY;
2813  }
2814 
2815  /* there are at most n + 2 many linear varibles */
2816  SCIP_CALL( SCIPallocBufferArray(scip, &disvars, consdata->nvars + 2) );
2817  SCIP_CALL( SCIPallocBufferArray(scip, &sumvars, consdata->nvars + 2) );
2818  SCIP_CALL( SCIPallocBufferArray(scip, &difvars, consdata->nvars + 2) );
2819  SCIP_CALL( SCIPallocBufferArray(scip, &discoefs, consdata->nvars + 2) );
2820  ndisvars = 0;
2821 
2822  scale = 1.0 * (consdata->nvars + 1)/4.0;
2823 
2824  /* add (*) (alpha_i * (x_i + beta_i))^2 <= alpha_{n+1} * (x_{n+1} + beta_{n+1}) * z_i:
2825  * create sumvar = alpha_{n+1} * (x_{n+1} + beta_{n+1}) + z_i (multiagg)
2826  * create difvar = alpha_{n+1} * (x_{n+1} + beta_{n+1}) - z_i (multiagg)
2827  * note that (*) is equiv to sqrt( (2 * alpha_i * (x_i + beta_i))^2 + difvar^2) <= sumvar
2828  * scaling give us: sqrt( (2 * scale * alpha_i * (x_i + beta_i))^2 + (scale * difvar)^2) <= scale * sumvar
2829  */
2830  aggvars[0] = consdata->rhsvar;
2831  scalars[0] = consdata->rhscoeff;
2832  for( i = 0; i < consdata->nvars; ++i )
2833  {
2834  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "conedis_%s_%d", SCIPvarGetName(consdata->vars[i]), i);
2835  SCIP_CALL( SCIPcreateVar(scip, &disvars[i], name, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE,
2836  NULL, NULL, NULL, NULL, NULL) );
2837  SCIP_CALL( SCIPaddVar(scip, disvars[i]) );
2838 
2839  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "conedisS_%s_%d", SCIPvarGetName(consdata->vars[i]), i);
2840  SCIP_CALL( SCIPcreateVar(scip, &sumvars[i], name, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE,
2841  NULL, NULL, NULL, NULL, NULL) );
2842  SCIP_CALL( SCIPaddVar(scip, sumvars[i]) );
2843 
2844  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "conedisD_%s_%d", SCIPvarGetName(consdata->vars[i]), i);
2845  SCIP_CALL( SCIPcreateVar(scip, &difvars[i], name, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
2846  SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
2847  SCIP_CALL( SCIPaddVar(scip, difvars[i]) );
2848 
2849  aggvars[1] = disvars[i];
2850  scalars[1] = 1.0;
2851  constant = consdata->rhscoeff * consdata->rhsoffset;
2852  SCIP_CALL( SCIPmultiaggregateVar(scip, sumvars[i], 2, aggvars, scalars, constant, &infeas, success) );
2853  /* @todo what shall we do if multiagg fails? */
2854  assert(!infeas && *success);
2855 
2856  scalars[1] = -1.0;
2857  SCIP_CALL( SCIPmultiaggregateVar(scip, difvars[i], 2, aggvars, scalars, constant, &infeas, success) );
2858  assert(!infeas && *success);
2859 
2860  /* create soc */
2861  lhsvars[0] = difvars[i];
2862  coefs[0] = scale;
2863  offsets[0] = 0.0;
2864  lhsvars[1] = consdata->vars[i];
2865  coefs[1] = scale * 2 * consdata->coefs[i];
2866  offsets[1] = consdata->offsets[i];
2867 
2868  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "consdis_%s_%d", SCIPconsGetName(cons), i);
2869  SCIP_CALL( SCIPcreateConsBasicSOC(scip, &discons, name, 2, lhsvars, coefs, offsets, 0.0, sumvars[i], scale, 0.0) );
2870  SCIP_CALL( SCIPaddCons(scip, discons) );
2871 #ifdef SCIP_DEBUG
2872  SCIP_CALL( SCIPprintCons(scip, discons, NULL) );
2873 #endif
2874  SCIP_CALL( SCIPreleaseCons(scip, &discons) );
2875  ++(*naddconss);
2876 
2877  /* linear coefficient in the linear constraint */
2878  discoefs[ndisvars] = 1.0;
2879  ++ndisvars;
2880  }
2881  assert(ndisvars == consdata->nvars);
2882 
2883  /* add gamma <= alpha_{n+1} * (x_{n+1} + beta_{n+1}) * z_i
2884  * sumvar and difvar are the same as before, but the equivalent soc now is
2885  * sqrt(4 * gamma + difvar^2) <= sumvar
2886  * scaling give us: sqrt( (4 * scale^2 * gamma + (scale * difvar)^2) <= scale * sumvar
2887  */
2888  if( !SCIPisZero(scip, consdata->constant) )
2889  {
2890 
2891  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "conedis_const_%s", SCIPconsGetName(cons));
2892  SCIP_CALL( SCIPcreateVar(scip, &disvars[ndisvars], name, 0.0, SCIPinfinity(scip), 0.0,
2893  SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
2894  SCIP_CALL( SCIPaddVar(scip, disvars[ndisvars]) );
2895 
2896  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "conedisS_const_%s", SCIPconsGetName(cons));
2897  SCIP_CALL( SCIPcreateVar(scip, &sumvars[ndisvars], name, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE,
2898  NULL, NULL, NULL, NULL, NULL) );
2899  SCIP_CALL( SCIPaddVar(scip, sumvars[ndisvars]) );
2900 
2901  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "conedisD_const_%s", SCIPconsGetName(cons));
2902  SCIP_CALL( SCIPcreateVar(scip, &difvars[ndisvars], name, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
2903  SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
2904  SCIP_CALL( SCIPaddVar(scip, difvars[ndisvars]) );
2905 
2906  aggvars[1] = disvars[i];
2907  scalars[1] = 1.0;
2908  constant = consdata->rhscoeff * consdata->rhsoffset;
2909  SCIP_CALL( SCIPmultiaggregateVar(scip, sumvars[i], 2, aggvars, scalars, constant, &infeas, success) );
2910  assert(!infeas && *success);
2911 
2912  scalars[1] = -1.0;
2913  SCIP_CALL( SCIPmultiaggregateVar(scip, difvars[i], 2, aggvars, scalars, constant, &infeas, success) );
2914  assert(!infeas && *success);
2915 
2916  /* create soc */
2917  lhsvars[0] = difvars[ndisvars];
2918  coefs[0] = scale;
2919  offsets[0] = 0.0;
2920  constant = 4.0 * SQR(scale) * consdata->constant;
2921  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "consdis_%s_constant", SCIPconsGetName(cons));
2922  SCIP_CALL( SCIPcreateConsBasicSOC(scip, &discons, name, 1, lhsvars, coefs, offsets, constant,
2923  sumvars[ndisvars], scale, 0.0) );
2924  SCIP_CALL( SCIPaddCons(scip, discons) );
2925  SCIP_CALL( SCIPreleaseCons(scip, &discons) );
2926  ++(*naddconss);
2927 
2928  /* linear coefficient in the linear constraint */
2929  discoefs[ndisvars] = 1.0;
2930  ++ndisvars;
2931  }
2932 
2933  /* create linear constraint sum z_i <= alpha_{n+1} * (x_{n+1} + beta_{n+1}); first add extra coefficient for the rhs */
2934  discoefs[ndisvars] = -1.0 * consdata->rhscoeff;
2935  disvars[ndisvars] = consdata->rhsvar;
2936 
2937  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "consdis_linear_%s", SCIPconsGetName(cons));
2938  SCIP_CALL( SCIPcreateConsBasicLinear(scip, &discons, name, ndisvars + 1, disvars, discoefs, -SCIPinfinity(scip),
2939  consdata->rhscoeff * consdata->rhsoffset) );
2940 
2941  SCIP_CALL( SCIPaddCons(scip, discons) );
2942  SCIP_CALL( SCIPreleaseCons(scip, &discons) );
2943  ++(*naddconss);
2944 
2945  /* release all variables */
2946  for( i = ndisvars - 1; i >= 0; --i )
2947  {
2948  SCIP_CALL( SCIPreleaseVar(scip, &disvars[i]) );
2949  SCIP_CALL( SCIPreleaseVar(scip, &sumvars[i]) );
2950  SCIP_CALL( SCIPreleaseVar(scip, &difvars[i]) );
2951  }
2952  SCIPfreeBufferArray(scip, &discoefs);
2953  SCIPfreeBufferArray(scip, &difvars);
2954  SCIPfreeBufferArray(scip, &sumvars);
2955  SCIPfreeBufferArray(scip, &disvars);
2956 
2957  /* delete constraint */
2958  SCIP_CALL( SCIPdelCons(scip, cons) );
2959  ++(*ndelconss);
2960 
2961  *success = TRUE;
2962 
2963  return SCIP_OKAY;
2964 }
2965 
2966 
2967 /** helper function to enforce constraints */
2968 static
2970  SCIP* scip, /**< SCIP data structure */
2971  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2972  SCIP_CONS** conss, /**< constraints to process */
2973  int nconss, /**< number of constraints */
2974  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
2975  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
2976  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
2977  )
2978 {
2979  SCIP_CONSHDLRDATA* conshdlrdata;
2980  SCIP_CONSDATA* consdata;
2981  SCIP_CONS* maxviolcons;
2982  SCIP_Bool success;
2983  SCIP_Bool cutoff;
2984  SCIP_Bool redundant;
2985  int nbndchg;
2986  int c;
2987 
2988  assert(scip != NULL);
2989  assert(conshdlr != NULL);
2990  assert(conss != NULL || nconss == 0);
2991  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2992  assert(result != NULL);
2993 
2994  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2995  assert(conshdlrdata != NULL);
2996 
2997  SCIP_CALL( computeViolations(scip, conshdlr, conss, nconss, sol, &maxviolcons) );
2998 
2999  if( maxviolcons == NULL )
3000  {
3001  *result = SCIP_FEASIBLE;
3002  return SCIP_OKAY;
3003  }
3004 
3005  /* if we are above the 100'th enforcement round for this node, something is strange
3006  * (maybe the LP does not think that the cuts we add are violated, or we do ECP on a high-dimensional convex function)
3007  * 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
3008  * (in optimized more, returning SCIP_INFEASIBLE in *result would be sufficient, but in debug mode this would give an assert in scip.c)
3009  * the reason to wait for 100 rounds is to avoid calls to SCIPisStopped in normal runs, which may be expensive
3010  * we only increment nenforounds until 101 to avoid an overflow
3011  */
3012  if( conshdlrdata->lastenfonode == SCIPgetCurrentNode(scip) )
3013  {
3014  if( conshdlrdata->nenforounds > 100 )
3015  {
3016  if( SCIPisStopped(scip) )
3017  {
3018  SCIP_NODE* child;
3019 
3020  SCIP_CALL( SCIPcreateChild(scip, &child, 1.0, SCIPnodeGetEstimate(SCIPgetCurrentNode(scip))) );
3021  *result = SCIP_BRANCHED;
3022 
3023  return SCIP_OKAY;
3024  }
3025  }
3026  else
3027  ++conshdlrdata->nenforounds;
3028  }
3029  else
3030  {
3031  conshdlrdata->lastenfonode = SCIPgetCurrentNode(scip);
3032  conshdlrdata->nenforounds = 0;
3033  }
3034 
3035  /* try separation, this should usually work */
3036  SCIP_CALL( separatePoint(scip, conshdlr, conss, nconss, nusefulconss, sol, TRUE, &cutoff, &success) );
3037  if( cutoff )
3038  {
3039  *result = SCIP_CUTOFF;
3040  return SCIP_OKAY;
3041  }
3042  if( success )
3043  {
3044  SCIPdebugMsg(scip, "enforced by separation\n");
3045  *result = SCIP_SEPARATED;
3046  return SCIP_OKAY;
3047  }
3048 
3049  /* try propagation */
3050  for( c = 0; c < nconss; ++c )
3051  {
3052  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
3053  if( !SCIPisGT(scip, consdata->violation, SCIPfeastol(scip)) )
3054  continue;
3055 
3056  nbndchg = 0;
3057  SCIP_CALL( propagateBounds(scip, conss[c], result, &nbndchg, &redundant) ); /*lint !e613*/
3058  assert(!redundant); /* constraint should not be violated and redundant simultaneously (unless solution is far out of bounds) */
3059  if( *result == SCIP_CUTOFF || *result == SCIP_REDUCEDDOM )
3060  {
3061  SCIPdebugMsg(scip, "enforced by %s\n", *result == SCIP_CUTOFF ? "cutting off node" : "reducing domain");
3062  return SCIP_OKAY;
3063  }
3064  }
3065 
3066  SCIPwarningMessage(scip, "could not enforce feasibility by separating or branching; declaring solution with viol %g feasible\n", SCIPconsGetData(maxviolcons)->violation);
3067  *result = SCIP_FEASIBLE;
3068 
3069  return SCIP_OKAY;
3070 }
3071 
3072 /*
3073  * Quadratic constraint upgrading
3074  */
3075 
3076 
3077 #ifdef QUADCONSUPGD_PRIORITY
3078 /** tries to upgrade a quadratic constraint to a SOC constraint
3079  *
3080  * We treat as special cases, quadratic with no bilinear terms and hyperbolic quadratic
3081  * constraints with exactly on bilinear component containing nonnegative variables. For this we use the formula:
3082  * \f[
3083  * x^T x \leq yz,\; y \geq 0,\; z \geq 0
3084  * \qquad\Leftrightarrow\qquad
3085  * \left\| \left(\begin{array}{c} x \\ \frac{1}{2}(y - z)\end{array}\right) \right\| \leq \frac{1}{2}(y + z).
3086  * \f]
3087  *
3088  * @todo implement more general hyperbolic upgrade, e.g., for -x^T x + yz >= 0 or x^T x <= ax + by + cyz
3089  */
3090 static
3091 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
3093  int nquadvars;
3094  int nbilinterms;
3095  SCIP_QUADVARTERM* term;
3096  SCIP_QUADVARTERM* quadterms;
3097  SCIP_BILINTERM* bilinterm;
3098  SCIP_VAR** quadvars;
3099  SCIP_VAR** lhsvars;
3100  SCIP_Real* lhscoefs;
3101  SCIP_Real* lhsoffsets;
3102  SCIP_Real lhsconstant;
3103  int lhscount;
3104  int lhsnvars;
3105  SCIP_VAR* rhsvar;
3106  SCIP_Real rhscoef;
3107  SCIP_Real rhsoffset;
3108  SCIP_VAR* bilinvar1;
3109  SCIP_VAR* bilinvar2;
3110  SCIP_Real bilincoef;
3111  int i;
3112  int j;
3113  int negeigpos;
3114  SCIP_Real* a;
3115  SCIP_Real* bp;
3116  SCIP_Real* eigvals;
3117  SCIP_Bool infeas;
3118  SCIP_Bool success;
3119  SCIP_Bool trygeneralupg;
3120  int nneg;
3121  int npos;
3122  SCIP_Bool rhsvarfound;
3123  SCIP_Bool rhsissoc;
3124  SCIP_Bool lhsissoc;
3125  SCIP_Real rhsvarlb;
3126  SCIP_Real rhsvarub;
3127  SCIP_CONSHDLR* conshdlr;
3128  SCIP_CONSHDLRDATA* conshdlrdata;
3129 
3130  assert(scip != NULL);
3131  assert(cons != NULL);
3132  assert(nupgdconss != NULL);
3133  assert(upgdconss != NULL);
3134 
3135  *nupgdconss = 0;
3136 
3137  SCIPdebugMsg(scip, "upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
3138  SCIPdebugPrintCons(scip, cons, NULL);
3139 
3140  /* currently do not support linear parts in upgrading of SOC constraints */
3141  if( SCIPgetNLinearVarsQuadratic(scip, cons) > 0 )
3142  return SCIP_OKAY;
3143 
3144  nbilinterms = SCIPgetNBilinTermsQuadratic(scip, cons);
3145  nquadvars = SCIPgetNQuadVarTermsQuadratic(scip, cons);
3146 
3147  /* currently, a proper SOC constraint needs at least 3 variables */
3148  if( nquadvars < 3 )
3149  return SCIP_OKAY;
3150 
3151  /* reserve space */
3152  SCIP_CALL( SCIPallocBufferArray(scip, &lhsvars, nquadvars - 1) );
3153  SCIP_CALL( SCIPallocBufferArray(scip, &lhscoefs, nquadvars - 1) );
3154  SCIP_CALL( SCIPallocBufferArray(scip, &lhsoffsets, nquadvars - 1) );
3155 
3156  /* initialize data */
3157  a = NULL;
3158  bp = NULL;
3159  eigvals = NULL;
3160  quadvars = NULL;
3161  bilinvar1 = NULL;
3162  bilinvar2 = NULL;
3163  lhsconstant = 0.0;
3164  lhscount = 0;
3165  rhsvar = NULL;
3166  rhscoef = 0.0;
3167  rhsoffset = 0.0;
3168 
3169  trygeneralupg = FALSE;
3170 
3171  /* if more than one bilinear term is present, we are in the general case */
3172  if( nbilinterms > 1 )
3173  {
3174  trygeneralupg = TRUE;
3175  goto GENERALUPG;
3176  }
3177 
3178  /* check hyperbolic part */
3179  if ( nbilinterms == 1 )
3180  {
3181  bilinterm = SCIPgetBilinTermsQuadratic(scip, cons);
3182  bilinvar1 = bilinterm->var1;
3183  bilinvar2 = bilinterm->var2;
3184  bilincoef = bilinterm->coef;
3185 
3186  /* the variables in the bilinear term need to be nonnegative */
3187  if ( SCIPisNegative(scip, SCIPvarGetLbGlobal(bilinvar1)) || SCIPisNegative(scip, SCIPvarGetLbGlobal(bilinvar2)) )
3188  {
3189  trygeneralupg = TRUE;
3190  goto GENERALUPG;
3191  }
3192 
3193  /* we need a rhs */
3194  if ( ! SCIPisZero(scip, SCIPgetRhsQuadratic(scip, cons)) )
3195  {
3196  trygeneralupg = TRUE;
3197  goto GENERALUPG;
3198  }
3199 
3200  /* we only allow for -1.0 bilincoef */
3201  if ( ! SCIPisEQ(scip, bilincoef, -1.0) )
3202  {
3203  trygeneralupg = TRUE;
3204  goto GENERALUPG;
3205  }
3206 
3207  /* check that bilinear terms do not appear in the rest and quadratic terms have postive sqrcoef have no lincoef */
3208  quadterms = SCIPgetQuadVarTermsQuadratic(scip, cons);
3209  for (i = 0; i < nquadvars; ++i)
3210  {
3211  term = &quadterms[i];
3212 
3213  if( ! SCIPisZero(scip, term->lincoef) || SCIPisNegative(scip, term->sqrcoef) )
3214  {
3215  trygeneralupg = TRUE;
3216  goto GENERALUPG;
3217  }
3218 
3219  if ( (term->var == bilinvar1 || term->var == bilinvar2) && ! SCIPisZero(scip, term->sqrcoef) )
3220  {
3221  trygeneralupg = TRUE;
3222  goto GENERALUPG;
3223  }
3224  }
3225  }
3226 
3227 
3228  quadterms = SCIPgetQuadVarTermsQuadratic(scip, cons);
3229  assert( quadterms != NULL );
3230 
3231  if( ! SCIPisInfinity(scip, SCIPgetRhsQuadratic(scip, cons)) )
3232  {
3233  /* try whether constraint on right hand side is SOC */
3234  lhsconstant = -SCIPgetRhsQuadratic(scip, cons);
3235 
3236  for( i = 0; i < nquadvars; ++i )
3237  {
3238  term = &quadterms[i];
3239 
3240  /* skip terms with 0 coefficients */
3241  if ( SCIPisZero(scip, term->sqrcoef) )
3242  continue;
3243 
3244  if( term->sqrcoef > 0.0 )
3245  {
3246  if( lhscount >= nquadvars - 1 )
3247  { /* too many variables on lhs, i.e., all variables seem to have positive coefficient */
3248  rhsvar = NULL;
3249  break;
3250  }
3251 
3252  lhsvars[lhscount] = term->var;
3253  lhscoefs[lhscount] = sqrt(term->sqrcoef);
3254 
3255  if( term->lincoef != 0.0 )
3256  {
3257  lhsoffsets[lhscount] = term->lincoef / (2 * term->sqrcoef);
3258  lhsconstant -= term->lincoef * term->lincoef / (4 * term->sqrcoef);
3259  }
3260  else
3261  {
3262  lhsoffsets[lhscount] = 0.0;
3263  }
3264 
3265  ++lhscount;
3266  }
3267  else if( rhsvar != NULL ||
3268  (SCIPisLT(scip, SCIPcomputeVarLbGlobal(scip, term->var), -term->lincoef / (2 * term->sqrcoef))
3269  && SCIPisGT(scip, SCIPcomputeVarUbGlobal(scip, term->var), -term->lincoef / (2 * term->sqrcoef))) )
3270  { /* second variable with negative coefficient -> cannot be SOC */
3271  /* or rhs side changes sign */
3272  rhsvar = NULL;
3273  break;
3274  }
3275  else
3276  {
3277  rhsvar = term->var;
3278  rhsoffset = term->lincoef / (2 * term->sqrcoef);
3279  lhsconstant -= term->lincoef * term->lincoef / (4 * term->sqrcoef);
3280 
3281  if( SCIPisGE(scip, SCIPcomputeVarLbGlobal(scip, term->var), -term->lincoef / (2*term->sqrcoef)) )
3282  rhscoef = sqrt(-term->sqrcoef);
3283  else
3284  rhscoef = -sqrt(-term->sqrcoef);
3285  }
3286  }
3287  }
3288 
3289  /* treat hyberbolic case */
3290  if ( nbilinterms == 1 )
3291  {
3292  char name[SCIP_MAXSTRLEN];
3293  SCIP_VAR* auxvarsum;
3294  SCIP_VAR* auxvardiff;
3295  SCIP_CONS* couplingcons;
3296  SCIP_VAR* consvars[3];
3297  SCIP_Real consvals[3];
3298 
3299  /* can only upgrade if rhs is 0 */
3300  if ( rhsvar != NULL )
3301  goto cleanup;
3302 
3303  SCIPdebugMsg(scip, "found hyberbolic quadratic constraint <%s> to be SOC\n", SCIPconsGetName(cons));
3304 
3305  /* check if upgdconss is long enough to store upgrade constraints: we need two if we will have a quadratic
3306  * constraint for the left hand side left */
3307  *nupgdconss = SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, cons)) ? 1 : 2;
3308  if ( *nupgdconss > upgdconsssize )
3309  {
3310  /* signal that we need more memory and return */
3311  *nupgdconss = -*nupgdconss;
3312  goto cleanup;
3313  }
3314 
3315  /* create auxiliary variable for sum (nonnegative) */
3316  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "soc#%s_s", SCIPconsGetName(cons));
3317  SCIP_CALL( SCIPcreateVar(scip, &auxvarsum, name, 0.0, SCIPinfinity(scip), 0.0,
3318  SCIP_VARTYPE_CONTINUOUS, SCIPconsIsInitial(cons), FALSE, NULL, NULL, NULL, NULL, NULL) );
3319  SCIP_CALL( SCIPaddVar(scip, auxvarsum) );
3320 
3321  /* create auxiliary variable for difference (free) */
3322  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "soc#%s_d", SCIPconsGetName(cons));
3323  SCIP_CALL( SCIPcreateVar(scip, &auxvardiff, name, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
3324  SCIP_VARTYPE_CONTINUOUS, SCIPconsIsInitial(cons), FALSE, NULL, NULL, NULL, NULL, NULL) );
3325  SCIP_CALL( SCIPaddVar(scip, auxvardiff) );
3326 
3327  /* add coupling constraint for sum */
3328  consvars[0] = bilinvar1;
3329  consvars[1] = bilinvar2;
3330  consvars[2] = auxvarsum;
3331  consvals[0] = 1.0;
3332  consvals[1] = 1.0;
3333  consvals[2] = -1.0;
3334 
3335  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "soc#%s_cs", SCIPconsGetName(cons));
3336  SCIP_CALL( SCIPcreateConsLinear(scip, &couplingcons, name, 3, consvars, consvals, 0.0, 0.0,
3340  SCIPconsIsStickingAtNode(cons)) );
3341  SCIP_CALL( SCIPaddCons(scip, couplingcons) );
3342  SCIP_CALL( SCIPreleaseCons(scip, &couplingcons) );
3343 
3344  /* add coupling constraint for difference */
3345  consvars[0] = bilinvar1;
3346  consvars[1] = bilinvar2;
3347  consvars[2] = auxvardiff;
3348  consvals[0] = 1.0;
3349  consvals[1] = -1.0;
3350  consvals[2] = -1.0;
3351 
3352  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "soc#%s_cd", SCIPconsGetName(cons));
3353  SCIP_CALL( SCIPcreateConsLinear(scip, &couplingcons, name, 3, consvars, consvals, 0.0, 0.0,
3357  SCIPconsIsStickingAtNode(cons)) );
3358  SCIP_CALL( SCIPaddCons(scip, couplingcons) );
3359  SCIP_CALL( SCIPreleaseCons(scip, &couplingcons) );
3360 
3361  /* add difference variable to constraint */
3362  lhsvars[lhscount] = auxvardiff;
3363  lhscoefs[lhscount] = 0.5;
3364  lhsoffsets[lhscount] = 0.0;
3365 
3366  SCIP_CALL( SCIPcreateConsSOC(scip, &upgdconss[0], SCIPconsGetName(cons),
3367  lhscount + 1, lhsvars, lhscoefs, lhsoffsets, MAX(lhsconstant, 0.0),
3368  auxvarsum, 0.5, 0.0,
3372  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
3373 
3374  /* create constraint that is equal to cons except that rhs is now infinity */
3375  if( ! SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, cons)) )
3376  {
3377  SCIP_CALL( SCIPcreateConsQuadratic2(scip, &upgdconss[1], SCIPconsGetName(cons),
3381  SCIPgetLhsQuadratic(scip, cons), SCIPinfinity(scip),
3385  }
3386  SCIP_CALL( SCIPreleaseVar(scip, &auxvardiff) );
3387  SCIP_CALL( SCIPreleaseVar(scip, &auxvarsum) );
3388 
3389  for (i = 0; i < lhscount; ++i)
3390  {
3391  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, lhsvars[i]) );
3392  }
3393 
3394  goto cleanup;
3395  }
3396 
3397  if( rhsvar != NULL && lhscount >= 2 && !SCIPisNegative(scip, lhsconstant) )
3398  { /* found SOC constraint, so upgrade to SOC constraint(s) (below) and relax right hand side */
3399  SCIPdebugMsg(scip, "found right hand side of constraint <%s> to be SOC\n", SCIPconsGetName(cons));
3400 
3401  /* check if upgdconss is long enough to store upgrade constraints:
3402  * we need two if we will have a quadratic constraint for the left hand side left */
3403  *nupgdconss = SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, cons)) ? 1 : 2;
3404  if( *nupgdconss > upgdconsssize )
3405  {
3406  /* signal that we need more memory and return */
3407  *nupgdconss = -*nupgdconss;
3408  goto cleanup;
3409  }
3410 
3411  SCIP_CALL( SCIPcreateConsSOC(scip, &upgdconss[0], SCIPconsGetName(cons),
3412  lhscount, lhsvars, lhscoefs, lhsoffsets, MAX(lhsconstant, 0.0),
3413  rhsvar, rhscoef, rhsoffset,
3417  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
3418 
3419  /* create constraint that is equal to cons except that rhs is now infinity */
3420  if( !SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, cons)) )
3421  {
3422  SCIP_CALL( SCIPcreateConsQuadratic2(scip, &upgdconss[1], SCIPconsGetName(cons),
3426  SCIPgetLhsQuadratic(scip, cons), SCIPinfinity(scip),
3430  }
3431  }
3432  else if( !SCIPisInfinity(scip, - SCIPgetLhsQuadratic(scip, cons)) )
3433  { /* if the first failed, try if constraint on left hand side is SOC (using negated coefficients) */
3434  lhscount = 0;
3435  rhsvar = NULL;
3436 
3437  lhsconstant = SCIPgetLhsQuadratic(scip, cons);
3438 
3439  for( i = 0; i < nquadvars; ++i )
3440  {
3441  term = &SCIPgetQuadVarTermsQuadratic(scip, cons)[i];
3442 
3443  /* if there is a linear variable that is still considered as quadratic (constraint probably not presolved yet),
3444  * then give up
3445  */
3446  if( term->sqrcoef == 0.0 )
3447  goto cleanup;
3448 
3449  if( term->sqrcoef < 0.0 )
3450  {
3451  if( lhscount >= nquadvars - 1 )
3452  { /* too many variables on lhs, i.e., all variables seem to have negative coefficient */
3453  rhsvar = NULL;
3454  break;
3455  }
3456 
3457  lhsvars[lhscount] = term->var;
3458  lhscoefs[lhscount] = sqrt(-term->sqrcoef);
3459 
3460  if( term->lincoef != 0.0 )
3461  {
3462  lhsoffsets[lhscount] = term->lincoef / (2 * term->sqrcoef);
3463  lhsconstant += term->lincoef * term->lincoef / (4 * term->sqrcoef);
3464  }
3465  else
3466  {
3467  lhsoffsets[lhscount] = 0.0;
3468  }
3469 
3470  ++lhscount;
3471  }
3472  else if( rhsvar != NULL ||
3473  (SCIPisLT(scip, SCIPcomputeVarLbGlobal(scip, term->var), -term->lincoef / (2 * term->sqrcoef))
3474  && SCIPisGT(scip, SCIPcomputeVarUbGlobal(scip, term->var), -term->lincoef / (2 * term->sqrcoef))) )
3475  { /* second variable with positive coefficient -> cannot be SOC */
3476  /* or rhs side changes sign */
3477  rhsvar = NULL;
3478  break;
3479  }
3480  else
3481  {
3482  rhsvar = term->var;
3483  rhsoffset = term->lincoef / (2 * term->sqrcoef);
3484  lhsconstant += term->lincoef * term->lincoef / (4 * term->sqrcoef);
3485 
3486  if( SCIPisGE(scip, SCIPcomputeVarLbGlobal(scip, term->var), -term->lincoef / (2*term->sqrcoef)) )
3487  rhscoef = sqrt(term->sqrcoef);
3488  else
3489  rhscoef = -sqrt(term->sqrcoef);
3490  }
3491  }
3492 
3493  if( rhsvar && lhscount >= 2 && !SCIPisNegative(scip, lhsconstant) )
3494  { /* found SOC constraint, so upgrade to SOC constraint(s) (below) and relax left hand side */
3495  SCIPdebugMsg(scip, "found left hand side of constraint <%s> to be SOC\n", SCIPconsGetName(cons));
3496 
3497  /* check if upgdconss is long enough to store upgrade constraints:
3498  * we need two if we will have a quadratic constraint for the right hand side left */
3499  *nupgdconss = SCIPisInfinity(scip, SCIPgetRhsQuadratic(scip, cons)) ? 1 : 2;
3500  if( *nupgdconss > upgdconsssize )
3501  {
3502  /* signal that we need more memory and return */
3503  *nupgdconss = -*nupgdconss;
3504  goto cleanup;
3505  }
3506 
3507  SCIP_CALL( SCIPcreateConsSOC(scip, &upgdconss[0], SCIPconsGetName(cons),
3508  lhscount, lhsvars, lhscoefs, lhsoffsets, MAX(lhsconstant, 0.0),
3509  rhsvar, rhscoef, rhsoffset,
3513  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
3514 
3515  /* create constraint that is equal to cons except that lhs is now -infinity */
3516  if( !SCIPisInfinity(scip, SCIPgetRhsQuadratic(scip, cons)) )
3517  {
3518  SCIP_CALL( SCIPcreateConsQuadratic2(scip, &upgdconss[1], SCIPconsGetName(cons),
3522  -SCIPinfinity(scip), SCIPgetRhsQuadratic(scip, cons),
3526  }
3527  }
3528  }
3529 
3530 GENERALUPG:
3531  if( !trygeneralupg )
3532  goto cleanup;
3533 
3534  /* find the soc constraint handler */
3535  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3536  assert(conshdlr != NULL);
3537  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3538  assert(conshdlrdata != NULL);
3539 
3540  if( !conshdlrdata->generalsocupg )
3541  goto cleanup;
3542 
3543  SCIPdebugMsg(scip, "Trying general method of upgrade to a soc const\n");
3544 
3545  rhsvarlb = 1.0;
3546  rhsvarub = 0.0;
3547 
3548 #ifndef SCIP_STATISTIC
3549  /* skip large matrices (needs to compute eigenvalues/vectors) according to presolve timing */
3550  if( (presoltiming & SCIP_PRESOLTIMING_FAST) != 0 && nquadvars > 10 )
3551  goto cleanup;
3552  if( (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 && nquadvars > 50 )
3553  goto cleanup;
3554 #endif
3555 
3556  /* need routine to compute eigenvalues/eigenvectors */
3557  if( !SCIPisIpoptAvailableIpopt() )
3558  goto cleanup;
3559 
3560  /* build lower triangular part the A matrix */
3561  SCIP_CALL( SCIPallocClearBufferArray(scip, &a, nquadvars*nquadvars) ); /*lint !e647*/
3562  SCIP_CALL( SCIPallocClearBufferArray(scip, &bp, nquadvars) );
3563  SCIP_CALL( SCIPallocBufferArray(scip, &quadvars, nquadvars) );
3564  SCIP_CALL( SCIPallocBufferArray(scip, &eigvals, nquadvars) );
3565 
3566  /* make sure quadratic variables terms are sorted */
3568 
3569  /* set lower triangular entries of A corresponding to square terms */
3570  for( i = 0; i < nquadvars; ++i )
3571  {
3572  term = &SCIPgetQuadVarTermsQuadratic(scip, cons)[i];
3573  a[i*nquadvars + i] = term->sqrcoef;
3574  quadvars[i] = term->var;
3575  }
3576 
3577  /* set lower triangular entries of A corresponding to bilinear terms */
3578  for( i = 0; i < nbilinterms; ++i )
3579  {
3580  int idx1;
3581  int idx2;
3582 
3583  bilinterm = &SCIPgetBilinTermsQuadratic(scip, cons)[i];
3584 
3585  SCIP_CALL( SCIPfindQuadVarTermQuadratic(scip, cons, bilinterm->var1, &idx1) );
3586  SCIP_CALL( SCIPfindQuadVarTermQuadratic(scip, cons, bilinterm->var2, &idx2) );
3587 
3588  assert(idx1 >= 0);
3589  assert(idx2 >= 0);
3590  assert(idx1 != idx2);
3591 
3592  a[MIN(idx1,idx2) * nquadvars + MAX(idx1,idx2)] = bilinterm->coef / 2.0;
3593  }
3594 
3595  /* compute eigenvalues and vectors, A = PDP^t
3596  * note: a stores P^t
3597  */
3598  if( LapackDsyev(TRUE, nquadvars, a, eigvals) != SCIP_OKAY )
3599  {
3600  SCIPdebugMsg(scip, "Failed to compute eigenvalues and eigenvectors for constraint <%s>.\n", SCIPconsGetName(cons));
3601  goto cleanup;
3602  }
3603 
3604  /* set small eigenvalues to 0 and compute b*P */
3605  nneg = 0;
3606  npos = 0;
3607  for( i = 0; i < nquadvars; ++i )
3608  {
3609  for( j = 0; j < nquadvars; ++j )
3610  {
3611  term = &SCIPgetQuadVarTermsQuadratic(scip, cons)[j];
3612  bp[i] += term->lincoef * a[i * nquadvars + j];
3613  }
3614 
3615  if( SCIPisZero(scip, eigvals[i]) )
3616  {
3617  /* if there is a purely linear variable, the constraint can't be written as a SOC */
3618  if( !SCIPisZero(scip, bp[i]) )
3619  {
3620  goto cleanup;
3621  }
3622 
3623  bp[i] = 0.0;
3624  eigvals[i] = 0.0;
3625  }
3626  else if( eigvals[i] > 0.0 )
3627  npos++;
3628  else
3629  nneg++;
3630  }
3631 
3632  /* currently, a proper SOC constraint needs at least 3 variables */
3633  if( npos + nneg < 3 )
3634  goto cleanup;
3635 
3636  /* determine whether rhs or lhs of cons is potentially SOC, if any */
3637  rhsissoc = nneg == 1 && !SCIPisInfinity(scip, SCIPgetRhsQuadratic(scip, cons));
3638  lhsissoc = npos == 1 && !SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, cons));
3639 
3640  /* if non is potentially SOC, stop */
3641  if( !rhsissoc && !lhsissoc )
3642  goto cleanup;
3643 
3644  assert(rhsissoc != lhsissoc);
3645 
3646 
3647  if( lhsissoc )
3648  {
3649  /* lhs is potentially SOC, change signs */
3650  lhsconstant = SCIPgetLhsQuadratic(scip, cons);
3651 
3652  for( i = 0; i < nquadvars; ++i )
3653  {
3654  eigvals[i] = -eigvals[i];
3655  bp[i] = -bp[i];
3656  }
3657  }
3658  else
3659  {
3660  lhsconstant = -SCIPgetRhsQuadratic(scip, cons);
3661  }
3662 
3663  /* we have lhsconstant + x^t A x + b x <= 0 and A has a single negative eigenvalue; try to build soc */
3664  negeigpos = -1;
3665  rhsvarfound = FALSE;
3666  for( i = 0; i < nquadvars; ++i )
3667  {
3668  if( SCIPisZero(scip, eigvals[i]) )
3669  continue;
3670 
3671  if( eigvals[i] > 0.0 )
3672  {
3673  lhscoefs[lhscount] = sqrt(eigvals[i]) * UPGSCALE;
3674  lhsoffsets[lhscount] = bp[i] / (2 * eigvals[i]);
3675  lhsconstant -= bp[i] * bp[i] / (4 * eigvals[i]);
3676 
3677  ++lhscount;
3678  }
3679  else
3680  {
3681  /* should enter here only once */
3682  assert(rhsvarfound == FALSE);
3683 
3684  rhsoffset = bp[i] / (2 * eigvals[i]);
3685 
3686  /* the constraint can only be a soc if the resulting rhs var does not change var; the rhs var is going to be a
3687  * multiaggregated variable, so estimate its bounds
3688  */
3689  rhsvarlb = 0.0;
3690  rhsvarub = 0.0;
3691  for( j = 0; j < nquadvars; ++j )
3692  {
3693  SCIP_Real aux;
3694 
3695  if( a[i * nquadvars + j] > 0.0 )
3696  {
3697  aux = SCIPcomputeVarLbGlobal(scip, quadvars[j]);
3698  assert(!SCIPisInfinity(scip, aux));
3699  }
3700  else
3701  {
3702  aux = SCIPcomputeVarUbGlobal(scip, quadvars[j]);
3703  assert(!SCIPisInfinity(scip, -aux));
3704  }
3705 
3706  if( SCIPisInfinity(scip, aux) || SCIPisInfinity(scip, -aux) )
3707  {
3708  rhsvarlb = -SCIPinfinity(scip);
3709  break;
3710  }
3711  else
3712  rhsvarlb += a[i * nquadvars + j] * aux;
3713  }
3714  rhsvarlb += rhsoffset;
3715 
3716  for( j = 0; j < nquadvars; ++j )
3717  {
3718  SCIP_Real aux;
3719 
3720  if( a[i * nquadvars + j] > 0.0 )
3721  {
3722  aux = SCIPcomputeVarUbGlobal(scip, quadvars[j]);
3723  assert(!SCIPisInfinity(scip, -aux));
3724  }
3725  else
3726  {
3727  aux = SCIPcomputeVarLbGlobal(scip, quadvars[j]);
3728  assert(!SCIPisInfinity(scip, aux));
3729  }
3730 
3731  if( SCIPisInfinity(scip, aux) || SCIPisInfinity(scip, -aux) )
3732  {
3733  rhsvarub = SCIPinfinity(scip);
3734  break;
3735  }
3736  else
3737  rhsvarub += a[i * nquadvars + j] * aux;
3738  }
3739  rhsvarub += rhsoffset;
3740 
3741  /* since we are just interested in obtaining an interval that contains the real bounds and is tight enough so
3742  * that we can identify that the rhsvar does not change sign, we swap the bounds in case of numerical troubles
3743  */
3744  if( rhsvarub < rhsvarlb )
3745  {
3746  assert(SCIPisEQ(scip, rhsvarub, rhsvarlb));
3747  SCIPswapReals(&rhsvarub, &rhsvarlb);
3748  }
3749 
3750  /* check whether rhsvar changes sign */
3751  if( SCIPisGE(scip, rhsvarlb, 0.0) || SCIPisLE(scip, rhsvarub, 0.0) )
3752  {
3753  rhsvarfound = TRUE;
3754  negeigpos = i;
3755  lhsconstant -= rhsoffset * rhsoffset * eigvals[i];
3756  rhscoef = SCIPisLE(scip, rhsvarub, 0.0) ? -sqrt(-eigvals[i]) : sqrt(-eigvals[i]);
3757  }
3758  else
3759  {
3760  SCIPdebugMsg(scip, "Failed because rhsvar [%g, %g] changes sign.\n", rhsvarlb, rhsvarub);
3761  rhsvarfound = FALSE;
3762  break;
3763  }
3764  }
3765  }
3766 
3767  if( rhsvarfound && lhscount >= 2 && !SCIPisNegative(scip, lhsconstant) )
3768  {
3769  /* found SOC constraint, so upgrade to SOC constraint(s) (below) and relax right hand side */
3770  SCIPdebugMsg(scip, "found right hand side of constraint <%s> to be SOC\n", SCIPconsGetName(cons));
3771 
3772  /* check if upgdconss is long enough to store upgrade constraints:
3773  * we need two if we will have a quadratic constraint for the left hand side left */
3774  if( rhsissoc )
3775  *nupgdconss = SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, cons)) ? 1 : 2;
3776  else
3777  *nupgdconss = SCIPisInfinity(scip, SCIPgetRhsQuadratic(scip, cons)) ? 1 : 2;
3778  if( *nupgdconss > upgdconsssize )
3779  {
3780  /* signal that we need more memory and return */
3781  *nupgdconss = -*nupgdconss;
3782  goto cleanup;
3783  }
3784 
3785  /* create lhs and rhs vars */
3786  lhsnvars = 0;
3787  for( i = 0; i < nquadvars; ++i )
3788  {
3789  if( eigvals[i] <= 0.0 )
3790  continue;
3791 
3792  SCIP_CALL( SCIPcreateVarBasic(scip, &lhsvars[lhsnvars], NULL,
3793  -SCIPinfinity(scip), SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS) );
3794  SCIP_CALL( SCIPaddVar(scip, lhsvars[lhsnvars]) );
3795 
3796  SCIP_CALL( SCIPmultiaggregateVar(scip, lhsvars[lhsnvars], nquadvars, quadvars, &(a[i * nquadvars]),
3797  lhsoffsets[lhsnvars], &infeas, &success) );
3798 
3799  if( infeas || !success )
3800  {
3801  SCIPdebugMsg(scip, "Problem with aggregation while trying to upgrade <%s>.\n", SCIPconsGetName(cons) );
3802 
3803  /* release all created vars so far */
3804  for( j = 0; j <= lhsnvars; ++j )
3805  SCIP_CALL( SCIPreleaseVar(scip, &lhsvars[j]) );
3806 
3807  goto cleanup;
3808  }
3809  lhsnvars++;
3810  }
3811  assert(lhsnvars == lhscount);
3812  assert(negeigpos >= 0);
3813 
3814  SCIP_CALL( SCIPcreateVarBasic(scip, &rhsvar, NULL,
3815  rhsvarlb, rhsvarub, 0.0, SCIP_VARTYPE_CONTINUOUS) );
3816  SCIP_CALL( SCIPaddVar(scip, rhsvar) );
3817  SCIP_CALL( SCIPmultiaggregateVar(scip, rhsvar, nquadvars, quadvars, &(a[negeigpos * nquadvars]),
3818  rhsoffset, &infeas, &success) );
3819 
3820  if( infeas || !success )
3821  {
3822  SCIPdebugMsg(scip, "Problem with aggregation while trying to upgrade <%s>.\n", SCIPconsGetName(cons) );
3823 
3824  /* release all created vars */
3825  SCIP_CALL( SCIPreleaseVar(scip, &rhsvar) );
3826  for( j = 0; j < lhsnvars; ++j )
3827  {
3828  SCIP_CALL( SCIPreleaseVar(scip, &lhsvars[j]) );
3829  }
3830 
3831  goto cleanup;
3832  }
3833 
3834  SCIP_CALL( SCIPcreateConsSOC(scip, &upgdconss[0], SCIPconsGetName(cons),
3835  lhscount, lhsvars, lhscoefs, NULL, MAX(lhsconstant, 0.0) * UPGSCALE * UPGSCALE,
3836  rhsvar, rhscoef * UPGSCALE, 0.0,
3840  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
3841 
3842  /* release created variables */
3843  SCIP_CALL( SCIPreleaseVar(scip, &rhsvar) );
3844  for( i = 0; i < lhsnvars; ++i )
3845  {
3846  SCIP_CALL( SCIPreleaseVar(scip, &lhsvars[i]) );
3847  }
3848 
3849  /* create constraint that is equal to cons except that rhs/lhs is now +/-infinity */
3850  if( rhsissoc && !SCIPisInfinity(scip, -SCIPgetLhsQuadratic(scip, cons)) )
3851  {
3852  SCIPdebugMsg(scip, "rhs is soc, keep quadratic\n");
3853  SCIP_CALL( SCIPcreateConsQuadratic2(scip, &upgdconss[1], SCIPconsGetName(cons),
3857  SCIPgetLhsQuadratic(scip, cons), SCIPinfinity(scip),
3861  }
3862  else if( lhsissoc && !SCIPisInfinity(scip, SCIPgetRhsQuadratic(scip,cons)) )
3863  {
3864  SCIPdebugMsg(scip, "lhs is soc, keep quadratic\n");
3865  SCIP_CALL( SCIPcreateConsQuadratic2(scip, &upgdconss[1], SCIPconsGetName(cons),
3869  -SCIPinfinity(scip), SCIPgetRhsQuadratic(scip, cons),
3873  }
3874  }
3875 #ifdef SCIP_DEBUG
3876  else
3877  {
3878  if( lhscount < 2 )
3879  {
3880  SCIPdebugMsg(scip, "Failed because there are not enough lhsvars (%d)\n", lhscount);
3881  }
3882  if( SCIPisNegative(scip, lhsconstant) )
3883  {
3884  SCIPdebugMsg(scip, "Failed because lhsconstant is negative (%g)\n", lhsconstant);
3885  }
3886  }
3887 #endif
3888 
3889  cleanup:
3890  SCIPfreeBufferArray(scip, &lhsoffsets);
3891  SCIPfreeBufferArray(scip, &lhscoefs);
3892  SCIPfreeBufferArray(scip, &lhsvars);
3893  SCIPfreeBufferArrayNull(scip, &a);
3894  SCIPfreeBufferArrayNull(scip, &bp);
3895  SCIPfreeBufferArrayNull(scip, &quadvars);
3896  SCIPfreeBufferArrayNull(scip, &eigvals);
3897 
3898  return SCIP_OKAY;
3899 } /*lint !e715*/
3900 #endif
3901 
3902 /*
3903  * Callback methods of constraint handler
3904  */
3905 
3906 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
3907 static
3908 SCIP_DECL_CONSHDLRCOPY(conshdlrCopySOC)
3909 { /*lint --e{715}*/
3910  assert(scip != NULL);
3911  assert(conshdlr != NULL);
3912  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3913 
3914  /* call inclusion method of constraint handler */
3916 
3917  *valid = TRUE;
3918 
3919  return SCIP_OKAY;
3920 }
3921 
3922 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
3923 static
3924 SCIP_DECL_CONSFREE(consFreeSOC)
3925 {
3926  SCIP_CONSHDLRDATA* conshdlrdata;
3927 
3928  assert( scip != NULL );
3929  assert( conshdlr != NULL );
3930  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
3931 
3932  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3933  assert(conshdlrdata != NULL);
3934 
3935  SCIPfreeBlockMemory(scip, &conshdlrdata);
3936 
3937  return SCIP_OKAY;
3938 }
3939 
3940 
3941 /** initialization method of constraint handler (called after problem was transformed) */
3942 static
3943 SCIP_DECL_CONSINIT(consInitSOC)
3944 { /*lint --e{715}*/
3945  SCIP_CONSHDLRDATA* conshdlrdata;
3946  int c;
3947 
3948  assert(scip != NULL);
3949  assert(conshdlr != NULL);
3950  assert(conss != NULL || nconss == 0);
3951 
3952  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3953  assert(conshdlrdata != NULL);
3954 
3955  conshdlrdata->subnlpheur = SCIPfindHeur(scip, "subnlp");
3956  conshdlrdata->trysolheur = SCIPfindHeur(scip, "trysol");
3957  conshdlrdata->haveexprint = (strcmp(SCIPexprintGetName(), "NONE") != 0);
3958 
3959  /* mark constraints for propagation */
3960  for( c = 0; c < nconss; ++c )
3961  {
3962  SCIP_CALL( SCIPmarkConsPropagate(scip, conss[c]) ); /*lint !e613*/
3963  }
3964 
3965  return SCIP_OKAY;
3966 }
3967 
3968 
3969 /** deinitialization method of constraint handler (called before transformed problem is freed) */
3970 static
3971 SCIP_DECL_CONSEXIT(consExitSOC)
3972 { /*lint --e{715}*/
3973  SCIP_CONSHDLRDATA* conshdlrdata;
3974 
3975  assert(scip != NULL);
3976  assert(conshdlr != NULL);
3977 
3978  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3979  assert(conshdlrdata != NULL);
3980 
3981  conshdlrdata->subnlpheur = NULL;
3982  conshdlrdata->trysolheur = NULL;
3983  conshdlrdata->haveexprint = FALSE;
3984 
3985  return SCIP_OKAY;
3986 }
3987 
3988 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
3989 static
3990 SCIP_DECL_CONSEXITPRE(consExitpreSOC)
3991 { /*lint --e{715}*/
3992  int c;
3993 
3994  assert(scip != NULL);
3995  assert(conshdlr != NULL);
3996  assert(conss != NULL || nconss == 0);
3997 
3998  /* tell SCIP that we have something nonlinear */
3999  for( c = 0; c < nconss; ++c )
4000  {
4001  if( SCIPconsIsAdded(conss[c]) ) /*lint !e613*/
4002  {
4003  SCIPenableNLP(scip);
4004  break;
4005  }
4006  }
4007 
4008  return SCIP_OKAY;
4009 }
4010 
4011 
4012 /** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
4013 static
4014 SCIP_DECL_CONSINITSOL(consInitsolSOC)
4015 {
4016  SCIP_CONSHDLRDATA* conshdlrdata;
4017  SCIP_CONSDATA* consdata;
4018  int c;
4019 
4020  assert(scip != NULL);
4021  assert(conshdlr != NULL);
4022 
4023  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4024  assert(conshdlrdata != NULL);
4025  assert(conshdlrdata->eventhdlr != NULL);
4026 
4027  /* add nlrow representation to NLP, if NLP has been enabled */
4028  if( SCIPisNLPConstructed(scip) )
4029  {
4030  for( c = 0; c < nconss; ++c )
4031  {
4032  if( SCIPconsIsEnabled(conss[c]) )
4033  {
4034  consdata = SCIPconsGetData(conss[c]);
4035  assert(consdata != NULL);
4036 
4037  if( consdata->nlrow == NULL )
4038  {
4039  SCIP_CALL( createNlRow(scip, conshdlr, conss[c]) );
4040  assert(consdata->nlrow != NULL);
4041  }
4042  SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
4043  }
4044  }
4045  }
4046 
4047  conshdlrdata->newsoleventfilterpos = -1;
4048  if( nconss != 0 )
4049  {
4050  SCIP_EVENTHDLR* eventhdlr;
4051 
4052  eventhdlr = SCIPfindEventhdlr(scip, CONSHDLR_NAME"_newsolution");
4053  assert(eventhdlr != NULL);
4054 
4055  SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_SOLFOUND, eventhdlr, (SCIP_EVENTDATA*)conshdlr, &conshdlrdata->newsoleventfilterpos) );
4056  }
4057 
4058  /* reset flags and counters */
4059  conshdlrdata->sepanlp = FALSE;
4060  conshdlrdata->lastenfonode = NULL;
4061  conshdlrdata->nenforounds = 0;
4062 
4063  return SCIP_OKAY;
4064 }
4065 
4066 
4067 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
4068 static
4069 SCIP_DECL_CONSEXITSOL(consExitsolSOC)
4071  SCIP_CONSHDLRDATA* conshdlrdata;
4072  SCIP_CONSDATA* consdata;
4073  int c;
4074 
4075  assert(scip != NULL);
4076  assert(conshdlr != NULL);
4077 
4078  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4079  assert(conshdlrdata != NULL);
4080  assert(conshdlrdata->eventhdlr != NULL);
4081 
4082  if( conshdlrdata->newsoleventfilterpos >= 0 )
4083  {
4084  SCIP_EVENTHDLR* eventhdlr;
4085 
4086  eventhdlr = SCIPfindEventhdlr(scip, CONSHDLR_NAME"_newsolution");
4087  assert(eventhdlr != NULL);
4088 
4089  SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_SOLFOUND, eventhdlr, (SCIP_EVENTDATA*)conshdlr, conshdlrdata->newsoleventfilterpos) );
4090  conshdlrdata->newsoleventfilterpos = -1;
4091  }
4092 
4093  for( c = 0; c < nconss; ++c )
4094  {
4095  consdata = SCIPconsGetData(conss[c]);
4096  assert(consdata != NULL);
4097 
4098  /* free nonlinear row representation */
4099  if( consdata->nlrow != NULL )
4100  {
4101  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
4102  }
4103  }
4104 
4105  return SCIP_OKAY;
4106 } /*lint !e715*/
4107 
4108 
4109 /** frees specific constraint data */
4110 static
4111 SCIP_DECL_CONSDELETE(consDeleteSOC)
4113  int i;
4114 
4115  assert(scip != NULL);
4116  assert(conshdlr != NULL);
4117  assert(cons != NULL);
4118  assert(consdata != NULL);
4119  assert(*consdata != NULL);
4120  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
4121 
4122  SCIPdebugMsg(scip, "Deleting SOC constraint <%s>.\n", SCIPconsGetName(cons) );
4123 
4124  if( SCIPconsIsTransformed(cons) )
4125  {
4126  SCIP_CONSHDLRDATA* conshdlrdata;
4127 
4128  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4129  assert(conshdlrdata != NULL);
4130 
4131  SCIP_CALL( dropVarEvents(scip, conshdlrdata->eventhdlr, cons) );
4132  }
4133 
4134  for( i = 0; i < (*consdata)->nvars; ++i )
4135  {
4136  SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->vars[i]) );
4137  }
4138 
4139  SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->nvars);
4140  SCIPfreeBlockMemoryArray(scip, &(*consdata)->coefs, (*consdata)->nvars);
4141  SCIPfreeBlockMemoryArray(scip, &(*consdata)->offsets, (*consdata)->nvars);
4142  assert((*consdata)->lhsbndchgeventdata == NULL);
4143 
4144  if( (*consdata)->rhsvar != NULL )
4145  {
4146  SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->rhsvar) );
4147  }
4148 
4149  /* free nonlinear row representation
4150  * normally released in exitsol, but constraint may be deleted early (e.g., if found redundant)
4151  */
4152  if( (*consdata)->nlrow != NULL )
4153  {
4154  SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
4155  }
4156 
4157  SCIPfreeBlockMemory(scip, consdata);
4158 
4159  return SCIP_OKAY;
4160 }
4161 
4162 
4163 /** transforms constraint data into data belonging to the transformed problem */
4164 static
4165 SCIP_DECL_CONSTRANS(consTransSOC)
4166 {
4167  SCIP_CONSDATA* consdata;
4168  SCIP_CONSHDLRDATA* conshdlrdata;
4169  SCIP_CONSDATA* sourcedata;
4170  char s[SCIP_MAXSTRLEN];
4171  int i;
4172 
4173  assert(scip != NULL);
4174  assert(conshdlr != NULL);
4175  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4176  assert(sourcecons != NULL);
4177  assert(targetcons != NULL);
4178 
4179  /* get constraint handler data */
4180  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4181  assert(conshdlrdata != NULL);
4182 
4183  SCIPdebugMsg(scip, "Transforming SOC constraint: <%s>.\n", SCIPconsGetName(sourcecons) );
4184 
4185  /* get data of original constraint */
4186  sourcedata = SCIPconsGetData(sourcecons);
4187  assert(sourcedata != NULL);
4188  assert(sourcedata->vars != NULL);
4189  assert(sourcedata->coefs != NULL);
4190  assert(sourcedata->offsets != NULL);
4191 
4192  /* create constraint data */
4193  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
4194 
4195  consdata->nvars = sourcedata->nvars;
4196  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, consdata->nvars) );
4197  SCIP_CALL( SCIPgetTransformedVars(scip, consdata->nvars, sourcedata->vars, consdata->vars) );
4198  for( i = 0; i < consdata->nvars; ++i )
4199  {
4200  SCIP_CALL( SCIPcaptureVar(scip, consdata->vars[i]) );
4201  }
4202 
4203  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->coefs, sourcedata->coefs, consdata->nvars) );
4204  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->offsets, sourcedata->offsets, consdata->nvars) );
4205  consdata->constant = sourcedata->constant;
4206 
4207  SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->rhsvar, &consdata->rhsvar) );
4208  consdata->rhsoffset = sourcedata->rhsoffset;
4209  consdata->rhscoeff = sourcedata->rhscoeff;
4210 
4211  SCIP_CALL( SCIPcaptureVar(scip, consdata->rhsvar) );
4212 
4213  consdata->nlrow = NULL;
4214  consdata->lhsbndchgeventdata = NULL;
4215  consdata->isapproxadded = FALSE;
4216 
4217  /* create transformed constraint with the same flags */
4218  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
4219  SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
4220  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
4221  SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
4222  SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
4223  SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
4224  SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
4225 
4226  SCIP_CALL( catchVarEvents(scip, conshdlrdata->eventhdlr, *targetcons) );
4227 
4228  return SCIP_OKAY;
4229 }
4230 
4231 /** separation method of constraint handler for LP solutions */
4232 static
4233 SCIP_DECL_CONSSEPALP(consSepalpSOC)
4234 {
4235  SCIP_CONSHDLRDATA* conshdlrdata;
4236  SCIP_CONS* maxviolcon;
4237  SCIP_Bool sepasuccess;
4238  SCIP_Bool cutoff;
4239 
4240  assert(scip != NULL);
4241  assert(conshdlr != NULL);
4242  assert(conss != NULL || nconss == 0);
4243  assert(result != NULL);
4244 
4245  *result = SCIP_DIDNOTFIND;
4246 
4247  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4248  assert(conshdlrdata != NULL);
4249 
4250  SCIP_CALL( computeViolations(scip, conshdlr, conss, nconss, NULL, &maxviolcon) );
4251  if( maxviolcon == NULL )
4252  return SCIP_OKAY;
4253 
4254  /* at root, check if we want to solve the NLP relaxation and use its solutions as reference point
4255  * if there is something convex, then linearizing in the solution of the NLP relaxation can be very useful
4256  */
4257  if( SCIPgetDepth(scip) == 0 && !conshdlrdata->sepanlp &&
4258  (SCIPgetNContVars(scip) >= conshdlrdata->sepanlpmincont * SCIPgetNVars(scip) || (SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_UNBOUNDEDRAY && conshdlrdata->sepanlpmincont <= 1.0)) &&
4259  SCIPisNLPConstructed(scip) && SCIPgetNNlpis(scip) > 0 )
4260  {
4261  SCIP_NLPSOLSTAT solstat;
4262  SCIP_Bool solvednlp;
4263 
4264  solstat = SCIPgetNLPSolstat(scip);
4265  solvednlp = FALSE;
4266  if( solstat == SCIP_NLPSOLSTAT_UNKNOWN )
4267  {
4268  /* NLP is not solved yet, so we do it now and update solstat */
4269 
4270  /* ensure linear conss are in NLP */
4271  if( conshdlrdata->subnlpheur != NULL )
4272  {
4273  SCIP_CALL( SCIPaddLinearConsToNlpHeurSubNlp(scip, conshdlrdata->subnlpheur, TRUE, TRUE) );
4274  }
4275 
4276  /* set LP solution as starting values, if available */
4278  {
4279  SCIP_CALL( SCIPsetNLPInitialGuessSol(scip, NULL) );
4280  }
4281 
4282  /* SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_VERBLEVEL, 1) ); */
4283  SCIP_CALL( SCIPsolveNLP(scip) );
4284 
4285  solstat = SCIPgetNLPSolstat(scip);
4286  SCIPdebugMsg(scip, "solved NLP relax, solution status: %d\n", solstat);
4287 
4288  solvednlp = TRUE;
4289  }
4290 
4291  conshdlrdata->sepanlp = TRUE;
4292 
4293  if( solstat == SCIP_NLPSOLSTAT_GLOBINFEASIBLE )
4294  {
4295  SCIPdebugMsg(scip, "NLP relaxation is globally infeasible, thus can cutoff node\n");
4296  *result = SCIP_CUTOFF;
4297  return SCIP_OKAY;
4298  }
4299 
4300  if( solstat <= SCIP_NLPSOLSTAT_FEASIBLE )
4301  {
4302  /* if we have feasible NLP solution, generate linearization cuts there */
4303  SCIP_Bool lpsolseparated;
4304  SCIP_SOL* nlpsol;
4305 
4306  SCIP_CALL( SCIPcreateNLPSol(scip, &nlpsol, NULL) );
4307  assert(nlpsol != NULL);
4308 
4309  /* if we solved the NLP and solution is integral, then pass it to trysol heuristic */
4310  if( solvednlp && conshdlrdata->trysolheur != NULL )
4311  {
4312  int nfracvars = 0;
4313 
4314  if( SCIPgetNBinVars(scip) > 0 || SCIPgetNIntVars(scip) > 0 )
4315  {
4316  SCIP_CALL( SCIPgetNLPFracVars(scip, NULL, NULL, NULL, &nfracvars, NULL) );
4317  }
4318 
4319  if( nfracvars == 0 )
4320  {
4321  SCIP_CALL( SCIPheurPassSolTrySol(scip, conshdlrdata->trysolheur, nlpsol) );
4322  }
4323  }
4324 
4325  SCIP_CALL( addLinearizationCuts(scip, conshdlr, conss, nconss, nlpsol, &lpsolseparated, SCIPgetSepaMinEfficacy(scip), &cutoff) );
4326 
4327  SCIP_CALL( SCIPfreeSol(scip, &nlpsol) );
4328 
4329  if( cutoff )
4330  {
4331  *result = SCIP_CUTOFF;
4332  return SCIP_OKAY;
4333  }
4334 
4335  /* if a cut that separated the LP solution was added, then return, otherwise continue with usual separation in LP solution */
4336  if( lpsolseparated )
4337  {
4338  SCIPdebugMsg(scip, "linearization cuts separate LP solution\n");
4339 
4340  *result = SCIP_SEPARATED;
4341 
4342  return SCIP_OKAY;
4343  }
4344  }
4345  }
4346  /* if we do not want to try solving the NLP, or have no NLP, or have no NLP solver, or solving the NLP failed,
4347  * or separating with NLP solution as reference point failed, then try (again) with LP solution as reference point
4348  */
4349 
4350  SCIP_CALL( separatePoint(scip, conshdlr, conss, nconss, nusefulconss, NULL, FALSE, &cutoff, &sepasuccess) );
4351  if( cutoff )
4352  *result = SCIP_CUTOFF;
4353  else if ( sepasuccess )
4354  *result = SCIP_SEPARATED;
4355 
4356  return SCIP_OKAY;
4357 }
4358 
4359 
4360 /** separation method of constraint handler for arbitrary primal solutions */
4361 static
4362 SCIP_DECL_CONSSEPASOL(consSepasolSOC)
4363 {
4364  SCIP_CONS* maxviolcon;
4365  SCIP_Bool sepasuccess;
4366  SCIP_Bool cutoff;
4367 
4368  assert(scip != NULL);
4369  assert(conss != NULL || nconss == 0);
4370  assert(result != NULL);
4371  assert(sol != NULL);
4372 
4373  *result = SCIP_DIDNOTFIND;
4374 
4375  SCIP_CALL( computeViolations(scip, conshdlr, conss, nconss, sol, &maxviolcon) );
4376  if( maxviolcon == NULL )
4377  return SCIP_OKAY;
4378 
4379  SCIP_CALL( separatePoint(scip, conshdlr, conss, nconss, nusefulconss, sol, FALSE, &cutoff, &sepasuccess) );
4380  if( cutoff )
4381  *result = SCIP_CUTOFF;
4382  else if ( sepasuccess )
4383  *result = SCIP_SEPARATED;
4384 
4385  return SCIP_OKAY;
4386 }
4387 
4388 
4389 /** constraint enforcing method of constraint handler for LP solutions */
4390 static
4391 SCIP_DECL_CONSENFOLP(consEnfolpSOC)
4392 { /*lint --e{715}*/
4393  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
4394 
4395  return SCIP_OKAY;
4396 }
4397 
4398 
4399 /** constraint enforcing method of constraint handler for relaxation solutions */
4400 static
4401 SCIP_DECL_CONSENFORELAX(consEnforelaxSOC)
4402 { /*lint --e{715}*/
4403  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
4404 
4405  return SCIP_OKAY;
4406 }
4407 
4408 
4409 /** constraint enforcing method of constraint handler for pseudo solutions */
4410 static
4411 SCIP_DECL_CONSENFOPS(consEnfopsSOC)
4413  SCIP_CONS* maxviolcons;
4414 
4415  assert(scip != NULL);
4416  assert(conss != NULL || nconss == 0);
4417  assert(result != NULL);
4418 
4419  SCIP_CALL( computeViolations(scip, conshdlr, conss, nconss, NULL, &maxviolcons) );
4420 
4421  if( maxviolcons == NULL )
4422  *result = SCIP_FEASIBLE;
4423 
4424  *result = SCIP_INFEASIBLE;
4425 
4426  return SCIP_OKAY;
4427 } /*lint !e715*/
4428 
4429 
4430 /** feasibility check method of constraint handler for integral solutions */
4431 static
4432 SCIP_DECL_CONSCHECK(consCheckSOC)
4434  SCIP_CONSHDLRDATA* conshdlrdata;
4435  SCIP_CONSDATA* consdata;
4436  SCIP_Real maxviol;
4437  SCIP_Bool dolinfeasshift;
4438  SCIP_SOL* polishedsol;
4439  int c;
4440 
4441  assert(scip != NULL);
4442  assert(conshdlr != NULL);
4443  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4444  assert(conss != NULL || nconss == 0);
4445  assert(result != NULL );
4446 
4447  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4448  assert(conshdlrdata != NULL);
4449 
4450  *result = SCIP_FEASIBLE;
4451  maxviol = 0.0;
4452 
4453  dolinfeasshift = conshdlrdata->linfeasshift && (conshdlrdata->trysolheur != NULL);
4454  polishedsol = NULL;
4455 
4456  for( c = 0; c < nconss; ++c )
4457  {
4458  SCIP_CALL( computeViolation(scip, conshdlr, conss[c], sol) ); /*lint !e613*/
4459 
4460  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
4461  assert(consdata != NULL);
4462 
4463  /* if feasible, just continue */
4464  if( !SCIPisGT(scip, consdata->violation, SCIPfeastol(scip)) )
4465  continue;
4466 
4467  *result = SCIP_INFEASIBLE;
4468 
4469  if( consdata->violation > maxviol )
4470  maxviol = consdata->violation;
4471 
4472  if( printreason )
4473  {
4474  SCIP_Real unscaledviol;
4475 
4476  unscaledviol = consdata->lhsval;
4477  if( !SCIPisInfinity(scip, unscaledviol) )
4478  unscaledviol -= consdata->rhscoeff * (SCIPgetSolVal(scip, sol, consdata->rhsvar) + consdata->rhsoffset);
4479 
4480  SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) ); /*lint !e613*/
4481  SCIPinfoMessage(scip, NULL, ";\n\tviolation: %g (scaled: %g)\n", unscaledviol, consdata->violation);
4482  }
4483 
4484  /* if we do linear feasibility shifting, then try to adjust solution */
4485  if( dolinfeasshift )
4486  {
4487  if( SCIPvarGetStatus(consdata->rhsvar) != SCIP_VARSTATUS_MULTAGGR &&
4488  !SCIPisInfinity(scip, REALABS(consdata->lhsval)) &&
4489  ( (consdata->rhscoeff > 0.0 && SCIPvarMayRoundUp (consdata->rhsvar)) ||
4490  (consdata->rhscoeff < 0.0 && SCIPvarMayRoundDown(consdata->rhsvar)) ) )
4491  {
4492  SCIP_Bool success;
4493 
4494  if( polishedsol == NULL )
4495  {
4496  if( sol != NULL )
4497  {
4498  SCIP_CALL( SCIPcreateSolCopy(scip, &polishedsol, sol) );
4499  }
4500  else
4501  {
4502  SCIP_CALL( SCIPcreateLPSol(scip, &polishedsol, NULL) );
4503  }
4504  SCIP_CALL( SCIPunlinkSol(scip, polishedsol) );
4505  }
4506  SCIP_CALL( polishSolution(scip, conss[c], polishedsol, &success) ); /*lint !e613*/
4507 
4508  /* disable solution polishing if we failed for this constraint */
4509  dolinfeasshift = success;
4510  }
4511  else /* if locks of the variable are bad or rhs is multi-aggregated, disable solution polishing */
4512  {
4513  dolinfeasshift = FALSE;
4514  }
4515  }
4516 
4517  /* if solution polishing is off and there is no NLP heuristic or we just check the LP solution,
4518  * then there is no need to check remaining constraints (NLP heuristic will pick up LP solution anyway) */
4519  if( !dolinfeasshift && (conshdlrdata->subnlpheur == NULL || sol == NULL) && !completely )
4520  break;
4521  }
4522 
4523  /* if we failed to polish solution, clear the solution */
4524  if( !dolinfeasshift && polishedsol != NULL )
4525  {
4526  SCIP_CALL( SCIPfreeSol(scip, &polishedsol) );
4527  }
4528 
4529  if( polishedsol != NULL )
4530  {
4531  assert(*result == SCIP_INFEASIBLE);
4532  SCIP_CALL( SCIPheurPassSolTrySol(scip, conshdlrdata->trysolheur, polishedsol) );
4533  SCIP_CALL( SCIPfreeSol(scip, &polishedsol) );
4534  }
4535  else if( conshdlrdata->subnlpheur != NULL && sol != NULL && *result == SCIP_INFEASIBLE && !SCIPisInfinity(scip, maxviol) )
4536  {
4537  SCIP_CALL( SCIPupdateStartpointHeurSubNlp(scip, conshdlrdata->subnlpheur, sol, maxviol) );
4538  }
4539 
4540  return SCIP_OKAY;
4541 } /*lint !e715*/
4542 
4543 
4544 /** domain propagation method of constraint handler */
4545 static
4546 SCIP_DECL_CONSPROP(consPropSOC)
4548  SCIP_RESULT propresult;
4549  int c;
4550  int nchgbds;
4551  SCIP_Bool redundant;
4552 
4553  assert(scip != NULL);
4554  assert(conss != NULL || ((nconss == 0) && (nmarkedconss == 0)));
4555  assert(result != NULL);
4556 
4557  *result = SCIP_DIDNOTFIND;
4558  nchgbds = 0;
4559 
4560  for( c = 0; c < nmarkedconss && *result != SCIP_CUTOFF; ++c )
4561  {
4562  SCIP_CALL( propagateBounds(scip, conss[c], &propresult, &nchgbds, &redundant) ); /*lint !e613*/
4563  if( propresult != SCIP_DIDNOTFIND && propresult != SCIP_DIDNOTRUN )
4564  *result = propresult;
4565  }
4566 
4567  return SCIP_OKAY;
4568 } /*lint !e715*/
4569 
4570 
4571 /** presolving method of constraint handler */
4572 static
4573 SCIP_DECL_CONSPRESOL(consPresolSOC)
4575  SCIP_CONSHDLRDATA* conshdlrdata;
4576  SCIP_CONSDATA* consdata;
4577  int c;
4578  SCIP_RESULT propresult;
4579  SCIP_Bool iscutoff;
4580  SCIP_Bool isdeleted;
4581 
4582  assert(scip != NULL);
4583  assert(conss != NULL || nconss == 0);
4584  assert(conshdlr != NULL);
4585  assert(result != NULL);
4586 
4587  *result = SCIP_DIDNOTFIND;
4588 
4589  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4590  assert(conshdlrdata != NULL);
4591 
4592  for( c = 0; c < nconss; ++c )
4593  {
4594  consdata = SCIPconsGetData(conss[c]); /*lint !e613*/
4595  assert(consdata != NULL);
4596 
4597  SCIP_CALL( presolveRemoveFixedVariables(scip, conshdlr, conss[c], ndelconss, nupgdconss, nchgbds, nfixedvars, &iscutoff, &isdeleted) ); /*lint !e613*/
4598  if( iscutoff )
4599  {
4600  *result = SCIP_CUTOFF;
4601  return SCIP_OKAY;
4602  }
4603  if( isdeleted )
4604  {
4605  /* conss[c] has been deleted */
4606  *result = SCIP_SUCCESS;
4607  continue;
4608  }
4609 
4610  if( conshdlrdata->nauxvars > 0 && !consdata->isapproxadded && consdata->nvars > 1 )
4611  {
4612  SCIP_CALL( presolveCreateOuterApprox(scip, consdata->nvars, consdata->vars, consdata->coefs, consdata->offsets,
4613  consdata->rhsvar, consdata->rhscoeff, consdata->rhscoeff, consdata->constant, SCIPconsGetName(conss[c]), conss[c],
4614  conshdlrdata->nauxvars, conshdlrdata->glineur, naddconss) ); /*lint !e613*/
4615  consdata->isapproxadded = TRUE;
4616  }
4617 
4618  if( (presoltiming & SCIP_PRESOLTIMING_FAST) != 0 )
4619  {
4620  SCIP_Bool redundant;
4621 
4622  SCIP_CALL( propagateBounds(scip, conss[c], &propresult, nchgbds, &redundant) ); /*lint !e613*/
4623  switch( propresult )
4624  {
4625  case SCIP_DIDNOTRUN:
4626  case SCIP_DIDNOTFIND:
4627  break;
4628  case SCIP_REDUCEDDOM:
4629  *result = SCIP_SUCCESS;
4630  break;
4631  case SCIP_CUTOFF:
4632  *result = SCIP_CUTOFF;
4633  SCIPdebugMsg(scip, "infeasible in presolve due to propagation for constraint %s\n", SCIPconsGetName(conss[c])); /*lint !e613*/
4634  return SCIP_OKAY;
4635  default:
4636  SCIPerrorMessage("unexpected result from propagation: %d\n", propresult);
4637  return SCIP_ERROR;
4638  } /*lint !e788*/
4639  if( redundant )
4640  ++*ndelconss;
4641  }
4642 
4643  /* disaggregate each lhs term to a quadratic constraint by using auxiliary variables */
4644  if( conshdlrdata->disaggregate && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4645  {
4646  SCIP_Bool success;
4647 
4648  SCIP_CALL( disaggregate(scip, conss[c], consdata, naddconss, ndelconss, &success) ); /*lint !e613*/
4649 
4650  if( success )
4651  {
4652  SCIPdebugMsg(scip, "disaggregated SOC constraint\n");
4653 
4654  /* conss[c] has been deleted */
4655  *result = SCIP_SUCCESS;
4656  continue;
4657  }
4658  }
4659  }
4660 
4661  return SCIP_OKAY;
4662 } /*lint !e715*/
4663 
4664 
4665 /** variable rounding lock method of constraint handler */
4666 static
4667 SCIP_DECL_CONSLOCK(consLockSOC)
4669  SCIP_CONSDATA* consdata;
4670  int i;
4671 
4672  assert(scip != NULL);
4673  assert(conshdlr != NULL);
4674  assert(cons != NULL);
4675  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4676  consdata = SCIPconsGetData(cons);
4677  assert(consdata != NULL);
4678 
4679  SCIPdebugMsg(scip, "Locking constraint <%s>.\n", SCIPconsGetName(cons));
4680 
4681  /* Changing variables x_i, i <= n, in both directions can lead to an infeasible solution. */
4682  for( i = 0; i < consdata->nvars; ++i )
4683  {
4684  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos + nlocksneg, nlockspos + nlocksneg) );
4685  }
4686 
4687  /* Rounding x_{n+1} up will not violate a solution. */
4688  if( consdata->rhsvar != NULL )
4689  {
4690  SCIP_CALL( SCIPaddVarLocks(scip, consdata->rhsvar, consdata->rhscoeff > 0.0 ? nlockspos : nlocksneg, consdata->rhscoeff > 0.0 ? nlocksneg : nlockspos) );
4691  }
4692 
4693  return SCIP_OKAY;
4694 }
4695 
4696 /** constraint display method of constraint handler */
4697 static
4698 SCIP_DECL_CONSPRINT(consPrintSOC)
4699 {
4700  SCIP_CONSDATA* consdata;
4701  int i;
4702 
4703  assert(scip != NULL);
4704  assert(conshdlr != NULL);
4705  assert(cons != NULL);
4706  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4707 
4708  consdata = SCIPconsGetData(cons);
4709  assert(consdata != NULL);
4710 
4711  SCIPinfoMessage(scip, file, "sqrt( ");
4712  if( consdata->constant != 0.0 )
4713  {
4714  SCIPinfoMessage(scip, file, "%.15g", consdata->constant);
4715  }
4716 
4717  for( i = 0; i < consdata->nvars; ++i )
4718  {
4719  SCIPinfoMessage(scip, file, "+ (%.15g*(", consdata->coefs[i]);
4720  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[i], TRUE) );
4721  SCIPinfoMessage(scip, file, "%+.15g))^2 ", consdata->offsets[i]);
4722  }
4723 
4724  SCIPinfoMessage(scip, file, ") <= ");
4725  if( consdata->rhsvar != NULL )
4726  {
4727  SCIPinfoMessage(scip, file, "%.15g*(", consdata->rhscoeff);
4728  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->rhsvar, TRUE) );
4729  SCIPinfoMessage(scip, file, "%+.15g)", consdata->rhsoffset);
4730  }
4731  else
4732  {
4733  SCIPinfoMessage(scip, file, "%.15g", consdata->rhscoeff*consdata->rhsoffset);
4734  }
4735 
4736  return SCIP_OKAY;
4737 }
4738 
4739 /** constraint copying method of constraint handler */
4740 static
4741 SCIP_DECL_CONSCOPY(consCopySOC)
4743  SCIP_CONSDATA* consdata;
4744  SCIP_VAR** vars;
4745  SCIP_VAR* rhsvar;
4746  int i;
4747 
4748  assert(scip != NULL);
4749  assert(cons != NULL);
4750  assert(sourcescip != NULL);
4751  assert(sourceconshdlr != NULL);
4752  assert(sourcecons != NULL);
4753  assert(varmap != NULL);
4754  assert(valid != NULL);
4755  assert(stickingatnode == FALSE);
4756 
4757  consdata = SCIPconsGetData(sourcecons);
4758  assert(consdata != NULL);
4759 
4760  *valid = TRUE;
4761 
4762  SCIP_CALL( SCIPallocBufferArray(sourcescip, &vars, consdata->nvars) );
4763 
4764  /* map variables to active variables of the target SCIP */
4765  for( i = 0; i < consdata->nvars && *valid; ++i )
4766  {
4767  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, consdata->vars[i], &vars[i], varmap, consmap, global, valid) );
4768  assert(!(*valid) || vars[i] != NULL);
4769  }
4770 
4771  /* map rhs variable to active variable of the target SCIP */
4772  if( *valid )
4773  {
4774  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, consdata->rhsvar, &rhsvar, varmap, consmap, global, valid) );
4775  assert(!(*valid) || rhsvar != NULL);
4776  }
4777 
4778  /* only create the target constraint, if all variables could be copied */
4779  if( *valid )
4780  {
4781  SCIP_CALL( SCIPcreateConsSOC(scip, cons, name ? name : SCIPconsGetName(sourcecons),
4782  consdata->nvars, vars, consdata->coefs, consdata->offsets, consdata->constant,
4783  rhsvar, consdata->rhscoeff, consdata->rhsoffset,
4784  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable) ); /*lint !e644 */
4785  }
4786 
4787  SCIPfreeBufferArray(sourcescip, &vars);
4788 
4789  return SCIP_OKAY;
4790 }
4791 
4792 
4793 /** constraint parsing method of constraint handler */
4794 static
4795 SCIP_DECL_CONSPARSE(consParseSOC)
4796 { /*lint --e{715}*/
4797  SCIP_VAR* var;
4798  SCIP_VAR** vars;
4799  SCIP_Real* coefs;
4800  SCIP_Real* offsets;
4801  int nvars;
4802  int varssize;
4803  SCIP_VAR* rhsvar;
4804  SCIP_Real rhscoef;
4805  SCIP_Real rhsoffset;
4806  SCIP_Real constant;
4807  SCIP_Real coef;
4808  SCIP_Real offset;
4809  char* endptr;
4810 
4811  assert(scip != NULL);
4812  assert(success != NULL);
4813  assert(str != NULL);
4814  assert(name != NULL);
4815  assert(cons != NULL);
4816 
4817  /* check that string starts with "sqrt( " */
4818  if( strncmp(str, "sqrt( ", 6) != 0 )
4819  {
4820  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected 'sqrt( ' at begin of soc constraint string '%s'\n", str);
4821  *success = FALSE;
4822  return SCIP_OKAY;
4823  }
4824  str += 6;
4825 
4826  *success = TRUE;
4827 
4828  /* check if we have a constant in the beginning */
4829  if( SCIPstrToRealValue(str, &constant, &endptr) )
4830  str = endptr;
4831  else
4832  constant = 0.0;
4833 
4834  nvars = 0;
4835  varssize = 5;
4836  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
4837  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, varssize) );
4838  SCIP_CALL( SCIPallocBufferArray(scip, &offsets, varssize) );
4839 
4840  /* read '+ (coef*(var+offset))^2' on lhs, as long as possible */
4841  while( *str != '\0' )
4842  {
4843  /* skip whitespace */
4844  while( isspace((int)*str) )
4845  ++str;
4846 
4847  /* stop if no more coefficients */
4848  if( strncmp(str, "+ (", 3) != 0 )
4849  break;
4850 
4851  str += 3;
4852 
4853  /* parse coef */
4854  if( !SCIPstrToRealValue(str, &coef, &endptr) )
4855  {
4856  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected coefficient at begin of '%s'\n", str);
4857  *success = FALSE;
4858  break;
4859  }
4860  str = endptr;
4861 
4862  if( strncmp(str, "*(", 2) != 0 )
4863  {
4864  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected '*(' at begin of '%s'\n", str);
4865  *success = FALSE;
4866  break;
4867  }
4868  str += 2;
4869 
4870  /* parse variable name */
4871  SCIP_CALL( SCIPparseVarName(scip, str, &var, &endptr) );
4872  if( var == NULL )
4873  {
4874  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable name at '%s'\n", str);
4875  *success = FALSE;
4876  break;
4877  }
4878  str = endptr;
4879 
4880  /* parse offset */
4881  if( !SCIPstrToRealValue(str, &offset, &endptr) )
4882  {
4883  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected offset at begin of '%s'\n", str);
4884  *success = FALSE;
4885  break;
4886  }
4887  str = endptr;
4888 
4889  if( strncmp(str, "))^2", 4) != 0 )
4890  {
4891  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected '))^2' at begin of '%s'\n", str);
4892  *success = FALSE;
4893  break;
4894  }
4895  str += 4;
4896 
4897  if( varssize <= nvars )
4898  {
4899  varssize = SCIPcalcMemGrowSize(scip, varssize+1);
4900  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
4901  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, varssize) );
4902  SCIP_CALL( SCIPreallocBufferArray(scip, &offsets, varssize) );
4903  }
4904  vars[nvars] = var;
4905  coefs[nvars] = coef;
4906  offsets[nvars] = offset;
4907  ++nvars;
4908  }
4909 
4910  if( strncmp(str, ") <=", 4) != 0 )
4911  {
4912  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected ') <=' at begin of '%s'\n", str);
4913  *success = FALSE;
4914  }
4915  str += 4;
4916 
4917  /* read rhs coef*(var+offset) or just a constant */
4918 
4919  /* parse coef */
4920  if( *success )
4921  {
4922  /* skip whitespace */
4923  while( isspace((int)*str) )
4924  ++str;
4925 
4926  if( !SCIPstrToRealValue(str, &rhscoef, &endptr) )
4927  {
4928  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected coefficient at begin of '%s'\n", str);
4929  *success = FALSE;
4930  }
4931  str = endptr;
4932 
4933  /* skip whitespace */
4934  while( isspace((int)*str) )
4935  ++str;
4936  }
4937 
4938  /* parse *(var+offset) */
4939  if( *str != '\0' )
4940  {
4941  if( *success )
4942  {
4943  if( strncmp(str, "*(", 2) != 0 )
4944  {
4945  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected '*(' at begin of '%s'\n", str);
4946  *success = FALSE;
4947  }
4948  else
4949  {
4950  str += 2;
4951  }
4952  }
4953 
4954  /* parse variable name */
4955  if( *success )
4956  {
4957  SCIP_CALL( SCIPparseVarName(scip, str, &rhsvar, &endptr) );
4958  if( rhsvar == NULL )
4959  {
4960  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable name at '%s'\n", str);
4961  *success = FALSE;
4962  }
4963  else
4964  {
4965  str = endptr;
4966  }
4967  }
4968 
4969  /* parse offset */
4970  if( *success )
4971  {
4972  if( !SCIPstrToRealValue(str, &rhsoffset, &endptr) )
4973  {
4974  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected offset at begin of '%s'\n", str);
4975  *success = FALSE;
4976  }
4977  else
4978  {
4979  str = endptr;
4980  }
4981  }
4982 
4983  if( *success )
4984  {
4985  if( *str != ')' )
4986  {
4987  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "expected ')' at begin of '%s'\n", str);
4988  *success = FALSE;
4989  }
4990  }
4991  }
4992  else if( *success )
4993  {
4994  /* only a constant at right hand side */
4995  rhsoffset = rhscoef; /*lint !e644*/
4996  rhscoef = 1.0;
4997  rhsvar = NULL;
4998  }
4999 
5000  if( *success )
5001  {
5002  assert(!stickingatnode);
5003  SCIP_CALL( SCIPcreateConsSOC(scip, cons, name, nvars, vars, coefs, offsets, constant, rhsvar, rhscoef, rhsoffset,
5004  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable) ); /*lint !e644 */
5005  }
5006 
5007  SCIPfreeBufferArray(scip, &vars);
5008  SCIPfreeBufferArray(scip, &coefs);
5009  SCIPfreeBufferArray(scip, &offsets);
5010 
5011  return SCIP_OKAY;
5012 }
5013 
5014 /** constraint method of constraint handler which returns the variables (if possible) */
5015 static
5016 SCIP_DECL_CONSGETVARS(consGetVarsSOC)
5017 { /*lint --e{715}*/
5018  SCIP_CONSDATA* consdata;
5019 
5020  consdata = SCIPconsGetData(cons);
5021  assert(consdata != NULL);
5022 
5023  if( varssize < consdata->nvars + 1 )
5024  (*success) = FALSE;
5025  else
5026  {
5027  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
5028  vars[consdata->nvars] = consdata->rhsvar;
5029  (*success) = TRUE;
5030  }
5031 
5032  return SCIP_OKAY;
5033 }
5034 
5035 /** constraint method of constraint handler which returns the number of variable (if possible) */
5036 static
5037 SCIP_DECL_CONSGETNVARS(consGetNVarsSOC)
5038 { /*lint --e{715}*/
5039  SCIP_CONSDATA* consdata;
5040 
5041  assert(cons != NULL);
5042 
5043  consdata = SCIPconsGetData(cons);
5044  assert(consdata != NULL);
5045 
5046  (*nvars) = consdata->nvars + 1;
5047  (*success) = TRUE;
5048 
5049  return SCIP_OKAY;
5050 }
5051 
5052 /*
5053  * constraint specific interface methods
5054  */
5055 
5056 /** creates the handler for second order cone constraints and includes it in SCIP */
5058  SCIP* scip /**< SCIP data structure */
5059  )
5060 {
5061  SCIP_CONSHDLRDATA* conshdlrdata;
5062  SCIP_CONSHDLR* conshdlr;
5063  SCIP_EVENTHDLR* eventhdlr;
5064 
5065  /* create constraint handler data */
5066  SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
5067  conshdlrdata->subnlpheur = NULL;
5068  conshdlrdata->trysolheur = NULL;
5069 
5070  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, CONSHDLR_NAME"_boundchange",
5071  "signals a bound change to a second order cone constraint",
5072  processVarEvent, NULL) );
5073  conshdlrdata->eventhdlr = eventhdlr;
5074 
5075  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, NULL, CONSHDLR_NAME"_newsolution",
5076  "handles the event that a new primal solution has been found",
5077  processNewSolutionEvent, NULL) );
5078 
5079  /* include constraint handler */
5082  consEnfolpSOC, consEnfopsSOC, consCheckSOC, consLockSOC,
5083  conshdlrdata) );
5084  assert(conshdlr != NULL);
5085 
5086  /* set non-fundamental callbacks via specific setter functions */
5087  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySOC, consCopySOC) );
5088  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSOC) );
5089  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitSOC) );
5090  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreSOC) );
5091  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolSOC) );
5092  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSOC) );
5093  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSOC) );
5094  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSOC) );
5095  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitSOC) );
5096  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolSOC) );
5097  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseSOC) );
5098  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolSOC, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
5099  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSOC) );
5101  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSOC, consSepasolSOC, CONSHDLR_SEPAFREQ,
5103  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSOC) );
5104  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxSOC) );
5105 
5106  if( SCIPfindConshdlr(scip,"quadratic") != NULL )
5107  {
5108  /* notify function that upgrades quadratic constraint to SOC's */
5110  }
5111 
5112  /* add soc constraint handler parameters */
5113  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/projectpoint",
5114  "whether the reference point of a cut should be projected onto the feasible set of the SOC constraint",
5115  &conshdlrdata->projectpoint, TRUE, FALSE, NULL, NULL) );
5116 
5117  SCIP_CALL( SCIPaddIntParam (scip, "constraints/" CONSHDLR_NAME "/nauxvars",
5118  "number of auxiliary variables to use when creating a linear outer approx. of a SOC3 constraint; 0 to turn off",
5119  &conshdlrdata->nauxvars, FALSE, 0, 0, INT_MAX, NULL, NULL) );
5120 
5121  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/glineur",
5122  "whether the Glineur Outer Approximation should be used instead of Ben-Tal Nemirovski",
5123  &conshdlrdata->glineur, FALSE, TRUE, NULL, NULL) );
5124 
5125  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/sparsify",
5126  "whether to sparsify cuts",
5127  &conshdlrdata->sparsify, TRUE, FALSE, NULL, NULL) );
5128 
5129  SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/sparsifymaxloss",
5130  "maximal loss in cut efficacy by sparsification",
5131  &conshdlrdata->sparsifymaxloss, TRUE, 0.2, 0.0, 1.0, NULL, NULL) );
5132 
5133  SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/sparsifynzgrowth",
5134  "growth rate of maximal allowed nonzeros in cuts in sparsification",
5135  &conshdlrdata->sparsifynzgrowth, TRUE, 1.3, 1.000001, SCIPinfinity(scip), NULL, NULL) );
5136 
5137  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/linfeasshift",
5138  "whether to try to make solutions feasible in check by shifting the variable on the right hand side",
5139  &conshdlrdata->linfeasshift, FALSE, TRUE, NULL, NULL) );
5140 
5141  SCIP_CALL( SCIPaddCharParam(scip, "constraints/" CONSHDLR_NAME "/nlpform",
5142  "which formulation to use when adding a SOC constraint to the NLP (a: automatic, q: nonconvex quadratic form, s: convex sqrt form, e: convex exponential-sqrt form, d: convex division form)",
5143  &conshdlrdata->nlpform, FALSE, 'a', "aqsed", NULL, NULL) );
5144 
5145  SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/sepanlpmincont",
5146  "minimal required fraction of continuous variables in problem to use solution of NLP relaxation in root for separation",
5147  &conshdlrdata->sepanlpmincont, FALSE, 1.0, 0.0, 2.0, NULL, NULL) );
5148 
5149  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/enfocutsremovable",
5150  "are cuts added during enforcement removable from the LP in the same node?",
5151  &conshdlrdata->enfocutsremovable, TRUE, FALSE, NULL, NULL) );
5152 
5153  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/generalsocupgrade",
5154  "try to upgrade more general quadratics to soc?",
5155  &conshdlrdata->generalsocupg, TRUE, TRUE, NULL, NULL) );
5156 
5157  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/disaggregate",
5158  "try to completely disaggregate soc?",
5159  &conshdlrdata->disaggregate, TRUE, TRUE, NULL, NULL) );
5160 
5161  return SCIP_OKAY;
5162 }
5163 
5164 /** creates and captures a second order cone constraint
5165  *
5166  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5167  */
5169  SCIP* scip, /**< SCIP data structure */
5170  SCIP_CONS** cons, /**< pointer to hold the created constraint */
5171  const char* name, /**< name of constraint */
5172  int nvars, /**< number of variables on left hand side of constraint (n) */
5173  SCIP_VAR** vars, /**< array with variables on left hand side (x_i) */
5174  SCIP_Real* coefs, /**< array with coefficients of left hand side variables (alpha_i), or NULL if all 1.0 */
5175  SCIP_Real* offsets, /**< array with offsets of variables (beta_i), or NULL if all 0.0 */
5176  SCIP_Real constant, /**< constant on left hand side (gamma) */
5177  SCIP_VAR* rhsvar, /**< variable on right hand side of constraint (x_{n+1}) */
5178  SCIP_Real rhscoeff, /**< coefficient of variable on right hand side (alpha_{n+1}) */
5179  SCIP_Real rhsoffset, /**< offset of variable on right hand side (beta_{n+1}) */
5180  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
5181  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
5182  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
5183  * Usually set to TRUE. */
5184  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
5185  * TRUE for model constraints, FALSE for additional, redundant constraints. */
5186  SCIP_Bool check, /**< should the constraint be checked for feasibility?
5187  * TRUE for model constraints, FALSE for additional, redundant constraints. */
5188  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
5189  * Usually set to TRUE. */
5190  SCIP_Bool local, /**< is constraint only valid locally?
5191  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
5192  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
5193  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
5194  * adds coefficients to this constraint. */
5195  SCIP_Bool dynamic, /**< is constraint subject to aging?
5196  * Usually set to FALSE. Set to TRUE for own cuts which
5197  * are separated as constraints. */
5198  SCIP_Bool removable /**< should the relaxation be removed from the LP due to aging or cleanup?
5199  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
5200  )
5201 {
5202  SCIP_CONSHDLR* conshdlr;
5203  SCIP_CONSDATA* consdata;
5204  int i;
5205 
5206  assert(scip != NULL);
5207  assert(cons != NULL);
5208  assert(modifiable == FALSE); /* we do not support column generation */
5209 
5210  /* find the soc constraint handler */
5211  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5212  if( conshdlr == NULL )
5213  {
5214  SCIPerrorMessage("SOC constraint handler not found\n");
5215  return SCIP_PLUGINNOTFOUND;
5216  }
5217 
5218  assert(vars != NULL);
5219  assert(nvars >= 1);
5220  assert(constant >= 0.0);
5221  assert(!SCIPisInfinity(scip, ABS(rhsoffset)));
5222  assert(!SCIPisInfinity(scip, constant));
5223  assert(rhsvar == NULL || rhscoeff <= 0.0 || SCIPisGE(scip, local ? SCIPcomputeVarLbLocal(scip, rhsvar) : SCIPcomputeVarLbGlobal(scip, rhsvar), -rhsoffset));
5224  assert(rhsvar == NULL || rhscoeff >= 0.0 || SCIPisLE(scip, local ? SCIPcomputeVarUbLocal(scip, rhsvar) : SCIPcomputeVarUbGlobal(scip, rhsvar), -rhsoffset));
5225 
5226  /* create constraint data */
5227  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
5228 
5229  consdata->nvars = nvars;
5230  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->vars, vars, nvars) );
5231  for( i = 0; i < nvars; ++i )
5232  {
5233  SCIP_CALL( SCIPcaptureVar(scip, vars[i]) );
5234  }
5235 
5236  if( coefs != NULL )
5237  {
5238  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->coefs, coefs, nvars) );
5239  for( i = 0; i < nvars; ++i )
5240  {
5241  if( consdata->coefs[i] < 0.0 )
5242  consdata->coefs[i] = -consdata->coefs[i];
5243  }
5244  }
5245  else
5246  {
5247  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->coefs, nvars) );
5248  for( i = 0; i < nvars; ++i )
5249  consdata->coefs[i] = 1.0;
5250  }
5251 
5252  if( offsets != NULL )
5253  {
5254  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->offsets, offsets, nvars) );
5255  }
5256  else
5257  {
5258  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->offsets, nvars) );
5259  BMSclearMemoryArray(consdata->offsets, nvars);
5260  }
5261 
5262  consdata->constant = constant;
5263  consdata->rhsvar = rhsvar;
5264  consdata->rhscoeff = rhscoeff;
5265  consdata->rhsoffset = rhsoffset;
5266 
5267  if( rhsvar != NULL )
5268  {
5269  SCIP_CALL( SCIPcaptureVar(scip, rhsvar) );
5270  }
5271 
5272  consdata->nlrow = NULL;
5273 
5274  consdata->lhsbndchgeventdata = NULL;
5275  consdata->isapproxadded = FALSE;
5276 
5277  /* create constraint */
5278  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5279  local, modifiable, dynamic, removable, FALSE) );
5280 
5281  if( SCIPisTransformed(scip) )
5282  {
5283  SCIP_CONSHDLRDATA* conshdlrdata = SCIPconshdlrGetData(conshdlr);
5284  assert(conshdlrdata != NULL);
5285 
5286  SCIP_CALL( catchVarEvents(scip, conshdlrdata->eventhdlr, *cons) );
5287  }
5288 
5289  return SCIP_OKAY;
5290 }
5291 
5292 /** creates and captures a second order cone constraint with all its constraint flags
5293  * set to their default values
5294  *
5295  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5296  */
5298  SCIP* scip, /**< SCIP data structure */
5299  SCIP_CONS** cons, /**< pointer to hold the created constraint */
5300  const char* name, /**< name of constraint */
5301  int nvars, /**< number of variables on left hand side of constraint (n) */
5302  SCIP_VAR** vars, /**< array with variables on left hand side (x_i) */
5303  SCIP_Real* coefs, /**< array with coefficients of left hand side variables (alpha_i), or NULL if all 1.0 */
5304  SCIP_Real* offsets, /**< array with offsets of variables (beta_i), or NULL if all 0.0 */
5305  SCIP_Real constant, /**< constant on left hand side (gamma) */
5306  SCIP_VAR* rhsvar, /**< variable on right hand side of constraint (x_{n+1}) */
5307  SCIP_Real rhscoeff, /**< coefficient of variable on right hand side (alpha_{n+1}) */
5308  SCIP_Real rhsoffset /**< offset of variable on right hand side (beta_{n+1}) */
5309  )
5310 {
5311  SCIP_CALL( SCIPcreateConsSOC(scip, cons, name, nvars, vars, coefs, offsets, constant,
5312  rhsvar, rhscoeff, rhsoffset,
5313  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
5314 
5315  return SCIP_OKAY;
5316 }
5317 
5318 /** Gets the SOC constraint as a nonlinear row representation. */
5320  SCIP* scip, /**< SCIP data structure */
5321  SCIP_CONS* cons, /**< constraint */
5322  SCIP_NLROW** nlrow /**< pointer to store nonlinear row */
5323  )
5324 {
5325  SCIP_CONSDATA* consdata;
5326 
5327  assert(cons != NULL);
5328  assert(nlrow != NULL);
5329 
5330  consdata = SCIPconsGetData(cons);
5331  assert(consdata != NULL);
5332 
5333  if( consdata->nlrow == NULL )
5334  {
5335  SCIP_CALL( createNlRow(scip, SCIPconsGetHdlr(cons), cons) );
5336  }
5337  assert(consdata->nlrow != NULL);
5338  *nlrow = consdata->nlrow;
5339 
5340  return SCIP_OKAY;
5341 }
5342 
5343 /** Gets the number of variables on the left hand side of a SOC constraint. */
5344 int SCIPgetNLhsVarsSOC(
5345  SCIP* scip, /**< SCIP data structure */
5346  SCIP_CONS* cons /**< constraint data */
5347  )
5348 {
5349  assert(cons != NULL);
5350  assert(SCIPconsGetData(cons) != NULL);
5351 
5352  return SCIPconsGetData(cons)->nvars;
5353 }
5354 
5355 /** Gets the variables on the left hand side of a SOC constraint. */
5357  SCIP* scip, /**< SCIP data structure */
5358  SCIP_CONS* cons /**< constraint data */
5359  )
5360 {
5361  assert(cons != NULL);
5362  assert(SCIPconsGetData(cons) != NULL);
5363 
5364  return SCIPconsGetData(cons)->vars;
5365 }
5366 
5367 /** Gets the coefficients of the variables on the left hand side of a SOC constraint, or NULL if all are equal to 1.0. */
5369  SCIP* scip, /**< SCIP data structure */
5370  SCIP_CONS* cons /**< constraint data */
5371  )
5372 {
5373  assert(cons != NULL);
5374  assert(SCIPconsGetData(cons) != NULL);
5375 
5376  return SCIPconsGetData(cons)->coefs;
5377 }
5378 
5379 /** Gets the offsets of the variables on the left hand side of a SOC constraint, or NULL if all are equal to 0.0. */
5381  SCIP* scip, /**< SCIP data structure */
5382  SCIP_CONS* cons /**< constraint data */
5383  )
5384 {
5385  assert(cons != NULL);
5386  assert(SCIPconsGetData(cons) != NULL);
5387 
5388  return SCIPconsGetData(cons)->offsets;
5389 }
5390 
5391 /** Gets the constant on the left hand side of a SOC constraint. */
5393  SCIP* scip, /**< SCIP data structure */
5394  SCIP_CONS* cons /**< constraint data */
5395  )
5396 {
5397  assert(cons != NULL);
5398  assert(SCIPconsGetData(cons) != NULL);
5399 
5400  return SCIPconsGetData(cons)->constant;
5401 }
5402 
5403 /** Gets the variable on the right hand side of a SOC constraint. */
5405  SCIP* scip, /**< SCIP data structure */
5406  SCIP_CONS* cons /**< constraint data */
5407  )
5408 {
5409  assert(cons != NULL);
5410  assert(SCIPconsGetData(cons) != NULL);
5411 
5412  return SCIPconsGetData(cons)->rhsvar;
5413 }
5414 
5415 /** Gets the coefficient of the variable on the right hand side of a SOC constraint. */
5417  SCIP* scip, /**< SCIP data structure */
5418  SCIP_CONS* cons /**< constraint data */
5419  )
5420 {
5421  assert(cons != NULL);
5422  assert(SCIPconsGetData(cons) != NULL);
5423 
5424  return SCIPconsGetData(cons)->rhscoeff;
5425 }
5426 
5427 /** Gets the offset of the variables on the right hand side of a SOC constraint. */
5429  SCIP* scip, /**< SCIP data structure */
5430  SCIP_CONS* cons /**< constraint data */
5431  )
5432 {
5433  assert(cons != NULL);
5434  assert(SCIPconsGetData(cons) != NULL);
5435 
5436  return SCIPconsGetData(cons)->rhsoffset;
5437 }
5438 
5439 /** Adds the constraint to an NLPI problem.
5440  * Uses nonconvex formulation as quadratic function.
5441  */
5443  SCIP* scip, /**< SCIP data structure */
5444  SCIP_CONS* cons, /**< SOC constraint */
5445  SCIP_NLPI* nlpi, /**< interface to NLP solver */
5446  SCIP_NLPIPROBLEM* nlpiprob, /**< NLPI problem where to add constraint */
5447  SCIP_HASHMAP* scipvar2nlpivar, /**< mapping from SCIP variables to variable indices in NLPI */
5448  SCIP_Bool names /**< whether to pass constraint names to NLPI */
5449  )
5450 {
5451  SCIP_CONSDATA* consdata;
5452  int nlininds;
5453  int* lininds;
5454  SCIP_Real* linvals;
5455  int nquadelems;
5456  SCIP_QUADELEM* quadelems;
5457  int j;
5458  int lincnt;
5459  SCIP_Real lhs;
5460  SCIP_Real rhs;
5461  const char* name;
5462 
5463  assert(scip != NULL);
5464  assert(cons != NULL);
5465  assert(nlpi != NULL);
5466  assert(nlpiprob != NULL);
5467  assert(scipvar2nlpivar != NULL);
5468 
5469  consdata = SCIPconsGetData(cons);
5470  assert(consdata != NULL);
5471 
5472  lhs = -SCIPinfinity(scip);
5473  rhs = -consdata->constant;
5474 
5475  /* count how length is the linear part, i.e., how many offsets we have */
5476  nlininds = consdata->rhsoffset != 0.0 ? 1 : 0;
5477  for( j = 0; j < consdata->nvars; ++j )
5478  if( consdata->offsets[j] != 0.0 )
5479  ++nlininds;
5480 
5481  lininds = NULL;
5482  linvals = NULL;
5483  if( nlininds )
5484  {
5485  SCIP_CALL( SCIPallocBufferArray(scip, &lininds, nlininds) );
5486  SCIP_CALL( SCIPallocBufferArray(scip, &linvals, nlininds) );
5487  }
5488  lincnt = 0;
5489 
5490  nquadelems = consdata->nvars + 1;
5491  SCIP_CALL( SCIPallocBufferArray(scip, &quadelems, nquadelems) );
5492 
5493  for( j = 0; j < consdata->nvars; ++j )
5494  {
5495  quadelems[j].idx1 = (int) (size_t) SCIPhashmapGetImage(scipvar2nlpivar, consdata->vars[j]);
5496  quadelems[j].idx2 = quadelems[j].idx1;
5497  quadelems[j].coef = consdata->coefs[j] * consdata->coefs[j];
5498 
5499  if( consdata->offsets[j] != 0.0 )
5500  {
5501  assert(lininds != NULL);
5502  assert(linvals != NULL);
5503  lininds[lincnt] = quadelems[j].idx1;
5504  linvals[lincnt] = 2 * quadelems[j].coef * consdata->offsets[j];
5505  ++lincnt;
5506 
5507  rhs -= quadelems[j].coef * consdata->offsets[j] * consdata->offsets[j];
5508  }
5509  }
5510  quadelems[consdata->nvars].idx1 = (int) (size_t) SCIPhashmapGetImage(scipvar2nlpivar, consdata->rhsvar);
5511  quadelems[consdata->nvars].idx2 = quadelems[consdata->nvars].idx1;
5512  quadelems[consdata->nvars].coef = - consdata->rhscoeff * consdata->rhscoeff;
5513 
5514  if( consdata->rhsoffset != 0.0 )
5515  {
5516  assert(lininds != NULL);
5517  assert(linvals != NULL);
5518  lininds[lincnt] = quadelems[consdata->nvars].idx1;
5519  linvals[lincnt] = -2.0 * consdata->rhscoeff * consdata->rhscoeff * consdata->rhsoffset;
5520  ++lincnt;
5521 
5522  rhs += consdata->rhscoeff * consdata->rhscoeff * consdata->rhsoffset * consdata->rhsoffset;
5523  }
5524 
5525  assert(lincnt == nlininds);
5526 
5527  name = names ? SCIPconsGetName(cons) : NULL;
5528 
5529  SCIP_CALL( SCIPnlpiAddConstraints(nlpi, nlpiprob, 1,
5530  &lhs, &rhs,
5531  &nlininds, &lininds, &linvals,
5532  &nquadelems, &quadelems,
5533  NULL, NULL, &name) );
5534 
5535  SCIPfreeBufferArrayNull(scip, &lininds);
5536  SCIPfreeBufferArrayNull(scip, &linvals);
5537  SCIPfreeBufferArray(scip, &quadelems);
5538 
5539  return SCIP_OKAY;
5540 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
static SCIP_DECL_EVENTEXEC(processVarEvent)
Definition: cons_soc.c:327
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_VAR ** SCIPgetLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22604
void SCIPintervalDivScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11902
static SCIP_RETCODE catchRhsVarEvents(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons)
Definition: cons_soc.c:174
SCIP_Bool SCIPisIpoptAvailableIpopt(void)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:22593
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6291
SCIP_VAR ** SCIPgetLhsVarsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5357
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22282
void SCIPintervalSubScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:46443
const char * SCIPexprintGetName(void)
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8083
static SCIP_RETCODE separatePoint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_Bool inenforcement, SCIP_Bool *cutoff, SCIP_Bool *success)
Definition: cons_soc.c:1143
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
primal heuristic that tries a given solution
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:31233
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22523
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
Definition: cons_soc.c:2970
SCIP_VAR * var2
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
static SCIP_RETCODE generateSparseCut(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_ROWPREP **rowprep, SCIP_Real minefficacy)
Definition: cons_soc.c:1033
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:41404
methods to interpret (evaluate) an expression tree "fast"
SCIP_RETCODE SCIPcreateConsBasicSOC(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *coefs, SCIP_Real *offsets, SCIP_Real constant, SCIP_VAR *rhsvar, SCIP_Real rhscoeff, SCIP_Real rhsoffset)
Definition: cons_soc.c:5298
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8245
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6314
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopySOC)
Definition: cons_soc.c:3909
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
int SCIPnlrowSearchQuadVar(SCIP_NLROW *nlrow, SCIP_VAR *var)
Definition: nlp.c:3295
SCIP_CONS * cons
Definition: cons_soc.c:79
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41226
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
#define SCIPallocClearBufferArray(scip, ptr, num)
Definition: scip.h:22622
SCIP_RETCODE SCIPincludeConshdlrSOC(SCIP *scip)
Definition: cons_soc.c:5058
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
SCIP_RETCODE SCIPincludeQuadconsUpgrade(SCIP *scip, SCIP_DECL_QUADCONSUPGD((*quadconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
static SCIP_DECL_CONSENFORELAX(consEnforelaxSOC)
Definition: cons_soc.c:4402
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6544
#define SCIP_MAXSTRLEN
Definition: def.h:259
static SCIP_RETCODE generateCutProjectedPoint(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_ROWPREP **rowprep)
Definition: cons_soc.c:964
SCIP_VAR * var1
SCIP_Real * SCIPgetLhsOffsetsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5381
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:6036
SCIPInterval pow(const SCIPInterval &x, const SCIPInterval &y)
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28400
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12663
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:46813
SCIP_RETCODE SCIPcleanupRowprep(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Real maxcoefrange, SCIP_Real minviol, SCIP_Real *coefrange, SCIP_Real *viol)
static SCIP_DECL_CONSPROP(consPropSOC)
Definition: cons_soc.c:4547
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47088
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
SCIP_RETCODE SCIPchgNlRowRhs(SCIP *scip, SCIP_NLROW *nlrow, SCIP_Real rhs)
Definition: scip.c:32344
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47015
internal methods for NLPI solver interfaces
SCIP_RETCODE SCIPaddRowprepTerm(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_VAR *var, SCIP_Real coef)
SCIP_RETCODE SCIPchgVarLbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22186
SCIP_Bool local
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:8355
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip.c:31616
SCIP_RETCODE SCIPexprCreateMonomial(BMS_BLKMEM *blkmem, SCIP_EXPRDATA_MONOMIAL **monomial, SCIP_Real coef, int nfactors, int *childidxs, SCIP_Real *exponents)
Definition: expr.c:7035
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18957
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip.c:18038
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
SCIPInterval cos(const SCIPInterval &x)
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4485
#define FALSE
Definition: def.h:64
#define M_PI
Definition: string.c:42
SCIP_RETCODE SCIPnlpiAddConstraints(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nconss, const SCIP_Real *lhss, const SCIP_Real *rhss, const int *nlininds, int *const *lininds, SCIP_Real *const *linvals, const int *nquadelems, SCIP_QUADELEM *const *quadelems, int *const *exprvaridxs, SCIP_EXPRTREE *const *exprtrees, const char **names)
Definition: nlpi.c:268
SCIP_RETCODE SCIPaddToNlpiProblemSOC(SCIP *scip, SCIP_CONS *cons, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *scipvar2nlpivar, SCIP_Bool names)
Definition: cons_soc.c:5443
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10289
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5894
SCIP_RETCODE SCIPaddQuadElementToNlRow(SCIP *scip, SCIP_NLROW *nlrow, SCIP_QUADELEM quadelem)
Definition: scip.c:32538
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47100
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28630
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPsolveNLP(SCIP *scip)
Definition: scip.c:31593
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21660
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8265
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:45
static SCIP_DECL_CONSDELETE(consDeleteSOC)
Definition: cons_soc.c:4112
static SCIP_DECL_CONSCHECK(consCheckSOC)
Definition: cons_soc.c:4433
SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
Definition: scip.c:17699
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8295
static SCIP_DECL_CONSEXITPRE(consExitpreSOC)
Definition: cons_soc.c:3991
void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
Definition: misc.c:9626
SCIP_RETCODE SCIPexprtreeSetVars(SCIP_EXPRTREE *tree, int nvars, SCIP_VAR **vars)
Definition: nlp.c:111
static SCIP_RETCODE dropLhsVarEvents(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons, int varidx)
Definition: cons_soc.c:239
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22639
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5948
SCIP_EVENTHDLR * SCIPfindEventhdlr(SCIP *scip, const char *name)
Definition: scip.c:8741
static SCIP_RETCODE dropVarEvents(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons)
Definition: cons_soc.c:291
#define CONSHDLR_SEPAPRIORITY
Definition: cons_soc.c:52
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
SCIP_RETCODE SCIPcreateLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37920
SCIP_RETCODE SCIPexprtreeCreate(BMS_BLKMEM *blkmem, SCIP_EXPRTREE **tree, SCIP_EXPR *root, int nvars, int nparams, SCIP_Real *params)
Definition: expr.c:8771
constraint handler for second order cone constraints
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
static SCIP_RETCODE catchLhsVarEvents(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons, int varidx)
Definition: cons_soc.c:142
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8255
#define CONSHDLR_PROP_TIMING
Definition: cons_soc.c:65
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1267
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4265
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18998
SCIP_RETCODE SCIPaddLinearCoefToNlRow(SCIP *scip, SCIP_NLROW *nlrow, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:32390
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6521
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define CONSHDLR_PROPFREQ
Definition: cons_soc.c:56
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:11992
static SCIP_DECL_CONSGETNVARS(consGetNVarsSOC)
Definition: cons_soc.c:5038
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:27584
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:46415
#define SCIP_PRESOLTIMING_FAST
Definition: type_timing.h:43
SCIP_Real SCIPcomputeVarUbGlobal(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:23798
SCIP_Real SCIPcomputeVarLbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:23819
int filterpos
Definition: cons_soc.c:81
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE polishSolution(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *success)
Definition: cons_soc.c:2680
static SCIP_DECL_CONSINITSOL(consInitsolSOC)
Definition: cons_soc.c:4015
int SCIPgetNBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPheurPassSolTrySol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol)
Definition: heur_trysol.c:236
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip.c:6157
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:22599
static SCIP_RETCODE presolveCreateGlineurApproxDim3(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *x1, SCIP_VAR *x2, SCIP_VAR *x3, SCIP_Real alpha1, SCIP_Real alpha2, SCIP_Real alpha3, SCIP_Real offset1, SCIP_Real offset2, SCIP_Real offset3, int N, const char *basename, int *naddconss)
Definition: cons_soc.c:1831
SCIP_RETCODE SCIPmultiaggregateVar(SCIP *scip, SCIP_VAR *var, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: scip.c:25818
SCIP_Real coef
Definition: type_expr.h:102
static SCIP_RETCODE dropRhsVarEvents(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons)
Definition: cons_soc.c:267
#define SCIP_EVENTTYPE_SOLFOUND
Definition: type_event.h:127
void SCIPfreeRowprep(SCIP *scip, SCIP_ROWPREP **rowprep)
SCIP_Real inf
Definition: intervalarith.h:39
static SCIP_RETCODE computeViolation(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_SOL *sol)
Definition: cons_soc.c:727
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:38168
static SCIP_RETCODE presolveCreateOuterApproxDim3(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *x1, SCIP_VAR *x2, SCIP_VAR *x3, SCIP_Real alpha1, SCIP_Real alpha2, SCIP_Real alpha3, SCIP_Real offset1, SCIP_Real offset2, SCIP_Real offset3, int N, SCIP_Bool glineur, const char *basename, int *naddconss)
Definition: cons_soc.c:2310
#define SCIP_PRESOLTIMING_MEDIUM
Definition: type_timing.h:44
void SCIPmarkRowNotRemovableLocal(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30835
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:6060
SCIP_RETCODE SCIPaddLinearConsToNlpHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:2391
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1198
SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition: scip.c:8225
static SCIP_DECL_CONSEXIT(consExitSOC)
Definition: cons_soc.c:3972
SCIP_RETCODE SCIPfindQuadVarTermQuadratic(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, int *pos)
SCIP_RETCODE SCIPensureRowprepSize(SCIP *scip, SCIP_ROWPREP *rowprep, int size)
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
SCIP_RETCODE SCIPgetNlRowSOC(SCIP *scip, SCIP_CONS *cons, SCIP_NLROW **nlrow)
Definition: cons_soc.c:5320
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12591
interval arithmetics for provable bounds
SCIP_Real SCIPgetRowprepViolation(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip.c:31484
SCIP_VAR ** vars
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition: type_nlpi.h:69
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13297
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38948
static SCIP_RETCODE propagateBounds(SCIP *scip, SCIP_CONS *cons, SCIP_RESULT *result, int *nchgbds, SCIP_Bool *redundant)
Definition: cons_soc.c:2482
int varidx
Definition: cons_soc.c:80
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip.c:32299
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip.c:19311
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIPInterval sqrt(const SCIPInterval &x)
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:22633
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21788
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:25932
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8205
void SCIPaddRowprepSide(SCIP_ROWPREP *rowprep, SCIP_Real side)
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
static SCIP_RETCODE computeViolations(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_CONS **maxviolcons)
Definition: cons_soc.c:793
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6085
static SCIP_RETCODE presolveCreateOuterApprox(SCIP *scip, int nlhsvars, SCIP_VAR **lhsvars, SCIP_Real *lhscoefs, SCIP_Real *lhsoffsets, SCIP_VAR *rhsvar, SCIP_Real rhscoeff, SCIP_Real rhsoffset, SCIP_Real constant, const char *basename, SCIP_CONS *origcons, int soc3_nr_auxvars, SCIP_Bool glineur, int *naddconss)
Definition: cons_soc.c:2346
constraint handler for quadratic constraints
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
#define CONSHDLR_NAME
Definition: cons_soc.c:50
SCIP_RETCODE SCIPcreateRowprep(SCIP *scip, SCIP_ROWPREP **rowprep, SCIP_SIDETYPE sidetype, SCIP_Bool local)
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28602
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2548
int SCIPgetNNlpis(SCIP *scip)
Definition: scip.c:9602
#define REALABS(x)
Definition: def.h:173
SCIP_RETCODE SCIPsetNLPInitialGuessSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31561
static SCIP_RETCODE presolveRemoveFixedVariables(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, int *ndelconss, int *nupgdconss, int *nchgbds, int *nfixedvars, SCIP_Bool *iscutoff, SCIP_Bool *isdeleted)
Definition: cons_soc.c:1394
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip.c:37577
SCIP_Real SCIPgetSepaMinEfficacy(SCIP *scip)
Definition: scip.c:7583
static SCIP_DECL_CONSGETVARS(consGetVarsSOC)
Definition: cons_soc.c:5017
static SCIP_RETCODE generateCutSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_ROWPREP **rowprep)
Definition: cons_soc.c:832
#define SCIP_CALL(x)
Definition: def.h:350
static SCIP_RETCODE disaggregate(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, int *naddconss, int *ndelconss, SCIP_Bool *success)
Definition: cons_soc.c:2771
SCIP_Real SCIPcomputeVarUbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:23840
SCIP_RETCODE SCIPexprCreatePolynomial(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, int nmonomials, SCIP_EXPRDATA_MONOMIAL **monomials, SCIP_Real constant, SCIP_Bool copymonomials)
Definition: expr.c:6632
SCIP_Real sup
Definition: intervalarith.h:40
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47324
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1360
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8225
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34661
#define CONSHDLR_MAXPREROUNDS
Definition: cons_soc.c:60
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
SCIP_BILINTERM * SCIPgetBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:106
SCIP_RETCODE LapackDsyev(SCIP_Bool computeeigenvectors, int N, SCIP_Real *a, SCIP_Real *w)
#define CONSHDLR_DELAYSEPA
Definition: cons_soc.c:61
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4515
SCIP_Real SCIPgetRhsOffsetSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5429
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
Ipopt NLP interface.
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:38771
#define CONSHDLR_CHECKPRIORITY
Definition: cons_soc.c:54
#define CONSHDLR_DELAYPROP
Definition: cons_soc.c:62
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41158
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:29293
int SCIPgetNLhsVarsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5345
#define CONSHDLR_NEEDSCONS
Definition: cons_soc.c:63
SCIPInterval sin(const SCIPInterval &x)
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
static SCIP_DECL_CONSEXITSOL(consExitsolSOC)
Definition: cons_soc.c:4070
SCIP_VAR * SCIPgetRhsVarSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5405
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:43045
SCIP_Real SCIPlpfeastol(SCIP *scip)
Definition: scip.c:46457
#define CONSHDLR_SEPAFREQ
Definition: cons_soc.c:55
static SCIP_DECL_CONSLOCK(consLockSOC)
Definition: cons_soc.c:4668
static SCIP_DECL_CONSSEPASOL(consSepasolSOC)
Definition: cons_soc.c:4363
static SCIP_DECL_CONSINIT(consInitSOC)
Definition: cons_soc.c:3944
static SCIP_RETCODE generateCutPoint(SCIP *scip, SCIP_CONS *cons, SCIP_Real *x, SCIP_ROWPREP **rowprep)
Definition: cons_soc.c:877
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:29091
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10082
void SCIPintervalSquareRoot(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:34772
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8006
#define CONSHDLR_PRESOLTIMING
Definition: cons_soc.c:66
void SCIPintervalSquare(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:34505
static SCIP_RETCODE createNlRow(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons)
Definition: cons_soc.c:347
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41192
SCIP_RETCODE SCIPexprCreate(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, SCIP_EXPROP op,...)
Definition: expr.c:5973
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:38535
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8185
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8155
SCIP_Real SCIPcomputeVarLbGlobal(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:23777
SCIP_RETCODE SCIPexprtreeFree(SCIP_EXPRTREE **tree)
Definition: expr.c:8852
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41272
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:17619
void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
static SCIP_RETCODE presolveCreateBenTalNemirovskiApproxDim3(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *x1, SCIP_VAR *x2, SCIP_VAR *x3, SCIP_Real alpha1, SCIP_Real alpha2, SCIP_Real alpha3, SCIP_Real offset1, SCIP_Real offset2, SCIP_Real offset3, int N, const char *basename, int *naddconss)
Definition: cons_soc.c:2064
SCIP_RETCODE SCIPexprtreeAddVars(SCIP_EXPRTREE *tree, int nvars, SCIP_VAR **vars)
Definition: nlp.c:143
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:25575
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21714
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6498
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisCutApplicable(SCIP *scip, SCIP_ROW *cut)
Definition: scip.c:34618
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
SCIP_RETCODE SCIPgetRowprepRowCons(SCIP *scip, SCIP_ROW **row, SCIP_ROWPREP *rowprep, SCIP_CONSHDLR *conshdlr)
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
static SCIP_DECL_CONSPRESOL(consPresolSOC)
Definition: cons_soc.c:4574
SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
Definition: tree.c:7372
void SCIPenableNLP(SCIP *scip)
Definition: scip.c:31218
static SCIP_DECL_CONSENFOPS(consEnfopsSOC)
Definition: cons_soc.c:4412
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip.c:6229
enum SCIP_ExprCurv SCIP_EXPRCURV
Definition: type_expr.h:93
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30540
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSENFOLP(consEnfolpSOC)
Definition: cons_soc.c:4392
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37948
static SCIP_DECL_CONSTRANS(consTransSOC)
Definition: cons_soc.c:4166
SCIP_RETCODE SCIPaddQuadVarToNlRow(SCIP *scip, SCIP_NLROW *nlrow, SCIP_VAR *var)
Definition: scip.c:32479
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4349
static const SCIP_Real scalars[]
Definition: lp.c:5618
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1920
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11492
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8016
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip.c:6109
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip.c:6133
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:135
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
SCIP_Real SCIPgetLhsConstantSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5393
void SCIPintervalSetRoundingModeUpwards(void)
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6253
NLP local search primal heuristic using sub-SCIPs.
void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip.c:13790
SCIP_RETCODE SCIPsortQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsCoefSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5417
SCIP_RETCODE SCIPgetNLPFracVars(SCIP *scip, SCIP_VAR ***fracvars, SCIP_Real **fracvarssol, SCIP_Real **fracvarsfrac, int *nfracvars, int *npriofracvars)
Definition: scip.c:31736
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16781
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18732
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8235
static SCIP_DECL_CONSPRINT(consPrintSOC)
Definition: cons_soc.c:4699
#define CONSHDLR_EAGERFREQ
Definition: cons_soc.c:57
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6567
void SCIPintervalMulScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
static SCIP_RETCODE evalLhs(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
Definition: cons_soc.c:687
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8175
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8165
SCIP_RETCODE SCIPprintNlRow(SCIP *scip, SCIP_NLROW *nlrow, FILE *file)
Definition: scip.c:33028
static SCIP_RETCODE addLinearizationCuts(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *ref, SCIP_Bool *separatedlpsol, SCIP_Real minefficacy, SCIP_Bool *cutoff)
Definition: cons_soc.c:1258
SCIP_RETCODE SCIPcreateConsQuadratic2(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadvarterms, SCIP_QUADVARTERM *quadvarterms, int nbilinterms, SCIP_BILINTERM *bilinterms, 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)
#define CONSHDLR_ENFOPRIORITY
Definition: cons_soc.c:53
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38740
int SCIP_ROUNDMODE
Definition: intervalarith.h:46
void SCIPintervalSub(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47076
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46989
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
static SCIP_DECL_CONSFREE(consFreeSOC)
Definition: cons_soc.c:3925
static SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
Definition: cons_soc.c:3092
SCIP_RETCODE SCIPupdateStartpointHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *solcand, SCIP_Real violation)
Definition: heur_subnlp.c:2425
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8195
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
SCIP_QUADVARTERM * SCIPgetQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadvars, SCIP_VAR **quadvars, int nquadelems, SCIP_QUADELEM *quadelems, SCIP_EXPRTREE *expression, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: scip.c:32191
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:47161
SCIP_RETCODE SCIPexprCreateLinear(BMS_BLKMEM *blkmem, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefs, SCIP_Real constant)
Definition: expr.c:6502
#define UPGSCALE
Definition: cons_soc.c:70
void SCIPintervalAddScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
SCIP_RETCODE SCIPcreateConsSOC(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *coefs, SCIP_Real *offsets, SCIP_Real constant, SCIP_VAR *rhsvar, SCIP_Real rhscoeff, SCIP_Real rhsoffset, 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)
Definition: cons_soc.c:5169
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:6181
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:42314
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:17735
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16853
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
static SCIP_DECL_CONSPARSE(consParseSOC)
Definition: cons_soc.c:4796
SCIP_SOL * SCIPeventGetSol(SCIP_EVENT *event)
Definition: event.c:1223
SCIP_Real * SCIPgetLhsCoefsSOC(SCIP *scip, SCIP_CONS *cons)
Definition: cons_soc.c:5369
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4321
void SCIPintervalSetRoundingModeDownwards(void)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47149
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3280
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3272
#define CONSHDLR_DESC
Definition: cons_soc.c:51
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239
#define QUADCONSUPGD_PRIORITY
Definition: cons_soc.c:68
static SCIP_RETCODE catchVarEvents(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons)
Definition: cons_soc.c:202
static SCIP_DECL_CONSCOPY(consCopySOC)
Definition: cons_soc.c:4742
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16949
static SCIP_DECL_CONSSEPALP(consSepalpSOC)
Definition: cons_soc.c:4234
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:22624
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5994