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 if( activity == SCIP_INVALID ) /*lint !e777*/
375 {
376 *position = EXTERIOR;
377 SCIPdebugMsg(scip, "exterior because cons <%s> cannot be evaluated\n", SCIPnlrowGetName(nlrow));
378 SCIPdebug( SCIPprintNlRow(scip, nlrow, NULL) );
379 return SCIP_OKAY;
380 }
381
382 if( convexside == RHS )
383 {
384 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
385
386 /* if nlrow <= rhs is violated, then we are in the exterior */
387 if( SCIPisFeasGT(scip, activity, SCIPnlrowGetRhs(nlrow)) )
388 {
389 *position = EXTERIOR;
390 SCIPdebugMsg(scip, "exterior because cons <%s> has activity %g. rhs: %g\n", SCIPnlrowGetName(nlrow),
391 activity, SCIPnlrowGetRhs(nlrow));
392 SCIPdebug( SCIPprintNlRow(scip, nlrow, NULL) );
393
394 return SCIP_OKAY;
395 }
396
397 /* if nlrow(point) == rhs, then we are currently at the boundary */
398 if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow)) )
399 *position = BOUNDARY;
400 }
401 else
402 {
403 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
404 assert(convexside == LHS);
405
406 /* if lhs <= nlrow is violated, then we are in the exterior */
407 if( SCIPisFeasLT(scip, activity, SCIPnlrowGetLhs(nlrow)) )
408 {
409 *position = EXTERIOR;
410 return SCIP_OKAY;
411 }
412
413 /* if lhs == nlrow(point), then we are currently at the boundary */
414 if( SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow)) )
415 *position = BOUNDARY;
416 }
417 }
418
419 return SCIP_OKAY;
420}
421
422
423/** returns, in convexcomb, the convex combination
424 * \f$ \lambda\, \text{endpoint} + (1 - \lambda) \text{startpoint} = \text{startpoint} + \lambda (\text{endpoint} - \text{startpoint})\f$
425 */
426static
428 SCIP* scip, /**< SCIP data structure */
429 SCIP_Real lambda, /**< convex combination multiplier */
430 SCIP_SOL* startpoint, /**< point corresponding to \f$ \lambda = 0 \f$ */
431 SCIP_SOL* endpoint, /**< point corresponding to \f$ \lambda = 1 \f$ */
432 SCIP_SOL* convexcomb /**< solution to store convex combination of intsol and tosepasol */
433 )
434{
435 SCIP_VAR** vars;
436 int nvars;
437 int i;
438
439 assert(scip != NULL);
440 assert(startpoint != NULL);
441 assert(endpoint != NULL);
442 assert(convexcomb != NULL);
443
444 vars = SCIPgetVars(scip);
445 nvars = SCIPgetNVars(scip);
446
447 for( i = 0; i < nvars; i++ )
448 {
449 SCIP_Real val;
450 SCIP_VAR* var;
451
452 var = vars[i];
453 val = lambda * SCIPgetSolVal(scip, endpoint, var) + (1.0 - lambda) * SCIPgetSolVal(scip, startpoint, var);
454
455 if( !SCIPisZero(scip, val) )
456 {
457 SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, val) );
458 }
459 else
460 {
461 SCIP_CALL( SCIPsetSolVal(scip, convexcomb, var, 0.0) );
462 }
463 }
464
465 return SCIP_OKAY;
466}
467
468
469/** performs binary search to find the point belonging to the segment [`intsol`, `tosepasol`] that intersects the boundary
470 * of the region described by the intersection of `nlrows[i]` &le; rhs if `convexsides[i] = RHS` or lhs &le; `nlrows[i]` if not,
471 * for i in `nlrowsidx`
472 */
473static
475 SCIP* scip, /**< SCIP data structure */
476 SCIP_NLROW** nlrows, /**< nlrows defining the region */
477 int* nlrowsidx, /**< indices of nlrows defining the region */
478 int nnlrowsidx, /**< number of nlrows indices */
479 CONVEXSIDE* convexsides, /**< sides of the nlrows involved in the region */
480 SCIP_SOL* intsol, /**< point acting as 'interior point' */
481 SCIP_SOL* tosepasol, /**< solution that should be separated */
482 SCIP_SOL* sol, /**< convex combination of intsol and lpsol */
483 POSITION* position /**< buffer to store position of sol */
484 )
485{
486 SCIP_Real lb;
487 SCIP_Real ub;
488 int i;
489
490 assert(scip != NULL);
491 assert(nlrows != NULL);
492 assert(nlrowsidx != NULL);
493 assert(convexsides != NULL);
494 assert(intsol != NULL);
495 assert(tosepasol != NULL);
496 assert(sol != NULL);
497 assert(position != NULL);
498
499 SCIPdebugMsg(scip, "starting binary search\n");
500 lb = 0.0; /* corresponds to intsol */
501 ub = 1.0; /* corresponds to tosepasol */
502 for( i = 0; i < MAX_ITER; i++ )
503 {
504 /* sol = (ub+lb)/2 * lpsol + (1 - (ub+lb)/2) * intsol */
505 SCIP_CALL( buildConvexCombination(scip, (ub + lb)/2.0, intsol, tosepasol, sol) );
506
507 /* find poisition of point: boundary, interior, exterior */
508 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, position) );
509 SCIPdebugMsg(scip, "Position: %d, lambda: %g\n", *position, (ub + lb)/2.0);
510
511 switch( *position )
512 {
513 case BOUNDARY:
514 SCIPdebugMsg(scip, "Done\n");
515 return SCIP_OKAY;
516
517 case INTERIOR:
518 /* want to be closer to tosepasol */
519 lb = (ub + lb)/2.0;
520 break;
521
522 case EXTERIOR:
523 /* want to be closer to intsol */
524 ub = (ub + lb)/2.0;
525 break;
526 }
527 }
528 SCIPdebugMsg(scip, "Done\n");
529 return SCIP_OKAY;
530}
531
532
533/** computes gradient cut (linearization) of nlrow at sol */
534static
536 SCIP* scip, /**< SCIP data structure */
537 SCIP_SOL* sol, /**< point used to construct gradient cut (x_0) */
538 SCIP_NLROW* nlrow, /**< constraint */
539 CONVEXSIDE convexside, /**< whether we use rhs or lhs of nlrow */
540 SCIP_EXPRITER* exprit, /**< expression iterator that can be used */
541 SCIP_ROW* row, /**< storage for cut */
542 SCIP_Bool* success /**< buffer to store whether the gradient was finite */
543 )
544{
545 SCIP_EXPR* expr;
546 SCIP_Real exprval;
547 SCIP_Real gradx0; /* <grad f(x_0), x_0> */
548 int i;
549
550 assert(scip != NULL);
551 assert(nlrow != NULL);
552 assert(row != NULL);
553
554 gradx0 = 0.0;
555 *success = TRUE;
556
558
559#ifdef CUT_DEBUG
561#endif
562
563 /* linear part */
564 for( i = 0; i < SCIPnlrowGetNLinearVars(nlrow); i++ )
565 {
567 }
568
569 expr = SCIPnlrowGetExpr(nlrow);
570 assert(expr != NULL);
571
572 SCIP_CALL( SCIPevalExprGradient(scip, expr, sol, 0L) );
573
575 for( ; !SCIPexpriterIsEnd(exprit); expr = SCIPexpriterGetNext(exprit) ) /*lint !e441*/ /*lint !e440*/
576 {
577 SCIP_Real grad;
578 SCIP_VAR* var;
579
580 if( !SCIPisExprVar(scip, expr) )
581 continue;
582
583 grad = SCIPexprGetDerivative(expr);
584 var = SCIPgetVarExprVar(expr);
585 assert(var != NULL);
586
587 /* check gradient entries: function might not be differentiable */
588 if( !SCIPisFinite(grad) || grad == SCIP_INVALID ) /*lint !e777*/
589 {
590 *success = FALSE;
591 break;
592 }
593 /* SCIPdebugMsg(scip, "grad w.r.t. <%s> (%g) = %g, gradx0 += %g\n", SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var), grad, grad * SCIPgetSolVal(scip, sol, var)); */
594
595 gradx0 += grad * SCIPgetSolVal(scip, sol, var);
596 SCIP_CALL( SCIPaddVarToRow(scip, row, var, grad) );
597 }
598
600
601 /* if there was a problem computing the cut -> return */
602 if( ! *success )
603 return SCIP_OKAY;
604
605#ifdef CUT_DEBUG
606 SCIPdebugMsg(scip, "gradient: ");
608 SCIPdebugMsg(scip, "gradient dot x_0: %g\n", gradx0);
609#endif
610
611 /* gradient cut is linear part + f(x_0) - <grad f(x_0), x_0> + <grad f(x_0), x> <= rhs or >= lhs */
612 exprval = SCIPexprGetEvalValue(SCIPnlrowGetExpr(nlrow));
613 assert(exprval != SCIP_INVALID); /* we should have noticed a domain error above */ /*lint !e777*/
614 if( convexside == RHS )
615 {
616 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
617 SCIP_CALL( SCIPchgRowRhs(scip, row, SCIPnlrowGetRhs(nlrow) - SCIPnlrowGetConstant(nlrow) - exprval + gradx0) );
618 }
619 else
620 {
621 assert(convexside == LHS);
622 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
623 SCIP_CALL( SCIPchgRowLhs(scip, row, SCIPnlrowGetLhs(nlrow) - SCIPnlrowGetConstant(nlrow) - exprval + gradx0) );
624 }
625
626#ifdef CUT_DEBUG
627 SCIPdebugMsg(scip, "gradient cut: ");
629#endif
630
631 return SCIP_OKAY;
632}
633
634/** tries to generate gradient cuts at the point on the segment [`intsol`, `tosepasol`] that intersecs the boundary of the
635 * convex relaxation
636 *
637 * -# checks that the relative interior of the segment actually intersects the boundary
638 * (this check is needed since `intsol` is not necessarily an interior point)
639 * -# finds point on the boundary
640 * -# generates gradient cut at point on the boundary
641 */
642static
644 SCIP* scip, /**< SCIP data structure */
645 SCIP_SEPA* sepa, /**< the cut separator itself */
646 SCIP_SOL* tosepasol, /**< solution that should be separated */
647 SCIP_RESULT* result /**< pointer to store the result of the separation call */
648 )
649{
650 SCIP_SEPADATA* sepadata;
651 SCIP_NLROW** nlrows;
652 CONVEXSIDE* convexsides;
653 SCIP_SOL* sol;
654 SCIP_SOL* intsol;
655 POSITION position;
656 int* nlrowsidx;
657 int nnlrowsidx;
658 int i;
659 SCIP_EXPRITER* exprit;
660
661 assert(sepa != NULL);
662
663 sepadata = SCIPsepaGetData(sepa);
664 assert(sepadata != NULL);
665
666 intsol = sepadata->intsol;
667 nlrows = sepadata->nlrows;
668 nlrowsidx = sepadata->nlrowsidx;
669 nnlrowsidx = sepadata->nnlrowsidx;
670 convexsides = sepadata->convexsides;
671
672 assert(intsol != NULL);
673 assert(nlrows != NULL);
674 assert(nlrowsidx != NULL);
675 assert(nnlrowsidx > 0);
676 assert(convexsides != NULL);
677
678 /* to evaluate the nlrow one needs a solution */
679 SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
680
681 /* don't separate if, under SCIP tolerances, only a slight perturbation of the interior point in the direction of
682 * tosepasol gives a point that is in the exterior */
683 SCIP_CALL( buildConvexCombination(scip, VIOLATIONFAC * SCIPfeastol(scip), intsol, tosepasol, sol) );
684 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
685
686 if( position == EXTERIOR )
687 {
688#ifdef SCIP_DEBUG
689 SCIPdebugMsg(scip, "segment joining intsol and tosepasol seems to be contained in the exterior of the region, can't separate\n");
690 /* move from intsol in the direction of -tosepasol to check if we are really tangent to the region */
691 SCIP_CALL( buildConvexCombination(scip, -1e-3, intsol, tosepasol, sol) );
692 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
693 if( position == EXTERIOR )
694 {
695 SCIPdebugMsg(scip, "line through intsol and tosepasol is tangent to region; can't separate\n");
696 }
697 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, &position) );
698 printf("Position of intsol is %s\n",
699 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
700 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, tosepasol, &position) );
701 printf("Position of tosepasol is %s\n",
702 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
703
704 /* slightly move from intsol in the direction of +-tosepasol */
705 SCIP_CALL( buildConvexCombination(scip, 1e-5, intsol, tosepasol, sol) );
706 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
707 printf("Position of intsol + 0.00001(tosepasol - inisol) is %s\n",
708 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
710
711 SCIP_CALL( buildConvexCombination(scip, -1e-5, intsol, tosepasol, sol) );
712 SCIP_CALL( findPointPosition(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, sol, &position) );
713 printf("Position of intsol - 0.00001(tosepasol - inisol) is %s\n",
714 position == EXTERIOR ? "exterior" : position == INTERIOR ? "interior": "boundary");
716#endif
717 *result = SCIP_DIDNOTFIND;
718 goto CLEANUP;
719 }
720
721 /* find point on boundary */
722 if( position != BOUNDARY )
723 {
724 SCIP_CALL( findBoundaryPoint(scip, nlrows, nlrowsidx, nnlrowsidx, convexsides, intsol, tosepasol, sol,
725 &position) );
726
727 /* if MAX_ITER weren't enough to find a point in the boundary we don't separate */
728 if( position != BOUNDARY )
729 {
730 SCIPdebugMsg(scip, "couldn't find boundary point, don't separate\n");
731 goto CLEANUP;
732 }
733 }
734
735 /** @todo: could probably be moved inside generateCut */
736 SCIP_CALL( SCIPcreateExpriter(scip, &exprit) );
737
738 /* generate cuts at sol */
739 for( i = 0; i < nnlrowsidx; i++ )
740 {
741 SCIP_NLROW* nlrow;
742 SCIP_ROW* row;
743 SCIP_Real activity;
744 CONVEXSIDE convexside;
745 SCIP_Bool success;
746 char rowname[SCIP_MAXSTRLEN];
747
748 nlrow = nlrows[nlrowsidx[i]];
749 convexside = convexsides[nlrowsidx[i]];
750
751 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%u", SCIPnlrowGetName(nlrow), ++(sepadata->ncuts));
752
753 /* only separate nlrows that are tight at the boundary point */
754 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, sol, &activity) );
755 SCIPdebugMsg(scip, "cons <%s> at boundary point has activity: %g\n", SCIPnlrowGetName(nlrow), activity);
756
757 if( activity == SCIP_INVALID
758 || (convexside == RHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetRhs(nlrow))) /*lint !e777*/
759 || (convexside == LHS && !SCIPisFeasEQ(scip, activity, SCIPnlrowGetLhs(nlrow))) )
760 continue;
761
762 /* cut is globally valid, since we work on nlrows from the NLP built at the root node, which are globally valid */
763 /* @todo: when local nlrows get supported in SCIP, one can think of recomputing the interior point */
765 FALSE, FALSE , TRUE) );
766 SCIP_CALL( generateCut(scip, sol, nlrow, convexside, exprit, row, &success) );
767
768 /* add cut */
769 SCIPdebugMsg(scip, "cut <%s> has efficacy %g\n", SCIProwGetName(row), SCIPgetCutEfficacy(scip, NULL, row));
770 if( success && SCIPisCutEfficacious(scip, NULL, row) )
771 {
772 SCIP_Bool infeasible;
773
774 SCIPdebugMsg(scip, "adding cut\n");
775 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
776
777 if( infeasible )
778 {
779 *result = SCIP_CUTOFF;
780 SCIP_CALL( SCIPreleaseRow(scip, &row) );
781 break;
782 }
783 else
784 {
785 *result = SCIP_SEPARATED;
786 }
787 }
788
789 /* release the row */
790 SCIP_CALL( SCIPreleaseRow(scip, &row) );
791 }
792
793 SCIPfreeExpriter(&exprit);
794
795CLEANUP:
796 SCIP_CALL( SCIPfreeSol(scip, &sol) );
797
798 return SCIP_OKAY;
799}
800
801/*
802 * Callback methods of separator
803 */
804
805/** copy method for separator plugins (called when SCIP copies plugins) */
806static
807SCIP_DECL_SEPACOPY(sepaCopyGauge)
808{ /*lint --e{715}*/
809 assert(scip != NULL);
810 assert(sepa != NULL);
811 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
812
813 /* call inclusion method of separator */
815
816 return SCIP_OKAY;
817}
818
819/** destructor of separator to free user data (called when SCIP is exiting) */
820static
821SCIP_DECL_SEPAFREE(sepaFreeGauge)
822{ /*lint --e{715}*/
823 SCIP_SEPADATA* sepadata;
824
825 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
826
827 /* free separator data */
828 sepadata = SCIPsepaGetData(sepa);
829 assert(sepadata != NULL);
830
831 SCIPfreeBlockMemory(scip, &sepadata);
832
833 SCIPsepaSetData(sepa, NULL);
834
835 return SCIP_OKAY;
836}
837
838
839/** solving process deinitialization method of separator (called before branch and bound process data is freed) */
840static
841SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
842{ /*lint --e{715}*/
843 SCIP_SEPADATA* sepadata;
844
845 assert(sepa != NULL);
846
847 sepadata = SCIPsepaGetData(sepa);
848
849 assert(sepadata != NULL);
850
851 /* free memory and reset data */
852 if( sepadata->isintsolavailable )
853 {
854 SCIPfreeBlockMemoryArray(scip, &sepadata->nlrowsidx, sepadata->nlrowssize);
855 SCIPfreeBlockMemoryArray(scip, &sepadata->convexsides, sepadata->nlrowssize);
856 SCIPfreeBlockMemoryArray(scip, &sepadata->nlrows, sepadata->nlrowssize);
857 SCIP_CALL( SCIPfreeSol(scip, &sepadata->intsol) );
858
859 sepadata->nnlrows = 0;
860 sepadata->nnlrowsidx = 0;
861 sepadata->nlrowssize = 0;
862 sepadata->isintsolavailable = FALSE;
863 }
864 assert(sepadata->nnlrows == 0);
865 assert(sepadata->nnlrowsidx == 0);
866 assert(sepadata->nlrowssize == 0);
867 assert(sepadata->isintsolavailable == FALSE);
868
869 sepadata->skipsepa = FALSE;
870
871 return SCIP_OKAY;
872}
873
874
875/** LP solution separation method of separator */
876static
877SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
878{ /*lint --e{715}*/
879 SCIP_SEPADATA* sepadata;
880 SCIP_SOL* lpsol;
881 int i;
882
883 assert(scip != NULL);
884 assert(sepa != NULL);
885
886 sepadata = SCIPsepaGetData(sepa);
887
888 assert(sepadata != NULL);
889
890 *result = SCIP_DIDNOTRUN;
891
892 /* do not run if there is no interesting convex relaxation (with at least two nonlinear convex constraint) */
893 if( sepadata->skipsepa )
894 {
895 SCIPdebugMsg(scip, "not running because convex relaxation is uninteresting\n");
896 return SCIP_OKAY;
897 }
898
899 /* do not run if SCIP has not constructed an NLP */
901 {
902 SCIPdebugMsg(scip, "NLP not constructed, skipping gauge separator\n");
903 return SCIP_OKAY;
904 }
905
906 /* do not run if SCIP has no way of solving nonlinear problems */
907 if( SCIPgetNNlpis(scip) == 0 )
908 {
909 SCIPdebugMsg(scip, "Skip gauge separator: no nlpi and SCIP can't solve nonlinear problems without a nlpi\n");
910 return SCIP_OKAY;
911 }
912
913 /* if we don't have an interior point compute one; if we fail to compute one, then separator will not be run again;
914 * otherwise, we also store the convex nlrows in sepadata
915 */
916 if( !sepadata->isintsolavailable )
917 {
918 /* @todo: one could store the convex nonlinear rows inside computeInteriorPoint */
919 SCIP_CALL( computeInteriorPoint(scip, sepadata) );
920 assert(sepadata->skipsepa || sepadata->isintsolavailable);
921
922 if( sepadata->skipsepa )
923 return SCIP_OKAY;
924
926 }
927
928#ifdef SCIP_DISABLED_CODE
929 /* get interior point: try to compute an interior point, otherwise use primal solution, otherwise use NLP solution */
930 /* @todo: - decide order:
931 * - we can also use convex combination of solutions; there is a function SCIPvarGetAvgSol!
932 * - can add an event handler to only update when a new solution has been found
933 */
934 if( !sepadata->isintsolavailable )
935 {
936 if( SCIPgetNSols(scip) > 0 )
937 {
938 SCIPdebugMsg(scip, "Using current primal solution as interior point!\n");
939 SCIP_CALL( SCIPcreateSolCopy(scip, &sepadata->intsol, SCIPgetBestSol(scip)) );
940 sepadata->isintsolavailable = TRUE;
941 }
943 {
944 SCIPdebugMsg(scip, "Using NLP solution as interior point!\n");
945 SCIP_CALL( SCIPcreateNLPSol(scip, &sepadata->intsol, NULL) );
946 sepadata->isintsolavailable = TRUE;
947 }
948 else
949 {
950 SCIPdebugMsg(scip, "We couldn't find an interior point, don't have a feasible nor an NLP solution; skip separator\n");
951 return SCIP_OKAY;
952 }
953 }
954#endif
955
956 /* store lp sol (or pseudo sol when lp is not solved) to be able to use it to compute nlrows' activities */
958
959 /* store indices of relevant constraints, ie, the ones that violate the lp sol */
960 sepadata->nnlrowsidx = 0;
961 for( i = 0; i < sepadata->nnlrows; i++ )
962 {
963 SCIP_NLROW* nlrow;
964 SCIP_Real activity;
965
966 nlrow = sepadata->nlrows[i];
967
968 SCIP_CALL( SCIPgetNlRowSolActivity(scip, nlrow, lpsol, &activity) );
969 if( activity == SCIP_INVALID ) /*lint !e777*/
970 continue;
971
972 if( sepadata->convexsides[i] == RHS )
973 {
974 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
975
976 if( activity - SCIPnlrowGetRhs(nlrow) < VIOLATIONFAC * SCIPfeastol(scip) )
977 continue;
978 }
979 else
980 {
981 assert(sepadata->convexsides[i] == LHS);
982 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
983
984 if( SCIPnlrowGetLhs(nlrow) - activity < VIOLATIONFAC * SCIPfeastol(scip) )
985 continue;
986 }
987
988 sepadata->nlrowsidx[sepadata->nnlrowsidx] = i;
989 ++(sepadata->nnlrowsidx);
990 }
991
992 /* separate only if there are violated nlrows */
993 SCIPdebugMsg(scip, "there are %d violated nlrows\n", sepadata->nnlrowsidx);
994 if( sepadata->nnlrowsidx > 0 )
995 {
996 SCIP_CALL( separateCuts(scip, sepa, lpsol, result) );
997 }
998
999 /* free lpsol */
1000 SCIP_CALL( SCIPfreeSol(scip, &lpsol) );
1001
1002 return SCIP_OKAY;
1003}
1004
1005
1006/*
1007 * separator specific interface methods
1008 */
1009
1010/** creates the gauge separator and includes it in SCIP */
1012 SCIP* scip /**< SCIP data structure */
1013 )
1014{
1015 SCIP_SEPADATA* sepadata;
1016 SCIP_SEPA* sepa;
1017
1018 /* create gauge separator data */
1019 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
1020
1021 /* this sets all data in sepadata to 0 */
1022 BMSclearMemory(sepadata);
1023
1024 /* include separator */
1027 sepaExeclpGauge, NULL,
1028 sepadata) );
1029
1030 assert(sepa != NULL);
1031
1032 /* set non fundamental callbacks via setter functions */
1033 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyGauge) );
1034 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeGauge) );
1035 SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolGauge) );
1036
1037 /* add gauge separator parameters */
1038 SCIP_CALL( SCIPaddIntParam(scip, "separating/" SEPA_NAME "/nlpiterlimit",
1039 "iteration limit of NLP solver; 0 for no limit",
1040 &sepadata->nlpiterlimit, TRUE, DEFAULT_NLPITERLIM, 0, INT_MAX, NULL, NULL) );
1041
1042 return SCIP_OKAY;
1043}
#define NULL
Definition: def.h:262
#define SCIP_MAXSTRLEN
Definition: def.h:283
#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:234
#define SCIP_CALL(x)
Definition: def.h:369
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:3110
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3283
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3076
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3425
#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:1673
SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
Definition: expriter.c:969
SCIP_Real SCIPexprGetDerivative(SCIP_EXPR *expr)
Definition: expr.c:3971
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1438
SCIP_RETCODE SCIPcreateExpriter(SCIP *scip, SCIP_EXPRITER **iterator)
Definition: scip_expr.c:2343
SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
Definition: expr.c:3945
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:2357
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:606
int SCIPgetNLPRows(SCIP *scip)
Definition: scip_lp.c:627
#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: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:1945
SCIP_Real SCIPnlrowGetRhs(SCIP_NLROW *nlrow)
Definition: nlp.c:1926
SCIP_Real SCIPnlrowGetLhs(SCIP_NLROW *nlrow)
Definition: nlp.c:1916
SCIP_EXPRCURV SCIPnlrowGetCurvature(SCIP_NLROW *nlrow)
Definition: nlp.c:1936
int SCIPnlrowGetNLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:1876
SCIP_VAR ** SCIPnlrowGetLinearVars(SCIP_NLROW *nlrow)
Definition: nlp.c:1886
SCIP_Real SCIPnlrowGetConstant(SCIP_NLROW *nlrow)
Definition: nlp.c:1866
SCIP_EXPR * SCIPnlrowGetExpr(SCIP_NLROW *nlrow)
Definition: nlp.c:1906
SCIP_Real * SCIPnlrowGetLinearCoefs(SCIP_NLROW *nlrow)
Definition: nlp.c:1896
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:1639
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1587
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1662
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1705
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2216
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17380
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1566
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:1457
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1611
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
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:173
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol)))
Definition: scip_sepa.c:237
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:157
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:1011
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10878
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:4515
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:535
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:841
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:474
#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:807
static SCIP_DECL_SEPAFREE(sepaFreeGauge)
Definition: sepa_gauge.c:821
static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *tosepasol, SCIP_RESULT *result)
Definition: sepa_gauge.c:643
#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:427
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:877
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