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-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};
    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 */
    213 assert(SCIPgetNNlpis(scip) > 0);
    214
    215 nlpi = SCIPgetNlpis(scip)[0];
    216 assert(nlpi != NULL);
    217
    218 nvars = SCIPgetNVars(scip);
    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");
    299 SCIP_CALL( SCIPcreateSol(scip, &sepadata->intsol, NULL) );
    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? */
    308 SCIP_CALL( SCIPsetSolVal(scip, sepadata->intsol, var,
    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 {
    382 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
    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 {
    401 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
    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
    442 vars = SCIPgetVars(scip);
    443 nvars = SCIPgetNVars(scip);
    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 {
    614 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
    615 SCIP_CALL( SCIPchgRowRhs(scip, row, SCIPnlrowGetRhs(nlrow) - SCIPnlrowGetConstant(nlrow) - exprval + gradx0) );
    616 }
    617 else
    618 {
    619 assert(convexside == LHS);
    620 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
    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{
    648 SCIP_SEPADATA* sepadata;
    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
    661 sepadata = SCIPsepaGetData(sepa);
    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 */
    677 SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
    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 */
    681 SCIP_CALL( buildConvexCombination(scip, VIOLATIONFAC * SCIPfeastol(scip), intsol, tosepasol, sol) );
    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
    715 *result = SCIP_DIDNOTFIND;
    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 {
    777 *result = SCIP_CUTOFF;
    778 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    779 break;
    780 }
    781 else
    782 {
    783 *result = SCIP_SEPARATED;
    784 }
    785 }
    786
    787 /* release the row */
    788 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    789 }
    790
    791 SCIPfreeExpriter(&exprit);
    792
    793CLEANUP:
    794 SCIP_CALL( SCIPfreeSol(scip, &sol) );
    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}*/
    822 SCIP_SEPADATA* sepadata;
    823
    825
    826 /* free separator data */
    827 sepadata = SCIPsepaGetData(sepa);
    828 assert(sepadata != NULL);
    829
    830 SCIPfreeBlockMemory(scip, &sepadata);
    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}*/
    842 SCIP_SEPADATA* sepadata;
    843
    844 assert(sepa != NULL);
    845
    846 sepadata = SCIPsepaGetData(sepa);
    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}*/
    878 SCIP_SEPADATA* sepadata;
    879 SCIP_SOL* lpsol;
    880 int i;
    881
    882 assert(scip != NULL);
    883 assert(sepa != NULL);
    884
    885 sepadata = SCIPsepaGetData(sepa);
    886
    887 assert(sepadata != NULL);
    888
    889 *result = SCIP_DIDNOTRUN;
    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 */
    918 SCIP_CALL( computeInteriorPoint(scip, sepadata) );
    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");
    938 SCIP_CALL( SCIPcreateSolCopy(scip, &sepadata->intsol, SCIPgetBestSol(scip)) );
    939 sepadata->isintsolavailable = TRUE;
    940 }
    942 {
    943 SCIPdebugMsg(scip, "Using NLP solution as interior point!\n");
    944 SCIP_CALL( SCIPcreateNLPSol(scip, &sepadata->intsol, NULL) );
    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 {
    973 assert(!SCIPisInfinity(scip, SCIPnlrowGetRhs(nlrow)));
    974
    975 if( activity - SCIPnlrowGetRhs(nlrow) < VIOLATIONFAC * SCIPfeastol(scip) )
    976 continue;
    977 }
    978 else
    979 {
    980 assert(sepadata->convexsides[i] == LHS);
    981 assert(!SCIPisInfinity(scip, -SCIPnlrowGetLhs(nlrow)));
    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{
    1014 SCIP_SEPADATA* sepadata;
    1015 SCIP_SEPA* sepa;
    1016
    1017 /* create gauge separator data */
    1018 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
    1019
    1020 /* this sets all data in sepadata to 0 */
    1021 BMSclearMemory(sepadata);
    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
    Definition: scip_message.h:78
    SCIP_Bool SCIPnlpiOracleIsConstraintNonlinear(SCIP_NLPIORACLE *oracle, int considx)
    Definition: nlpioracle.c:2181
    SCIP_RETCODE SCIPnlpiOraclePrintProblem(SCIP *scip, SCIP_NLPIORACLE *oracle, FILE *file)
    Definition: nlpioracle.c:3011
    int SCIPnlpiOracleGetNVars(SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:2030
    int SCIPnlpiOracleGetNConstraints(SCIP_NLPIORACLE *oracle)
    Definition: nlpioracle.c:2040
    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
    const char * SCIPsepaGetName(SCIP_SEPA *sepa)
    Definition: sepa.c:746
    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:636
    void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
    Definition: sepa.c:646
    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:2986
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:882
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    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)
    Definition: sepa_gauge.c:1010
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    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
    ConvexSide
    enum ConvexSide CONVEXSIDE
    #define SEPA_PRIORITY
    Definition: sepa_gauge.c:66
    #define SEPA_DELAY
    Definition: sepa_gauge.c:70
    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
    @ LHS
    Definition: sepa_gauge.c:88
    @ RHS
    Definition: sepa_gauge.c:89
    static SCIP_DECL_SEPAEXITSOL(sepaExitsolGauge)
    Definition: sepa_gauge.c:840
    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
    #define SEPA_DESC
    Definition: sepa_gauge.c:65
    static SCIP_RETCODE computeInteriorPoint(SCIP *scip, SCIP_SEPADATA *sepadata)
    Definition: sepa_gauge.c:188
    #define INTERIOROBJVARLB
    Definition: sepa_gauge.c:79
    #define SEPA_USESSUBSCIP
    Definition: sepa_gauge.c:69
    static SCIP_DECL_SEPACOPY(sepaCopyGauge)
    Definition: sepa_gauge.c:805
    static SCIP_DECL_SEPAFREE(sepaFreeGauge)
    Definition: sepa_gauge.c:820
    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
    enum ConvexSide CONVEXSIDE
    Definition: sepa_gauge.c:91
    #define SEPA_MAXBOUNDDIST
    Definition: sepa_gauge.c:68
    #define SEPA_FREQ
    Definition: sepa_gauge.c:67
    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 DEFAULT_NLPITERLIM
    Definition: sepa_gauge.c:75
    #define SEPA_NAME
    Definition: sepa_gauge.c:64
    #define MAX_ITER
    Definition: sepa_gauge.c:73
    #define VIOLATIONFAC
    Definition: sepa_gauge.c:72
    static SCIP_DECL_SEPAEXECLP(sepaExeclpGauge)
    Definition: sepa_gauge.c:876
    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
    @ 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
    @ 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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    struct SCIP_SepaData SCIP_SEPADATA
    Definition: type_sepa.h:52