SCIP

    Solving Constraint Integer Programs

    nlhdlr_default.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 nlhdlr_default.c
    26 * @ingroup DEFPLUGINS_NLHDLR
    27 * @brief default nonlinear handler that calls expression handler methods
    28 * @author Stefan Vigerske
    29 */
    30
    31#include "scip/nlhdlr_default.h"
    32#include "scip/pub_nlhdlr.h"
    33#include "scip/cons_nonlinear.h"
    34
    35/* fundamental nonlinear handler properties */
    36#define NLHDLR_NAME "default"
    37#define NLHDLR_DESC "default handler for expressions"
    38#define NLHDLR_DETECTPRIORITY 0
    39#define NLHDLR_ENFOPRIORITY 0
    40
    41/** translate from one value of infinity to another
    42 *
    43 * if val is ≥ infty1, then give infty2, else give val
    44 */
    45#define infty2infty(infty1, infty2, val) ((val) >= (infty1) ? (infty2) : (val))
    46
    47#define UNDERESTIMATEUSESACTIVITY 0x1u /**< whether underestimation uses activity */
    48#define OVERESTIMATEUSESACTIVITY 0x2u /**< whether overestimation uses activity */
    49
    50/*lint -e666*/
    51/*lint -e850*/
    52
    53/** evaluates an expression w.r.t. the values in the auxiliary variables */
    54static
    56 SCIP* scip, /**< SCIP data structure */
    57 SCIP_EXPR* expr, /**< expression to be evaluated */
    58 SCIP_Real* val, /**< buffer to store value of expression */
    59 SCIP_SOL* sol /**< solution to be evaluated */
    60 )
    61{
    62 SCIP_Real* childvals;
    63 SCIP_VAR* childvar;
    64 int c;
    65
    66 assert(scip != NULL);
    67 assert(expr != NULL);
    68 assert(val != NULL);
    69 assert(SCIPexprGetNChildren(expr) > 0);
    70
    72
    73 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    74 {
    76 /* there should be an auxiliary variable, because we created them in detect for every child if we said that we will separate;
    77 * at the moment, EVALAUX should only be called for nlhdlrs that said they will separate
    78 * if that changes, then we should handle this here, e.g., via *val = SCIPexprGetEvalValue(expr); break;
    79 */
    80 assert(childvar != NULL);
    81
    82 childvals[c] = SCIPgetSolVal(scip, sol, childvar);
    83 }
    84
    85 SCIP_CALL( SCIPcallExprEval(scip, expr, childvals, val) );
    86
    87 SCIPfreeBufferArray(scip, &childvals);
    88
    89 return SCIP_OKAY;
    90}
    91
    92/** check whether expression should be handled by the default nlhdlr
    93 *
    94 * if no nlhdlr so far provides enforcement or boundtightening for expr, then the default nlhdlr takes over
    95 */
    96static
    97SCIP_DECL_NLHDLRDETECT(nlhdlrDetectDefault)
    98{ /*lint --e{715}*/
    99 SCIP_EXPRHDLR* exprhdlr;
    100 SCIP_Bool estimatebelowusesactivity = FALSE;
    101 SCIP_Bool estimateaboveusesactivity = FALSE;
    102 int c;
    103
    104 assert(scip != NULL);
    105 assert(nlhdlr != NULL);
    106 assert(expr != NULL);
    107 assert(enforcing != NULL);
    108 assert(participating != NULL);
    109 assert(nlhdlrexprdata != NULL);
    110
    111 exprhdlr = SCIPexprGetHdlr(expr);
    112 assert(exprhdlr != NULL);
    113
    114 if( (*enforcing & SCIP_NLHDLR_METHOD_ACTIVITY) == 0 )
    115 {
    116 /* expr handlers having reverseprop but no inteval is something that we don't support at the moment for simplicity */
    117 assert(!SCIPexprhdlrHasReverseProp(exprhdlr) || SCIPexprhdlrHasIntEval(exprhdlr));
    118
    119 /* participate in inteval and/or reverseprop if that is not yet provided in enforcing and we have inteval */
    120 if( SCIPexprhdlrHasIntEval(exprhdlr) )
    121 *participating = SCIP_NLHDLR_METHOD_ACTIVITY;
    122 }
    123
    124 /* participate in sepa if exprhdlr for expr has an estimate callback and sepa below or above is still missing */
    126 {
    127 /* communicate back that the nlhdlr will provide the separation on the currently missing sides */
    128 if( (*enforcing & SCIP_NLHDLR_METHOD_SEPABELOW) == 0 )
    129 *participating |= SCIP_NLHDLR_METHOD_SEPABELOW;
    130
    131 if( (*enforcing & SCIP_NLHDLR_METHOD_SEPAABOVE) == 0 )
    132 *participating |= SCIP_NLHDLR_METHOD_SEPAABOVE;
    133 }
    134
    135 if( !*participating )
    136 return SCIP_OKAY;
    137
    138 /* since this is the default handler, we enforce where we participate */
    139 *enforcing |= *participating;
    140
    141 /* increment activity usage counter and create auxiliary variables if necessary
    142 * if separating, first guess whether we will use activities in estimate (distinguish under- and overestimation)
    143 * we assume that the exprhdlr will use activity on all children iff we are estimating on a nonconvex side
    144 * TODO it would be better to request this information directly from the exprhdlr than inferring it from curvature,
    145 * but with the currently available exprhdlr that wouldn't make a difference
    146 */
    147 if( *participating & SCIP_NLHDLR_METHOD_SEPABOTH )
    148 {
    149 SCIP_EXPRCURV* childcurv;
    150
    151 /* allocate memory to store the required curvature of the children (though we don't use it) */
    153
    154 if( *participating & SCIP_NLHDLR_METHOD_SEPABELOW )
    155 {
    156 /* check whether the expression is convex */
    157 SCIP_Bool isconvex;
    158 SCIP_CALL( SCIPcallExprCurvature(scip, expr, SCIP_EXPRCURV_CONVEX, &isconvex, childcurv) );
    159 estimatebelowusesactivity = !isconvex;
    160 }
    161
    162 if( *participating & SCIP_NLHDLR_METHOD_SEPAABOVE )
    163 {
    164 /* check whether the expression is concave */
    165 SCIP_Bool isconcave;
    166 SCIP_CALL( SCIPcallExprCurvature(scip, expr, SCIP_EXPRCURV_CONCAVE, &isconcave, childcurv) );
    167 estimateaboveusesactivity = !isconcave;
    168 }
    169
    170 /* free memory */
    171 SCIPfreeBufferArray(scip, &childcurv);
    172 }
    173
    174 /* indicate enforcement methods required in children:
    175 * - if separating, make sure that (auxiliary) variable will exist
    176 * - if activity computation, then register activity usage
    177 * - if estimating on a non-convex side, then indicate activity usage for separation for that side
    178 */
    179 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    180 {
    181 /* todo skip auxvarusage for value-expressions? would then need update in evalExprInAux, too */
    183 *participating & SCIP_NLHDLR_METHOD_SEPABOTH,
    184 *participating & SCIP_NLHDLR_METHOD_ACTIVITY, estimatebelowusesactivity, estimateaboveusesactivity) );
    185 }
    186
    187 /* remember estimatebelowusesactivity and estimateaboveusesactivity in nlhdlrexprdata */
    188 *nlhdlrexprdata = (SCIP_NLHDLREXPRDATA*)(size_t)((estimatebelowusesactivity ? UNDERESTIMATEUSESACTIVITY : 0x0u)
    189 | (estimateaboveusesactivity ? OVERESTIMATEUSESACTIVITY : 0x0u));
    190
    191 return SCIP_OKAY;
    192}
    193
    194/** evaluate expression w.r.t. values of auxiliary variables in children */
    195static
    196SCIP_DECL_NLHDLREVALAUX(nlhdlrEvalAuxDefault)
    197{ /*lint --e{715}*/
    198 assert(expr != NULL);
    199 assert(auxvalue != NULL);
    200
    201 SCIP_CALL( evalExprInAux(scip, expr, auxvalue, sol) );
    202
    203 return SCIP_OKAY;
    204}
    205
    206/** initialize LP relaxation by initial estimators */
    207static
    208SCIP_DECL_NLHDLRINITSEPA(nlhdlrInitSepaDefault)
    209{ /*lint --e{715}*/
    210 SCIP_INTERVAL* childrenbounds;
    213 SCIP_VAR* auxvar;
    214 SCIP_ROWPREP* rowprep;
    215 int nreturned;
    216 int i, j;
    217
    218 assert(scip != NULL);
    219 assert(expr != NULL);
    220 assert(infeasible != NULL);
    221
    222 *infeasible = FALSE;
    223
    225 return SCIP_OKAY;
    226
    227 SCIPdebug( SCIPinfoMessage(scip, NULL, "initsepa exprhdlr %s for expr ", SCIPexprhdlrGetName(SCIPexprGetHdlr(expr))) );
    228 SCIPdebug( SCIPprintExpr(scip, expr, NULL) );
    230
    231 /* use global bounds of auxvar as global valid bounds for children
    232 * if at root node (thus local=global) and estimate actually uses bounds, then intersect with (local) activity of expression
    233 */
    234 SCIP_CALL( SCIPallocBufferArray(scip, &childrenbounds, SCIPexprGetNChildren(expr)) );
    235 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    236 {
    238 assert(auxvar != NULL);
    239
    240 SCIPintervalSetBounds(&childrenbounds[i],
    243
    244 if( SCIPgetDepth(scip) == 0 &&
    245 ((underestimate && ((size_t)nlhdlrexprdata & UNDERESTIMATEUSESACTIVITY)) ||
    246 (overestimate && ((size_t)nlhdlrexprdata & OVERESTIMATEUSESACTIVITY ))) )
    247 {
    249 SCIPintervalIntersect(&childrenbounds[i], childrenbounds[i], SCIPexprGetActivity(SCIPexprGetChildren(expr)[i]));
    250 }
    251
    252 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childrenbounds[i]) )
    253 {
    254 SCIPdebugMsg(scip, "activity for expression %d (unexpectedly) empty in initsepa\n", i);
    255 *infeasible = TRUE;
    256 SCIPfreeBufferArray(scip, &childrenbounds);
    257 return SCIP_OKAY;
    258 }
    259 }
    260
    261 /* allocate each coefficients array */
    262 for( i = 0; i < SCIP_EXPR_MAXINITESTIMATES; ++i )
    263 {
    265 }
    266
    267 /* create rowprep */
    270
    271 /* call the separation initialization callback of the expression handler and turn estimates into SCIP rows */
    272 for( i = 0; i < 2 && !*infeasible; ++i )
    273 {
    274 nreturned = 0;
    275 if( i == 0 && underestimate )
    276 {
    277 SCIP_CALL( SCIPcallExprInitestimates(scip, expr, childrenbounds, FALSE, coefs, constant, &nreturned) );
    279 }
    280 if( i == 1 && overestimate )
    281 {
    282 SCIP_CALL( SCIPcallExprInitestimates(scip, expr, childrenbounds, TRUE, coefs, constant, &nreturned) );
    284 }
    285
    286 for( j = 0; j < nreturned && !*infeasible; ++j )
    287 {
    288 SCIP_Bool success;
    289 int v;
    290
    291 SCIProwprepReset(rowprep);
    292
    293 for( v = 0; v < SCIPexprGetNChildren(expr); ++v )
    294 {
    296 }
    298 SCIProwprepAddConstant(rowprep, constant[j]); /*lint !e644*/
    299
    300 /* special treatment for sums to get equality rows */
    301 if( j == 0 && SCIPisExprSum(scip, expr) )
    302 {
    303 SCIP_Real scalefactor;
    304 SCIP_ROW* row;
    305
    306 /* improve numerics by scaling only (does not relax inequality) */
    307 scalefactor = SCIPscaleupRowprep(scip, rowprep, 1.0, &success);
    308 if( success && scalefactor == 1.0 && underestimate && overestimate )
    309 {
    310 /* if the rowprep didn't have to be changed, then turn it into a row, change this to an equality, and add it to the LP */
    311 /* TODO do this also if not actually needing both under- and overestimator (should still be valid, but also stronger?) */
    312 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "initestimate_sum%d", j);
    313
    314 SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, cons) );
    315
    316 /* since we did not relax the estimator, we can turn the row into an equality */
    318 {
    320 }
    321 else
    322 {
    324 }
    325 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
    326
    327 SCIPdebug( SCIPinfoMessage(scip, NULL, " added %scut ", *infeasible ? "infeasible " : "") );
    329
    330 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    331
    332 i = 2; /* to break outside loop on i, too */
    333 break;
    334 }
    335 }
    336
    337 /* straighten out numerics */
    339
    340 /* if cleanup removed all but one variable, then the cut is essentially a bound; we can skip this and rely on boundtightening */
    341 if( success && SCIProwprepGetNVars(rowprep) > 1 )
    342 {
    343 /* add the cut */
    344 SCIP_ROW* row;
    345
    346 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "init%sestimate%d_%s",
    347 i == 0 ? "under" : "over", j, SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)));
    348
    349 SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, cons) );
    350 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
    351
    352 SCIPdebug( SCIPinfoMessage(scip, NULL, " added %scut ", *infeasible ? "infeasible " : "") );
    354
    355 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    356 }
    357 }
    358 }
    359
    360 SCIPfreeRowprep(scip, &rowprep);
    361
    362 for( i = SCIP_EXPR_MAXINITESTIMATES-1; i >= 0; --i )
    363 {
    364 SCIPfreeBufferArray(scip, &coefs[i]);
    365 }
    366
    367 SCIPfreeBufferArray(scip, &childrenbounds);
    368
    369 return SCIP_OKAY;
    370}
    371
    372/** compute linear estimator */
    373static
    374SCIP_DECL_NLHDLRESTIMATE(nlhdlrEstimateDefault)
    375{ /*lint --e{715}*/
    376 SCIP_Real constant;
    377 SCIP_Bool local;
    378 SCIP_Bool* branchcand = NULL;
    379 int nchildren;
    380 int c;
    381 SCIP_INTERVAL* localbounds;
    382 SCIP_INTERVAL* globalbounds;
    383 SCIP_Real* refpoint;
    384 SCIP_ROWPREP* rowprep;
    385 SCIP_VAR* auxvar;
    386
    387 assert(scip != NULL);
    388 assert(expr != NULL);
    389 assert(rowpreps != NULL);
    390 assert(success != NULL);
    391
    392 *addedbranchscores = FALSE;
    393
    394 nchildren = SCIPexprGetNChildren(expr);
    395
    396 SCIP_CALL( SCIPallocBufferArray(scip, &localbounds, nchildren) );
    397 SCIP_CALL( SCIPallocBufferArray(scip, &globalbounds, nchildren) );
    398 SCIP_CALL( SCIPallocBufferArray(scip, &refpoint, nchildren) );
    399 /* we need to pass a branchcand array to exprhdlr's estimate also if not asked to add branching scores */
    400 SCIP_CALL( SCIPallocBufferArray(scip, &branchcand, nchildren) );
    401
    402 SCIPdebug( SCIPinfoMessage(scip, NULL, "estimate exprhdlr %s for expr ", SCIPexprhdlrGetName(SCIPexprGetHdlr(expr))) );
    403 SCIPdebug( SCIPprintExpr(scip, expr, NULL) );
    405
    406 for( c = 0; c < nchildren; ++c )
    407 {
    409 assert(auxvar != NULL);
    410
    411 SCIPintervalSetBounds(&localbounds[c],
    414
    415 if( ((size_t)nlhdlrexprdata & (overestimate ? OVERESTIMATEUSESACTIVITY : UNDERESTIMATEUSESACTIVITY)) )
    416 {
    417 /* if expr estimate uses bounds, then intersect the auxvar bounds with the current activity, in case the latter is a bit tighter */
    419 SCIPintervalIntersectEps(&localbounds[c], SCIPepsilon(scip), localbounds[c], SCIPexprGetActivity(SCIPexprGetChildren(expr)[c]));
    420
    421 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, localbounds[c]) )
    422 {
    423 *success = FALSE;
    424 goto TERMINATE;
    425 }
    426 }
    427 else
    428 {
    429 /* if we think that expr estimate wouldn't use bounds, then just set something valid */
    430 }
    431
    432 SCIPintervalSetBounds(&globalbounds[c],
    435
    436 refpoint[c] = SCIPgetSolVal(scip, sol, auxvar);
    437
    438 branchcand[c] = TRUE;
    439 }
    440
    442
    443 /* make sure enough space is available in rowprep arrays */
    444 SCIP_CALL( SCIPensureRowprepSize(scip, rowprep, nchildren) );
    445
    446 /* call the estimation callback of the expression handler */
    447 SCIP_CALL( SCIPcallExprEstimate(scip, expr, localbounds, globalbounds, refpoint, overestimate, targetvalue,
    448 SCIProwprepGetCoefs(rowprep), &constant, &local, success, branchcand) );
    449
    450 if( *success )
    451 {
    452 int i;
    453
    454 SCIProwprepSetLocal(rowprep, local);
    455
    456 /* add variables to rowprep (coefs were already added by SCIPexprhdlrEstimateExpr) */
    457 for( i = 0; i < nchildren; ++i )
    458 {
    460 SCIProwprepGetCoefs(rowprep)[i]) );
    461 }
    462
    463 SCIProwprepAddConstant(rowprep, constant);
    464
    465 SCIPdebug( SCIPinfoMessage(scip, NULL, " found rowprep ") );
    466 SCIPdebug( SCIPprintRowprepSol(scip, rowprep, sol, NULL) );
    467
    468 SCIP_CALL( SCIPsetPtrarrayVal(scip, rowpreps, 0, rowprep) );
    469
    470 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "%sestimate_%s%p_%s%" SCIP_LONGINT_FORMAT,
    471 overestimate ? "over" : "under",
    473 (void*)expr,
    474 sol != NULL ? "sol" : "lp",
    476 }
    477 else
    478 {
    479 SCIPfreeRowprep(scip, &rowprep);
    480 }
    481
    482 if( addbranchscores )
    483 {
    484 SCIP_Real violation;
    485
    486#ifndef BRSCORE_ABSVIOL
    487 SCIP_CALL( SCIPgetExprRelAuxViolationNonlinear(scip, expr, auxvalue, sol, &violation, NULL, NULL) );
    488#else
    489 SCIP_CALL( SCIPgetExprAbsAuxViolationNonlinear(scip, expr, auxvalue, sol, &violation, NULL, NULL) );
    490#endif
    491 assert(violation > 0.0); /* there should be a violation if we were called to enforce */
    492
    493 if( nchildren == 1 )
    494 {
    495 if( branchcand[0] )
    496 {
    497 SCIP_CALL( SCIPaddExprsViolScoreNonlinear(scip, SCIPexprGetChildren(expr), 1, violation, sol, addedbranchscores) );
    498 }
    499 }
    500 else
    501 {
    502 SCIP_EXPR** exprs;
    503 int nexprs = 0;
    504
    505 /* get list of those children that have the branchcand-flag set */
    506 SCIP_CALL( SCIPallocBufferArray(scip, &exprs, nchildren) );
    507
    508 for( c = 0; c < nchildren; ++c )
    509 if( branchcand[c] )
    510 exprs[nexprs++] = SCIPexprGetChildren(expr)[c];
    511
    512 SCIP_CALL( SCIPaddExprsViolScoreNonlinear(scip, exprs, nexprs, violation, sol, addedbranchscores) );
    513
    514 SCIPfreeBufferArray(scip, &exprs);
    515 }
    516
    517 if( *addedbranchscores )
    518 {
    519 /* count this branchscore as belonging to the exprhdlr, too
    520 * thus, it will be counted for the default nlhdlr, but also for this exprhdlr
    521 */
    523 }
    524 }
    525
    526TERMINATE:
    527 SCIPfreeBufferArray(scip, &branchcand);
    528 SCIPfreeBufferArray(scip, &refpoint);
    529 SCIPfreeBufferArray(scip, &globalbounds);
    530 SCIPfreeBufferArray(scip, &localbounds);
    531
    532 return SCIP_OKAY;
    533}
    534
    535/** solution linearization callback */
    536static
    537SCIP_DECL_NLHDLRSOLLINEARIZE(nlhdlrSollinearizeDefault)
    538{ /*lint --e{715}*/
    539 SCIP_Real constant;
    540 SCIP_Bool local;
    541 SCIP_Bool* branchcand = NULL;
    542 int nchildren;
    543 int c;
    544 int rnd;
    545 SCIP_INTERVAL* bounds;
    546 SCIP_Real* refpoint;
    547 SCIP_VAR* auxvar;
    548
    549 assert(scip != NULL);
    550 assert(expr != NULL);
    551
    552 SCIPdebug( SCIPinfoMessage(scip, NULL, "sollinearize exprhdlr %s for expr ", SCIPexprhdlrGetName(SCIPexprGetHdlr(expr))) );
    553 SCIPdebug( SCIPprintExpr(scip, expr, NULL) );
    555
    556 nchildren = SCIPexprGetNChildren(expr);
    557
    558 if( !overestimate && !underestimate )
    559 return SCIP_OKAY;
    560
    561 /* skip on sum, as the estimator doesn't depend on the reference point (expr is linear in auxvars) */
    562 if( SCIPisExprSum(scip, expr) )
    563 return SCIP_OKAY;
    564
    565 /* if expr estimate would use bounds, then the function is very likely not convex (w.r.t. global bounds), so skip */
    566 if( (overestimate && ((size_t)nlhdlrexprdata & OVERESTIMATEUSESACTIVITY)) &&
    567 (underestimate && ((size_t)nlhdlrexprdata & UNDERESTIMATEUSESACTIVITY)) )
    568 return SCIP_OKAY;
    569
    570 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nchildren) );
    571 SCIP_CALL( SCIPallocBufferArray(scip, &refpoint, nchildren) );
    572 /* we need to pass a branchcand array to exprhdlr's estimate also if not asked to add branching scores */
    573 SCIP_CALL( SCIPallocBufferArray(scip, &branchcand, nchildren) );
    574
    575 for( c = 0; c < nchildren; ++c )
    576 {
    578 assert(auxvar != NULL);
    579
    580 SCIPintervalSetBounds(&bounds[c],
    583
    584 refpoint[c] = SCIPgetSolVal(scip, sol, auxvar);
    585 }
    586
    587 for( rnd = (overestimate ? 0 : 1); rnd < (underestimate ? 2 : 1); ++rnd ) /* rnd == 0: overestimate, rnd == 1: underestimate */
    588 {
    589 SCIP_ROWPREP* rowprep;
    590 SCIP_Bool success = FALSE;
    591
    592 if( rnd == 0 && ((size_t)nlhdlrexprdata & OVERESTIMATEUSESACTIVITY) )
    593 continue;
    594 if( rnd == 1 && ((size_t)nlhdlrexprdata & UNDERESTIMATEUSESACTIVITY) )
    595 continue;
    596
    598
    599 /* make sure enough space is available in rowprep arrays */
    600 SCIP_CALL( SCIPensureRowprepSize(scip, rowprep, nchildren + 1) );
    601
    602 for( c = 0; c < nchildren; ++c )
    603 branchcand[c] = TRUE;
    604
    605 /* call the estimation callback of the expression handler
    606 * since we pass the global bounds as local bounds, too, we can ignore whether resulting estimator is marked as local
    607 */
    608 SCIP_CALL( SCIPcallExprEstimate(scip, expr, bounds, bounds, refpoint, rnd == 0,
    609 rnd == 0 ? SCIPinfinity(scip) : -SCIPinfinity(scip),
    610 SCIProwprepGetCoefs(rowprep), &constant, &local, &success, branchcand) );
    611
    612 if( success )
    613 {
    614 int i;
    615
    616 /* add variables to rowprep (coefs were already added by SCIPexprhdlrEstimateExpr) */
    617 for( i = 0; i < nchildren; ++i )
    618 {
    620 SCIProwprepGetCoefs(rowprep)[i]) );
    621 }
    622
    623 SCIProwprepAddConstant(rowprep, constant);
    624
    625 SCIPdebug( SCIPinfoMessage(scip, NULL, " found rowprep ") );
    626 SCIPdebug( SCIPprintRowprepSol(scip, rowprep, sol, NULL) );
    627
    628 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "%sestimate_%s%p_sol%dnotify",
    629 rnd == 0 ? "over" : "under", SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), (void*)expr, SCIPsolGetIndex(sol));
    630
    631 /* complete estimator to cut and clean it up */
    633 SCIP_CALL( SCIPcleanupRowprep2(scip, rowprep, sol, SCIPgetHugeValue(scip), &success) );
    634 }
    635
    636 /* if cleanup succeeded and rowprep is still global, add to cutpool */
    637 if( success && !SCIProwprepIsLocal(rowprep) )
    638 {
    639 SCIP_ROW* row;
    640
    641 SCIP_CALL( SCIPgetRowprepRowCons(scip, &row, rowprep, cons) );
    643 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    644 }
    645
    646 SCIPfreeRowprep(scip, &rowprep);
    647 }
    648
    649 SCIPfreeBufferArray(scip, &branchcand);
    650 SCIPfreeBufferArray(scip, &refpoint);
    651 SCIPfreeBufferArray(scip, &bounds);
    652
    653 return SCIP_OKAY;
    654}
    655
    656/** interval-evaluate expression w.r.t. activity of children */
    657static
    658SCIP_DECL_NLHDLRINTEVAL(nlhdlrIntevalDefault)
    659{ /*lint --e{715}*/
    660 assert(scip != NULL);
    661 assert(expr != NULL);
    662
    663 /* call the interval evaluation callback of the expression handler */
    664 SCIP_CALL( SCIPcallExprInteval(scip, expr, interval, intevalvar, intevalvardata) );
    665
    666 return SCIP_OKAY;
    667}
    668
    669/** tighten bounds on children from bounds on expression and bounds on children */
    670static
    671SCIP_DECL_NLHDLRREVERSEPROP(nlhdlrReversepropDefault)
    672{ /*lint --e{715}*/
    673 SCIP_INTERVAL* childrenbounds;
    674 int c;
    675
    676 assert(scip != NULL);
    677 assert(expr != NULL);
    678 assert(infeasible != NULL);
    679 assert(nreductions != NULL);
    680
    681 *nreductions = 0;
    682
    683 SCIP_CALL( SCIPallocBufferArray(scip, &childrenbounds, SCIPexprGetNChildren(expr)) );
    684 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    685 childrenbounds[c] = SCIPgetExprBoundsNonlinear(scip, SCIPexprGetChildren(expr)[c]);
    686
    687 /* call the reverse propagation callback of the expression handler */
    688 SCIP_CALL( SCIPcallExprReverseprop(scip, expr, bounds, childrenbounds, infeasible) );
    689
    690 if( !*infeasible )
    691 {
    692 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    693 {
    695 infeasible, nreductions) );
    696 }
    698 }
    699
    700 SCIPfreeBufferArray(scip, &childrenbounds);
    701
    702 return SCIP_OKAY;
    703}
    704
    705/** nonlinear handler copy callback */
    706static
    707SCIP_DECL_NLHDLRCOPYHDLR(nlhdlrCopyhdlrDefault)
    708{ /*lint --e{715}*/
    709 assert(targetscip != NULL);
    710 assert(sourcenlhdlr != NULL);
    711
    713
    714 SCIP_CALL( SCIPincludeNlhdlrDefault(targetscip) );
    715
    716 return SCIP_OKAY;
    717}
    718
    719/** callback to free expression specific data */
    720static
    721SCIP_DECL_NLHDLRFREEEXPRDATA(nlhdlrFreeExprDataDefault)
    722{ /*lint --e{715}*/
    723 assert(nlhdlrexprdata != NULL);
    724
    725 *nlhdlrexprdata = NULL;
    726
    727 return SCIP_OKAY;
    728}
    729
    730/** includes default nonlinear handler in nonlinear constraint handler */
    732 SCIP* scip /**< SCIP data structure */
    733 )
    734{
    735 SCIP_NLHDLR* nlhdlr;
    736
    737 assert(scip != NULL);
    738
    740 NLHDLR_ENFOPRIORITY, nlhdlrDetectDefault, nlhdlrEvalAuxDefault, NULL) );
    741 assert(nlhdlr != NULL);
    742
    743 SCIPnlhdlrSetCopyHdlr(nlhdlr, nlhdlrCopyhdlrDefault);
    744 SCIPnlhdlrSetFreeExprData(nlhdlr, nlhdlrFreeExprDataDefault);
    745 SCIPnlhdlrSetSepa(nlhdlr, nlhdlrInitSepaDefault, NULL, nlhdlrEstimateDefault, NULL);
    746 SCIPnlhdlrSetSollinearize(nlhdlr, nlhdlrSollinearizeDefault);
    747 SCIPnlhdlrSetProp(nlhdlr, nlhdlrIntevalDefault, nlhdlrReversepropDefault);
    748
    749 return SCIP_OKAY;
    750}
    constraint handler for nonlinear constraints specified by algebraic expressions
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_INTERVAL_INFINITY
    Definition: def.h:189
    #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 SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPgetExprRelAuxViolationNonlinear(SCIP *scip, SCIP_EXPR *expr, SCIP_Real auxvalue, SCIP_SOL *sol, SCIP_Real *viol, SCIP_Bool *violunder, SCIP_Bool *violover)
    SCIP_VAR * SCIPgetExprAuxVarNonlinear(SCIP_EXPR *expr)
    SCIP_RETCODE SCIPtightenExprIntervalNonlinear(SCIP *scip, SCIP_EXPR *expr, SCIP_INTERVAL newbounds, SCIP_Bool *cutoff, int *ntightenings)
    SCIP_RETCODE SCIPaddExprsViolScoreNonlinear(SCIP *scip, SCIP_EXPR **exprs, int nexprs, SCIP_Real violscore, SCIP_SOL *sol, SCIP_Bool *success)
    SCIP_RETCODE SCIPregisterExprUsageNonlinear(SCIP *scip, SCIP_EXPR *expr, SCIP_Bool useauxvar, SCIP_Bool useactivityforprop, SCIP_Bool useactivityforsepabelow, SCIP_Bool useactivityforsepaabove)
    SCIP_INTERVAL SCIPgetExprBoundsNonlinear(SCIP *scip, SCIP_EXPR *expr)
    SCIP_RETCODE SCIPgetExprAbsAuxViolationNonlinear(SCIP *scip, SCIP_EXPR *expr, SCIP_Real auxvalue, SCIP_SOL *sol, SCIP_Real *viol, SCIP_Bool *violunder, SCIP_Bool *violover)
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPincludeNlhdlrDefault(SCIP *scip)
    SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
    Definition: scip_cut.c:336
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    SCIP_RETCODE SCIPsetPtrarrayVal(SCIP *scip, SCIP_PTRARRAY *ptrarray, int idx, void *val)
    const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:545
    void SCIPexprhdlrIncrementNDomainReductions(SCIP_EXPRHDLR *exprhdlr, int nreductions)
    Definition: expr.c:771
    void SCIPexprhdlrIncrementNBranchings(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:817
    SCIP_Bool SCIPexprhdlrHasReverseProp(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:675
    SCIP_Bool SCIPexprhdlrHasInitEstimates(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:635
    SCIP_Bool SCIPexprhdlrHasEstimate(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:625
    SCIP_Bool SCIPexprhdlrHasIntEval(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:615
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1479
    SCIP_RETCODE SCIPcallExprEval(SCIP *scip, SCIP_EXPR *expr, SCIP_Real *childrenvalues, SCIP_Real *val)
    Definition: scip_expr.c:2210
    SCIP_RETCODE SCIPprintExpr(SCIP *scip, SCIP_EXPR *expr, FILE *file)
    Definition: scip_expr.c:1512
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
    Definition: expr.c:4028
    SCIP_RETCODE SCIPevalExprActivity(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1742
    SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
    Definition: expr.c:3895
    void SCIPintervalIntersectEps(SCIP_INTERVAL *resultant, SCIP_Real eps, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    void SCIPintervalIntersect(SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
    void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    void SCIPnlhdlrSetCopyHdlr(SCIP_NLHDLR *nlhdlr, SCIP_DECL_NLHDLRCOPYHDLR((*copy)))
    Definition: nlhdlr.c:77
    void SCIPnlhdlrSetFreeExprData(SCIP_NLHDLR *nlhdlr, SCIP_DECL_NLHDLRFREEEXPRDATA((*freeexprdata)))
    Definition: nlhdlr.c:99
    void SCIPnlhdlrSetProp(SCIP_NLHDLR *nlhdlr, SCIP_DECL_NLHDLRINTEVAL((*inteval)), SCIP_DECL_NLHDLRREVERSEPROP((*reverseprop)))
    Definition: nlhdlr.c:124
    void SCIPnlhdlrSetSollinearize(SCIP_NLHDLR *nlhdlr, SCIP_DECL_NLHDLRSOLLINEARIZE((*sollinearize)))
    Definition: nlhdlr.c:155
    void SCIPnlhdlrSetSepa(SCIP_NLHDLR *nlhdlr, SCIP_DECL_NLHDLRINITSEPA((*initsepa)), SCIP_DECL_NLHDLRENFO((*enfo)), SCIP_DECL_NLHDLRESTIMATE((*estimate)), SCIP_DECL_NLHDLREXITSEPA((*exitsepa)))
    Definition: nlhdlr.c:137
    const char * SCIPnlhdlrGetName(SCIP_NLHDLR *nlhdlr)
    Definition: nlhdlr.c:167
    SCIP_RETCODE SCIPincludeNlhdlrNonlinear(SCIP *scip, SCIP_NLHDLR **nlhdlr, const char *name, const char *desc, int detectpriority, int enfopriority, SCIP_DECL_NLHDLRDETECT((*detect)), SCIP_DECL_NLHDLREVALAUX((*evalaux)), SCIP_NLHDLRDATA *nlhdlrdata)
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
    Definition: scip_lp.c:1529
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
    Definition: scip_lp.c:1553
    int SCIPsolGetIndex(SCIP_SOL *sol)
    Definition: sol.c:4305
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPgetHugeValue(SCIP *scip)
    SCIP_Real SCIPepsilon(SCIP *scip)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    void SCIProwprepReset(SCIP_ROWPREP *rowprep)
    Definition: misc_rowprep.c:719
    SCIP_RETCODE SCIPcleanupRowprep2(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Real maxcoefbound, SCIP_Bool *success)
    SCIP_RETCODE SCIPensureRowprepSize(SCIP *scip, SCIP_ROWPREP *rowprep, int size)
    Definition: misc_rowprep.c:887
    SCIP_Real SCIPscaleupRowprep(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_Real minscaleup, SCIP_Bool *success)
    SCIP_Real * SCIProwprepGetCoefs(SCIP_ROWPREP *rowprep)
    Definition: misc_rowprep.c:649
    char * SCIProwprepGetName(SCIP_ROWPREP *rowprep)
    Definition: misc_rowprep.c:689
    void SCIProwprepSetSidetype(SCIP_ROWPREP *rowprep, SCIP_SIDETYPE sidetype)
    Definition: misc_rowprep.c:769
    SCIP_Bool SCIProwprepIsLocal(SCIP_ROWPREP *rowprep)
    Definition: misc_rowprep.c:679
    void SCIPprintRowprepSol(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, FILE *file)
    Definition: misc_rowprep.c:826
    void SCIProwprepAddConstant(SCIP_ROWPREP *rowprep, SCIP_Real constant)
    Definition: misc_rowprep.c:760
    SCIP_SIDETYPE SCIProwprepGetSidetype(SCIP_ROWPREP *rowprep)
    Definition: misc_rowprep.c:669
    SCIP_RETCODE SCIPaddRowprepTerm(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_VAR *var, SCIP_Real coef)
    Definition: misc_rowprep.c:913
    SCIP_RETCODE SCIPgetRowprepRowCons(SCIP *scip, SCIP_ROW **row, SCIP_ROWPREP *rowprep, SCIP_CONS *cons)
    SCIP_RETCODE SCIPcreateRowprep(SCIP *scip, SCIP_ROWPREP **rowprep, SCIP_SIDETYPE sidetype, SCIP_Bool local)
    Definition: misc_rowprep.c:563
    int SCIProwprepGetNVars(SCIP_ROWPREP *rowprep)
    Definition: misc_rowprep.c:629
    void SCIProwprepSetLocal(SCIP_ROWPREP *rowprep, SCIP_Bool islocal)
    Definition: misc_rowprep.c:780
    void SCIPfreeRowprep(SCIP *scip, SCIP_ROWPREP **rowprep)
    Definition: misc_rowprep.c:583
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    #define NLHDLR_DETECTPRIORITY
    static SCIP_DECL_NLHDLRSOLLINEARIZE(nlhdlrSollinearizeDefault)
    static SCIP_DECL_NLHDLRDETECT(nlhdlrDetectDefault)
    static SCIP_DECL_NLHDLRFREEEXPRDATA(nlhdlrFreeExprDataDefault)
    #define NLHDLR_ENFOPRIORITY
    static SCIP_DECL_NLHDLREVALAUX(nlhdlrEvalAuxDefault)
    #define OVERESTIMATEUSESACTIVITY
    static SCIP_DECL_NLHDLRINITSEPA(nlhdlrInitSepaDefault)
    #define UNDERESTIMATEUSESACTIVITY
    #define infty2infty(infty1, infty2, val)
    #define NLHDLR_DESC
    static SCIP_DECL_NLHDLRCOPYHDLR(nlhdlrCopyhdlrDefault)
    #define NLHDLR_NAME
    static SCIP_DECL_NLHDLRESTIMATE(nlhdlrEstimateDefault)
    static SCIP_DECL_NLHDLRINTEVAL(nlhdlrIntevalDefault)
    static SCIP_RETCODE evalExprInAux(SCIP *scip, SCIP_EXPR *expr, SCIP_Real *val, SCIP_SOL *sol)
    static SCIP_DECL_NLHDLRREVERSEPROP(nlhdlrReversepropDefault)
    default nonlinear handler that calls expression handler methods
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public functions of nonlinear handlers of nonlinear constraints
    SCIP_EXPRCURV
    Definition: type_expr.h:61
    @ SCIP_EXPRCURV_CONVEX
    Definition: type_expr.h:63
    @ SCIP_EXPRCURV_CONCAVE
    Definition: type_expr.h:64
    #define SCIP_EXPR_MAXINITESTIMATES
    Definition: type_expr.h:198
    @ SCIP_SIDETYPE_RIGHT
    Definition: type_lp.h:66
    @ SCIP_SIDETYPE_LEFT
    Definition: type_lp.h:65
    #define SCIP_NLHDLR_METHOD_SEPAABOVE
    Definition: type_nlhdlr.h:52
    #define SCIP_NLHDLR_METHOD_SEPABOTH
    Definition: type_nlhdlr.h:53
    #define SCIP_NLHDLR_METHOD_ACTIVITY
    Definition: type_nlhdlr.h:54
    struct SCIP_NlhdlrExprData SCIP_NLHDLREXPRDATA
    Definition: type_nlhdlr.h:453
    #define SCIP_NLHDLR_METHOD_SEPABELOW
    Definition: type_nlhdlr.h:51
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63