Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_subnlp.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 heur_subnlp.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief NLP local search primal heuristic using sub-SCIPs
    28 * @author Stefan Vigerske
    29 *
    30 * @todo reconstruct sub-SCIP if problem has changed
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    36#include "scip/nlpi_ipopt.h"
    38#include "scip/cons_setppc.h"
    39#include "scip/heur_subnlp.h"
    40#include "scip/pub_event.h"
    41#include "scip/pub_heur.h"
    42#include "scip/pub_message.h"
    43#include "scip/pub_misc.h"
    44#include "scip/pub_sol.h"
    45#include "scip/pub_var.h"
    46#include "scip/scip_branch.h"
    47#include "scip/scip_cons.h"
    48#include "scip/scip_copy.h"
    49#include "scip/scip_event.h"
    50#include "scip/scip_general.h"
    51#include "scip/scip_heur.h"
    52#include "scip/scip_lp.h"
    53#include "scip/scip_mem.h"
    54#include "scip/scip_message.h"
    55#include "scip/scip_nlp.h"
    56#include "scip/scip_nlpi.h"
    57#include "scip/scip_numerics.h"
    58#include "scip/scip_param.h"
    59#include "scip/scip_presol.h"
    60#include "scip/scip_pricer.h"
    61#include "scip/scip_prob.h"
    62#include "scip/scip_sol.h"
    63#include "scip/scip_solve.h"
    65#include "scip/scip_timing.h"
    66#include "scip/scip_var.h"
    67#include <string.h>
    68
    69#define HEUR_NAME "subnlp"
    70#define HEUR_DESC "primal heuristic that performs a local search in an NLP after fixing integer variables and presolving"
    71#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    72#define HEUR_PRIORITY -2000010
    73#define HEUR_FREQ 1
    74#define HEUR_FREQOFS 0
    75#define HEUR_MAXDEPTH -1
    76#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
    77#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? we set this to FALSE because we want this heuristic to also run within other heuristics */
    78
    79/*
    80 * Data structures
    81 */
    82
    83/** primal heuristic data */
    84struct SCIP_HeurData
    85{
    86 SCIP* subscip; /**< copy of CIP where presolving and NLP solving is done */
    87 SCIP_Bool triedsetupsubscip; /**< whether we have tried to setup a sub-SCIP */
    88 SCIP_Bool subscipisvalid; /**< whether all constraints have been copied */
    89 SCIP_Bool continuous; /**< whether problem was continuous when sub-SCIP was created */
    90 int nseriousnlpierror; /**< number of consecutive serious NLP solver failures (memout, ...) */
    91 SCIP_EVENTHDLR* eventhdlr; /**< event handler for global bound change events */
    92
    93 int nvars; /**< number of active transformed variables in SCIP */
    94 int nsubvars; /**< number of original variables in sub-SCIP */
    95 SCIP_VAR** var_subscip2scip; /**< mapping variables in sub-SCIP to SCIP variables */
    96 SCIP_VAR** var_scip2subscip; /**< mapping variables in SCIP to sub-SCIP variables */
    97
    98 SCIP_SOL* startcand; /**< candidate for start point for heuristic */
    99 SCIP_Real startcandviol; /**< violation of start point candidate w.r.t. constraint that reported this candidate */
    100 SCIP_SOL* lastsol; /**< pointer to last found solution (or NULL if none), not captured, thus may be dangling */
    101
    102 int nlpverblevel; /**< verbosity level of NLP solver */
    103 SCIP_Real opttol; /**< optimality tolerance to use for NLP solves */
    104 SCIP_Real feastolfactor; /**< factor on SCIP feasibility tolerance for NLP solves if resolving when NLP solution not feasible in CIP */
    105 SCIP_Real feastol; /**< feasibility tolerance for NLP solves */
    106 SCIP_Bool tighterfeastolfailed;/**< whether we tried to use a tighter feasibility tolerance but the NLP solution was still not accepted */
    107 int maxpresolverounds; /**< limit on number of presolve rounds in sub-SCIP */
    108 int presolveemphasis; /**< presolve emphasis in sub-SCIP */
    109 SCIP_Bool setcutoff; /**< whether to set cutoff in sub-SCIP to current primal bound */
    110 SCIP_Bool forbidfixings; /**< whether to add constraints that forbid specific fixations that turned out to be infeasible */
    111 SCIP_Bool keepcopy; /**< whether to keep SCIP copy or to create new copy each time heuristic is applied */
    112 SCIP_Real expectinfeas; /**< when to tell NLP solver that an infeasible NLP is not unexpected */
    113
    114 SCIP_Longint iterused; /**< number of iterations used so far (+ number of heuristic runs + number of presolve runs in subscip) */
    115 SCIP_Longint iterusedokay; /**< number of iterations used so far when NLP stopped with status okay */
    116 SCIP_Longint iterusediterlim; /**< maximal number of iterations used when NLP stopped due to iteration limit */
    117 int nnlpsolves; /**< number of NLP solves */
    118 int nnlpsolvesokay; /**< number of NLP solves with status okay */
    119 int nnlpsolvesiterlim; /**< number of NLP solves that hit an iteration limit */
    120 int nnlpsolvesinfeas; /**< number of NLP solves with status okay and infeasible */
    121 int nodesoffset; /**< number of nodes added to the actual number of nodes when computing itercontingent */
    122 SCIP_Real nodesfactor; /**< factor to apply to number of nodes in SCIP to compute initial itercontingent */
    123 SCIP_Real successrateexp; /**< exponent for power of success rate to be multiplied with itercontingent */
    124 int iterinit; /**< number of iterations used for initial NLP solves */
    125 int ninitsolves; /**< number of successful NLP solves until switching to iterlimit guess and using success rate */
    126 int itermin; /**< minimal number of iterations for NLP solves */
    127 SCIP_HEURTIMING inittiming; /**< initial heuristic timing */
    128};
    129
    130
    131/*
    132 * Local methods
    133 */
    134
    135/** free sub-SCIP data structure */
    136static
    138 SCIP* scip, /**< SCIP data structure */
    139 SCIP_HEURDATA* heurdata /**< heuristic data structure */
    140 )
    141{
    142 SCIP_VAR** subvars;
    143 int nsubvars;
    144 int i;
    145 SCIP_VAR* var;
    146 SCIP_VAR* subvar;
    147
    148 assert(scip != NULL);
    149 assert(heurdata != NULL);
    150
    151 assert(heurdata->subscip != NULL);
    152
    153 SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, NULL, NULL, NULL, NULL) );
    154 assert(nsubvars == heurdata->nsubvars);
    155
    156 /* drop global bound change events
    157 * release variables in SCIP and sub-SCIP
    158 */
    159 for( i = 0; i < heurdata->nsubvars; ++i )
    160 {
    161 subvar = subvars[i];
    162 assert(subvar != NULL);
    163 assert(SCIPvarGetProbindex(subvar) == i);
    164
    165 var = heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)];
    166 assert(var != NULL);
    167 assert(SCIPvarGetProbindex(var) <= heurdata->nvars);
    168 assert(!SCIPvarIsActive(var) || heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] == subvar);
    169
    170 SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, -1) );
    171
    172 SCIP_CALL( SCIPreleaseVar(heurdata->subscip, &subvar) );
    173 SCIP_CALL( SCIPreleaseVar(scip, &var) );
    174 }
    175
    176 /* free variable mappings subscip -> scip and scip -> subscip */
    177 SCIPfreeBlockMemoryArray(scip, &heurdata->var_subscip2scip, heurdata->nsubvars);
    178 SCIPfreeBlockMemoryArray(scip, &heurdata->var_scip2subscip, heurdata->nvars);
    179 heurdata->nsubvars = 0;
    180 heurdata->nvars = 0;
    181
    182 /* free sub-SCIP */
    183 SCIP_CALL( SCIPfree(&heurdata->subscip) );
    184
    185 return SCIP_OKAY;
    186}
    187
    188/** creates copy of CIP from problem in SCIP */
    189static
    191 SCIP* scip, /**< SCIP data structure */
    192 SCIP_HEURDATA* heurdata /**< heuristic data structure */
    193 )
    194{
    195 int nvars;
    196 SCIP_VAR** vars;
    197 SCIP_VAR** subvars;
    198 SCIP_VAR* var;
    199 SCIP_VAR* subvar;
    200 SCIP_Bool success;
    201 char probname[SCIP_MAXSTRLEN];
    202 int i;
    203 SCIP_HASHMAP* varsmap;
    204 SCIP_HASHMAP* conssmap;
    205
    206 assert(heurdata != NULL);
    207 assert(heurdata->subscip == NULL);
    208
    209 heurdata->triedsetupsubscip = TRUE;
    210
    211 /* initializing the subproblem */
    212 SCIP_CALL( SCIPcreate(&heurdata->subscip) );
    213
    214 /* create sub-SCIP copy of CIP */
    215
    216 /* copy interesting plugins */
    217 success = TRUE;
    218 SCIP_CALL( SCIPcopyPlugins(scip, heurdata->subscip,
    219 FALSE, /* readers */
    220 FALSE, /* pricers */
    221 TRUE, /* conshdlrs */
    222 FALSE, /* conflicthdlrs */
    223 TRUE, /* presolvers */
    224 FALSE, /* relaxators */
    225 FALSE, /* separators */
    226 FALSE, /* cutselectors */
    227 TRUE, /* propagators */
    228 FALSE, /* heuristics */
    229 TRUE, /* eventhandler */
    230 TRUE, /* nodeselectors (SCIP gives an error if there is none) */
    231 FALSE, /* branchrules */
    232 FALSE, /* iis */
    233 TRUE, /* displays */
    234 FALSE, /* tables */
    235 FALSE, /* dialogs */
    236 TRUE, /* expression handlers */
    237 TRUE, /* nlpis */
    238 TRUE, /* message handler */
    239 &success) );
    240 if( !success )
    241 {
    242 SCIPdebugMsg(scip, "failed to copy some plugins to sub-SCIP, continue anyway\n");
    243 }
    244
    245 /* check if we still have NLPI's in subscip */
    246 if( SCIPgetNNlpis(heurdata->subscip) <= 0 )
    247 {
    248 SCIPdebugMsg(scip, "none of the NLPIs from main SCIP copied into sub-SCIP, give up heuristic.\n");
    249 SCIP_CALL( SCIPfree(&heurdata->subscip) );
    250
    251 return SCIP_OKAY;
    252 }
    253
    254 /* copy parameter settings */
    255 SCIP_CALL( SCIPcopyParamSettings(scip, heurdata->subscip) );
    256
    257 /* create problem in sub-SCIP */
    258 /* get name of the original problem and add "subnlp" */
    259 (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_subnlp", SCIPgetProbName(scip));
    260 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    261 SCIP_CALL( SCIPhashmapCreate(&varsmap, SCIPblkmem(scip), nvars) );
    263 SCIP_CALL( SCIPcopyProb(scip, heurdata->subscip, varsmap, conssmap, TRUE, probname) );
    264
    265 /* copy all variables */
    266 SCIP_CALL( SCIPcopyVars(scip, heurdata->subscip, varsmap, conssmap, NULL, NULL, 0, TRUE) );
    267
    268 /* copy as many constraints as possible */
    269 SCIP_CALL( SCIPcopyConss(scip, heurdata->subscip, varsmap, conssmap, TRUE, FALSE, &heurdata->subscipisvalid) );
    270 SCIPhashmapFree(&conssmap);
    271 if( !heurdata->subscipisvalid )
    272 {
    273 SCIPdebugMsg(scip, "failed to copy some constraints to sub-SCIP, continue anyway\n");
    274 }
    275
    276 /* create arrays translating scip transformed vars to subscip original vars, and vice versa
    277 * capture variables in SCIP and sub-SCIP
    278 * catch global bound change events
    279 */
    280
    281 SCIP_CALL( SCIPgetVarsData(heurdata->subscip, &subvars, &heurdata->nsubvars, NULL, NULL, NULL, NULL) );
    282
    283 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &heurdata->var_subscip2scip, heurdata->nsubvars) );
    284
    285 heurdata->nvars = nvars;
    286 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &heurdata->var_scip2subscip, heurdata->nvars) );
    287
    288 /* we need to get all subscip variables, also those which are copies of fixed variables from the main scip
    289 * therefore we iterate over the hashmap
    290 */
    291 for( i = 0; i < SCIPhashmapGetNEntries(varsmap); ++i )
    292 {
    293 SCIP_HASHMAPENTRY* entry;
    294 entry = SCIPhashmapGetEntry(varsmap, i);
    295 if( entry != NULL )
    296 {
    297 var = (SCIP_VAR*) SCIPhashmapEntryGetOrigin(entry);
    298 subvar = (SCIP_VAR*) SCIPhashmapEntryGetImage(entry);
    299 assert(subvar != NULL);
    300 assert(SCIPvarGetProbindex(subvar) >= 0);
    301 assert(SCIPvarGetProbindex(subvar) <= heurdata->nsubvars);
    302
    303 if( SCIPvarIsActive(var) )
    304 {
    305 assert(SCIPvarGetProbindex(var) <= heurdata->nvars);
    306 assert(heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] == NULL); /* assert that we have no mapping for this var yet */
    307 heurdata->var_scip2subscip[SCIPvarGetProbindex(var)] = subvar;
    308 }
    309
    310 assert(heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)] == NULL); /* assert that we have no mapping for this subvar yet */
    311 heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)] = var;
    312 }
    313 }
    314
    315 for( i = 0; i < heurdata->nsubvars; ++i )
    316 {
    317 subvar = SCIPgetVars(heurdata->subscip)[i];
    318 assert(SCIPvarGetProbindex(subvar) == i);
    319 var = heurdata->var_subscip2scip[i];
    320
    322 SCIP_CALL( SCIPcaptureVar(heurdata->subscip, subvar) );
    323
    326
    327 SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, NULL) );
    328 }
    329
    330#ifndef NDEBUG
    331 for( i = 0; i < heurdata->nvars; ++i )
    332 {
    333 assert(heurdata->var_scip2subscip[i] == NULL || (SCIP_VAR*)SCIPhashmapGetImage(varsmap, (void*)vars[i]) == heurdata->var_scip2subscip[i]);
    334 }
    335 for( i = 0; i < heurdata->nsubvars; ++i )
    336 {
    337 assert(heurdata->var_subscip2scip[i] != NULL);
    338 assert((SCIP_VAR*)SCIPhashmapGetImage(varsmap, (void*)heurdata->var_subscip2scip[i]) == subvars[i]);
    339 }
    340#endif
    341
    342 /* do not need hashmap anymore */
    343 SCIPhashmapFree(&varsmap);
    344
    345 /* do not abort subproblem on CTRL-C */
    346 SCIP_CALL( SCIPsetBoolParam(heurdata->subscip, "misc/catchctrlc", FALSE) );
    347
    348 /* disable keeping solutions from one subscip solve for next solve (with usually different fixings) */
    349 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "limits/maxorigsol", 0) );
    350
    351#ifdef SCIP_DEBUG
    352 /* for debugging, enable SCIP output */
    353 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 5) );
    354#else
    355 /* disable output to console */
    356 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "display/verblevel", 0) );
    357#endif
    358
    359 /* reset some limits to default values, in case users changed them in main scip (SCIPcopy copies parameter values :-() */
    360 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/absgap") );
    361 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/bestsol") );
    362 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/gap") );
    363 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/restarts") );
    364 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/solutions") );
    365 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/time") );
    366 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/totalnodes") );
    367 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/primal") );
    368 SCIP_CALL( SCIPresetParam(heurdata->subscip, "limits/dual") );
    369
    370 /* we remember here which way (continuous or not) we went, in case all binary and integer vars get fixed in root */
    371 heurdata->continuous = (SCIPgetNContVars(heurdata->subscip) + SCIPgetNContImplVars(heurdata->subscip)
    372 == SCIPgetNVars(heurdata->subscip));
    373 if( !heurdata->continuous )
    374 {
    375 /* set presolve maxrounds and emphasis; always disable components presolver
    376 * heuristics and separators were not copied into subscip, so should not need to switch off
    377 */
    378 if( !SCIPisParamFixed(heurdata->subscip, "presolving/maxrounds") )
    379 {
    380 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "presolving/maxrounds", heurdata->maxpresolverounds) );
    381 }
    382 SCIP_CALL( SCIPsetPresolving(heurdata->subscip, (SCIP_PARAMSETTING)heurdata->presolveemphasis, TRUE) );
    383 if( !SCIPisParamFixed(heurdata->subscip, "constraints/components/maxprerounds") )
    384 {
    385 SCIP_CALL( SCIPsetIntParam(heurdata->subscip, "constraints/components/maxprerounds", 0) );
    386 }
    387 }
    388 else
    389 {
    390 /* for continuous problems, disable presolve and move subscip into a stage where it has a NLP
    391 * the only reason why we don't solve the NLP in the main SCIP is that we want global variable bounds for the NLP
    392 */
    393 SCIP_RETCODE retcode;
    394
    395 SCIP_CALL( SCIPtransformProb(heurdata->subscip) );
    396
    398 SCIP_CALL( SCIPpresolve(heurdata->subscip) );
    399
    400 if( SCIPgetStage(heurdata->subscip) != SCIP_STAGE_PRESOLVED || SCIPgetNVars(heurdata->subscip) == 0 )
    401 {
    402 /* presolve found problem infeasible, solved it, or stopped due to some limit
    403 * all a bit strange, since problem should be the same as original, presolve was disabled, and we didn't set any limits
    404 * we will give up and not run the heuristic
    405 */
    406 SCIP_CALL( freeSubSCIP(scip, heurdata) );
    407 return SCIP_OKAY;
    408 }
    409
    410 /* do initial solve, i.e., "solve" root node with node limit 0 (should do scip.c::initSolve and then stop immediately in solve.c::SCIPsolveCIP) */
    411 SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 0LL) );
    412 retcode = SCIPsolve(heurdata->subscip);
    413
    414 /* errors in solving the subproblem should not kill the overall solving process
    415 * hence, the return code is caught and a warning is printed
    416 */
    417 if( retcode != SCIP_OKAY )
    418 {
    419 SCIPwarningMessage(scip, "Error while initializing subproblem in subnlp heuristic; sub-SCIP terminated with code <%d>\n", retcode);
    420 SCIP_CALL( freeSubSCIP(scip, heurdata) );
    421 return SCIP_OKAY;
    422 }
    423
    424 /* If we are in stage "solved" (strange) or have no NLP (also strange), then do not run heuristic, too */
    425 if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED || !SCIPisNLPConstructed(heurdata->subscip) )
    426 {
    427 SCIP_CALL( freeSubSCIP(scip, heurdata) );
    428 return SCIP_OKAY;
    429 }
    430
    431 assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVING);
    432 assert(SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_NODELIMIT);
    433 assert(SCIPisNLPConstructed(heurdata->subscip));
    434 }
    435
    436 return SCIP_OKAY;
    437}
    438
    439/** process variable global bound change event */
    440static
    441SCIP_DECL_EVENTEXEC(processVarEvent)
    442{
    443 SCIP_HEURDATA* heurdata;
    444 SCIP_VAR* var;
    445 SCIP_VAR* subvar;
    446 int idx;
    447
    448 assert(scip != NULL);
    449 assert(event != NULL);
    450 assert(eventdata != NULL);
    451 assert(eventhdlr != NULL);
    452
    453 heurdata = (SCIP_HEURDATA*)eventdata;
    454 assert(heurdata != NULL);
    455
    456 var = SCIPeventGetVar(event);
    457 assert(var != NULL);
    458
    459 idx = SCIPvarGetProbindex(var);
    460 /* if event corresponds to an active variable, we can easily look up the corresponding subvar
    461 * if it is an inactive variable that has been copied to the subproblem,
    462 * then we need to check the subscip2scip mapping
    463 * @todo we could do this faster if we keep the variables mapping from SCIPcopy around
    464 */
    465 if( idx >= 0 )
    466 {
    467 assert(idx < heurdata->nvars);
    468
    469 subvar = heurdata->var_scip2subscip[idx];
    470 }
    471 else
    472 {
    473 for( idx = 0; idx < heurdata->nsubvars; ++idx )
    474 {
    475 if( heurdata->var_subscip2scip[idx] == var )
    476 break;
    477 }
    478 assert(idx < heurdata->nsubvars);
    479 subvar = SCIPgetVars(heurdata->subscip)[idx];
    480 }
    481 assert(subvar != NULL);
    482
    484 {
    485 SCIP_CALL( SCIPchgVarLbGlobal(heurdata->subscip, subvar, SCIPeventGetNewbound(event)) );
    486 }
    487
    489 {
    490 SCIP_CALL( SCIPchgVarUbGlobal(heurdata->subscip, subvar, SCIPeventGetNewbound(event)) );
    491 }
    492
    493 return SCIP_OKAY;
    494}
    495
    496/* creates a SCIP_SOL in our SCIP space out of the solution from NLP solver in sub-SCIP */
    497static
    499 SCIP* scip, /**< SCIP data structure */
    500 SCIP_HEUR* heur, /**< heuristic data structure */
    501 SCIP_SOL** sol, /**< buffer to store solution value; if pointing to NULL, then a new solution is created, otherwise values in the given one are overwritten */
    502 SCIP_HEUR* authorheur /**< the heuristic which should be registered as author of the solution */
    503 )
    504{
    505 SCIP_HEURDATA* heurdata;
    506 SCIP_VAR** vars;
    507 int nvars;
    508 SCIP_VAR* var;
    509 SCIP_VAR* subvar;
    510 SCIP_Real solval;
    511 int i;
    512
    513 assert(scip != NULL);
    514 assert(heur != NULL);
    515 assert(sol != NULL);
    516
    517 heurdata = SCIPheurGetData(heur);
    518 assert(heurdata != NULL);
    519 assert(SCIPhasNLPSolution(heurdata->subscip));
    520
    521 if( *sol == NULL )
    522 {
    523 SCIP_CALL( SCIPcreateSol(scip, sol, authorheur) );
    524 }
    525 else
    526 {
    527 SCIPsolSetHeur(*sol, authorheur);
    528 }
    529
    530 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    531
    532 assert(nvars >= heurdata->nvars);
    533 for( i = 0; i < heurdata->nvars; ++i )
    534 {
    535 var = vars[i];
    536 assert(var != NULL);
    537 assert(SCIPvarIsActive(var)); /* SCIPgetVarsData should have given us only active vars */
    538
    539 subvar = heurdata->var_scip2subscip[i];
    540 if( subvar == NULL )
    541 solval = MIN(MAX(0.0, SCIPvarGetLbLocal(var)), SCIPvarGetUbLocal(var)); /*lint !e666*/
    542 else
    543 solval = SCIPvarGetNLPSol(subvar);
    544
    545 assert(solval != SCIP_INVALID); /*lint !e777*/
    546 SCIP_CALL( SCIPsetSolVal(scip, *sol, var, solval) );
    547 }
    548
    549 for( ; i < nvars; ++i )
    550 {
    551 var = vars[i];
    552 assert(var != NULL);
    553 assert(SCIPvarIsActive(var)); /* SCIPgetVarsData should have given us only active vars */
    554
    555 solval = MIN(MAX(0.0, SCIPvarGetLbLocal(var)), SCIPvarGetUbLocal(var)); /*lint !e666*/
    556 SCIP_CALL( SCIPsetSolVal(scip, *sol, var, solval) );
    557 }
    558
    559 return SCIP_OKAY;
    560}
    561
    562/** creates SCIP solution from NLP and tries adding to SCIP or only checks feasibility */
    563static
    565 SCIP* scip, /**< original SCIP data structure */
    566 SCIP_HEUR* heur, /**< heuristic data structure */
    567 SCIP_HEUR* authorheur, /**< the heuristic that should be the author of solution, if any */
    568 SCIP_RESULT* result, /**< buffer to store result FOUNDSOL if a solution has been found and accepted */
    569 SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
    570 )
    571{
    572 SCIP_HEURDATA* heurdata;
    573
    574 assert(scip != NULL);
    575 assert(heur != NULL);
    576 assert(result != NULL);
    577
    578 heurdata = SCIPheurGetData(heur);
    579 assert(heurdata != NULL);
    580
    581 assert(SCIPhasNLPSolution(heurdata->subscip));
    582
    583 if( resultsol == NULL )
    584 {
    585 /* resultsol NULL means we should try adding the sol to SCIP */
    586 if( SCIPisLE(scip, SCIPgetNLPObjval(heurdata->subscip), SCIPgetUpperbound(scip)) )
    587 {
    588 /* solution is feasible and should improve upper bound, so try adding it to SCIP */
    589 SCIP_SOL* sol;
    590 SCIP_Bool stored;
    591
    592 sol = NULL;
    593 SCIP_CALL( createSolFromNLP(scip, heur, &sol, authorheur) );
    594
    595 heurdata->lastsol = sol; /* remember just the pointer so we might recognize if this solution comes back as startingpoint */
    596#ifdef SCIP_DEBUG
    597 /* print the infeasibilities to stdout */
    598 SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, TRUE, TRUE, FALSE, TRUE, &stored) );
    599#else
    600 SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
    601#endif
    602
    603 if( stored )
    604 {
    605 /* SCIP stored solution (yippi!), so we are done */
    606 if( heurdata->nlpverblevel >= 1 )
    607 {
    608 SCIPinfoMessage(scip, NULL, "SCIP stored solution from NLP solve\n");
    609 }
    610 else
    611 {
    612 SCIPdebugMsg(scip, "SCIP stored solution from NLP solve\n");
    613 }
    614
    615 *result = SCIP_FOUNDSOL;
    616 }
    617 else
    618 {
    619 if( heurdata->nlpverblevel >= 1 )
    620 {
    621 SCIPinfoMessage(scip, NULL, "solution reported by NLP solver not stored by SCIP\n");
    622 }
    623 else
    624 {
    625 SCIPdebugMsg(scip, "solution reported by NLP solver not stored by SCIP\n");
    626 }
    627 }
    628 }
    629 else if( heurdata->nlpverblevel >= 1 )
    630 {
    631 SCIPinfoMessage(scip, NULL, "subnlp solution objval %e is above the primal bound %e\n",
    632 SCIPgetNLPObjval(heurdata->subscip), SCIPgetUpperbound(scip));
    633 }
    634 }
    635 else
    636 {
    637 /* only create a solution and pass it back in resultsol, do not add to SCIP */
    638 SCIP_Bool feasible;
    639
    640 SCIP_CALL( createSolFromNLP(scip, heur, &resultsol, authorheur) );
    641
    642 heurdata->lastsol = resultsol;
    643#ifdef SCIP_DEBUG
    644 /* print the infeasibilities to stdout */
    645 SCIP_CALL( SCIPcheckSol(scip, resultsol, TRUE, TRUE, TRUE, FALSE, TRUE, &feasible) );
    646#else
    647 SCIP_CALL( SCIPcheckSol(scip, resultsol, FALSE, FALSE, TRUE, FALSE, TRUE, &feasible) );
    648#endif
    649 if( feasible )
    650 {
    651 /* SCIP find solution feasible, so we are done */
    652 if( heurdata->nlpverblevel >= 1 )
    653 {
    654 SCIPinfoMessage(scip, NULL, "solution reported by NLP solver feasible for SCIP\n");
    655 }
    656 else
    657 {
    658 SCIPdebugMsg(scip, "solution reported by NLP solver feasible for SCIP\n");
    659 }
    660 *result = SCIP_FOUNDSOL;
    661 }
    662 else
    663 {
    664 if( heurdata->nlpverblevel >= 1 )
    665 {
    666 SCIPinfoMessage(scip, NULL, "solution reported by NLP solver not feasible for SCIP\n");
    667 }
    668 else
    669 {
    670 SCIPdebugMsg(scip, "solution reported by NLP solver not feasible for SCIP\n");
    671 }
    672 }
    673 }
    674
    675 return SCIP_OKAY;
    676}
    677
    678/* creates a SCIP_SOL in our SCIP space out of the SCIP_SOL from a sub-SCIP */
    679static
    681 SCIP* scip, /**< SCIP data structure */
    682 SCIP_HEUR* heur, /**< heuristic data structure */
    683 SCIP_SOL** sol, /**< buffer to store solution value; if pointing to NULL, then a new solution is created, otherwise values in the given one are overwritten */
    684 SCIP_SOL* subsol, /**< solution of sub-SCIP */
    685 SCIP_HEUR* authorheur /**< the heuristic which should be registered as author of the solution */
    686 )
    687{
    688 SCIP_HEURDATA* heurdata;
    689 SCIP_VAR** vars;
    690 int nvars;
    691 SCIP_VAR* var;
    692 SCIP_VAR* subvar;
    693 SCIP_Real solval;
    694 int i;
    695
    696 assert(scip != NULL);
    697 assert(heur != NULL);
    698 assert(sol != NULL);
    699 assert(subsol != NULL);
    700
    701 heurdata = SCIPheurGetData(heur);
    702 assert(heurdata != NULL);
    703
    704 if( *sol == NULL )
    705 {
    706 SCIP_CALL( SCIPcreateSol(scip, sol, authorheur) );
    707 }
    708 else
    709 {
    710 SCIPsolSetHeur(*sol, authorheur);
    711 }
    712
    713 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    714
    715 assert(nvars >= heurdata->nvars);
    716 for( i = 0; i < heurdata->nvars; ++i )
    717 {
    718 var = vars[i];
    719 assert(var != NULL);
    720 assert(SCIPvarIsActive(var));
    721
    722 subvar = heurdata->var_scip2subscip[i];
    723 if( subvar == NULL )
    724 solval = MIN(MAX(0.0, SCIPvarGetLbLocal(var)), SCIPvarGetUbLocal(var)); /*lint !e666*/
    725 else
    726 solval = SCIPgetSolVal(heurdata->subscip, subsol, subvar);
    727
    728 assert(solval != SCIP_INVALID); /*lint !e777*/
    729 SCIP_CALL( SCIPsetSolVal(scip, *sol, var, solval) );
    730 }
    731
    732 for( ; i < nvars; ++i )
    733 {
    734 var = vars[i];
    735 assert(var != NULL);
    736 assert(SCIPvarIsActive(var));
    737
    738 solval = MIN(MAX(0.0, SCIPvarGetLbLocal(var)), SCIPvarGetUbLocal(var)); /*lint !e666*/
    739 SCIP_CALL( SCIPsetSolVal(scip, *sol, var, solval) );
    740 }
    741
    742 return SCIP_OKAY;
    743}
    744
    745/** finds an iteration limit */ /*lint --e{715}*/
    746static
    748 SCIP* scip, /**< original SCIP data structure */
    749 SCIP_HEURDATA* heurdata /**< heuristic data */
    750 )
    751{
    752 /* if we hit more often an iterlimit than we were successful (termstatus=okay), then allow for more iterations:
    753 * take twice the maximal iterusage on solves that hit the iterlimit
    754 */
    755 if( heurdata->nnlpsolvesiterlim > heurdata->nnlpsolvesokay )
    756 return MAX(heurdata->itermin, 2 * heurdata->iterusediterlim); /*lint !e712*/
    757
    758 /* if we had sufficiently many successful solves, then take twice the average of previous iterusages on successful solves */
    759 if( heurdata->nnlpsolvesokay >= heurdata->ninitsolves )
    760 return MAX(heurdata->itermin, 2 * heurdata->iterusedokay / heurdata->nnlpsolvesokay); /*lint !e712*/
    761
    762 /* if we had too few successful solves, then still ensure that we allow for at least iterinit iterations */
    763 if( heurdata->nnlpsolvesokay > 0 )
    764 return MAX3(heurdata->itermin, heurdata->iterinit, 2 * heurdata->iterusedokay / heurdata->nnlpsolvesokay); /*lint !e712*/
    765
    766 /* if we had no successful solve so far and none that hit an iterlimit, e.g., we are at the first NLP solve, then use iterinit */
    767 return MAX(heurdata->itermin, heurdata->iterinit);
    768}
    769
    770/** solves the subNLP specified in subscip */
    771static
    773 SCIP* scip, /**< original SCIP data structure */
    774 SCIP_HEUR* heur, /**< heuristic data structure */
    775 SCIP_RESULT* result, /**< buffer to store result, DIDNOTFIND, FOUNDSOL, or CUTOFF */
    776 SCIP_SOL* refpoint, /**< point to take fixation of discrete variables from, and startpoint for NLP solver; if NULL, then LP solution is used */
    777 SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
    778 )
    779{
    780 SCIP_HEURDATA* heurdata = SCIPheurGetData(heur);
    781 SCIP_RETCODE retcode;
    782 SCIP_Real* startpoint;
    783 SCIP_VAR* var;
    784 SCIP_VAR* subvar;
    785 int i;
    786 SCIP_HEUR* authorheur; /* the heuristic which will be the author of a solution, if found */
    787 SCIP_Real timelimit;
    788 SCIP_Bool expectinfeas;
    789 SCIP_NLPSTATISTICS nlpstatistics;
    790
    791 assert(scip != NULL);
    792 assert(heur != NULL);
    793 assert(heurdata != NULL);
    794 assert(result != NULL);
    795 assert(SCIPisTransformed(heurdata->subscip));
    796
    797 /* get remaining SCIP solve time; if no time left, then stop */
    798 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
    799 if( !SCIPisInfinity(scip, timelimit) )
    800 {
    801 timelimit -= SCIPgetSolvingTime(scip);
    802 if( timelimit <= 0.0 )
    803 return SCIP_OKAY;
    804 }
    805 /* set timelimit for NLP solve and in case presolve is unexpectedly expensive */
    806 SCIP_CALL( SCIPsetRealParam(heurdata->subscip, "limits/time", timelimit) );
    807
    808 /* if the refpoint comes from a heuristic, then make it the author of a found solution,
    809 * otherwise let the subNLP heuristic claim authorship
    810 * TODO: I doubt that this has much effect; for the statistics, the number of solutions found by a heuristic
    811 * seems to be computed as the increase in number of solutions before and after a heuristic is run
    812 * check this and maybe change
    813 */
    814 if( refpoint == NULL || SCIPsolGetHeur(refpoint) == NULL )
    815 authorheur = heur;
    816 else
    817 authorheur = SCIPsolGetHeur(refpoint);
    818
    819 if( !heurdata->continuous )
    820 {
    821 /* presolve sub-SCIP
    822 * set node limit to 1 so that presolve can go
    823 */
    824 SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
    825 SCIP_CALL( SCIPpresolve(heurdata->subscip) );
    826
    827 /* count one presolve round as on NLP iteration for now
    828 * plus one extra for all the setup cost
    829 * this is mainly to avoid that the primal heuristics runs all the time on instances that are solved in the subscip-presolve
    830 */
    831 heurdata->iterused += 1 + SCIPgetNPresolRounds(scip); /*lint !e776*/
    832
    833 if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED )
    834 {
    835 /* presolve probably found the subproblem infeasible */
    836 SCIPdebugMsg(scip, "SCIP returned from presolve in stage solved with status %d and %d sols\n", SCIPgetStatus(heurdata->subscip), SCIPgetNSols(heurdata->subscip));
    837 /* if presolve found subproblem infeasible, report this to caller by setting *result to cutoff */
    838 if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
    839 *result = SCIP_CUTOFF;
    840 }
    841 else if( SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVING )
    842 {
    843 /* presolve was stopped because some still existing limit was hit (e.g., memory) */
    844 SCIPdebugMsg(scip, "SCIP returned from presolve in stage presolving with status %d and %d sols\n", SCIPgetStatus(heurdata->subscip), SCIPgetNSols(heurdata->subscip));
    845 /* if presolve found subproblem infeasible, report this to caller by setting *result to cutoff */
    846 if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
    847 *result = SCIP_CUTOFF;
    848 }
    849 else
    850 {
    851 assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVED);
    852
    853 if( SCIPgetNVars(heurdata->subscip) > 0 )
    854 {
    855 /* do initial solve, i.e., "solve" root node with node limit 0 (should do scip.c::initSolve and then stop immediately in solve.c::SCIPsolveCIP) */
    856 SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 0LL) );
    857 retcode = SCIPsolve(heurdata->subscip);
    858
    859 /* If no NLP was constructed, then there were no nonlinearities after presolve.
    860 * So we increase the nodelimit to 1 and hope that SCIP will find some solution to this probably linear subproblem.
    861 */
    862 if( retcode == SCIP_OKAY && SCIPgetStage(heurdata->subscip) != SCIP_STAGE_SOLVED && !SCIPisNLPConstructed(heurdata->subscip) )
    863 {
    864 SCIP_CALL( SCIPsetLongintParam(heurdata->subscip, "limits/nodes", 1LL) );
    865 retcode = SCIPsolve(heurdata->subscip);
    866 }
    867 }
    868 else
    869 {
    870 /* If all variables were removed by presolve, but presolve did not end with status SOLVED,
    871 * then we run solve, still with nodelimit=1, and hope to find some (maybe trivial) solution.
    872 */
    873 retcode = SCIPsolve(heurdata->subscip);
    874 }
    875
    876 /* errors in solving the subproblem should not kill the overall solving process
    877 * hence, the return code is caught and a warning is printed
    878 */
    879 if( retcode != SCIP_OKAY )
    880 {
    881 SCIPwarningMessage(scip, "Error while solving subproblem in subnlp heuristic; sub-SCIP terminated with code <%d>\n", retcode);
    882 return SCIP_OKAY;
    883 }
    884 }
    885
    886 /* we should either have variables, or the problem was trivial, in which case it should have been presolved or solved */
    887 assert(SCIPgetNVars(heurdata->subscip) > 0 || SCIPgetStage(heurdata->subscip) == SCIP_STAGE_PRESOLVING || SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED);
    888
    889 SCIPdebug( SCIP_CALL( SCIPprintStatistics(heurdata->subscip, NULL) ); )
    890
    891 /* if sub-SCIP found solutions already, then pass them to main scip */
    892 for( i = 0; i < SCIPgetNSols(heurdata->subscip); ++i )
    893 {
    894 if( resultsol == NULL )
    895 {
    896 SCIP_Bool stored;
    897 SCIP_SOL* sol;
    898
    899 sol = NULL;
    900 SCIP_CALL( createSolFromSubScipSol(scip, heur, &sol, SCIPgetSols(heurdata->subscip)[i], authorheur) );
    901
    902 heurdata->lastsol = sol; /* remember just the pointer so we might recognize if this solution comes back as startingpoint */
    903 SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, TRUE, FALSE, TRUE, &stored) );
    904 if( stored )
    905 {
    906 if( heurdata->nlpverblevel >= 1 )
    907 {
    908 SCIPinfoMessage(scip, NULL, "SCIP stored solution from sub-SCIP root node\n");
    909 }
    910 else
    911 {
    912 SCIPdebugMsg(scip, "SCIP stored solution from sub-SCIP root node\n");
    913 }
    914 *result = SCIP_FOUNDSOL;
    915 break;
    916 }
    917 else
    918 {
    919 if( heurdata->nlpverblevel >= 1 )
    920 {
    921 SCIPinfoMessage(scip, NULL, "SCIP did not store sub-SCIP optimal solution\n");
    922 }
    923 else
    924 {
    925 SCIPdebugMsg(scip, "SCIP did not store sub-SCIP optimal solution\n");
    926 }
    927 }
    928 }
    929 else
    930 {
    931 SCIP_Bool feasible;
    932
    933 SCIP_CALL( createSolFromSubScipSol(scip, heur, &resultsol, SCIPgetSols(heurdata->subscip)[i], authorheur) );
    934
    935 heurdata->lastsol = resultsol;
    936 SCIP_CALL( SCIPcheckSol(scip, resultsol, FALSE, FALSE, TRUE, FALSE, TRUE, &feasible) );
    937 if( feasible )
    938 {
    939 if( heurdata->nlpverblevel >= 1 )
    940 {
    941 SCIPinfoMessage(scip, NULL, "SCIP solution from sub-SCIP root node is feasible\n");
    942 }
    943 else
    944 {
    945 SCIPdebugMsg(scip, "SCIP solution from sub-SCIP root node is feasible\n");
    946 }
    947 *result = SCIP_FOUNDSOL;
    948 break;
    949 }
    950 else
    951 {
    952 if( heurdata->nlpverblevel >= 1 )
    953 {
    954 SCIPinfoMessage(scip, NULL, "SCIP solution from sub-SCIP root node is not feasible\n");
    955 }
    956 else
    957 {
    958 SCIPdebugMsg(scip, "SCIP solution from sub-SCIP root node is not feasible\n");
    959 }
    960 }
    961 }
    962 }
    963
    964 /* if subscip is infeasible here, we signal this to the caller */
    965 if( SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_INFEASIBLE )
    966 {
    967 if( heurdata->nlpverblevel >= 1 )
    968 {
    969 SCIPinfoMessage(scip, NULL, "sub-SCIP detected infeasibility\n");
    970 }
    971 else
    972 {
    973 SCIPdebugMsg(scip, "sub-SCIP detected infeasibility\n");
    974 }
    975
    976 assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED);
    977 *result = SCIP_CUTOFF;
    978 return SCIP_OKAY;
    979 }
    980
    981 /* if we stopped for some other reason, or there is no NLP, we also stop */
    982 if( SCIPgetStage(heurdata->subscip) <= SCIP_STAGE_PRESOLVED || SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVED || !SCIPisNLPConstructed(heurdata->subscip) )
    983 return SCIP_OKAY;
    984
    985 /* in most cases, the status should be nodelimit
    986 * in some cases, if the sub-SCIP is very easy, it may report optimal, so we do not need invoke an NLP solver
    987 * if the presolve found the problem infeasible, then there is no use in solving an NLP
    988 * if the user interrupted or a timelimit was reached, then we should also stop here
    989 * unbounded is very unlikely to happen, in most cases, it should have been concluded in the main scip already
    990 */
    991 switch( SCIPgetStatus(heurdata->subscip) )
    992 {
    994 break; /* this is the status that is most likely happening */
    1000 /* these should not happen, but if one does, it's safe to return */
    1001 SCIPABORT(); /*lint -fallthrough*/
    1009 return SCIP_OKAY;
    1010 default:
    1011 SCIPerrorMessage("unexpected status of sub-SCIP: <%d>\n", SCIPgetStatus(heurdata->subscip));
    1012 return SCIP_ERROR;
    1013 } /*lint !e788*/
    1014 }
    1015 else
    1016 {
    1017 /* for continuous problem, createSubSCIP() should have put us into a state where we can invoke the NLP solver */
    1018 assert(SCIPisNLPConstructed(heurdata->subscip));
    1019 assert(SCIPgetStage(heurdata->subscip) == SCIP_STAGE_SOLVING);
    1020 assert(SCIPgetStatus(heurdata->subscip) == SCIP_STATUS_NODELIMIT);
    1021 }
    1022
    1023 /* set starting values (=refpoint, if not NULL; otherwise LP solution (or pseudo solution)) */
    1024 SCIP_CALL( SCIPallocBufferArray(scip, &startpoint, SCIPgetNNLPVars(heurdata->subscip)) );
    1025
    1026 if( heurdata->nlpverblevel >= 3 )
    1027 {
    1028 SCIPinfoMessage(scip, NULL, "set NLP starting point\n");
    1029 }
    1030
    1031 for( i = 0; i < SCIPgetNNLPVars(heurdata->subscip); ++i )
    1032 {
    1033 SCIP_Real scalar;
    1034 SCIP_Real constant;
    1035
    1036 subvar = SCIPgetNLPVars(heurdata->subscip)[i];
    1037
    1038 /* gets corresponding original variable */
    1039 scalar = 1.0;
    1040 constant = 0.0;
    1041 SCIP_CALL( SCIPvarGetOrigvarSum(&subvar, &scalar, &constant) );
    1042 if( subvar == NULL )
    1043 {
    1044 startpoint[i] = constant;
    1045
    1046 if( heurdata->nlpverblevel >= 3 && !SCIPisZero(heurdata->subscip, startpoint[i]) )
    1047 {
    1048 SCIPinfoMessage(scip, NULL, "%s = %e\n", SCIPvarGetName(SCIPgetNLPVars(heurdata->subscip)[i]), startpoint[i]);
    1049 }
    1050
    1051 continue;
    1052 }
    1053
    1054 assert(SCIPvarGetProbindex(subvar) >= 0);
    1055 assert(SCIPvarGetProbindex(subvar) < heurdata->nsubvars);
    1056 var = heurdata->var_subscip2scip[SCIPvarGetProbindex(subvar)];
    1057 if( var == NULL || REALABS(SCIPgetSolVal(scip, refpoint, var)) > 1.0e+12 )
    1058 startpoint[i] = MIN(MAX(0.0, SCIPvarGetLbGlobal(subvar)), SCIPvarGetUbGlobal(subvar)); /*lint !e666*/
    1059 else
    1060 /* scalar*subvar+constant corresponds to nlpvar[i], so nlpvar[i] gets value scalar*varval+constant */
    1061 startpoint[i] = scalar * SCIPgetSolVal(scip, refpoint, var) + constant;
    1062
    1063 if( heurdata->nlpverblevel >= 3 && !SCIPisZero(heurdata->subscip, startpoint[i]) )
    1064 {
    1065 SCIPinfoMessage(scip, NULL, "%s = %e\n", SCIPvarGetName(SCIPgetNLPVars(heurdata->subscip)[i]), startpoint[i]);
    1066 }
    1067 }
    1068 SCIP_CALL( SCIPsetNLPInitialGuess(heurdata->subscip, startpoint) );
    1069
    1070 SCIPfreeBufferArray(scip, &startpoint);
    1071
    1072 *result = SCIP_DIDNOTFIND;
    1073
    1074 /* if we had many (fraction > expectinfeas) infeasible NLPs, then tell NLP solver to expect an infeasible problem */
    1075 expectinfeas = FALSE; /* cppcheck-suppress unreadVariable */
    1076 if( heurdata->expectinfeas == 0.0 ) /* to keep original behavior on default settings */
    1077 expectinfeas = TRUE; /* cppcheck-suppress unreadVariable */
    1078 else if( heurdata->nnlpsolvesokay > heurdata->ninitsolves && heurdata->nnlpsolvesinfeas > heurdata->expectinfeas * heurdata->nnlpsolvesokay )
    1079 expectinfeas = TRUE; /* cppcheck-suppress unreadVariable */
    1080
    1081 /* let the NLP solver do its magic */
    1082 SCIPdebugMsg(scip, "start NLP solve with iteration limit %d\n", calcIterLimit(scip, heurdata));
    1083 SCIP_CALL( SCIPsolveNLP(heurdata->subscip,
    1084 .iterlimit = calcIterLimit(scip, heurdata),
    1085 .opttol = heurdata->opttol,
    1086 .feastol = heurdata->feastol,
    1087 .verblevel = (unsigned short)heurdata->nlpverblevel,
    1088 .expectinfeas = expectinfeas
    1089 ) ); /*lint !e666*/
    1090
    1091 SCIPdebugMsg(scip, "NLP solver returned with termination status %d and solution status %d, objective value is %g\n",
    1092 SCIPgetNLPTermstat(heurdata->subscip), SCIPgetNLPSolstat(heurdata->subscip), SCIPgetNLPObjval(heurdata->subscip));
    1093
    1094 /* add NLP solve statistics from subscip to main SCIP, so they show up in final statistics
    1095 * for continuous problems, we also ask to reset statistics, since we do not retransform subSCIP in the next run (which would reset all stats)
    1096 * (merging statistics once in exitsol is too late, since they may be printed before)
    1097 */
    1098 SCIPmergeNLPIStatistics(heurdata->subscip, scip, heurdata->continuous);
    1099
    1100 if( SCIPgetNLPTermstat(heurdata->subscip) >= SCIP_NLPTERMSTAT_OUTOFMEMORY )
    1101 {
    1102 /* oops, something did not go well at all */
    1103 if( heurdata->nlpverblevel >= 1 )
    1104 {
    1105 SCIPinfoMessage(scip, NULL, "NLP solver in subNLP heuristic for problem <%s> returned with bad termination status %d.\n",
    1106 SCIPgetProbName(scip), SCIPgetNLPTermstat(heurdata->subscip));
    1107 }
    1108
    1109 ++(heurdata->nseriousnlpierror);
    1111 "NLP solver in subNLP heuristic for problem <%s> returned with bad termination status %d. This was the %d%s successive time.\n",
    1112 SCIPgetProbName(scip), SCIPgetNLPTermstat(heurdata->subscip), heurdata->nseriousnlpierror,
    1113 heurdata->nseriousnlpierror == 1 ? "st" : heurdata->nseriousnlpierror == 2 ? "nd" : heurdata->nseriousnlpierror == 3 ? "rd" : "th");
    1114 if( heurdata->nseriousnlpierror >= 5 )
    1115 {
    1116 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Will not run subNLP heuristic again for this run.\n");
    1117 SCIP_CALL( freeSubSCIP(scip, heurdata) );
    1118 }
    1119 return SCIP_OKAY;
    1120 }
    1121 heurdata->nseriousnlpierror = 0;
    1122
    1123 SCIP_CALL( SCIPgetNLPStatistics(heurdata->subscip, &nlpstatistics) );
    1124
    1125 SCIPdebugMsg(scip, "NLP solver used %d iterations and %g seconds; violation cons %g, bounds %g\n",
    1126 nlpstatistics.niterations, nlpstatistics.totaltime, nlpstatistics.consviol, nlpstatistics.boundviol);
    1127
    1128 heurdata->iterused += nlpstatistics.niterations;
    1129 ++heurdata->nnlpsolves;
    1130 if( SCIPgetNLPTermstat(heurdata->subscip) == SCIP_NLPTERMSTAT_OKAY )
    1131 {
    1132 ++heurdata->nnlpsolvesokay;
    1133 heurdata->iterusedokay += nlpstatistics.niterations;
    1134
    1135 if( (SCIPgetNLPSolstat(heurdata->subscip) == SCIP_NLPSOLSTAT_GLOBINFEASIBLE) || (SCIPgetNLPSolstat(heurdata->subscip) == SCIP_NLPSOLSTAT_LOCINFEASIBLE) )
    1136 ++heurdata->nnlpsolvesinfeas;
    1137 }
    1138 else if( SCIPgetNLPTermstat(heurdata->subscip) == SCIP_NLPTERMSTAT_ITERLIMIT )
    1139 {
    1140 ++heurdata->nnlpsolvesiterlim;
    1141 heurdata->iterusediterlim = MAX(heurdata->iterusediterlim, nlpstatistics.niterations);
    1142 }
    1143
    1144 if( SCIPgetNLPSolstat(heurdata->subscip) > SCIP_NLPSOLSTAT_FEASIBLE )
    1145 return SCIP_OKAY;
    1146
    1147 /* create SCIP solution, check whether feasible, and try adding to SCIP (if resultsol==NULL) */
    1148 SCIP_CALL( processNLPSol(scip, heur, authorheur, result, resultsol) );
    1149
    1150 if( *result == SCIP_FOUNDSOL || !SCIPisLE(scip, SCIPgetNLPObjval(heurdata->subscip), SCIPgetUpperbound(scip)) )
    1151 return SCIP_OKAY;
    1152
    1153 /* if solution was not added to SCIP, then either
    1154 * - the objective function value was not good enough,
    1155 * - the NLP was missing some constraints of the original CIP, or
    1156 * - the solution is feasible for the presolved CIP, but slightly infeasible for the unpresolved problem
    1157 *
    1158 * The first case we can check easily (see if() above).
    1159 * For the last case, we try whether tightening the feasibility tolerance for the NLP solve may help.
    1160 * If that doesn't help, we guess that we are in the second case and will not try a tighter feastol anymore.
    1161 */
    1162
    1163 /* if we tried with a tighter feastol before, but solution was still not accepted, then don't try again */
    1164 if( heurdata->tighterfeastolfailed )
    1165 return SCIP_OKAY;
    1166
    1167 /* if resolve with tighter feastol is disabled, then don't do anything */
    1168 if( heurdata->feastolfactor == 1.0 )
    1169 return SCIP_OKAY;
    1170
    1171 /* if we have already used a tighter feastol, then give up */
    1172 if( heurdata->feastol < SCIPfeastol(scip) )
    1173 return SCIP_OKAY;
    1174
    1175 /* if original CIP is continuous, then we have not done any presolve, so it shouldn't have caused problems */
    1176 if( heurdata->continuous )
    1177 return SCIP_OKAY;
    1178
    1179 /* if solution is NLP-feasible for a tightened tolerance already, then there is no use in resolving with that tighter feastol */
    1180 if( MAX(nlpstatistics.consviol, nlpstatistics.boundviol) <= heurdata->feastolfactor * heurdata->feastol )
    1181 return SCIP_OKAY;
    1182
    1183 /* let the NLP solver redo its magic
    1184 * as iterlimit, we use the number of iterations it took for the first solve, or itermin
    1185 */
    1186 SCIPdebugMsg(scip, "start NLP solve with iteration limit %d\n", calcIterLimit(scip, heurdata));
    1187 SCIP_CALL( SCIPsolveNLP(heurdata->subscip,
    1188 .iterlimit = MAX(heurdata->itermin, nlpstatistics.niterations),
    1189 .opttol = heurdata->opttol,
    1190 .feastol = heurdata->feastolfactor * heurdata->feastol,
    1191 .verblevel = (unsigned short)heurdata->nlpverblevel,
    1192 .warmstart = TRUE
    1193 ) ); /*lint !e666*/
    1194
    1195 SCIPdebugMsg(scip, "NLP solver returned with termination status %d and solution status %d, objective value is %g\n",
    1196 SCIPgetNLPTermstat(heurdata->subscip), SCIPgetNLPSolstat(heurdata->subscip), SCIPgetNLPObjval(heurdata->subscip));
    1197
    1198 /* add NLP solve statistics from subscip to main SCIP again, so they show up in final statistics */
    1199 SCIPmergeNLPIStatistics(heurdata->subscip, scip, heurdata->continuous);
    1200
    1201 /* some serious problem: just pretend it didn't happen */
    1202 if( SCIPgetNLPTermstat(heurdata->subscip) >= SCIP_NLPTERMSTAT_OUTOFMEMORY )
    1203 return SCIP_OKAY;
    1204
    1205 SCIP_CALL( SCIPgetNLPStatistics(heurdata->subscip, &nlpstatistics) );
    1206 SCIPdebugMsg(scip, "NLP solver used %d iterations and %g seconds; violation cons %g, bounds %g\n",
    1207 nlpstatistics.niterations, nlpstatistics.totaltime, nlpstatistics.consviol, nlpstatistics.boundviol);
    1208
    1209 /* we account only the extra iterations for this unusual NLP solve, but don't add anything else to our statistics (nnlpsolved, etc) */
    1210 heurdata->iterused += nlpstatistics.niterations;
    1211
    1212 /* if failed to get a feasible NLP solution now, then nothing to do */
    1213 if( SCIPgetNLPSolstat(heurdata->subscip) > SCIP_NLPSOLSTAT_FEASIBLE )
    1214 return SCIP_OKAY;
    1215
    1216 SCIP_CALL( processNLPSol(scip, heur, authorheur, result, resultsol) );
    1217
    1218 /* if successful, then use tighter feastol for all NLP solves from now on
    1219 * if still not accepted, then don't try this again
    1220 * (maybe the NLP is incomplete; we could give up on running this heur completely, but for now let the successrate factor in heurExec take care of running it less often)
    1221 */
    1222 if( *result == SCIP_FOUNDSOL )
    1223 heurdata->feastol *= heurdata->feastolfactor;
    1224 else
    1225 heurdata->tighterfeastolfailed = TRUE;
    1226
    1227 return SCIP_OKAY;
    1228}
    1229
    1230
    1231/** adds a set covering or bound disjunction constraint to the original problem */
    1232static
    1234 SCIP* scip, /**< SCIP data structure */
    1235 SCIP_HEURDATA* heurdata /**< heuristic data */
    1236 )
    1237{
    1238 SCIP_VAR** subvars;
    1239 int nsubvars;
    1240 int nsubbinvars;
    1241 int nsubintvars;
    1242 SCIP_VAR* var;
    1243 SCIP_VAR* subvar;
    1244 SCIP_CONS* cons;
    1245 SCIP_VAR** consvars;
    1246 int nconsvars;
    1247 char name[SCIP_MAXSTRLEN];
    1248 int i;
    1249 SCIP_Real fixval;
    1250
    1251 assert(scip != NULL);
    1252
    1253 SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
    1254 assert(nsubvars == heurdata->nsubvars);
    1255
    1256 if( nsubbinvars == 0 && nsubintvars == 0 )
    1257 {
    1258 /* If we did not fix any discrete variables but found the "sub"CIP infeasible, then also the CIP is infeasible. */
    1259 SCIPdebugMsg(scip, "heur_subnlp found subCIP infeasible after fixing no variables, something is strange here...\n");
    1260 return SCIP_OKAY;
    1261 }
    1262
    1263 /* initialize */
    1264 cons = NULL;
    1265 consvars = NULL;
    1266
    1267 /* create constraint name */
    1268 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "subnlp_cutoff");
    1269
    1270 /* if all discrete variables in the CIP are binary, then we create a set covering constraint
    1271 * sum_{x_i fixed at 0} x_i + sum_{x_i fixed at 1} ~x_i >= 1
    1272 */
    1273 if( nsubintvars == 0 )
    1274 {
    1275 /* allocate memory for constraint variables */
    1276 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsubbinvars) );
    1277
    1278 /* get fixations of discrete variables
    1279 * to be sure, we take the values that were put into the subCIP before
    1280 */
    1281 nconsvars = 0;
    1282 for( i = nsubbinvars - 1; i >= 0; --i )
    1283 {
    1284 subvar = subvars[i];
    1285 assert(SCIPvarGetProbindex(subvar) == i);
    1286
    1287 var = heurdata->var_subscip2scip[i];
    1288 assert(var != NULL || SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar))); /* otherwise we should have exited in the variable fixation loop */
    1289 if( var == NULL )
    1290 continue;
    1291
    1292 fixval = SCIPvarGetLbGlobal(subvar);
    1293 assert(fixval == SCIPvarGetUbGlobal(subvar)); /* variable should be fixed in sub-SCIP */ /*lint !e777*/
    1294 assert(fixval == 0.0 || fixval == 1.0); /* we have rounded values before fixing */
    1295
    1296 if( fixval == 0.0 )
    1297 {
    1298 /* variable fixed at lower bound */
    1299 consvars[nconsvars] = var;
    1300 }
    1301 else
    1302 {
    1303 SCIP_CALL( SCIPgetNegatedVar(scip, var, &consvars[nconsvars]) );
    1304 }
    1305
    1306 ++nconsvars;
    1307 }
    1308
    1309 /* create conflict constraint
    1310 * In undercover, ConsLogicor is used, since then the inequality is not added to the LP.
    1311 * However, I may want to use Setcover to avoid that the same fixing is computed by some LP based heuristic again.
    1312 */
    1313 SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, name, nconsvars, consvars,
    1315 }
    1316 else
    1317 {
    1318 /* if there are also integer variable, then create a bound disjunction constraint
    1319 * x_1 >= fixval_1 + 1 || x_1 <= fixval_1 - 1 || x_2 >= fixval_2 + 1 || x_2 <= fixval_2 - 1 || ...
    1320 */
    1321 SCIP_BOUNDTYPE* boundtypes;
    1322 SCIP_Real* bounds;
    1323
    1324 /* allocate memory for constraint variables, boundtypes, and bounds
    1325 * (there should be at most two literals for each integer variable)
    1326 */
    1327 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsubbinvars + 2*nsubintvars) );
    1328 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nsubbinvars + 2*nsubintvars) );
    1329 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nsubbinvars + 2*nsubintvars) );
    1330
    1331 /* get fixations of discrete variables
    1332 * to be sure, we take the values that were put into the subCIP before
    1333 */
    1334 nconsvars = 0;
    1335 for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
    1336 {
    1337 subvar = subvars[i];
    1338 assert(SCIPvarGetProbindex(subvar) == i);
    1339
    1340 var = heurdata->var_subscip2scip[i];
    1341 assert(var != NULL || SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetUbGlobal(subvar))); /* otherwise we should have exited in the variable fixation loop */
    1342
    1343 if( var == NULL )
    1344 continue;
    1345
    1346 fixval = SCIPvarGetLbGlobal(subvar);
    1347 assert(fixval == SCIPvarGetUbGlobal(subvar)); /* variable should be fixed in sub-SCIP */ /*lint !e777*/
    1348 assert(SCIPceil(scip, fixval - 0.5) == fixval); /* we have rounded values before fixing */ /*lint !e777*/
    1350 || SCIPvarGetLbGlobal(var) == fixval || SCIPvarGetUbGlobal(var) == fixval); /* for binaries, the fixval should be either 0.0 or 1.0 */ /*lint !e777*/
    1351
    1352 if( SCIPvarGetLbGlobal(var) < fixval )
    1353 {
    1354 assert(nconsvars < nsubbinvars + 2*nsubintvars);
    1355
    1356 /* literal x_i <= fixval-1 */
    1357 boundtypes[nconsvars] = SCIP_BOUNDTYPE_UPPER;
    1358 bounds[nconsvars] = fixval - 1.0;
    1359 consvars[nconsvars] = var;
    1360 ++nconsvars;
    1361 }
    1362
    1363 if( SCIPvarGetUbGlobal(var) > fixval )
    1364 {
    1365 assert(nconsvars < nsubbinvars + 2*nsubintvars);
    1366
    1367 /* literal x_i >= fixval+1 */
    1368 boundtypes[nconsvars] = SCIP_BOUNDTYPE_LOWER;
    1369 bounds[nconsvars] = fixval + 1.0;
    1370 consvars[nconsvars] = var;
    1371 ++nconsvars;
    1372 }
    1373 }
    1374
    1375 /* create conflict constraint */
    1376 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, name, nconsvars, consvars, boundtypes, bounds,
    1378
    1379 SCIPfreeBufferArray(scip, &bounds);
    1380 SCIPfreeBufferArray(scip, &boundtypes);
    1381 SCIPfreeBufferArray(scip, &consvars);
    1382 }
    1383
    1384 /* add and release constraint if created successfully */
    1385 if( cons != NULL )
    1386 {
    1387 SCIPdebugMsg(scip, "adding constraint to forbid fixation in main problem\n");
    1388 /* SCIPdebugPrintCons(scip, cons, NULL); */
    1389 SCIP_CALL( SCIPaddCons(scip, cons) );
    1390 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    1391 }
    1392
    1393 /* free memory */
    1394 SCIPfreeBufferArrayNull(scip, &consvars);
    1395
    1396 return SCIP_OKAY;
    1397}
    1398
    1399
    1400/*
    1401 * Callback methods of primal heuristic
    1402 */
    1403
    1404/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    1405static
    1406SCIP_DECL_HEURCOPY(heurCopySubNlp)
    1407{ /*lint --e{715}*/
    1408 assert(scip != NULL);
    1409 assert(heur != NULL);
    1410 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1411
    1412 /* call inclusion method of primal heuristic */
    1414
    1415 return SCIP_OKAY;
    1416}
    1417
    1418/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    1419static
    1420SCIP_DECL_HEURFREE(heurFreeSubNlp)
    1421{
    1422 SCIP_HEURDATA* heurdata;
    1423 assert(scip != NULL);
    1424 assert(heur != NULL);
    1425
    1426 heurdata = SCIPheurGetData(heur);
    1427 assert(heurdata != NULL);
    1428 assert(heurdata->subscip == NULL);
    1429 assert(heurdata->var_subscip2scip == NULL);
    1430 assert(heurdata->var_scip2subscip == NULL);
    1431 assert(heurdata->startcand == NULL);
    1432
    1433 SCIPfreeBlockMemory(scip, &heurdata);
    1434
    1435 return SCIP_OKAY;
    1436}
    1437
    1438/** initialization method of primal heuristic (called after problem was transformed) */
    1439static
    1440SCIP_DECL_HEURINIT(heurInitSubNlp)
    1441{ /*lint --e{715}*/
    1442 SCIP_HEURDATA* heurdata;
    1443
    1444 assert(scip != NULL);
    1445 assert(heur != NULL);
    1446
    1447 heurdata = SCIPheurGetData(heur);
    1448 assert(heurdata != NULL);
    1449 assert(heurdata->subscip == NULL);
    1450
    1451 /* reset or initialize some flags and counters */
    1452 heurdata->feastol = SCIPfeastol(scip);
    1453 heurdata->tighterfeastolfailed = FALSE;
    1454 heurdata->triedsetupsubscip = FALSE;
    1455 heurdata->nseriousnlpierror = 0;
    1456 heurdata->iterused = 0;
    1457 heurdata->iterusedokay = 0;
    1458 heurdata->iterusediterlim = 0;
    1459 heurdata->nnlpsolves = 0;
    1460 heurdata->nnlpsolvesokay = 0;
    1461 heurdata->nnlpsolvesiterlim = 0;
    1462 heurdata->nnlpsolvesinfeas = 0;
    1463
    1464 return SCIP_OKAY;
    1465}
    1466
    1467/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    1468static
    1469SCIP_DECL_HEURINITSOL(heurInitsolSubNlp)
    1470{
    1471 SCIP_HEURDATA* heurdata;
    1472
    1473 assert(scip != NULL);
    1474 assert(heur != NULL);
    1475
    1476 /* get heuristic data */
    1477 heurdata = SCIPheurGetData(heur);
    1478 assert(heurdata != NULL);
    1479
    1480 /* store subnlp timing */
    1481 heurdata->inittiming = SCIPheurGetTimingmask(heur);
    1482
    1483 /* disable subnlp heuristic */
    1486 /* if the heuristic is called at the root node, we want to be called directly after the initial root LP solve */
    1487 else if( SCIPheurGetFreqofs(heur) == 0 )
    1488 SCIPheurSetTimingmask(heur, heurdata->inittiming | SCIP_HEURTIMING_DURINGLPLOOP);
    1489
    1490 return SCIP_OKAY;
    1491}
    1492
    1493/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
    1494static
    1495SCIP_DECL_HEUREXITSOL(heurExitsolSubNlp)
    1496{
    1497 SCIP_HEURDATA* heurdata;
    1498
    1499 assert(scip != NULL);
    1500 assert(heur != NULL);
    1501
    1502 /* get heuristic data */
    1503 heurdata = SCIPheurGetData(heur);
    1504 assert(heurdata != NULL);
    1505
    1506 if( heurdata->subscip != NULL )
    1507 {
    1508 SCIP_CALL( freeSubSCIP(scip, heurdata) );
    1509 heurdata->triedsetupsubscip = FALSE;
    1510 }
    1511
    1512 /* free start candidate */
    1513 if( heurdata->startcand != NULL )
    1514 {
    1515 SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
    1516 }
    1517
    1518 /* reset subnlp timing */
    1519 SCIPheurSetTimingmask(heur, heurdata->inittiming);
    1520
    1521 return SCIP_OKAY;
    1522}
    1523
    1524
    1525/** execution method of primal heuristic */
    1526static
    1527SCIP_DECL_HEUREXEC(heurExecSubNlp)
    1528{ /*lint --e{666,715}*/
    1529 SCIP_HEURDATA* heurdata;
    1530 SCIP_Bool runheur;
    1531 SCIP_Real itercontingent;
    1532
    1533 assert(scip != NULL);
    1534 assert(heur != NULL);
    1535 assert(SCIPisNLPConstructed(scip));
    1536 assert(SCIPgetNNlpis(scip) >= 1);
    1537
    1538 /* obviously, we did not do anything yet */
    1539 *result = SCIP_DIDNOTRUN;
    1540
    1541 /* before we run the heuristic for the first time, check whether we want to run the heuristic at all */
    1542 if( SCIPheurGetNCalls(heur) == 0 )
    1543 {
    1545 if( !runheur )
    1546 {
    1548 return SCIP_OKAY;
    1549 }
    1550 }
    1551
    1552 /* get heuristic's data */
    1553 heurdata = SCIPheurGetData(heur);
    1554 assert(heurdata != NULL);
    1555
    1556 /* if triedsetupsubscip and keepcopy and subscip == NULL, then we tried to setup a subSCIP before, but failed due to some serious error
    1557 * thus, we should do not need to try again
    1558 *
    1559 * otherwise, we continue and let SCIPapplyHeurSubNlp try to create subscip
    1560 */
    1561 if( heurdata->subscip == NULL && heurdata->keepcopy && heurdata->triedsetupsubscip )
    1562 return SCIP_OKAY;
    1563
    1564 if( heurdata->startcand == NULL )
    1565 {
    1566 /* if no start candidate is given, we consider the LP solution of the current node */
    1567
    1568 /* however, if the node was already detected to be infeasible, then there is no point to look at its LP solution */
    1569 if( nodeinfeasible )
    1570 return SCIP_OKAY;
    1571
    1572 /* at least if we are not called the first time, we call the heuristic only if an optimal LP solution is available
    1573 * if we are called the first time and the LP is unbounded, then we are quite desperate and still give the NLP a try
    1574 */
    1576 {
    1578 {
    1579 *result = SCIP_DELAYED;
    1580 SCIPdebugMsg(scip, "NLP heuristic delayed because no start candidate given and no LP solution available; LP status = %d\n", SCIPgetLPSolstat(scip));
    1581 return SCIP_OKAY;
    1582 }
    1583 else
    1584 {
    1585 SCIPdebugMsg(scip, "LP is unbounded in root node, so we are quite desperate; run NLP heuristic and pray\n");
    1586 }
    1587 }
    1588 else if( SCIPgetNLPBranchCands(scip) > 0 )
    1589 {
    1590 /* only call heuristic, if there are no fractional variables */
    1591 *result = SCIP_DELAYED;
    1592 SCIPdebugMsg(scip, "NLP heuristic delayed because no start candidate given and current LP solution is fractional\n");
    1593 return SCIP_OKAY;
    1594 }
    1596 {
    1597 /* only call heuristic, if there is still room for improvement in the current node */
    1598 SCIPdebugMsg(scip, "NLP heuristic delayed because lower and upper bound coincide in current node\n");
    1599 return SCIP_OKAY;
    1600 }
    1601 SCIPdebugMsg(scip, "using current LP solution as startcand\n");
    1602 }
    1603 else
    1604 {
    1605 SCIPdebugMsg(scip, "have startcand from heur %s\n", SCIPsolGetHeur(heurdata->startcand) ? SCIPheurGetName(SCIPsolGetHeur(heurdata->startcand)) : "NULL");
    1606 }
    1607
    1608 /* check if enough nodes have been processed so that we want to run the heuristic again */
    1609
    1610 /* compute the contingent on number of iterations that the NLP solver is allowed to use
    1611 * we make it depending on the current number of processed nodes
    1612 */
    1613 itercontingent = heurdata->nodesfactor * (SCIPgetNNodes(scip) + heurdata->nodesoffset);
    1614 /* weight by previous success of heuristic if we have been running already
    1615 * require at least ninitsolves many runs that didn't run into the NLP iterlimit
    1616 * (so if we are still in the phase of finding a good iterlimit, do not consider success rate so far)
    1617 */
    1618 if( heurdata->successrateexp > 0.0 && SCIPheurGetNCalls(heur) - heurdata->nnlpsolvesiterlim >= heurdata->ninitsolves )
    1619 itercontingent *= pow((SCIPheurGetNSolsFound(heur) + 1.0) / (SCIPheurGetNCalls(heur) + 1.0), heurdata->successrateexp);
    1620 /* subtract the number of iterations used for all NLP solves so far */
    1621 itercontingent -= heurdata->iterused;
    1622
    1623 /* check whether the itercontingent is sufficient for the iteration limit we would use */
    1624 if( itercontingent < calcIterLimit(scip, heurdata) )
    1625 {
    1626 /* not enough iterations left to start NLP solver */
    1627 SCIPdebugMsg(scip, "skip NLP heuristic; contingent=%f; iterlimit=%d; success ratio=%g\n",
    1628 itercontingent, calcIterLimit(scip, heurdata), pow((SCIPheurGetNSolsFound(heur) + 1.0) / (SCIPheurGetNCalls(heur) + 1.0), heurdata->successrateexp));
    1629 return SCIP_OKAY;
    1630 }
    1631
    1632 /* so far we have not found any solution, but now we are willing to search for one */
    1633 *result = SCIP_DIDNOTFIND;
    1634
    1635 if( heurdata->nlpverblevel >= 1 )
    1636 {
    1637 SCIPinfoMessage(scip, NULL, "calling subnlp heuristic\n");
    1638 }
    1639
    1640 SCIP_CALL( SCIPapplyHeurSubNlp(scip, heur, result, heurdata->startcand, NULL) );
    1641
    1642 /* SCIP does not like cutoff as return, so we say didnotfind, since we did not find a solution */
    1643 if( *result == SCIP_CUTOFF )
    1644 *result = SCIP_DIDNOTFIND;
    1645
    1646 /* forget startcand */
    1647 if( heurdata->startcand != NULL )
    1648 {
    1649 SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
    1650 }
    1651
    1652 /* reset timing, if it was changed temporary (at the root node) */
    1653 if( heurtiming != HEUR_TIMING )
    1655
    1656 return SCIP_OKAY;
    1657}
    1658
    1659
    1660/*
    1661 * primal heuristic specific interface methods
    1662 */
    1663
    1664/** creates the NLP local search primal heuristic and includes it in SCIP */
    1666 SCIP* scip /**< SCIP data structure */
    1667 )
    1668{
    1669 SCIP_HEURDATA* heurdata;
    1670 SCIP_HEUR* heur;
    1671
    1672 /* create Nlp primal heuristic data */
    1673 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1674 BMSclearMemory(heurdata);
    1675 heurdata->inittiming = HEUR_TIMING;
    1676
    1677 /* include variable event handler */
    1678 heurdata->eventhdlr = NULL;
    1679 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &heurdata->eventhdlr, HEUR_NAME, "propagates a global bound change to the sub-SCIP",
    1680 processVarEvent, NULL) );
    1681 assert(heurdata->eventhdlr != NULL);
    1682
    1683 /* include primal heuristic */
    1686 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecSubNlp, heurdata) );
    1687
    1688 assert(heur != NULL);
    1689
    1690 /* set non-NULL pointers to callback methods */
    1691 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopySubNlp) );
    1692 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeSubNlp) );
    1693 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitSubNlp) );
    1694 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolSubNlp) );
    1695 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolSubNlp) );
    1696
    1697 /* add Nlp primal heuristic parameters */
    1698 SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/nlpverblevel",
    1699 "verbosity level of NLP solver",
    1700 &heurdata->nlpverblevel, FALSE, 0, 0, USHRT_MAX, NULL, NULL) );
    1701
    1702 SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/nodesoffset",
    1703 "number of nodes added to the current number of nodes when computing itercontingent (higher value runs heuristic more often in early search)",
    1704 &heurdata->nodesoffset, FALSE, 1600, 0, INT_MAX, NULL, NULL) );
    1705
    1706 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesfactor",
    1707 "factor on number of nodes in SCIP (plus nodesoffset) to compute itercontingent (higher value runs heuristics more frequently)",
    1708 &heurdata->nodesfactor, FALSE, 0.3, 0.0, SCIPinfinity(scip), NULL, NULL) );
    1709
    1710 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/successrateexp",
    1711 "exponent for power of success rate to be multiplied with itercontingent (lower value decreases impact of success rate)",
    1712 &heurdata->successrateexp, FALSE, 1.0, 0.0, DBL_MAX, NULL, NULL) );
    1713
    1714 SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/iterinit",
    1715 "number of iterations used for initial NLP solves",
    1716 &heurdata->iterinit, FALSE, 300, 0, INT_MAX, NULL, NULL) );
    1717
    1718 SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/ninitsolves",
    1719 "number of successful NLP solves until switching to iterlimit guess and using success rate",
    1720 &heurdata->ninitsolves, FALSE, 2, 0, INT_MAX, NULL, NULL) );
    1721
    1722 SCIP_CALL( SCIPaddIntParam (scip, "heuristics/" HEUR_NAME "/itermin",
    1723 "minimal number of iterations for NLP solves",
    1724 &heurdata->itermin, FALSE, 20, 0, INT_MAX, NULL, NULL) );
    1725
    1726 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/opttol",
    1727 "absolute optimality tolerance to use for NLP solves",
    1728 &heurdata->opttol, TRUE, SCIPdualfeastol(scip), 0.0, 1.0, NULL, NULL) );
    1729
    1730 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/feastolfactor",
    1731 "factor on SCIP feasibility tolerance for NLP solves if resolving when NLP solution not feasible in CIP",
    1732 &heurdata->feastolfactor, FALSE, 0.1, 0.0, 1.0, NULL, NULL) );
    1733
    1734 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxpresolverounds",
    1735 "limit on number of presolve rounds in sub-SCIP (-1 for unlimited, 0 for no presolve)",
    1736 &heurdata->maxpresolverounds, FALSE, -1, -1, INT_MAX, NULL, NULL) );
    1737
    1738 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/presolveemphasis",
    1739 "presolve emphasis in sub-SCIP (0: default, 1: aggressive, 2: fast, 3: off)",
    1740 &heurdata->presolveemphasis, FALSE, (int)SCIP_PARAMSETTING_FAST, (int)SCIP_PARAMSETTING_DEFAULT, (int)SCIP_PARAMSETTING_OFF, NULL, NULL) );
    1741
    1742 SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/setcutoff",
    1743 "whether to set cutoff in sub-SCIP to current primal bound",
    1744 &heurdata->setcutoff, FALSE, TRUE, NULL, NULL) );
    1745
    1746 SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/forbidfixings",
    1747 "whether to add constraints that forbid specific fixings that turned out to be infeasible",
    1748 &heurdata->forbidfixings, FALSE, FALSE, NULL, NULL) );
    1749
    1750 SCIP_CALL( SCIPaddBoolParam (scip, "heuristics/" HEUR_NAME "/keepcopy",
    1751 "whether to keep SCIP copy or to create new copy each time heuristic is applied",
    1752 &heurdata->keepcopy, TRUE, TRUE, NULL, NULL) );
    1753
    1754 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/expectinfeas",
    1755 "percentage of NLP solves with infeasible status required to tell NLP solver to expect an infeasible NLP",
    1756 &heurdata->expectinfeas, FALSE, 0.0, 0.0, 1.0, NULL, NULL) );
    1757
    1758 return SCIP_OKAY;
    1759}
    1760
    1761/** main procedure of the subNLP heuristic */
    1763 SCIP* scip, /**< original SCIP data structure */
    1764 SCIP_HEUR* heur, /**< heuristic data structure */
    1765 SCIP_RESULT* result, /**< pointer to store result of: did not run, solution found, no solution found, or fixing is infeasible (cutoff) */
    1766 SCIP_SOL* refpoint, /**< point to take fixation of discrete variables from, and startpoint for NLP solver; if NULL, then LP solution is used */
    1767 SCIP_SOL* resultsol /**< a solution where to store found solution values, if any, or NULL if to try adding to SCIP */
    1768 )
    1769{
    1770 SCIP_HEURDATA* heurdata;
    1771 SCIP_VAR* var;
    1772 SCIP_VAR* subvar;
    1773 int i;
    1774 SCIP_Real cutoff = SCIPinfinity(scip);
    1775
    1776 assert(scip != NULL);
    1777 assert(heur != NULL);
    1778
    1779 /* get heuristic's data */
    1780 heurdata = SCIPheurGetData(heur);
    1781 assert(heurdata != NULL);
    1782
    1783 /* try to setup NLP if not tried before */
    1784 if( heurdata->subscip == NULL && !heurdata->triedsetupsubscip )
    1785 {
    1786 SCIP_CALL( createSubSCIP(scip, heurdata) );
    1787 }
    1788
    1789 *result = SCIP_DIDNOTRUN;
    1790
    1791 /* if subSCIP could not be created, then do not run */
    1792 if( heurdata->subscip == NULL )
    1793 return SCIP_OKAY;
    1794
    1795 assert(heurdata->nsubvars > 0);
    1796 assert(heurdata->var_subscip2scip != NULL);
    1797
    1798 /* fix discrete variables in sub-SCIP */
    1799 if( !heurdata->continuous )
    1800 {
    1801 SCIP_Real fixval;
    1802 SCIP_VAR** subvars;
    1803 int nsubvars;
    1804 int nsubbinvars;
    1805 int nsubintvars;
    1806 SCIP_Bool infeas;
    1807 SCIP_Bool tightened;
    1808
    1809 /* transform sub-SCIP, so variable fixing are easily undone by free-transform */
    1810 assert(!SCIPisTransformed(heurdata->subscip));
    1811 SCIP_CALL( SCIPtransformProb(heurdata->subscip) );
    1812
    1813 SCIP_CALL( SCIPgetOrigVarsData(heurdata->subscip, &subvars, &nsubvars, &nsubbinvars, &nsubintvars, NULL, NULL) );
    1814 assert(nsubvars == heurdata->nsubvars);
    1815
    1816 /* fix discrete variables to values in startpoint */
    1817 for( i = nsubbinvars + nsubintvars - 1; i >= 0; --i )
    1818 {
    1819 subvar = subvars[i];
    1820 assert(SCIPvarGetProbindex(subvar) == i);
    1821
    1822 var = heurdata->var_subscip2scip[i];
    1823 assert(var != NULL);
    1824
    1825 /* at this point, variables in subscip and in our scip should have same bounds */
    1826 assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(subvar), SCIPvarGetLbGlobal(var)));
    1827 assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(subvar), SCIPvarGetUbGlobal(var)));
    1828
    1829 fixval = SCIPgetSolVal(scip, refpoint, var);
    1830
    1831 /* only run heuristic on integer feasible points (unless we are on an unbounded LP) */
    1832 if( !SCIPisFeasIntegral(scip, fixval) )
    1833 {
    1834 if( refpoint != NULL || SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
    1835 {
    1836 SCIPdebugMsg(scip, "skip NLP heuristic because start candidate not integer feasible: var <%s> has value %g\n", SCIPvarGetName(var), fixval);
    1837 goto CLEANUP;
    1838 }
    1839 }
    1840 /* if we do not really have a startpoint, then we should take care that we do not fix variables to very large values
    1841 * thus, we set to 0.0 here and project on bounds below
    1842 */
    1843 if( REALABS(fixval) > 1E+10 && refpoint == NULL && SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
    1844 fixval = 0.0;
    1845
    1846 /* fixing variables to infinity causes problems, we should not have been passed such a solution as refpoint */
    1847 assert(!SCIPisInfinity(scip, REALABS(fixval)));
    1848
    1849 /* round fractional variables to the nearest integer */
    1850 fixval = SCIPround(scip, fixval);
    1851
    1852 /* adjust value to the global bounds of the corresponding SCIP variable */
    1853 fixval = MAX(fixval, SCIPvarGetLbGlobal(var)); /*lint !e666*/
    1854 fixval = MIN(fixval, SCIPvarGetUbGlobal(var)); /*lint !e666*/
    1855
    1856 /* SCIPdebugMsg(scip, "fix variable <%s> to %g\n", SCIPvarGetName(var), fixval); */
    1857 SCIP_CALL( SCIPtightenVarLb(heurdata->subscip, subvar, fixval, TRUE, &infeas, &tightened) );
    1858 if( !infeas )
    1859 {
    1860 SCIP_CALL( SCIPtightenVarUb(heurdata->subscip, subvar, fixval, TRUE, &infeas, &tightened) );
    1861 }
    1862 if( infeas )
    1863 {
    1864 SCIPdebugMsg(scip, "skip NLP heuristic because start candidate not feasible: fixing var <%s> to value %g is infeasible\n", SCIPvarGetName(var), fixval);
    1865 goto CLEANUP;
    1866 }
    1867 }
    1868
    1869 /* if there is already a solution, possibly add an objective cutoff in sub-SCIP
    1870 * we do this here only for problems with discrete variables, since the cutoff may be useful when presolving the subscip
    1871 * for the NLP solver, a cutoff is useless at best
    1872 */
    1873 if( SCIPgetNSols(scip) > 0 && heurdata->setcutoff )
    1874 {
    1875 cutoff = SCIPgetUpperbound(scip);
    1876 assert( !SCIPisInfinity(scip, cutoff) );
    1877
    1878 SCIP_CALL( SCIPsetObjlimit(heurdata->subscip, cutoff) );
    1879 SCIPdebugMsg(scip, "set objective limit %g\n", cutoff);
    1880 }
    1881 }
    1882 else
    1883 {
    1884 /* for continuous problems, we should already be in the transformed stage */
    1885 assert(SCIPisTransformed(heurdata->subscip));
    1886 }
    1887
    1888 /* solve the subNLP and try to add solution to SCIP */
    1889 SCIP_CALL( solveSubNLP(scip, heur, result, refpoint, resultsol) );
    1890
    1891 if( heurdata->subscip == NULL )
    1892 {
    1893 /* something horrible must have happened that we decided to give up completely on this heuristic */
    1894 *result = SCIP_DIDNOTFIND;
    1895 return SCIP_OKAY;
    1896 }
    1897
    1898 if( *result == SCIP_CUTOFF )
    1899 {
    1900 if( heurdata->subscipisvalid && SCIPgetNActivePricers(scip) == 0 )
    1901 {
    1902 /* if the subNLP is valid and turned out to be globally infeasible (i.e., proven by SCIP), then we forbid this fixation in the main problem */
    1903 if( SCIPisInfinity(scip, cutoff) && heurdata->forbidfixings )
    1904 {
    1905 SCIP_CALL( forbidFixation(scip, heurdata) );
    1906 }
    1907 }
    1908 else
    1909 {
    1910 /* if the subNLP turned out to be globally infeasible but we are not sure that we have a valid copy, we change to DIDNOTFIND */
    1911 *result = SCIP_DIDNOTFIND;
    1912 }
    1913 }
    1914
    1915 CLEANUP:
    1916 if( !heurdata->continuous )
    1917 {
    1918 SCIP_CALL( SCIPfreeTransform(heurdata->subscip) );
    1919 }
    1920
    1921 /* if the heuristic was applied before solving has started, then destroy subSCIP, since EXITSOL may not be called
    1922 * also if keepcopy is disabled, then destroy subSCIP
    1923 */
    1924 if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING || !heurdata->keepcopy )
    1925 {
    1926 SCIP_CALL( freeSubSCIP(scip, heurdata) );
    1927 heurdata->triedsetupsubscip = FALSE;
    1928 }
    1929
    1930 return SCIP_OKAY;
    1931}
    1932
    1933/** updates the starting point for the NLP heuristic
    1934 *
    1935 * Is called by a constraint handler that handles nonlinear constraints when a check on feasibility of a solution fails.
    1936 */
    1938 SCIP* scip, /**< SCIP data structure */
    1939 SCIP_HEUR* heur, /**< NLP heuristic */
    1940 SCIP_SOL* solcand, /**< solution candidate */
    1941 SCIP_Real violation /**< constraint violation of solution candidate */
    1942 )
    1943{
    1944 SCIP_HEURDATA* heurdata;
    1945
    1946 assert(scip != NULL);
    1947 assert(heur != NULL);
    1948 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1949 assert(solcand != NULL);
    1950 assert(SCIPisPositive(scip, violation));
    1951
    1952 /* too early or the game is over already: no more interest in starting points */
    1954 return SCIP_OKAY;
    1955
    1956 /* only update starting point if an NLP relaxation has been constructed */
    1958 return SCIP_OKAY;
    1959
    1960 heurdata = SCIPheurGetData(heur);
    1961 assert(heurdata != NULL);
    1962
    1963 if( heurdata->subscip == NULL )
    1964 {
    1965 /* if we do not have a sub-SCIP, but tried to set one up before or will never create a subSCIP, then do not need a starting point */
    1966 SCIP_Bool runheur;
    1967 if( heurdata->triedsetupsubscip )
    1968 return SCIP_OKAY;
    1969 if( SCIPheurGetFreq(heur) < 0 )
    1970 return SCIP_OKAY;
    1972 if( !runheur )
    1973 return SCIP_OKAY;
    1974 }
    1975
    1976 /* if the solution is the one we created (last), then it is useless to use it as starting point again
    1977 * (we cannot check SCIPsolGetHeur()==heur, as subnlp may not be registered as author of the solution)
    1978 */
    1979 if( heurdata->lastsol == solcand )
    1980 return SCIP_OKAY;
    1981
    1982 SCIPdebugMsg(scip, "consider solution candidate with violation %g and objective %g from %s\n",
    1983 violation, SCIPgetSolTransObj(scip, solcand), SCIPsolGetHeur(solcand) ? SCIPheurGetName(SCIPsolGetHeur(solcand)) : "tree");
    1984
    1985 /* if we have no point yet, or the new point has a lower constraint violation, or it has a better objective function value, then take the new point */
    1986 if( heurdata->startcand == NULL || violation < heurdata->startcandviol ||
    1987 SCIPisRelGT(scip, SCIPgetSolTransObj(scip, heurdata->startcand), SCIPgetSolTransObj(scip, solcand)) )
    1988 {
    1989 if( heurdata->startcand != NULL )
    1990 {
    1991 SCIP_CALL( SCIPfreeSol(scip, &heurdata->startcand) );
    1992 }
    1993 SCIP_CALL( SCIPcreateSolCopy(scip, &heurdata->startcand, solcand) );
    1994 SCIP_CALL( SCIPunlinkSol(scip, heurdata->startcand) );
    1995 heurdata->startcandviol = violation;
    1996
    1997 /* remember which heuristic proposed the candidate */
    1998 SCIPsolSetHeur(heurdata->startcand, SCIPgetSolHeur(scip, solcand));
    1999 }
    2000
    2001 return SCIP_OKAY;
    2002}
    2003
    2004/** gets startpoint candidate to be used in next call to NLP heuristic, or NULL if none */
    2006 SCIP* scip, /**< original SCIP data structure */
    2007 SCIP_HEUR* heur /**< heuristic data structure */
    2008 )
    2009{
    2010 SCIP_HEURDATA* heurdata;
    2011
    2012 assert(scip != NULL);
    2013 assert(heur != NULL);
    2014 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    2015
    2016 heurdata = SCIPheurGetData(heur);
    2017 assert(heurdata != NULL);
    2018
    2019 return heurdata->startcand;
    2020}
    constraint handler for bound disjunction constraints
    Constraint handler for the set partitioning / packing / covering constraints .
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define MAX3(x, y, z)
    Definition: def.h:228
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIPABORT()
    Definition: def.h:327
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPcreateConsSetcover(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: cons_setppc.c:9518
    SCIP_RETCODE SCIPcopyPlugins(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool copyreaders, SCIP_Bool copypricers, SCIP_Bool copyconshdlrs, SCIP_Bool copyconflicthdlrs, SCIP_Bool copypresolvers, SCIP_Bool copyrelaxators, SCIP_Bool copyseparators, SCIP_Bool copycutselectors, SCIP_Bool copypropagators, SCIP_Bool copyheuristics, SCIP_Bool copyeventhdlrs, SCIP_Bool copynodeselectors, SCIP_Bool copybranchrules, SCIP_Bool copyiisfinders, SCIP_Bool copydisplays, SCIP_Bool copydialogs, SCIP_Bool copytables, SCIP_Bool copyexprhdlrs, SCIP_Bool copynlpis, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:276
    void SCIPmergeNLPIStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_Bool reset)
    Definition: scip_copy.c:1319
    SCIP_RETCODE SCIPcopyVars(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global)
    Definition: scip_copy.c:1167
    SCIP_RETCODE SCIPcopyProb(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, const char *name)
    Definition: scip_copy.c:529
    SCIP_RETCODE SCIPcopyConss(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool *valid)
    Definition: scip_copy.c:1716
    SCIP_RETCODE SCIPcopyParamSettings(SCIP *sourcescip, SCIP *targetscip)
    Definition: scip_copy.c:2547
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:647
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    SCIP_RETCODE SCIPgetOrigVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2753
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
    Definition: scip_prob.c:1661
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    int SCIPgetNConss(SCIP *scip)
    Definition: scip_prob.c:3620
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNContImplVars(SCIP *scip)
    Definition: scip_prob.c:2522
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3613
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3584
    SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
    Definition: misc.c:3592
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3603
    SCIP_Real SCIPgetLocalDualbound(SCIP *scip)
    Definition: scip_prob.c:4159
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_SOL * SCIPgetStartCandidateHeurSubNlp(SCIP *scip, SCIP_HEUR *heur)
    Definition: heur_subnlp.c:2005
    SCIP_RETCODE SCIPapplyHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_SOL *resultsol)
    Definition: heur_subnlp.c:1762
    SCIP_RETCODE SCIPupdateStartpointHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *solcand, SCIP_Real violation)
    Definition: heur_subnlp.c:1937
    SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
    Definition: scip_param.c:219
    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_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    SCIP_RETCODE SCIPresetParam(SCIP *scip, const char *name)
    Definition: scip_param.c:835
    SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:956
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
    Definition: scip_param.c:603
    SCIP_RETCODE SCIPincludeHeurSubNlp(SCIP *scip)
    Definition: heur_subnlp.c:1665
    int SCIPgetNLPBranchCands(SCIP *scip)
    Definition: scip_branch.c:436
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
    Definition: event.c:1217
    SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
    Definition: event.c:1415
    SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
    Definition: scip_heur.c:247
    SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
    Definition: scip_heur.c:122
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    SCIP_HEURTIMING SCIPheurGetTimingmask(SCIP_HEUR *heur)
    Definition: heur.c:1497
    SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
    Definition: heur.c:1603
    void SCIPheurSetTimingmask(SCIP_HEUR *heur, SCIP_HEURTIMING timingmask)
    Definition: heur.c:1507
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
    Definition: scip_heur.c:231
    int SCIPheurGetFreqofs(SCIP_HEUR *heur)
    Definition: heur.c:1573
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    int SCIPheurGetFreq(SCIP_HEUR *heur)
    Definition: heur.c:1552
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
    Definition: scip_lp.c:174
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocClearBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:97
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    int SCIPgetNNlpis(SCIP *scip)
    Definition: scip_nlpi.c:205
    SCIP_RETCODE SCIPhasNLPContinuousNonlinearity(SCIP *scip, SCIP_Bool *result)
    Definition: scip_nlp.c:125
    SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
    Definition: scip_nlp.c:110
    SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
    Definition: scip_nlp.c:574
    #define SCIPsolveNLP(...)
    Definition: scip_nlp.h:361
    SCIP_RETCODE SCIPsetNLPInitialGuess(SCIP *scip, SCIP_Real *initialguess)
    Definition: scip_nlp.c:474
    SCIP_Real SCIPgetNLPObjval(SCIP *scip)
    Definition: scip_nlp.c:645
    int SCIPgetNNLPVars(SCIP *scip)
    Definition: scip_nlp.c:201
    SCIP_VAR ** SCIPgetNLPVars(SCIP *scip)
    Definition: scip_nlp.c:179
    SCIP_Bool SCIPhasNLPSolution(SCIP *scip)
    Definition: scip_nlp.c:671
    SCIP_NLPTERMSTAT SCIPgetNLPTermstat(SCIP *scip)
    Definition: scip_nlp.c:596
    SCIP_RETCODE SCIPgetNLPStatistics(SCIP *scip, SCIP_NLPSTATISTICS *statistics)
    Definition: scip_nlp.c:621
    int SCIPgetNPresolRounds(SCIP *scip)
    Definition: scip_presol.c:296
    int SCIPgetNActivePricers(SCIP *scip)
    Definition: scip_pricer.c:348
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
    Definition: scip_sol.c:884
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_HEUR * SCIPgetSolHeur(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2249
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
    Definition: sol.c:4259
    SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1506
    SCIP_SOL ** SCIPgetSols(SCIP *scip)
    Definition: scip_sol.c:2931
    SCIP_RETCODE SCIPcheckSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
    Definition: scip_sol.c:4312
    SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4109
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2005
    void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
    Definition: sol.c:4304
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPpresolve(SCIP *scip)
    Definition: scip_solve.c:2449
    SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
    Definition: scip_solve.c:3462
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Real SCIPgetPrimalbound(SCIP *scip)
    SCIP_Real SCIPgetUpperbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisRelGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeastol(SCIP *scip)
    SCIP_Real SCIPdualfeastol(SCIP *scip)
    SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6401
    SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
    Definition: var.c:18320
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6651
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6141
    SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
    Definition: scip_var.c:2166
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6230
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
    Definition: var.c:24691
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    static SCIP_RETCODE processNLPSol(SCIP *scip, SCIP_HEUR *heur, SCIP_HEUR *authorheur, SCIP_RESULT *result, SCIP_SOL *resultsol)
    Definition: heur_subnlp.c:564
    static SCIP_DECL_HEURINITSOL(heurInitsolSubNlp)
    Definition: heur_subnlp.c:1469
    #define HEUR_TIMING
    Definition: heur_subnlp.c:76
    static SCIP_DECL_HEUREXITSOL(heurExitsolSubNlp)
    Definition: heur_subnlp.c:1495
    #define HEUR_FREQOFS
    Definition: heur_subnlp.c:74
    #define HEUR_DESC
    Definition: heur_subnlp.c:70
    static SCIP_RETCODE createSolFromNLP(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL **sol, SCIP_HEUR *authorheur)
    Definition: heur_subnlp.c:498
    static SCIP_RETCODE forbidFixation(SCIP *scip, SCIP_HEURDATA *heurdata)
    Definition: heur_subnlp.c:1233
    static SCIP_RETCODE createSolFromSubScipSol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL **sol, SCIP_SOL *subsol, SCIP_HEUR *authorheur)
    Definition: heur_subnlp.c:680
    static SCIP_DECL_EVENTEXEC(processVarEvent)
    Definition: heur_subnlp.c:441
    static SCIP_DECL_HEURFREE(heurFreeSubNlp)
    Definition: heur_subnlp.c:1420
    #define HEUR_DISPCHAR
    Definition: heur_subnlp.c:71
    #define HEUR_MAXDEPTH
    Definition: heur_subnlp.c:75
    #define HEUR_PRIORITY
    Definition: heur_subnlp.c:72
    #define HEUR_NAME
    Definition: heur_subnlp.c:69
    static int calcIterLimit(SCIP *scip, SCIP_HEURDATA *heurdata)
    Definition: heur_subnlp.c:747
    static SCIP_DECL_HEURCOPY(heurCopySubNlp)
    Definition: heur_subnlp.c:1406
    static SCIP_RETCODE solveSubNLP(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_SOL *refpoint, SCIP_SOL *resultsol)
    Definition: heur_subnlp.c:772
    static SCIP_RETCODE createSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
    Definition: heur_subnlp.c:190
    static SCIP_DECL_HEUREXEC(heurExecSubNlp)
    Definition: heur_subnlp.c:1527
    static SCIP_RETCODE freeSubSCIP(SCIP *scip, SCIP_HEURDATA *heurdata)
    Definition: heur_subnlp.c:137
    #define HEUR_FREQ
    Definition: heur_subnlp.c:73
    static SCIP_DECL_HEURINIT(heurInitSubNlp)
    Definition: heur_subnlp.c:1440
    #define HEUR_USESSUBSCIP
    Definition: heur_subnlp.c:77
    NLP local search primal heuristic using sub-SCIPs.
    memory allocation routines
    #define BMSclearMemory(ptr)
    Definition: memory.h:129
    Ipopt NLP interface.
    public methods for managing events
    public methods for primal heuristics
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    public methods for primal CIP solutions
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for event handler plugins and event handlers
    general public methods
    public methods for primal heuristic plugins and divesets
    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 presolving plugins
    public methods for variable pricer plugins
    public methods for global and local (sub)problems
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    public methods for timing
    public methods for SCIP variables
    SCIP_Real totaltime
    Definition: type_nlpi.h:190
    SCIP_Real boundviol
    Definition: type_nlpi.h:194
    SCIP_Real consviol
    Definition: type_nlpi.h:193
    #define SCIP_EVENTTYPE_GUBCHANGED
    Definition: type_event.h:76
    #define SCIP_EVENTTYPE_GBDCHANGED
    Definition: type_event.h:122
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_GLBCHANGED
    Definition: type_event.h:75
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_LPSOLSTAT_UNBOUNDEDRAY
    Definition: type_lp.h:46
    @ SCIP_VERBLEVEL_MINIMAL
    Definition: type_message.h:59
    @ SCIP_NLPTERMSTAT_OKAY
    Definition: type_nlpi.h:173
    @ SCIP_NLPTERMSTAT_ITERLIMIT
    Definition: type_nlpi.h:175
    @ SCIP_NLPTERMSTAT_OUTOFMEMORY
    Definition: type_nlpi.h:180
    @ SCIP_NLPSOLSTAT_GLOBINFEASIBLE
    Definition: type_nlpi.h:164
    @ SCIP_NLPSOLSTAT_LOCINFEASIBLE
    Definition: type_nlpi.h:163
    @ SCIP_NLPSOLSTAT_FEASIBLE
    Definition: type_nlpi.h:162
    @ SCIP_PARAMSETTING_OFF
    Definition: type_paramset.h:63
    @ SCIP_PARAMSETTING_DEFAULT
    Definition: type_paramset.h:59
    @ SCIP_PARAMSETTING_FAST
    Definition: type_paramset.h:62
    enum SCIP_ParamSetting SCIP_PARAMSETTING
    Definition: type_paramset.h:65
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_DELAYED
    Definition: type_result.h:43
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_SOLVED
    Definition: type_set.h:54
    @ SCIP_STAGE_PRESOLVING
    Definition: type_set.h:49
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    @ SCIP_STAGE_PRESOLVED
    Definition: type_set.h:51
    @ SCIP_STATUS_OPTIMAL
    Definition: type_stat.h:43
    @ SCIP_STATUS_TOTALNODELIMIT
    Definition: type_stat.h:50
    @ SCIP_STATUS_BESTSOLLIMIT
    Definition: type_stat.h:60
    @ SCIP_STATUS_SOLLIMIT
    Definition: type_stat.h:59
    @ SCIP_STATUS_UNBOUNDED
    Definition: type_stat.h:45
    @ SCIP_STATUS_GAPLIMIT
    Definition: type_stat.h:56
    @ SCIP_STATUS_USERINTERRUPT
    Definition: type_stat.h:47
    @ SCIP_STATUS_INFORUNBD
    Definition: type_stat.h:46
    @ SCIP_STATUS_STALLNODELIMIT
    Definition: type_stat.h:52
    @ SCIP_STATUS_TIMELIMIT
    Definition: type_stat.h:54
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44
    @ SCIP_STATUS_NODELIMIT
    Definition: type_stat.h:49
    @ SCIP_STATUS_MEMLIMIT
    Definition: type_stat.h:55
    unsigned int SCIP_HEURTIMING
    Definition: type_timing.h:103
    #define SCIP_HEURTIMING_DURINGLPLOOP
    Definition: type_timing.h:81
    #define SCIP_HEURTIMING_NONE
    Definition: type_timing.h:79
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64