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