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