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-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file sepa_gauge.c
26 * @ingroup DEFPLUGINS_SEPA
27 * @brief gauge separator
28 * @author Felipe Serrano
29 *
30 * @todo should separator only be run when SCIPallColsInLP is true?
31 * @todo add SCIPisStopped(scip) to the condition of time consuming loops
32 * @todo check if it makes sense to implement the copy callback
33 */
34
35/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36
37#include <assert.h>
38#include <string.h>
39
41#include "scip/scip_nlpi.h"
42#include "scip/nlpi_ipopt.h"
43#include "scip/nlpioracle.h"
44#include "scip/scip_expr.h"
45#include "scip/pub_expr.h"
46#include "scip/pub_lp.h"
47#include "scip/pub_message.h"
48#include "scip/pub_misc.h"
49#include "scip/pub_nlp.h"
50#include "scip/pub_sepa.h"
51#include "scip/pub_var.h"
52#include "scip/scip_cut.h"
53#include "scip/scip_lp.h"
54#include "scip/scip_mem.h"
55#include "scip/scip_message.h"
56#include "scip/scip_nlp.h"
57#include "scip/scip_numerics.h"
58#include "scip/scip_param.h"
59#include "scip/scip_prob.h"
60#include "scip/scip_sepa.h"
61#include "scip/scip_sol.h"
63#include "scip/scip_timing.h"
64#include "scip/sepa_gauge.h"
65#include <string.h>
66
67
68#define SEPA_NAME "gauge"
69#define SEPA_DESC "gauge separator"
70#define SEPA_PRIORITY 0
71#define SEPA_FREQ -1
72#define SEPA_MAXBOUNDDIST 1.0
73#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
74#define SEPA_DELAY FALSE /**< should separation method be delayed, if other separators found cuts? */
75
76#define VIOLATIONFAC 100 /**< constraints regarded as violated when violation > VIOLATIONFAC*SCIPfeastol */
77#define MAX_ITER 75 /**< maximum number of iterations for the line search */
78
79#define DEFAULT_NLPITERLIM 1000 /**< default NLP iteration limit */
80
81#define NLPFEASFAC 1e-1/**< NLP feasibility tolerance = NLPFEASFAC * SCIP's feasibility tolerance */
82
83#define INTERIOROBJVARLB -100 /**< lower bound of the objective variable when computing interior point */
84
85/*
86 * Data structures
87 */
88
89/** side that makes a nlrow convex */
91{
92 LHS = 0, /**< left hand side */
93 RHS = 1 /**< right hand side */
94};
96
97/** position of a point */
99{
100 INTERIOR = 0, /**< point is in the interior of the region */
101 BOUNDARY = 1, /**< point is in the boundary of the region */
102 EXTERIOR = 2 /**< point is in the exterior of the region */
104typedef enum Position POSITION;
105
106/** separator data */
107struct SCIP_SepaData
108{
109 SCIP_NLROW** nlrows; /**< stores convex nlrows */
110 CONVEXSIDE* convexsides; /**< which sides make the nlrows convex */
111 int* nlrowsidx; /**< indices of nlrows that violate the current lp solution */
112 int nnlrowsidx; /**< total number of convex nonlinear nlrows that violate the current lp solution */
113 int nnlrows; /**< total number of convex nonlinear nlrows */
114 int nlrowssize; /**< memory allocated for nlrows, convexsides and nlrowsidx */
115
116 SCIP_Bool isintsolavailable; /**< do we have an interior point available? */
117 SCIP_Bool skipsepa; /**< whether separator should be skipped */
118 SCIP_SOL* intsol; /**< stores interior point */
119
120 int ncuts; /**< number of cuts generated */
121
122 /* parameters */
123 int nlpiterlimit; /**< iteration limit of NLP solver; 0 for no limit */
124};
125
126/*
127 * Local methods
128 */
129
130/** stores, from the constraints represented by nlrows, the nonlinear convex ones in sepadata */
131static
133 SCIP* scip, /**< SCIP data structure */
134 SCIP_SEPADATA* sepadata, /**< separator data */
135 SCIP_NLROW** nlrows, /**< nlrows from which to store convex ones */
136 int nnlrows /**< number of nlrows */
137 )
138{
139 int i;
140
141 assert(scip != NULL);
142 assert(sepadata != NULL);
143 assert(nlrows != NULL);
144 assert(nnlrows > 0);
145
146 SCIPdebugMsg(scip, "storing convex nlrows\n");
147
148 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->nlrows), nnlrows) );
149 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->convexsides), nnlrows) );
150 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->nlrowsidx), nnlrows) );
151 sepadata->nlrowssize = nnlrows;
152
153 sepadata->nnlrows = 0;
154 for( i = 0; i < nnlrows; ++i )
155 {
156 SCIP_NLROW* nlrow;
157
158 nlrow = nlrows[i];
159 assert(nlrow != NULL);
160
161 /* linear case */
163 continue;
164
165 /* nonlinear case */
167 {
168 sepadata->convexsides[sepadata->nnlrows] = RHS;
169 sepadata->nlrows[sepadata->nnlrows] = nlrow;
170 ++(sepadata->nnlrows);
171 }
173 {
174 sepadata->convexsides[sepadata->nnlrows] = LHS;
175 sepadata->nlrows[sepadata->nnlrows] = nlrow;
176 ++(sepadata->nnlrows);
177 }
178 }
179
180 return SCIP_OKAY;
181}
182
183/** computes an interior point of a convex NLP relaxation
184 *
185 * builds the convex relaxation, modifies it to find an interior
186 * point, solves it and frees it; more details in @ref sepa_gauge.h
187 *
188 * @note the method also counts the number of nonlinear convex constraints and if there are < 2, then the convex
189 * relaxation is not interesting and the separator will not run again
190 */
191static
193 SCIP* scip, /**< SCIP data structure */
194 SCIP_SEPADATA* sepadata /**< separator data */
195 )
196{
197 SCIP_NLPIORACLE* nlpioracle;
198 SCIP_NLPIPROBLEM* nlpiprob;
199 SCIP_NLPI* nlpi;
200 SCIP_HASHMAP* var2nlpiidx;
201 SCIP_Real objvarlb;
202 SCIP_Real minusone;
203 SCIP_Real one;
204 int nconvexnlrows;
205 int objvaridx;
206 int nconss;
207 int nvars;
208 int i;
209
210 assert(scip != NULL);
211 assert(sepadata != NULL);
212 assert(!sepadata->skipsepa);
213
214 SCIPdebugMsg(scip, "Computing interior point\n");
215
216 /* create convex relaxation NLP */
217 assert(SCIPgetNNlpis(scip) > 0);
218
219 nlpi = SCIPgetNlpis(scip)[0];
220 assert(nlpi != NULL);
221
222 nvars = SCIPgetNVars(scip);
223 SCIP_CALL( SCIPhashmapCreate(&var2nlpiidx, SCIPblkmem(scip), nvars) );
224 SCIP_CALL( SCIPcreateNlpiProblemFromNlRows(scip, nlpi, &nlpiprob, "gauge-interiorpoint-nlp", SCIPgetNLPNlRows(scip), SCIPgetNNLPNlRows(scip), var2nlpiidx,
226
227 /* add objective variable; the problem is \min t, s.t. g(x) <= t, l(x) <= 0, where g are nonlinear and l linear */
228 objvaridx = nvars;
229 objvarlb = INTERIOROBJVARLB;
230 one = 1.0;
231 SCIP_CALL( SCIPaddNlpiVars(scip, nlpi, nlpiprob, 1, &objvarlb, NULL, NULL) );
232 SCIP_CALL( SCIPsetNlpiObjective(scip, nlpi, nlpiprob, 1, &objvaridx, &one, NULL, 0.0) );
233
234 /* add objective variables to constraints; for this we need to get nlpi oracle to have access to number of
235 * constraints and which constraints are nonlinear
236 */
237 /* @todo: this code is only valid when using IPOPT and needs to be changed when new NLP solvers get interfaced */
238 assert(strcmp(SCIPnlpiGetName(nlpi), "ipopt") == 0);
239 nlpioracle = (SCIP_NLPIORACLE *)SCIPgetNlpiOracleIpopt(nlpiprob);
240 assert(nlpioracle != NULL);
241 assert(SCIPnlpiOracleGetNVars(nlpioracle) == objvaridx + 1);
242
243 minusone = -1.0;
244 nconvexnlrows = 0;
245 nconss = SCIPnlpiOracleGetNConstraints(nlpioracle);
246 for( i = 0; i < nconss; i++ )
247 {
248 if( SCIPnlpiOracleIsConstraintNonlinear(nlpioracle, i) )
249 {
250 SCIP_CALL( SCIPchgNlpiLinearCoefs(scip, nlpi, nlpiprob, i, 1, &objvaridx, &minusone) );
251 ++nconvexnlrows;
252 }
253 }
255
256 /* check if convex relaxation is interesting */
257 if( nconvexnlrows < 2 )
258 {
259 SCIPdebugMsg(scip, "convex relaxation is not interesting, only %d nonlinear convex rows; abort\n", nconvexnlrows);
260 sepadata->skipsepa = TRUE;
261 goto CLEANUP;
262 }
263
264 /* add linear rows */
265 SCIP_CALL( SCIPaddNlpiProblemRows(scip, nlpi, nlpiprob, var2nlpiidx, SCIPgetLPRows(scip), SCIPgetNLPRows(scip)) );
266
267 /* compute interior point */
268 SCIPdebugMsg(scip, "starting interior point computation\n");
269 SCIP_CALL( SCIPsolveNlpi(scip, nlpi, nlpiprob,
270 .iterlimit = sepadata->nlpiterlimit > 0 ? sepadata->nlpiterlimit : INT_MAX,
271 .feastol = NLPFEASFAC * SCIPfeastol(scip),
272 .opttol = MAX(SCIPfeastol(scip), SCIPdualfeastol(scip))) ); /*lint !e666*/
273 SCIPdebugMsg(scip, "finish interior point computation\n");
274
275#ifdef SCIP_DEBUG
276 {
277 SCIP_NLPSTATISTICS nlpstatistics;
278
279 /* get statistics */
280 SCIP_CALL( SCIPgetNlpiStatistics(scip, nlpi, nlpiprob, &nlpstatistics) );
281
282 SCIPdebugMsg(scip, "nlpi took iters %d, time %g searching for an find interior point: solstat %d\n",
283 nlpstatistics.niterations, nlpstatistics.totaltime,
284 SCIPgetNlpiSolstat(scip, nlpi, nlpiprob));
285 }
286#endif
287
288 if( SCIPgetNlpiSolstat(scip, nlpi, nlpiprob) <= SCIP_NLPSOLSTAT_FEASIBLE )
289 {
290 SCIP_Real* nlpisol;
291
292 SCIP_CALL( SCIPgetNlpiSolution(scip, 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[SCIPhashmapGetImageInt(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", SCIPgetNlpiSolstat(scip, nlpi, nlpiprob));
325 sepadata->skipsepa = TRUE;
326 }
327
328CLEANUP:
329 /* free memory */
330 SCIPhashmapFree(&var2nlpiidx);
331 SCIP_CALL( SCIPfreeNlpiProblem(scip, 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]` &le; rhs if `convexsides[i]` = RHS or lhs &le; `nlrows[i]` if `convexsides[i]` = LHS
339 *
340 * @note point corresponds to a convex combination between the LP solution and the interior point
341 */
342static
344 SCIP* scip, /**< SCIP data structure */
345 SCIP_NLROW** nlrows, /**< nlrows defining the region */
346 int* nlrowsidx, /**< indices of nlrows defining the region */
347 int nnlrowsidx, /**< number of nlrows indices */
348 CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
349 SCIP_SOL* point, /**< point for which we want to know its position */
350 POSITION* position /**< buffer to store position of sol */
351 )
352{
353 int i;
354
355 assert(scip != NULL);
356 assert(nlrows != NULL);
357 assert(convexsides != NULL);
358 assert(nnlrowsidx > 0);
359 assert(point != NULL);
360 assert(position != NULL);
361
362 *position = INTERIOR;
363 for( i = 0; i < nnlrowsidx; i++ )
364 {
365 SCIP_NLROW* nlrow;
366 SCIP_Real activity;
367 CONVEXSIDE convexside;
368
369 nlrow = nlrows[nlrowsidx[i]];
370 convexside = convexsides[nlrowsidx[i]];
371
372 /* compute activity of nlrow at point */
373 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, point, &activity) );
374
375 if( convexside == RHS )
376 {
377 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
378
379 /* if nlrow <= rhs is violated, then we are in the exterior */
380 if( SCIPisFeasGT(scip, activity, SCIPnlrowGetRhs(nlrow)) )
381 {
382 *position = EXTERIOR;
383 SCIPdebugMsg(scip, "exterior because cons <%s> has activity %g. rhs: %g\n", SCIPnlrowGetName(nlrow),
384 activity, SCIPnlrowGetRhs(nlrow));
385 SCIPdebug( SCIPprintNlRow(scip, nlrow, NULL) );
386
387 return SCIP_OKAY;
388 }
389
390 /* if nlrow(point) == rhs, then we are currently at the boundary */
391 if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow)) )
392 *position = BOUNDARY;
393 }
394 else
395 {
396 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
397 assert(convexside == LHS);
398
399 /* if lhs <= nlrow is violated, then we are in the exterior */
400 if( SCIPisFeasLT(scip, activity, SCIPnlrowGetLhs(nlrow)) )
401 {
402 *position = EXTERIOR;
403 return SCIP_OKAY;
404 }
405
406 /* if lhs == nlrow(point), then we are currently at the boundary */
407 if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow)) )
408 *position = BOUNDARY;
409 }
410 }
411
412 return SCIP_OKAY;
413}
414
415
416/** returns, in convexcomb, the convex combination
417 * \f$ \lambda\, \text{endpoint} + (1 - \lambda) \text{startpoint} = \text{startpoint} + \lambda (\text{endpoint} - \text{startpoint})\f$
418 */
419static
421 SCIP* scip, /**< SCIP data structure */
422 SCIP_Real lambda, /**< convex combination multiplier */
423 SCIP_SOL* startpoint, /**< point corresponding to \f$ \lambda = 0 \f$ */
424 SCIP_SOL* endpoint, /**< point corresponding to \f$ \lambda = 1 \f$ */
425 SCIP_SOL* convexcomb /**< solution to store convex combination of intsol and tosepasol */
426 )
427{
428 SCIP_VAR** vars;
429 int nvars;
430 int i;
431
432 assert(scip != NULL);
433 assert(startpoint != NULL);
434 assert(endpoint != NULL);
435 assert(convexcomb != NULL);
436
437 vars = SCIPgetVars(scip);
438 nvars = SCIPgetNVars(scip);
439
440 for( i = 0; i < nvars; i++ )
441 {
442 SCIP_Real val;
443 SCIP_VAR* var;
444
445 var = vars[i];
446 val = lambda * SCIPgetSolVal(scip, endpoint, var) + (1.0 - lambda) * SCIPgetSolVal(scip, startpoint, var);
447
448 if( !SCIPisZero(scip, val) )
449 {
450 SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, val) );
451 }
452 else
453 {
454 SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, 0.0) );
455 }
456 }
457
458 return SCIP_OKAY;
459}
460
461
462/** performs binary search to find the point belonging to the segment [`intsol`, `tosepasol`] that intersects the boundary
463 * of the region described by the intersection of `nlrows[i]` &le; rhs if `convexsides[i] = RHS` or lhs &le; `nlrows[i]` if not,
464 * for i in `nlrowsidx`
465 */
466static
468 SCIP* scip, /**< SCIP data structure */
469 SCIP_NLROW** nlrows, /**< nlrows defining the region */
470 int* nlrowsidx, /**< indices of nlrows defining the region */
471 int nnlrowsidx, /**< number of nlrows indices */
472 CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
473 SCIP_SOL* intsol, /**< point acting as 'interior point' */
474 SCIP_SOL* tosepasol, /**< solution that should be separated */
475 SCIP_SOL* sol, /**< convex combination of intsol and lpsol */
476 POSITION* position /**< buffer to store position of sol */
477 )
478{
479 SCIP_Real lb;
480 SCIP_Real ub;
481 int i;
482
483 assert(scip != NULL);
484 assert(nlrows != NULL);
485 assert(nlrowsidx != NULL);
486 assert(convexsides != NULL);
487 assert(intsol != NULL);
488 assert(tosepasol != NULL);
489 assert(sol != NULL);
490 assert(position != NULL);
491
492 SCIPdebugMsg(scip, "starting binary search\n");
493 lb = 0.0; /* corresponds to intsol */
494 ub = 1.0; /* corresponds to tosepasol */
495 for( i = 0; i < MAX_ITER; i++ )
496 {
497 /* sol = (ub+lb)/2 * lpsol + (1 - (ub+lb)/2) * intsol */
498 SCIP_CALL( buildConvexCombination(scip, (ub + lb)/2.0, intsol, tosepasol, sol) );
499
500 /* find poisition of point: boundary, interior, exterior */
501 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, position) );
502 SCIPdebugMsg(scip, "Position: %d, lambda: %g\n", *position, (ub + lb)/2.0);
503
504 switch( *position )
505 {
506 case BOUNDARY:
507 SCIPdebugMsg(scip, "Done\n");
508 return SCIP_OKAY;
509
510 case INTERIOR:
511 /* want to be closer to tosepasol */
512 lb = (ub + lb)/2.0;
513 break;
514
515 case EXTERIOR:
516 /* want to be closer to intsol */
517 ub = (ub + lb)/2.0;
518 break;
519 }
520 }
521 SCIPdebugMsg(scip, "Done\n");
522 return SCIP_OKAY;
523}
524
525
526/** computes gradient cut (linearization) of nlrow at sol */
527static
529 SCIP* scip, /**< SCIP data structure */
530 SCIP_SOL* sol, /**< point used to construct gradient cut (x_0) */
531 SCIP_NLROW* nlrow, /**< constraint */
532 CONVEXSIDE convexside, /**< whether we use rhs or lhs of nlrow */
533 SCIP_EXPRITER* exprit, /**< expression iterator that can be used */
534 SCIP_ROW* row, /**< storage for cut */
535 SCIP_Bool* success /**< buffer to store whether the gradient was finite */
536 )
537{
538 SCIP_EXPR* expr;
539 SCIP_Real exprval;
540 SCIP_Real gradx0; /* <grad f(x_0), x_0> */
541 int i;
542
543 assert(scip != NULL);
544 assert(nlrow != NULL);
545 assert(row != NULL);
546
547 gradx0 = 0.0;
548 *success = TRUE;
549
551
552#ifdef CUT_DEBUG
554#endif
555
556 /* linear part */
557 for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
558 {
560 }
561
562 expr = SCIPnlrowGetExpr(nlrow);
563 assert(expr != NULL);
564
565 SCIP_CALL( SCIPevalExprGradient(scip, expr, sol, 0L) );
566
568 for( ; !SCIPexpriterIsEnd(exprit); expr = SCIPexpriterGetNext(exprit) ) /*lint !e441*/ /*lint !e440*/
569 {
570 SCIP_Real grad;
571 SCIP_VAR* var;
572
573 if( !SCIPisExprVar(scip, expr) )
574 continue;
575
576 grad = SCIPexprGetDerivative(expr);
577 var = SCIPgetVarExprVar(expr);
578 assert(var != NULL);
579
580 /* check gradient entries: function might not be differentiable */
581 if( !SCIPisFinite(grad) || grad == SCIP_INVALID ) /*lint !e777*/
582 {
583 *success = FALSE;
584 break;
585 }
586 /* SCIPdebugMsg(scip, "grad w.r.t. <%s> (%g) = %g, gradx0 += %g\n", SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var), grad, grad * SCIPgetSolVal(scip, sol, var)); */
587
588 gradx0 += grad * SCIPgetSolVal(scip, sol, var);
589 SCIP_CALL( SCIPaddVarToRow(scip, row, var, grad) );
590 }
591
593
594 /* if there was a problem computing the cut -> return */
595 if( ! *success )
596 return SCIP_OKAY;
597
598#ifdef CUT_DEBUG
599 SCIPdebugMsg(scip, "gradient: ");
601 SCIPdebugMsg(scip, "gradient dot x_0: %g\n", gradx0);
602#endif
603
604 /* gradient cut is linear part + f(x_0) - <grad f(x_0), x_0> + <grad f(x_0), x> <= rhs or >= lhs */
605 exprval = SCIPexprGetEvalValue(SCIPnlrowGetExpr(nlrow));
606 assert(exprval != SCIP_INVALID); /* we should have noticed a domain error above */ /*lint !e777*/
607 if( convexside == RHS )
608 {
609 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
610 SCIP_CALL( SCIPchgRowRhs(scip, row, SCIPnlrowGetRhs(nlrow) - SCIPnlrowGetConstant(nlrow) - exprval + gradx0) );
611 }
612 else
613 {
614 assert(convexside == LHS);
615 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
616 SCIP_CALL( SCIPchgRowLhs(scip, row, SCIPnlrowGetLhs(nlrow) - SCIPnlrowGetConstant(nlrow) - exprval + gradx0) );
617 }
618
619#ifdef CUT_DEBUG
620 SCIPdebugMsg(scip, "gradient cut: ");
622#endif
623
624 return SCIP_OKAY;
625}
626
627/** tries to generate gradient cuts at the point on the segment [`intsol`, `tosepasol`] that intersecs the boundary of the
628 * convex relaxation
629 *
630 * -# checks that the relative interior of the segment actually intersects the boundary
631 * (this check is needed since `intsol` is not necessarily an interior point)
632 * -# finds point on the boundary
633 * -# generates gradient cut at point on the boundary
634 */
635static
637 SCIP* scip, /**< SCIP data structure */
638 SCIP_SEPA* sepa, /**< the cut separator itself */
639 SCIP_SOL* tosepasol, /**< solution that should be separated */
640 SCIP_RESULT* result /**< pointer to store the result of the separation call */
641 )
642{
643 SCIP_SEPADATA* sepadata;
644 SCIP_NLROW** nlrows;
645 CONVEXSIDE* convexsides;
646 SCIP_SOL* sol;
647 SCIP_SOL* intsol;
648 POSITION position;
649 int* nlrowsidx;
650 int nnlrowsidx;
651 int i;
652 SCIP_EXPRITER* exprit;
653
654 assert(sepa != NULL);
655
656 sepadata = SCIPsepaGetData(sepa);
657 assert(sepadata != NULL);
658
659 intsol = sepadata->intsol;
660 nlrows = sepadata->nlrows;
661 nlrowsidx = sepadata->nlrowsidx;
662 nnlrowsidx = sepadata->nnlrowsidx;
663 convexsides = sepadata->convexsides;
664
665 assert(intsol != NULL);
666 assert(nlrows != NULL);
667 assert(nlrowsidx != NULL);
668 assert(nnlrowsidx > 0);
669 assert(convexsides != NULL);
670
671 /* to evaluate the nlrow one needs a solution */
672 SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
673
674 /* don't separate if, under SCIP tolerances, only a slight perturbation of the interior point in the direction of
675 * tosepasol gives a point that is in the exterior */
676 SCIP_CALL( buildConvexCombination(scip, VIOLATIONFAC * SCIPfeastol(scip), intsol, tosepasol, sol) );
677 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
678
679 if( position == EXTERIOR )
680 {
681#ifdef SCIP_DEBUG
682 SCIPdebugMsg(scip, "segment joining intsol and tosepasol seems to be contained in the exterior of the region, can't separate\n");
683 /* move from intsol in the direction of -tosepasol to check if we are really tangent to the region */
684 SCIP_CALL( buildConvexCombination(scip, -1e-3, intsol, tosepasol, sol) );
685 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
686 if( position == EXTERIOR )
687 {
688 SCIPdebugMsg(scip, "line through intsol and tosepasol is tangent to region; can't separate\n");
689 }
690 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, &position) );
691 printf("Position of intsol is %s\n",
692 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
693 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, tosepasol, &position) );
694 printf("Position of tosepasol is %s\n",
695 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
696
697 /* slightly move from intsol in the direction of +-tosepasol */
698 SCIP_CALL( buildConvexCombination(scip, 1e-5, intsol, tosepasol, sol) );
699 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
700 printf("Position of intsol + 0.00001(tosepasol - inisol) is %s\n",
701 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
703
704 SCIP_CALL( buildConvexCombination(scip, -1e-5, intsol, tosepasol, sol) );
705 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
706 printf("Position of intsol - 0.00001(tosepasol - inisol) is %s\n",
707 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
709#endif
710 *result = SCIP_DIDNOTFIND;
711 goto CLEANUP;
712 }
713
714 /* find point on boundary */
715 if( position != BOUNDARY )
716 {
717 SCIP_CALL( findBoundaryPoint(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, tosepasol, sol,
718 &position) );
719
720 /* if MAX_ITER weren't enough to find a point in the boundary we don't separate */
721 if( position != BOUNDARY )
722 {
723 SCIPdebugMsg(scip, "couldn't find boundary point, don't separate\n");
724 goto CLEANUP;
725 }
726 }
727
728 /** @todo: could probably be moved inside generateCut */
729 SCIP_CALL( SCIPcreateExpriter(scip, &exprit) );
730
731 /* generate cuts at sol */
732 for( i = 0; i < nnlrowsidx; i++ )
733 {
734 SCIP_NLROW* nlrow;
735 SCIP_ROW* row;
736 SCIP_Real activity;
737 CONVEXSIDE convexside;
738 SCIP_Bool success;
739 char rowname[SCIP_MAXSTRLEN];
740
741 nlrow = nlrows[nlrowsidx[i]];
742 convexside = convexsides[nlrowsidx[i]];
743
744 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%u", SCIPnlrowGetName(nlrow), ++(sepadata->ncuts));
745
746 /* only separate nlrows that are tight at the boundary point */
747 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
748 SCIPdebugMsg(scip, "cons <%s> at boundary point has activity: %g\n", SCIPnlrowGetName(nlrow), activity);
749
750 if( (convexside == RHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow)))
751 || (convexside == LHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow))) )
752 continue;
753
754 /* cut is globally valid, since we work on nlrows from the NLP built at the root node, which are globally valid */
755 /* @todo: when local nlrows get supported in SCIP, one can think of recomputing the interior point */
757 FALSE, FALSE , TRUE) );
758 SCIP_CALL( generateCut(scip, sol, nlrow, convexside, exprit, row, &success) );
759
760 /* add cut */
761 SCIPdebugMsg(scip, "cut <%s> has efficacy %g\n", SCIProwGetName(row), SCIPgetCutEfficacy(scip, NULL, row));
762 if( success && SCIPisCutEfficacious(scip, NULL, row) )
763 {
764 SCIP_Bool infeasible;
765
766 SCIPdebugMsg(scip, "adding cut\n");
767 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
768
769 if( infeasible )
770 {
771 *result = SCIP_CUTOFF;
772 SCIP_CALL( SCIPreleaseRow(scip, &row) );
773 break;
774 }
775 else
776 {
777 *result = SCIP_SEPARATED;
778 }
779 }
780
781 /* release the row */
782 SCIP_CALL( SCIPreleaseRow(scip, &row) );
783 }
784
785 SCIPfreeExpriter(&exprit);
786
787CLEANUP:
788 SCIP_CALL( SCIPfreeSol(scip, &sol) );
789
790 return SCIP_OKAY;
791}
792
793/*
794 * Callback methods of separator
795 */
796
797/** copy method for separator plugins (called when SCIP copies plugins) */
798static
799SCIP_DECL_SEPACOPY(sepaCopyGauge)
800{ /*lint --e{715}*/
801 assert(scip != NULL);
802 assert(sepa != NULL);
803 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
804
805 /* call inclusion method of separator */
807
808 return SCIP_OKAY;
809}
810
811/** destructor of separator to free user data (called when SCIP is exiting) */
812static
813SCIP_DECL_SEPAFREE(sepaFreeGauge)
814{ /*lint --e{715}*/
815 SCIP_SEPADATA* sepadata;
816
817 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
818
819 /* free separator data */
820 sepadata = SCIPsepaGetData(sepa);
821 assert(sepadata != NULL);
822
823 SCIPfreeBlockMemory(scip, &sepadata);
824
825 SCIPsepaSetData(sepa, NULL);
826
827 return SCIP_OKAY;
828}
829
830
831/** solving process deinitialization method of separator (called before branch and bound process data is freed) */
832static
833SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
834{ /*lint --e{715}*/
835 SCIP_SEPADATA* sepadata;
836
837 assert(sepa != NULL);
838
839 sepadata = SCIPsepaGetData(sepa);
840
841 assert(sepadata != NULL);
842
843 /* free memory and reset data */
844 if( sepadata->isintsolavailable )
845 {
846 SCIPfreeBlockMemoryArray(scip, &sepadata->nlrowsidx, sepadata->nlrowssize);
847 SCIPfreeBlockMemoryArray(scip, &sepadata->convexsides, sepadata->nlrowssize);
848 SCIPfreeBlockMemoryArray(scip, &sepadata->nlrows, sepadata->nlrowssize);
849 SCIP_CALL( SCIPfreeSol(scip, &sepadata->intsol) );
850
851 sepadata->nnlrows = 0;
852 sepadata->nnlrowsidx = 0;
853 sepadata->nlrowssize = 0;
854 sepadata->isintsolavailable = FALSE;
855 }
856 assert(sepadata->nnlrows == 0);
857 assert(sepadata->nnlrowsidx == 0);
858 assert(sepadata->nlrowssize == 0);
859 assert(sepadata->isintsolavailable == FALSE);
860
861 sepadata->skipsepa = FALSE;
862
863 return SCIP_OKAY;
864}
865
866
867/** LP solution separation method of separator */
868static
869SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
870{ /*lint --e{715}*/
871 SCIP_SEPADATA* sepadata;
872 SCIP_SOL* lpsol;
873 int i;
874
875 assert(scip != NULL);
876 assert(sepa != NULL);
877
878 sepadata = SCIPsepaGetData(sepa);
879
880 assert(sepadata != NULL);
881
882 *result = SCIP_DIDNOTRUN;
883
884 /* do not run if there is no interesting convex relaxation (with at least two nonlinear convex constraint) */
885 if( sepadata->skipsepa )
886 {
887 SCIPdebugMsg(scip, "not running because convex relaxation is uninteresting\n");
888 return SCIP_OKAY;
889 }
890
891 /* do not run if SCIP has not constructed an NLP */
893 {
894 SCIPdebugMsg(scip, "NLP not constructed, skipping gauge separator\n");
895 return SCIP_OKAY;
896 }
897
898 /* do not run if SCIP has no way of solving nonlinear problems */
899 if( SCIPgetNNlpis(scip) == 0 )
900 {
901 SCIPdebugMsg(scip, "Skip gauge separator: no nlpi and SCIP can't solve nonlinear problems without a nlpi\n");
902 return SCIP_OKAY;
903 }
904
905 /* if we don't have an interior point compute one; if we fail to compute one, then separator will not be run again;
906 * otherwise, we also store the convex nlrows in sepadata
907 */
908 if( !sepadata->isintsolavailable )
909 {
910 /* @todo: one could store the convex nonlinear rows inside computeInteriorPoint */
911 SCIP_CALL( computeInteriorPoint(scip, sepadata) );
912 assert(sepadata->skipsepa || sepadata->isintsolavailable);
913
914 if( sepadata->skipsepa )
915 return SCIP_OKAY;
916
918 }
919
920#ifdef SCIP_DISABLED_CODE
921 /* get interior point: try to compute an interior point, otherwise use primal solution, otherwise use NLP solution */
922 /* @todo: - decide order:
923 * - we can also use convex combination of solutions; there is a function SCIPvarGetAvgSol!
924 * - can add an event handler to only update when a new solution has been found
925 */
926 if( !sepadata->isintsolavailable )
927 {
928 if( SCIPgetNSols(scip) > 0 )
929 {
930 SCIPdebugMsg(scip, "Using current primal solution as interior point!\n");
931 SCIP_CALL( SCIPcreateSolCopy(scip, &sepadata->intsol, SCIPgetBestSol(scip)) );
932 sepadata->isintsolavailable = TRUE;
933 }
935 {
936 SCIPdebugMsg(scip, "Using NLP solution as interior point!\n");
937 SCIP_CALL( SCIPcreateNLPSol(scip, &sepadata->intsol, NULL) );
938 sepadata->isintsolavailable = TRUE;
939 }
940 else
941 {
942 SCIPdebugMsg(scip, "We couldn't find an interior point, don't have a feasible nor an NLP solution; skip separator\n");
943 return SCIP_OKAY;
944 }
945 }
946#endif
947
948 /* store lp sol (or pseudo sol when lp is not solved) to be able to use it to compute nlrows' activities */
950
951 /* store indices of relevant constraints, ie, the ones that violate the lp sol */
952 sepadata->nnlrowsidx = 0;
953 for( i = 0; i < sepadata->nnlrows; i++ )
954 {
955 SCIP_NLROW* nlrow;
956 SCIP_Real activity;
957
958 nlrow = sepadata->nlrows[i];
959
960 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, lpsol, &activity) );
961
962 if( sepadata->convexsides[i] == RHS )
963 {
964 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
965
966 if( activity - SCIPnlrowGetRhs(nlrow) < VIOLATIONFAC * SCIPfeastol(scip) )
967 continue;
968 }
969 else
970 {
971 assert(sepadata->convexsides[i] == LHS);
972 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
973
974 if( SCIPnlrowGetLhs(nlrow) - activity < VIOLATIONFAC * SCIPfeastol(scip) )
975 continue;
976 }
977
978 sepadata->nlrowsidx[sepadata->nnlrowsidx] = i;
979 ++(sepadata->nnlrowsidx);
980 }
981
982 /* separate only if there are violated nlrows */
983 SCIPdebugMsg(scip, "there are %d violated nlrows\n", sepadata->nnlrowsidx);
984 if( sepadata->nnlrowsidx > 0 )
985 {
986 SCIP_CALL( separateCuts(scip, sepa, lpsol, result) );
987 }
988
989 /* free lpsol */
990 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
991
992 return SCIP_OKAY;
993}
994
995
996/*
997 * separator specific interface methods
998 */
999
1000/** creates the gauge separator and includes it in SCIP */
1002 SCIP* scip /**< SCIP data structure */
1003 )
1004{
1005 SCIP_SEPADATA* sepadata;
1006 SCIP_SEPA* sepa;
1007
1008 /* create gauge separator data */
1009 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
1010
1011 /* this sets all data in sepadata to 0 */
1012 BMSclearMemory(sepadata);
1013
1014 /* include separator */
1017 sepaExeclpGauge, NULL,
1018 sepadata) );
1019
1020 assert(sepa != NULL);
1021
1022 /* set non fundamental callbacks via setter functions */
1023 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyGauge) );
1024 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeGauge) );
1025 SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolGauge) );
1026
1027 /* add gauge separator parameters */
1028 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/nlpiterlimit",
1029 "iteration limit of NLP solver; 0 for no limit",
1030 &sepadata->nlpiterlimit, TRUE, DEFAULT_NLPITERLIM, 0, INT_MAX, NULL, NULL) );
1031
1032 return SCIP_OKAY;
1033}
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL(x)
Definition: def.h:373
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3111
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3077
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3426
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_Bool SCIPnlpiOracleIsConstraintNonlinear(SCIP_NLPIORACLE *oracle, int considx)
Definition: nlpioracle.c:1847
SCIP_RETCODE SCIPnlpiOraclePrintProblem(SCIP *scip, SCIP_NLPIORACLE *oracle, FILE *file)
Definition: nlpioracle.c:2454
int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:1716
int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
Definition: nlpioracle.c:1726
void * SCIPgetNlpiOracleIpopt(SCIP_NLPIPROBLEM *nlpiproblem)
#define SCIPisFinite(x)
Definition: pub_misc.h:1933
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_param.c:83
SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip_cut.c:94
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip_cut.c:117
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
SCIP_RETCODE SCIPevalExprGradient(SCIP *scip, SCIP_EXPR *expr, SCIP_SOL *sol, SCIP_Longint soltag)
Definition: scip_expr.c:1667
SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
Definition: expriter.c:969
SCIP_Real SCIPexprGetDerivative(SCIP_EXPR *expr)
Definition: expr.c:3960
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1431
SCIP_RETCODE SCIPcreateExpriter(SCIP *scip, SCIP_EXPRITER **iterator)
Definition: scip_expr.c:2337
SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
Definition: expr.c:3934
SCIP_EXPR * SCIPexpriterGetNext(SCIP_EXPRITER *iterator)
Definition: expriter.c:858
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
void SCIPfreeExpriter(SCIP_EXPRITER **iterator)
Definition: scip_expr.c:2351
SCIP_RETCODE SCIPexpriterInit(SCIP_EXPRITER *iterator, SCIP_EXPR *expr, SCIP_EXPRITER_TYPE type, SCIP_Bool allowrevisit)
Definition: expriter.c:501
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
Definition: scip_lp.c:605
int SCIPgetNLPRows(SCIP *scip)
Definition: scip_lp.c:626
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_RETCODE SCIPaddNlpiProblemRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM *nlpiprob, SCIP_HASHMAP *var2idx, SCIP_ROW **rows, int nrows)
Definition: scip_nlpi.c:782
#define SCIPsolveNlpi(scip, nlpi,...)
Definition: scip_nlpi.h:208
const char * SCIPnlpiGetName(SCIP_NLPI *nlpi)
Definition: nlpi.c:722
SCIP_RETCODE SCIPcreateNlpiProblemFromNlRows(SCIP *scip, SCIP_NLPI *nlpi, SCIP_NLPIPROBLEM **nlpiprob, const char *name, SCIP_NLROW **nlrows, int nnlrows, SCIP_HASHMAP *var2idx, SCIP_HASHMAP *nlrow2idx, SCIP_Real *nlscore, SCIP_Real cutoffbound, SCIP_Bool setobj, SCIP_Bool onlyconvex)
Definition: scip_nlpi.c:444
int SCIPgetNNlpis(SCIP *scip)
Definition: scip_nlpi.c:200
SCIP_NLPI ** SCIPgetNlpis(SCIP *scip)
Definition: scip_nlpi.c:187
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
int SCIPgetNNLPNlRows(SCIP *scip)
Definition: scip_nlp.c:341
SCIP_NLROW ** SCIPgetNLPNlRows(SCIP *scip)
Definition: scip_nlp.c:319
const char * SCIPnlrowGetName(SCIP_NLROW *nlrow)
Definition: nlp.c:1936
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:1917
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:1907
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition: nlp.c:1927
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:1867
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:1877
SCIP_Real SCIPnlrowGetConstant(SCIP_NLROW *nlrow)
Definition: nlp.c:1857
SCIP_EXPR * SCIPnlrowGetExpr(SCIP_NLROW *nlrow)
Definition: nlp.c:1897
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition: nlp.c:1887
SCIP_RETCODE SCIPprintNlRow(SCIP *scip, SCIP_NLROW *nlrow, FILE *file)
Definition: scip_nlp.c:1601
SCIP_RETCODE SCIPgetNlRowSolActivity(SCIP *scip, SCIP_NLROW *nlrow, SCIP_SOL *sol, SCIP_Real *activity)
Definition: scip_nlp.c:1508
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1635
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1583
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1658
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17351
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
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_lp.c:1453
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1607
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_sepa.c:109
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition: sepa.c:743
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
Definition: scip_sepa.c:167
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol)))
Definition: scip_sepa.c:231
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition: sepa.c:633
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition: sepa.c:643
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
Definition: scip_sepa.c:151
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2165
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:180
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip_sol.c:470
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:837
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip_sol.c:1627
SCIP_RETCODE SCIPcreateCurrentSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:335
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:250
int SCIPgetNSols(SCIP *scip)
Definition: scip_sol.c:2066
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip_sol.c:1073
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPdualfeastol(SCIP *scip)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPincludeSepaGauge(SCIP *scip)
Definition: sepa_gauge.c:1001
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10880
memory allocation routines
#define BMSclearMemory(ptr)
Definition: memory.h:129
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
SCIP_NLPSOLSTAT SCIPnlpGetSolstat(SCIP_NLP *nlp)
Definition: nlp.c:4506
Ipopt NLP interface.
methods to store an NLP and request function, gradient, and Hessian values
public functions to work with algebraic expressions
public methods for LP management
public methods for message output
#define SCIPdebug(x)
Definition: pub_message.h:93
public data structures and miscellaneous methods
public methods for NLP management
public methods for separators
public methods for problem variables
public methods for cuts and aggregation rows
public functions to work with algebraic expressions
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for NLPI solver interfaces
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for separator plugins
public methods for solutions
public methods for querying solving statistics
public methods for timing
ConvexSide
enum ConvexSide CONVEXSIDE
#define SEPA_PRIORITY
Definition: sepa_gauge.c:70
#define SEPA_DELAY
Definition: sepa_gauge.c:74
static SCIP_RETCODE generateCut(SCIP *scip, SCIP_SOL *sol, SCIP_NLROW *nlrow, CONVEXSIDE convexside, SCIP_EXPRITER *exprit, SCIP_ROW *row, SCIP_Bool *success)
Definition: sepa_gauge.c:528
enum Position POSITION
Definition: sepa_gauge.c:104
@ LHS
Definition: sepa_gauge.c:92
@ RHS
Definition: sepa_gauge.c:93
static SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
Definition: sepa_gauge.c:833
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:467
#define SEPA_DESC
Definition: sepa_gauge.c:69
static SCIP_RETCODE computeInteriorPoint(SCIP *scip, SCIP_SEPADATA *sepadata)
Definition: sepa_gauge.c:192
#define INTERIOROBJVARLB
Definition: sepa_gauge.c:83
#define SEPA_USESSUBSCIP
Definition: sepa_gauge.c:73
static SCIP_DECL_SEPACOPY(sepaCopyGauge)
Definition: sepa_gauge.c:799
static SCIP_DECL_SEPAFREE(sepaFreeGauge)
Definition: sepa_gauge.c:813
static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *tosepasol, SCIP_RESULT *result)
Definition: sepa_gauge.c:636
#define NLPFEASFAC
Definition: sepa_gauge.c:81
static SCIP_RETCODE buildConvexCombination(SCIP *scip, SCIP_Real lambda, SCIP_SOL *startpoint, SCIP_SOL *endpoint, SCIP_SOL *convexcomb)
Definition: sepa_gauge.c:420
static SCIP_RETCODE findPointPosition(SCIP *scip, SCIP_NLROW **nlrows, int *nlrowsidx, int nnlrowsidx, CONVEXSIDE *convexsides, SCIP_SOL *point, POSITION *position)
Definition: sepa_gauge.c:343
enum ConvexSide CONVEXSIDE
Definition: sepa_gauge.c:95
#define SEPA_MAXBOUNDDIST
Definition: sepa_gauge.c:72
#define SEPA_FREQ
Definition: sepa_gauge.c:71
Position
Definition: sepa_gauge.c:99
@ EXTERIOR
Definition: sepa_gauge.c:102
@ INTERIOR
Definition: sepa_gauge.c:100
@ BOUNDARY
Definition: sepa_gauge.c:101
#define DEFAULT_NLPITERLIM
Definition: sepa_gauge.c:79
#define SEPA_NAME
Definition: sepa_gauge.c:68
#define MAX_ITER
Definition: sepa_gauge.c:77
#define VIOLATIONFAC
Definition: sepa_gauge.c:76
static SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
Definition: sepa_gauge.c:869
static SCIP_RETCODE storeNonlinearConvexNlrows(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_NLROW **nlrows, int nnlrows)
Definition: sepa_gauge.c:132
gauge separator
SCIP_Real totaltime
Definition: type_nlpi.h:200
@ SCIP_EXPRCURV_CONVEX
Definition: type_expr.h:63
@ SCIP_EXPRCURV_LINEAR
Definition: type_expr.h:65
@ SCIP_EXPRCURV_CONCAVE
Definition: type_expr.h:64
@ SCIP_EXPRITER_DFS
Definition: type_expr.h:716
@ SCIP_NLPSOLSTAT_FEASIBLE
Definition: type_nlpi.h:162
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_SEPARATED
Definition: type_result.h:49
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
struct SCIP_SepaData SCIP_SEPADATA
Definition: type_sepa.h:52