Scippy

SCIP

Solving Constraint Integer Programs

heur_trustregion.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_trustregion.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief Large neighborhood search heuristic for Benders' decomposition based on trust region methods
28 * @author Stephen J. Maher
29 *
30 * The Trust Region heuristic draws upon trust region methods for solving optimization problems, especially in the
31 * context of Benders' decomposition. This heuristic has been developed to improve the heuristic performance of the
32 * Benders' decomposition algorithm within SCIP.
33 *
34 * The Trust Region heuristic copies the original SCIP instance and adds a constraint to penalize changes from the
35 * incumbent solution. Consider a problem that includes a set of binary variables \f$\mathcal{B}\f$. Given a feasible
36 * solution \f$\hat{x}\f$ to the original problem, we define the set \f$\mathcal{B}^{+}\f$ as the index set for the
37 * binary variables that are 1 in the input solution and \f$\mathcal{B}^{-}\f$ as the index set for binary variables
38 * that are 0. The trust region constraint, which is added to the sub-SCIP, is given by
39 *
40 * \f[
41 * \sum_{i \in \mathcal{B}^{+}}(1 - x_{i}) + \sum_{i \in \mathcal{B}^{-}}x_{i} \le \theta
42 * \f]
43 *
44 * The variable \f$\theta\f$ measure the distance, in terms of the binary variables, of candidate solutions to the input
45 * solution.
46 *
47 * In addition, an upper bounding constraint is explicitly added to enforce a minimum improvement from the heuristic,
48 * given by \f$f(x) \le f(\hat{x}) - \epsilon\f$. The parameter \f$\epsilon \ge 0\f$ denotes the minimum improvement
49 * that must be achieved by the heuristic.
50 *
51 * The objective function is then modified to \f$f(x) + M\theta\f$, where \f$M\f$ is a parameter for penalizing the
52 * distance of solutions from the input solution \f$\hat{x}\f$.
53 *
54 * If a new incumbent solution is found by this heuristic, then the Trust Region heuristic is immediately
55 * re-executed with this new incumbent solution.
56 */
57
58/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
59
61#include "scip/cons_linear.h"
62#include "scip/heuristics.h"
64#include "scip/pub_event.h"
65#include "scip/pub_heur.h"
66#include "scip/pub_message.h"
67#include "scip/pub_misc.h"
68#include "scip/pub_sol.h"
69#include "scip/pub_var.h"
70#include "scip/scip_branch.h"
71#include "scip/scip_cons.h"
72#include "scip/scip_copy.h"
73#include "scip/scip_event.h"
74#include "scip/scip_general.h"
75#include "scip/scip_heur.h"
76#include "scip/scip_mem.h"
77#include "scip/scip_message.h"
78#include "scip/scip_nodesel.h"
79#include "scip/scip_numerics.h"
80#include "scip/scip_param.h"
81#include "scip/scip_prob.h"
82#include "scip/scip_sol.h"
83#include "scip/scip_solve.h"
85#include "scip/scip_var.h"
86#include <string.h>
87
88#define HEUR_NAME "trustregion"
89#define HEUR_DESC "LNS heuristic for Benders' decomposition based on trust region methods"
90#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
91#define HEUR_PRIORITY -1102010
92#define HEUR_FREQ -1
93#define HEUR_FREQOFS 0
94#define HEUR_MAXDEPTH -1
95#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
96#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
97
98#define DEFAULT_MINBINVARS 10 /**< the minimum number of binary variables necessary to run the heuristic */
99#define DEFAULT_NODESOFS 1000 /**< number of nodes added to the contingent of the total nodes */
100#define DEFAULT_MAXNODES 10000 /**< maximum number of nodes to regard in the subproblem */
101#define DEFAULT_MINNODES 100 /**< minimum number of nodes required to start the subproblem */
102#define DEFAULT_NODESQUOT 0.05 /**< contingent of sub problem nodes in relation to original nodes */
103#define DEFAULT_LPLIMFAC 1.5 /**< factor by which the limit on the number of LP depends on the node limit */
104#define DEFAULT_NWAITINGNODES 1 /**< number of nodes without incumbent change that heuristic should wait */
105#define DEFAULT_USELPROWS FALSE /**< should subproblem be created out of the rows in the LP rows,
106 * otherwise, the copy constructors of the constraints handlers are used */
107#define DEFAULT_COPYCUTS TRUE /**< if DEFAULT_USELPROWS is FALSE, then should all active cuts from the cutpool
108 * of the original scip be copied to constraints of the subscip */
109#define DEFAULT_BESTSOLLIMIT 3 /**< limit on number of improving incumbent solutions in sub-CIP */
110
111#define DEFAULT_VIOLPENALTY 100.0 /**< the penalty for violating the trust region */
112#define DEFAULT_OBJMINIMPROVE 1e-2 /**< the minimum absolute improvement in the objective function value */
113
114/* event handler properties */
115#define EVENTHDLR_NAME "Trustregion"
116#define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
117
118
119#define EXECUTE 0
120#define WAITFORNEWSOL 1
121
122
123/*
124 * Data structures
125 */
126
127/** primal heuristic data */
128struct SCIP_HeurData
129{
130 SCIP_SOL* lastsol; /**< the last incumbent trustregion used as reference point */
131 SCIP_Longint usednodes; /**< amount of nodes trust region used during all calls */
132 SCIP_Real nodesquot; /**< contingent of sub problem nodes in relation to original nodes */
133 SCIP_Real nodelimit; /**< the nodelimit employed in the current sub-SCIP, for the event handler*/
134 SCIP_Real lplimfac; /**< factor by which the limit on the number of LP depends on the node limit */
135 SCIP_Real violpenalty; /**< the penalty for violating the trust region */
136 SCIP_Real objminimprove; /**< the minimum absolute improvement in the objective function value */
137 int nwaitingnodes; /**< number of nodes without incumbent change that heuristic should wait */
138 int nodesofs; /**< number of nodes added to the contingent of the total nodes */
139 int minnodes; /**< minimum number of nodes required to start the subproblem */
140 int maxnodes; /**< maximum number of nodes to regard in the subproblem */
141 int minbinvars; /**< minimum number of binary variables necessary to run the heuristic */
142 int callstatus; /**< current status of trustregion heuristic */
143 int curminnodes; /**< current minimal number of nodes required to start the subproblem */
144 int bestsollimit; /**< limit on number of improving incumbent solutions in sub-CIP */
145 SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
146 SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
147 * to constraints in subproblem? */
148};
149
150
151/*
152 * Local methods
153 */
154
155/** create the extra constraint of trust region and add it to \p subscip */
156static
158 SCIP* scip, /**< SCIP data structure of the original problem */
159 SCIP* subscip, /**< SCIP data structure of the subproblem */
160 SCIP_VAR** subvars, /**< variables of the subproblem */
161 SCIP_HEURDATA* heurdata /**< heuristic's data structure */
162 )
163{
164 SCIP_CONS* cons; /* trust region constraint to create */
165 SCIP_VAR** consvars;
166 SCIP_VAR** vars;
167 SCIP_SOL* bestsol;
168
169 int nvars;
170 int nbinvars;
171 int nconsvars;
172 int i;
173 SCIP_Real lhs;
174 SCIP_Real rhs;
175 SCIP_Real* consvals;
176 char name[SCIP_MAXSTRLEN];
177
178 /* adding the neighborhood constraint for the trust region heuristic */
179 SCIP_CALL( SCIPaddTrustregionNeighborhoodConstraint(scip, subscip, subvars, heurdata->violpenalty) );
180
181 /* get the data of the variables and the best solution */
182 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, NULL, NULL, NULL) );
183 bestsol = SCIPgetBestSol(scip);
184 assert( bestsol != NULL );
185
186 /* memory allocation */
187 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nvars + 1) );
188 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nvars + 1) );
189 nconsvars = 0;
190
191 /* create the upper bounding constraint. An absolute minimum improvement is used for this heuristic. This is
192 * different to other LNS heuristics, where a relative improvement is used. The absolute improvement tries to take
193 * into account problem specific information that is available to the user, such as a minimum step in the objective
194 * limit if the objective function is integer
195 */
196 lhs = -SCIPinfinity(subscip);
197 rhs = SCIPgetSolTransObj(scip, bestsol) - heurdata->objminimprove;
198
199 /* if the objective function is integer, then the floor of the RHS is taken */
201 rhs = SCIPfeasFloor(scip, rhs);
202
203 /* adding the coefficients to the upper bounding constraint */
204 for( i = 0; i < nvars; i++ )
205 {
206 if( subvars[i] == NULL )
207 continue;
208 consvals[nconsvars] = SCIPvarGetObj(subvars[i]);
209 consvars[nconsvars] = subvars[i];
210 ++nconsvars;
211 }
212
213 /* creates trustregion constraint and adds it to subscip */
214 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_upperboundcons", SCIPgetProbName(scip));
215
216 SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, name, nconsvars, consvars, consvals,
217 lhs, rhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
218 SCIP_CALL( SCIPaddCons(subscip, cons) );
219 SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
220
221 /* free local memory */
222 SCIPfreeBufferArray(scip, &consvals);
223 SCIPfreeBufferArray(scip, &consvars);
224
225 return SCIP_OKAY;
226}
227
228
229/* ---------------- Callback methods of event handler ---------------- */
230
231/** event handler execution callback to interrupt the solution process */
232static
233SCIP_DECL_EVENTEXEC(eventExecTrustregion)
234{
235 SCIP_HEURDATA* heurdata;
236
237 assert(eventhdlr != NULL);
238 assert(eventdata != NULL);
239 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
240 assert(event != NULL);
242
243 heurdata = (SCIP_HEURDATA*)eventdata;
244 assert(heurdata != NULL);
245
246 /* interrupt solution process of sub-SCIP */
247 if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
248 {
249 SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n",SCIPgetNLPs(scip));
251 }
252
253 return SCIP_OKAY;
254}
255
256
257/*
258 * Callback methods of primal heuristic
259 */
260
261/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
262static
263SCIP_DECL_HEURCOPY(heurCopyTrustregion)
264{ /*lint --e{715}*/
265 assert(scip != NULL);
266 assert(heur != NULL);
267 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
268
269 /* call inclusion method of primal heuristic */
271
272 return SCIP_OKAY;
273}
274
275/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
276static
277SCIP_DECL_HEURFREE(heurFreeTrustregion)
278{ /*lint --e{715}*/
279 SCIP_HEURDATA* heurdata;
280
281 assert( heur != NULL );
282 assert( scip != NULL );
283
284 /* get heuristic data */
285 heurdata = SCIPheurGetData(heur);
286 assert( heurdata != NULL );
287
288 /* free heuristic data */
289 SCIPfreeBlockMemory(scip, &heurdata);
290 SCIPheurSetData(heur, NULL);
291
292 return SCIP_OKAY;
293}
294
295
296/** initialization method of primal heuristic (called after problem was transformed) */
297static
298SCIP_DECL_HEURINIT(heurInitTrustregion)
299{ /*lint --e{715}*/
300 SCIP_HEURDATA* heurdata;
301
302 assert( heur != NULL );
303 assert( scip != NULL );
304
305 /* get heuristic's data */
306 heurdata = SCIPheurGetData(heur);
307 assert( heurdata != NULL );
308
309 /* with a little abuse we initialize the heurdata as if trustregion would have finished its last step regularly */
310 heurdata->callstatus = WAITFORNEWSOL;
311 heurdata->lastsol = NULL;
312 heurdata->usednodes = 0;
313 heurdata->curminnodes = heurdata->minnodes;
314
315 return SCIP_OKAY;
316}
317
318/** sets up and solves the sub SCIP for the Trust Region heuristic */
319static
321 SCIP* scip, /**< SCIP data structure */
322 SCIP* subscip, /**< the subproblem created by trustregion */
323 SCIP_HEUR* heur, /**< trustregion heuristic */
324 SCIP_Longint nsubnodes, /**< nodelimit for subscip */
325 SCIP_RESULT* result /**< result pointer */
326 )
327{
328 SCIP_VAR** subvars;
329 SCIP_EVENTHDLR* eventhdlr;
330 SCIP_HEURDATA* heurdata;
331 SCIP_HASHMAP* varmapfw;
332 SCIP_VAR** vars;
333
334 int nvars;
335 int i;
336
337 SCIP_Bool success;
338
339 assert(scip != NULL);
340 assert(subscip != NULL);
341 assert(heur != NULL);
342
343 heurdata = SCIPheurGetData(heur);
344 assert(heurdata != NULL);
345
346 /* get the data of the variables and the best solution */
347 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
348
349 /* create the variable mapping hash map */
350 SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
351 success = FALSE;
352
353 /* create a problem copy as sub SCIP */
354 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "trustregion", NULL, NULL, 0, heurdata->uselprows,
355 heurdata->copycuts, &success, NULL) );
356
357 SCIPdebugMsg(scip, "Copying SCIP was %s successful.\n", success ? "" : "not ");
358
359 /* if the subproblem could not be created, free memory and return */
360 if( !success )
361 {
362 *result = SCIP_DIDNOTRUN;
363 goto TERMINATE;
364 }
365
366 /* create event handler for LP events */
367 eventhdlr = NULL;
368 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecTrustregion, NULL) );
369 if( eventhdlr == NULL )
370 {
371 /* free hash map */
372 SCIPhashmapFree(&varmapfw);
373
374 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
375 return SCIP_PLUGINNOTFOUND;
376 }
377
378 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
379 for (i = 0; i < nvars; ++i)
380 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
381
382 /* free hash map */
383 SCIPhashmapFree(&varmapfw);
384
385 heurdata->nodelimit = nsubnodes;
386 SCIP_CALL( SCIPsetCommonSubscipParams(scip, subscip, nsubnodes, MAX(10, nsubnodes/10), heurdata->bestsollimit) );
387
388 SCIP_CALL( addTrustRegionConstraints(scip, subscip, subvars, heurdata) );
389
390 /* catch LP events of sub-SCIP */
391 if( !heurdata->uselprows )
392 {
393 assert(eventhdlr != NULL);
394
395 SCIP_CALL( SCIPtransformProb(subscip) );
396 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
397 }
398
399 /* solve the subproblem */
400 SCIPdebugMsg(scip, "solving trust region subproblem with maxnodes %" SCIP_LONGINT_FORMAT "\n", nsubnodes);
401
402 SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/trysol/priority", 100000) );
403
404 /* Errors in solving the subproblem should not kill the overall solving process
405 * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
406 */
407 SCIP_CALL_ABORT( SCIPsolve(subscip) );
408
409 /* drop LP events of sub-SCIP */
410 if( !heurdata->uselprows )
411 {
412 assert(eventhdlr != NULL);
413
414 SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
415 }
416
417 /* print solving statistics of subproblem if we are in SCIP's debug mode */
419
420 heurdata->usednodes += SCIPgetNNodes(subscip);
421 SCIPdebugMsg(scip, "trust region used %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT " nodes\n",
422 SCIPgetNNodes(subscip), nsubnodes);
423
424 /* checks the solutions of the sub SCIP and adds them to the main SCIP if feasible */
425 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, &success, NULL) );
426
427 if( success )
428 *result = SCIP_FOUNDSOL;
429
430 /* checking the status of the subscip */
431 heurdata->callstatus = WAITFORNEWSOL;
434 {
435 heurdata->callstatus = EXECUTE;
436 heurdata->curminnodes *= 2;
437 }
438
439 TERMINATE:
440 /* free subproblem */
441 SCIPfreeBufferArray(scip, &subvars);
442
443 return SCIP_OKAY;
444}
445
446
447/** execution method of primal heuristic */
448static
449SCIP_DECL_HEUREXEC(heurExecTrustregion)
450{ /*lint --e{715}*/
451 SCIP_Longint maxnnodes;
452 SCIP_Longint nsubnodes;
453
454 SCIP_HEURDATA* heurdata;
455 SCIP* subscip;
456
457 SCIP_SOL* bestsol;
458
459 SCIP_Bool success;
460 SCIP_RETCODE retcode;
461
462 assert(heur != NULL);
463 assert(scip != NULL);
464 assert(result != NULL);
465
466 *result = SCIP_DIDNOTRUN;
467
468 /* get heuristic's data */
469 heurdata = SCIPheurGetData(heur);
470 assert( heurdata != NULL );
471
472 /* there should be enough binary variables that a trust region constraint makes sense */
473 if( SCIPgetNBinVars(scip) < heurdata->minbinvars )
474 return SCIP_OKAY;
475
476 *result = SCIP_DELAYED;
477
478 /* only call heuristic, if an IP solution is at hand */
479 if( SCIPgetNSols(scip) <= 0 )
480 return SCIP_OKAY;
481
482 bestsol = SCIPgetBestSol(scip);
483 assert(bestsol != NULL);
484
485 /* only call heuristic, if the best solution comes from transformed problem */
486 if( SCIPsolIsOriginal(bestsol) )
487 return SCIP_OKAY;
488
489 /* only call heuristic, if enough nodes were processed since last incumbent */
490 if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip, bestsol) < heurdata->nwaitingnodes)
491 return SCIP_OKAY;
492
493 /* only call heuristic, if the best solution does not come from trivial heuristic */
494 if( SCIPsolGetHeur(bestsol) != NULL && strcmp(SCIPheurGetName(SCIPsolGetHeur(bestsol)), "trivial") == 0 )
495 return SCIP_OKAY;
496
497 /* calculate the maximal number of branching nodes until heuristic is aborted */
498 maxnnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
499
500 /* reward trust region if it found solutions often.
501 * In this case, the trust region heuristic is designed for Benders' decomposition and solutions found may not be
502 * added by this heuristic but by trysol. So we don't reward finding best solutions, but finding any solution. */
503 maxnnodes = (SCIP_Longint)(maxnnodes * (1.0 + 2.0*(SCIPheurGetNSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur)+1.0)));
504 maxnnodes -= 100 * SCIPheurGetNCalls(heur); /* count the setup costs for the sub-MIP as 100 nodes */
505 maxnnodes += heurdata->nodesofs;
506
507 *result = SCIP_DIDNOTRUN;
508
509 /* we continue to execute the trust region heuristic until no new best solution is found */
510 do
511 {
512 SCIP_RESULT heurresult;
513
514 /* storing the best solution again since it is needed for the execution loop */
515 bestsol = SCIPgetBestSol(scip);
516
517 /* reset minnodes if new solution was found */
518 if( heurdata->lastsol != bestsol )
519 {
520 heurdata->curminnodes = heurdata->minnodes;
521 heurdata->callstatus = EXECUTE;
522 heurdata->lastsol = bestsol;
523 }
524
525 /* if no new solution was found and trust region also seems to fail, just keep on waiting */
526 if( heurdata->callstatus == WAITFORNEWSOL )
527 return SCIP_OKAY;
528
529 /* determine the node limit for the current process */
530 nsubnodes = maxnnodes - heurdata->usednodes;
531 nsubnodes = MIN(nsubnodes, heurdata->maxnodes);
532
533 /* check whether we have enough nodes left to call sub problem solving */
534 if( nsubnodes < heurdata->curminnodes )
535 return SCIP_OKAY;
536
537 if( SCIPisStopped(scip) )
538 return SCIP_OKAY;
539
540 /* check whether there is enough time and memory left */
541 SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
542
543 /* abort if no time is left or there is not enough memory to create a copy of SCIP */
544 if( !success )
545 return SCIP_OKAY;
546
547 heurresult = SCIP_DIDNOTFIND;
548
549 SCIPdebugMsg(scip, "running trust region heuristic ...\n");
550
551 SCIP_CALL( SCIPcreate(&subscip) );
552
553 retcode = setupAndSolveSubscipTrustregion(scip, subscip, heur, nsubnodes, &heurresult);
554
555 SCIP_CALL( SCIPfree(&subscip) );
556
557 /* if the result is FOUNDSOL, this means that a solution was found during a previous execution of the heuristic.
558 * So the heuristic result should only be updated if the result is not FOUNDSOL.
559 */
560 if( *result != SCIP_FOUNDSOL )
561 *result = heurresult;
562 }
563 while( bestsol != SCIPgetBestSol(scip) && retcode == SCIP_OKAY );
564
565 return retcode;
566}
567
568
569/*
570 * primal heuristic specific interface methods
571 */
572
573/** creates the trustregion primal heuristic and includes it in SCIP */
575 SCIP* scip /**< SCIP data structure */
576 )
577{
578 SCIP_HEURDATA* heurdata;
579 SCIP_HEUR* heur;
580
581 /* create Trustregion primal heuristic data */
582 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
583
584 /* include primal heuristic */
587 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecTrustregion, heurdata) );
588
589 assert(heur != NULL);
590
591 /* set non-NULL pointers to callback methods */
592 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyTrustregion) );
593 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeTrustregion) );
594 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitTrustregion) );
595
596 /* add trustregion primal heuristic parameters */
597 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
598 "number of nodes added to the contingent of the total nodes",
599 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0, INT_MAX, NULL, NULL) );
600
601 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minbinvars",
602 "the number of binary variables necessary to run the heuristic",
603 &heurdata->minbinvars, FALSE, DEFAULT_MINBINVARS, 1, INT_MAX, NULL, NULL) );
604
605 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
606 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
607 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
608
609 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
610 "factor by which the limit on the number of LP depends on the node limit",
611 &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
612
613 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minnodes",
614 "minimum number of nodes required to start the subproblem",
615 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0, INT_MAX, NULL, NULL) );
616
617 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
618 "maximum number of nodes to regard in the subproblem",
619 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0, INT_MAX, NULL, NULL) );
620
621 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
622 "number of nodes without incumbent change that heuristic should wait",
623 &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0, INT_MAX, NULL, NULL) );
624
625 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
626 "should subproblem be created out of the rows in the LP rows?",
627 &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
628
629 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
630 "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
631 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
632
633 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/bestsollimit",
634 "limit on number of improving incumbent solutions in sub-CIP",
635 &heurdata->bestsollimit, FALSE, DEFAULT_BESTSOLLIMIT, -1, INT_MAX, NULL, NULL) );
636
637 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/violpenalty",
638 "the penalty for each change in the binary variables from the candidate solution",
639 &heurdata->violpenalty, FALSE, DEFAULT_VIOLPENALTY, 0.0, SCIP_REAL_MAX, NULL, NULL) );
640
641 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/objminimprove",
642 "the minimum absolute improvement in the objective function value",
643 &heurdata->objminimprove, FALSE, DEFAULT_OBJMINIMPROVE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
644
645 return SCIP_OKAY;
646}
Constraint handler for linear constraints in their most general form, .
#define NULL
Definition: def.h:267
#define SCIP_MAXSTRLEN
Definition: def.h:288
#define SCIP_Longint
Definition: def.h:158
#define SCIP_REAL_MAX
Definition: def.h:174
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:243
#define SCIP_Real
Definition: def.h:173
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:239
#define SCIP_CALL_ABORT(x)
Definition: def.h:353
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
#define SCIP_CALL(x)
Definition: def.h:374
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, 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 SCIPtranslateSubSols(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_Bool *success, int *solindex)
Definition: scip_copy.c:1448
SCIP_RETCODE SCIPsetCommonSubscipParams(SCIP *sourcescip, SCIP *subscip, SCIP_Longint nsubnodes, SCIP_Longint nstallnodes, int bestsollimit)
Definition: scip_copy.c:3339
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip_copy.c:3253
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:724
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:339
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:307
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:498
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1067
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:1866
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip_prob.c:1562
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3108
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3261
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3074
#define SCIPdebugMsg
Definition: scip_message.h:78
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 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 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 SCIPincludeHeurTrustregion(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
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:324
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1030
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:286
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:320
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:162
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1364
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip_heur.c:117
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:178
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1589
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1579
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:194
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1453
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1374
#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 SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2169
int SCIPgetNSols(SCIP *scip)
Definition: scip_sol.c:2070
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2804
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2721
SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1513
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1347
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip_solve.c:222
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip_solve.c:3430
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2498
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
SCIP_Longint SCIPgetNLPs(SCIP *scip)
SCIP_RETCODE SCIPaddTrustregionNeighborhoodConstraint(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **subvars, SCIP_Real violpenalty)
Definition: heuristics.c:1029
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:951
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17926
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
#define EXECUTE
#define DEFAULT_NODESQUOT
static SCIP_DECL_HEURFREE(heurFreeTrustregion)
#define DEFAULT_NWAITINGNODES
#define DEFAULT_NODESOFS
#define DEFAULT_COPYCUTS
#define DEFAULT_MAXNODES
static SCIP_RETCODE setupAndSolveSubscipTrustregion(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_Longint nsubnodes, SCIP_RESULT *result)
#define HEUR_TIMING
#define DEFAULT_MINNODES
#define HEUR_FREQOFS
#define HEUR_DESC
static SCIP_DECL_HEURCOPY(heurCopyTrustregion)
#define DEFAULT_LPLIMFAC
static SCIP_RETCODE addTrustRegionConstraints(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEURDATA *heurdata)
#define WAITFORNEWSOL
#define DEFAULT_OBJMINIMPROVE
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
#define HEUR_NAME
#define DEFAULT_USELPROWS
#define DEFAULT_BESTSOLLIMIT
#define DEFAULT_VIOLPENALTY
static SCIP_DECL_HEUREXEC(heurExecTrustregion)
#define EVENTHDLR_DESC
static SCIP_DECL_HEURINIT(heurInitTrustregion)
static SCIP_DECL_EVENTEXEC(eventExecTrustregion)
#define HEUR_FREQ
#define HEUR_USESSUBSCIP
#define EVENTHDLR_NAME
#define DEFAULT_MINBINVARS
Large neighborhood search heuristic for Benders' decomposition based on trust region methods.
methods commonly used by primal heuristics
memory allocation routines
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
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 memory management
public methods for message handling
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 SCIP variables
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:101
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:77
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ 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_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STATUS_TOTALNODELIMIT
Definition: type_stat.h:45
@ SCIP_STATUS_STALLNODELIMIT
Definition: type_stat.h:48
@ SCIP_STATUS_NODELIMIT
Definition: type_stat.h:44