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