Scippy

SCIP

Solving Constraint Integer Programs

sepa_gauge.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file sepa_gauge.c
17  * @brief gauge separator
18  * @author Felipe Serrano
19  *
20  * @todo should separator only be run when SCIPallColsInLP is true?
21  * @todo add SCIPisStopped(scip) to the condition of time consuming loops
22  * @todo check if it makes sense to implement the copy callback
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 
30 #include "scip/sepa_gauge.h"
31 #include "nlpi/exprinterpret.h"
32 #include "nlpi/nlpi.h"
33 #include "nlpi/nlpioracle.h"
34 #include "nlpi/nlpi_ipopt.h"
35 
36 
37 #define SEPA_NAME "gauge"
38 #define SEPA_DESC "gauge separator"
39 #define SEPA_PRIORITY 0
40 #define SEPA_FREQ -1
41 #define SEPA_MAXBOUNDDIST 1.0
42 #define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
43 #define SEPA_DELAY FALSE /**< should separation method be delayed, if other separators found cuts? */
44 
45 #define VIOLATIONFAC 100 /* constraints regarded as violated when violation > VIOLATIONFAC*SCIPfeastol */
46 #define MAX_ITER 75 /* maximum number of iterations for the line search */
47 
48 #define DEFAULT_NLPTIMELIMIT 0.0 /**< default time limit of NLP solver; 0.0 for no limit */
49 #define DEFAULT_NLPITERLIM 1000 /**< default NLP iteration limit */
50 
51 #define NLPFEASFAC 1e-1/**< NLP feasibility tolerance = NLPFEASFAC * SCIP's feasibility tolerance */
52 #define NLPVERBOSITY 0 /**< NLP solver verbosity */
53 
54 #define INTERIOROBJVARLB -100 /**< lower bound of the objective variable when computing interior point */
55 /*
56  * Data structures
57  */
58 
59 /** side that makes a nlrow convex */
61 {
62  LHS = 0, /**< left hand side */
63  RHS = 1 /**< right hand side */
64 };
65 typedef enum ConvexSide CONVEXSIDE;
66 
67 /** position of a point */
69 {
70  INTERIOR = 0, /**< point is in the interior of the region */
71  BOUNDARY = 1, /**< point is in the boundary of the region */
72  EXTERIOR = 2 /**< point is in the exterior of the region */
73 };
74 typedef enum Position POSITION;
75 
76 /** separator data */
77 struct SCIP_SepaData
78 {
79  SCIP_NLROW** nlrows; /**< stores convex nlrows */
80  CONVEXSIDE* convexsides; /**< which sides make the nlrows convex */
81  int* nlrowsidx; /**< indices of nlrows that violate the current lp solution */
82  int nnlrowsidx; /**< total number of convex nonlinear nlrows that violate the current lp solution */
83  int nnlrows; /**< total number of convex nonlinear nlrows */
84  int nlrowssize; /**< memory allocated for nlrows, convexsides and nlrowsidx */
85 
86  SCIP_Bool isintsolavailable; /**< do we have an interior point available? */
87  SCIP_Bool skipsepa; /**< whether separator should be skipped */
88  SCIP_SOL* intsol; /**< stores interior point */
89 
90  SCIP_EXPRINT* exprinterpreter; /**< expression interpreter to compute gradients */
91 
92  int ncuts; /**< number of cuts generated */
93 
94  /* parameters */
95  SCIP_Real nlptimelimit; /**< time limit of NLP solver; 0.0 for no limit */
96  int nlpiterlimit; /**< iteration limit of NLP solver; 0 for no limit */
97 };
98 
99 /*
100  * Local methods
101  */
102 
103 /** stores, from the constraints represented by nlrows, the nonlinear convex ones in sepadata */
104 static
106  SCIP* scip, /**< SCIP data structure */
107  SCIP_SEPADATA* sepadata, /**< separator data */
108  SCIP_NLROW** nlrows, /**< nlrows from which to store convex ones */
109  int nnlrows /**< number of nlrows */
110  )
111 {
112  int i;
113 
114  assert(scip != NULL);
115  assert(sepadata != NULL);
116  assert(nlrows != NULL);
117  assert(nnlrows > 0);
118 
119  SCIPdebugMsg(scip, "storing convex nlrows\n");
120 
121  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->nlrows), nnlrows) );
122  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->convexsides), nnlrows) );
123  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->nlrowsidx), nnlrows) );
124  sepadata->nlrowssize = nnlrows;
125 
126  sepadata->nnlrows = 0;
127  for( i = 0; i < nnlrows; ++i )
128  {
129  SCIP_NLROW* nlrow;
130 
131  nlrow = nlrows[i];
132  assert(nlrow != NULL);
133 
134  /* linear case */
136  (SCIPnlrowGetNQuadElems(nlrow) == 0 && SCIPnlrowGetExprtree(nlrow) == NULL) )
137  continue;
138 
139  /* nonlinear case */
141  {
142  sepadata->convexsides[sepadata->nnlrows] = RHS;
143  sepadata->nlrows[sepadata->nnlrows] = nlrow;
144  ++(sepadata->nnlrows);
145  }
146  else if( !SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)) && SCIPnlrowGetCurvature(nlrow) == SCIP_EXPRCURV_CONCAVE )
147  {
148  sepadata->convexsides[sepadata->nnlrows] = LHS;
149  sepadata->nlrows[sepadata->nnlrows] = nlrow;
150  ++(sepadata->nnlrows);
151  }
152  }
153 
154  return SCIP_OKAY;
155 }
156 
157 /** computes an interior point of a convex NLP relaxation; builds the convex relaxation, modifies it to find an interior
158  * point, solves it and frees it; more details in @ref sepa_gauge.h
159  *
160  * @note the method also counts the number of nonlinear convex constraints and if there are < 2, then the convex
161  * relaxation is not interesting and the separator will not run again
162  */
163 static
165  SCIP* scip, /**< SCIP data structure */
166  SCIP_SEPADATA* sepadata /**< separator data */
167  )
168 {
169  SCIP_NLPIORACLE* nlpioracle;
170  SCIP_NLPIPROBLEM* nlpiprob;
171  SCIP_NLPI* nlpi;
172  SCIP_HASHMAP* var2nlpiidx;
173  SCIP_Real timelimit;
174  SCIP_Real objvarlb;
175  SCIP_Real minusone;
176  SCIP_Real one;
177  int nconvexnlrows;
178  int iterlimit;
179  int objvaridx;
180  int nconss;
181  int nvars;
182  int i;
183 
184  assert(scip != NULL);
185  assert(sepadata != NULL);
186  assert(!sepadata->skipsepa);
187 
188  SCIPdebugMsg(scip, "Computing interior point\n");
189 
190  /* create convex relaxation NLP */
191  assert(SCIPgetNNlpis(scip) > 0);
192 
193  nlpi = SCIPgetNlpis(scip)[0];
194  assert(nlpi != NULL);
195 
196  nvars = SCIPgetNVars(scip);
197  SCIP_CALL( SCIPnlpiCreateProblem(nlpi, &nlpiprob, "gauge-interiorpoint-nlp") );
198  SCIP_CALL( SCIPhashmapCreate(&var2nlpiidx, SCIPblkmem(scip), nvars) );
199  SCIP_CALL( SCIPcreateNlpiProb(scip, nlpi, SCIPgetNLPNlRows(scip), SCIPgetNNLPNlRows(scip), nlpiprob, var2nlpiidx,
200  NULL, SCIPgetCutoffbound(scip), FALSE, TRUE) );
201 
202  /* add objective variable; the problem is \min t, s.t. g(x) <= t, l(x) <= 0, where g are nonlinear and l linear */
203  objvaridx = nvars;
204  objvarlb = INTERIOROBJVARLB;
205  one = 1.0;
206  SCIP_CALL( SCIPnlpiAddVars(nlpi, nlpiprob, 1, &objvarlb, NULL, NULL) );
207  SCIP_CALL( SCIPnlpiSetObjective(nlpi, nlpiprob, 1, &objvaridx, &one, 0, NULL, NULL, NULL, 0.0) );
208 
209  /* add objective variables to constraints; for this we need to get nlpi oracle to have access to number of
210  * constraints and which constraints are nonlinear
211  */
212  /* @todo: this code is only valid when using IPOPT and needs to be changed when new NLP solvers get interfaced */
213  assert(strcmp(SCIPnlpiGetName(nlpi), "ipopt") == 0);
214  nlpioracle = (SCIP_NLPIORACLE *)SCIPgetNlpiOracleIpopt(nlpiprob);
215  assert(nlpioracle != NULL);
216  assert(SCIPnlpiOracleGetNVars(nlpioracle) == objvaridx + 1);
217 
218  minusone = -1.0;
219  nconvexnlrows = 0;
220  nconss = SCIPnlpiOracleGetNConstraints(nlpioracle);
221  for( i = 0; i < nconss; i++ )
222  {
223  if( SCIPnlpiOracleGetConstraintDegree(nlpioracle, i) > 1 )
224  {
225  SCIP_CALL( SCIPnlpiChgLinearCoefs(nlpi, nlpiprob, i, 1, &objvaridx, &minusone) );
226  ++nconvexnlrows;
227  }
228  }
230 
231  /* check if convex relaxation is interesting */
232  if( nconvexnlrows < 2 )
233  {
234  SCIPdebugMsg(scip, "convex relaxation is not interesting, only %d nonlinear convex rows; abort\n", nconvexnlrows);
235  sepadata->skipsepa = TRUE;
236  goto CLEANUP;
237  }
238 
239  /* add linear rows */
240  SCIP_CALL( SCIPaddNlpiProbRows(scip, nlpi, nlpiprob, var2nlpiidx, SCIPgetLPRows(scip), SCIPgetNLPRows(scip)) );
241 
242  /* set parameters in nlpi; time and iterations limit, tolerance, verbosity; for time limit, get time limit of scip;
243  * if scip doesn't have much time left, don't run separator. otherwise, timelimit is the minimum between whats left
244  * for scip and the timelimit setting
245  */
246  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
247  if( !SCIPisInfinity(scip, timelimit) )
248  {
249  timelimit -= SCIPgetSolvingTime(scip);
250  if( timelimit <= 1.0 )
251  {
252  SCIPdebugMsg(scip, "skip NLP solve; no time left\n");
253  sepadata->skipsepa = TRUE;
254  goto CLEANUP;
255  }
256  }
257  if( sepadata->nlptimelimit > 0.0 )
258  timelimit = MIN(sepadata->nlptimelimit, timelimit);
259  SCIP_CALL( SCIPnlpiSetRealPar(nlpi, nlpiprob, SCIP_NLPPAR_TILIM, timelimit) );
260 
261  iterlimit = sepadata->nlpiterlimit > 0 ? sepadata->nlpiterlimit : INT_MAX;
262  SCIP_CALL( SCIPnlpiSetIntPar(nlpi, nlpiprob, SCIP_NLPPAR_ITLIM, iterlimit) );
265 
266  /* compute interior point */
267  SCIPdebugMsg(scip, "starting interior point computation\n");
268  SCIP_CALL( SCIPnlpiSolve(nlpi, nlpiprob) );
269  SCIPdebugMsg(scip, "finish interior point computation\n");
270 
271 #ifdef SCIP_DEBUG
272  {
273  SCIP_NLPSTATISTICS* nlpstatistics;
274 
275  /* get statistics */
276  SCIP_CALL( SCIPnlpStatisticsCreate(&nlpstatistics) );
277  SCIP_CALL( SCIPnlpiGetStatistics(nlpi, nlpiprob, nlpstatistics) );
278 
279  SCIPdebugMsg(scip, "nlpi took iters %d, time %g searching for an find interior point: solstat %d\n",
280  SCIPnlpStatisticsGetNIterations(nlpstatistics), SCIPnlpStatisticsGetTotalTime(nlpstatistics),
281  SCIPnlpiGetSolstat(nlpi, nlpiprob));
282 
283  SCIPnlpStatisticsFree(&nlpstatistics);
284  }
285 #endif
286 
287  if( SCIPnlpiGetSolstat(nlpi, nlpiprob) <= SCIP_NLPSOLSTAT_FEASIBLE )
288  {
289  SCIP_Real* nlpisol;
290 
291  SCIP_CALL( SCIPnlpiGetSolution(nlpi, nlpiprob, &nlpisol, NULL, NULL, NULL) );
292 
293  assert(nlpisol != NULL);
294  SCIPdebugMsg(scip, "NLP solved: sol found has objvalue = %g\n", nlpisol[objvaridx]);
295 
296  /* if we found an interior point store it */
297  if( SCIPisFeasNegative(scip, nlpisol[objvaridx]) )
298  {
299  SCIPdebugMsg(scip, "Interior point found!, storing it\n");
300  SCIP_CALL( SCIPcreateSol(scip, &sepadata->intsol, NULL) );
301  for( i = 0; i < nvars; i ++ )
302  {
303  SCIP_VAR* var;
304 
305  var = SCIPgetVars(scip)[i];
306  assert(SCIPhashmapExists(var2nlpiidx, (void*)var) );
307 
308  /* @todo: filter zero? */
309  SCIP_CALL( SCIPsetSolVal(scip, sepadata->intsol, var,
310  nlpisol[(int)(size_t)SCIPhashmapGetImage(var2nlpiidx, (void *)var)]) );
311  }
312 
313  sepadata->isintsolavailable = TRUE;
314  }
315  else
316  {
317  SCIPdebugMsg(scip, "We got a feasible point but not interior (objval: %g)\n", nlpisol[objvaridx]);
318  sepadata->skipsepa = TRUE;
319  }
320  }
321  else
322  {
323  SCIPdebugMsg(scip, "We couldn't get an interior point (stat: %d)\n", SCIPnlpiGetSolstat(nlpi, nlpiprob));
324  sepadata->skipsepa = TRUE;
325  }
326 
327 CLEANUP:
328  /* free memory */
329  SCIPhashmapFree(&var2nlpiidx);
330  SCIP_CALL( SCIPnlpiFreeProblem(nlpi, &nlpiprob) );
331 
332  return SCIP_OKAY;
333 }
334 
335 
336 /** find whether point is in the interior, at the boundary or in the exterior of the region described by the
337  * intersection of nlrows[i] <= rhs if convexsides[i] = RHS or lhs <= nlrows[i] if convexsides[i] = LHS
338  * @note: point corresponds to a convex combination between the lp solution and the interior point
339  */
340 static
342  SCIP* scip, /**< SCIP data structure */
343  SCIP_NLROW** nlrows, /**< nlrows defining the region */
344  int* nlrowsidx, /**< indices of nlrows defining the region */
345  int nnlrowsidx, /**< number of nlrows indices */
346  CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
347  SCIP_SOL* point, /**< point for which we want to know its position */
348  POSITION* position /**< buffer to store position of sol */
349  )
350 {
351  int i;
352 
353  assert(scip != NULL);
354  assert(nlrows != NULL);
355  assert(convexsides != NULL);
356  assert(nnlrowsidx > 0);
357  assert(point != NULL);
358  assert(position != NULL);
359 
360  *position = INTERIOR;
361  for( i = 0; i < nnlrowsidx; i++ )
362  {
363  SCIP_NLROW* nlrow;
364  SCIP_Real activity;
365  CONVEXSIDE convexside;
366 
367  nlrow = nlrows[nlrowsidx[i]];
368  convexside = convexsides[nlrowsidx[i]];
369 
370  /* compute activity of nlrow at point */
371  SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, point, &activity) );
372 
373  if( convexside == RHS )
374  {
375  assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
376 
377  /* if nlrow <= rhs is violated, then we are in the exterior */
378  if( SCIPisFeasGT(scip, activity, SCIPnlrowGetRhs(nlrow)) )
379  {
380  *position = EXTERIOR;
381  SCIPdebugMsg(scip, "exterior because cons <%s> has activity %g. rhs: %g\n", SCIPnlrowGetName(nlrow),
382  activity, SCIPnlrowGetRhs(nlrow));
383  SCIPdebug( SCIPprintNlRow(scip, nlrow, NULL) );
384 
385  return SCIP_OKAY;
386  }
387 
388  /* if nlrow(point) == rhs, then we are currently at the boundary */
389  if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow)) )
390  *position = BOUNDARY;
391  }
392  else
393  {
394  assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
395  assert(convexside == LHS);
396 
397  /* if lhs <= nlrow is violated, then we are in the exterior */
398  if( SCIPisFeasLT(scip, activity, SCIPnlrowGetLhs(nlrow)) )
399  {
400  *position = EXTERIOR;
401  return SCIP_OKAY;
402  }
403 
404  /* if lhs == nlrow(point), then we are currently at the boundary */
405  if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow)) )
406  *position = BOUNDARY;
407  }
408  }
409 
410  return SCIP_OKAY;
411 }
412 
413 
414 /** returns, in convexcomb, the convex combination
415  * \f$ \lambda \f$ endpoint + (1 - \f$ lambda \f$) startpoint = startpoint + \f$ \lambda \f$ (endpoint - tosepasol) */
416 static
418  SCIP* scip, /**< SCIP data structure */
419  SCIP_Real lambda, /**< convex combination multiplier */
420  SCIP_SOL* startpoint, /**< point corresponding to \f$ \lambda = 0 \f$ */
421  SCIP_SOL* endpoint, /**< point corresponding to \f$ \lambda = 1 \f$ */
422  SCIP_SOL* convexcomb /**< solution to store convex combination of intsol and tosepasol */
423  )
424 {
425  SCIP_VAR** vars;
426  int nvars;
427  int i;
428 
429  assert(scip != NULL);
430  assert(startpoint != NULL);
431  assert(endpoint != NULL);
432  assert(convexcomb != NULL);
433 
434  vars = SCIPgetVars(scip);
435  nvars = SCIPgetNVars(scip);
436 
437  for( i = 0; i < nvars; i++ )
438  {
439  SCIP_Real val;
440  SCIP_VAR* var;
441 
442  var = vars[i];
443  val = lambda * SCIPgetSolVal(scip, endpoint, var) + (1.0 - lambda) * SCIPgetSolVal(scip, startpoint, var);
444 
445  if( !SCIPisZero(scip, val) )
446  {
447  SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, val) );
448  }
449  else
450  {
451  SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, 0.0) );
452  }
453  }
454 
455  return SCIP_OKAY;
456 }
457 
458 
459 /** performs binary search to find the point belonging to the segment [intsol, tosepasol] that intersects the boundary
460  * of the region described by the intersection of nlrows[i] <= rhs if convexsides[i] = RHS or lhs <= nlrows[i] if not,
461  * for i in nlrowsidx
462  */
463 static
465  SCIP* scip, /**< SCIP data structure */
466  SCIP_NLROW** nlrows, /**< nlrows defining the region */
467  int* nlrowsidx, /**< indices of nlrows defining the region */
468  int nnlrowsidx, /**< number of nlrows indices */
469  CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
470  SCIP_SOL* intsol, /**< point acting as 'interior point' */
471  SCIP_SOL* tosepasol, /**< solution that should be separated */
472  SCIP_SOL* sol, /**< convex combination of intsol and lpsol */
473  POSITION* position /**< buffer to store position of sol */
474  )
475 {
476  SCIP_Real lb;
477  SCIP_Real ub;
478  int i;
479 
480  assert(scip != NULL);
481  assert(nlrows != NULL);
482  assert(nlrowsidx != NULL);
483  assert(convexsides != NULL);
484  assert(intsol != NULL);
485  assert(tosepasol != NULL);
486  assert(sol != NULL);
487  assert(position != NULL);
488 
489  SCIPdebugMsg(scip, "starting binary search\n");
490  lb = 0.0; /* corresponds to intsol */
491  ub = 1.0; /* corresponds to tosepasol */
492  for( i = 0; i < MAX_ITER; i++ )
493  {
494  /* sol = (ub+lb)/2 * lpsol + (1 - (ub+lb)/2) * intsol */
495  SCIP_CALL( buildConvexCombination(scip, (ub + lb)/2.0, intsol, tosepasol, sol) );
496 
497  /* find poisition of point: boundary, interior, exterior */
498  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, position) );
499  SCIPdebugMsg(scip, "Position: %d, lambda: %g\n", position, (ub + lb)/2.0);
500 
501  switch( *position )
502  {
503  case BOUNDARY:
504  SCIPdebugMsg(scip, "Done\n");
505  return SCIP_OKAY;
506 
507  case INTERIOR:
508  /* want to be closer to tosepasol */
509  lb = (ub + lb)/2.0;
510  break;
511 
512  case EXTERIOR:
513  /* want to be closer to intsol */
514  ub = (ub + lb)/2.0;
515  break;
516  }
517  }
518  SCIPdebugMsg(scip, "Done\n");
519  return SCIP_OKAY;
520 }
521 
522 
523 /** computes gradient of exprtree at sol */
524 static
526  SCIP* scip, /**< SCIP data structure */
527  SCIP_EXPRINT* exprint, /**< expressions interpreter */
528  SCIP_SOL* sol, /**< point where we compute gradient */
529  SCIP_EXPRTREE* exprtree, /**< exprtree for which we compute the gradient */
530  SCIP_Real* grad /**< buffer to store the gradient */
531  )
532 {
533  SCIP_Real* x;
534  SCIP_Real val;
535  int nvars;
536  int i;
537 
538  assert(scip != NULL);
539  assert(exprint != NULL);
540  assert(sol != NULL);
541  assert(exprtree != NULL);
542  assert(grad != NULL);
543 
544  nvars = SCIPexprtreeGetNVars(exprtree);
545  assert(nvars > 0);
546 
547  SCIP_CALL( SCIPallocBufferArray(scip, &x, nvars) );
548 
549  /* compile expression exprtree, if not done before */
550  if( SCIPexprtreeGetInterpreterData(exprtree) == NULL )
551  {
552  SCIP_CALL( SCIPexprintCompile(exprint, exprtree) );
553  }
554 
555  for( i = 0; i < nvars; ++i )
556  {
557  x[i] = SCIPgetSolVal(scip, sol, SCIPexprtreeGetVars(exprtree)[i]);
558  }
559 
560  SCIP_CALL( SCIPexprintGrad(exprint, exprtree, x, TRUE, &val, grad) );
561 
562  /*SCIPdebug( for( i = 0; i < nvars; ++i ) printf("%e [%s]\n", grad[i], SCIPvarGetName(SCIPexprtreeGetVars(exprtree)[i])) );*/
563 
564  SCIPfreeBufferArray(scip, &x);
565 
566  return SCIP_OKAY;
567 }
568 
569 
570 /** computes gradient cut (linearization) of nlrow at sol */
571 static
573  SCIP* scip, /**< SCIP data structure */
574  SCIP_SOL* sol, /**< point used to construct gradient cut (x_0) */
575  SCIP_EXPRINT* exprint, /**< expression interpreter */
576  SCIP_NLROW* nlrow, /**< constraint */
577  CONVEXSIDE convexside, /**< whether we use rhs or lhs of nlrow */
578  SCIP_ROW* row /**< storage for cut */
579  )
580 {
581  SCIP_Real activity;
582  SCIP_Real gradx0; /* <grad f(x_0), x_0> */
583  int i;
584 
585  assert(scip != NULL);
586  assert(exprint != NULL);
587  assert(nlrow != NULL);
588  assert(row != NULL);
589 
590  gradx0 = 0.0;
591 
592  /* an nlrow has a linear part, quadratic part and expression tree; ideally one would just build the gradient but we
593  * do not know if the different parts share variables or not, so we can't just build the gradient; for this reason
594  * we create the row right away and compute the gradients of each part independently and add them to the row; the
595  * row takes care to add coeffs corresponding to the same variable when they appear in different parts of the nlrow
596  */
597 
598  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
599 
600  /* linear part */
601  for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
602  {
603  gradx0 += SCIPgetSolVal(scip, sol, SCIPnlrowGetLinearVars(nlrow)[i]) * SCIPnlrowGetLinearCoefs(nlrow)[i];
604  SCIP_CALL( SCIPaddVarToRow(scip, row, SCIPnlrowGetLinearVars(nlrow)[i], SCIPnlrowGetLinearCoefs(nlrow)[i]) );
605  }
606 
607  /* quadratic part */
608  for( i = 0; i < SCIPnlrowGetNQuadElems(nlrow); i++ )
609  {
610  SCIP_VAR* var1;
611  SCIP_VAR* var2;
612  SCIP_Real grad1;
613  SCIP_Real grad2;
614  SCIP_Real solval1;
615  SCIP_Real solval2;
616 
617  var1 = SCIPnlrowGetQuadVars(nlrow)[SCIPnlrowGetQuadElems(nlrow)[i].idx1];
618  var2 = SCIPnlrowGetQuadVars(nlrow)[SCIPnlrowGetQuadElems(nlrow)[i].idx2];
619  solval1 = SCIPgetSolVal(scip, sol, var1);
620  solval2 = SCIPgetSolVal(scip, sol, var2);
621  grad1 = SCIPnlrowGetQuadElems(nlrow)[i].coef * solval2; /* note that solval2 is correct */
622  grad2 = SCIPnlrowGetQuadElems(nlrow)[i].coef * solval1;
623 
624  SCIP_CALL( SCIPaddVarToRow(scip, row, var1, grad1) );
625  SCIP_CALL( SCIPaddVarToRow(scip, row, var2, grad2) );
626 
627  gradx0 += grad1 * solval1 + grad2 * solval2;
628  }
629 
630  /* expression tree part */
631  {
632  SCIP_Real* grad;
633  SCIP_EXPRTREE* tree;
634 
635  tree = SCIPnlrowGetExprtree(nlrow);
636 
637  if( tree != NULL && SCIPexprtreeGetNVars(tree) > 0 )
638  {
639  SCIP_CALL( SCIPallocBufferArray(scip, &grad, SCIPexprtreeGetNVars(tree)) );
640 
641  SCIP_CALL( computeGradient(scip, exprint, sol, tree, grad) );
642 
643  for( i = 0; i < SCIPexprtreeGetNVars(tree); i++ )
644  {
645  gradx0 += grad[i] * SCIPgetSolVal(scip, sol, SCIPexprtreeGetVars(tree)[i]);
646  SCIP_CALL( SCIPaddVarToRow(scip, row, SCIPexprtreeGetVars(tree)[i], grad[i]) );
647  }
648 
649  SCIPfreeBufferArray(scip, &grad);
650  }
651  }
652 
653  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
654 
655 #ifdef CUT_DEBUG
656  SCIPdebugMsg(scip, "gradient: ");
657  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
658  SCIPdebugMsg(scip, "gradient dot x_0: %g\n", gradx0);
659 #endif
660 
661  /* gradient cut is f(x_0) - <grad f(x_0), x_0> + <grad f(x_0), x> <= rhs or >= lhs */
662  SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
663  if( convexside == RHS )
664  {
665  assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
666  SCIP_CALL( SCIPchgRowRhs(scip, row, SCIPnlrowGetRhs(nlrow) - activity + gradx0) );
667  }
668  else
669  {
670  assert(convexside == LHS);
671  assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
672  SCIP_CALL( SCIPchgRowLhs(scip, row, SCIPnlrowGetLhs(nlrow) - activity + gradx0) );
673  }
674 
675 #ifdef CUT_DEBUG
676  SCIPdebugMsg(scip, "gradient cut: ");
677  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
678 #endif
679 
680  return SCIP_OKAY;
681 }
682 
683 /** tries to generate gradient cuts at the point on the segment [intsol, tosepasol] that intersecs the boundary of the
684  * convex relaxation
685  * -# checks that the relative interior of the segment actually intersects the boundary
686  * (this check is needed since intsol is not necessarily an interior point)
687  * -# finds point on the boundary
688  * -# generates gradient cut at point on the boundary
689  */
690 static
692  SCIP* scip, /**< SCIP data structure */
693  SCIP_SEPA* sepa, /**< the cut separator itself */
694  SCIP_SOL* tosepasol, /**< solution that should be separated */
695  SCIP_RESULT* result /**< pointer to store the result of the separation call */
696  )
697 {
698  SCIP_SEPADATA* sepadata;
699  SCIP_NLROW** nlrows;
700  CONVEXSIDE* convexsides;
701  SCIP_SOL* sol;
702  SCIP_SOL* intsol;
703  POSITION position;
704  int* nlrowsidx;
705  int nnlrowsidx;
706  int i;
707 
708  assert(sepa != NULL);
709 
710  sepadata = SCIPsepaGetData(sepa);
711  assert(sepadata != NULL);
712 
713  intsol = sepadata->intsol;
714  nlrows = sepadata->nlrows;
715  nlrowsidx = sepadata->nlrowsidx;
716  nnlrowsidx = sepadata->nnlrowsidx;
717  convexsides = sepadata->convexsides;
718 
719  assert(intsol != NULL);
720  assert(nlrows != NULL);
721  assert(nlrowsidx != NULL);
722  assert(nnlrowsidx > 0);
723  assert(convexsides != NULL);
724 
725  /* to evaluate the nlrow one needs a solution */
726  SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
727 
728  /* don't separate if, under SCIP tolerances, only a slight perturbation of the interior point in the direction of
729  * tosepasol gives a point that is in the exterior */
730  SCIP_CALL( buildConvexCombination(scip, VIOLATIONFAC * SCIPfeastol(scip), intsol, tosepasol, sol) );
731  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
732 
733  if( position == EXTERIOR )
734  {
735 #ifdef SCIP_DEBUG
736  SCIPdebugMsg(scip, "segment joining intsol and tosepasol seems to be contained in the exterior of the region, can't separate\n");
737  /* move from intsol in the direction of -tosepasol to check if we are really tangent to the region */
738  SCIP_CALL( buildConvexCombination(scip, -1e-3, intsol, tosepasol, sol) );
739  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
740  if( position == EXTERIOR )
741  {
742  SCIPdebugMsg(scip, "line through intsol and tosepasol is tangent to region; can't separate\n");
743  }
744  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, &position) );
745  printf("Position of intsol is %s\n",
746  position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
747  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, tosepasol, &position) );
748  printf("Position of tosepasol is %s\n",
749  position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
750 
751  /* slightly move from intsol in the direction of +-tosepasol */
752  SCIP_CALL( buildConvexCombination(scip, 1e-5, intsol, tosepasol, sol) );
753  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
754  printf("Position of intsol + 0.00001(tosepasol - inisol) is %s\n",
755  position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
756  SCIPdebug( SCIPprintSol(scip, sol, NULL, FALSE) );
757 
758  SCIP_CALL( buildConvexCombination(scip, -1e-5, intsol, tosepasol, sol) );
759  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
760  printf("Position of intsol - 0.00001(tosepasol - inisol) is %s\n",
761  position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
762  SCIPdebug( SCIPprintSol(scip, sol, NULL, FALSE) );
763 #endif
764  *result = SCIP_DIDNOTFIND;
765  goto CLEANUP;
766  }
767 
768  /* find point on boundary */
769  if( position != BOUNDARY )
770  {
771  SCIP_CALL( findBoundaryPoint(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, tosepasol, sol,
772  &position) );
773 
774  /* if MAX_ITER weren't enough to find a point in the boundary we don't separate */
775  if( position != BOUNDARY )
776  {
777  SCIPdebugMsg(scip, "couldn't find boundary point, don't separate\n");
778  goto CLEANUP;
779  }
780  }
781 
782  /* generate cuts at sol */
783  for( i = 0; i < nnlrowsidx; i++ )
784  {
785  SCIP_NLROW* nlrow;
786  SCIP_ROW* row;
787  SCIP_Real activity;
788  CONVEXSIDE convexside;
789  char rowname[SCIP_MAXSTRLEN];
790 
791  nlrow = nlrows[nlrowsidx[i]];
792  convexside = convexsides[nlrowsidx[i]];
793 
794  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%u", SCIPnlrowGetName(nlrow), ++(sepadata->ncuts));
795 
796  /* only separate nlrows that are tight at the boundary point */
797  SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
798  SCIPdebugMsg(scip, "cons <%s> at boundary point has activity: %g\n", SCIPnlrowGetName(nlrow), activity);
799 
800  if( (convexside == RHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow)))
801  || (convexside == LHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow))) )
802  continue;
803 
804  /* cut is globally valid, since we work on nlrows from the NLP built at the root node, which are globally valid */
805  /* @todo: when local nlrows get supported in SCIP, one can think of recomputing the interior point */
806  SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &row, sepa, rowname, -SCIPinfinity(scip), SCIPinfinity(scip),
807  FALSE, FALSE , TRUE) );
808  SCIP_CALL( generateCut(scip, sol, sepadata->exprinterpreter, nlrow, convexside, row) );
809 
810  /* add cut */
811  SCIPdebugMsg(scip, "cut <%s> has efficacy %g\n", SCIProwGetName(row), SCIPgetCutEfficacy(scip, NULL, row));
812  if( SCIPisCutEfficacious(scip, NULL, row) )
813  {
814  SCIP_Bool infeasible;
815 
816  SCIPdebugMsg(scip, "adding cut\n");
817  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
818 
819  if( infeasible )
820  {
821  *result = SCIP_CUTOFF;
822  SCIP_CALL( SCIPreleaseRow(scip, &row) );
823  break;
824  }
825  else
826  {
827  *result = SCIP_SEPARATED;
828  }
829  }
830 
831  /* release the row */
832  SCIP_CALL( SCIPreleaseRow(scip, &row) );
833  }
834 
835 CLEANUP:
836  SCIP_CALL( SCIPfreeSol(scip, &sol) );
837 
838  return SCIP_OKAY;
839 }
840 
841 /*
842  * Callback methods of separator
843  */
844 
845 
846 /** destructor of separator to free user data (called when SCIP is exiting) */
847 static
848 SCIP_DECL_SEPAFREE(sepaFreeGauge)
849 { /*lint --e{715}*/
850  SCIP_SEPADATA* sepadata;
851 
852  assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
853 
854  /* free separator data */
855  sepadata = SCIPsepaGetData(sepa);
856  assert(sepadata != NULL);
857 
858  SCIPfreeBlockMemory(scip, &sepadata);
859 
860  SCIPsepaSetData(sepa, NULL);
861 
862  return SCIP_OKAY;
863 }
864 
865 
866 /** solving process deinitialization method of separator (called before branch and bound process data is freed) */
867 static
868 SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
869 { /*lint --e{715}*/
870  SCIP_SEPADATA* sepadata;
871 
872  assert(sepa != NULL);
873 
874  sepadata = SCIPsepaGetData(sepa);
875 
876  assert(sepadata != NULL);
877 
878  /* free memory and reset data */
879  if( sepadata->isintsolavailable )
880  {
881  SCIPfreeBlockMemoryArray(scip, &sepadata->nlrowsidx, sepadata->nlrowssize);
882  SCIPfreeBlockMemoryArray(scip, &sepadata->convexsides, sepadata->nlrowssize);
883  SCIPfreeBlockMemoryArray(scip, &sepadata->nlrows, sepadata->nlrowssize);
884  SCIP_CALL( SCIPfreeSol(scip, &sepadata->intsol) );
885  SCIP_CALL( SCIPexprintFree(&sepadata->exprinterpreter) );
886 
887  sepadata->nnlrows = 0;
888  sepadata->nnlrowsidx = 0;
889  sepadata->nlrowssize = 0;
890  sepadata->isintsolavailable = FALSE;
891  }
892  assert(sepadata->nnlrows == 0);
893  assert(sepadata->nnlrowsidx == 0);
894  assert(sepadata->nlrowssize == 0);
895  assert(sepadata->isintsolavailable == FALSE);
896 
897  sepadata->skipsepa = FALSE;
898 
899  return SCIP_OKAY;
900 }
901 
902 
903 /** LP solution separation method of separator */
904 static
905 SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
906 { /*lint --e{715}*/
907  SCIP_SEPADATA* sepadata;
908  SCIP_SOL* lpsol;
909  int i;
910 
911  assert(scip != NULL);
912  assert(sepa != NULL);
913 
914  sepadata = SCIPsepaGetData(sepa);
915 
916  assert(sepadata != NULL);
917 
918  *result = SCIP_DIDNOTRUN;
919 
920  /* do not run if there is no interesting convex relaxation (with at least two nonlinear convex constraint) */
921  if( sepadata->skipsepa )
922  {
923  SCIPdebugMsg(scip, "not running because convex relaxation is uninteresting\n");
924  return SCIP_OKAY;
925  }
926 
927  /* do not run if SCIP has not constructed an NLP */
928  if( !SCIPisNLPConstructed(scip) )
929  {
930  SCIPdebugMsg(scip, "NLP not constructed, skipping gauge separator\n");
931  return SCIP_OKAY;
932  }
933 
934  /* do not run if SCIP has no way of solving nonlinear problems */
935  if( SCIPgetNNlpis(scip) == 0 )
936  {
937  SCIPdebugMsg(scip, "Skip gauge separator: no nlpi and SCIP can't solve nonlinear problems without a nlpi\n");
938  return SCIP_OKAY;
939  }
940 
941  /* if we don't have an interior point compute one; if we fail to compute one, then separator will not be run again;
942  * otherwise, we also store the convex nlrows in sepadata
943  */
944  if( !sepadata->isintsolavailable )
945  {
946  /* @todo: one could store the convex nonlinear rows inside computeInteriorPoint */
947  SCIP_CALL( computeInteriorPoint(scip, sepadata) );
948  assert(sepadata->skipsepa || sepadata->isintsolavailable);
949 
950  if( sepadata->skipsepa )
951  return SCIP_OKAY;
952 
954  SCIP_CALL( SCIPexprintCreate(SCIPblkmem(scip), &sepadata->exprinterpreter) );
955  }
956 
957 #ifdef SCIP_DISABLED_CODE
958  /* get interior point: try to compute an interior point, otherwise use primal solution, otherwise use NLP solution */
959  /* @todo: - decide order:
960  * - we can also use convex combination of solutions; there is a function SCIPvarGetAvgSol!
961  * - can add an event handler to only update when a new solution has been found
962  */
963  if( !sepadata->isintsolavailable && sepadata->computeintsol )
964  {
965  SCIP_Bool success;
966 
967  success = FALSE;
968  SCIP_CALL( computeInteriorPoint(scip, sepa, &success) );
969 
970  if( success )
971  sepadata->isintsolavailable = TRUE;
972  }
973 
974  if( !sepadata->isintsolavailable )
975  {
976  if( SCIPgetNSols(scip) > 0 )
977  {
978  SCIPdebugMsg(scip, "Using current primal solution as interior point!\n");
979  SCIP_CALL( SCIPcreateSolCopy(scip, &sepadata->intsol, SCIPgetBestSol(scip)) );
980  sepadata->isintsolavailable = TRUE;
981  }
982  else if( SCIPhasNLPSolution(scip, NULL) )
983  {
984  SCIPdebugMsg(scip, "Using NLP solution as interior point!\n");
985  SCIP_CALL( SCIPcreateNLPSol(scip, &sepadata->intsol, NULL) );
986  sepadata->isintsolavailable = TRUE;
987  }
988  else
989  {
990  SCIPdebugMsg(scip, "We couldn't find an interior point, don't have a feasible nor an NLP solution; skip separator\n");
991  return SCIP_OKAY;
992  }
993  }
994 #endif
995 
996  /* store lp sol (or pseudo sol when lp is not solved) to be able to use it to compute nlrows' activities */
998 
999  /* store indices of relevant constraints, ie, the ones that violate the lp sol */
1000  sepadata->nnlrowsidx = 0;
1001  for( i = 0; i < sepadata->nnlrows; i++ )
1002  {
1003  SCIP_NLROW* nlrow;
1004  SCIP_Real activity;
1005 
1006  nlrow = sepadata->nlrows[i];
1007 
1008  SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, lpsol, &activity) );
1009 
1010  if( sepadata->convexsides[i] == RHS )
1011  {
1012  assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
1013 
1014  if( activity - SCIPnlrowGetRhs(nlrow) < VIOLATIONFAC * SCIPfeastol(scip) )
1015  continue;
1016  }
1017  else
1018  {
1019  assert(sepadata->convexsides[i] == LHS);
1020  assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
1021 
1022  if( SCIPnlrowGetLhs(nlrow) - activity < VIOLATIONFAC * SCIPfeastol(scip) )
1023  continue;
1024  }
1025 
1026  sepadata->nlrowsidx[sepadata->nnlrowsidx] = i;
1027  ++(sepadata->nnlrowsidx);
1028  }
1029 
1030  /* separate only if there are violated nlrows */
1031  SCIPdebugMsg(scip, "there are %d violated nlrows\n", sepadata->nnlrowsidx);
1032  if( sepadata->nnlrowsidx > 0 )
1033  {
1034  SCIP_CALL( separateCuts(scip, sepa, lpsol, result) );
1035  }
1036 
1037  /* free lpsol */
1038  SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
1039 
1040  return SCIP_OKAY;
1041 }
1042 
1043 
1044 /*
1045  * separator specific interface methods
1046  */
1047 
1048 /** creates the gauge separator and includes it in SCIP */
1050  SCIP* scip /**< SCIP data structure */
1051  )
1052 {
1053  SCIP_SEPADATA* sepadata;
1054  SCIP_SEPA* sepa;
1055 
1056  /* create gauge separator data */
1057  SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
1058 
1059  /* this sets all data in sepadata to 0 */
1060  BMSclearMemory(sepadata);
1061 
1062  /* include separator */
1065  sepaExeclpGauge, NULL,
1066  sepadata) );
1067 
1068  assert(sepa != NULL);
1069 
1070  /* set non fundamental callbacks via setter functions */
1071  SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeGauge) );
1072  SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolGauge) );
1073 
1074  /* add gauge separator parameters */
1075  SCIP_CALL( SCIPaddIntParam(scip, "separating/"SEPA_NAME"/nlpiterlimit",
1076  "iteration limit of NLP solver; 0 for no limit",
1077  &sepadata->nlpiterlimit, TRUE, DEFAULT_NLPITERLIM, 0, INT_MAX, NULL, NULL) );
1078 
1079  SCIP_CALL( SCIPaddRealParam(scip, "separating/"SEPA_NAME"/nlptimelimit",
1080  "time limit of NLP solver; 0.0 for no limit",
1081  &sepadata->nlptimelimit, TRUE, DEFAULT_NLPTIMELIMIT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
1082 
1083  return SCIP_OKAY;
1084 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define SEPA_DESC
Definition: sepa_gauge.c:38
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21909
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
Definition: scip.c:29200
int SCIPgetNNLPNlRows(SCIP *scip)
Definition: scip.c:31064
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:45137
SCIP_RETCODE SCIPnlpiGetStatistics(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:553
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:45274
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21892
void * SCIPgetNlpiOracleIpopt(SCIP_NLPIPROBLEM *nlpiproblem)
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:30835
SCIP_RETCODE SCIPnlpStatisticsCreate(SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:781
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30233
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46086
#define NLPVERBOSITY
Definition: sepa_gauge.c:52
methods to interpret (evaluate) an expression tree "fast"
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46099
int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2190
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:42499
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30256
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)
Definition: scip.c:33265
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:4426
#define SCIP_MAXSTRLEN
Definition: def.h:215
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30288
SCIP_Real SCIPnlpStatisticsGetTotalTime(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:820
internal methods for NLPI solver interfaces
SCIP_RETCODE SCIPnlpiCreateProblem(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM **problem, const char *name)
Definition: nlpi.c:211
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:16370
methods to store an NLP and request function, gradient, and hessian values
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:46175
static SCIP_RETCODE computeInteriorPoint(SCIP *scip, SCIP_SEPADATA *sepadata)
Definition: sepa_gauge.c:164
#define FALSE
Definition: def.h:64
gauge separator
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2765
static SCIP_DECL_SEPAFREE(sepaFreeGauge)
Definition: sepa_gauge.c:848
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:45816
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum Position POSITION
Definition: sepa_gauge.c:74
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition: sepa.c:632
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPexprintCompile(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree)
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3383
enum ConvexSide CONVEXSIDE
Definition: sepa_gauge.c:65
const char * SCIPnlpiGetName(SCIP_NLPI *nlpi)
Definition: nlpi.c:740
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3245
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21907
#define DEFAULT_NLPITERLIM
Definition: sepa_gauge.c:49
SCIP_RETCODE SCIPgetNlRowSolActivity(SCIP *scip, SCIP_NLROW *nlrow, SCIP_SOL *sol, SCIP_Real *activity)
Definition: scip.c:32537
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1228
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition: nlp.c:3393
SCIP_RETCODE SCIPnlpiGetSolution(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_Real **primalvalues, SCIP_Real **consdualvalues, SCIP_Real **varlbdualvalues, SCIP_Real **varubdualvalues)
Definition: nlpi.c:535
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2903
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:21937
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21890
#define SCIPdebugMsg
Definition: scip.h:451
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4202
void SCIPnlpStatisticsFree(SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:798
int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2200
SCIP_VAR ** SCIPexprtreeGetVars(SCIP_EXPRTREE *tree)
Definition: nlp.c:101
SCIP_NLROW ** SCIPgetNLPNlRows(SCIP *scip)
Definition: scip.c:31042
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition: sepa.c:543
int SCIPnlrowGetNQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3322
#define SEPA_MAXBOUNDDIST
Definition: sepa_gauge.c:41
static SCIP_RETCODE computeGradient(SCIP *scip, SCIP_EXPRINT *exprint, SCIP_SOL *sol, SCIP_EXPRTREE *exprtree, SCIP_Real *grad)
Definition: sepa_gauge.c:525
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2997
SCIP_RETCODE SCIPnlpiSolve(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem)
Definition: nlpi.c:495
Definition: sepa_gauge.c:63
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
static SCIP_RETCODE generateCut(SCIP *scip, SCIP_SOL *sol, SCIP_EXPRINT *exprint, SCIP_NLROW *nlrow, CONVEXSIDE convexside, SCIP_ROW *row)
Definition: sepa_gauge.c:572
static SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
Definition: sepa_gauge.c:868
SCIP_Real coef
Definition: type_expr.h:102
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:33761
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:37295
SCIP_VAR ** SCIPnlrowGetQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3285
int SCIPnlpiOracleGetConstraintDegree(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2312
static SCIP_RETCODE storeNonlinearConvexNlrows(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_NLROW **nlrows, int nnlrows)
Definition: sepa_gauge.c:105
SCIP_RETCODE SCIPexprintCreate(BMS_BLKMEM *blkmem, SCIP_EXPRINT **exprint)
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45519
static SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
Definition: sepa_gauge.c:905
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2798
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition: sepa.c:553
SCIP_RETCODE SCIPaddNlpiProbRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2idx, SCIP_ROW **rows, int nrows)
Definition: scip.c:33640
#define NULL
Definition: lpi_spx1.cpp:137
int SCIPgetNNlpis(SCIP *scip)
Definition: scip.c:9444
#define SEPA_NAME
Definition: sepa_gauge.c:37
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8543
int SCIPgetNLPRows(SCIP *scip)
Definition: scip.c:29221
SCIP_QUADELEM * SCIPnlrowGetQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3332
#define NLPFEASFAC
Definition: sepa_gauge.c:51
#define SCIP_CALL(x)
Definition: def.h:306
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46125
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:33869
SCIP_RETCODE SCIPincludeSepaGauge(SCIP *scip)
Definition: sepa_gauge.c:1049
SCIP_NLPSOLSTAT SCIPnlpiGetSolstat(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem)
Definition: nlpi.c:509
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
SCIP_RETCODE SCIPincludeSepaBasic(SCIP *scip, SCIP_SEPA **sepa, const char *name, const char *desc, int priority, int freq, SCIP_Real maxbounddist, SCIP_Bool usessubscip, SCIP_Bool delay, SCIP_DECL_SEPAEXECLP((*sepaexeclp)), SCIP_DECL_SEPAEXECSOL((*sepaexecsol)), SCIP_SEPADATA *sepadata)
Definition: scip.c:7325
SCIP_RETCODE SCIPnlpiFreeProblem(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM **problem)
Definition: nlpi.c:224
Ipopt NLP interface.
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21925
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:37867
SCIP_RETCODE SCIPnlpiOraclePrintProblem(SCIP_NLPIORACLE *oracle, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: nlpioracle.c:2917
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol)))
Definition: scip.c:7447
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip.c:30205
#define DEFAULT_NLPTIMELIMIT
Definition: sepa_gauge.c:48
SCIP_RETCODE SCIPnlpiSetIntPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, int ival)
Definition: nlpi.c:633
SCIP_EXPRINTDATA * SCIPexprtreeGetInterpreterData(SCIP_EXPRTREE *tree)
Definition: expr.c:8588
#define SEPA_DELAY
Definition: sepa_gauge.c:43
SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:30051
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip.c:30181
SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:33738
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:37631
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:38832
#define SEPA_PRIORITY
Definition: sepa_gauge.c:39
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:45827
#define BMSclearMemory(ptr)
Definition: memory.h:84
SCIP_RETCODE SCIPexprintGrad(SCIP_EXPRINT *exprint, SCIP_EXPRTREE *tree, SCIP_Real *varvals, SCIP_Bool new_varvals, SCIP_Real *val, SCIP_Real *gradient)
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11631
#define SCIP_REAL_MAX
Definition: def.h:136
SCIP_EXPRTREE * SCIPnlrowGetExprtree(SCIP_NLROW *nlrow)
Definition: nlp.c:3363
SCIP_Bool SCIPhasNLPSolution(SCIP *scip)
Definition: scip.c:31313
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30160
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37075
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
Definition: scip.c:7383
Position
Definition: sepa_gauge.c:68
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:38931
Definition: sepa_gauge.c:62
#define SEPA_FREQ
Definition: sepa_gauge.c:40
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11586
#define SCIP_Real
Definition: def.h:135
static SCIP_RETCODE buildConvexCombination(SCIP *scip, SCIP_Real lambda, SCIP_SOL *startpoint, SCIP_SOL *endpoint, SCIP_SOL *convexcomb)
Definition: sepa_gauge.c:417
#define MIN(x, y)
Definition: memory.c:75
static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *tosepasol, SCIP_RESULT *result)
Definition: sepa_gauge.c:691
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:30762
SCIP_RETCODE SCIPprintNlRow(SCIP *scip, SCIP_NLROW *nlrow, FILE *file)
Definition: scip.c:32630
int SCIPnlpStatisticsGetNIterations(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:810
SCIP_RETCODE SCIPcreateCurrentSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37160
SCIP_RETCODE SCIPnlpiChgLinearCoefs(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, const int idx, int nvals, const int *varidxs, const SCIP_Real *vals)
Definition: nlpi.c:393
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:45864
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition: nlp.c:3265
const char * SCIPnlrowGetName(SCIP_NLROW *nlrow)
Definition: nlp.c:3412
#define INTERIOROBJVARLB
Definition: sepa_gauge.c:54
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3255
ConvexSide
SCIP_NLPI ** SCIPgetNlpis(SCIP *scip)
Definition: scip.c:9431
SCIP_RETCODE SCIPexprintFree(SCIP_EXPRINT **exprint)
static SCIP_RETCODE findPointPosition(SCIP *scip, SCIP_NLROW **nlrows, int *nlrowsidx, int nnlrowsidx, CONVEXSIDE *convexsides, SCIP_SOL *point, POSITION *position)
Definition: sepa_gauge.c:341
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:3373
#define SEPA_USESSUBSCIP
Definition: sepa_gauge.c:42
static SCIP_RETCODE findBoundaryPoint(SCIP *scip, SCIP_NLROW **nlrows, int *nlrowsidx, int nnlrowsidx, CONVEXSIDE *convexsides, SCIP_SOL *intsol, SCIP_SOL *tosepasol, SCIP_SOL *sol, POSITION *position)
Definition: sepa_gauge.c:464
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38007
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:4258
#define VIOLATIONFAC
Definition: sepa_gauge.c:45
enum ConvexSide CONVEXSIDE
struct SCIP_SepaData SCIP_SEPADATA
Definition: type_sepa.h:38
#define MAX_ITER
Definition: sepa_gauge.c:46
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37005
SCIP_RETCODE SCIPnlpiSetRealPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, SCIP_Real dval)
Definition: nlpi.c:668
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:38421