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