Scippy

SCIP

Solving Constraint Integer Programs

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