SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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-2026 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
38#include "scip/scip_nlpi.h"
39#include "scip/nlpi_ipopt.h"
40#include "scip/nlpioracle.h"
41#include "scip/scip_expr.h"
42#include "scip/pub_expr.h"
43#include "scip/pub_lp.h"
44#include "scip/pub_message.h"
45#include "scip/pub_misc.h"
46#include "scip/pub_nlp.h"
47#include "scip/pub_sepa.h"
48#include "scip/pub_var.h"
49#include "scip/scip_cut.h"
50#include "scip/scip_lp.h"
51#include "scip/scip_mem.h"
52#include "scip/scip_message.h"
53#include "scip/scip_nlp.h"
54#include "scip/scip_numerics.h"
55#include "scip/scip_param.h"
56#include "scip/scip_prob.h"
57#include "scip/scip_sepa.h"
58#include "scip/scip_sol.h"
60#include "scip/scip_timing.h"
61#include "scip/sepa_gauge.h"
62
63
64#define SEPA_NAME "gauge"
65#define SEPA_DESC "gauge separator"
66#define SEPA_PRIORITY 0
67#define SEPA_FREQ -1
68#define SEPA_MAXBOUNDDIST 1.0
69#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
70#define SEPA_DELAY FALSE /**< should separation method be delayed, if other separators found cuts? */
71
72#define VIOLATIONFAC 100 /**< constraints regarded as violated when violation > VIOLATIONFAC*SCIPfeastol */
73#define MAX_ITER 75 /**< maximum number of iterations for the line search */
74
75#define DEFAULT_NLPITERLIM 1000 /**< default NLP iteration limit */
76
77#define NLPFEASFAC 1e-1/**< NLP feasibility tolerance = NLPFEASFAC * SCIP's feasibility tolerance */
78
79#define INTERIOROBJVARLB -100 /**< lower bound of the objective variable when computing interior point */
80
81/*
82 * Data structures
83 */
84
85/** side that makes a nlrow convex */
87{
88 LHS = 0, /**< left hand side */
89 RHS = 1 /**< right hand side */
90};
91typedef enum ConvexSide CONVEXSIDE;
92
93/** position of a point */
95{
96 INTERIOR = 0, /**< point is in the interior of the region */
97 BOUNDARY = 1, /**< point is in the boundary of the region */
98 EXTERIOR = 2 /**< point is in the exterior of the region */
99};
100typedef enum Position POSITION;
101
102/** separator data */
103struct SCIP_SepaData
104{
105 SCIP_NLROW** nlrows; /**< stores convex nlrows */
106 CONVEXSIDE* convexsides; /**< which sides make the nlrows convex */
107 int* nlrowsidx; /**< indices of nlrows that violate the current lp solution */
108 int nnlrowsidx; /**< total number of convex nonlinear nlrows that violate the current lp solution */
109 int nnlrows; /**< total number of convex nonlinear nlrows */
110 int nlrowssize; /**< memory allocated for nlrows, convexsides and nlrowsidx */
111
112 SCIP_Bool isintsolavailable; /**< do we have an interior point available? */
113 SCIP_Bool skipsepa; /**< whether separator should be skipped */
114 SCIP_SOL* intsol; /**< stores interior point */
115
116 int ncuts; /**< number of cuts generated */
117
118 /* parameters */
119 int nlpiterlimit; /**< iteration limit of NLP solver; 0 for no limit */
120};
121
122/*
123 * Local methods
124 */
125
126/** stores, from the constraints represented by nlrows, the nonlinear convex ones in sepadata */
127static
129 SCIP* scip, /**< SCIP data structure */
130 SCIP_SEPADATA* sepadata, /**< separator data */
131 SCIP_NLROW** nlrows, /**< nlrows from which to store convex ones */
132 int nnlrows /**< number of nlrows */
133 )
134{
135 int i;
136
137 assert(scip != NULL);
138 assert(sepadata != NULL);
139 assert(nlrows != NULL);
140 assert(nnlrows > 0);
141
142 SCIPdebugMsg(scip, "storing convex nlrows\n");
143
144 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->nlrows), nnlrows) );
145 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->convexsides), nnlrows) );
146 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->nlrowsidx), nnlrows) );
147 sepadata->nlrowssize = nnlrows;
148
149 sepadata->nnlrows = 0;
150 for( i = 0; i < nnlrows; ++i )
151 {
152 SCIP_NLROW* nlrow;
153
154 nlrow = nlrows[i];
155 assert(nlrow != NULL);
156
157 /* linear case */
159 continue;
160
161 /* nonlinear case */
163 {
164 sepadata->convexsides[sepadata->nnlrows] = RHS;
165 sepadata->nlrows[sepadata->nnlrows] = nlrow;
166 ++(sepadata->nnlrows);
167 }
169 {
170 sepadata->convexsides[sepadata->nnlrows] = LHS;
171 sepadata->nlrows[sepadata->nnlrows] = nlrow;
172 ++(sepadata->nnlrows);
173 }
174 }
175
176 return SCIP_OKAY;
177}
178
179/** computes an interior point of a convex NLP relaxation
180 *
181 * builds the convex relaxation, modifies it to find an interior
182 * point, solves it and frees it; more details in @ref sepa_gauge.h
183 *
184 * @note the method also counts the number of nonlinear convex constraints and if there are < 2, then the convex
185 * relaxation is not interesting and the separator will not run again
186 */
187static
189 SCIP* scip, /**< SCIP data structure */
190 SCIP_SEPADATA* sepadata /**< separator data */
191 )
192{
193 SCIP_NLPIORACLE* nlpioracle;
194 SCIP_NLPIPROBLEM* nlpiprob;
195 SCIP_NLPI* nlpi;
196 SCIP_HASHMAP* var2nlpiidx;
197 SCIP_Real objvarlb;
198 SCIP_Real minusone;
199 SCIP_Real one;
200 int nconvexnlrows;
201 int objvaridx;
202 int nconss;
203 int nvars;
204 int i;
205
206 assert(scip != NULL);
207 assert(sepadata != NULL);
208 assert(!sepadata->skipsepa);
209
210 SCIPdebugMsg(scip, "Computing interior point\n");
211
212 /* create convex relaxation NLP */
214
215 nlpi = SCIPgetNlpis(scip)[0];
216 assert(nlpi != NULL);
217
219 SCIP_CALL( SCIPhashmapCreate(&var2nlpiidx, SCIPblkmem(scip), nvars) );
220 SCIP_CALL( SCIPcreateNlpiProblemFromNlRows(scip, nlpi, &nlpiprob, "gauge-interiorpoint-nlp", SCIPgetNLPNlRows(scip), SCIPgetNNLPNlRows(scip), var2nlpiidx,
222
223 /* add objective variable; the problem is \min t, s.t. g(x) <= t, l(x) <= 0, where g are nonlinear and l linear */
224 objvaridx = nvars;
225 objvarlb = INTERIOROBJVARLB;
226 one = 1.0;
227 SCIP_CALL( SCIPaddNlpiVars(scip, nlpi, nlpiprob, 1, &objvarlb, NULL, NULL) );
228 SCIP_CALL( SCIPsetNlpiObjective(scip, nlpi, nlpiprob, 1, &objvaridx, &one, NULL, 0.0) );
229
230 /* add objective variables to constraints; for this we need to get nlpi oracle to have access to number of
231 * constraints and which constraints are nonlinear
232 */
233 /* @todo: this code is only valid when using IPOPT and needs to be changed when new NLP solvers get interfaced */
234
236
237 nlpioracle = (SCIP_NLPIORACLE *)SCIPgetNlpiOracleIpopt(nlpiprob);
238 assert(nlpioracle != NULL);
239 assert(SCIPnlpiOracleGetNVars(nlpioracle) == objvaridx + 1);
240
241 minusone = -1.0;
242 nconvexnlrows = 0;
243 nconss = SCIPnlpiOracleGetNConstraints(nlpioracle);
244 for( i = 0; i < nconss; i++ )
245 {
246 if( SCIPnlpiOracleIsConstraintNonlinear(nlpioracle, i) )
247 {
248 SCIP_CALL( SCIPchgNlpiLinearCoefs(scip, nlpi, nlpiprob, i, 1, &objvaridx, &minusone) );
249 ++nconvexnlrows;
250 }
251 }
253
254 /* check if convex relaxation is interesting */
255 if( nconvexnlrows < 2 )
256 {
257 SCIPdebugMsg(scip, "convex relaxation is not interesting, only %d nonlinear convex rows; abort\n", nconvexnlrows);
258 sepadata->skipsepa = TRUE;
259 goto CLEANUP;
260 }
261
262 /* add linear rows */
263 SCIP_CALL( SCIPaddNlpiProblemRows(scip, nlpi, nlpiprob, var2nlpiidx, SCIPgetLPRows(scip), SCIPgetNLPRows(scip)) );
264
265 /* compute interior point */
266 SCIPdebugMsg(scip, "starting interior point computation\n");
267 SCIP_CALL( SCIPsolveNlpi(scip, nlpi, nlpiprob,
268 .iterlimit = sepadata->nlpiterlimit > 0 ? sepadata->nlpiterlimit : INT_MAX,
269 .feastol = NLPFEASFAC * SCIPfeastol(scip),
270 .opttol = MAX(SCIPfeastol(scip), SCIPdualfeastol(scip))) ); /*lint !e666*/
271 SCIPdebugMsg(scip, "finish interior point computation\n");
272
273#ifdef SCIP_DEBUG
274 {
275 SCIP_NLPSTATISTICS nlpstatistics;
276
277 /* get statistics */
278 SCIP_CALL( SCIPgetNlpiStatistics(scip, nlpi, nlpiprob, &nlpstatistics) );
279
280 SCIPdebugMsg(scip, "nlpi took iters %d, time %g searching for an find interior point: solstat %d\n",
281 nlpstatistics.niterations, nlpstatistics.totaltime,
282 SCIPgetNlpiSolstat(scip, nlpi, nlpiprob));
283 }
284#endif
285
286 if( SCIPgetNlpiSolstat(scip, nlpi, nlpiprob) <= SCIP_NLPSOLSTAT_FEASIBLE )
287 {
288 SCIP_Real* nlpisol;
289
290 SCIP_CALL( SCIPgetNlpiSolution(scip, nlpi, nlpiprob, &nlpisol, NULL, NULL, NULL, NULL) );
291
292 assert(nlpisol != NULL);
293 SCIPdebugMsg(scip, "NLP solved: sol found has objvalue = %g\n", nlpisol[objvaridx]);
294
295 /* if we found an interior point store it */
296 if( SCIPisFeasNegative(scip, nlpisol[objvaridx]) )
297 {
298 SCIPdebugMsg(scip, "Interior point found!, storing it\n");
300 for( i = 0; i < nvars; i ++ )
301 {
302 SCIP_VAR* var;
303
304 var = SCIPgetVars(scip)[i];
305 assert(SCIPhashmapExists(var2nlpiidx, (void*)var) );
306
307 /* @todo: filter zero? */
309 nlpisol[SCIPhashmapGetImageInt(var2nlpiidx, (void *)var)]) );
310 }
311
312 sepadata->isintsolavailable = TRUE;
313 }
314 else
315 {
316 SCIPdebugMsg(scip, "We got a feasible point but not interior (objval: %g)\n", nlpisol[objvaridx]);
317 sepadata->skipsepa = TRUE;
318 }
319 }
320 else
321 {
322 SCIPdebugMsg(scip, "We couldn't get an interior point (stat: %d)\n", SCIPgetNlpiSolstat(scip, nlpi, nlpiprob));
323 sepadata->skipsepa = TRUE;
324 }
325
326CLEANUP:
327 /* free memory */
328 SCIPhashmapFree(&var2nlpiidx);
329 SCIP_CALL( SCIPfreeNlpiProblem(scip, nlpi, &nlpiprob) );
330
331 return SCIP_OKAY;
332}
333
334
335/** find whether point is in the interior, at the boundary, or in the exterior of the region described by the
336 * intersection of `nlrows[i]` &le; rhs if `convexsides[i]` = RHS or lhs &le; `nlrows[i]` if `convexsides[i]` = LHS
337 *
338 * @note point corresponds to a convex combination between the LP solution and the interior point
339 */
340static
342 SCIP* scip, /**< SCIP data structure */
343 SCIP_NLROW** nlrows, /**< nlrows defining the region */
344 int* nlrowsidx, /**< indices of nlrows defining the region */
345 int nnlrowsidx, /**< number of nlrows indices */
346 CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
347 SCIP_SOL* point, /**< point for which we want to know its position */
348 POSITION* position /**< buffer to store position of sol */
349 )
350{
351 int i;
352
353 assert(scip != NULL);
354 assert(nlrows != NULL);
355 assert(convexsides != NULL);
356 assert(nnlrowsidx > 0);
357 assert(point != NULL);
358 assert(position != NULL);
359
360 *position = INTERIOR;
361 for( i = 0; i < nnlrowsidx; i++ )
362 {
363 SCIP_NLROW* nlrow;
364 SCIP_Real activity;
365 CONVEXSIDE convexside;
366
367 nlrow = nlrows[nlrowsidx[i]];
368 convexside = convexsides[nlrowsidx[i]];
369
370 /* compute activity of nlrow at point */
371 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, point, &activity) );
372 if( activity == SCIP_INVALID ) /*lint !e777*/
373 {
374 *position = EXTERIOR;
375 SCIPdebugMsg(scip, "exterior because cons <%s> cannot be evaluated\n", SCIPnlrowGetName(nlrow));
376 SCIPdebug( SCIPprintNlRow(scip, nlrow, NULL) );
377 return SCIP_OKAY;
378 }
379
380 if( convexside == RHS )
381 {
383
384 /* if nlrow <= rhs is violated, then we are in the exterior */
385 if( SCIPisFeasGT(scip, activity, SCIPnlrowGetRhs(nlrow)) )
386 {
387 *position = EXTERIOR;
388 SCIPdebugMsg(scip, "exterior because cons <%s> has activity %g. rhs: %g\n", SCIPnlrowGetName(nlrow),
389 activity, SCIPnlrowGetRhs(nlrow));
390 SCIPdebug( SCIPprintNlRow(scip, nlrow, NULL) );
391
392 return SCIP_OKAY;
393 }
394
395 /* if nlrow(point) == rhs, then we are currently at the boundary */
396 if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow)) )
397 *position = BOUNDARY;
398 }
399 else
400 {
402 assert(convexside == LHS);
403
404 /* if lhs <= nlrow is violated, then we are in the exterior */
405 if( SCIPisFeasLT(scip, activity, SCIPnlrowGetLhs(nlrow)) )
406 {
407 *position = EXTERIOR;
408 return SCIP_OKAY;
409 }
410
411 /* if lhs == nlrow(point), then we are currently at the boundary */
412 if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow)) )
413 *position = BOUNDARY;
414 }
415 }
416
417 return SCIP_OKAY;
418}
419
420
421/** returns, in convexcomb, the convex combination
422 * \f$ \lambda\, \text{endpoint} + (1 - \lambda) \text{startpoint} = \text{startpoint} + \lambda (\text{endpoint} - \text{startpoint})\f$
423 */
424static
426 SCIP* scip, /**< SCIP data structure */
427 SCIP_Real lambda, /**< convex combination multiplier */
428 SCIP_SOL* startpoint, /**< point corresponding to \f$ \lambda = 0 \f$ */
429 SCIP_SOL* endpoint, /**< point corresponding to \f$ \lambda = 1 \f$ */
430 SCIP_SOL* convexcomb /**< solution to store convex combination of intsol and tosepasol */
431 )
432{
433 SCIP_VAR** vars;
434 int nvars;
435 int i;
436
437 assert(scip != NULL);
438 assert(startpoint != NULL);
439 assert(endpoint != NULL);
440 assert(convexcomb != NULL);
441
444
445 for( i = 0; i < nvars; i++ )
446 {
447 SCIP_Real val;
448 SCIP_VAR* var;
449
450 var = vars[i];
451 val = lambda * SCIPgetSolVal(scip, endpoint, var) + (1.0 - lambda) * SCIPgetSolVal(scip, startpoint, var);
452
453 if( !SCIPisZero(scip, val) )
454 {
455 SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, val) );
456 }
457 else
458 {
459 SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, 0.0) );
460 }
461 }
462
463 return SCIP_OKAY;
464}
465
466
467/** performs binary search to find the point belonging to the segment [`intsol`, `tosepasol`] that intersects the boundary
468 * of the region described by the intersection of `nlrows[i]` &le; rhs if `convexsides[i] = RHS` or lhs &le; `nlrows[i]` if not,
469 * for i in `nlrowsidx`
470 */
471static
473 SCIP* scip, /**< SCIP data structure */
474 SCIP_NLROW** nlrows, /**< nlrows defining the region */
475 int* nlrowsidx, /**< indices of nlrows defining the region */
476 int nnlrowsidx, /**< number of nlrows indices */
477 CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
478 SCIP_SOL* intsol, /**< point acting as 'interior point' */
479 SCIP_SOL* tosepasol, /**< solution that should be separated */
480 SCIP_SOL* sol, /**< convex combination of intsol and lpsol */
481 POSITION* position /**< buffer to store position of sol */
482 )
483{
484 SCIP_Real lb;
485 SCIP_Real ub;
486 int i;
487
488 assert(scip != NULL);
489 assert(nlrows != NULL);
490 assert(nlrowsidx != NULL);
491 assert(convexsides != NULL);
492 assert(intsol != NULL);
493 assert(tosepasol != NULL);
494 assert(sol != NULL);
495 assert(position != NULL);
496
497 SCIPdebugMsg(scip, "starting binary search\n");
498 lb = 0.0; /* corresponds to intsol */
499 ub = 1.0; /* corresponds to tosepasol */
500 for( i = 0; i < MAX_ITER; i++ )
501 {
502 /* sol = (ub+lb)/2 * lpsol + (1 - (ub+lb)/2) * intsol */
503 SCIP_CALL( buildConvexCombination(scip, (ub + lb)/2.0, intsol, tosepasol, sol) );
504
505 /* find poisition of point: boundary, interior, exterior */
506 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, position) );
507 SCIPdebugMsg(scip, "Position: %d, lambda: %g\n", *position, (ub + lb)/2.0);
508
509 switch( *position )
510 {
511 case BOUNDARY:
512 SCIPdebugMsg(scip, "Done\n");
513 return SCIP_OKAY;
514
515 case INTERIOR:
516 /* want to be closer to tosepasol */
517 lb = (ub + lb)/2.0;
518 break;
519
520 case EXTERIOR:
521 /* want to be closer to intsol */
522 ub = (ub + lb)/2.0;
523 break;
524 }
525 }
526 SCIPdebugMsg(scip, "Done\n");
527 return SCIP_OKAY;
528}
529
530
531/** computes gradient cut (linearization) of nlrow at sol */
532static
534 SCIP* scip, /**< SCIP data structure */
535 SCIP_SOL* sol, /**< point used to construct gradient cut (x_0) */
536 SCIP_NLROW* nlrow, /**< constraint */
537 CONVEXSIDE convexside, /**< whether we use rhs or lhs of nlrow */
538 SCIP_EXPRITER* exprit, /**< expression iterator that can be used */
539 SCIP_ROW* row, /**< storage for cut */
540 SCIP_Bool* success /**< buffer to store whether the gradient was finite */
541 )
542{
543 SCIP_EXPR* expr;
544 SCIP_Real exprval;
545 SCIP_Real gradx0; /* <grad f(x_0), x_0> */
546 int i;
547
548 assert(scip != NULL);
549 assert(nlrow != NULL);
550 assert(row != NULL);
551
552 gradx0 = 0.0;
553 *success = TRUE;
554
556
557#ifdef CUT_DEBUG
559#endif
560
561 /* linear part */
562 for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
563 {
565 }
566
567 expr = SCIPnlrowGetExpr(nlrow);
568 assert(expr != NULL);
569
570 SCIP_CALL( SCIPevalExprGradient(scip, expr, sol, 0L) );
571
573 for( ; !SCIPexpriterIsEnd(exprit); expr = SCIPexpriterGetNext(exprit) ) /*lint !e441*/ /*lint !e440*/
574 {
575 SCIP_Real grad;
576 SCIP_VAR* var;
577
578 if( !SCIPisExprVar(scip, expr) )
579 continue;
580
581 grad = SCIPexprGetDerivative(expr);
582 var = SCIPgetVarExprVar(expr);
583 assert(var != NULL);
584
585 /* check gradient entries: function might not be differentiable */
586 if( !SCIPisFinite(grad) || grad == SCIP_INVALID ) /*lint !e777*/
587 {
588 *success = FALSE;
589 break;
590 }
591 /* SCIPdebugMsg(scip, "grad w.r.t. <%s> (%g) = %g, gradx0 += %g\n", SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var), grad, grad * SCIPgetSolVal(scip, sol, var)); */
592
593 gradx0 += grad * SCIPgetSolVal(scip, sol, var);
594 SCIP_CALL( SCIPaddVarToRow(scip, row, var, grad) );
595 }
596
598
599 /* if there was a problem computing the cut -> return */
600 if( ! *success )
601 return SCIP_OKAY;
602
603#ifdef CUT_DEBUG
604 SCIPdebugMsg(scip, "gradient: ");
606 SCIPdebugMsg(scip, "gradient dot x_0: %g\n", gradx0);
607#endif
608
609 /* gradient cut is linear part + f(x_0) - <grad f(x_0), x_0> + <grad f(x_0), x> <= rhs or >= lhs */
610 exprval = SCIPexprGetEvalValue(SCIPnlrowGetExpr(nlrow));
611 assert(exprval != SCIP_INVALID); /* we should have noticed a domain error above */ /*lint !e777*/
612 if( convexside == RHS )
613 {
615 SCIP_CALL( SCIPchgRowRhs(scip, row, SCIPnlrowGetRhs(nlrow) - SCIPnlrowGetConstant(nlrow) - exprval + gradx0) );
616 }
617 else
618 {
619 assert(convexside == LHS);
621 SCIP_CALL( SCIPchgRowLhs(scip, row, SCIPnlrowGetLhs(nlrow) - SCIPnlrowGetConstant(nlrow) - exprval + gradx0) );
622 }
623
624#ifdef CUT_DEBUG
625 SCIPdebugMsg(scip, "gradient cut: ");
627#endif
628
629 return SCIP_OKAY;
630}
631
632/** tries to generate gradient cuts at the point on the segment [`intsol`, `tosepasol`] that intersecs the boundary of the
633 * convex relaxation
634 *
635 * -# checks that the relative interior of the segment actually intersects the boundary
636 * (this check is needed since `intsol` is not necessarily an interior point)
637 * -# finds point on the boundary
638 * -# generates gradient cut at point on the boundary
639 */
640static
642 SCIP* scip, /**< SCIP data structure */
643 SCIP_SEPA* sepa, /**< the cut separator itself */
644 SCIP_SOL* tosepasol, /**< solution that should be separated */
645 SCIP_RESULT* result /**< pointer to store the result of the separation call */
646 )
647{
649 SCIP_NLROW** nlrows;
650 CONVEXSIDE* convexsides;
651 SCIP_SOL* sol;
652 SCIP_SOL* intsol;
653 POSITION position;
654 int* nlrowsidx;
655 int nnlrowsidx;
656 int i;
657 SCIP_EXPRITER* exprit;
658
659 assert(sepa != NULL);
660
662 assert(sepadata != NULL);
663
664 intsol = sepadata->intsol;
665 nlrows = sepadata->nlrows;
666 nlrowsidx = sepadata->nlrowsidx;
667 nnlrowsidx = sepadata->nnlrowsidx;
668 convexsides = sepadata->convexsides;
669
670 assert(intsol != NULL);
671 assert(nlrows != NULL);
672 assert(nlrowsidx != NULL);
673 assert(nnlrowsidx > 0);
674 assert(convexsides != NULL);
675
676 /* to evaluate the nlrow one needs a solution */
678
679 /* don't separate if, under SCIP tolerances, only a slight perturbation of the interior point in the direction of
680 * tosepasol gives a point that is in the exterior */
682 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
683
684 if( position == EXTERIOR )
685 {
686#ifdef SCIP_DEBUG
687 SCIPdebugMsg(scip, "segment joining intsol and tosepasol seems to be contained in the exterior of the region, can't separate\n");
688 /* move from intsol in the direction of -tosepasol to check if we are really tangent to the region */
689 SCIP_CALL( buildConvexCombination(scip, -1e-3, intsol, tosepasol, sol) );
690 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
691 if( position == EXTERIOR )
692 {
693 SCIPdebugMsg(scip, "line through intsol and tosepasol is tangent to region; can't separate\n");
694 }
695 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, &position) );
696 printf("Position of intsol is %s\n",
697 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
698 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, tosepasol, &position) );
699 printf("Position of tosepasol is %s\n",
700 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
701
702 /* slightly move from intsol in the direction of +-tosepasol */
703 SCIP_CALL( buildConvexCombination(scip, 1e-5, intsol, tosepasol, sol) );
704 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
705 printf("Position of intsol + 0.00001(tosepasol - inisol) is %s\n",
706 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
708
709 SCIP_CALL( buildConvexCombination(scip, -1e-5, intsol, tosepasol, sol) );
710 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
711 printf("Position of intsol - 0.00001(tosepasol - inisol) is %s\n",
712 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
714#endif
716 goto CLEANUP;
717 }
718
719 /* find point on boundary */
720 if( position != BOUNDARY )
721 {
722 SCIP_CALL( findBoundaryPoint(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, tosepasol, sol,
723 &position) );
724
725 /* if MAX_ITER weren't enough to find a point in the boundary we don't separate */
726 if( position != BOUNDARY )
727 {
728 SCIPdebugMsg(scip, "couldn't find boundary point, don't separate\n");
729 goto CLEANUP;
730 }
731 }
732
733 /** @todo: could probably be moved inside generateCut */
734 SCIP_CALL( SCIPcreateExpriter(scip, &exprit) );
735
736 /* generate cuts at sol */
737 for( i = 0; i < nnlrowsidx; i++ )
738 {
739 SCIP_NLROW* nlrow;
740 SCIP_ROW* row;
741 SCIP_Real activity;
742 CONVEXSIDE convexside;
743 SCIP_Bool success;
744 char rowname[SCIP_MAXSTRLEN];
745
746 nlrow = nlrows[nlrowsidx[i]];
747 convexside = convexsides[nlrowsidx[i]];
748
749 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%u", SCIPnlrowGetName(nlrow), ++(sepadata->ncuts));
750
751 /* only separate nlrows that are tight at the boundary point */
752 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
753 SCIPdebugMsg(scip, "cons <%s> at boundary point has activity: %g\n", SCIPnlrowGetName(nlrow), activity);
754
755 if( activity == SCIP_INVALID /*lint !e777*/
756 || (convexside == RHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow))) /*lint !e777*/
757 || (convexside == LHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow))) )
758 continue;
759
760 /* cut is globally valid, since we work on nlrows from the NLP built at the root node, which are globally valid */
761 /* @todo: when local nlrows get supported in SCIP, one can think of recomputing the interior point */
763 FALSE, FALSE , TRUE) );
764 SCIP_CALL( generateCut(scip, sol, nlrow, convexside, exprit, row, &success) );
765
766 /* add cut */
767 SCIPdebugMsg(scip, "cut <%s> has efficacy %g\n", SCIProwGetName(row), SCIPgetCutEfficacy(scip, NULL, row));
768 if( success && SCIPisCutEfficacious(scip, NULL, row) )
769 {
770 SCIP_Bool infeasible;
771
772 SCIPdebugMsg(scip, "adding cut\n");
773 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
774
775 if( infeasible )
776 {
778 SCIP_CALL( SCIPreleaseRow(scip, &row) );
779 break;
780 }
781 else
782 {
784 }
785 }
786
787 /* release the row */
788 SCIP_CALL( SCIPreleaseRow(scip, &row) );
789 }
790
791 SCIPfreeExpriter(&exprit);
792
793CLEANUP:
795
796 return SCIP_OKAY;
797}
798
799/*
800 * Callback methods of separator
801 */
802
803/** copy method for separator plugins (called when SCIP copies plugins) */
804static
805SCIP_DECL_SEPACOPY(sepaCopyGauge)
806{ /*lint --e{715}*/
807 assert(scip != NULL);
808 assert(sepa != NULL);
809
811
812 /* call inclusion method of separator */
814
815 return SCIP_OKAY;
816}
817
818/** destructor of separator to free user data (called when SCIP is exiting) */
819static
820SCIP_DECL_SEPAFREE(sepaFreeGauge)
821{ /*lint --e{715}*/
823
825
826 /* free separator data */
828 assert(sepadata != NULL);
829
831
832 SCIPsepaSetData(sepa, NULL);
833
834 return SCIP_OKAY;
835}
836
837
838/** solving process deinitialization method of separator (called before branch and bound process data is freed) */
839static
840SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
841{ /*lint --e{715}*/
843
844 assert(sepa != NULL);
845
847
848 assert(sepadata != NULL);
849
850 /* free memory and reset data */
851 if( sepadata->isintsolavailable )
852 {
853 SCIPfreeBlockMemoryArray(scip, &sepadata->nlrowsidx, sepadata->nlrowssize);
854 SCIPfreeBlockMemoryArray(scip, &sepadata->convexsides, sepadata->nlrowssize);
855 SCIPfreeBlockMemoryArray(scip, &sepadata->nlrows, sepadata->nlrowssize);
856 SCIP_CALL( SCIPfreeSol(scip, &sepadata->intsol) );
857
858 sepadata->nnlrows = 0;
859 sepadata->nnlrowsidx = 0;
860 sepadata->nlrowssize = 0;
861 sepadata->isintsolavailable = FALSE;
862 }
863 assert(sepadata->nnlrows == 0);
864 assert(sepadata->nnlrowsidx == 0);
865 assert(sepadata->nlrowssize == 0);
866 assert(sepadata->isintsolavailable == FALSE);
867
868 sepadata->skipsepa = FALSE;
869
870 return SCIP_OKAY;
871}
872
873
874/** LP solution separation method of separator */
875static
876SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
877{ /*lint --e{715}*/
879 SCIP_SOL* lpsol;
880 int i;
881
882 assert(scip != NULL);
883 assert(sepa != NULL);
884
886
887 assert(sepadata != NULL);
888
890
891 /* do not run if there is no interesting convex relaxation (with at least two nonlinear convex constraint) */
892 if( sepadata->skipsepa )
893 {
894 SCIPdebugMsg(scip, "not running because convex relaxation is uninteresting\n");
895 return SCIP_OKAY;
896 }
897
898 /* do not run if SCIP has not constructed an NLP */
900 {
901 SCIPdebugMsg(scip, "NLP not constructed, skipping gauge separator\n");
902 return SCIP_OKAY;
903 }
904
905 /* do not run if SCIP has no way of solving nonlinear problems */
906 if( SCIPgetNNlpis(scip) == 0 )
907 {
908 SCIPdebugMsg(scip, "Skip gauge separator: no nlpi and SCIP can't solve nonlinear problems without a nlpi\n");
909 return SCIP_OKAY;
910 }
911
912 /* if we don't have an interior point compute one; if we fail to compute one, then separator will not be run again;
913 * otherwise, we also store the convex nlrows in sepadata
914 */
915 if( !sepadata->isintsolavailable )
916 {
917 /* @todo: one could store the convex nonlinear rows inside computeInteriorPoint */
919 assert(sepadata->skipsepa || sepadata->isintsolavailable);
920
921 if( sepadata->skipsepa )
922 return SCIP_OKAY;
923
925 }
926
927#ifdef SCIP_DISABLED_CODE
928 /* get interior point: try to compute an interior point, otherwise use primal solution, otherwise use NLP solution */
929 /* @todo: - decide order:
930 * - we can also use convex combination of solutions; there is a function SCIPvarGetAvgSol!
931 * - can add an event handler to only update when a new solution has been found
932 */
933 if( !sepadata->isintsolavailable )
934 {
935 if( SCIPgetNSols(scip) > 0 )
936 {
937 SCIPdebugMsg(scip, "Using current primal solution as interior point!\n");
939 sepadata->isintsolavailable = TRUE;
940 }
942 {
943 SCIPdebugMsg(scip, "Using NLP solution as interior point!\n");
945 sepadata->isintsolavailable = TRUE;
946 }
947 else
948 {
949 SCIPdebugMsg(scip, "We couldn't find an interior point, don't have a feasible nor an NLP solution; skip separator\n");
950 return SCIP_OKAY;
951 }
952 }
953#endif
954
955 /* store lp sol (or pseudo sol when lp is not solved) to be able to use it to compute nlrows' activities */
957
958 /* store indices of relevant constraints, ie, the ones that violate the lp sol */
959 sepadata->nnlrowsidx = 0;
960 for( i = 0; i < sepadata->nnlrows; i++ )
961 {
962 SCIP_NLROW* nlrow;
963 SCIP_Real activity;
964
965 nlrow = sepadata->nlrows[i];
966
967 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, lpsol, &activity) );
968 if( activity == SCIP_INVALID ) /*lint !e777*/
969 continue;
970
971 if( sepadata->convexsides[i] == RHS )
972 {
974
975 if( activity - SCIPnlrowGetRhs(nlrow) < VIOLATIONFAC * SCIPfeastol(scip) )
976 continue;
977 }
978 else
979 {
980 assert(sepadata->convexsides[i] == LHS);
982
983 if( SCIPnlrowGetLhs(nlrow) - activity < VIOLATIONFAC * SCIPfeastol(scip) )
984 continue;
985 }
986
987 sepadata->nlrowsidx[sepadata->nnlrowsidx] = i;
988 ++(sepadata->nnlrowsidx);
989 }
990
991 /* separate only if there are violated nlrows */
992 SCIPdebugMsg(scip, "there are %d violated nlrows\n", sepadata->nnlrowsidx);
993 if( sepadata->nnlrowsidx > 0 )
994 {
995 SCIP_CALL( separateCuts(scip, sepa, lpsol, result) );
996 }
997
998 /* free lpsol */
999 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
1000
1001 return SCIP_OKAY;
1002}
1003
1004
1005/*
1006 * separator specific interface methods
1007 */
1008
1009/** creates the gauge separator and includes it in SCIP */
1011 SCIP* scip /**< SCIP data structure */
1012 )
1013{
1015 SCIP_SEPA* sepa;
1016
1017 /* create gauge separator data */
1019
1020 /* this sets all data in sepadata to 0 */
1022
1023 /* include separator */
1026 sepaExeclpGauge, NULL,
1027 sepadata) );
1028
1029 assert(sepa != NULL);
1030
1031 /* set non fundamental callbacks via setter functions */
1032 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyGauge) );
1033 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeGauge) );
1034 SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolGauge) );
1035
1036 /* add gauge separator parameters */
1037 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/nlpiterlimit",
1038 "iteration limit of NLP solver; 0 for no limit",
1039 &sepadata->nlpiterlimit, TRUE, DEFAULT_NLPITERLIM, 0, INT_MAX, NULL, NULL) );
1040
1041 return SCIP_OKAY;
1042}
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL(x)
Definition def.h:364
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition scip_prob.c:2201
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition misc.c:3095
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3304
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
#define SCIPdebugMsg
SCIP_Bool SCIPnlpiOracleIsConstraintNonlinear(SCIP_NLPIORACLE *oracle, int considx)
SCIP_RETCODE SCIPnlpiOraclePrintProblem(SCIP *scip, SCIP_NLPIORACLE *oracle, FILE *file)
int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
struct SCIP_NlpiOracle SCIP_NLPIORACLE
Definition nlpioracle.h:51
void * SCIPgetNlpiOracleIpopt(SCIP_NLPIPROBLEM *nlpiproblem)
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:225
SCIP_RETCODE SCIPevalExprGradient(SCIP *scip, SCIP_EXPR *expr, SCIP_SOL *sol, SCIP_Longint soltag)
Definition scip_expr.c:1692
SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
Definition expriter.c:969
SCIP_Real SCIPexprGetDerivative(SCIP_EXPR *expr)
Definition expr.c:3972
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1457
SCIP_RETCODE SCIPcreateExpriter(SCIP *scip, SCIP_EXPRITER **iterator)
Definition scip_expr.c:2362
SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
Definition expr.c:3946
SCIP_EXPR * SCIPexpriterGetNext(SCIP_EXPRITER *iterator)
Definition expriter.c:858
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition expr_var.c:423
void SCIPfreeExpriter(SCIP_EXPRITER **iterator)
Definition scip_expr.c:2376
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:611
int SCIPgetNLPRows(SCIP *scip)
Definition scip_lp.c:632
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
#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:787
#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:449
int SCIPgetNNlpis(SCIP *scip)
Definition scip_nlpi.c:205
SCIP_NLPI ** SCIPgetNlpis(SCIP *scip)
Definition scip_nlpi.c:192
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:1933
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition nlp.c:1914
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition nlp.c:1904
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition nlp.c:1924
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition nlp.c:1864
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition nlp.c:1874
SCIP_Real SCIPnlrowGetConstant(SCIP_NLROW *nlrow)
Definition nlp.c:1854
SCIP_EXPR * SCIPnlrowGetExpr(SCIP_NLROW *nlrow)
Definition nlp.c:1894
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition nlp.c:1884
SCIP_RETCODE SCIPprintNlRow(SCIP *scip, SCIP_NLROW *nlrow, FILE *file)
Definition scip_nlp.c:1617
SCIP_RETCODE SCIPgetNlRowSolActivity(SCIP *scip, SCIP_NLROW *nlrow, SCIP_SOL *sol, SCIP_Real *activity)
Definition scip_nlp.c:1522
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1581
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition scip_lp.c:1529
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1604
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
const char * SCIProwGetName(SCIP_ROW *row)
Definition lp.c:17745
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
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:1429
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition scip_lp.c:1553
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:115
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:173
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition sepa.c:746
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:237
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition sepa.c:636
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition sepa.c:646
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:157
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2986
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition scip_sol.c:882
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition scip_sol.c:2351
SCIP_RETCODE SCIPcreateCurrentSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition scip_sol.c:747
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition scip_sol.c:662
int SCIPgetNSols(SCIP *scip)
Definition scip_sol.c:2887
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition scip_sol.c:1569
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
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)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
SCIPfreeSol(scip, &heurdata->sol))
SCIPcreateSol(scip, &heurdata->sol, heur))
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_VAR ** vars
memory allocation routines
#define BMSclearMemory(ptr)
Definition memory.h:129
SCIP_NLPSOLSTAT SCIPnlpGetSolstat(SCIP_NLP *nlp)
Definition nlp.c:4503
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
#define SCIPisFinite(x)
Definition pub_misc.h:82
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
#define SEPA_PRIORITY
#define SEPA_DELAY
#define SEPA_DESC
#define SEPA_USESSUBSCIP
#define SEPA_MAXBOUNDDIST
#define SEPA_FREQ
#define SEPA_NAME
ConvexSide
@ LHS
@ RHS
enum ConvexSide CONVEXSIDE
#define DEFAULT_NLPITERLIM
#define VIOLATIONFAC
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:533
enum Position POSITION
Definition sepa_gauge.c:100
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:472
static SCIP_RETCODE computeInteriorPoint(SCIP *scip, SCIP_SEPADATA *sepadata)
Definition sepa_gauge.c:188
#define INTERIOROBJVARLB
Definition sepa_gauge.c:79
static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *tosepasol, SCIP_RESULT *result)
Definition sepa_gauge.c:641
#define NLPFEASFAC
Definition sepa_gauge.c:77
static SCIP_RETCODE buildConvexCombination(SCIP *scip, SCIP_Real lambda, SCIP_SOL *startpoint, SCIP_SOL *endpoint, SCIP_SOL *convexcomb)
Definition sepa_gauge.c:425
static SCIP_RETCODE findPointPosition(SCIP *scip, SCIP_NLROW **nlrows, int *nlrowsidx, int nnlrowsidx, CONVEXSIDE *convexsides, SCIP_SOL *point, POSITION *position)
Definition sepa_gauge.c:341
Position
Definition sepa_gauge.c:95
@ EXTERIOR
Definition sepa_gauge.c:98
@ INTERIOR
Definition sepa_gauge.c:96
@ BOUNDARY
Definition sepa_gauge.c:97
#define MAX_ITER
Definition sepa_gauge.c:73
static SCIP_RETCODE storeNonlinearConvexNlrows(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_NLROW **nlrows, int nnlrows)
Definition sepa_gauge.c:128
gauge separator
SCIP_Real totaltime
Definition type_nlpi.h:190
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
struct SCIP_ExprIter SCIP_EXPRITER
Definition type_expr.h:722
@ 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:718
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
struct SCIP_NlRow SCIP_NLROW
Definition type_nlp.h:41
struct SCIP_NlpiProblem SCIP_NLPIPROBLEM
Definition type_nlpi.h:53
struct SCIP_NlpStatistics SCIP_NLPSTATISTICS
Definition type_nlpi.h:196
struct SCIP_Nlpi SCIP_NLPI
Definition type_nlpi.h:51
@ 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_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_SepaData SCIP_SEPADATA
Definition type_sepa.h:52
#define SCIP_DECL_SEPAEXECLP(x)
Definition type_sepa.h:136
#define SCIP_DECL_SEPAFREE(x)
Definition type_sepa.h:69
#define SCIP_DECL_SEPAEXITSOL(x)
Definition type_sepa.h:107
struct SCIP_Sepa SCIP_SEPA
Definition type_sepa.h:51
#define SCIP_DECL_SEPACOPY(x)
Definition type_sepa.h:61
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Var SCIP_VAR
Definition type_var.h:166