Scippy

SCIP

Solving Constraint Integer Programs

heur_proximity.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_proximity.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief improvement heuristic which uses an auxiliary objective instead of the original objective function which
28 * is itself added as a constraint to a sub-SCIP instance. The heuristic was presented by Matteo Fischetti
29 * and Michele Monaci.
30 * @author Gregor Hendel
31 */
32
33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34
36#include "scip/cons_linear.h"
37#include "scip/heuristics.h"
38#include "scip/heur_proximity.h"
39#include "scip/pub_event.h"
40#include "scip/pub_heur.h"
41#include "scip/pub_message.h"
42#include "scip/pub_misc.h"
43#include "scip/pub_sol.h"
44#include "scip/pub_var.h"
45#include "scip/scip_branch.h"
46#include "scip/scip_cons.h"
47#include "scip/scip_copy.h"
48#include "scip/scip_event.h"
49#include "scip/scip_exact.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_nodesel.h"
57#include "scip/scip_numerics.h"
58#include "scip/scip_param.h"
59#include "scip/scip_prob.h"
60#include "scip/scip_sol.h"
61#include "scip/scip_solve.h"
63#include "scip/scip_timing.h"
64#include "scip/scip_var.h"
65#include <string.h>
66
67#define HEUR_NAME "proximity"
68#define HEUR_DESC "heuristic trying to improve the incumbent by an auxiliary proximity objective function"
69#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
70#define HEUR_PRIORITY -2000000
71#define HEUR_FREQ -1
72#define HEUR_FREQOFS 0
73#define HEUR_MAXDEPTH -1
74#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
75#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
76
77/* event handler properties */
78#define EVENTHDLR_NAME "Proximity"
79#define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
80
81/* default values for proximity-specific parameters */
82/* todo refine these values */
83#define DEFAULT_MAXNODES 10000LL /**< maximum number of nodes to regard in the subproblem */
84#define DEFAULT_MINIMPROVE 0.02 /**< factor by which proximity should at least improve the incumbent */
85#define DEFAULT_MINGAP 0.01 /**< minimum primal-dual gap for which the heuristic is executed */
86#define DEFAULT_MINNODES 1LL /**< minimum number of nodes to regard in the subproblem */
87#define DEFAULT_MINLPITERS 200LL /**< minimum number of LP iterations to perform in one sub-mip */
88#define DEFAULT_MAXLPITERS 100000LL /**< maximum number of LP iterations to be performed in the subproblem */
89#define DEFAULT_NODESOFS 50LL /**< number of nodes added to the contingent of the total nodes */
90#define DEFAULT_WAITINGNODES 100LL /**< default waiting nodes since last incumbent before heuristic is executed */
91#define DEFAULT_NODESQUOT 0.1 /**< default quotient of sub-MIP nodes with respect to number of processed nodes*/
92#define DEFAULT_USELPROWS FALSE /**< should subproblem be constructed based on LP row information? */
93#define DEFAULT_BINVARQUOT 0.1 /**< default threshold for percentage of binary variables required to start */
94#define DEFAULT_RESTART TRUE /**< should the heuristic immediately run again on its newly found solution? */
95#define DEFAULT_USEFINALLP FALSE /**< should the heuristic solve a final LP in case of continuous objective variables? */
96#define DEFAULT_LPITERSQUOT 0.2 /**< default quotient of sub-MIP LP iterations with respect to LP iterations so far */
97#define DEFAULT_USEUCT FALSE /**< should uct node selection be used at the beginning of the search? */
98
99/*
100 * Data structures
101 */
102
103/** primal heuristic data */
104struct SCIP_HeurData
105{
106 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
107 SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
108 SCIP_Longint maxlpiters; /**< maximum number of LP iterations to be performed in the subproblem */
109 SCIP_Longint nusedlpiters; /**< number of actually performed LP iterations */
110 SCIP_Longint minlpiters; /**< minimum number of LP iterations to perform in one sub-mip */
111 SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
112 SCIP_Longint usednodes; /**< nodes already used by proximity in earlier calls */
113 SCIP_Longint waitingnodes; /**< waiting nodes since last incumbent before heuristic is executed */
114 SCIP_Real lpitersquot; /**< quotient of sub-MIP LP iterations with respect to LP iterations so far */
115 SCIP_Real minimprove; /**< factor by which proximity should at least improve the incumbent */
116 SCIP_Real mingap; /**< minimum primal-dual gap for which the heuristic is executed */
117 SCIP_Real nodesquot; /**< quotient of sub-MIP nodes with respect to number of processed nodes */
118 SCIP_Real binvarquot; /**< threshold for percantage of binary variables required to start */
119
120 SCIP* subscip; /**< the subscip used by the heuristic */
121 SCIP_HASHMAP* varmapfw; /**< map between scip variables and subscip variables */
122 SCIP_VAR** subvars; /**< variables in subscip */
123 SCIP_CONS* objcons; /**< the objective cutoff constraint of the subproblem */
124
125 int nsubvars; /**< the number of subvars */
126 int lastsolidx; /**< index of last solution on which the heuristic was processed */
127 int subprobidx; /**< counter for the subproblem index to be solved by proximity */
128
129 SCIP_Bool uselprows; /**< should subproblem be constructed based on LP row information? */
130 SCIP_Bool restart; /**< should the heuristic immediately run again on its newly found solution? */
131 SCIP_Bool usefinallp; /**< should the heuristic solve a final LP in case of continuous objective variables? */
132 SCIP_Bool useuct; /**< should uct node selection be used at the beginning of the search? */
133};
134
135
136/*
137 * Local methods
138 */
139
140/** optimizes the continuous variables in an LP diving by fixing all integer variables to the given solution values */
141static
143 SCIP* scip, /**< SCIP data structure */
144 SCIP_SOL* sol, /**< candidate solution for which continuous variables should be optimized */
145 SCIP_Bool* success /**< was the dive successful? */
146 )
147{
148 SCIP_VAR** vars;
149 SCIP_RETCODE retstat;
150
151 int v;
152 int nvars;
153 int ncontvars;
154 int nintvars;
155
156 SCIP_Bool lperror;
157 SCIP_Bool requiresnlp;
158
159 assert(success != NULL);
160
161 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, &ncontvars) );
162
163 nintvars = nvars - ncontvars;
164
165 /**@todo in case of an MINLP, if SCIPisNLPConstructed() is TRUE rather solve the NLP instead of the LP */
166 requiresnlp = SCIPisNLPConstructed(scip);
167 if( requiresnlp || ncontvars == 0 )
168 return SCIP_OKAY;
169
170 /* start diving to calculate the LP relaxation */
172
173 /* set the bounds of the variables: fixed for integers, global bounds for continuous */
174 for( v = 0; v < nvars; ++v )
175 {
177 {
178 SCIP_CALL( SCIPchgVarLbDive(scip, vars[v], SCIPvarGetLbGlobal(vars[v])) );
179 SCIP_CALL( SCIPchgVarUbDive(scip, vars[v], SCIPvarGetUbGlobal(vars[v])) );
180 }
181 }
182
183 /* apply this after global bounds to not cause an error with intermediate empty domains */
184 for( v = 0; v < nintvars; ++v )
185 {
187 {
188 SCIP_Real solval;
189
190 solval = SCIPgetSolVal(scip, sol, vars[v]);
191 SCIP_CALL( SCIPchgVarLbDive(scip, vars[v], solval) );
192 SCIP_CALL( SCIPchgVarUbDive(scip, vars[v], solval) );
193 }
194 }
195
196 /* solve LP */
197 SCIPdebugMsg(scip, " -> old LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
198
199 /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
200 * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
201 */
202 retstat = SCIPsolveDiveLP(scip, -1, &lperror, NULL);
203 if( retstat != SCIP_OKAY )
204 {
205#ifdef NDEBUG
206 SCIPwarningMessage(scip, "Error while solving LP in Proximity heuristic; LP solve terminated with code <%d>\n",retstat);
207#else
208 SCIP_CALL( retstat );
209#endif
210 }
211
212 SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
213 SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, SCIPgetLPSolstat(scip));
214 if( !lperror && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
215 {
217
218 /* in exact mode we have to end diving prior to trying the solution */
219 if( SCIPisExact(scip) )
220 {
223 }
224
225 SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
226 }
227
228 /* terminate diving mode */
229 if( SCIPinDive(scip) )
230 {
232 }
233
234 return SCIP_OKAY;
235}
236
237/** creates a new solution for the original problem by copying the solution of the subproblem */
238static
240 SCIP* scip, /**< original SCIP data structure */
241 SCIP* subscip, /**< SCIP structure of the subproblem */
242 SCIP_VAR** subvars, /**< the variables of the subproblem */
243 SCIP_HEUR* heur, /**< proximity heuristic structure */
244 SCIP_SOL* subsol, /**< solution of the subproblem */
245 SCIP_Bool usefinallp, /**< should continuous variables be optimized by a final LP */
246 SCIP_Bool* success /**< used to store whether new solution was found or not */
247 )
248{
249 SCIP_VAR** vars; /* the original problem's variables */
250 int nvars; /* the original problem's number of variables */
251 int ncontvars; /* the original problem's number of continuous variables */
252 SCIP_Real* subsolvals; /* solution values of the subproblem */
253 SCIP_SOL* newsol; /* solution to be created for the original problem */
254 int i;
255
256 assert(scip != NULL);
257 assert(subscip != NULL);
258 assert(subvars != NULL);
259 assert(subsol != NULL);
260 assert(success != NULL);
261
262 /* get variables' data */
263 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, &ncontvars) );
264
265 SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
266
267 /* copy the solution */
268 for( i = 0; i < nvars; ++i )
269 {
270 if( subvars[i] == NULL )
271 subsolvals[i] = MIN(MAX(0.0, SCIPvarGetLbLocal(vars[i])), SCIPvarGetUbLocal(vars[i])); /*lint !e666*/
272 else
273 subsolvals[i] = SCIPgetSolVal(subscip, subsol, subvars[i]);
274 }
275
276 /* create new solution for the original problem */
277 SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
278 SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
279
280 *success = FALSE;
281
282 /* solve an LP with all integer variables fixed to improve solution quality */
283 if( ncontvars > 0 && usefinallp && SCIPisLPConstructed(scip) )
284 {
285 int v;
286 int ncontobjvars = 0; /* does the problem instance have continuous variables with nonzero objective coefficients? */
287 SCIP_Real sumofobjsquares = 0.0;
288
289 /* check if continuous variables with nonzero objective coefficient are present */
290 for( v = nvars - 1; v >= nvars - ncontvars; --v )
291 {
292 SCIP_VAR* var;
293
294 var = vars[v];
295 assert(vars[v] != NULL);
296 assert(!SCIPvarIsIntegral(var));
297
299 {
300 ++ncontobjvars;
301 sumofobjsquares += SCIPvarGetObj(var) * SCIPvarGetObj(var);
302 }
303 }
304
305 SCIPstatisticMessage(" Continuous Objective variables: %d, Euclidean OBJ: %g total, %g continuous\n", ncontobjvars, SCIPgetObjNorm(scip), sumofobjsquares);
306
307 /* solve a final LP to optimize solution values of continuous problem variables */
308 SCIPstatisticMessage("Solution Value before LP resolve: %g\n", SCIPgetSolOrigObj(scip, newsol));
309 SCIP_CALL( solveLp(scip, newsol, success) );
310
311 /* if the LP solve was not successful, reset the solution */
312 if( !*success )
313 {
314 for( v = nvars - 1; v >= nvars - ncontvars; --v )
315 {
316 SCIP_CALL( SCIPsetSolVal(scip, newsol, vars[v], subsolvals[v]) );
317 }
318 }
319 }
320
321 /* try to add new solution to SCIP and free it immediately */
322 if( !*success )
323 {
324 SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
325 }
326 SCIP_CALL( SCIPfreeSol(scip, &newsol) );
327
328 SCIPfreeBufferArray(scip, &subsolvals);
329
330 return SCIP_OKAY;
331}
332
333/** sets solving parameters for the subproblem created by the heuristic */
334static
336 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
337 SCIP* subscip /**< copied SCIP data structure */
338 )
339{
340 assert(subscip != NULL);
341
342 /* do not abort subproblem on CTRL-C */
343 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
344
345#ifdef SCIP_DEBUG
346 /* for debugging, enable full output */
347 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
348 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
349#else
350 /* disable statistic timing inside sub SCIP and output to console */
351 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
352 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
353#endif
354
355 /* forbid recursive call of heuristics and separators solving sub-SCIPs */
356 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
357
358 /* use restart dfs node selection */
359 if( SCIPfindNodesel(subscip, "restartdfs") != NULL && !SCIPisParamFixed(subscip, "nodeselection/restartdfs/stdpriority") )
360 {
361 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/restartdfs/stdpriority", INT_MAX/4) );
362 }
363
364 /* activate uct node selection at the top of the tree */
365 if( heurdata->useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
366 {
367 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
368 }
369
370 /* disable expensive presolving
371 * todo maybe presolving can be entirely turned off here - parameter???
372 */
374
375 /* SCIP_CALL( SCIPsetPresolving(scip, SCIP_PARAMSETTING_OFF, TRUE) ); */
376 if( !SCIPisParamFixed(subscip, "presolving/maxrounds") )
377 {
378 SCIP_CALL( SCIPsetIntParam(subscip, "presolving/maxrounds", 50) );
379 }
380
381 /* disable cutting plane separation */
383
384 /* todo: check branching rule in sub-SCIP */
385 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
386 {
387 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
388 }
389
390 /* disable feasibility pump and fractional diving */
391 if( !SCIPisParamFixed(subscip, "heuristics/feaspump/freq") )
392 {
393 SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/feaspump/freq", -1) );
394 }
395 if( !SCIPisParamFixed(subscip, "heuristics/fracdiving/freq") )
396 {
397 SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/fracdiving/freq", -1) );
398 }
399
400 /* todo check if
401 * SCIP_CALL( SCIPsetEmphasis(subscip, SCIP_PARAMEMPHASIS_FEASIBILITY, TRUE) );
402 * improves performance */
403
404 return SCIP_OKAY;
405}
406
407/** frees the subproblem */
408static
410 SCIP* scip, /**< SCIP data structure */
411 SCIP_HEURDATA* heurdata /**< heuristic data */
412 )
413{
414 /* free remaining memory from heuristic execution */
415 if( heurdata->subscip != NULL )
416 {
417 assert(heurdata->varmapfw != NULL);
418 assert(heurdata->subvars != NULL);
419 assert(heurdata->objcons != NULL);
420
421 SCIPdebugMsg(scip, "Freeing subproblem of proximity heuristic\n");
422 SCIPfreeBlockMemoryArray(scip, &heurdata->subvars, heurdata->nsubvars);
423 SCIPhashmapFree(&heurdata->varmapfw);
424 SCIP_CALL( SCIPreleaseCons(heurdata->subscip, &heurdata->objcons) );
425 SCIP_CALL( SCIPfree(&heurdata->subscip) );
426
427 heurdata->subscip = NULL;
428 heurdata->varmapfw = NULL;
429 heurdata->subvars = NULL;
430 heurdata->objcons = NULL;
431 }
432 return SCIP_OKAY;
433}
434
435/* ---------------- Callback methods of event handler ---------------- */
436
437/** exec the event handler
438 *
439 * We interrupt the solution process.
440 */
441static
442SCIP_DECL_EVENTEXEC(eventExecProximity)
443{
444 SCIP_HEURDATA* heurdata;
445
446 assert(eventhdlr != NULL);
447 assert(eventdata != NULL);
448 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
449 assert(event != NULL);
451
452 heurdata = (SCIP_HEURDATA*)eventdata;
453 assert(heurdata != NULL);
454
455 /* interrupt solution process of sub-SCIP
456 * todo adjust interruption limit */
457 if( SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_ITERLIMIT || SCIPgetNLPIterations(scip) >= heurdata->maxlpiters )
458 {
460 }
461
462 return SCIP_OKAY;
463}
464
465
466/* ---------------- Callback methods of primal heuristic ---------------- */
467
468/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
469static
470SCIP_DECL_HEURCOPY(heurCopyProximity)
471{ /*lint --e{715}*/
472 assert(scip != NULL);
473 assert(heur != NULL);
474 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
475
476 /* call inclusion method of primal heuristic */
478
479 return SCIP_OKAY;
480}
481
482/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
483static
484SCIP_DECL_HEURFREE(heurFreeProximity)
485{ /*lint --e{715}*/
486 SCIP_HEURDATA* heurdata;
487
488 assert( heur != NULL );
489 assert( scip != NULL );
490
491 /* get heuristic data */
492 heurdata = SCIPheurGetData(heur);
493 assert( heurdata != NULL );
494
495 /* free heuristic data */
496 SCIPfreeBlockMemory(scip, &heurdata);
497 SCIPheurSetData(heur, NULL);
498
499 return SCIP_OKAY;
500}
501
502
503/** initialization method of primal heuristic (called after problem was transformed) */
504static
505SCIP_DECL_HEURINIT(heurInitProximity)
506{ /*lint --e{715}*/
507 SCIP_HEURDATA* heurdata;
508
509 assert( heur != NULL );
510 assert( scip != NULL );
511
512 /* get heuristic data */
513 heurdata = SCIPheurGetData(heur);
514 assert( heurdata != NULL );
515
516 /* initialize data */
517 heurdata->usednodes = 0LL;
518 heurdata->lastsolidx = -1;
519 heurdata->nusedlpiters = 0LL;
520 heurdata->subprobidx = 0;
521
522 heurdata->subscip = NULL;
523 heurdata->varmapfw = NULL;
524 heurdata->subvars = NULL;
525 heurdata->objcons = NULL;
526
527 heurdata->nsubvars = 0;
528
529 return SCIP_OKAY;
530}
531
532/** solution process exiting method of proximity heuristic */
533static
534SCIP_DECL_HEUREXITSOL(heurExitsolProximity)
535{
536 SCIP_HEURDATA* heurdata;
537
538 assert( heur != NULL );
539 assert( scip != NULL );
540
541 /* get heuristic data */
542 heurdata = SCIPheurGetData(heur);
543 assert( heurdata != NULL );
544
545 SCIP_CALL( deleteSubproblem(scip, heurdata) );
546
547 assert(heurdata->subscip == NULL && heurdata->varmapfw == NULL && heurdata->subvars == NULL && heurdata->objcons == NULL);
548
549 return SCIP_OKAY;
550}
551
552/** execution method of primal heuristic */
553static
554SCIP_DECL_HEUREXEC(heurExecProximity)
555{ /*lint --e{715}*/
556 SCIP_HEURDATA* heurdata; /* heuristic's data */
557 SCIP_Longint nnodes; /* number of stalling nodes for the subproblem */
558 SCIP_Longint nlpiters; /* lp iteration limit for the subproblem */
559 SCIP_Bool foundsol = FALSE;
560
561 assert(heur != NULL);
562 assert(scip != NULL);
563 assert(result != NULL);
564
565 *result = SCIP_DIDNOTRUN;
566
567 /* get heuristic data */
568 heurdata = SCIPheurGetData(heur);
569 assert(heurdata != NULL);
570
571 /* do not run heuristic when there are only few binary varables */
572 if( SCIPgetNBinVars(scip) < heurdata->binvarquot * SCIPgetNVars(scip) )
573 return SCIP_OKAY;
574
575 /* calculate branching node limit for sub problem */
576 /* todo maybe treat root node differently */
577 nnodes = (SCIP_Longint) (heurdata->nodesquot * SCIPgetNNodes(scip));
578 nnodes += heurdata->nodesofs;
579
580 /* determine the node and LP iteration limit for the solve of the sub-SCIP */
581 nnodes -= heurdata->usednodes;
582 nnodes = MIN(nnodes, heurdata->maxnodes);
583
584 nlpiters = (SCIP_Longint) (heurdata->lpitersquot * SCIPgetNRootFirstLPIterations(scip));
585 nlpiters = MIN(nlpiters, heurdata->maxlpiters);
586
587 /* check whether we have enough nodes left to call subproblem solving */
588 if( nnodes < heurdata->minnodes )
589 {
590 SCIPdebugMsg(scip, "skipping proximity: nnodes=%" SCIP_LONGINT_FORMAT ", minnodes=%" SCIP_LONGINT_FORMAT "\n", nnodes, heurdata->minnodes);
591 return SCIP_OKAY;
592 }
593
594 /* do not run proximity, if the problem does not have an objective function anyway */
595 if( SCIPgetNObjVars(scip) == 0 )
596 {
597 SCIPdebugMsg(scip, "skipping proximity: pure feasibility problem anyway\n");
598 return SCIP_OKAY;
599 }
600
601 do
602 {
603 /* main loop of proximity: in every iteration, a new subproblem is set up and solved until no improved solution
604 * is found or one of the heuristic limits on nodes or LP iterations is hit
605 * heuristic performs only one iteration if restart parameter is set to FALSE
606 */
607 SCIP_Longint nusednodes = 0LL;
608 SCIP_Longint nusedlpiters = 0LL;
609
610 nlpiters = MAX(nlpiters, heurdata->minlpiters);
611
612 /* define and solve the proximity subproblem */
613 SCIP_CALL( SCIPapplyProximity(scip, heur, result, heurdata->minimprove, nnodes, nlpiters, &nusednodes, &nusedlpiters, FALSE) );
614
615 /* adjust node limit and LP iteration limit for future iterations */
616 assert(nusednodes <= nnodes);
617 heurdata->usednodes += nusednodes;
618 nnodes -= nusednodes;
619
620 nlpiters -= nusedlpiters;
621 heurdata->nusedlpiters += nusedlpiters;
622
623 /* memorize if a new solution has been found in at least one iteration */
624 if( *result == SCIP_FOUNDSOL )
625 foundsol = TRUE;
626 }
627 while( *result == SCIP_FOUNDSOL && heurdata->restart && !SCIPisStopped(scip) && nnodes > 0 );
628
629 /* reset result pointer if solution has been found in previous iteration */
630 if( foundsol )
631 *result = SCIP_FOUNDSOL;
632
633 /* free the occupied memory */
634 if( heurdata->subscip != NULL )
635 {
636 /* just for testing the library method, in debug mode, we call the wrapper method for the actual delete method */
637#ifndef NDEBUG
639#else
640 SCIP_CALL( deleteSubproblem(scip, heurdata) );
641#endif
642 }
643 return SCIP_OKAY;
644}
645
646
647/*
648 * primal heuristic specific interface methods
649 */
650
651/** frees the sub-MIP created by proximity */
653 SCIP* scip /** SCIP data structure */
654 )
655{
656 SCIP_HEUR* heur;
657 SCIP_HEURDATA* heurdata;
658
659 assert(scip != NULL);
660
661 heur = SCIPfindHeur(scip, HEUR_NAME);
662 assert(heur != NULL);
663
664 heurdata = SCIPheurGetData(heur);
665 if( heurdata != NULL )
666 {
667 SCIP_CALL( deleteSubproblem(scip, heurdata) );
668 }
669
670 return SCIP_OKAY;
671}
672
673/** main procedure of the proximity heuristic, creates and solves a sub-SCIP
674 *
675 * @note The method can be applied in an iterative way, keeping the same subscip in between. If the @p freesubscip
676 * parameter is set to FALSE, the heuristic will keep the subscip data structures. Always set this parameter
677 * to TRUE, or call SCIPdeleteSubproblemProximity() afterwards.
678 */
680 SCIP* scip, /**< original SCIP data structure */
681 SCIP_HEUR* heur, /**< heuristic data structure */
682 SCIP_RESULT* result, /**< result data structure */
683 SCIP_Real minimprove, /**< factor by which proximity should at least improve the incumbent */
684 SCIP_Longint nnodes, /**< node limit for the subproblem */
685 SCIP_Longint nlpiters, /**< LP iteration limit for the subproblem */
686 SCIP_Longint* nusednodes, /**< pointer to store number of used nodes in subscip */
687 SCIP_Longint* nusedlpiters, /**< pointer to store number of used LP iterations in subscip */
688 SCIP_Bool freesubscip /**< should the created sub-MIP be freed at the end of the method? */
689 )
690{
691 SCIP* subscip; /* the subproblem created by proximity */
692 SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */
693 SCIP_VAR** vars; /* original problem's variables */
694 SCIP_VAR** subvars; /* subproblem's variables */
695 SCIP_HEURDATA* heurdata; /* heuristic's private data structure */
696 SCIP_EVENTHDLR* eventhdlr; /* event handler for LP events */
697
698 SCIP_SOL* incumbent;
699 SCIP_CONS* objcons;
700 SCIP_Longint iterlim;
701
702 SCIP_Real large;
703 SCIP_Real inf;
704
705 SCIP_Real bestobj;
706 SCIP_Real objcutoff;
707 SCIP_Real lowerbound;
708
709 int nvars; /* number of original problem's variables */
710 int nfixedvars;
711 int nsubsols;
712 int solidx;
713 int i;
714
715 SCIP_Bool valid;
716 SCIP_Bool success;
717
718 assert(scip != NULL);
719 assert(heur != NULL);
720 assert(result != NULL);
721
722 assert(nnodes >= 0);
723 assert(0.0 <= minimprove && minimprove <= 1.0);
724
725 *result = SCIP_DIDNOTRUN;
726
727 /* get heuristic data */
728 heurdata = SCIPheurGetData(heur);
729 assert(heurdata != NULL);
730
731 /* only call the heuristic if we have an incumbent */
732 if( SCIPgetNSolsFound(scip) == 0 )
733 return SCIP_OKAY;
734
735 /* do not use heuristic on problems without binary variables */
736 if( SCIPgetNBinVars(scip) == 0 )
737 return SCIP_OKAY;
738
739 incumbent = SCIPgetBestSol(scip);
740 assert(incumbent != NULL);
741
742 /* make sure that the incumbent is valid for the transformed space, otherwise terminate */
743 if( SCIPsolIsOriginal(incumbent) )
744 return SCIP_OKAY;
745
746 solidx = SCIPsolGetIndex(incumbent);
747
748 if( heurdata->lastsolidx == solidx )
749 return SCIP_OKAY;
750
751 /* only call heuristic, if the best solution does not come from trivial heuristic */
752 if( SCIPsolGetHeur(incumbent) != NULL && strcmp(SCIPheurGetName(SCIPsolGetHeur(incumbent)), "trivial") == 0 )
753 return SCIP_OKAY;
754
755 /* waitingnodes parameter defines the minimum number of nodes to wait before a new incumbent is processed */
756 if( SCIPgetNNodes(scip) > 1 && SCIPgetNNodes(scip) - SCIPsolGetNodenum(incumbent) < heurdata->waitingnodes )
757 return SCIP_OKAY;
758
759 bestobj = SCIPgetSolTransObj(scip, incumbent);
760 lowerbound = SCIPgetLowerbound(scip);
761
762 /* use knowledge about integrality of objective to round up lower bound */
764 {
765 SCIPdebugMsg(scip, " Rounding up lower bound: %f --> %f \n", lowerbound, SCIPfeasCeil(scip, lowerbound));
766 lowerbound = SCIPfeasCeil(scip, lowerbound);
767 }
768
769 /* do not trigger heuristic if primal and dual bound are already close together */
770 if( SCIPisFeasLE(scip, bestobj, lowerbound) || SCIPgetGap(scip) <= heurdata->mingap )
771 return SCIP_OKAY;
772
773 /* calculate the minimum improvement for a heuristic solution in terms of the distance between incumbent objective
774 * and the lower bound */
775 if( SCIPisInfinity(scip, REALABS(lowerbound)) )
776 {
777 if( SCIPisZero(scip, bestobj) )
778 objcutoff = bestobj - 1;
779 else
780 objcutoff = (1 - minimprove) * bestobj;
781 }
782 else
783 objcutoff = minimprove * lowerbound + (1 - minimprove) * (bestobj);
784
785 /* use integrality of the objective function to round down (and thus strengthen) the objective cutoff */
787 objcutoff = SCIPfeasFloor(scip, objcutoff);
788
789 if( SCIPisFeasLT(scip, objcutoff, lowerbound) )
790 objcutoff = lowerbound;
791
792 /* exit execution if the right hand side of the objective constraint does not change (suggests that the heuristic
793 * was not successful in a previous iteration) */
794 if( heurdata->objcons != NULL && SCIPisFeasEQ(scip, SCIPgetRhsLinear(heurdata->subscip, heurdata->objcons), objcutoff) )
795 return SCIP_OKAY;
796
797 /* check whether there is enough time and memory left */
799
800 if( ! valid )
801 return SCIP_OKAY;
802
803 *result = SCIP_DIDNOTFIND;
804
805 heurdata->lastsolidx = solidx;
806
807 /* get variable data */
808 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
809
810 /* create a subscip and copy the original scip instance into it */
811 if( heurdata->subscip == NULL )
812 {
813 assert(heurdata->varmapfw == NULL);
814 assert(heurdata->objcons == NULL);
815
816 /* initialize the subproblem */
817 SCIP_CALL( SCIPcreate(&subscip) );
818
819 /* create the variable mapping hash map */
820 SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
821 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &subvars, nvars) );
822
823 /* copy complete SCIP instance */
824 valid = FALSE;
825
826 /* create a problem copy as sub SCIP */
827 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "proximity", NULL, NULL, 0, heurdata->uselprows, TRUE,
828 &success, &valid) );
829
830 SCIPdebugMsg(scip, "Copying the SCIP instance was %s complete.\n", valid ? "" : "not ");
831
832 /* create event handler for LP events */
833 eventhdlr = NULL;
834 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecProximity, NULL) );
835 if( eventhdlr == NULL )
836 {
837 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
838 return SCIP_PLUGINNOTFOUND;
839 }
840
841 /* set up parameters for the copied instance */
842 SCIP_CALL( setupSubproblem(heurdata, subscip) );
843
844 /* create the objective constraint in the sub scip, first without variables and values which will be added later */
845 SCIP_CALL( SCIPcreateConsBasicLinear(subscip, &objcons, "objbound_of_origscip", 0, NULL, NULL, -SCIPinfinity(subscip), SCIPinfinity(subscip)) );
846
847 /* determine large value to set variable bounds to, safe-guard to avoid fixings to infinite values */
848 large = SCIPinfinity(scip);
849 if( !SCIPisInfinity(scip, 0.1 / SCIPfeastol(scip)) )
850 large = 0.1 / SCIPfeastol(scip);
851 inf = SCIPinfinity(subscip);
852
853 /* get variable image and change objective to proximity function (Manhattan distance) in sub-SCIP */
854 for( i = 0; i < nvars; i++ )
855 {
856 SCIP_Real adjustedbound;
857 SCIP_Real lb;
858 SCIP_Real ub;
859
860 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
861
862 if( subvars[i] == NULL )
863 continue;
864
865 SCIP_CALL( SCIPchgVarObj(subscip, subvars[i], 0.0) );
866
867 lb = SCIPvarGetLbGlobal(subvars[i]);
868 ub = SCIPvarGetUbGlobal(subvars[i]);
869
870 /* adjust infinite bounds in order to avoid that variables with non-zero objective
871 * get fixed to infinite value in proximity subproblem
872 */
873 if( SCIPisInfinity(subscip, ub) )
874 {
875 adjustedbound = MAX(large, lb + large);
876 adjustedbound = MIN(adjustedbound, inf);
877 SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[i], adjustedbound) );
878 }
879 if( SCIPisInfinity(subscip, -lb) )
880 {
881 adjustedbound = MIN(-large, ub - large);
882 adjustedbound = MAX(adjustedbound, -inf);
883 SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[i], adjustedbound) );
884 }
885
886 /* add all nonzero objective coefficients to the objective constraint */
887 if( !SCIPisFeasZero(subscip, SCIPvarGetObj(vars[i])) )
888 {
889 SCIP_CALL( SCIPaddCoefLinear(subscip, objcons, subvars[i], SCIPvarGetObj(vars[i])) );
890 }
891 }
892
893 /* add objective constraint to the subscip */
894 SCIP_CALL( SCIPaddCons(subscip, objcons) );
895 }
896 else
897 {
898 /* the instance, event handler, hash map and variable array were already copied in a previous iteration
899 * and stored in heuristic data
900 */
901 assert(heurdata->varmapfw != NULL);
902 assert(heurdata->subvars != NULL);
903 assert(heurdata->objcons != NULL);
904
905 subscip = heurdata->subscip;
906 varmapfw = heurdata->varmapfw;
907 subvars = heurdata->subvars;
908 objcons = heurdata->objcons;
909
910 eventhdlr = SCIPfindEventhdlr(subscip, EVENTHDLR_NAME);
911 assert(eventhdlr != NULL);
912 }
913
914 SCIP_CALL( SCIPchgRhsLinear(subscip, objcons, objcutoff) );
915
916 for( i = 0; i < SCIPgetNBinVars(scip); ++i )
917 {
918 SCIP_Real solval;
919
920 if( subvars[i] == NULL )
921 continue;
922
923 /* objective coefficients are only set for binary variables of the problem */
924 assert(SCIPvarIsBinary(subvars[i]));
925
926 solval = SCIPgetSolVal(scip, incumbent, vars[i]);
927 assert(SCIPisFeasGE(scip, solval, 0.0));
928 assert(SCIPisFeasLE(scip, solval, 1.0));
929 assert(SCIPisFeasIntegral(scip, solval));
930
931 if( solval < 0.5 )
932 {
933 SCIP_CALL( SCIPchgVarObj(subscip, subvars[i], 1.0) );
934 }
935 else
936 {
937 SCIP_CALL( SCIPchgVarObj(subscip, subvars[i], -1.0) );
938 }
939 }
940
941 /* set limits for the subproblem */
942 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
943 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nnodes) );
944 SCIP_CALL( SCIPsetIntParam(subscip, "limits/solutions", 1) );
945
946 /* restrict LP iterations */
947 /* todo set iterations limit depending on the number of iterations of the original problem root */
948 iterlim = nlpiters;
949 SCIP_CALL( SCIPsetLongintParam(subscip, "lp/iterlim", MAX(1, iterlim / MIN(10, nnodes))) );
950 SCIP_CALL( SCIPsetLongintParam(subscip, "lp/rootiterlim", iterlim) );
951
952 /* catch LP events of sub-SCIP */
953 SCIP_CALL( SCIPtransformProb(subscip) );
954 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_NODESOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
955
956 SCIPstatisticMessage("solving subproblem at Node: %" SCIP_LONGINT_FORMAT " "
957 "nnodes: %" SCIP_LONGINT_FORMAT " "
958 "iterlim: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNNodes(scip), nnodes, iterlim);
959
960 /* solve the subproblem with all previously adjusted parameters */
961 nfixedvars = SCIPgetNFixedVars(subscip);
962
963 SCIP_CALL( SCIPpresolve(subscip) );
964
965 nfixedvars = SCIPgetNFixedVars(subscip) - nfixedvars;
966 assert(nfixedvars >= 0);
967 SCIPstatisticMessage("presolve fixings %d: %d\n", ++(heurdata->subprobidx), nfixedvars);
968
969 /* errors in solving the subproblem should not kill the overall solving process;
970 * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
971 */
972 SCIP_CALL_ABORT( SCIPsolve(subscip) );
973
974 /* print solving statistics of subproblem if we are in SCIP's debug mode */
976 SCIPstatisticMessage("solve of subscip %d:"
977 "usednodes: %" SCIP_LONGINT_FORMAT " "
978 "lp iters: %" SCIP_LONGINT_FORMAT " "
979 "root iters: %" SCIP_LONGINT_FORMAT " "
980 "Presolving Time: %.2f\n", heurdata->subprobidx,
982
983 SCIPstatisticMessage("Solving Time %d: %.2f\n", heurdata->subprobidx, SCIPgetSolvingTime(subscip) );
984
985 /* drop LP events of sub-SCIP */
986 SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_NODESOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
987
988 /* keep track of relevant information for future runs of heuristic */
989 if( nusednodes != NULL )
990 *nusednodes = SCIPgetNNodes(subscip);
991 if( nusedlpiters != NULL )
992 *nusedlpiters = SCIPgetNLPIterations(subscip);
993
994 /* check whether a solution was found */
995 nsubsols = SCIPgetNSols(subscip);
996 incumbent = SCIPgetBestSol(subscip);
997 assert(nsubsols == 0 || incumbent != NULL);
998
999 SCIPstatisticMessage("primal bound before subproblem %d: %g\n", heurdata->subprobidx, SCIPgetPrimalbound(scip));
1000 if( nsubsols > 0 )
1001 {
1002 /* try to translate the sub problem solution to the original scip instance */
1003 success = FALSE;
1004 SCIP_CALL( createNewSol(scip, subscip, subvars, heur, incumbent, heurdata->usefinallp, &success) );
1005
1006 if( success )
1007 *result = SCIP_FOUNDSOL;
1008 }
1009 SCIPstatisticMessage("primal bound after subproblem %d: %g\n", heurdata->subprobidx, SCIPgetPrimalbound(scip));
1010
1011 /* free the transformed subproblem data */
1012 SCIP_CALL( SCIPfreeTransform(subscip) );
1013
1014 /* save subproblem in heuristic data for subsequent runs if it has been successful, otherwise free subproblem */
1015 heurdata->subscip = subscip;
1016 heurdata->varmapfw = varmapfw;
1017 heurdata->subvars = subvars;
1018 heurdata->objcons = objcons;
1019 heurdata->nsubvars = nvars;
1020
1021 /* delete the sub problem */
1022 if( freesubscip )
1023 {
1024 SCIP_CALL( deleteSubproblem(scip, heurdata) );
1025 }
1026
1027 return SCIP_OKAY;
1028}
1029
1030
1031/** creates the proximity primal heuristic and includes it in SCIP */
1033 SCIP* scip /**< SCIP data structure */
1034 )
1035{
1036 SCIP_HEURDATA* heurdata;
1037 SCIP_HEUR* heur = NULL;
1038
1039 /* create heuristic data */
1040 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1041
1042 /* include primal heuristic */
1045 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecProximity, heurdata) );
1046 assert(heur != NULL);
1047
1048 /* primal heuristic is safe to use in exact solving mode */
1049 SCIPheurMarkExact(heur);
1050
1051 /* set non-NULL pointers to callback methods */
1052 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyProximity) );
1053 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeProximity) );
1054 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitProximity) );
1055 SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolProximity) );
1056
1057 /* add proximity primal heuristic parameters */
1058 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
1059 "should subproblem be constructed based on LP row information?",
1060 &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
1061
1062 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/restart",
1063 "should the heuristic immediately run again on its newly found solution?",
1064 &heurdata->restart, TRUE, DEFAULT_RESTART, NULL, NULL) );
1065
1066 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usefinallp",
1067 "should the heuristic solve a final LP in case of continuous objective variables?",
1068 &heurdata->usefinallp, TRUE, DEFAULT_USEFINALLP, NULL, NULL) );
1069
1070 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1071 "maximum number of nodes to regard in the subproblem",
1072 &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1073
1074 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1075 "number of nodes added to the contingent of the total nodes",
1076 &heurdata->nodesofs, TRUE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1077
1078 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1079 "minimum number of nodes required to start the subproblem",
1080 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1081
1082 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxlpiters",
1083 "maximum number of LP iterations to be performed in the subproblem",
1084 &heurdata->maxlpiters, TRUE, DEFAULT_MAXLPITERS, -1LL, SCIP_LONGINT_MAX, NULL, NULL) );
1085
1086 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minlpiters",
1087 "minimum number of LP iterations performed in subproblem",
1088 &heurdata->minlpiters, TRUE, DEFAULT_MINLPITERS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1089
1090 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/waitingnodes",
1091 "waiting nodes since last incumbent before heuristic is executed",
1092 &heurdata->waitingnodes, TRUE, DEFAULT_WAITINGNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1093
1094 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1095 "factor by which proximity should at least improve the incumbent",
1096 &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1097
1098 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1099 "sub-MIP node limit w.r.t number of original nodes",
1100 &heurdata->nodesquot, TRUE, DEFAULT_NODESQUOT, 0.0, SCIPinfinity(scip), NULL, NULL) );
1101
1102 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/binvarquot",
1103 "threshold for percentage of binary variables required to start",
1104 &heurdata->binvarquot, TRUE, DEFAULT_BINVARQUOT, 0.0, 1.0, NULL, NULL) );
1105
1106 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lpitersquot",
1107 "quotient of sub-MIP LP iterations with respect to LP iterations so far",
1108 &heurdata->lpitersquot, TRUE, DEFAULT_LPITERSQUOT, 0.0, 1.0, NULL, NULL) );
1109
1110 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/mingap",
1111 "minimum primal-dual gap for which the heuristic is executed",
1112 &heurdata->mingap, TRUE, DEFAULT_MINGAP, 0.0, SCIPinfinity(scip), NULL, NULL) );
1113
1114 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useuct",
1115 "should uct node selection be used at the beginning of the search?",
1116 &heurdata->useuct, TRUE, DEFAULT_USEUCT, NULL, NULL) );
1117
1118 return SCIP_OKAY;
1119}
Constraint handler for linear constraints in their most general form, .
#define NULL
Definition: def.h:248
#define SCIP_Longint
Definition: def.h:141
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#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 SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define REALABS(x)
Definition: def.h:182
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define SCIP_CALL(x)
Definition: def.h:355
#define nnodes
Definition: gastrans.c:74
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip_copy.c:3249
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip_copy.c:3292
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:402
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:370
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2616
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
SCIP_Real SCIPgetObjNorm(SCIP *scip)
Definition: scip_prob.c:1880
int SCIPgetNFixedVars(SCIP *scip)
Definition: scip_prob.c:2705
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2293
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip_prob.c:1801
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPdeleteSubproblemProximity(SCIP *scip)
SCIP_RETCODE SCIPapplyProximity(SCIP *scip, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_Real minimprove, SCIP_Longint nnodes, SCIP_Longint nlpiters, SCIP_Longint *nusednodes, SCIP_Longint *nusedlpiters, SCIP_Bool freesubscip)
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:111
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip_param.c:219
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 SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip_param.c:904
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 SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:985
SCIP_RETCODE SCIPincludeHeurProximity(SCIP *scip)
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip_branch.c:304
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_EVENTHDLR * SCIPfindEventhdlr(SCIP *scip, const char *name)
Definition: scip_event.c:241
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1194
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:293
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:333
SCIP_Bool SCIPisExact(SCIP *scip)
Definition: scip_exact.c:193
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_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition: scip_heur.c:263
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition: heur.c:1457
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:199
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1467
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1378
SCIP_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_lp.c:2384
SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_lp.c:2416
SCIP_RETCODE SCIPstartDive(SCIP *scip)
Definition: scip_lp.c:2206
SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip_lp.c:2643
SCIP_RETCODE SCIPendDive(SCIP *scip)
Definition: scip_lp.c:2255
SCIP_Bool SCIPinDive(SCIP *scip)
Definition: scip_lp.c:2740
SCIP_Bool SCIPisLPConstructed(SCIP *scip)
Definition: scip_lp.c:105
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 SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip_nodesel.c:242
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2981
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:516
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1252
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:4239
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_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:4140
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition: sol.c:4290
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_sol.c:1662
SCIP_RETCODE SCIPtrySol(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:4012
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1295
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1892
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
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 SCIPinterruptSolve(SCIP *scip)
Definition: scip_solve.c:3548
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2635
SCIP_Longint SCIPgetNSolsFound(SCIP *scip)
SCIP_Real SCIPgetPrimalbound(SCIP *scip)
SCIP_Real SCIPgetGap(SCIP *scip)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
SCIP_Longint SCIPgetNRootLPIterations(SCIP *scip)
SCIP_Longint SCIPgetNRootFirstLPIterations(SCIP *scip)
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_RETCODE SCIPcopyLargeNeighborhoodSearch(SCIP *sourcescip, SCIP *subscip, SCIP_HASHMAP *varmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool uselprows, SCIP_Bool copycuts, SCIP_Bool *success, SCIP_Bool *valid)
Definition: heuristics.c:953
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip_timing.c:378
SCIP_Real SCIPgetPresolvingTime(SCIP *scip)
Definition: scip_timing.c:442
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:6141
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
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_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:5372
static SCIP_RETCODE solveLp(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
static SCIP_DECL_HEURINIT(heurInitProximity)
#define DEFAULT_RESTART
#define DEFAULT_NODESQUOT
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEUR *heur, SCIP_SOL *subsol, SCIP_Bool usefinallp, SCIP_Bool *success)
#define DEFAULT_BINVARQUOT
#define DEFAULT_NODESOFS
#define DEFAULT_MINGAP
#define DEFAULT_USEFINALLP
#define DEFAULT_MAXNODES
static SCIP_RETCODE setupSubproblem(SCIP_HEURDATA *heurdata, SCIP *subscip)
#define HEUR_TIMING
#define DEFAULT_MINNODES
#define HEUR_FREQOFS
#define HEUR_DESC
#define DEFAULT_WAITINGNODES
#define DEFAULT_USEUCT
static SCIP_RETCODE deleteSubproblem(SCIP *scip, SCIP_HEURDATA *heurdata)
static SCIP_DECL_HEUREXITSOL(heurExitsolProximity)
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
#define DEFAULT_MINIMPROVE
#define HEUR_NAME
#define DEFAULT_USELPROWS
#define DEFAULT_LPITERSQUOT
static SCIP_DECL_HEUREXEC(heurExecProximity)
#define EVENTHDLR_DESC
#define HEUR_FREQ
#define DEFAULT_MAXLPITERS
static SCIP_DECL_HEURCOPY(heurCopyProximity)
#define HEUR_USESSUBSCIP
static SCIP_DECL_HEURFREE(heurFreeProximity)
#define EVENTHDLR_NAME
static SCIP_DECL_EVENTEXEC(eventExecProximity)
#define DEFAULT_MINLPITERS
improvement heuristic which uses an auxiliary objective instead of the original objective function wh...
methods commonly used by primal heuristics
memory allocation routines
public methods for managing events
public methods for primal heuristics
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPstatisticMessage
Definition: pub_message.h:123
#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
public methods for exact solving
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 node selector plugins
public methods for numerical tolerances
public methods for SCIP parameter handling
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
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:179
#define SCIP_EVENTTYPE_NODESOLVED
Definition: type_event.h:138
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:77
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:44
@ SCIP_LPSOLSTAT_ITERLIMIT
Definition: type_lp.h:48
@ SCIP_PARAMSETTING_OFF
Definition: type_paramset.h:63
@ SCIP_PARAMSETTING_FAST
Definition: type_paramset.h:62
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ 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_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:53