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-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file 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  }
229  SCIPdebug( SCIP_CALL( SCIPnlpiOraclePrintProblem(nlpioracle, SCIPgetMessagehdlr(scip), NULL) ) );
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) );
264  SCIP_CALL( SCIPnlpiSetRealPar(nlpi, nlpiprob, SCIP_NLPPAR_RELOBJTOL, MAX(SCIPfeastol(scip), SCIPdualfeastol(scip))) ); /*lint !e666*/
266 
267  /* compute interior point */
268  SCIPdebugMsg(scip, "starting interior point computation\n");
269  SCIP_CALL( SCIPnlpiSolve(nlpi, nlpiprob) );
270  SCIPdebugMsg(scip, "finish interior point computation\n");
271 
272 #ifdef SCIP_DEBUG
273  {
274  SCIP_NLPSTATISTICS* nlpstatistics;
275 
276  /* get statistics */
277  SCIP_CALL( SCIPnlpStatisticsCreate(SCIPblkmem(scip), &nlpstatistics) );
278  SCIP_CALL( SCIPnlpiGetStatistics(nlpi, nlpiprob, nlpstatistics) );
279 
280  SCIPdebugMsg(scip, "nlpi took iters %d, time %g searching for an find interior point: solstat %d\n",
281  SCIPnlpStatisticsGetNIterations(nlpstatistics), SCIPnlpStatisticsGetTotalTime(nlpstatistics),
282  SCIPnlpiGetSolstat(nlpi, nlpiprob));
283 
284  SCIPnlpStatisticsFree(SCIPblkmem(scip), &nlpstatistics);
285  }
286 #endif
287 
288  if( SCIPnlpiGetSolstat(nlpi, nlpiprob) <= SCIP_NLPSOLSTAT_FEASIBLE )
289  {
290  SCIP_Real* nlpisol;
291 
292  SCIP_CALL( SCIPnlpiGetSolution(nlpi, nlpiprob, &nlpisol, NULL, NULL, NULL, NULL) );
293 
294  assert(nlpisol != NULL);
295  SCIPdebugMsg(scip, "NLP solved: sol found has objvalue = %g\n", nlpisol[objvaridx]);
296 
297  /* if we found an interior point store it */
298  if( SCIPisFeasNegative(scip, nlpisol[objvaridx]) )
299  {
300  SCIPdebugMsg(scip, "Interior point found!, storing it\n");
301  SCIP_CALL( SCIPcreateSol(scip, &sepadata->intsol, NULL) );
302  for( i = 0; i < nvars; i ++ )
303  {
304  SCIP_VAR* var;
305 
306  var = SCIPgetVars(scip)[i];
307  assert(SCIPhashmapExists(var2nlpiidx, (void*)var) );
308 
309  /* @todo: filter zero? */
310  SCIP_CALL( SCIPsetSolVal(scip, sepadata->intsol, var,
311  nlpisol[(int)(size_t)SCIPhashmapGetImage(var2nlpiidx, (void *)var)]) );
312  }
313 
314  sepadata->isintsolavailable = TRUE;
315  }
316  else
317  {
318  SCIPdebugMsg(scip, "We got a feasible point but not interior (objval: %g)\n", nlpisol[objvaridx]);
319  sepadata->skipsepa = TRUE;
320  }
321  }
322  else
323  {
324  SCIPdebugMsg(scip, "We couldn't get an interior point (stat: %d)\n", SCIPnlpiGetSolstat(nlpi, nlpiprob));
325  sepadata->skipsepa = TRUE;
326  }
327 
328 CLEANUP:
329  /* free memory */
330  SCIPhashmapFree(&var2nlpiidx);
331  SCIP_CALL( SCIPnlpiFreeProblem(nlpi, &nlpiprob) );
332 
333  return SCIP_OKAY;
334 }
335 
336 
337 /** find whether point is in the interior, at the boundary or in the exterior of the region described by the
338  * intersection of nlrows[i] <= rhs if convexsides[i] = RHS or lhs <= nlrows[i] if convexsides[i] = LHS
339  * @note: point corresponds to a convex combination between the lp solution and the interior point
340  */
341 static
343  SCIP* scip, /**< SCIP data structure */
344  SCIP_NLROW** nlrows, /**< nlrows defining the region */
345  int* nlrowsidx, /**< indices of nlrows defining the region */
346  int nnlrowsidx, /**< number of nlrows indices */
347  CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
348  SCIP_SOL* point, /**< point for which we want to know its position */
349  POSITION* position /**< buffer to store position of sol */
350  )
351 {
352  int i;
353 
354  assert(scip != NULL);
355  assert(nlrows != NULL);
356  assert(convexsides != NULL);
357  assert(nnlrowsidx > 0);
358  assert(point != NULL);
359  assert(position != NULL);
360 
361  *position = INTERIOR;
362  for( i = 0; i < nnlrowsidx; i++ )
363  {
364  SCIP_NLROW* nlrow;
365  SCIP_Real activity;
366  CONVEXSIDE convexside;
367 
368  nlrow = nlrows[nlrowsidx[i]];
369  convexside = convexsides[nlrowsidx[i]];
370 
371  /* compute activity of nlrow at point */
372  SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, point, &activity) );
373 
374  if( convexside == RHS )
375  {
376  assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
377 
378  /* if nlrow <= rhs is violated, then we are in the exterior */
379  if( SCIPisFeasGT(scip, activity, SCIPnlrowGetRhs(nlrow)) )
380  {
381  *position = EXTERIOR;
382  SCIPdebugMsg(scip, "exterior because cons <%s> has activity %g. rhs: %g\n", SCIPnlrowGetName(nlrow),
383  activity, SCIPnlrowGetRhs(nlrow));
384  SCIPdebug( SCIPprintNlRow(scip, nlrow, NULL) );
385 
386  return SCIP_OKAY;
387  }
388 
389  /* if nlrow(point) == rhs, then we are currently at the boundary */
390  if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow)) )
391  *position = BOUNDARY;
392  }
393  else
394  {
395  assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
396  assert(convexside == LHS);
397 
398  /* if lhs <= nlrow is violated, then we are in the exterior */
399  if( SCIPisFeasLT(scip, activity, SCIPnlrowGetLhs(nlrow)) )
400  {
401  *position = EXTERIOR;
402  return SCIP_OKAY;
403  }
404 
405  /* if lhs == nlrow(point), then we are currently at the boundary */
406  if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow)) )
407  *position = BOUNDARY;
408  }
409  }
410 
411  return SCIP_OKAY;
412 }
413 
414 
415 /** returns, in convexcomb, the convex combination
416  * \f$ \lambda \f$ endpoint + (1 - \f$ lambda \f$) startpoint = startpoint + \f$ \lambda \f$ (endpoint - tosepasol) */
417 static
419  SCIP* scip, /**< SCIP data structure */
420  SCIP_Real lambda, /**< convex combination multiplier */
421  SCIP_SOL* startpoint, /**< point corresponding to \f$ \lambda = 0 \f$ */
422  SCIP_SOL* endpoint, /**< point corresponding to \f$ \lambda = 1 \f$ */
423  SCIP_SOL* convexcomb /**< solution to store convex combination of intsol and tosepasol */
424  )
425 {
426  SCIP_VAR** vars;
427  int nvars;
428  int i;
429 
430  assert(scip != NULL);
431  assert(startpoint != NULL);
432  assert(endpoint != NULL);
433  assert(convexcomb != NULL);
434 
435  vars = SCIPgetVars(scip);
436  nvars = SCIPgetNVars(scip);
437 
438  for( i = 0; i < nvars; i++ )
439  {
440  SCIP_Real val;
441  SCIP_VAR* var;
442 
443  var = vars[i];
444  val = lambda * SCIPgetSolVal(scip, endpoint, var) + (1.0 - lambda) * SCIPgetSolVal(scip, startpoint, var);
445 
446  if( !SCIPisZero(scip, val) )
447  {
448  SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, val) );
449  }
450  else
451  {
452  SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, 0.0) );
453  }
454  }
455 
456  return SCIP_OKAY;
457 }
458 
459 
460 /** performs binary search to find the point belonging to the segment [intsol, tosepasol] that intersects the boundary
461  * of the region described by the intersection of nlrows[i] <= rhs if convexsides[i] = RHS or lhs <= nlrows[i] if not,
462  * for i in nlrowsidx
463  */
464 static
466  SCIP* scip, /**< SCIP data structure */
467  SCIP_NLROW** nlrows, /**< nlrows defining the region */
468  int* nlrowsidx, /**< indices of nlrows defining the region */
469  int nnlrowsidx, /**< number of nlrows indices */
470  CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
471  SCIP_SOL* intsol, /**< point acting as 'interior point' */
472  SCIP_SOL* tosepasol, /**< solution that should be separated */
473  SCIP_SOL* sol, /**< convex combination of intsol and lpsol */
474  POSITION* position /**< buffer to store position of sol */
475  )
476 {
477  SCIP_Real lb;
478  SCIP_Real ub;
479  int i;
480 
481  assert(scip != NULL);
482  assert(nlrows != NULL);
483  assert(nlrowsidx != NULL);
484  assert(convexsides != NULL);
485  assert(intsol != NULL);
486  assert(tosepasol != NULL);
487  assert(sol != NULL);
488  assert(position != NULL);
489 
490  SCIPdebugMsg(scip, "starting binary search\n");
491  lb = 0.0; /* corresponds to intsol */
492  ub = 1.0; /* corresponds to tosepasol */
493  for( i = 0; i < MAX_ITER; i++ )
494  {
495  /* sol = (ub+lb)/2 * lpsol + (1 - (ub+lb)/2) * intsol */
496  SCIP_CALL( buildConvexCombination(scip, (ub + lb)/2.0, intsol, tosepasol, sol) );
497 
498  /* find poisition of point: boundary, interior, exterior */
499  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, position) );
500  SCIPdebugMsg(scip, "Position: %d, lambda: %g\n", position, (ub + lb)/2.0);
501 
502  switch( *position )
503  {
504  case BOUNDARY:
505  SCIPdebugMsg(scip, "Done\n");
506  return SCIP_OKAY;
507 
508  case INTERIOR:
509  /* want to be closer to tosepasol */
510  lb = (ub + lb)/2.0;
511  break;
512 
513  case EXTERIOR:
514  /* want to be closer to intsol */
515  ub = (ub + lb)/2.0;
516  break;
517  }
518  }
519  SCIPdebugMsg(scip, "Done\n");
520  return SCIP_OKAY;
521 }
522 
523 
524 /** computes gradient of exprtree at sol */
525 static
527  SCIP* scip, /**< SCIP data structure */
528  SCIP_EXPRINT* exprint, /**< expressions interpreter */
529  SCIP_SOL* sol, /**< point where we compute gradient */
530  SCIP_EXPRTREE* exprtree, /**< exprtree for which we compute the gradient */
531  SCIP_Real* grad /**< buffer to store the gradient */
532  )
533 {
534  SCIP_Real* x;
535  SCIP_Real val;
536  int nvars;
537  int i;
538 
539  assert(scip != NULL);
540  assert(exprint != NULL);
541  assert(sol != NULL);
542  assert(exprtree != NULL);
543  assert(grad != NULL);
544 
545  nvars = SCIPexprtreeGetNVars(exprtree);
546  assert(nvars > 0);
547 
548  SCIP_CALL( SCIPallocBufferArray(scip, &x, nvars) );
549 
550  /* compile expression exprtree, if not done before */
551  if( SCIPexprtreeGetInterpreterData(exprtree) == NULL )
552  {
553  SCIP_CALL( SCIPexprintCompile(exprint, exprtree) );
554  }
555 
556  for( i = 0; i < nvars; ++i )
557  {
558  x[i] = SCIPgetSolVal(scip, sol, SCIPexprtreeGetVars(exprtree)[i]);
559  }
560 
561  SCIP_CALL( SCIPexprintGrad(exprint, exprtree, x, TRUE, &val, grad) );
562 
563  /*SCIPdebug( for( i = 0; i < nvars; ++i ) printf("%e [%s]\n", grad[i], SCIPvarGetName(SCIPexprtreeGetVars(exprtree)[i])) );*/
564 
565  SCIPfreeBufferArray(scip, &x);
566 
567  return SCIP_OKAY;
568 }
569 
570 
571 /** computes gradient cut (linearization) of nlrow at sol */
572 static
574  SCIP* scip, /**< SCIP data structure */
575  SCIP_SOL* sol, /**< point used to construct gradient cut (x_0) */
576  SCIP_EXPRINT* exprint, /**< expression interpreter */
577  SCIP_NLROW* nlrow, /**< constraint */
578  CONVEXSIDE convexside, /**< whether we use rhs or lhs of nlrow */
579  SCIP_ROW* row /**< storage for cut */
580  )
581 {
582  SCIP_Real activity;
583  SCIP_Real gradx0; /* <grad f(x_0), x_0> */
584  int i;
585 
586  assert(scip != NULL);
587  assert(exprint != NULL);
588  assert(nlrow != NULL);
589  assert(row != NULL);
590 
591  gradx0 = 0.0;
592 
593  /* an nlrow has a linear part, quadratic part and expression tree; ideally one would just build the gradient but we
594  * do not know if the different parts share variables or not, so we can't just build the gradient; for this reason
595  * we create the row right away and compute the gradients of each part independently and add them to the row; the
596  * row takes care to add coeffs corresponding to the same variable when they appear in different parts of the nlrow
597  */
598 
599  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
600 
601  /* linear part */
602  for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
603  {
604  gradx0 += SCIPgetSolVal(scip, sol, SCIPnlrowGetLinearVars(nlrow)[i]) * SCIPnlrowGetLinearCoefs(nlrow)[i];
605  SCIP_CALL( SCIPaddVarToRow(scip, row, SCIPnlrowGetLinearVars(nlrow)[i], SCIPnlrowGetLinearCoefs(nlrow)[i]) );
606  }
607 
608  /* quadratic part */
609  for( i = 0; i < SCIPnlrowGetNQuadElems(nlrow); i++ )
610  {
611  SCIP_VAR* var1;
612  SCIP_VAR* var2;
613  SCIP_Real grad1;
614  SCIP_Real grad2;
615  SCIP_Real solval1;
616  SCIP_Real solval2;
617 
618  var1 = SCIPnlrowGetQuadVars(nlrow)[SCIPnlrowGetQuadElems(nlrow)[i].idx1];
619  var2 = SCIPnlrowGetQuadVars(nlrow)[SCIPnlrowGetQuadElems(nlrow)[i].idx2];
620  solval1 = SCIPgetSolVal(scip, sol, var1);
621  solval2 = SCIPgetSolVal(scip, sol, var2);
622  grad1 = SCIPnlrowGetQuadElems(nlrow)[i].coef * solval2; /* note that solval2 is correct */
623  grad2 = SCIPnlrowGetQuadElems(nlrow)[i].coef * solval1;
624 
625  SCIP_CALL( SCIPaddVarToRow(scip, row, var1, grad1) );
626  SCIP_CALL( SCIPaddVarToRow(scip, row, var2, grad2) );
627 
628  gradx0 += grad1 * solval1 + grad2 * solval2;
629  }
630 
631  /* expression tree part */
632  {
633  SCIP_Real* grad;
634  SCIP_EXPRTREE* tree;
635 
636  tree = SCIPnlrowGetExprtree(nlrow);
637 
638  if( tree != NULL && SCIPexprtreeGetNVars(tree) > 0 )
639  {
640  SCIP_CALL( SCIPallocBufferArray(scip, &grad, SCIPexprtreeGetNVars(tree)) );
641 
642  SCIP_CALL( computeGradient(scip, exprint, sol, tree, grad) );
643 
644  for( i = 0; i < SCIPexprtreeGetNVars(tree); i++ )
645  {
646  gradx0 += grad[i] * SCIPgetSolVal(scip, sol, SCIPexprtreeGetVars(tree)[i]);
647  SCIP_CALL( SCIPaddVarToRow(scip, row, SCIPexprtreeGetVars(tree)[i], grad[i]) );
648  }
649 
650  SCIPfreeBufferArray(scip, &grad);
651  }
652  }
653 
654  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
655 
656 #ifdef CUT_DEBUG
657  SCIPdebugMsg(scip, "gradient: ");
658  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
659  SCIPdebugMsg(scip, "gradient dot x_0: %g\n", gradx0);
660 #endif
661 
662  /* gradient cut is f(x_0) - <grad f(x_0), x_0> + <grad f(x_0), x> <= rhs or >= lhs */
663  SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
664  if( convexside == RHS )
665  {
666  assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
667  SCIP_CALL( SCIPchgRowRhs(scip, row, SCIPnlrowGetRhs(nlrow) - activity + gradx0) );
668  }
669  else
670  {
671  assert(convexside == LHS);
672  assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
673  SCIP_CALL( SCIPchgRowLhs(scip, row, SCIPnlrowGetLhs(nlrow) - activity + gradx0) );
674  }
675 
676 #ifdef CUT_DEBUG
677  SCIPdebugMsg(scip, "gradient cut: ");
678  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
679 #endif
680 
681  return SCIP_OKAY;
682 }
683 
684 /** tries to generate gradient cuts at the point on the segment [intsol, tosepasol] that intersecs the boundary of the
685  * convex relaxation
686  * -# checks that the relative interior of the segment actually intersects the boundary
687  * (this check is needed since intsol is not necessarily an interior point)
688  * -# finds point on the boundary
689  * -# generates gradient cut at point on the boundary
690  */
691 static
693  SCIP* scip, /**< SCIP data structure */
694  SCIP_SEPA* sepa, /**< the cut separator itself */
695  SCIP_SOL* tosepasol, /**< solution that should be separated */
696  SCIP_RESULT* result /**< pointer to store the result of the separation call */
697  )
698 {
699  SCIP_SEPADATA* sepadata;
700  SCIP_NLROW** nlrows;
701  CONVEXSIDE* convexsides;
702  SCIP_SOL* sol;
703  SCIP_SOL* intsol;
704  POSITION position;
705  int* nlrowsidx;
706  int nnlrowsidx;
707  int i;
708 
709  assert(sepa != NULL);
710 
711  sepadata = SCIPsepaGetData(sepa);
712  assert(sepadata != NULL);
713 
714  intsol = sepadata->intsol;
715  nlrows = sepadata->nlrows;
716  nlrowsidx = sepadata->nlrowsidx;
717  nnlrowsidx = sepadata->nnlrowsidx;
718  convexsides = sepadata->convexsides;
719 
720  assert(intsol != NULL);
721  assert(nlrows != NULL);
722  assert(nlrowsidx != NULL);
723  assert(nnlrowsidx > 0);
724  assert(convexsides != NULL);
725 
726  /* to evaluate the nlrow one needs a solution */
727  SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
728 
729  /* don't separate if, under SCIP tolerances, only a slight perturbation of the interior point in the direction of
730  * tosepasol gives a point that is in the exterior */
731  SCIP_CALL( buildConvexCombination(scip, VIOLATIONFAC * SCIPfeastol(scip), intsol, tosepasol, sol) );
732  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
733 
734  if( position == EXTERIOR )
735  {
736 #ifdef SCIP_DEBUG
737  SCIPdebugMsg(scip, "segment joining intsol and tosepasol seems to be contained in the exterior of the region, can't separate\n");
738  /* move from intsol in the direction of -tosepasol to check if we are really tangent to the region */
739  SCIP_CALL( buildConvexCombination(scip, -1e-3, intsol, tosepasol, sol) );
740  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
741  if( position == EXTERIOR )
742  {
743  SCIPdebugMsg(scip, "line through intsol and tosepasol is tangent to region; can't separate\n");
744  }
745  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, &position) );
746  printf("Position of intsol is %s\n",
747  position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
748  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, tosepasol, &position) );
749  printf("Position of tosepasol is %s\n",
750  position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
751 
752  /* slightly move from intsol in the direction of +-tosepasol */
753  SCIP_CALL( buildConvexCombination(scip, 1e-5, intsol, tosepasol, sol) );
754  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
755  printf("Position of intsol + 0.00001(tosepasol - inisol) is %s\n",
756  position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
757  SCIPdebug( SCIPprintSol(scip, sol, NULL, FALSE) );
758 
759  SCIP_CALL( buildConvexCombination(scip, -1e-5, intsol, tosepasol, sol) );
760  SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
761  printf("Position of intsol - 0.00001(tosepasol - inisol) is %s\n",
762  position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
763  SCIPdebug( SCIPprintSol(scip, sol, NULL, FALSE) );
764 #endif
765  *result = SCIP_DIDNOTFIND;
766  goto CLEANUP;
767  }
768 
769  /* find point on boundary */
770  if( position != BOUNDARY )
771  {
772  SCIP_CALL( findBoundaryPoint(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, tosepasol, sol,
773  &position) );
774 
775  /* if MAX_ITER weren't enough to find a point in the boundary we don't separate */
776  if( position != BOUNDARY )
777  {
778  SCIPdebugMsg(scip, "couldn't find boundary point, don't separate\n");
779  goto CLEANUP;
780  }
781  }
782 
783  /* generate cuts at sol */
784  for( i = 0; i < nnlrowsidx; i++ )
785  {
786  SCIP_NLROW* nlrow;
787  SCIP_ROW* row;
788  SCIP_Real activity;
789  CONVEXSIDE convexside;
790  char rowname[SCIP_MAXSTRLEN];
791 
792  nlrow = nlrows[nlrowsidx[i]];
793  convexside = convexsides[nlrowsidx[i]];
794 
795  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%u", SCIPnlrowGetName(nlrow), ++(sepadata->ncuts));
796 
797  /* only separate nlrows that are tight at the boundary point */
798  SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
799  SCIPdebugMsg(scip, "cons <%s> at boundary point has activity: %g\n", SCIPnlrowGetName(nlrow), activity);
800 
801  if( (convexside == RHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow)))
802  || (convexside == LHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow))) )
803  continue;
804 
805  /* cut is globally valid, since we work on nlrows from the NLP built at the root node, which are globally valid */
806  /* @todo: when local nlrows get supported in SCIP, one can think of recomputing the interior point */
807  SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &row, sepa, rowname, -SCIPinfinity(scip), SCIPinfinity(scip),
808  FALSE, FALSE , TRUE) );
809  SCIP_CALL( generateCut(scip, sol, sepadata->exprinterpreter, nlrow, convexside, row) );
810 
811  /* add cut */
812  SCIPdebugMsg(scip, "cut <%s> has efficacy %g\n", SCIProwGetName(row), SCIPgetCutEfficacy(scip, NULL, row));
813  if( SCIPisCutEfficacious(scip, NULL, row) )
814  {
815  SCIP_Bool infeasible;
816 
817  SCIPdebugMsg(scip, "adding cut\n");
818  SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
819 
820  if( infeasible )
821  {
822  *result = SCIP_CUTOFF;
823  SCIP_CALL( SCIPreleaseRow(scip, &row) );
824  break;
825  }
826  else
827  {
828  *result = SCIP_SEPARATED;
829  }
830  }
831 
832  /* release the row */
833  SCIP_CALL( SCIPreleaseRow(scip, &row) );
834  }
835 
836 CLEANUP:
837  SCIP_CALL( SCIPfreeSol(scip, &sol) );
838 
839  return SCIP_OKAY;
840 }
841 
842 /*
843  * Callback methods of separator
844  */
845 
846 
847 /** destructor of separator to free user data (called when SCIP is exiting) */
848 static
849 SCIP_DECL_SEPAFREE(sepaFreeGauge)
850 { /*lint --e{715}*/
851  SCIP_SEPADATA* sepadata;
852 
853  assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
854 
855  /* free separator data */
856  sepadata = SCIPsepaGetData(sepa);
857  assert(sepadata != NULL);
858 
859  SCIPfreeBlockMemory(scip, &sepadata);
860 
861  SCIPsepaSetData(sepa, NULL);
862 
863  return SCIP_OKAY;
864 }
865 
866 
867 /** solving process deinitialization method of separator (called before branch and bound process data is freed) */
868 static
869 SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
870 { /*lint --e{715}*/
871  SCIP_SEPADATA* sepadata;
872 
873  assert(sepa != NULL);
874 
875  sepadata = SCIPsepaGetData(sepa);
876 
877  assert(sepadata != NULL);
878 
879  /* free memory and reset data */
880  if( sepadata->isintsolavailable )
881  {
882  SCIPfreeBlockMemoryArray(scip, &sepadata->nlrowsidx, sepadata->nlrowssize);
883  SCIPfreeBlockMemoryArray(scip, &sepadata->convexsides, sepadata->nlrowssize);
884  SCIPfreeBlockMemoryArray(scip, &sepadata->nlrows, sepadata->nlrowssize);
885  SCIP_CALL( SCIPfreeSol(scip, &sepadata->intsol) );
886  SCIP_CALL( SCIPexprintFree(&sepadata->exprinterpreter) );
887 
888  sepadata->nnlrows = 0;
889  sepadata->nnlrowsidx = 0;
890  sepadata->nlrowssize = 0;
891  sepadata->isintsolavailable = FALSE;
892  }
893  assert(sepadata->nnlrows == 0);
894  assert(sepadata->nnlrowsidx == 0);
895  assert(sepadata->nlrowssize == 0);
896  assert(sepadata->isintsolavailable == FALSE);
897 
898  sepadata->skipsepa = FALSE;
899 
900  return SCIP_OKAY;
901 }
902 
903 
904 /** LP solution separation method of separator */
905 static
906 SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
907 { /*lint --e{715}*/
908  SCIP_SEPADATA* sepadata;
909  SCIP_SOL* lpsol;
910  int i;
911 
912  assert(scip != NULL);
913  assert(sepa != NULL);
914 
915  sepadata = SCIPsepaGetData(sepa);
916 
917  assert(sepadata != NULL);
918 
919  *result = SCIP_DIDNOTRUN;
920 
921  /* do not run if there is no interesting convex relaxation (with at least two nonlinear convex constraint) */
922  if( sepadata->skipsepa )
923  {
924  SCIPdebugMsg(scip, "not running because convex relaxation is uninteresting\n");
925  return SCIP_OKAY;
926  }
927 
928  /* do not run if SCIP has not constructed an NLP */
929  if( !SCIPisNLPConstructed(scip) )
930  {
931  SCIPdebugMsg(scip, "NLP not constructed, skipping gauge separator\n");
932  return SCIP_OKAY;
933  }
934 
935  /* do not run if SCIP has no way of solving nonlinear problems */
936  if( SCIPgetNNlpis(scip) == 0 )
937  {
938  SCIPdebugMsg(scip, "Skip gauge separator: no nlpi and SCIP can't solve nonlinear problems without a nlpi\n");
939  return SCIP_OKAY;
940  }
941 
942  /* if we don't have an interior point compute one; if we fail to compute one, then separator will not be run again;
943  * otherwise, we also store the convex nlrows in sepadata
944  */
945  if( !sepadata->isintsolavailable )
946  {
947  /* @todo: one could store the convex nonlinear rows inside computeInteriorPoint */
948  SCIP_CALL( computeInteriorPoint(scip, sepadata) );
949  assert(sepadata->skipsepa || sepadata->isintsolavailable);
950 
951  if( sepadata->skipsepa )
952  return SCIP_OKAY;
953 
955  SCIP_CALL( SCIPexprintCreate(SCIPblkmem(scip), &sepadata->exprinterpreter) );
956  }
957 
958 #ifdef SCIP_DISABLED_CODE
959  /* get interior point: try to compute an interior point, otherwise use primal solution, otherwise use NLP solution */
960  /* @todo: - decide order:
961  * - we can also use convex combination of solutions; there is a function SCIPvarGetAvgSol!
962  * - can add an event handler to only update when a new solution has been found
963  */
964  if( !sepadata->isintsolavailable && sepadata->computeintsol )
965  {
966  SCIP_Bool success;
967 
968  success = FALSE;
969  SCIP_CALL( computeInteriorPoint(scip, sepa, &success) );
970 
971  if( success )
972  sepadata->isintsolavailable = TRUE;
973  }
974 
975  if( !sepadata->isintsolavailable )
976  {
977  if( SCIPgetNSols(scip) > 0 )
978  {
979  SCIPdebugMsg(scip, "Using current primal solution as interior point!\n");
980  SCIP_CALL( SCIPcreateSolCopy(scip, &sepadata->intsol, SCIPgetBestSol(scip)) );
981  sepadata->isintsolavailable = TRUE;
982  }
983  else if( SCIPhasNLPSolution(scip, NULL) )
984  {
985  SCIPdebugMsg(scip, "Using NLP solution as interior point!\n");
986  SCIP_CALL( SCIPcreateNLPSol(scip, &sepadata->intsol, NULL) );
987  sepadata->isintsolavailable = TRUE;
988  }
989  else
990  {
991  SCIPdebugMsg(scip, "We couldn't find an interior point, don't have a feasible nor an NLP solution; skip separator\n");
992  return SCIP_OKAY;
993  }
994  }
995 #endif
996 
997  /* store lp sol (or pseudo sol when lp is not solved) to be able to use it to compute nlrows' activities */
998  SCIP_CALL( SCIPcreateCurrentSol(scip, &lpsol, NULL) );
999 
1000  /* store indices of relevant constraints, ie, the ones that violate the lp sol */
1001  sepadata->nnlrowsidx = 0;
1002  for( i = 0; i < sepadata->nnlrows; i++ )
1003  {
1004  SCIP_NLROW* nlrow;
1005  SCIP_Real activity;
1006 
1007  nlrow = sepadata->nlrows[i];
1008 
1009  SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, lpsol, &activity) );
1010 
1011  if( sepadata->convexsides[i] == RHS )
1012  {
1013  assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
1014 
1015  if( activity - SCIPnlrowGetRhs(nlrow) < VIOLATIONFAC * SCIPfeastol(scip) )
1016  continue;
1017  }
1018  else
1019  {
1020  assert(sepadata->convexsides[i] == LHS);
1021  assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
1022 
1023  if( SCIPnlrowGetLhs(nlrow) - activity < VIOLATIONFAC * SCIPfeastol(scip) )
1024  continue;
1025  }
1026 
1027  sepadata->nlrowsidx[sepadata->nnlrowsidx] = i;
1028  ++(sepadata->nnlrowsidx);
1029  }
1030 
1031  /* separate only if there are violated nlrows */
1032  SCIPdebugMsg(scip, "there are %d violated nlrows\n", sepadata->nnlrowsidx);
1033  if( sepadata->nnlrowsidx > 0 )
1034  {
1035  SCIP_CALL( separateCuts(scip, sepa, lpsol, result) );
1036  }
1037 
1038  /* free lpsol */
1039  SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
1040 
1041  return SCIP_OKAY;
1042 }
1043 
1044 
1045 /*
1046  * separator specific interface methods
1047  */
1048 
1049 /** creates the gauge separator and includes it in SCIP */
1051  SCIP* scip /**< SCIP data structure */
1052  )
1053 {
1054  SCIP_SEPADATA* sepadata;
1055  SCIP_SEPA* sepa;
1056 
1057  /* create gauge separator data */
1058  SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
1059 
1060  /* this sets all data in sepadata to 0 */
1061  BMSclearMemory(sepadata);
1062 
1063  /* include separator */
1066  sepaExeclpGauge, NULL,
1067  sepadata) );
1068 
1069  assert(sepa != NULL);
1070 
1071  /* set non fundamental callbacks via setter functions */
1072  SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeGauge) );
1073  SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolGauge) );
1074 
1075  /* add gauge separator parameters */
1076  SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/nlpiterlimit",
1077  "iteration limit of NLP solver; 0 for no limit",
1078  &sepadata->nlpiterlimit, TRUE, DEFAULT_NLPITERLIM, 0, INT_MAX, NULL, NULL) );
1079 
1080  SCIP_CALL( SCIPaddRealParam(scip, "separating/" SEPA_NAME "/nlptimelimit",
1081  "time limit of NLP solver; 0.0 for no limit",
1082  &sepadata->nlptimelimit, TRUE, DEFAULT_NLPTIMELIMIT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
1083 
1084  return SCIP_OKAY;
1085 }
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:22604
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
Definition: scip.c:29675
int SCIPgetNNLPNlRows(SCIP *scip)
Definition: scip.c:31462
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:46306
SCIP_RETCODE SCIPnlpiGetStatistics(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:556
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:46443
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
void * SCIPgetNlpiOracleIpopt(SCIP_NLPIPROBLEM *nlpiproblem)
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:31233
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30613
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
#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:47311
int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2195
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:43453
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30636
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:34032
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:4489
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30668
SCIP_Real SCIPnlpStatisticsGetTotalTime(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:826
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:16543
methods to store an NLP and request function, gradient, and hessian values
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47387
SCIP_RETCODE SCIPnlpiGetSolution(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_Real **primalvalues, SCIP_Real **consdualvalues, SCIP_Real **varlbdualvalues, SCIP_Real **varubdualvalues, SCIP_Real *objval)
Definition: nlpi.c:537
SCIP_Real SCIPdualfeastol(SCIP *scip)
Definition: scip.c:46471
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:2793
static SCIP_DECL_SEPAFREE(sepaFreeGauge)
Definition: sepa_gauge.c:849
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
#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:646
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:743
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3245
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
#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:32935
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1235
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition: nlp.c:3393
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
void SCIPnlpStatisticsFree(BMS_BLKMEM *blkmem, SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:801
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4265
int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:2205
SCIP_VAR ** SCIPexprtreeGetVars(SCIP_EXPRTREE *tree)
Definition: nlp.c:101
SCIP_NLROW ** SCIPgetNLPNlRows(SCIP *scip)
Definition: scip.c:31440
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition: sepa.c:557
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:526
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3025
SCIP_RETCODE SCIPnlpiSolve(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem)
Definition: nlpi.c:497
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:573
static SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
Definition: sepa_gauge.c:869
SCIP_Real coef
Definition: type_expr.h:102
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:34528
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:38168
SCIP_VAR ** SCIPnlrowGetQuadVars(SCIP_NLROW *nlrow)
Definition: nlp.c:3285
int SCIPnlpiOracleGetConstraintDegree(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:2317
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:46731
static SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
Definition: sepa_gauge.c:906
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition: sepa.c:567
SCIP_RETCODE SCIPaddNlpiProbRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2idx, SCIP_ROW **rows, int nrows)
Definition: scip.c:34407
int SCIPgetNNlpis(SCIP *scip)
Definition: scip.c:9602
#define SEPA_NAME
Definition: sepa_gauge.c:37
int SCIPexprtreeGetNVars(SCIP_EXPRTREE *tree)
Definition: expr.c:8612
int SCIPgetNLPRows(SCIP *scip)
Definition: scip.c:29696
SCIP_QUADELEM * SCIPnlrowGetQuadElems(SCIP_NLROW *nlrow)
Definition: nlp.c:3332
#define NLPFEASFAC
Definition: sepa_gauge.c:51
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47337
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34661
SCIP_RETCODE SCIPincludeSepaGauge(SCIP *scip)
Definition: sepa_gauge.c:1050
SCIP_NLPSOLSTAT SCIPnlpiGetSolstat(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem)
Definition: nlpi.c:511
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:7385
SCIP_RETCODE SCIPnlpiFreeProblem(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM **problem)
Definition: nlpi.c:224
Ipopt NLP interface.
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:38771
SCIP_RETCODE SCIPnlpiOraclePrintProblem(SCIP_NLPIORACLE *oracle, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: nlpioracle.c:2932
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol)))
Definition: scip.c:7507
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip.c:30585
#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:636
SCIP_EXPRINTDATA * SCIPexprtreeGetInterpreterData(SCIP_EXPRTREE *tree)
Definition: expr.c:8657
#define MAX(x, y)
Definition: tclique_def.h:75
#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:30431
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip.c:30561
SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:34505
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:38535
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39783
#define SEPA_PRIORITY
Definition: sepa_gauge.c:39
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
#define BMSclearMemory(ptr)
Definition: memory.h:111
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:11812
#define SCIP_REAL_MAX
Definition: def.h:150
SCIP_EXPRTREE * SCIPnlrowGetExprtree(SCIP_NLROW *nlrow)
Definition: nlp.c:3363
SCIP_Bool SCIPhasNLPSolution(SCIP *scip)
Definition: scip.c:31711
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30540
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37948
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
Definition: scip.c:7443
Position
Definition: sepa_gauge.c:68
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:39882
Definition: sepa_gauge.c:62
#define SEPA_FREQ
Definition: sepa_gauge.c:40
SCIP_RETCODE SCIPnlpStatisticsCreate(BMS_BLKMEM *blkmem, SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:784
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11767
#define SCIP_Real
Definition: def.h:149
static SCIP_RETCODE buildConvexCombination(SCIP *scip, SCIP_Real lambda, SCIP_SOL *startpoint, SCIP_SOL *endpoint, SCIP_SOL *convexcomb)
Definition: sepa_gauge.c:418
static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *tosepasol, SCIP_RESULT *result)
Definition: sepa_gauge.c:692
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:31160
SCIP_RETCODE SCIPprintNlRow(SCIP *scip, SCIP_NLROW *nlrow, FILE *file)
Definition: scip.c:33028
int SCIPnlpStatisticsGetNIterations(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:816
SCIP_RETCODE SCIPcreateCurrentSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:38033
SCIP_RETCODE SCIPnlpiChgLinearCoefs(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, const int idx, int nvals, const int *varidxs, const SCIP_Real *vals)
Definition: nlpi.c:395
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47076
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:9589
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:342
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:465
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4321
#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:37878
SCIP_RETCODE SCIPnlpiSetRealPar(SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *problem, SCIP_NLPPARAM type, SCIP_Real dval)
Definition: nlpi.c:671
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:39325