Scippy

SCIP

Solving Constraint Integer Programs

scip_nonlinear.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2019 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file scip_nonlinear.c
17  * @brief public methods for nonlinear functions
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  * @author Robert Lion Gottwald
22  * @author Stefan Heinz
23  * @author Gregor Hendel
24  * @author Thorsten Koch
25  * @author Alexander Martin
26  * @author Marc Pfetsch
27  * @author Michael Winkler
28  * @author Kati Wolter
29  *
30  * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
31  */
32 
33 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34 
35 #include "blockmemshell/memory.h"
36 #include "nlpi/nlpi.h"
37 #include "nlpi/pub_expr.h"
38 #include "nlpi/type_expr.h"
39 #include "scip/dbldblarith.h"
40 #include "scip/pub_lp.h"
41 #include "scip/pub_message.h"
42 #include "scip/pub_misc.h"
43 #include "scip/pub_nlp.h"
44 #include "scip/pub_var.h"
45 #include "scip/scip_mem.h"
46 #include "scip/scip_message.h"
47 #include "scip/scip_nonlinear.h"
48 #include "scip/scip_numerics.h"
49 #include "scip/scip_prob.h"
50 
51 /** computes coefficients of linearization of a square term in a reference point */
53  SCIP* scip, /**< SCIP data structure */
54  SCIP_Real sqrcoef, /**< coefficient of square term */
55  SCIP_Real refpoint, /**< point where to linearize */
56  SCIP_Bool isint, /**< whether corresponding variable is a discrete variable, and thus linearization could be moved */
57  SCIP_Real* lincoef, /**< buffer to add coefficient of linearization */
58  SCIP_Real* linconstant, /**< buffer to add constant of linearization */
59  SCIP_Bool* success /**< buffer to set to FALSE if linearization has failed due to large numbers */
60  )
61 {
62  assert(scip != NULL);
63  assert(lincoef != NULL);
64  assert(linconstant != NULL);
65  assert(success != NULL);
66 
67  if( sqrcoef == 0.0 )
68  return;
69 
70  if( SCIPisInfinity(scip, REALABS(refpoint)) )
71  {
72  *success = FALSE;
73  return;
74  }
75 
76  if( !isint || SCIPisIntegral(scip, refpoint) )
77  {
78  SCIP_Real tmp;
79 
80  /* sqrcoef * x^2 -> tangent in refpoint = sqrcoef * 2 * refpoint * (x - refpoint) */
81 
82  tmp = sqrcoef * refpoint;
83 
84  if( SCIPisInfinity(scip, 2.0 * REALABS(tmp)) )
85  {
86  *success = FALSE;
87  return;
88  }
89 
90  *lincoef += 2.0 * tmp;
91  tmp *= refpoint;
92  *linconstant -= tmp;
93  }
94  else
95  {
96  /* sqrcoef * x^2 -> secant between f=floor(refpoint) and f+1 = sqrcoef * (f^2 + ((f+1)^2 - f^2) * (x-f))
97  * = sqrcoef * (-f*(f+1) + (2*f+1)*x)
98  */
99  SCIP_Real f;
100  SCIP_Real coef;
101  SCIP_Real constant;
102 
103  f = SCIPfloor(scip, refpoint);
104 
105  coef = sqrcoef * (2.0 * f + 1.0);
106  constant = -sqrcoef * f * (f + 1.0);
107 
108  if( SCIPisInfinity(scip, REALABS(coef)) || SCIPisInfinity(scip, REALABS(constant)) )
109  {
110  *success = FALSE;
111  return;
112  }
113 
114  *lincoef += coef;
115  *linconstant += constant;
116  }
117 }
118 
119 /** computes coefficients of secant of a square term */
121  SCIP* scip, /**< SCIP data structure */
122  SCIP_Real sqrcoef, /**< coefficient of square term */
123  SCIP_Real lb, /**< lower bound on variable */
124  SCIP_Real ub, /**< upper bound on variable */
125  SCIP_Real refpoint, /**< point for which to compute value of linearization */
126  SCIP_Real* lincoef, /**< buffer to add coefficient of secant */
127  SCIP_Real* linconstant, /**< buffer to add constant of secant */
128  SCIP_Bool* success /**< buffer to set to FALSE if secant has failed due to large numbers or unboundedness */
129  )
130 {
131  SCIP_Real coef;
132  SCIP_Real constant;
133 
134  assert(scip != NULL);
135  assert(!SCIPisInfinity(scip, lb));
136  assert(!SCIPisInfinity(scip, -ub));
137  assert(SCIPisLE(scip, lb, ub));
138  assert(SCIPisLE(scip, lb, refpoint));
139  assert(SCIPisGE(scip, ub, refpoint));
140  assert(lincoef != NULL);
141  assert(linconstant != NULL);
142  assert(success != NULL);
143 
144  if( sqrcoef == 0.0 )
145  return;
146 
147  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
148  {
149  /* unboundedness */
150  *success = FALSE;
151  return;
152  }
153 
154  /* sqrcoef * x^2 -> sqrcoef * (lb * lb + (ub*ub - lb*lb)/(ub-lb) * (x-lb)) = sqrcoef * (lb*lb + (ub+lb)*(x-lb))
155  * = sqrcoef * ((lb+ub)*x - lb*ub)
156  */
157  coef = sqrcoef * (lb + ub);
158  constant = -sqrcoef * lb * ub;
159  if( SCIPisInfinity(scip, REALABS(coef)) || SCIPisInfinity(scip, REALABS(constant)) )
160  {
161  *success = FALSE;
162  return;
163  }
164 
165  *lincoef += coef;
166  *linconstant += constant;
167 }
168 
169 /** computes coefficients of linearization of a bilinear term in a reference point */
171  SCIP* scip, /**< SCIP data structure */
172  SCIP_Real bilincoef, /**< coefficient of bilinear term */
173  SCIP_Real refpointx, /**< point where to linearize first variable */
174  SCIP_Real refpointy, /**< point where to linearize second variable */
175  SCIP_Real* lincoefx, /**< buffer to add coefficient of first variable in linearization */
176  SCIP_Real* lincoefy, /**< buffer to add coefficient of second variable in linearization */
177  SCIP_Real* linconstant, /**< buffer to add constant of linearization */
178  SCIP_Bool* success /**< buffer to set to FALSE if linearization has failed due to large numbers */
179  )
180 {
181  SCIP_Real constant;
182 
183  assert(scip != NULL);
184  assert(lincoefx != NULL);
185  assert(lincoefy != NULL);
186  assert(linconstant != NULL);
187  assert(success != NULL);
188 
189  if( bilincoef == 0.0 )
190  return;
191 
192  if( SCIPisInfinity(scip, REALABS(refpointx)) || SCIPisInfinity(scip, REALABS(refpointy)) )
193  {
194  *success = FALSE;
195  return;
196  }
197 
198  /* bilincoef * x * y -> bilincoef * (refpointx * refpointy + refpointy * (x - refpointx) + refpointx * (y - refpointy))
199  * = -bilincoef * refpointx * refpointy + bilincoef * refpointy * x + bilincoef * refpointx * y
200  */
201 
202  constant = -bilincoef * refpointx * refpointy;
203 
204  if( SCIPisInfinity(scip, REALABS(bilincoef * refpointx)) || SCIPisInfinity(scip, REALABS(bilincoef * refpointy))
205  || SCIPisInfinity(scip, REALABS(constant)) )
206  {
207  *success = FALSE;
208  return;
209  }
210 
211  *lincoefx += bilincoef * refpointy;
212  *lincoefy += bilincoef * refpointx;
213  *linconstant += constant;
214 }
215 
216 /** computes coefficients of McCormick under- or overestimation of a bilinear term */
218  SCIP* scip, /**< SCIP data structure */
219  SCIP_Real bilincoef, /**< coefficient of bilinear term */
220  SCIP_Real lbx, /**< lower bound on first variable */
221  SCIP_Real ubx, /**< upper bound on first variable */
222  SCIP_Real refpointx, /**< reference point for first variable */
223  SCIP_Real lby, /**< lower bound on second variable */
224  SCIP_Real uby, /**< upper bound on second variable */
225  SCIP_Real refpointy, /**< reference point for second variable */
226  SCIP_Bool overestimate, /**< whether to compute an overestimator instead of an underestimator */
227  SCIP_Real* lincoefx, /**< buffer to add coefficient of first variable in linearization */
228  SCIP_Real* lincoefy, /**< buffer to add coefficient of second variable in linearization */
229  SCIP_Real* linconstant, /**< buffer to add constant of linearization */
230  SCIP_Bool* success /**< buffer to set to FALSE if linearization has failed due to large numbers */
231  )
232 {
233  SCIP_Real constant;
234  SCIP_Real coefx;
235  SCIP_Real coefy;
236 
237  assert(scip != NULL);
238  assert(!SCIPisInfinity(scip, lbx));
239  assert(!SCIPisInfinity(scip, -ubx));
240  assert(!SCIPisInfinity(scip, lby));
241  assert(!SCIPisInfinity(scip, -uby));
242  assert(SCIPisLE(scip, lbx, ubx));
243  assert(SCIPisLE(scip, lby, uby));
244  assert(SCIPisLE(scip, lbx, refpointx));
245  assert(SCIPisGE(scip, ubx, refpointx));
246  assert(SCIPisLE(scip, lby, refpointy));
247  assert(SCIPisGE(scip, uby, refpointy));
248  assert(lincoefx != NULL);
249  assert(lincoefy != NULL);
250  assert(linconstant != NULL);
251  assert(success != NULL);
252 
253  if( bilincoef == 0.0 )
254  return;
255 
256  if( overestimate )
257  bilincoef = -bilincoef;
258 
259  if( SCIPisRelEQ(scip, lbx, ubx) && SCIPisRelEQ(scip, lby, uby) )
260  {
261  /* both x and y are mostly fixed */
262  SCIP_Real cand1;
263  SCIP_Real cand2;
264  SCIP_Real cand3;
265  SCIP_Real cand4;
266 
267  coefx = 0.0;
268  coefy = 0.0;
269 
270  /* estimate x * y by constant */
271  cand1 = lbx * lby;
272  cand2 = lbx * uby;
273  cand3 = ubx * lby;
274  cand4 = ubx * uby;
275 
276  /* take most conservative value for underestimator */
277  if( bilincoef < 0.0 )
278  constant = bilincoef * MAX( MAX(cand1, cand2), MAX(cand3, cand4) );
279  else
280  constant = bilincoef * MIN( MIN(cand1, cand2), MIN(cand3, cand4) );
281  }
282  else if( bilincoef > 0.0 )
283  {
284  /* either x or y is not fixed and coef > 0.0 */
285  if( !SCIPisInfinity(scip, -lbx) && !SCIPisInfinity(scip, -lby) &&
286  (SCIPisInfinity(scip, ubx) || SCIPisInfinity(scip, uby)
287  || (uby - refpointy) * (ubx - refpointx) >= (refpointy - lby) * (refpointx - lbx)) )
288  {
289  if( SCIPisRelEQ(scip, lbx, ubx) )
290  {
291  /* x*y = lbx * y + (x-lbx) * y >= lbx * y + (x-lbx) * lby >= lbx * y + min{(ubx-lbx) * lby, 0 * lby} */
292  coefx = 0.0;
293  coefy = bilincoef * lbx;
294  constant = bilincoef * (lby < 0.0 ? (ubx-lbx) * lby : 0.0);
295  }
296  else if( SCIPisRelEQ(scip, lby, uby) )
297  {
298  /* x*y = lby * x + (y-lby) * x >= lby * x + (y-lby) * lbx >= lby * x + min{(uby-lby) * lbx, 0 * lbx} */
299  coefx = bilincoef * lby;
300  coefy = 0.0;
301  constant = bilincoef * (lbx < 0.0 ? (uby-lby) * lbx : 0.0);
302  }
303  else
304  {
305  coefx = bilincoef * lby;
306  coefy = bilincoef * lbx;
307  constant = -bilincoef * lbx * lby;
308  }
309  }
310  else if( !SCIPisInfinity(scip, ubx) && !SCIPisInfinity(scip, uby) )
311  {
312  if( SCIPisRelEQ(scip, lbx, ubx) )
313  {
314  /* x*y = ubx * y + (x-ubx) * y >= ubx * y + (x-ubx) * uby >= ubx * y + min{(lbx-ubx) * uby, 0 * uby} */
315  coefx = 0.0;
316  coefy = bilincoef * ubx;
317  constant = bilincoef * (uby > 0.0 ? (lbx - ubx) * uby : 0.0);
318  }
319  else if( SCIPisRelEQ(scip, lby, uby) )
320  {
321  /* x*y = uby * x + (y-uby) * x >= uby * x + (y-uby) * ubx >= uby * x + min{(lby-uby) * ubx, 0 * ubx} */
322  coefx = bilincoef * uby;
323  coefy = 0.0;
324  constant = bilincoef * (ubx > 0.0 ? (lby - uby) * ubx : 0.0);
325  }
326  else
327  {
328  coefx = bilincoef * uby;
329  coefy = bilincoef * ubx;
330  constant = -bilincoef * ubx * uby;
331  }
332  }
333  else
334  {
335  *success = FALSE;
336  return;
337  }
338  }
339  else
340  {
341  /* either x or y is not fixed and coef < 0.0 */
342  if( !SCIPisInfinity(scip, ubx) && !SCIPisInfinity(scip, -lby) &&
343  (SCIPisInfinity(scip, -lbx) || SCIPisInfinity(scip, uby)
344  || (ubx - lbx) * (refpointy - lby) <= (uby - lby) * (refpointx - lbx)) )
345  {
346  if( SCIPisRelEQ(scip, lbx, ubx) )
347  {
348  /* x*y = ubx * y + (x-ubx) * y <= ubx * y + (x-ubx) * lby <= ubx * y + max{(lbx-ubx) * lby, 0 * lby} */
349  coefx = 0.0;
350  coefy = bilincoef * ubx;
351  constant = bilincoef * (lby < 0.0 ? (lbx - ubx) * lby : 0.0);
352  }
353  else if( SCIPisRelEQ(scip, lby, uby) )
354  {
355  /* x*y = lby * x + (y-lby) * x <= lby * x + (y-lby) * ubx <= lby * x + max{(uby-lby) * ubx, 0 * ubx} */
356  coefx = bilincoef * lby;
357  coefy = 0.0;
358  constant = bilincoef * (ubx > 0.0 ? (uby - lby) * ubx : 0.0);
359  }
360  else
361  {
362  coefx = bilincoef * lby;
363  coefy = bilincoef * ubx;
364  constant = -bilincoef * ubx * lby;
365  }
366  }
367  else if( !SCIPisInfinity(scip, -lbx) && !SCIPisInfinity(scip, uby) )
368  {
369  if( SCIPisRelEQ(scip, lbx, ubx) )
370  {
371  /* x*y = lbx * y + (x-lbx) * y <= lbx * y + (x-lbx) * uby <= lbx * y + max{(ubx-lbx) * uby, 0 * uby} */
372  coefx = 0.0;
373  coefy = bilincoef * lbx;
374  constant = bilincoef * (uby > 0.0 ? (ubx - lbx) * uby : 0.0);
375  }
376  else if( SCIPisRelEQ(scip, lby, uby) )
377  {
378  /* x*y = uby * x + (y-uby) * x <= uby * x + (y-uby) * lbx <= uby * x + max{(lby-uby) * lbx, 0 * lbx} */
379  coefx = bilincoef * uby;
380  coefy = 0.0;
381  constant = bilincoef * (lbx < 0.0 ? (lby - uby) * lbx : 0.0);
382  }
383  else
384  {
385  coefx = bilincoef * uby;
386  coefy = bilincoef * lbx;
387  constant = -bilincoef * lbx * uby;
388  }
389  }
390  else
391  {
392  *success = FALSE;
393  return;
394  }
395  }
396 
397  if( SCIPisInfinity(scip, REALABS(coefx)) || SCIPisInfinity(scip, REALABS(coefy))
398  || SCIPisInfinity(scip, REALABS(constant)) )
399  {
400  *success = FALSE;
401  return;
402  }
403 
404  if( overestimate )
405  {
406  coefx = -coefx;
407  coefy = -coefy;
408  constant = -constant;
409  }
410 
411  SCIPdebugMsg(scip, "%.15g * x[%.15g,%.15g] * y[%.15g,%.15g] %c= %.15g * x %+.15g * y %+.15g\n", bilincoef, lbx, ubx,
412  lby, uby, overestimate ? '<' : '>', coefx, coefy, constant);
413 
414  *lincoefx += coefx;
415  *lincoefy += coefy;
416  *linconstant += constant;
417 }
418 
419 
420 /** computes coefficients of linearization of a bilinear term in a reference point when given a linear inequality
421  * involving only the variables of the bilinear term
422  *
423  * @note the formulas are extracted from "Convex envelopes of bivariate functions through the solution of KKT systems"
424  * by Marco Locatelli
425  */
427  SCIP* scip, /**< SCIP data structure */
428  SCIP_Real bilincoef, /**< coefficient of bilinear term */
429  SCIP_Real lbx, /**< lower bound on first variable */
430  SCIP_Real ubx, /**< upper bound on first variable */
431  SCIP_Real refpointx, /**< reference point for first variable */
432  SCIP_Real lby, /**< lower bound on second variable */
433  SCIP_Real uby, /**< upper bound on second variable */
434  SCIP_Real refpointy, /**< reference point for second variable */
435  SCIP_Bool overestimate, /**< whether to compute an overestimator instead of an underestimator */
436  SCIP_Real xcoef, /**< x coefficient of linear inequality; must be in {-1,0,1} */
437  SCIP_Real ycoef, /**< y coefficient of linear inequality */
438  SCIP_Real constant, /**< constant of linear inequality */
439  SCIP_Real* RESTRICT lincoefx, /**< buffer to store coefficient of first variable in linearization */
440  SCIP_Real* RESTRICT lincoefy, /**< buffer to store coefficient of second variable in linearization */
441  SCIP_Real* RESTRICT linconstant, /**< buffer to store constant of linearization */
442  SCIP_Bool* RESTRICT success /**< buffer to store whether linearization was successful */
443  )
444 {
445  SCIP_Real xs[2] = {lbx, ubx};
446  SCIP_Real ys[2] = {lby, uby};
447  SCIP_Real minx;
448  SCIP_Real maxx;
449  SCIP_Real miny;
450  SCIP_Real maxy;
451  SCIP_Real QUAD(lincoefyq);
452  SCIP_Real QUAD(lincoefxq);
453  SCIP_Real QUAD(linconstantq);
454  SCIP_Real QUAD(denomq);
455  SCIP_Real QUAD(mjq);
456  SCIP_Real QUAD(qjq);
457  SCIP_Real QUAD(xjq);
458  SCIP_Real QUAD(yjq);
459  SCIP_Real QUAD(tmpq);
460  SCIP_Real vx;
461  SCIP_Real vy;
462  int n;
463  int i;
464 
465  assert(scip != NULL);
466  assert(!SCIPisInfinity(scip, lbx));
467  assert(!SCIPisInfinity(scip, -ubx));
468  assert(!SCIPisInfinity(scip, lby));
469  assert(!SCIPisInfinity(scip, -uby));
470  assert(SCIPisLE(scip, lbx, ubx));
471  assert(SCIPisLE(scip, lby, uby));
472  assert(SCIPisLE(scip, lbx, refpointx));
473  assert(SCIPisGE(scip, ubx, refpointx));
474  assert(SCIPisLE(scip, lby, refpointy));
475  assert(SCIPisGE(scip, uby, refpointy));
476  assert(lincoefx != NULL);
477  assert(lincoefy != NULL);
478  assert(linconstant != NULL);
479  assert(success != NULL);
480  assert(xcoef == 0.0 || xcoef == -1.0 || xcoef == 1.0); /*lint !e777*/
481  assert(ycoef != SCIP_INVALID && ycoef != 0.0); /*lint !e777*/
482  assert(constant != SCIP_INVALID); /*lint !e777*/
483 
484  *success = FALSE;
485  *lincoefx = SCIP_INVALID;
486  *lincoefy = SCIP_INVALID;
487  *linconstant = SCIP_INVALID;
488 
489  /* reference point does not satisfy linear inequality */
490  if( SCIPisFeasGT(scip, xcoef * refpointx - ycoef * refpointy - constant, 0.0) )
491  return;
492 
493  /* compute minimal and maximal bounds on x and y for accepting the reference point */
494  minx = lbx + 0.01 * (ubx-lbx);
495  maxx = ubx - 0.01 * (ubx-lbx);
496  miny = lby + 0.01 * (uby-lby);
497  maxy = uby - 0.01 * (uby-lby);
498 
499  /* check whether the reference point is in [minx,maxx]x[miny,maxy] */
500  if( SCIPisLE(scip, refpointx, minx) || SCIPisGE(scip, refpointx, maxx)
501  || SCIPisLE(scip, refpointy, miny) || SCIPisGE(scip, refpointy, maxy) )
502  return;
503 
504  /* always consider xy without the bilinear coefficient */
505  if( bilincoef < 0.0 )
506  overestimate = !overestimate;
507 
508  /* we use same notation as in "Convex envelopes of bivariate functions through the solution of KKT systems", 2016 */
509  /* mj = xcoef / ycoef */
510  SCIPquadprecDivDD(mjq, xcoef, ycoef);
511 
512  /* qj = -constant / ycoef */
513  SCIPquadprecDivDD(qjq, -constant, ycoef);
514 
515  /* mj > 0 => underestimate; mj < 0 => overestimate */
516  if( SCIPisNegative(scip, QUAD_TO_DBL(mjq)) != overestimate )
517  return;
518 
519  /* get the corner point that satisfies the linear inequality xcoef*x <= ycoef*y + constant */
520  if( !overestimate )
521  {
522  ys[0] = uby;
523  ys[1] = lby;
524  }
525 
526  vx = SCIP_INVALID;
527  vy = SCIP_INVALID;
528  n = 0;
529  for( i = 0; i < 2; ++i )
530  {
531  SCIP_Real activity = xcoef * xs[i] - ycoef * ys[i] - constant;
532  if( SCIPisLE(scip, activity, 0.0) )
533  {
534  /* corner point is satisfies inequality */
535  vx = xs[i];
536  vy = ys[i];
537  }
538  else if( SCIPisFeasGT(scip, activity, 0.0) )
539  /* corner point is clearly cut off */
540  ++n;
541  }
542 
543  /* skip if no corner point satisfies the inequality or if no corner point is cut off (that is, all corner points satisfy the inequality almost [1e-9..1e-6]) */
544  if( n != 1 || vx == SCIP_INVALID || vy == SCIP_INVALID ) /*lint !e777*/
545  return;
546 
547  /* denom = mj*(refpointx - vx) + vy - refpointy */
548  SCIPquadprecSumDD(denomq, refpointx, -vx); /* refpoint - vx */
549  SCIPquadprecProdQQ(denomq, denomq, mjq); /* mj * (refpoint - vx) */
550  SCIPquadprecSumQD(denomq, denomq, vy); /* mj * (refpoint - vx) + vy */
551  SCIPquadprecSumQD(denomq, denomq, -refpointy); /* mj * (refpoint - vx) + vy - refpointy */
552 
553  if( SCIPisZero(scip, QUAD_TO_DBL(denomq)) )
554  return;
555 
556  /* (xj,yj) is the projection onto the line xcoef*x = ycoef*y + constant */
557  /* xj = (refpointx*(vy - qj) - vx*(refpointy - qj)) / denom */
558  SCIPquadprecProdQD(xjq, qjq, -1.0); /* - qj */
559  SCIPquadprecSumQD(xjq, xjq, vy); /* vy - qj */
560  SCIPquadprecProdQD(xjq, xjq, refpointx); /* refpointx * (vy - qj) */
561  SCIPquadprecProdQD(tmpq, qjq, -1.0); /* - qj */
562  SCIPquadprecSumQD(tmpq, tmpq, refpointy); /* refpointy - qj */
563  SCIPquadprecProdQD(tmpq, tmpq, -vx); /* - vx * (refpointy - qj) */
564  SCIPquadprecSumQQ(xjq, xjq, tmpq); /* refpointx * (vy - qj) - vx * (refpointy - qj) */
565  SCIPquadprecDivQQ(xjq, xjq, denomq); /* (refpointx * (vy - qj) - vx * (refpointy - qj)) / denom */
566 
567  /* yj = mj * xj + qj */
568  SCIPquadprecProdQQ(yjq, mjq, xjq);
569  SCIPquadprecSumQQ(yjq, yjq, qjq);
570 
571  assert(SCIPisFeasEQ(scip, xcoef*QUAD_TO_DBL(xjq) - ycoef*QUAD_TO_DBL(yjq) - constant, 0.0));
572 
573  /* check whether the projection is in [minx,maxx] x [miny,maxy]; this avoids numerical difficulties when the
574  * projection is close to the variable bounds
575  */
576  if( SCIPisLE(scip, QUAD_TO_DBL(xjq), minx) || SCIPisGE(scip, QUAD_TO_DBL(xjq), maxx)
577  || SCIPisLE(scip, QUAD_TO_DBL(yjq), miny) || SCIPisGE(scip, QUAD_TO_DBL(yjq), maxy) )
578  return;
579 
580  assert(vy - QUAD_TO_DBL(mjq)*vx - QUAD_TO_DBL(qjq) != 0.0);
581 
582  /* lincoefy = (mj*SQR(xj) - 2.0*mj*vx*xj - qj*vx + vx*vy) / (vy - mj*vx - qj) */
583  SCIPquadprecSquareQ(lincoefyq, xjq); /* xj^2 */
584  SCIPquadprecProdQQ(lincoefyq, lincoefyq, mjq); /* mj * xj^2 */
585  SCIPquadprecProdQQ(tmpq, mjq, xjq); /* mj * xj */
586  SCIPquadprecProdQD(tmpq, tmpq, -2.0 * vx); /* -2 * vx * mj * xj */
587  SCIPquadprecSumQQ(lincoefyq, lincoefyq, tmpq); /* mj * xj^2 -2 * vx * mj * xj */
588  SCIPquadprecProdQD(tmpq, qjq, -vx); /* -qj * vx */
589  SCIPquadprecSumQQ(lincoefyq, lincoefyq, tmpq); /* mj * xj^2 -2 * vx * mj * xj -qj * vx */
590  SCIPquadprecProdDD(tmpq, vx, vy); /* vx * vy */
591  SCIPquadprecSumQQ(lincoefyq, lincoefyq, tmpq); /* mj * xj^2 -2 * vx * mj * xj -qj * vx + vx * vy */
592  SCIPquadprecProdQD(tmpq, mjq, vx); /* mj * vx */
593  SCIPquadprecSumQD(tmpq, tmpq, -vy); /* -vy + mj * vx */
594  SCIPquadprecSumQQ(tmpq, tmpq, qjq); /* -vy + mj * vx + qj */
595  QUAD_SCALE(tmpq, -1.0); /* vy - mj * vx - qj */
596  SCIPquadprecDivQQ(lincoefyq, lincoefyq, tmpq); /* (mj * xj^2 -2 * vx * mj * xj -qj * vx + vx * vy) / (vy - mj * vx - qj) */
597 
598  /* lincoefx = 2.0*mj*xj + qj - mj*(*lincoefy) */
599  SCIPquadprecProdQQ(lincoefxq, mjq, xjq); /* mj * xj */
600  QUAD_SCALE(lincoefxq, 2.0); /* 2 * mj * xj */
601  SCIPquadprecSumQQ(lincoefxq, lincoefxq, qjq); /* 2 * mj * xj + qj */
602  SCIPquadprecProdQQ(tmpq, mjq, lincoefyq); /* mj * lincoefy */
603  QUAD_SCALE(tmpq, -1.0); /* - mj * lincoefy */
604  SCIPquadprecSumQQ(lincoefxq, lincoefxq, tmpq); /* 2 * mj * xj + qj - mj * lincoefy */
605 
606  /* linconstant = -mj*SQR(xj) - (*lincoefy)*qj */
607  SCIPquadprecSquareQ(linconstantq, xjq); /* xj^2 */
608  SCIPquadprecProdQQ(linconstantq, linconstantq, mjq); /* mj * xj^2 */
609  QUAD_SCALE(linconstantq, -1.0); /* - mj * xj^2 */
610  SCIPquadprecProdQQ(tmpq, lincoefyq, qjq); /* lincoefy * qj */
611  QUAD_SCALE(tmpq, -1.0); /* - lincoefy * qj */
612  SCIPquadprecSumQQ(linconstantq, linconstantq, tmpq); /* - mj * xj^2 - lincoefy * qj */
613 
614  /* consider the bilinear coefficient */
615  SCIPquadprecProdQD(lincoefxq, lincoefxq, bilincoef);
616  SCIPquadprecProdQD(lincoefyq, lincoefyq, bilincoef);
617  SCIPquadprecProdQD(linconstantq, linconstantq, bilincoef);
618  *lincoefx = QUAD_TO_DBL(lincoefxq);
619  *lincoefy = QUAD_TO_DBL(lincoefyq);
620  *linconstant = QUAD_TO_DBL(linconstantq);
621 
622  /* cut needs to be tight at (vx,vy) and (xj,yj); otherwise we consider the cut to be numerically bad */
623  *success = SCIPisFeasEQ(scip, (*lincoefx)*vx + (*lincoefy)*vy + (*linconstant), bilincoef*vx*vy)
624  && SCIPisFeasEQ(scip, (*lincoefx)*QUAD_TO_DBL(xjq) + (*lincoefy)*QUAD_TO_DBL(yjq) + (*linconstant), bilincoef*QUAD_TO_DBL(xjq)*QUAD_TO_DBL(yjq));
625 
626 #ifndef NDEBUG
627  {
628  SCIP_Real activity = (*lincoefx)*refpointx + (*lincoefy)*refpointy + (*linconstant);
629 
630  /* cut needs to under- or overestimate the bilinear term at the reference point */
631  if( bilincoef < 0.0 )
632  overestimate = !overestimate;
633 
634  if( overestimate )
635  assert(SCIPisFeasGE(scip, activity, bilincoef*refpointx*refpointy));
636  else
637  assert(SCIPisFeasLE(scip, activity, bilincoef*refpointx*refpointy));
638  }
639 #endif
640 }
641 
642 /** helper function to compute the convex envelope of a bilinear term when two linear inequalities are given; we
643  * use the same notation and formulas as in Locatelli 2016
644  */
645 static
647  SCIP* scip, /**< SCIP data structure */
648  SCIP_Real x, /**< reference point for x */
649  SCIP_Real y, /**< reference point for y */
650  SCIP_Real mi, /**< coefficient of x in the first linear inequality */
651  SCIP_Real qi, /**< constant in the first linear inequality */
652  SCIP_Real mj, /**< coefficient of x in the second linear inequality */
653  SCIP_Real qj, /**< constant in the second linear inequality */
654  SCIP_Real* RESTRICT xi, /**< buffer to store x coordinate of the first point */
655  SCIP_Real* RESTRICT yi, /**< buffer to store y coordinate of the first point */
656  SCIP_Real* RESTRICT xj, /**< buffer to store x coordinate of the second point */
657  SCIP_Real* RESTRICT yj, /**< buffer to store y coordinate of the second point */
658  SCIP_Real* RESTRICT xcoef, /**< buffer to store the x coefficient of the envelope */
659  SCIP_Real* RESTRICT ycoef, /**< buffer to store the y coefficient of the envelope */
660  SCIP_Real* RESTRICT constant /**< buffer to store the constant of the envelope */
661  )
662 {
663  SCIP_Real QUAD(xiq);
664  SCIP_Real QUAD(yiq);
665  SCIP_Real QUAD(xjq);
666  SCIP_Real QUAD(yjq);
667  SCIP_Real QUAD(xcoefq);
668  SCIP_Real QUAD(ycoefq);
669  SCIP_Real QUAD(constantq);
670  SCIP_Real QUAD(tmpq);
671 
672  assert(xi != NULL);
673  assert(yi != NULL);
674  assert(xj != NULL);
675  assert(yj != NULL);
676  assert(xcoef != NULL);
677  assert(ycoef != NULL);
678  assert(constant != NULL);
679 
680  if( SCIPisEQ(scip, mi, mj) )
681  {
682  /* xi = (x + mi * y - qi) / (2.0*mi) */
683  SCIPquadprecProdDD(xiq, mi, y);
684  SCIPquadprecSumQD(xiq, xiq, x);
685  SCIPquadprecSumQD(xiq, xiq, -qi);
686  SCIPquadprecDivQD(xiq, xiq, 2.0 * mi);
687  assert(EPSEQ((x + mi * y - qi) / (2.0*mi), QUAD_TO_DBL(xiq), 1e-3));
688 
689  /* yi = mi*(*xi) + qi */
690  SCIPquadprecProdQD(yiq, xiq, mi);
691  SCIPquadprecSumQD(yiq, yiq, qi);
692  assert(EPSEQ(mi*QUAD_TO_DBL(xiq) + qi, QUAD_TO_DBL(yiq), 1e-3));
693 
694  /* xj = (*xi) + (qi - qj)/ (2.0*mi) */
695  SCIPquadprecSumDD(xjq, qi, -qj);
696  SCIPquadprecDivQD(xjq, xjq, 2.0 * mi);
697  SCIPquadprecSumQQ(xjq, xjq, xiq);
698  assert(EPSEQ(QUAD_TO_DBL(xiq) + (qi - qj)/ (2.0*mi), QUAD_TO_DBL(xjq), 1e-3));
699 
700  /* yj = mj * (*xj) + qj */
701  SCIPquadprecProdQD(yjq, xjq, mj);
702  SCIPquadprecSumQD(yjq, yjq, qj);
703  assert(EPSEQ(mj * QUAD_TO_DBL(xjq) + qj, QUAD_TO_DBL(yjq), 1e-3));
704 
705  /* ycoef = (*xi) + (qi - qj) / (4.0*mi) note that this is wrong in Locatelli 2016 */
706  SCIPquadprecSumDD(ycoefq, qi, -qj);
707  SCIPquadprecDivQD(ycoefq, ycoefq, 4.0 * mi);
708  SCIPquadprecSumQQ(ycoefq, ycoefq, xiq);
709  assert(EPSEQ(QUAD_TO_DBL(xiq) + (qi - qj) / (4.0*mi), QUAD_TO_DBL(ycoefq), 1e-3));
710 
711  /* xcoef = 2.0*mi*(*xi) - mi * (*ycoef) + qi */
712  SCIPquadprecProdQD(xcoefq, xiq, 2.0 * mi);
713  SCIPquadprecProdQD(tmpq, ycoefq, -mi);
714  SCIPquadprecSumQQ(xcoefq, xcoefq, tmpq);
715  SCIPquadprecSumQD(xcoefq, xcoefq, qi);
716  assert(EPSEQ(2.0*mi*QUAD_TO_DBL(xiq) - mi * QUAD_TO_DBL(ycoefq) + qi, QUAD_TO_DBL(xcoefq), 1e-3));
717 
718  /* constant = -mj*SQR(*xj) - (*ycoef) * qj */
719  SCIPquadprecSquareQ(constantq, xjq);
720  SCIPquadprecProdQD(constantq, constantq, -mj);
721  SCIPquadprecProdQD(tmpq, ycoefq, -qj);
722  SCIPquadprecSumQQ(constantq, constantq, tmpq);
723  assert(EPSEQ(-mj*SQR(QUAD_TO_DBL(xjq)) - QUAD_TO_DBL(ycoefq) * qj, QUAD_TO_DBL(constantq), 1e-3));
724 
725  *xi = QUAD_TO_DBL(xiq);
726  *yi = QUAD_TO_DBL(yiq);
727  *xj = QUAD_TO_DBL(xjq);
728  *yj = QUAD_TO_DBL(yjq);
729  *ycoef = QUAD_TO_DBL(ycoefq);
730  *xcoef = QUAD_TO_DBL(xcoefq);
731  *constant = QUAD_TO_DBL(constantq);
732  }
733  else if( mi > 0.0 )
734  {
735  assert(mj > 0.0);
736 
737  /* xi = (y + SQRT(mi*mj)*x - qi) / (REALABS(mi) + SQRT(mi*mj)) */
738  SCIPquadprecProdDD(xiq, mi, mj);
739  SCIPquadprecSqrtQ(xiq, xiq);
740  SCIPquadprecProdQD(xiq, xiq, x);
741  SCIPquadprecSumQD(xiq, xiq, y);
742  SCIPquadprecSumQD(xiq, xiq, -qi); /* (y + SQRT(mi*mj)*x - qi) */
743  SCIPquadprecProdDD(tmpq, mi, mj);
744  SCIPquadprecSqrtQ(tmpq, tmpq);
745  SCIPquadprecSumQD(tmpq, tmpq, REALABS(mi)); /* REALABS(mi) + SQRT(mi*mj) */
746  SCIPquadprecDivQQ(xiq, xiq, tmpq);
747  assert(EPSEQ((y + SQRT(mi*mj)*x - qi) / (REALABS(mi) + SQRT(mi*mj)), QUAD_TO_DBL(xiq), 1e-3));
748 
749  /* yi = mi*(*xi) + qi */
750  SCIPquadprecProdQD(yiq, xiq, mi);
751  SCIPquadprecSumQD(yiq, yiq, qi);
752  assert(EPSEQ(mi*(QUAD_TO_DBL(xiq)) + qi, QUAD_TO_DBL(yiq), 1e-3));
753 
754  /* xj = (y + SQRT(mi*mj)*x - qj) / (REALABS(mj) + SQRT(mi*mj)) */
755  SCIPquadprecProdDD(xjq, mi, mj);
756  SCIPquadprecSqrtQ(xjq, xjq);
757  SCIPquadprecProdQD(xjq, xjq, x);
758  SCIPquadprecSumQD(xjq, xjq, y);
759  SCIPquadprecSumQD(xjq, xjq, -qj); /* (y + SQRT(mi*mj)*x - qj) */
760  SCIPquadprecProdDD(tmpq, mi, mj);
761  SCIPquadprecSqrtQ(tmpq, tmpq);
762  SCIPquadprecSumQD(tmpq, tmpq, REALABS(mj)); /* REALABS(mj) + SQRT(mi*mj) */
763  SCIPquadprecDivQQ(xjq, xjq, tmpq);
764  assert(EPSEQ((y + SQRT(mi*mj)*x - qj) / (REALABS(mj) + SQRT(mi*mj)), QUAD_TO_DBL(xjq), 1e-3));
765 
766  /* yj = mj*(*xj) + qj */
767  SCIPquadprecProdQD(yjq, xjq, mj);
768  SCIPquadprecSumQD(yjq, yjq, qj);
769  assert(EPSEQ(mj*QUAD_TO_DBL(xjq) + qj, QUAD_TO_DBL(yjq), 1e-3));
770 
771  /* ycoef = (2.0*mj*(*xj) + qj - 2.0*mi*(*xi) - qi) / (mj - mi) */
772  SCIPquadprecProdQD(ycoefq, xjq, 2.0 * mj);
773  SCIPquadprecSumQD(ycoefq, ycoefq, qj);
774  SCIPquadprecProdQD(tmpq, xiq, -2.0 * mi);
775  SCIPquadprecSumQQ(ycoefq, ycoefq, tmpq);
776  SCIPquadprecSumQD(ycoefq, ycoefq, -qi);
777  SCIPquadprecSumDD(tmpq, mj, -mi);
778  SCIPquadprecDivQQ(ycoefq, ycoefq, tmpq);
779  assert(EPSEQ((2.0*mj*QUAD_TO_DBL(xjq) + qj - 2.0*mi*QUAD_TO_DBL(xiq) - qi) / (mj - mi), QUAD_TO_DBL(ycoefq), 1e-3));
780 
781  /* xcoef = 2.0*mj*(*xj) + qj - mj*(*ycoef) */
782  SCIPquadprecProdQD(xcoefq, xjq, 2.0 * mj);
783  SCIPquadprecSumQD(xcoefq, xcoefq, qj);
784  SCIPquadprecProdQD(tmpq, ycoefq, -mj);
785  SCIPquadprecSumQQ(xcoefq, xcoefq, tmpq);
786  assert(EPSEQ(2.0*mj*QUAD_TO_DBL(xjq) + qj - mj*QUAD_TO_DBL(ycoefq), QUAD_TO_DBL(xcoefq), 1e-3));
787 
788  /* constant = -mj*SQR(*xj) - (*ycoef) * qj */
789  SCIPquadprecSquareQ(constantq, xjq);
790  SCIPquadprecProdQD(constantq, constantq, -mj);
791  SCIPquadprecProdQD(tmpq, ycoefq, -qj);
792  SCIPquadprecSumQQ(constantq, constantq, tmpq);
793  assert(EPSEQ(-mj*SQR(QUAD_TO_DBL(xjq)) - QUAD_TO_DBL(ycoefq) * qj, QUAD_TO_DBL(constantq), 1e-3));
794 
795  *xi = QUAD_TO_DBL(xiq);
796  *yi = QUAD_TO_DBL(yiq);
797  *xj = QUAD_TO_DBL(xjq);
798  *yj = QUAD_TO_DBL(yjq);
799  *ycoef = QUAD_TO_DBL(ycoefq);
800  *xcoef = QUAD_TO_DBL(xcoefq);
801  *constant = QUAD_TO_DBL(constantq);
802  }
803  else
804  {
805  assert(mi < 0.0 && mj < 0.0);
806 
807  /* apply variable transformation x = -x in case for overestimation */
808  computeBilinEnvelope2(scip, -x, y, -mi, qi, -mj, qj, xi, yi, xj, yj, xcoef, ycoef, constant);
809 
810  /* revert transformation; multiply cut by -1 and change -x by x */
811  *xi = -(*xi);
812  *xj = -(*xj);
813  *ycoef = -(*ycoef);
814  *constant = -(*constant);
815  }
816 }
817 
818 /** computes coefficients of linearization of a bilinear term in a reference point when given two linear inequality
819  * involving only the variables of the bilinear term
820  *
821  * @note the formulas are extracted from "Convex envelopes of bivariate functions through the solution of KKT systems"
822  * by Marco Locatelli
823  *
824  */
826  SCIP* scip, /**< SCIP data structure */
827  SCIP_Real bilincoef, /**< coefficient of bilinear term */
828  SCIP_Real lbx, /**< lower bound on first variable */
829  SCIP_Real ubx, /**< upper bound on first variable */
830  SCIP_Real refpointx, /**< reference point for first variable */
831  SCIP_Real lby, /**< lower bound on second variable */
832  SCIP_Real uby, /**< upper bound on second variable */
833  SCIP_Real refpointy, /**< reference point for second variable */
834  SCIP_Bool overestimate, /**< whether to compute an overestimator instead of an underestimator */
835  SCIP_Real xcoef1, /**< x coefficient of linear inequality; must be in {-1,0,1} */
836  SCIP_Real ycoef1, /**< y coefficient of linear inequality */
837  SCIP_Real constant1, /**< constant of linear inequality */
838  SCIP_Real xcoef2, /**< x coefficient of linear inequality; must be in {-1,0,1} */
839  SCIP_Real ycoef2, /**< y coefficient of linear inequality */
840  SCIP_Real constant2, /**< constant of linear inequality */
841  SCIP_Real* RESTRICT lincoefx, /**< buffer to store coefficient of first variable in linearization */
842  SCIP_Real* RESTRICT lincoefy, /**< buffer to store coefficient of second variable in linearization */
843  SCIP_Real* RESTRICT linconstant, /**< buffer to store constant of linearization */
844  SCIP_Bool* RESTRICT success /**< buffer to store whether linearization was successful */
845  )
846 {
847  SCIP_Real mi, mj, qi, qj, xi, xj, yi, yj;
848  SCIP_Real xcoef, ycoef, constant;
849  SCIP_Real minx, maxx, miny, maxy;
850 
851  assert(scip != NULL);
852  assert(!SCIPisInfinity(scip, lbx));
853  assert(!SCIPisInfinity(scip, -ubx));
854  assert(!SCIPisInfinity(scip, lby));
855  assert(!SCIPisInfinity(scip, -uby));
856  assert(SCIPisLE(scip, lbx, ubx));
857  assert(SCIPisLE(scip, lby, uby));
858  assert(SCIPisLE(scip, lbx, refpointx));
859  assert(SCIPisGE(scip, ubx, refpointx));
860  assert(SCIPisLE(scip, lby, refpointy));
861  assert(SCIPisGE(scip, uby, refpointy));
862  assert(lincoefx != NULL);
863  assert(lincoefy != NULL);
864  assert(linconstant != NULL);
865  assert(success != NULL);
866  assert(xcoef1 != 0.0 && xcoef1 != SCIP_INVALID); /*lint !e777*/
867  assert(ycoef1 != SCIP_INVALID && ycoef1 != 0.0); /*lint !e777*/
868  assert(constant1 != SCIP_INVALID); /*lint !e777*/
869  assert(xcoef2 != 0.0 && xcoef2 != SCIP_INVALID); /*lint !e777*/
870  assert(ycoef2 != SCIP_INVALID && ycoef2 != 0.0); /*lint !e777*/
871  assert(constant2 != SCIP_INVALID); /*lint !e777*/
872 
873  *success = FALSE;
874  *lincoefx = SCIP_INVALID;
875  *lincoefy = SCIP_INVALID;
876  *linconstant = SCIP_INVALID;
877 
878  /* reference point does not satisfy linear inequalities */
879  if( SCIPisFeasGT(scip, xcoef1 * refpointx - ycoef1 * refpointy - constant1, 0.0)
880  || SCIPisFeasGT(scip, xcoef2 * refpointx - ycoef2 * refpointy - constant2, 0.0) )
881  return;
882 
883  /* compute minimal and maximal bounds on x and y for accepting the reference point */
884  minx = lbx + 0.01 * (ubx-lbx);
885  maxx = ubx - 0.01 * (ubx-lbx);
886  miny = lby + 0.01 * (uby-lby);
887  maxy = uby - 0.01 * (uby-lby);
888 
889  /* check the reference point is in the interior of the domain */
890  if( SCIPisLE(scip, refpointx, minx) || SCIPisGE(scip, refpointx, maxx)
891  || SCIPisLE(scip, refpointy, miny) || SCIPisFeasGE(scip, refpointy, maxy) )
892  return;
893 
894  /* the sign of the x-coefficients of the two inequalities must be different; otherwise the convex or concave
895  * envelope can be computed via SCIPcomputeBilinEnvelope1 for each inequality separately
896  */
897  if( (xcoef1 > 0) == (xcoef2 > 0) )
898  return;
899 
900  /* always consider xy without the bilinear coefficient */
901  if( bilincoef < 0.0 )
902  overestimate = !overestimate;
903 
904  /* we use same notation as in "Convex envelopes of bivariate functions through the solution of KKT systems", 2016 */
905  mi = xcoef1 / ycoef1;
906  qi = -constant1 / ycoef1;
907  mj = xcoef2 / ycoef2;
908  qj = -constant2 / ycoef2;
909 
910  /* mi, mj > 0 => underestimate; mi, mj < 0 => overestimate */
911  if( SCIPisNegative(scip, mi) != overestimate || SCIPisNegative(scip, mj) != overestimate )
912  return;
913 
914  /* compute cut according to Locatelli 2016 */
915  computeBilinEnvelope2(scip, refpointx, refpointy, mi, qi, mj, qj, &xi, &yi, &xj, &yj, &xcoef, &ycoef, &constant);
916  assert(SCIPisRelEQ(scip, mi*xi + qi, yi));
917  assert(SCIPisRelEQ(scip, mj*xj + qj, yj));
918 
919  /* it might happen that (xi,yi) = (xj,yj) if the two lines intersect */
920  if( SCIPisEQ(scip, xi, xj) && SCIPisEQ(scip, yi, yj) )
921  return;
922 
923  /* check whether projected points are in the interior */
924  if( SCIPisLE(scip, xi, minx) || SCIPisGE(scip, xi, maxx) || SCIPisLE(scip, yi, miny) || SCIPisGE(scip, yi, maxy) )
925  return;
926  if( SCIPisLE(scip, xj, minx) || SCIPisGE(scip, xj, maxx) || SCIPisLE(scip, yj, miny) || SCIPisGE(scip, yj, maxy) )
927  return;
928 
929  *lincoefx = bilincoef * xcoef;
930  *lincoefy = bilincoef * ycoef;
931  *linconstant = bilincoef * constant;
932 
933  /* cut needs to be tight at (vx,vy) and (xj,yj) */
934  *success = SCIPisFeasEQ(scip, (*lincoefx)*xi + (*lincoefy)*yi + (*linconstant), bilincoef*xi*yi)
935  && SCIPisFeasEQ(scip, (*lincoefx)*xj + (*lincoefy)*yj + (*linconstant), bilincoef*xj*yj);
936 
937 #ifndef NDEBUG
938  {
939  SCIP_Real activity = (*lincoefx)*refpointx + (*lincoefy)*refpointy + (*linconstant);
940 
941  /* cut needs to under- or overestimate the bilinear term at the reference point */
942  if( bilincoef < 0.0 )
943  overestimate = !overestimate;
944 
945  if( overestimate )
946  assert(SCIPisFeasGE(scip, activity, bilincoef*refpointx*refpointy));
947  else
948  assert(SCIPisFeasLE(scip, activity, bilincoef*refpointx*refpointy));
949  }
950 #endif
951 }
952 
953 /** creates an NLP relaxation and stores it in a given NLPI problem; the function computes for each variable which the
954  * number of non-linearly occurrences and stores it in the nlscore array
955  *
956  * @note the first row corresponds always to the cutoff row (even if cutoffbound is SCIPinfinity(scip))
957  **/
959  SCIP* scip, /**< SCIP data structure */
960  SCIP_NLPI* nlpi, /**< interface to NLP solver */
961  SCIP_NLROW** nlrows, /**< nonlinear rows */
962  int nnlrows, /**< total number of nonlinear rows */
963  SCIP_NLPIPROBLEM* nlpiprob, /**< empty nlpi problem */
964  SCIP_HASHMAP* var2idx, /**< empty hash map to store mapping between variables and indices in nlpi
965  * problem */
966  SCIP_Real* nlscore, /**< array to store the score of each nonlinear variable (NULL if not
967  * needed) */
968  SCIP_Real cutoffbound, /**< cutoff bound */
969  SCIP_Bool setobj, /**< should the objective function be set? */
970  SCIP_Bool onlyconvex /**< filter only for convex constraints */
971  )
972 {
973  SCIP_EXPRTREE** exprtrees;
974  int** exprvaridxs;
975  SCIP_QUADELEM** quadelems;
976  int* nquadelems;
977  SCIP_Real** linvals;
978  int** lininds;
979  int* nlininds;
980  SCIP_Real* lhss;
981  SCIP_Real* rhss;
982  const char** names;
983  SCIP_VAR** vars;
984  int nvars;
985  SCIP_Real* lbs;
986  SCIP_Real* ubs;
987  SCIP_Real* objvals = NULL;
988  int* objinds = NULL;
989  const char** varnames;
990  int nobjinds;
991  int nconss;
992  int i;
993 
994  assert(nlpiprob != NULL);
995  assert(var2idx != NULL);
996  assert(nlrows != NULL);
997  assert(nnlrows > 0);
998  assert(nlpi != NULL);
999 
1000  SCIPdebugMsg(scip, "call SCIPcreateConvexNlpNlobbt() with cutoffbound %g\n", cutoffbound);
1001 
1002  if( nlscore != NULL )
1003  {
1004  BMSclearMemoryArray(nlscore, SCIPgetNVars(scip));
1005  }
1006  vars = SCIPgetVars(scip);
1007  nvars = SCIPgetNVars(scip);
1008  nconss = 0;
1009 
1010  SCIP_CALL( SCIPallocBufferArray(scip, &exprtrees, nnlrows + 1) );
1011  SCIP_CALL( SCIPallocBufferArray(scip, &exprvaridxs, nnlrows + 1) );
1012  SCIP_CALL( SCIPallocBufferArray(scip, &quadelems, nnlrows + 1) );
1013  SCIP_CALL( SCIPallocBufferArray(scip, &nquadelems, nnlrows + 1) );
1014  SCIP_CALL( SCIPallocBufferArray(scip, &linvals, nnlrows + 1) );
1015  SCIP_CALL( SCIPallocBufferArray(scip, &lininds, nnlrows + 1) );
1016  SCIP_CALL( SCIPallocBufferArray(scip, &nlininds, nnlrows + 1) );
1017  SCIP_CALL( SCIPallocBufferArray(scip, &names, nnlrows + 1) );
1018  SCIP_CALL( SCIPallocBufferArray(scip, &lhss, nnlrows + 1) );
1019  SCIP_CALL( SCIPallocBufferArray(scip, &rhss, nnlrows + 1) );
1020 
1021  if( setobj )
1022  {
1023  SCIP_CALL( SCIPallocBufferArray(scip, &objvals, nvars) );
1024  SCIP_CALL( SCIPallocBufferArray(scip, &objinds, nvars) );
1025  }
1026 
1027  SCIP_CALL( SCIPallocBufferArray(scip, &lbs, nvars) );
1028  SCIP_CALL( SCIPallocBufferArray(scip, &ubs, nvars) );
1029  SCIP_CALL( SCIPallocBufferArray(scip, &varnames, nvars) );
1030 
1031  /* create a unique mapping between variables and {0,..,nvars-1} */
1032  nobjinds = 0;
1033  for( i = 0; i < nvars; ++i )
1034  {
1035  assert(vars[i] != NULL);
1036  SCIP_CALL( SCIPhashmapInsertInt(var2idx, (void*)vars[i], i) );
1037 
1038  lbs[i] = SCIPvarGetLbLocal(vars[i]);
1039  ubs[i] = SCIPvarGetUbLocal(vars[i]);
1040  varnames[i] = SCIPvarGetName(vars[i]);
1041 
1042  /* collect non-zero objective coefficients */
1043  if( setobj && !SCIPisZero(scip, SCIPvarGetObj(vars[i])) )
1044  {
1045  assert(objvals != NULL);
1046  assert(objinds != NULL);
1047 
1048  objvals[nobjinds] = SCIPvarGetObj(vars[i]);
1049  objinds[nobjinds] = i;
1050  ++nobjinds;
1051  }
1052  }
1053 
1054  /* add variables */
1055  SCIP_CALL( SCIPnlpiAddVars(nlpi, nlpiprob, nvars, lbs, ubs, varnames) );
1056  SCIPfreeBufferArray(scip, &varnames);
1057  SCIPfreeBufferArray(scip, &ubs);
1058  SCIPfreeBufferArray(scip, &lbs);
1059 
1060  /* set the objective function */
1061  if( setobj )
1062  {
1063  if( nobjinds > 0 )
1064  {
1065  SCIP_CALL( SCIPnlpiSetObjective(nlpi, nlpiprob, nobjinds, objinds, objvals, 0, NULL, NULL, NULL, 0.0) );
1066  }
1067 
1068  SCIPfreeBufferArray(scip, &objinds);
1069  SCIPfreeBufferArray(scip, &objvals);
1070  }
1071 
1072  /* add row for cutoff bound even if cutoffbound == SCIPinfinity() */
1073  lhss[nconss] = -SCIPinfinity(scip);
1074  rhss[nconss] = cutoffbound;
1075  names[nconss] = "objcutoff";
1076  lininds[nconss] = NULL;
1077  linvals[nconss] = NULL;
1078  nlininds[nconss] = 0;
1079  nquadelems[nconss] = 0;
1080  quadelems[nconss] = NULL;
1081  exprtrees[nconss] = NULL;
1082  exprvaridxs[nconss] = NULL;
1083 
1084  SCIP_CALL( SCIPallocBufferArray(scip, &lininds[nconss], nvars) ); /*lint !e866*/
1085  SCIP_CALL( SCIPallocBufferArray(scip, &linvals[nconss], nvars) ); /*lint !e866*/
1086 
1087  for( i = 0; i < nvars; ++i )
1088  {
1089  if( !SCIPisZero(scip, SCIPvarGetObj(vars[i])) )
1090  {
1091  linvals[nconss][nlininds[nconss]] = SCIPvarGetObj(vars[i]);
1092  lininds[nconss][nlininds[nconss]] = i;
1093  ++nlininds[nconss];
1094  }
1095  }
1096  ++nconss;
1097 
1098  /* add convex nonlinear rows to NLPI problem */
1099  for( i = 0; i < nnlrows; ++i )
1100  {
1101  SCIP_Bool userhs;
1102  SCIP_Bool uselhs;
1103  int k;
1104 
1105  assert(nlrows[i] != NULL);
1106 
1107  uselhs = FALSE;
1108  userhs = FALSE;
1109 
1110  /* check curvature together with constraint sides of a nonlinear row */
1111  if( SCIPnlrowGetNQuadElems(nlrows[i]) == 0 && SCIPnlrowGetExprtree(nlrows[i]) == NULL )
1112  {
1113  uselhs = TRUE;
1114  userhs = TRUE;
1115  }
1116  else
1117  {
1118  if( (!onlyconvex || SCIPnlrowGetCurvature(nlrows[i]) == SCIP_EXPRCURV_CONVEX)
1119  && !SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrows[i])) )
1120  userhs = TRUE;
1121  if( (!onlyconvex || SCIPnlrowGetCurvature(nlrows[i]) == SCIP_EXPRCURV_CONCAVE)
1122  && !SCIPisInfinity(scip, SCIPnlrowGetLhs(nlrows[i])) )
1123  uselhs = TRUE;
1124  }
1125 
1126  if( !uselhs && !userhs )
1127  continue;
1128 
1129  lhss[nconss] = uselhs ? SCIPnlrowGetLhs(nlrows[i]) - SCIPnlrowGetConstant(nlrows[i]) : -SCIPinfinity(scip);
1130  rhss[nconss] = userhs ? SCIPnlrowGetRhs(nlrows[i]) - SCIPnlrowGetConstant(nlrows[i]) : SCIPinfinity(scip);
1131  names[nconss] = SCIPnlrowGetName(nlrows[i]);
1132  nlininds[nconss] = 0;
1133  lininds[nconss] = NULL;
1134  linvals[nconss] = NULL;
1135  nquadelems[nconss] = 0;
1136  quadelems[nconss] = NULL;
1137  exprtrees[nconss] = NULL;
1138  exprvaridxs[nconss] = NULL;
1139 
1140  /* copy linear part */
1141  if( SCIPnlrowGetNLinearVars(nlrows[i]) > 0 )
1142  {
1143  SCIP_VAR* var;
1144 
1145  nlininds[nconss] = SCIPnlrowGetNLinearVars(nlrows[i]);
1146 
1147  SCIP_CALL( SCIPallocBufferArray(scip, &lininds[nconss], nlininds[nconss]) ); /*lint !e866*/
1148  SCIP_CALL( SCIPallocBufferArray(scip, &linvals[nconss], nlininds[nconss]) ); /*lint !e866*/
1149 
1150  for( k = 0; k < nlininds[nconss]; ++k )
1151  {
1152  var = SCIPnlrowGetLinearVars(nlrows[i])[k];
1153  assert(var != NULL);
1154  assert(SCIPhashmapExists(var2idx, (void*)var));
1155 
1156  lininds[nconss][k] = SCIPhashmapGetImageInt(var2idx, (void*)var);
1157  assert(var == vars[lininds[nconss][k]]);
1158  linvals[nconss][k] = SCIPnlrowGetLinearCoefs(nlrows[i])[k];
1159  }
1160  }
1161 
1162  /* copy quadratic part */
1163  if( SCIPnlrowGetNQuadElems(nlrows[i]) > 0 )
1164  {
1165  SCIP_QUADELEM quadelem;
1166  SCIP_VAR* var1;
1167  SCIP_VAR* var2;
1168 
1169  nquadelems[nconss] = SCIPnlrowGetNQuadElems(nlrows[i]);
1170  SCIP_CALL( SCIPallocBufferArray(scip, &quadelems[nconss], nquadelems[nconss]) ); /*lint !e866*/
1171 
1172  for( k = 0; k < nquadelems[nconss]; ++k )
1173  {
1174  quadelem = SCIPnlrowGetQuadElems(nlrows[i])[k];
1175 
1176  var1 = SCIPnlrowGetQuadVars(nlrows[i])[quadelem.idx1];
1177  assert(var1 != NULL);
1178  assert(SCIPhashmapExists(var2idx, (void*)var1));
1179 
1180  var2 = SCIPnlrowGetQuadVars(nlrows[i])[quadelem.idx2];
1181  assert(var2 != NULL);
1182  assert(SCIPhashmapExists(var2idx, (void*)var2));
1183 
1184  quadelems[nconss][k].coef = quadelem.coef;
1185  quadelems[nconss][k].idx1 = SCIPhashmapGetImageInt(var2idx, (void*)var1);
1186  quadelems[nconss][k].idx2 = SCIPhashmapGetImageInt(var2idx, (void*)var2);
1187 
1188  /* expr.c assumes that the indices are ordered */
1189  if( quadelems[nconss][k].idx1 > quadelems[nconss][k].idx2 )
1190  {
1191  SCIPswapInts(&quadelems[nconss][k].idx1, &quadelems[nconss][k].idx2);
1192  }
1193  assert(quadelems[nconss][k].idx1 <= quadelems[nconss][k].idx2);
1194 
1195  /* update nlscore */
1196  if( nlscore != NULL )
1197  {
1198  ++nlscore[quadelems[nconss][k].idx1];
1199  if( quadelems[nconss][k].idx1 != quadelems[nconss][k].idx2 )
1200  ++nlscore[quadelems[nconss][k].idx2];
1201  }
1202  }
1203  }
1204 
1205  /* copy expression tree */
1206  if( SCIPnlrowGetExprtree(nlrows[i]) != NULL )
1207  {
1208  SCIP_VAR* var;
1209 
1210  /* note that we don't need to copy the expression tree here since only the mapping between variables in the
1211  * tree and the corresponding indices change; this mapping is stored in the exprvaridxs array
1212  */
1213  exprtrees[nconss] = SCIPnlrowGetExprtree(nlrows[i]);
1214 
1215  SCIP_CALL( SCIPallocBufferArray(scip, &exprvaridxs[nconss], SCIPexprtreeGetNVars(exprtrees[nconss])) ); /*lint !e866*/
1216 
1217  for( k = 0; k < SCIPexprtreeGetNVars(exprtrees[nconss]); ++k )
1218  {
1219  var = SCIPexprtreeGetVars(exprtrees[nconss])[k];
1220  assert(var != NULL);
1221  assert(SCIPhashmapExists(var2idx, (void*)var));
1222 
1223  exprvaridxs[nconss][k] = SCIPhashmapGetImageInt(var2idx, (void*)var);
1224 
1225  /* update nlscore */
1226  if( nlscore != NULL )
1227  ++nlscore[exprvaridxs[nconss][k]];
1228  }
1229  }
1230 
1231  ++nconss;
1232  }
1233  assert(nconss > 0);
1234 
1235  /* pass all constraint information to nlpi */
1236  SCIP_CALL( SCIPnlpiAddConstraints(nlpi, nlpiprob, nconss, lhss, rhss, nlininds, lininds, linvals, nquadelems,
1237  quadelems, exprvaridxs, exprtrees, names) );
1238 
1239  /* free memory */
1240  for( i = nconss - 1; i > 0; --i )
1241  {
1242  if( exprtrees[i] != NULL )
1243  {
1244  assert(exprvaridxs[i] != NULL);
1245  SCIPfreeBufferArray(scip, &exprvaridxs[i]);
1246  }
1247 
1248  if( nquadelems[i] > 0 )
1249  {
1250  assert(quadelems[i] != NULL);
1251  SCIPfreeBufferArray(scip, &quadelems[i]);
1252  }
1253 
1254  if( nlininds[i] > 0 )
1255  {
1256  assert(linvals[i] != NULL);
1257  assert(lininds[i] != NULL);
1258  SCIPfreeBufferArray(scip, &linvals[i]);
1259  SCIPfreeBufferArray(scip, &lininds[i]);
1260  }
1261  }
1262  /* free row for cutoff bound even if objective is 0 */
1263  SCIPfreeBufferArray(scip, &linvals[i]);
1264  SCIPfreeBufferArray(scip, &lininds[i]);
1265 
1266  SCIPfreeBufferArray(scip, &rhss);
1267  SCIPfreeBufferArray(scip, &lhss);
1268  SCIPfreeBufferArray(scip, &names);
1269  SCIPfreeBufferArray(scip, &nlininds);
1270  SCIPfreeBufferArray(scip, &lininds);
1271  SCIPfreeBufferArray(scip, &linvals);
1272  SCIPfreeBufferArray(scip, &nquadelems);
1273  SCIPfreeBufferArray(scip, &quadelems);
1274  SCIPfreeBufferArray(scip, &exprvaridxs);
1275  SCIPfreeBufferArray(scip, &exprtrees);
1276 
1277  return SCIP_OKAY;
1278 }
1279 
1280 /** updates bounds of each variable and the cutoff row in the nlpiproblem */
1282  SCIP* scip, /**< SCIP data structure */
1283  SCIP_NLPI* nlpi, /**< interface to NLP solver */
1284  SCIP_NLPIPROBLEM* nlpiprob, /**< nlpi problem representing the convex NLP relaxation */
1285  SCIP_HASHMAP* var2nlpiidx, /**< mapping between variables and nlpi indices */
1286  SCIP_VAR** nlpivars, /**< array containing all variables of the nlpi */
1287  int nlpinvars, /**< total number of nlpi variables */
1288  SCIP_Real cutoffbound /**< new cutoff bound */
1289  )
1290 {
1291  SCIP_Real* lbs;
1292  SCIP_Real* ubs;
1293  SCIP_Real lhs;
1294  SCIP_Real rhs;
1295  int* inds;
1296  int i;
1297 
1298  SCIPdebugMsg(scip, "call SCIPupdateConvexNlpNlobbt()\n");
1299 
1300  /* update variable bounds */
1301  SCIP_CALL( SCIPallocBufferArray(scip, &lbs, nlpinvars) );
1302  SCIP_CALL( SCIPallocBufferArray(scip, &ubs, nlpinvars) );
1303  SCIP_CALL( SCIPallocBufferArray(scip, &inds, nlpinvars) );
1304 
1305  for( i = 0; i < nlpinvars; ++i )
1306  {
1307  assert(nlpivars[i] != NULL);
1308  assert(SCIPhashmapExists(var2nlpiidx, (void*)nlpivars[i]));
1309 
1310  lbs[i] = SCIPvarGetLbLocal(nlpivars[i]);
1311  ubs[i] = SCIPvarGetUbLocal(nlpivars[i]);
1312  inds[i] = SCIPhashmapGetImageInt(var2nlpiidx, (void*)nlpivars[i]);
1313  assert(inds[i] >= 0 && inds[i] < nlpinvars);
1314  }
1315 
1316  SCIP_CALL( SCIPnlpiChgVarBounds(nlpi, nlpiprob, nlpinvars, inds, lbs, ubs) );
1317 
1318  SCIPfreeBufferArray(scip, &inds);
1319  SCIPfreeBufferArray(scip, &ubs);
1320  SCIPfreeBufferArray(scip, &lbs);
1321 
1322  /* update cutoff row */
1323  lhs = -SCIPinfinity(scip);
1324  rhs = cutoffbound;
1325  i = 0;
1326 
1327  SCIP_CALL( SCIPnlpiChgConsSides(nlpi, nlpiprob, 1, &i, &lhs, &rhs) );
1328 
1329  return SCIP_OKAY;
1330 }
1331 
1332 /** adds linear rows to the NLP relaxation */
1334  SCIP* scip, /**< SCIP data structure */
1335  SCIP_NLPI* nlpi, /**< interface to NLP solver */
1336  SCIP_NLPIPROBLEM* nlpiprob, /**< nlpi problem */
1337  SCIP_HASHMAP* var2idx, /**< empty hash map to store mapping between variables and indices in nlpi
1338  * problem */
1339  SCIP_ROW** rows, /**< rows to add */
1340  int nrows /**< total number of rows to add */
1341  )
1342 {
1343  const char** names;
1344  SCIP_Real* lhss;
1345  SCIP_Real* rhss;
1346  SCIP_Real** linvals;
1347  int** lininds;
1348  int* nlininds;
1349  int i;
1350 
1351  assert(nlpi != NULL);
1352  assert(nlpiprob != NULL);
1353  assert(var2idx != NULL);
1354  assert(nrows == 0 || rows != NULL);
1355 
1356  SCIPdebugMsg(scip, "call SCIPaddConvexNlpRowsNlobbt() with %d rows\n", nrows);
1357 
1358  if( nrows <= 0 )
1359  return SCIP_OKAY;
1360 
1361  SCIP_CALL( SCIPallocBufferArray(scip, &names, nrows) );
1362  SCIP_CALL( SCIPallocBufferArray(scip, &lhss, nrows) );
1363  SCIP_CALL( SCIPallocBufferArray(scip, &rhss, nrows) );
1364  SCIP_CALL( SCIPallocBufferArray(scip, &linvals, nrows) );
1365  SCIP_CALL( SCIPallocBufferArray(scip, &lininds, nrows) );
1366  SCIP_CALL( SCIPallocBufferArray(scip, &nlininds, nrows) );
1367 
1368  for( i = 0; i < nrows; ++i )
1369  {
1370  int k;
1371 
1372  assert(rows[i] != NULL);
1373  assert(SCIProwGetNNonz(rows[i]) <= SCIPgetNVars(scip));
1374 
1375  names[i] = SCIProwGetName(rows[i]);
1376  lhss[i] = SCIProwGetLhs(rows[i]) - SCIProwGetConstant(rows[i]);
1377  rhss[i] = SCIProwGetRhs(rows[i]) - SCIProwGetConstant(rows[i]);
1378  nlininds[i] = SCIProwGetNNonz(rows[i]);
1379  linvals[i] = SCIProwGetVals(rows[i]);
1380  lininds[i] = NULL;
1381 
1382  SCIP_CALL( SCIPallocBufferArray(scip, &lininds[i], SCIProwGetNNonz(rows[i])) ); /*lint !e866*/
1383 
1384  for( k = 0; k < SCIProwGetNNonz(rows[i]); ++k )
1385  {
1386  SCIP_VAR* var;
1387 
1388  var = SCIPcolGetVar(SCIProwGetCols(rows[i])[k]);
1389  assert(var != NULL);
1390  assert(SCIPhashmapExists(var2idx, (void*)var));
1391 
1392  lininds[i][k] = SCIPhashmapGetImageInt(var2idx, (void*)var);
1393  assert(lininds[i][k] >= 0 && lininds[i][k] < SCIPgetNVars(scip));
1394  }
1395  }
1396 
1397  /* pass all linear rows to the nlpi */
1398  SCIP_CALL( SCIPnlpiAddConstraints(nlpi, nlpiprob, nrows, lhss, rhss, nlininds, lininds, linvals, NULL,
1399  NULL, NULL, NULL, names) );
1400 
1401  /* free memory */
1402  for( i = nrows - 1; i >= 0; --i )
1403  {
1404  SCIPfreeBufferArray(scip, &lininds[i]);
1405  }
1406  SCIPfreeBufferArray(scip, &nlininds);
1407  SCIPfreeBufferArray(scip, &lininds);
1408  SCIPfreeBufferArray(scip, &linvals);
1409  SCIPfreeBufferArray(scip, &rhss);
1410  SCIPfreeBufferArray(scip, &lhss);
1411  SCIPfreeBufferArray(scip, &names);
1412 
1413  return SCIP_OKAY;
1414 }
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPnlpiAddVars(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nvars, const SCIP_Real *lbs, const SCIP_Real *ubs, const char **varnames)
Definition: nlpi.c:250
#define NULL
Definition: def.h:253
SCIP_EXPRTREE * SCIPnlrowGetExprtree(SCIP_NLROW *nlrow)
Definition: nlp.c:3364
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPquadprecSumQD(r, a, b)
Definition: dbldblarith.h:53
public methods for memory management
#define SQR(x)
Definition: def.h:205
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:16887
internal methods for NLPI solver interfaces
#define RESTRICT
Definition: def.h:265
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3009
#define SCIPquadprecSquareQ(r, a)
Definition: dbldblarith.h:59
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:16932
#define SCIPquadprecProdQQ(r, a, b)
Definition: dbldblarith.h:57
SCIP_RETCODE SCIPnlpiChgVarBounds(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nvars, const int *indices, const SCIP_Real *lbs, const SCIP_Real *ubs)
Definition: nlpi.c:325
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1987
#define FALSE
Definition: def.h:73
#define EPSEQ(x, y, eps)
Definition: def.h:189
SCIP_EXPORT SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17200
#define TRUE
Definition: def.h:72
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
public methods for problem variables
static void computeBilinEnvelope2(SCIP *scip, SCIP_Real x, SCIP_Real y, SCIP_Real mi, SCIP_Real qi, SCIP_Real mj, SCIP_Real qj, SCIP_Real *RESTRICT xi, SCIP_Real *RESTRICT yi, SCIP_Real *RESTRICT xj, SCIP_Real *RESTRICT yj, SCIP_Real *RESTRICT xcoef, SCIP_Real *RESTRICT ycoef, SCIP_Real *RESTRICT constant)
#define QUAD_SCALE(x, a)
Definition: dbldblarith.h:41
void SCIPcomputeBilinEnvelope1(SCIP *scip, SCIP_Real bilincoef, SCIP_Real lbx, SCIP_Real ubx, SCIP_Real refpointx, SCIP_Real lby, SCIP_Real uby, SCIP_Real refpointy, SCIP_Bool overestimate, SCIP_Real xcoef, SCIP_Real ycoef, SCIP_Real constant, SCIP_Real *RESTRICT lincoefx, SCIP_Real *RESTRICT lincoefy, SCIP_Real *RESTRICT linconstant, SCIP_Bool *RESTRICT success)
void SCIPaddSquareLinearization(SCIP *scip, SCIP_Real sqrcoef, SCIP_Real refpoint, SCIP_Bool isint, SCIP_Real *lincoef, SCIP_Real *linconstant, SCIP_Bool *success)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:123
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
#define SCIPdebugMsg
Definition: scip_message.h:69
#define SCIPquadprecDivQD(r, a, b)
Definition: dbldblarith.h:56
SCIP_VAR ** x
Definition: circlepacking.c:54
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:40
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
public methods for numerical tolerances
SCIP_RETCODE SCIPnlpiSetObjective(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nlins, const int *lininds, const SCIP_Real *linvals, int nquadelems, const SCIP_QUADELEM *quadelems, const int *exprvaridxs, const SCIP_EXPRTREE *exprtree, const SCIP_Real constant)
Definition: nlpi.c:300
public methods for expressions, expression trees, expression graphs, and related stuff ...
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3098
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3240
SCIP_Real coef
Definition: type_expr.h:104
void SCIPaddBilinLinearization(SCIP *scip, SCIP_Real bilincoef, SCIP_Real refpointx, SCIP_Real refpointy, SCIP_Real *lincoefx, SCIP_Real *lincoefy, SCIP_Real *linconstant, SCIP_Bool *success)
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_EXPORT const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16738
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:16912
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
public methods for nonlinear functions
void SCIPcomputeBilinEnvelope2(SCIP *scip, SCIP_Real bilincoef, SCIP_Real lbx, SCIP_Real ubx, SCIP_Real refpointx, SCIP_Real lby, SCIP_Real uby, SCIP_Real refpointy, SCIP_Bool overestimate, SCIP_Real xcoef1, SCIP_Real ycoef1, SCIP_Real constant1, SCIP_Real xcoef2, SCIP_Real ycoef2, SCIP_Real constant2, SCIP_Real *RESTRICT lincoefx, SCIP_Real *RESTRICT lincoefy, SCIP_Real *RESTRICT linconstant, SCIP_Bool *RESTRICT success)
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1942
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:16922
#define QUAD(x)
Definition: dbldblarith.h:38
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
int SCIPnlrowGetNQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3323
#define REALABS(x)
Definition: def.h:188
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8613
SCIP_RETCODE SCIPcreateNlpiProb(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLROW **nlrows, int nnlrows, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2idx, SCIP_Real *nlscore, SCIP_Real cutoffbound, SCIP_Bool setobj, SCIP_Bool onlyconvex)
#define SCIP_CALL(x)
Definition: def.h:365
void SCIPswapInts(int *value1, int *value2)
Definition: misc.c:9865
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3246
SCIP_QUADELEM * SCIPnlrowGetQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3333
#define SCIPquadprecProdDD(r, a, b)
Definition: dbldblarith.h:49
public methods for NLP management
#define SCIPquadprecSqrtQ(r, a)
Definition: dbldblarith.h:62
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition: nlp.c:3394
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:111
SCIP_Real SCIPinfinity(SCIP *scip)
public data structures and miscellaneous methods
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3384
#define SCIP_Bool
Definition: def.h:70
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:16966
#define MIN(x, y)
Definition: def.h:223
public methods for LP management
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_VAR ** SCIPexprtreeGetVars(SCIP_EXPRTREE *tree)
Definition: nlp.c:102
#define SCIPquadprecProdQD(r, a, b)
Definition: dbldblarith.h:54
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3374
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition: nlp.c:3266
SCIP_EXPORT SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17408
#define SCIPquadprecSumQQ(r, a, b)
Definition: dbldblarith.h:58
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:16736
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_EXPORT SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17418
#define SQRT(x)
Definition: def.h:206
#define SCIPquadprecDivDD(r, a, b)
Definition: dbldblarith.h:52
#define MAX(x, y)
Definition: def.h:222
SCIP_RETCODE SCIPnlpiChgConsSides(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, int nconss, const int *indices, const SCIP_Real *lhss, const SCIP_Real *rhss)
Definition: nlpi.c:343
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPupdateNlpiProb(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2nlpiidx, SCIP_VAR **nlpivars, int nlpinvars, SCIP_Real cutoffbound)
type definitions for expressions and expression trees
public methods for message output
const char * SCIPnlrowGetName(SCIP_NLROW *nlrow)
Definition: nlp.c:3413
#define SCIP_Real
Definition: def.h:164
SCIP_VAR ** y
Definition: circlepacking.c:55
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17025
public methods for message handling
#define SCIP_INVALID
Definition: def.h:184
#define SCIPquadprecSumDD(r, a, b)
Definition: dbldblarith.h:51
SCIP_VAR ** SCIPnlrowGetQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3286
SCIP_Real SCIPnlrowGetConstant(SCIP_NLROW *nlrow)
Definition: nlp.c:3236
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:16976
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3256
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:120
void SCIPaddBilinMcCormick(SCIP *scip, SCIP_Real bilincoef, SCIP_Real lbx, SCIP_Real ubx, SCIP_Real refpointx, SCIP_Real lby, SCIP_Real uby, SCIP_Real refpointy, SCIP_Bool overestimate, SCIP_Real *lincoefx, SCIP_Real *lincoefy, SCIP_Real *linconstant, SCIP_Bool *success)
public methods for global and local (sub)problems
#define SCIPquadprecDivQQ(r, a, b)
Definition: dbldblarith.h:60
void SCIPaddSquareSecant(SCIP *scip, SCIP_Real sqrcoef, SCIP_Real lb, SCIP_Real ub, SCIP_Real refpoint, SCIP_Real *lincoef, SCIP_Real *linconstant, SCIP_Bool *success)
SCIP_RETCODE SCIPaddNlpiProbRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2idx, SCIP_ROW **rows, int nrows)
memory allocation routines