Scippy

SCIP

Solving Constraint Integer Programs

heur_alns.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_alns.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief Adaptive large neighborhood search heuristic that orchestrates popular LNS heuristics
28 * @author Gregor Hendel
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
34#include "scip/cons_linear.h"
35#include "scip/heur_alns.h"
36#include "scip/heuristics.h"
40#include "scip/pub_bandit.h"
41#include "scip/pub_bandit_ucb.h"
42#include "scip/pub_cons.h"
43#include "scip/pub_event.h"
44#include "scip/pub_heur.h"
45#include "scip/pub_message.h"
46#include "scip/pub_misc.h"
48#include "scip/pub_sol.h"
49#include "scip/pub_var.h"
50#include "scip/scip_bandit.h"
51#include "scip/scip_branch.h"
52#include "scip/scip_cons.h"
53#include "scip/scip_copy.h"
54#include "scip/scip_event.h"
55#include "scip/scip_general.h"
56#include "scip/scip_heur.h"
57#include "scip/scip_lp.h"
58#include "scip/scip_mem.h"
59#include "scip/scip_message.h"
60#include "scip/scip_nodesel.h"
61#include "scip/scip_numerics.h"
62#include "scip/scip_param.h"
63#include "scip/scip_prob.h"
65#include "scip/scip_sol.h"
66#include "scip/scip_solve.h"
68#include "scip/scip_table.h"
69#include "scip/scip_timing.h"
70#include "scip/scip_tree.h"
71#include "scip/scip_var.h"
72#include <string.h>
73
74#define HEUR_NAME "alns"
75#define HEUR_DESC "Large neighborhood search heuristic that orchestrates the popular neighborhoods Local Branching, RINS, RENS, DINS etc."
76#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
77#define HEUR_PRIORITY -1100500
78#define HEUR_FREQ 20
79#define HEUR_FREQOFS 0
80#define HEUR_MAXDEPTH -1
81#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE | SCIP_HEURTIMING_DURINGLPLOOP
82#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
83
84#define NNEIGHBORHOODS 9
85
86#define DEFAULT_SHOWNBSTATS FALSE /**< show statistics on neighborhoods? */
87
88/*
89 * limit parameters for sub-SCIPs
90 */
91#define DEFAULT_NODESQUOT 0.1
92#define DEFAULT_NODESQUOTMIN 0.0
93#define DEFAULT_NODESOFFSET 500LL
94#define DEFAULT_NSOLSLIM 3
95#define DEFAULT_MINNODES 50LL
96#define DEFAULT_MAXNODES 5000LL
97#define DEFAULT_WAITINGNODES 25LL /**< number of nodes since last incumbent solution that the heuristic should wait */
98#define DEFAULT_TARGETNODEFACTOR 1.05
99#define LRATEMIN 0.01 /**< lower bound for learning rate for target nodes and minimum improvement */
100#define LPLIMFAC 4.0
101#define DEFAULT_INITDURINGROOT FALSE
102#define DEFAULT_MAXCALLSSAMESOL -1 /**< number of allowed executions of the heuristic on the same incumbent solution */
103
104/*
105 * parameters for the minimum improvement
106 */
107#define DEFAULT_MINIMPROVELOW 0.01
108#define DEFAULT_MINIMPROVEHIGH 0.01
109#define MINIMPROVEFAC 1.5
110#define DEFAULT_STARTMINIMPROVE 0.01
111#define DEFAULT_ADJUSTMINIMPROVE FALSE
112#define DEFAULT_ADJUSTTARGETNODES TRUE /**< should the target nodes be dynamically adjusted? */
113
114/*
115 * bandit algorithm parameters
116 */
117#define DEFAULT_BESTSOLWEIGHT 1
118#define DEFAULT_BANDITALGO 'i' /**< the default bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy, exp.3-(i)x */
119#define DEFAULT_REWARDCONTROL 0.8 /**< reward control to increase the weight of the simple solution indicator and decrease the weight of the closed gap reward */
120#define DEFAULT_SCALEBYEFFORT TRUE /**< should the reward be scaled by the effort? */
121#define DEFAULT_RESETWEIGHTS TRUE /**< should the bandit algorithms be reset when a new problem is read? */
122#define DEFAULT_SUBSCIPRANDSEEDS FALSE /**< should random seeds of sub-SCIPs be altered to increase diversification? */
123#define DEFAULT_REWARDBASELINE 0.5 /**< the reward baseline to separate successful and failed calls */
124#define DEFAULT_FIXTOL 0.1 /**< tolerance by which the fixing rate may be missed without generic fixing */
125#define DEFAULT_UNFIXTOL 0.1 /**< tolerance by which the fixing rate may be exceeded without generic unfixing */
126#define DEFAULT_USELOCALREDCOST FALSE /**< should local reduced costs be used for generic (un)fixing? */
127#define DEFAULT_BETA 0.0 /**< default reward offset between 0 and 1 at every observation for exp3 */
128
129/*
130 * the following 3 parameters have been tuned by a simulation experiment
131 * as described in the paper.
132 */
133#define DEFAULT_EPS 0.4685844 /**< increase exploration in epsilon-greedy bandit algorithm */
134#define DEFAULT_ALPHA 0.0016 /**< parameter to increase the confidence width in UCB */
135#define DEFAULT_GAMMA 0.07041455 /**< default weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3 */
136/*
137 * parameters to control variable fixing
138 */
139#define DEFAULT_USEREDCOST TRUE /**< should reduced cost scores be used for variable priorization? */
140#define DEFAULT_USEPSCOST TRUE /**< should pseudo cost scores be used for variable priorization? */
141#define DEFAULT_USEDISTANCES TRUE /**< should distances from fixed variables be used for variable priorization */
142#define DEFAULT_DOMOREFIXINGS TRUE /**< should the ALNS heuristic do more fixings by itself based on variable prioritization
143 * until the target fixing rate is reached? */
144#define DEFAULT_ADJUSTFIXINGRATE TRUE /**< should the heuristic adjust the target fixing rate based on the success? */
145#define FIXINGRATE_DECAY 0.75 /**< geometric decay for fixing rate adjustments */
146#define FIXINGRATE_STARTINC 0.2 /**< initial increment value for fixing rate */
147#define DEFAULT_USESUBSCIPHEURS FALSE /**< should the heuristic activate other sub-SCIP heuristics during its search? */
148#define DEFAULT_COPYCUTS FALSE /**< should cutting planes be copied to the sub-SCIP? */
149#define DEFAULT_REWARDFILENAME "-" /**< file name to store all rewards and the selection of the bandit */
150
151/* individual random seeds */
152#define DEFAULT_SEED 113
153#define MUTATIONSEED 121
154#define CROSSOVERSEED 321
155
156/* individual neighborhood parameters */
157#define DEFAULT_MINFIXINGRATE_RENS 0.3
158#define DEFAULT_MAXFIXINGRATE_RENS 0.9
159#define DEFAULT_ACTIVE_RENS TRUE
160#define DEFAULT_PRIORITY_RENS 1.0
161
162#define DEFAULT_MINFIXINGRATE_RINS 0.3
163#define DEFAULT_MAXFIXINGRATE_RINS 0.9
164#define DEFAULT_ACTIVE_RINS TRUE
165#define DEFAULT_PRIORITY_RINS 1.0
166
167#define DEFAULT_MINFIXINGRATE_MUTATION 0.3
168#define DEFAULT_MAXFIXINGRATE_MUTATION 0.9
169#define DEFAULT_ACTIVE_MUTATION TRUE
170#define DEFAULT_PRIORITY_MUTATION 1.0
171
172#define DEFAULT_MINFIXINGRATE_LOCALBRANCHING 0.3
173#define DEFAULT_MAXFIXINGRATE_LOCALBRANCHING 0.9
174#define DEFAULT_ACTIVE_LOCALBRANCHING TRUE
175#define DEFAULT_PRIORITY_LOCALBRANCHING 1.0
176
177#define DEFAULT_MINFIXINGRATE_PROXIMITY 0.3
178#define DEFAULT_MAXFIXINGRATE_PROXIMITY 0.9
179#define DEFAULT_ACTIVE_PROXIMITY TRUE
180#define DEFAULT_PRIORITY_PROXIMITY 1.0
181
182#define DEFAULT_MINFIXINGRATE_CROSSOVER 0.3
183#define DEFAULT_MAXFIXINGRATE_CROSSOVER 0.9
184#define DEFAULT_ACTIVE_CROSSOVER TRUE
185#define DEFAULT_PRIORITY_CROSSOVER 1.0
186
187#define DEFAULT_MINFIXINGRATE_ZEROOBJECTIVE 0.3
188#define DEFAULT_MAXFIXINGRATE_ZEROOBJECTIVE 0.9
189#define DEFAULT_ACTIVE_ZEROOBJECTIVE TRUE
190#define DEFAULT_PRIORITY_ZEROOBJECTIVE 1.0
191
192#define DEFAULT_MINFIXINGRATE_DINS 0.3
193#define DEFAULT_MAXFIXINGRATE_DINS 0.9
194#define DEFAULT_ACTIVE_DINS TRUE
195#define DEFAULT_PRIORITY_DINS 1.0
196
197#define DEFAULT_MINFIXINGRATE_TRUSTREGION 0.3
198#define DEFAULT_MAXFIXINGRATE_TRUSTREGION 0.9
199#define DEFAULT_ACTIVE_TRUSTREGION FALSE
200#define DEFAULT_PRIORITY_TRUSTREGION 1.0
201
202
203#define DEFAULT_NSOLS_CROSSOVER 2 /**< parameter for the number of solutions that crossover should combine */
204#define DEFAULT_NPOOLSOLS_DINS 5 /**< number of pool solutions where binary solution values must agree */
205#define DEFAULT_VIOLPENALTY_TRUSTREGION 100.0 /**< the penalty for violating the trust region */
206
207/* event handler properties */
208#define EVENTHDLR_NAME "Alns"
209#define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
210#define SCIP_EVENTTYPE_ALNS (SCIP_EVENTTYPE_LPSOLVED | SCIP_EVENTTYPE_SOLFOUND | SCIP_EVENTTYPE_BESTSOLFOUND)
211
212/* properties of the ALNS neighborhood statistics table */
213#define TABLE_NAME_NEIGHBORHOOD "neighborhood"
214#define TABLE_DESC_NEIGHBORHOOD "ALNS neighborhood statistics"
215#define TABLE_POSITION_NEIGHBORHOOD 12500 /**< the position of the statistics table */
216#define TABLE_EARLIEST_STAGE_NEIGHBORHOOD SCIP_STAGE_TRANSFORMED /**< output of the statistics table is only printed from this stage onwards */
217
218/** reward types of ALNS */
220 REWARDTYPE_TOTAL, /**< combination of the other rewards */
221 REWARDTYPE_BESTSOL, /**< 1, if a new solution was found, 0 otherwise */
222 REWARDTYPE_CLOSEDGAP, /**< 0 if no solution was found, closed gap otherwise */
223 REWARDTYPE_NOSOLPENALTY, /**< 1 if a solution was found, otherwise between 0 and 1 depending on the effort spent */
226
227/*
228 * Data structures
229 */
230
231/*
232 * additional neighborhood data structures
233 */
234
235
236typedef struct data_crossover DATA_CROSSOVER; /**< crossover neighborhood data structure */
237
238typedef struct data_mutation DATA_MUTATION; /**< mutation neighborhood data structure */
239
240typedef struct data_dins DATA_DINS; /**< dins neighborhood data structure */
241
242typedef struct data_trustregion DATA_TRUSTREGION; /**< trustregion neighborhood data structure */
243
244typedef struct NH_FixingRate NH_FIXINGRATE; /** fixing rate data structure */
245
246typedef struct NH_Stats NH_STATS; /**< neighborhood statistics data structure */
247
248typedef struct Nh NH; /**< neighborhood data structure */
249
250
251/*
252 * variable priorization data structure for sorting
253 */
254typedef struct VarPrio VARPRIO;
255
256/** callback to collect variable fixings of neighborhood */
257 #define DECL_VARFIXINGS(x) SCIP_RETCODE x ( \
258 SCIP* scip, /**< SCIP data structure */ \
259 NH* neighborhood, /**< ALNS neighborhood data structure */ \
260 SCIP_VAR** varbuf, /**< buffer array to collect variables to fix */\
261 SCIP_Real* valbuf, /**< buffer array to collect fixing values */ \
262 int* nfixings, /**< pointer to store the number of fixings */ \
263 SCIP_RESULT* result /**< result pointer */ \
264 )
265
266/** callback for subproblem changes other than variable fixings
267 *
268 * this callback can be used to further modify the subproblem by changes other than variable fixings.
269 * Typical modifications include restrictions of variable domains, the formulation of additional constraints,
270 * or changed objective coefficients.
271 *
272 * The callback should set the \p success pointer to indicate whether it was successful with its modifications or not.
273 */
274#define DECL_CHANGESUBSCIP(x) SCIP_RETCODE x ( \
275 SCIP* sourcescip, /**< source SCIP data structure */\
276 SCIP* targetscip, /**< target SCIP data structure */\
277 NH* neighborhood, /**< ALNS neighborhood data structure */\
278 SCIP_VAR** subvars, /**< array of targetscip variables in the same order as the source SCIP variables */\
279 int* ndomchgs, /**< pointer to store the number of performed domain changes */\
280 int* nchgobjs, /**< pointer to store the number of changed objective coefficients */ \
281 int* naddedconss, /**< pointer to store the number of additional constraints */\
282 SCIP_Bool* success /**< pointer to store if the sub-MIP was successfully adjusted */\
283 )
284
285/** optional initialization callback for neighborhoods when a new problem is read */
286#define DECL_NHINIT(x) SCIP_RETCODE x ( \
287 SCIP* scip, /**< SCIP data structure */ \
288 NH* neighborhood /**< neighborhood data structure */ \
289 )
290
291/** deinitialization callback for neighborhoods when exiting a problem */
292#define DECL_NHEXIT(x) SCIP_RETCODE x ( \
293 SCIP* scip, /**< SCIP data structure */ \
294 NH* neighborhood /**< neighborhood data structure */ \
295 )
296
297/** deinitialization callback for neighborhoods before SCIP is freed */
298#define DECL_NHFREE(x) SCIP_RETCODE x ( \
299 SCIP* scip, /**< SCIP data structure */ \
300 NH* neighborhood /**< neighborhood data structure */ \
301 )
302
303/** callback function to return a feasible reference solution for further fixings
304 *
305 * The reference solution should be stored in the \p solptr.
306 * The \p result pointer can be used to indicate either
307 *
308 * - SCIP_SUCCESS or
309 * - SCIP_DIDNOTFIND
310 */
311#define DECL_NHREFSOL(x) SCIP_RETCODE x ( \
312 SCIP* scip, /**< SCIP data structure */ \
313 NH* neighborhood, /**< neighborhood data structure */ \
314 SCIP_SOL** solptr, /**< pointer to store the reference solution */ \
315 SCIP_RESULT* result /**< pointer to indicate the callback success whether a reference solution is available */ \
316 )
317
318/** callback function to deactivate neighborhoods on problems where they are irrelevant */
319#define DECL_NHDEACTIVATE(x) SCIP_RETCODE x (\
320 SCIP* scip, /**< SCIP data structure */ \
321 SCIP_Bool* deactivate /**< pointer to store whether the neighborhood should be deactivated (TRUE) for an instance */ \
322 )
323
324/** sub-SCIP status code enumerator */
326{
327 HIDX_OPT = 0, /**< sub-SCIP was solved to optimality */
328 HIDX_USR = 1, /**< sub-SCIP was user interrupted */
329 HIDX_NODELIM = 2, /**< sub-SCIP reached the node limit */
330 HIDX_STALLNODE = 3, /**< sub-SCIP reached the stall node limit */
331 HIDX_INFEAS = 4, /**< sub-SCIP was infeasible */
332 HIDX_SOLLIM = 5, /**< sub-SCIP reached the solution limit */
333 HIDX_OTHER = 6 /**< sub-SCIP reached none of the above codes */
335typedef enum HistIndex HISTINDEX;
336#define NHISTENTRIES 7
337
338
339/** statistics for a neighborhood */
341{
342 SCIP_CLOCK* setupclock; /**< clock for sub-SCIP setup time */
343 SCIP_CLOCK* submipclock; /**< clock for the sub-SCIP solve */
344 SCIP_Longint usednodes; /**< total number of used nodes */
345 SCIP_Real oldupperbound; /**< upper bound before the sub-SCIP started */
346 SCIP_Real newupperbound; /**< new upper bound for allrewards mode to work correctly */
347 int nruns; /**< number of runs of a neighborhood */
348 int nrunsbestsol; /**< number of runs that produced a new incumbent */
349 SCIP_Longint nsolsfound; /**< the total number of solutions found */
350 SCIP_Longint nbestsolsfound; /**< the total number of improving solutions found */
351 int nfixings; /**< the number of fixings in one run */
352 int statushist[NHISTENTRIES]; /**< array to count sub-SCIP statuses */
353};
354
355
356/** fixing rate data structure to control the amount of target fixings of a neighborhood */
358{
359 SCIP_Real minfixingrate; /**< the minimum fixing rate */
360 SCIP_Real targetfixingrate; /**< the current target fixing rate */
361 SCIP_Real increment; /**< the current increment by which the target fixing rate is in-/decreased */
362 SCIP_Real maxfixingrate; /**< the maximum fixing rate */
363};
364
365/** neighborhood data structure with callbacks, statistics, fixing rate */
366struct Nh
367{
368 char* name; /**< the name of this neighborhood */
369 NH_FIXINGRATE fixingrate; /**< fixing rate for this neighborhood */
370 NH_STATS stats; /**< statistics for this neighborhood */
371 DECL_VARFIXINGS ((*varfixings)); /**< variable fixings callback for this neighborhood */
372 DECL_CHANGESUBSCIP ((*changesubscip)); /**< callback for subproblem changes other than variable fixings */
373 DECL_NHINIT ((*nhinit)); /**< initialization callback when a new problem is read */
374 DECL_NHEXIT ((*nhexit)); /**< deinitialization callback when exiting a problem */
375 DECL_NHFREE ((*nhfree)); /**< deinitialization callback before SCIP is freed */
376 DECL_NHREFSOL ((*nhrefsol)); /**< callback function to return a reference solution for further fixings, or NULL */
377 DECL_NHDEACTIVATE ((*nhdeactivate)); /**< callback function to deactivate neighborhoods on problems where they are irrelevant, or NULL if it is always active */
378 SCIP_Bool active; /**< is this neighborhood active or not? */
379 SCIP_Real priority; /**< positive call priority to initialize bandit algorithms */
380 union
381 {
382 DATA_MUTATION* mutation; /**< mutation data */
383 DATA_CROSSOVER* crossover; /**< crossover data */
384 DATA_DINS* dins; /**< dins data */
385 DATA_TRUSTREGION* trustregion; /**< trustregion data */
386 } data; /**< data object for neighborhood specific data */
387};
388
389/** mutation neighborhood data structure */
391{
392 SCIP_RANDNUMGEN* rng; /**< random number generator */
393};
394
395/** crossover neighborhood data structure */
397{
398 int nsols; /**< the number of solutions that crossover should combine */
399 SCIP_RANDNUMGEN* rng; /**< random number generator to draw from the solution pool */
400 SCIP_SOL* selsol; /**< best selected solution by crossover as reference point */
401};
402
403/** dins neighborhood data structure */
405{
406 int npoolsols; /**< number of pool solutions where binary solution values must agree */
407};
408
410{
411 SCIP_Real violpenalty; /**< the penalty for violating the trust region */
412};
413
414/** primal heuristic data */
415struct SCIP_HeurData
416{
417 NH** neighborhoods; /**< array of neighborhoods */
418 SCIP_BANDIT* bandit; /**< bandit algorithm */
419 SCIP_SOL* lastcallsol; /**< incumbent when the heuristic was last called */
420 char* rewardfilename; /**< file name to store all rewards and the selection of the bandit */
421 FILE* rewardfile; /**< reward file pointer, or NULL */
422 SCIP_Longint nodesoffset; /**< offset added to the nodes budget */
423 SCIP_Longint maxnodes; /**< maximum number of nodes in a single sub-SCIP */
424 SCIP_Longint targetnodes; /**< targeted number of nodes to start a sub-SCIP */
425 SCIP_Longint minnodes; /**< minimum number of nodes required to start a sub-SCIP */
426 SCIP_Longint usednodes; /**< total number of nodes already spent in sub-SCIPs */
427 SCIP_Longint waitingnodes; /**< number of nodes since last incumbent solution that the heuristic should wait */
428 SCIP_Real nodesquot; /**< fraction of nodes compared to the main SCIP for budget computation */
429 SCIP_Real nodesquotmin; /**< lower bound on fraction of nodes compared to the main SCIP for budget computation */
430 SCIP_Real startminimprove; /**< initial factor by which ALNS should at least improve the incumbent */
431 SCIP_Real minimprovelow; /**< lower threshold for the minimal improvement over the incumbent */
432 SCIP_Real minimprovehigh; /**< upper bound for the minimal improvement over the incumbent */
433 SCIP_Real minimprove; /**< factor by which ALNS should at least improve the incumbent */
434 SCIP_Real lplimfac; /**< limit fraction of LPs per node to interrupt sub-SCIP */
435 SCIP_Real exp3_gamma; /**< weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3 */
436 SCIP_Real exp3_beta; /**< reward offset between 0 and 1 at every observation for exp3 */
437 SCIP_Real epsgreedy_eps; /**< increase exploration in epsilon-greedy bandit algorithm */
438 SCIP_Real ucb_alpha; /**< parameter to increase the confidence width in UCB */
439 SCIP_Real rewardcontrol; /**< reward control to increase the weight of the simple solution indicator
440 * and decrease the weight of the closed gap reward */
441 SCIP_Real targetnodefactor; /**< factor by which target node number is eventually increased */
442 SCIP_Real rewardbaseline; /**< the reward baseline to separate successful and failed calls */
443 SCIP_Real fixtol; /**< tolerance by which the fixing rate may be missed without generic fixing */
444 SCIP_Real unfixtol; /**< tolerance by which the fixing rate may be exceeded without generic unfixing */
445 int nneighborhoods; /**< number of neighborhoods */
446 int nactiveneighborhoods;/**< number of active neighborhoods */
447 int ninitneighborhoods; /**< neighborhoods that were used at least one time */
448 int nsolslim; /**< limit on the number of improving solutions in a sub-SCIP call */
449 int seed; /**< initial random seed for bandit algorithms and random decisions by neighborhoods */
450 int currneighborhood; /**< index of currently selected neighborhood */
451 int ndelayedcalls; /**< the number of delayed calls */
452 int maxcallssamesol; /**< number of allowed executions of the heuristic on the same incumbent solution
453 * (-1: no limit, 0: number of active neighborhoods) */
454 SCIP_Longint firstcallthissol; /**< counter for the number of calls on this incumbent */
455 char banditalgo; /**< the bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy */
456 SCIP_Bool useredcost; /**< should reduced cost scores be used for variable prioritization? */
457 SCIP_Bool usedistances; /**< should distances from fixed variables be used for variable prioritization */
458 SCIP_Bool usepscost; /**< should pseudo cost scores be used for variable prioritization? */
459 SCIP_Bool domorefixings; /**< should the ALNS heuristic do more fixings by itself based on variable prioritization
460 * until the target fixing rate is reached? */
461 SCIP_Bool adjustfixingrate; /**< should the heuristic adjust the target fixing rate based on the success? */
462 SCIP_Bool usesubscipheurs; /**< should the heuristic activate other sub-SCIP heuristics during its search? */
463 SCIP_Bool adjustminimprove; /**< should the factor by which the minimum improvement is bound be dynamically updated? */
464 SCIP_Bool adjusttargetnodes; /**< should the target nodes be dynamically adjusted? */
465 SCIP_Bool resetweights; /**< should the bandit algorithms be reset when a new problem is read? */
466 SCIP_Bool subsciprandseeds; /**< should random seeds of sub-SCIPs be altered to increase diversification? */
467 SCIP_Bool scalebyeffort; /**< should the reward be scaled by the effort? */
468 SCIP_Bool copycuts; /**< should cutting planes be copied to the sub-SCIP? */
469 SCIP_Bool uselocalredcost; /**< should local reduced costs be used for generic (un)fixing? */
470 SCIP_Bool initduringroot; /**< should the heuristic be executed multiple times during the root node? */
471 SCIP_Bool shownbstats; /**< show statistics on neighborhoods? */
472};
473
474/** event handler data */
475struct SCIP_EventData
476{
477 SCIP_VAR** subvars; /**< the variables of the subproblem */
478 SCIP* sourcescip; /**< original SCIP data structure */
479 SCIP_HEUR* heur; /**< alns heuristic structure */
480 SCIP_Longint nodelimit; /**< node limit of the run */
481 SCIP_Real lplimfac; /**< limit fraction of LPs per node to interrupt sub-SCIP */
482 NH_STATS* runstats; /**< run statistics for the current neighborhood */
483 SCIP_Bool allrewardsmode; /**< true if solutions should only be checked for reward comparisons */
484};
485
486/** represents limits for the sub-SCIP solving process */
488{
489 SCIP_Longint nodelimit; /**< maximum number of solving nodes for the sub-SCIP */
490 SCIP_Real memorylimit; /**< memory limit for the sub-SCIP */
491 SCIP_Real timelimit; /**< time limit for the sub-SCIP */
492 SCIP_Longint stallnodes; /**< maximum number of nodes without (primal) stalling */
493};
494
496
497/** data structure that can be used for variable prioritization for additional fixings */
499{
500 SCIP* scip; /**< SCIP data structure */
501 SCIP_Real* randscores; /**< random scores for prioritization */
502 int* distances; /**< breadth-first distances from already fixed variables */
503 SCIP_Real* redcostscores; /**< reduced cost scores for fixing a variable to a reference value */
504 SCIP_Real* pscostscores; /**< pseudocost scores for fixing a variable to a reference value */
505 unsigned int useredcost:1; /**< should reduced cost scores be used for variable prioritization? */
506 unsigned int usedistances:1; /**< should distances from fixed variables be used for variable prioritization */
507 unsigned int usepscost:1; /**< should pseudo cost scores be used for variable prioritization? */
508};
509
510/*
511 * Local methods
512 */
513
514/** Reset target fixing rate */
515static
517 SCIP* scip, /**< SCIP data structure */
518 NH_FIXINGRATE* fixingrate /**< heuristic fixing rate */
519 )
520{
521 assert(scip != NULL);
522 assert(fixingrate != NULL);
523 fixingrate->increment = FIXINGRATE_STARTINC;
524
525 /* always start with the most conservative value */
526 fixingrate->targetfixingrate = fixingrate->maxfixingrate;
527
528 return SCIP_OKAY;
529}
530
531/** reset the currently active neighborhood */
532static
534 SCIP_HEURDATA* heurdata
535 )
536{
537 assert(heurdata != NULL);
538 heurdata->currneighborhood = -1;
539 heurdata->ndelayedcalls = 0;
540}
541
542/** update increment for fixing rate */
543static
545 NH_FIXINGRATE* fx /**< fixing rate */
546 )
547{
549 fx->increment = MAX(fx->increment, LRATEMIN);
550}
551
552
553/** increase fixing rate
554 *
555 * decrease also the rate by which the target fixing rate is adjusted
556 */
557static
559 NH_FIXINGRATE* fx /**< fixing rate */
560 )
561{
562 fx->targetfixingrate += fx->increment;
564}
565
566/** decrease fixing rate
567 *
568 * decrease also the rate by which the target fixing rate is adjusted
569 */
570static
572 NH_FIXINGRATE* fx /**< fixing rate */
573 )
574{
575 fx->targetfixingrate -= fx->increment;
577}
578
579/** update fixing rate based on the results of the current run */
580static
582 NH* neighborhood, /**< neighborhood */
583 SCIP_STATUS subscipstatus, /**< status of the sub-SCIP run */
584 NH_STATS* runstats /**< run statistics for this run */
585 )
586{
587 NH_FIXINGRATE* fx;
588
589 fx = &neighborhood->fixingrate;
590
591 switch (subscipstatus)
592 {
598 /* decrease the fixing rate (make subproblem harder) */
600 break;
605 /* increase the fixing rate (make the subproblem easier) only if no solution was found */
606 if( runstats->nbestsolsfound <= 0 )
608 break;
609 /* fall through cases to please lint */
619 default:
620 break;
621 }
622
624}
625
626/** increase target node limit */
627static
629 SCIP_HEURDATA* heurdata /**< heuristic data */
630 )
631{
632 heurdata->targetnodes = (SCIP_Longint)(heurdata->targetnodes * heurdata->targetnodefactor) + 1;
633
634 /* respect upper and lower parametrized bounds on targetnodes */
635 if( heurdata->targetnodes > heurdata->maxnodes )
636 heurdata->targetnodes = heurdata->maxnodes;
637}
638
639/** reset target node limit */
640static
642 SCIP_HEURDATA* heurdata /**< heuristic data */
643 )
644{
645 heurdata->targetnodes = heurdata->minnodes;
646}
647
648/** update target node limit based on the current run results */
649static
651 SCIP_HEURDATA* heurdata, /**< heuristic data */
652 NH_STATS* runstats, /**< statistics of the run */
653 SCIP_STATUS subscipstatus /**< status of the sub-SCIP run */
654 )
655{
656 switch (subscipstatus)
657 {
660 /* the subproblem could be explored more */
661 if( runstats->nbestsolsfound == 0 )
662 increaseTargetNodeLimit(heurdata);
663 break;
680 default:
681 break;
682 }
683}
684
685/** reset the minimum improvement for the sub-SCIPs */
686static
688 SCIP_HEURDATA* heurdata /**< heuristic data */
689 )
690{
691 assert(heurdata != NULL);
692 heurdata->minimprove = heurdata->startminimprove;
693}
694
695/** increase minimum improvement for the sub-SCIPs */
696static
698 SCIP_HEURDATA* heurdata /**< heuristic data */
699 )
700{
701 assert(heurdata != NULL);
702
703 heurdata->minimprove *= MINIMPROVEFAC;
704 heurdata->minimprove = MIN(heurdata->minimprove, heurdata->minimprovehigh);
705}
706
707/** decrease the minimum improvement for the sub-SCIPs */
708static
710 SCIP_HEURDATA* heurdata /**< heuristic data */
711 )
712{
713 assert(heurdata != NULL);
714
715 heurdata->minimprove /= MINIMPROVEFAC;
716 SCIPdebugMessage("%.4f", heurdata->minimprovelow);
717 heurdata->minimprove = MAX(heurdata->minimprove, heurdata->minimprovelow);
718}
719
720/** update the minimum improvement based on the status of the sub-SCIP */
721static
723 SCIP_HEURDATA* heurdata, /**< heuristic data */
724 SCIP_STATUS subscipstatus, /**< status of the sub-SCIP run */
725 NH_STATS* runstats /**< run statistics for this run */
726 )
727{
728 assert(heurdata != NULL);
729
730 /* if the sub-SCIP status was infeasible, we rather want to make the sub-SCIP easier
731 * with a smaller minimum improvement.
732 *
733 * If a solution limit was reached, we may, set it higher.
734 */
735 switch (subscipstatus)
736 {
739 /* subproblem was infeasible, probably due to the minimum improvement -> decrease minimum improvement */
741
742 break;
746 /* subproblem could be optimally solved -> try higher minimum improvement */
748 break;
752 /* subproblem was too hard, decrease minimum improvement */
753 if( runstats->nbestsolsfound <= 0 )
755 break;
766 default:
767 break;
768 }
769}
770
771/** Reset neighborhood statistics */
772static
774 SCIP* scip, /**< SCIP data structure */
775 NH_STATS* stats /**< neighborhood statistics */
776 )
777{
778 assert(scip != NULL);
779 assert(stats != NULL);
780
781 stats->nbestsolsfound = 0;
782 stats->nruns = 0;
783 stats->nrunsbestsol = 0;
784 stats->nsolsfound = 0;
785 stats->usednodes = 0L;
786 stats->nfixings = 0L;
787
789
792
793 return SCIP_OKAY;
794}
795
796/** create a neighborhood of the specified name and include it into the ALNS heuristic */
797static
799 SCIP* scip, /**< SCIP data structure */
800 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS heuristic */
801 NH** neighborhood, /**< pointer to store the neighborhood */
802 const char* name, /**< name for this neighborhood */
803 SCIP_Real minfixingrate, /**< default value for minfixingrate parameter of this neighborhood */
804 SCIP_Real maxfixingrate, /**< default value for maxfixingrate parameter of this neighborhood */
805 SCIP_Bool active, /**< default value for active parameter of this neighborhood */
806 SCIP_Real priority, /**< positive call priority to initialize bandit algorithms */
807 DECL_VARFIXINGS ((*varfixings)), /**< variable fixing callback for this neighborhood, or NULL */
808 DECL_CHANGESUBSCIP ((*changesubscip)), /**< subscip changes callback for this neighborhood, or NULL */
809 DECL_NHINIT ((*nhinit)), /**< initialization callback for neighborhood, or NULL */
810 DECL_NHEXIT ((*nhexit)), /**< deinitialization callback for neighborhood, or NULL */
811 DECL_NHFREE ((*nhfree)), /**< deinitialization callback before SCIP is freed, or NULL */
812 DECL_NHREFSOL ((*nhrefsol)), /**< callback function to return a reference solution for further fixings, or NULL */
813 DECL_NHDEACTIVATE ((*nhdeactivate)) /**< callback function to deactivate neighborhoods on problems where they are irrelevant, or NULL if neighborhood is always active */
814 )
815{
817
818 assert(scip != NULL);
819 assert(heurdata != NULL);
820 assert(neighborhood != NULL);
821 assert(name != NULL);
822
823 SCIP_CALL( SCIPallocBlockMemory(scip, neighborhood) );
824 assert(*neighborhood != NULL);
825
826 SCIP_ALLOC( BMSduplicateMemoryArray(&(*neighborhood)->name, name, strlen(name)+1) );
827
828 SCIP_CALL( SCIPcreateClock(scip, &(*neighborhood)->stats.setupclock) );
829 SCIP_CALL( SCIPcreateClock(scip, &(*neighborhood)->stats.submipclock) );
830
831 (*neighborhood)->changesubscip = changesubscip;
832 (*neighborhood)->varfixings = varfixings;
833 (*neighborhood)->nhinit = nhinit;
834 (*neighborhood)->nhexit = nhexit;
835 (*neighborhood)->nhfree = nhfree;
836 (*neighborhood)->nhrefsol = nhrefsol;
837 (*neighborhood)->nhdeactivate = nhdeactivate;
838
839 /* add parameters for this neighborhood */
840 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/alns/%s/minfixingrate", name);
841 SCIP_CALL( SCIPaddRealParam(scip, paramname, "minimum fixing rate for this neighborhood",
842 &(*neighborhood)->fixingrate.minfixingrate, TRUE, minfixingrate, 0.0, 1.0, NULL, NULL) );
843 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/alns/%s/maxfixingrate", name);
844 SCIP_CALL( SCIPaddRealParam(scip, paramname, "maximum fixing rate for this neighborhood",
845 &(*neighborhood)->fixingrate.maxfixingrate, TRUE, maxfixingrate, 0.0, 1.0, NULL, NULL) );
846 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/alns/%s/active", name);
847 SCIP_CALL( SCIPaddBoolParam(scip, paramname, "is this neighborhood active?",
848 &(*neighborhood)->active, TRUE, active, NULL, NULL) );
849 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/alns/%s/priority", name);
850 SCIP_CALL( SCIPaddRealParam(scip, paramname, "positive call priority to initialize bandit algorithms",
851 &(*neighborhood)->priority, TRUE, priority, 1e-2, 1.0, NULL, NULL) );
852
853 /* add the neighborhood to the ALNS heuristic */
854 heurdata->neighborhoods[heurdata->nneighborhoods++] = (*neighborhood);
855
856 return SCIP_OKAY;
857}
858
859/** release all data and free neighborhood */
860static
862 SCIP* scip, /**< SCIP data structure */
863 NH** neighborhood /**< pointer to neighborhood that should be freed */
864 )
865{
866 NH* nhptr;
867 assert(scip != NULL);
868 assert(neighborhood != NULL);
869
870 nhptr = *neighborhood;
871 assert(nhptr != NULL);
872
873 BMSfreeMemoryArray(&nhptr->name);
874
875 /* release further, neighborhood specific data structures */
876 if( nhptr->nhfree != NULL )
877 {
878 SCIP_CALL( nhptr->nhfree(scip, nhptr) );
879 }
880
883
884 SCIPfreeBlockMemory(scip, neighborhood);
885 *neighborhood = NULL;
886
887 return SCIP_OKAY;
888}
889
890/** initialize neighborhood specific data */
891static
893 SCIP* scip, /**< SCIP data structure */
894 NH* neighborhood /**< neighborhood to initialize */
895 )
896{
897 assert(scip != NULL);
898 assert(neighborhood != NULL);
899
900 /* call the init callback of the neighborhood */
901 if( neighborhood->nhinit != NULL )
902 {
903 SCIP_CALL( neighborhood->nhinit(scip, neighborhood) );
904 }
905
906 return SCIP_OKAY;
907}
908
909/** deinitialize neighborhood specific data */
910static
912 SCIP* scip, /**< SCIP data structure */
913 NH* neighborhood /**< neighborhood to initialize */
914 )
915{
916 assert(scip != NULL);
917 assert(neighborhood != NULL);
918
919 if( neighborhood->nhexit != NULL )
920 {
921 SCIP_CALL( neighborhood->nhexit(scip, neighborhood) );
922 }
923
924 return SCIP_OKAY;
925}
926
927/** creates a new solution for the original problem by copying the solution of the subproblem */
928static
930 SCIP* subscip, /**< SCIP data structure of the subproblem */
931 SCIP_EVENTDATA* eventdata /**< event handler data */
932 )
933{
934 SCIP* sourcescip; /* original SCIP data structure */
935 SCIP_VAR** subvars; /* the variables of the subproblem */
936 SCIP_HEUR* heur; /* alns heuristic structure */
937 SCIP_SOL* subsol; /* solution of the subproblem */
938 SCIP_SOL* newsol; /* solution to be created for the original problem */
939 SCIP_Bool success;
940 NH_STATS* runstats;
941 SCIP_SOL* oldbestsol;
942
943 assert(subscip != NULL);
944
945 subsol = SCIPgetBestSol(subscip);
946 assert(subsol != NULL);
947
948 sourcescip = eventdata->sourcescip;
949 subvars = eventdata->subvars;
950 heur = eventdata->heur;
951 runstats = eventdata->runstats;
952 assert(sourcescip != NULL);
953 assert(sourcescip != subscip);
954 assert(heur != NULL);
955 assert(subvars != NULL);
956 assert(runstats != NULL);
957
958 SCIP_CALL( SCIPtranslateSubSol(sourcescip, subscip, subsol, heur, subvars, &newsol) );
959
960 oldbestsol = SCIPgetBestSol(sourcescip);
961
962 /* in the special, experimental all rewards mode, the solution is only checked for feasibility
963 * but not stored
964 */
965 if( eventdata->allrewardsmode )
966 {
967 SCIP_CALL( SCIPcheckSol(sourcescip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
968
969 if( success )
970 {
971 runstats->nsolsfound++;
972 if( SCIPgetSolTransObj(sourcescip, newsol) < SCIPgetCutoffbound(sourcescip) )
973 runstats->nbestsolsfound++;
974 }
975
976 SCIP_CALL( SCIPfreeSol(sourcescip, &newsol) );
977 }
978 else
979 {
980 /* try to add new solution to scip and free it immediately */
981 SCIP_CALL( SCIPtrySolFree(sourcescip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
982
983 if( success )
984 {
985 runstats->nsolsfound++;
986 if( SCIPgetBestSol(sourcescip) != oldbestsol )
987 runstats->nbestsolsfound++;
988 }
989 }
990
991 /* update new upper bound for reward later */
992 runstats->newupperbound = SCIPgetUpperbound(sourcescip);
993
994 return SCIP_OKAY;
995}
996
997
998/* ---------------- Callback methods of event handler ---------------- */
999
1000/** execution callback of the event handler
1001 *
1002 * transfer new solutions or interrupt the solving process manually
1003 */
1004static
1006{
1007 assert(eventhdlr != NULL);
1008 assert(eventdata != NULL);
1009 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1010 assert(event != NULL);
1011 assert(SCIPeventGetType(event) & SCIP_EVENTTYPE_ALNS);
1012 assert(eventdata != NULL);
1013
1014 /* treat the different atomic events */
1015 switch( SCIPeventGetType(event) )
1016 {
1019 /* try to transfer the solution to the original SCIP */
1020 SCIP_CALL( transferSolution(scip, eventdata) );
1021 break;
1023 /* interrupt solution process of sub-SCIP */
1024 if( SCIPgetNLPs(scip) > eventdata->lplimfac * eventdata->nodelimit )
1025 {
1026 SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n", SCIPgetNLPs(scip));
1028 }
1029 break;
1030 default:
1031 break;
1032 }
1033
1034 return SCIP_OKAY;
1035}
1036
1037/** initialize neighborhood statistics before the next run */
1038static
1040 SCIP* scip, /**< SCIP data structure */
1041 NH_STATS* stats /**< run statistics */
1042 )
1043{
1044 stats->nbestsolsfound = 0;
1045 stats->nsolsfound = 0;
1046 stats->usednodes = 0L;
1047 stats->nfixings = 0;
1050}
1051
1052/** update run stats after the sub SCIP was solved */
1053static
1055 NH_STATS* stats, /**< run statistics */
1056 SCIP* subscip /**< sub-SCIP instance, or NULL */
1057 )
1058{
1059 /* treat an untransformed subscip as if none was created */
1060 if( subscip != NULL && ! SCIPisTransformed(subscip) )
1061 subscip = NULL;
1062
1063 stats->usednodes = subscip != NULL ? SCIPgetNNodes(subscip) : 0L;
1064}
1065
1066/** get the histogram index for this status */
1067static
1069 SCIP_STATUS subscipstatus /**< sub-SCIP status */
1070 )
1071{
1072 switch (subscipstatus)
1073 {
1075 return (int)HIDX_OPT;
1077 return (int)HIDX_INFEAS;
1079 return (int)HIDX_NODELIM;
1081 return (int)HIDX_STALLNODE;
1084 return (int)HIDX_SOLLIM;
1086 return (int)HIDX_USR;
1087 default:
1088 return (int)HIDX_OTHER;
1089 } /*lint !e788*/
1090}
1091
1092/** print neighborhood statistics */
1093static
1095 SCIP* scip, /**< SCIP data structure */
1096 SCIP_HEURDATA* heurdata, /**< heuristic data */
1097 FILE* file /**< file handle, or NULL for standard out */
1098 )
1099{
1100 int i;
1101 int j;
1103
1104 if( ! heurdata->shownbstats )
1105 return;
1106
1107 SCIPinfoMessage(scip, file, "Neighborhoods : %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %4s %4s %4s %4s %4s %4s %4s %4s\n",
1108 "Calls", "SetupTime", "SolveTime", "SolveNodes", "Sols", "Best", "Exp3", "Exp3-IX", "EpsGreedy", "UCB", "TgtFixRate",
1109 "Opt", "Inf", "Node", "Stal", "Sol", "Usr", "Othr", "Actv");
1110
1111 /* loop over neighborhoods and fill in statistics */
1112 for( i = 0; i < heurdata->nneighborhoods; ++i )
1113 {
1114 NH* neighborhood;
1115 SCIP_Real proba;
1116 SCIP_Real probaix;
1117 SCIP_Real ucb;
1118 SCIP_Real epsgreedyweight;
1119
1120 neighborhood = heurdata->neighborhoods[i];
1121 SCIPinfoMessage(scip, file, " %-17s:", neighborhood->name);
1122 SCIPinfoMessage(scip, file, " %10d", neighborhood->stats.nruns);
1123 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, neighborhood->stats.setupclock) );
1124 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, neighborhood->stats.submipclock) );
1125 SCIPinfoMessage(scip, file, " %10" SCIP_LONGINT_FORMAT, neighborhood->stats.usednodes );
1126 SCIPinfoMessage(scip, file, " %10" SCIP_LONGINT_FORMAT, neighborhood->stats.nsolsfound);
1127 SCIPinfoMessage(scip, file, " %10" SCIP_LONGINT_FORMAT, neighborhood->stats.nbestsolsfound);
1128
1129 proba = 0.0;
1130 probaix = 0.0;
1131 ucb = 1.0;
1132 epsgreedyweight = -1.0;
1133
1134 if( heurdata->bandit != NULL && i < heurdata->nactiveneighborhoods )
1135 {
1136 switch (heurdata->banditalgo)
1137 {
1138 case 'u':
1139 ucb = SCIPgetConfidenceBoundUcb(heurdata->bandit, i);
1140 break;
1141 case 'g':
1142 epsgreedyweight = SCIPgetWeightsEpsgreedy(heurdata->bandit)[i];
1143 break;
1144 case 'e':
1145 proba = SCIPgetProbabilityExp3(heurdata->bandit, i);
1146 break;
1147 case 'i':
1148 probaix = SCIPgetProbabilityExp3IX(heurdata->bandit, i);
1149 break;
1150 default:
1151 break;
1152 }
1153 }
1154
1155 SCIPinfoMessage(scip, file, " %10.5f", proba);
1156 SCIPinfoMessage(scip, file, " %10.5f", probaix);
1157 SCIPinfoMessage(scip, file, " %10.5f", epsgreedyweight);
1158 SCIPinfoMessage(scip, file, " %10.5f", ucb);
1159 SCIPinfoMessage(scip, file, " %10.3f", neighborhood->fixingrate.targetfixingrate);
1160
1161 /* loop over status histogram */
1162 for( j = 0; j < NHISTENTRIES; ++j )
1163 SCIPinfoMessage(scip, file, " %4d", neighborhood->stats.statushist[statusses[j]]);
1164
1165 SCIPinfoMessage(scip, file, " %4d", i < heurdata->nactiveneighborhoods ? 1 : 0);
1166 SCIPinfoMessage(scip, file, "\n");
1167 }
1168}
1169
1170/** update the statistics of the neighborhood based on the sub-SCIP run */
1171static
1173 NH_STATS* runstats, /**< run statistics */
1174 NH* neighborhood, /**< the selected neighborhood */
1175 SCIP_STATUS subscipstatus /**< status of the sub-SCIP solve */
1176 )
1177{ /*lint --e{715}*/
1178 NH_STATS* stats;
1179 stats = &neighborhood->stats;
1180
1181 /* copy run statistics into neighborhood statistics */
1182 stats->nbestsolsfound += runstats->nbestsolsfound;
1183 stats->nsolsfound += runstats->nsolsfound;
1184 stats->usednodes += runstats->usednodes;
1185 stats->nruns += 1;
1186
1187 if( runstats->nbestsolsfound > 0 )
1189 else if( runstats->nsolsfound > 0 )
1190 stats->nrunsbestsol++;
1191
1192 /* update the counter for the subscip status */
1193 ++stats->statushist[getHistIndex(subscipstatus)];
1194}
1195
1196/** sort callback for variable pointers using the ALNS variable prioritization
1197 *
1198 * the variable prioritization works hierarchically as follows. A variable
1199 * a has the higher priority over b iff
1200 *
1201 * - variable distances should be used and a has a smaller distance than b
1202 * - variable reduced costs should be used and a has a smaller score than b
1203 * - variable pseudo costs should be used and a has a smaller score than b
1204 * - based on previously assigned random scores
1205 *
1206 * @note: distances are context-based. For fixing more variables,
1207 * distances are initialized from the already fixed variables.
1208 * For unfixing variables, distances are initialized starting
1209 * from the unfixed variables
1210 */
1211static
1213{ /*lint --e{715}*/
1214 VARPRIO* varprio;
1215
1216 varprio = (VARPRIO*)dataptr;
1217 assert(varprio != NULL);
1218 assert(varprio->randscores != NULL);
1219
1220 if( ind1 == ind2 )
1221 return 0;
1222
1223 /* priority is on distances, if enabled. The variable which is closer in a breadth-first search sense to
1224 * the already fixed variables has precedence */
1225 if( varprio->usedistances )
1226 {
1227 int dist1;
1228 int dist2;
1229
1230 dist1 = varprio->distances[ind1];
1231 dist2 = varprio->distances[ind2];
1232
1233 if( dist1 < 0 )
1234 dist1 = INT_MAX;
1235
1236 if( dist2 < 0 )
1237 dist2 = INT_MAX;
1238
1239 assert(varprio->distances != NULL);
1240 if( dist1 < dist2 )
1241 return -1;
1242 else if( dist1 > dist2 )
1243 return 1;
1244 }
1245
1246 assert(! varprio->usedistances || varprio->distances[ind1] == varprio->distances[ind2]);
1247
1248 /* if the indices tie considering distances or distances are disabled -> use reduced cost information instead */
1249 if( varprio->useredcost )
1250 {
1251 assert(varprio->redcostscores != NULL);
1252
1253 if( varprio->redcostscores[ind1] < varprio->redcostscores[ind2] )
1254 return -1;
1255 else if( varprio->redcostscores[ind1] > varprio->redcostscores[ind2] )
1256 return 1;
1257 }
1258
1259 /* use pseudo cost scores if reduced costs are disabled or a tie was found */
1260 if( varprio->usepscost )
1261 {
1262 assert(varprio->pscostscores != NULL);
1263
1264 /* prefer the variable with smaller pseudocost score */
1265 if( varprio->pscostscores[ind1] < varprio->pscostscores[ind2] )
1266 return -1;
1267 else if( varprio->pscostscores[ind1] > varprio->pscostscores[ind2] )
1268 return 1;
1269 }
1270
1271 if( varprio->randscores[ind1] < varprio->randscores[ind2] )
1272 return -1;
1273 else if( varprio->randscores[ind1] > varprio->randscores[ind2] )
1274 return 1;
1275
1276 return ind1 - ind2;
1277}
1278
1279/** Compute the reduced cost score for this variable in the reference solution */
1280static
1282 SCIP* scip, /**< SCIP data structure */
1283 SCIP_VAR* var, /**< the variable for which the score should be computed */
1284 SCIP_Real refsolval, /**< solution value in reference solution */
1285 SCIP_Bool uselocalredcost /**< should local reduced costs be used for generic (un)fixing? */
1286 )
1287{
1288 SCIP_Real bestbound;
1289 SCIP_Real redcost;
1290 SCIP_Real score;
1291 assert(scip != NULL);
1292 assert(var != NULL);
1293
1294 /* prefer column variables */
1296 return SCIPinfinity(scip);
1297
1298 if( ! uselocalredcost )
1299 {
1300 redcost = SCIPvarGetBestRootRedcost(var);
1301
1302 bestbound = SCIPvarGetBestRootSol(var);
1303
1304 /* using global reduced costs, the two factors yield a nonnegative score within tolerances */
1305 assert(SCIPisDualfeasZero(scip, redcost)
1306 || (SCIPisDualfeasNegative(scip, redcost) && ! SCIPisFeasPositive(scip, refsolval - bestbound))
1307 || (SCIPisDualfeasPositive(scip, redcost) && ! SCIPisFeasNegative(scip, refsolval - bestbound)));
1308 }
1309 else
1310 {
1311 /* this can be safely asserted here, since the heuristic would not reach this point, otherwise */
1312 assert(SCIPhasCurrentNodeLP(scip));
1314
1315 redcost = SCIPgetVarRedcost(scip, var);
1316
1317 bestbound = SCIPvarGetLPSol(var);
1318 }
1319
1320 assert(! SCIPisInfinity(scip, REALABS(bestbound)));
1321 assert(SCIPisDualfeasZero(scip, redcost) || SCIPisFeasIntegral(scip, bestbound));
1322
1323 score = redcost * (refsolval - bestbound);
1324
1325 /* max out numerical inaccuracies from global scores */
1326 if( ! uselocalredcost )
1327 score = MAX(score, 0.0);
1328
1329 return score;
1330}
1331
1332/** get the pseudo cost score of this variable with respect to the reference solution */
1333static
1335 SCIP* scip, /**< SCIP data structure */
1336 SCIP_VAR* var, /**< the variable for which the score should be computed */
1337 SCIP_Real refsolval, /**< solution value in reference solution */
1338 SCIP_Bool uselocallpsol /**< should local LP solution be used? */
1339 )
1340{
1341 SCIP_Real soldiff;
1342
1343 assert(scip != NULL);
1344 assert(var != NULL);
1345
1346 /* variables that aren't LP columns have no pseudocost score */
1348 return 0.0;
1349
1350 soldiff = refsolval - (uselocallpsol ? SCIPvarGetLPSol(var) : SCIPvarGetRootSol(var));
1351
1352 /* the score is 0.0 if the values are equal */
1353 if( SCIPisFeasZero(scip, soldiff) )
1354 return 0.0;
1355 else
1356 return SCIPgetVarPseudocostVal(scip, var, soldiff);
1357}
1358
1359/** add variable and solution value to buffer data structure for variable fixings. The method checks if
1360 * the value still lies within the variable bounds. The value stays unfixed otherwise.
1361 */
1362static
1364 SCIP* scip, /**< SCIP data structure */
1365 SCIP_VAR* var, /**< (source) SCIP variable that should be added to the buffer */
1366 SCIP_Real val, /**< fixing value for this variable */
1367 SCIP_VAR** varbuf, /**< variable buffer to store variables that should be fixed */
1368 SCIP_Real* valbuf, /**< value buffer to store fixing values */
1369 int* nfixings, /**< pointer to number of fixed buffer variables, will be increased by 1 */
1370 SCIP_Bool integer /**< is this an integer variable? */
1371 )
1372{
1373 assert(integer == (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER));
1374 assert(!integer || SCIPisFeasIntegral(scip, val));
1375 assert(*nfixings < SCIPgetNVars(scip));
1376
1377 /* round the value to its nearest integer */
1378 if( integer )
1379 val = SCIPfloor(scip, val + 0.5);
1380
1381 /* only add fixing if it is still valid within the global variable bounds. Invalidity
1382 * of this solution value may come from a dual reduction that was performed after the solution from which
1383 * this value originated was found
1384 */
1385 if( SCIPvarGetLbGlobal(var) <= val && val <= SCIPvarGetUbGlobal(var) )
1386 {
1387 varbuf[*nfixings] = var;
1388 valbuf[*nfixings] = val;
1389 ++(*nfixings);
1390 }
1391}
1392
1393/** query neighborhood for a reference solution for further fixings */
1394static
1396 SCIP* scip, /**< SCIP data structure */
1397 NH* neighborhood, /**< ALNS neighborhood data structure */
1398 SCIP_SOL** solptr /**< solution pointer */
1399 )
1400{
1401 assert(solptr != NULL);
1402 assert(scip != NULL);
1403 assert(neighborhood != NULL);
1404
1405 *solptr = NULL;
1406 if( neighborhood->nhrefsol != NULL )
1407 {
1408 SCIP_RESULT result;
1409 SCIP_CALL( neighborhood->nhrefsol(scip, neighborhood, solptr, &result) );
1410
1411 if( result == SCIP_DIDNOTFIND )
1412 *solptr = NULL;
1413 else
1414 assert(*solptr != NULL);
1415 }
1416
1417 return SCIP_OKAY;
1418}
1419
1420/** fix additional variables found in feasible reference solution if the ones that the neighborhood found were not enough
1421 *
1422 * use not always the best solution for the values, but a reference solution provided by the neighborhood itself
1423 *
1424 * @note it may happen that the target fixing rate is not completely reached. This is the case if intermediate,
1425 * dual reductions render the solution values of the reference solution infeasible for
1426 * the current, global variable bounds.
1427 */
1428static
1430 SCIP* scip, /**< SCIP data structure */
1431 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
1432 SCIP_SOL* refsol, /**< feasible reference solution for more variable fixings */
1433 SCIP_VAR** varbuf, /**< buffer array to store variables to fix */
1434 SCIP_Real* valbuf, /**< buffer array to store fixing values */
1435 int* nfixings, /**< pointer to store the number of fixings */
1436 int ntargetfixings, /**< number of required target fixings */
1437 SCIP_Bool* success /**< pointer to store whether the target fixings have been successfully reached */
1438 )
1439{
1440 VARPRIO varprio;
1441 SCIP_VAR** vars;
1442 SCIP_Real* redcostscores;
1443 SCIP_Real* pscostscores;
1444 SCIP_Real* solvals;
1445 SCIP_RANDNUMGEN* rng;
1446 SCIP_VAR** unfixedvars;
1447 SCIP_Bool* isfixed;
1448 int* distances;
1449 int* perm;
1450 SCIP_Real* randscores;
1451 int nbinvars;
1452 int nintvars;
1453 int nbinintvars;
1454 int nvars;
1455 int b;
1456 int nvarstoadd;
1457 int nunfixedvars;
1458
1459 assert(scip != NULL);
1460 assert(varbuf != NULL);
1461 assert(nfixings != NULL);
1462 assert(success != NULL);
1463 assert(heurdata != NULL);
1464 assert(refsol != NULL);
1465
1466 *success = FALSE;
1467
1468 /* if the user parameter forbids more fixings, return immediately */
1469 if( ! heurdata->domorefixings )
1470 return SCIP_OKAY;
1471
1472 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
1473
1474 nbinintvars = nbinvars + nintvars;
1475
1476 if( ntargetfixings >= nbinintvars )
1477 return SCIP_OKAY;
1478
1479 /* determine the number of required additional fixings */
1480 nvarstoadd = ntargetfixings - *nfixings;
1481 if( nvarstoadd == 0 )
1482 return SCIP_OKAY;
1483
1484 varprio.usedistances = heurdata->usedistances && (*nfixings >= 1);
1485 varprio.useredcost = heurdata->useredcost;
1486 varprio.usepscost = heurdata->usepscost;
1487 varprio.scip = scip;
1488 rng = SCIPbanditGetRandnumgen(heurdata->bandit);
1489 assert(rng != NULL);
1490
1491 SCIP_CALL( SCIPallocBufferArray(scip, &randscores, nbinintvars) );
1492 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nbinintvars) );
1493 SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
1494 SCIP_CALL( SCIPallocBufferArray(scip, &redcostscores, nbinintvars) );
1495 SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nbinintvars) );
1496 SCIP_CALL( SCIPallocBufferArray(scip, &isfixed, nbinintvars) );
1497 SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, nbinintvars) );
1498 SCIP_CALL( SCIPallocBufferArray(scip, &pscostscores, nbinintvars) );
1499
1500 /* initialize variable graph distances from already fixed variables */
1501 if( varprio.usedistances )
1502 {
1503 SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, NULL, varbuf, *nfixings, distances, INT_MAX, INT_MAX, ntargetfixings) );
1504 }
1505 else
1506 {
1507 /* initialize all equal distances to make them irrelevant */
1508 BMSclearMemoryArray(distances, nbinintvars);
1509 }
1510
1511 BMSclearMemoryArray(isfixed, nbinintvars);
1512
1513 /* mark binary and integer variables if they are fixed */
1514 for( b = 0; b < *nfixings; ++b )
1515 {
1516 int probindex;
1517
1518 assert(varbuf[b] != NULL);
1519 probindex = SCIPvarGetProbindex(varbuf[b]);
1520 assert(probindex >= 0);
1521
1522 if( probindex < nbinintvars )
1523 isfixed[probindex] = TRUE;
1524 }
1525
1526 SCIP_CALL( SCIPgetSolVals(scip, refsol, nbinintvars, vars, solvals) );
1527
1528 /* assign scores to unfixed every discrete variable of the problem */
1529 nunfixedvars = 0;
1530 for( b = 0; b < nbinintvars; ++b )
1531 {
1532 SCIP_VAR* var = vars[b];
1533
1534 /* filter fixed variables */
1535 if( isfixed[b] )
1536 continue;
1537
1538 /* filter variables with a solution value outside its global bounds */
1539 if( solvals[b] < SCIPvarGetLbGlobal(var) - 0.5 || solvals[b] > SCIPvarGetUbGlobal(var) + 0.5 )
1540 continue;
1541
1542 redcostscores[nunfixedvars] = getVariableRedcostScore(scip, var, solvals[b], heurdata->uselocalredcost);
1543 pscostscores[nunfixedvars] = getVariablePscostScore(scip, var, solvals[b], heurdata->uselocalredcost);
1544
1545 unfixedvars[nunfixedvars] = var;
1546 perm[nunfixedvars] = nunfixedvars;
1547 randscores[nunfixedvars] = SCIPrandomGetReal(rng, 0.0, 1.0);
1548
1549 /* these assignments are based on the fact that nunfixedvars <= b */
1550 solvals[nunfixedvars] = solvals[b];
1551 distances[nunfixedvars] = distances[b];
1552
1553 SCIPdebugMsg(scip, "Var <%s> scores: dist %3d, red cost %15.9g, pscost %15.9g rand %6.4f\n",
1554 SCIPvarGetName(var), distances[nunfixedvars], redcostscores[nunfixedvars],
1555 pscostscores[nunfixedvars], randscores[nunfixedvars]);
1556
1557 nunfixedvars++;
1558 }
1559
1560 /* use selection algorithm (order of the variables does not matter) for quickly completing the fixing */
1561 varprio.randscores = randscores;
1562 varprio.distances = distances;
1563 varprio.redcostscores = redcostscores;
1564 varprio.pscostscores = pscostscores;
1565
1566 nvarstoadd = MIN(nunfixedvars, nvarstoadd);
1567
1568 /* select the first nvarstoadd many variables according to the score */
1569 if( nvarstoadd < nunfixedvars )
1570 SCIPselectInd(perm, sortIndCompAlns, &varprio, nvarstoadd, nunfixedvars);
1571
1572 /* loop over the first elements of the selection defined in permutation. They represent the best variables */
1573 for( b = 0; b < nvarstoadd; ++b )
1574 {
1575 int permindex = perm[b];
1576 assert(permindex >= 0);
1577 assert(permindex < nunfixedvars);
1578
1579 tryAdd2variableBuffer(scip, unfixedvars[permindex], solvals[permindex], varbuf, valbuf, nfixings, TRUE);
1580 }
1581
1582 *success = TRUE;
1583
1584 /* free buffer arrays */
1585 SCIPfreeBufferArray(scip, &pscostscores);
1586 SCIPfreeBufferArray(scip, &unfixedvars);
1587 SCIPfreeBufferArray(scip, &isfixed);
1588 SCIPfreeBufferArray(scip, &solvals);
1589 SCIPfreeBufferArray(scip, &redcostscores);
1590 SCIPfreeBufferArray(scip, &distances);
1591 SCIPfreeBufferArray(scip, &perm);
1592 SCIPfreeBufferArray(scip, &randscores);
1593
1594 return SCIP_OKAY;
1595}
1596
1597/** create the bandit algorithm for the heuristic depending on the user parameter */
1598static
1600 SCIP* scip, /**< SCIP data structure */
1601 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
1602 SCIP_Real* priorities, /**< call priorities for active neighborhoods */
1603 unsigned int initseed /**< initial random seed */
1604 )
1605{
1606 switch (heurdata->banditalgo)
1607 {
1608 case 'u':
1609 SCIP_CALL( SCIPcreateBanditUcb(scip, &heurdata->bandit, priorities,
1610 heurdata->ucb_alpha, heurdata->nactiveneighborhoods, initseed) );
1611 break;
1612
1613 case 'e':
1614 SCIP_CALL( SCIPcreateBanditExp3(scip, &heurdata->bandit, priorities,
1615 heurdata->exp3_gamma, heurdata->exp3_beta, heurdata->nactiveneighborhoods, initseed) );
1616 break;
1617
1618 case 'i':
1619 SCIP_CALL( SCIPcreateBanditExp3IX(scip, &heurdata->bandit, priorities,
1620 heurdata->nactiveneighborhoods, initseed) );
1621 break;
1622
1623 case 'g':
1624 SCIP_CALL( SCIPcreateBanditEpsgreedy(scip, &heurdata->bandit, priorities,
1625 heurdata->epsgreedy_eps, FALSE, FALSE, 0.9, 0, heurdata->nactiveneighborhoods, initseed) );
1626 break;
1627
1628 default:
1629 SCIPerrorMessage("Unknown bandit parameter %c\n", heurdata->banditalgo);
1630 return SCIP_INVALIDDATA;
1631 }
1632
1633 return SCIP_OKAY;
1634}
1635
1636/*
1637 * Callback methods of primal heuristic
1638 */
1639
1640/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
1641static
1643{ /*lint --e{715}*/
1644 assert(scip != NULL);
1645 assert(heur != NULL);
1646 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1647
1648 /* call inclusion method of primal heuristic */
1650
1651 return SCIP_OKAY;
1652}
1653
1654/** unfix some of the variables because there are too many fixed
1655 *
1656 * a variable is ideally unfixed if it is close to other unfixed variables
1657 * and fixing it has a high reduced cost impact
1658 */
1659static
1661 SCIP* scip, /**< SCIP data structure */
1662 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
1663 SCIP_VAR** varbuf, /**< buffer array to store variables to fix */
1664 SCIP_Real* valbuf, /**< buffer array to store fixing values */
1665 int* nfixings, /**< pointer to store the number of fixings */
1666 int ntargetfixings, /**< number of required target fixings */
1667 SCIP_Bool* success /**< pointer to store whether the target fixings have been successfully reached */
1668 )
1669{
1670 VARPRIO varprio;
1671 SCIP_Real* redcostscores;
1672 SCIP_Real* pscostscores;
1673 SCIP_Real* randscores;
1674 SCIP_VAR** unfixedvars;
1675 SCIP_VAR** varbufcpy;
1676 SCIP_Real* valbufcpy;
1677 SCIP_Bool* isfixedvar;
1678 SCIP_VAR** vars;
1679 SCIP_RANDNUMGEN* rng;
1680 int* distances;
1681 int* fixeddistances;
1682 int* perm;
1683 int nvars;
1684 int i;
1685 int nbinintvars;
1686 int nunfixed;
1687
1688 *success = FALSE;
1689
1690 nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
1691 if( nbinintvars == 0 )
1692 return SCIP_OKAY;
1693
1694 assert(*nfixings > 0);
1695
1696 nvars = SCIPgetNVars(scip);
1697 SCIP_CALL( SCIPallocBufferArray(scip, &isfixedvar, nvars) );
1698 SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, nbinintvars) );
1699 SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
1700 SCIP_CALL( SCIPallocBufferArray(scip, &fixeddistances, *nfixings) );
1701 SCIP_CALL( SCIPallocBufferArray(scip, &redcostscores, *nfixings) );
1702 SCIP_CALL( SCIPallocBufferArray(scip, &randscores, *nfixings) );
1703 SCIP_CALL( SCIPallocBufferArray(scip, &perm, *nfixings) );
1704 SCIP_CALL( SCIPallocBufferArray(scip, &pscostscores, *nfixings) );
1705
1706 SCIP_CALL( SCIPduplicateBufferArray(scip, &varbufcpy, varbuf, *nfixings) );
1707 SCIP_CALL( SCIPduplicateBufferArray(scip, &valbufcpy, valbuf, *nfixings) );
1708
1709 /*
1710 * collect the unfixed binary and integer variables
1711 */
1712 BMSclearMemoryArray(isfixedvar, nvars);
1713 /* loop over fixed variables and mark their respective positions as fixed */
1714 for( i = 0; i < *nfixings; ++i )
1715 {
1716 int probindex = SCIPvarGetProbindex(varbuf[i]);
1717
1718 assert(probindex >= 0);
1719
1720 isfixedvar[probindex] = TRUE;
1721 }
1722
1723 nunfixed = 0;
1724 vars = SCIPgetVars(scip);
1725 /* collect unfixed binary and integer variables */
1726 for( i = 0; i < nbinintvars; ++i )
1727 {
1728 if( ! isfixedvar[i] )
1729 unfixedvars[nunfixed++] = vars[i];
1730 }
1731
1732 varprio.usedistances = heurdata->usedistances && nunfixed > 0;
1733
1734 /* collect distances of all fixed variables from those that are not fixed */
1735 if( varprio.usedistances )
1736 {
1737 SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, NULL, unfixedvars, nunfixed, distances, INT_MAX, INT_MAX, INT_MAX) );
1738
1739 for( i = 0; i < *nfixings; ++i )
1740 {
1741 int probindex = SCIPvarGetProbindex(varbuf[i]);
1742 if( probindex >= 0 )
1743 fixeddistances[i] = distances[probindex];
1744 }
1745 }
1746 else
1747 {
1748 BMSclearMemoryArray(fixeddistances, *nfixings);
1749 }
1750
1751 /* collect reduced cost scores of the fixings and assign random scores */
1752 rng = SCIPbanditGetRandnumgen(heurdata->bandit);
1753 for( i = 0; i < *nfixings; ++i )
1754 {
1755 SCIP_VAR* fixedvar = varbuf[i];
1756 SCIP_Real fixval = valbuf[i];
1757
1758 /* use negative reduced cost and pseudo cost scores to prefer variable fixings with small score */
1759 redcostscores[i] = - getVariableRedcostScore(scip, fixedvar, fixval, heurdata->uselocalredcost);
1760 pscostscores[i] = - getVariablePscostScore(scip, fixedvar, fixval, heurdata->uselocalredcost);
1761 randscores[i] = SCIPrandomGetReal(rng, 0.0, 1.0);
1762 perm[i] = i;
1763
1764 SCIPdebugMsg(scip, "Var <%s> scores: dist %3d, red cost %15.9g, pscost %15.9g rand %6.4f\n",
1765 SCIPvarGetName(fixedvar), fixeddistances[i], redcostscores[i], pscostscores[i], randscores[i]);
1766 }
1767
1768 varprio.distances = fixeddistances;
1769 varprio.randscores = randscores;
1770 varprio.redcostscores = redcostscores;
1771 varprio.pscostscores = pscostscores;
1772 varprio.useredcost = heurdata->useredcost;
1773 varprio.usepscost = heurdata->usepscost;
1774 varprio.scip = scip;
1775
1776 /* scores are assigned in such a way that variables with a smaller score should be fixed last */
1777 SCIPselectDownInd(perm, sortIndCompAlns, &varprio, ntargetfixings, *nfixings);
1778
1779 /* bring the desired variables to the front of the array */
1780 for( i = 0; i < ntargetfixings; ++i )
1781 {
1782 valbuf[i] = valbufcpy[perm[i]];
1783 varbuf[i] = varbufcpy[perm[i]];
1784 }
1785
1786 *nfixings = ntargetfixings;
1787
1788 /* free the buffer arrays in reverse order of allocation */
1789 SCIPfreeBufferArray(scip, &valbufcpy);
1790 SCIPfreeBufferArray(scip, &varbufcpy);
1791 SCIPfreeBufferArray(scip, &pscostscores);
1792 SCIPfreeBufferArray(scip, &perm);
1793 SCIPfreeBufferArray(scip, &randscores);
1794 SCIPfreeBufferArray(scip, &redcostscores);
1795 SCIPfreeBufferArray(scip, &fixeddistances);
1796 SCIPfreeBufferArray(scip, &distances);
1797 SCIPfreeBufferArray(scip, &unfixedvars);
1798 SCIPfreeBufferArray(scip, &isfixedvar);
1799
1800 *success = TRUE;
1801
1802 return SCIP_OKAY;
1803}
1804
1805/** call variable fixing callback for this neighborhood and orchestrate additional variable fixings, if necessary */
1806static
1808 SCIP* scip, /**< SCIP data structure */
1809 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
1810 NH* neighborhood, /**< neighborhood data structure */
1811 SCIP_VAR** varbuf, /**< buffer array to keep variables that should be fixed */
1812 SCIP_Real* valbuf, /**< buffer array to keep fixing values */
1813 int* nfixings, /**< pointer to store the number of variable fixings */
1814 SCIP_RESULT* result /**< pointer to store the result of the fixing operation */
1815 )
1816{
1817 int ntargetfixings;
1818 int nmaxfixings;
1819 int nminfixings;
1820 int nbinintvars;
1821
1822 assert(scip != NULL);
1823 assert(neighborhood != NULL);
1824 assert(varbuf != NULL);
1825 assert(valbuf != NULL);
1826 assert(nfixings != NULL);
1827 assert(result != NULL);
1828
1829 *nfixings = 0;
1830
1831 *result = SCIP_DIDNOTRUN;
1832 ntargetfixings = (int)(neighborhood->fixingrate.targetfixingrate * (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)));
1833
1834 if( neighborhood->varfixings != NULL )
1835 {
1836 SCIP_CALL( neighborhood->varfixings(scip, neighborhood, varbuf, valbuf, nfixings, result) );
1837
1838 if( *result != SCIP_SUCCESS )
1839 return SCIP_OKAY;
1840 }
1841 else if( ntargetfixings == 0 )
1842 {
1843 *result = SCIP_SUCCESS;
1844
1845 return SCIP_OKAY;
1846 }
1847
1848 /* compute upper and lower target fixing limits using tolerance parameters */
1849 assert(neighborhood->varfixings == NULL || *result != SCIP_DIDNOTRUN);
1850 nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
1851 ntargetfixings = (int)(neighborhood->fixingrate.targetfixingrate * nbinintvars);
1852 nminfixings = (int)((neighborhood->fixingrate.targetfixingrate - heurdata->fixtol) * nbinintvars);
1853 nminfixings = MAX(nminfixings, 0);
1854 nmaxfixings = (int)((neighborhood->fixingrate.targetfixingrate + heurdata->unfixtol) * nbinintvars);
1855 nmaxfixings = MIN(nmaxfixings, nbinintvars);
1856
1857 SCIPdebugMsg(scip, "Neighborhood Fixings/Target: %d / %d <= %d <= %d\n",*nfixings, nminfixings, ntargetfixings, nmaxfixings);
1858
1859 /* if too few fixings, use a strategy to select more variable fixings: randomized, LP graph, ReducedCost based, mix */
1860 if( (*result == SCIP_SUCCESS || *result == SCIP_DIDNOTRUN) && (*nfixings < nminfixings) )
1861 {
1862 SCIP_Bool success;
1863 SCIP_SOL* refsol;
1864
1865 /* get reference solution from neighborhood */
1866 SCIP_CALL( neighborhoodGetRefsol(scip, neighborhood, &refsol) );
1867
1868 /* try to fix more variables based on the reference solution */
1869 if( refsol != NULL )
1870 {
1871 SCIP_CALL( alnsFixMoreVariables(scip, heurdata, refsol, varbuf, valbuf, nfixings, ntargetfixings, &success) );
1872 }
1873 else
1874 success = FALSE;
1875
1876 if( success )
1877 *result = SCIP_SUCCESS;
1878 else if( *result == SCIP_SUCCESS )
1879 *result = SCIP_DIDNOTFIND;
1880 else
1881 *result = SCIP_DIDNOTRUN;
1882
1883 SCIPdebugMsg(scip, "After additional fixings: %d / %d\n",*nfixings, ntargetfixings);
1884 }
1885 else if( (SCIP_Real)(*nfixings) > nmaxfixings )
1886 {
1887 SCIP_Bool success;
1888
1889 SCIP_CALL( alnsUnfixVariables(scip, heurdata, varbuf, valbuf, nfixings, ntargetfixings, &success) );
1890
1891 assert(success);
1892 *result = SCIP_SUCCESS;
1893 SCIPdebugMsg(scip, "Unfixed variables, fixed variables remaining: %d\n", ntargetfixings);
1894 }
1895 else
1896 {
1897 SCIPdebugMsg(scip, "No additional fixings performed\n");
1898 }
1899
1900 return SCIP_OKAY;
1901}
1902
1903/** change the sub-SCIP by restricting variable domains, changing objective coefficients, or adding constraints */
1904static
1906 SCIP* sourcescip, /**< source SCIP data structure */
1907 SCIP* targetscip, /**< target SCIP data structure */
1908 NH* neighborhood, /**< neighborhood */
1909 SCIP_VAR** targetvars, /**< array of target SCIP variables aligned with source SCIP variables */
1910 int* ndomchgs, /**< pointer to store the number of variable domain changes */
1911 int* nchgobjs, /**< pointer to store the number of changed objective coefficients */
1912 int* naddedconss, /**< pointer to store the number of added constraints */
1913 SCIP_Bool* success /**< pointer to store whether the sub-SCIP has been successfully modified */
1914 )
1915{
1916 assert(sourcescip != NULL);
1917 assert(targetscip != NULL);
1918 assert(neighborhood != NULL);
1919 assert(targetvars != NULL);
1920 assert(ndomchgs != NULL);
1921 assert(nchgobjs != NULL);
1922 assert(naddedconss != NULL);
1923 assert(success != NULL);
1924
1925 *success = FALSE;
1926 *ndomchgs = 0;
1927 *nchgobjs = 0;
1928 *naddedconss = 0;
1929
1930 /* call the change sub-SCIP callback of the neighborhood */
1931 if( neighborhood->changesubscip != NULL )
1932 {
1933 SCIP_CALL( neighborhood->changesubscip(sourcescip, targetscip, neighborhood, targetvars, ndomchgs, nchgobjs, naddedconss, success) );
1934 }
1935 else
1936 {
1937 *success = TRUE;
1938 }
1939
1940 return SCIP_OKAY;
1941}
1942
1943/** set sub-SCIP solving limits */
1944static
1946 SCIP* subscip, /**< SCIP data structure */
1947 SOLVELIMITS* solvelimits /**< pointer to solving limits data structure */
1948 )
1949{
1950 assert(subscip != NULL);
1951 assert(solvelimits != NULL);
1952
1953 assert(solvelimits->nodelimit >= solvelimits->stallnodes);
1954
1955 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", solvelimits->nodelimit) );
1956 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", solvelimits->stallnodes));
1957 SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", solvelimits->timelimit) );
1958 SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", solvelimits->memorylimit) );
1959
1960 return SCIP_OKAY;
1961}
1962
1963/** determine limits for a sub-SCIP */
1964static
1966 SCIP* scip, /**< SCIP data structure */
1967 SCIP_HEUR* heur, /**< this heuristic */
1968 SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
1969 SCIP_Bool* runagain /**< can we solve another sub-SCIP with these limits */
1970 )
1971{
1972 SCIP_HEURDATA* heurdata;
1973 SCIP_Real initfactor;
1974 SCIP_Real nodesquot;
1975 SCIP_Bool avoidmemout;
1976
1977 assert(scip != NULL);
1978 assert(heur != NULL);
1979 assert(solvelimits != NULL);
1980 assert(runagain != NULL);
1981
1982 heurdata = SCIPheurGetData(heur);
1983
1984 /* check whether there is enough time and memory left */
1985 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &solvelimits->timelimit) );
1986 if( ! SCIPisInfinity(scip, solvelimits->timelimit) )
1987 solvelimits->timelimit -= SCIPgetSolvingTime(scip);
1988 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &solvelimits->memorylimit) );
1989 SCIP_CALL( SCIPgetBoolParam(scip, "misc/avoidmemout", &avoidmemout) );
1990
1991 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
1992 if( ! SCIPisInfinity(scip, solvelimits->memorylimit) )
1993 {
1994 solvelimits->memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
1995 solvelimits->memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
1996 }
1997
1998 /* abort if no time is left or not enough memory (we don't abort in this case if misc_avoidmemout == FALSE)
1999 * to create a copy of SCIP, including external memory usage */
2000 if( solvelimits->timelimit <= 0.0 || (avoidmemout && solvelimits->memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0) )
2001 *runagain = FALSE;
2002
2003 nodesquot = heurdata->nodesquot;
2004
2005 /* if the heuristic is used to measure all rewards, it will always be penalized here */
2006 if( heurdata->rewardfile == NULL )
2007 nodesquot *= (SCIPheurGetNBestSolsFound(heur) + 1.0)/(SCIPheurGetNCalls(heur) + 1.0);
2008
2009 nodesquot = MAX(nodesquot, heurdata->nodesquotmin);
2010
2011 /* calculate the search node limit of the heuristic */
2012 solvelimits->stallnodes = (SCIP_Longint)(nodesquot * SCIPgetNNodes(scip));
2013 solvelimits->stallnodes += heurdata->nodesoffset;
2014 solvelimits->stallnodes -= heurdata->usednodes;
2015 solvelimits->stallnodes -= 100 * SCIPheurGetNCalls(heur);
2016 solvelimits->stallnodes = MIN(heurdata->maxnodes, solvelimits->stallnodes);
2017
2018 /* use a smaller budget if not all neighborhoods have been initialized yet */
2019 assert(heurdata->ninitneighborhoods >= 0);
2020 initfactor = (heurdata->nactiveneighborhoods - heurdata->ninitneighborhoods + 1.0) / (heurdata->nactiveneighborhoods + 1.0);
2021 solvelimits->stallnodes = (SCIP_Longint)(solvelimits->stallnodes * initfactor);
2022 solvelimits->nodelimit = (SCIP_Longint)(heurdata->maxnodes);
2023
2024 /* check whether we have enough nodes left to call subproblem solving */
2025 if( solvelimits->stallnodes < heurdata->targetnodes )
2026 *runagain = FALSE;
2027
2028 return SCIP_OKAY;
2029}
2030
2031/** return the bandit algorithm that should be used */
2032static
2034 SCIP_HEURDATA* heurdata /**< heuristic data of the ALNS neighborhood */
2035 )
2036{
2037 assert(heurdata != NULL);
2038 return heurdata->bandit;
2039}
2040
2041/** select a neighborhood depending on the selected bandit algorithm */
2042static
2044 SCIP* scip, /**< SCIP data structure */
2045 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
2046 int* neighborhoodidx /**< pointer to store the selected neighborhood index */
2047 )
2048{
2049 SCIP_BANDIT* bandit;
2050 assert(scip != NULL);
2051 assert(heurdata != NULL);
2052 assert(neighborhoodidx != NULL);
2053
2054 *neighborhoodidx = -1;
2055
2056 bandit = getBandit(heurdata);
2057
2058 SCIP_CALL( SCIPbanditSelect(bandit, neighborhoodidx) );
2059 assert(*neighborhoodidx >= 0);
2060
2061 return SCIP_OKAY;
2062}
2063
2064/** Calculate reward based on the selected reward measure */
2065static
2067 SCIP* scip, /**< SCIP data structure */
2068 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
2069 NH_STATS* runstats, /**< run statistics */
2070 SCIP_Real* rewardptr /**< array to store the computed rewards, total and individual */
2071 )
2072{
2073 SCIP_Real reward = 0.0;
2074 SCIP_Real effort;
2075 int ndiscretevars;
2076
2077 memset(rewardptr, 0, sizeof(*rewardptr)*(int)NREWARDTYPES);
2078
2079 assert(rewardptr != NULL);
2080 assert(runstats->usednodes >= 0);
2081 assert(runstats->nfixings >= 0);
2082
2083 effort = runstats->usednodes / 100.0;
2084
2085 ndiscretevars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
2086 /* assume that every fixed variable linearly reduces the subproblem complexity */
2087 if( ndiscretevars > 0 )
2088 {
2089 effort = (1.0 - (runstats->nfixings / (SCIP_Real)ndiscretevars)) * effort;
2090 }
2091 assert(rewardptr != NULL);
2092
2093 /* a positive reward is only assigned if a new incumbent solution was found */
2094 if( runstats->nbestsolsfound > 0 )
2095 {
2096 SCIP_Real rewardcontrol = heurdata->rewardcontrol;
2097
2098 SCIP_Real lb;
2099 SCIP_Real ub;
2100
2101 /* the indicator function is simply 1.0 */
2102 rewardptr[REWARDTYPE_BESTSOL] = 1.0;
2103 rewardptr[REWARDTYPE_NOSOLPENALTY] = 1.0;
2104
2105 ub = runstats->newupperbound;
2106 lb = SCIPgetLowerbound(scip);
2107
2108 /* compute the closed gap reward */
2109 if( SCIPisEQ(scip, ub, lb) || SCIPisInfinity(scip, runstats->oldupperbound) )
2110 rewardptr[REWARDTYPE_CLOSEDGAP] = 1.0;
2111 else
2112 {
2113 rewardptr[REWARDTYPE_CLOSEDGAP] = (runstats->oldupperbound - ub) / (runstats->oldupperbound - lb);
2114 }
2115
2116 /* the reward is a convex combination of the best solution reward and the reward for the closed gap */
2117 reward = rewardcontrol * rewardptr[REWARDTYPE_BESTSOL] + (1.0 - rewardcontrol) * rewardptr[REWARDTYPE_CLOSEDGAP];
2118
2119 /* optionally, scale the reward by the involved effort */
2120 if( heurdata->scalebyeffort )
2121 reward /= (effort + 1.0);
2122
2123 /* add the baseline and rescale the reward into the interval [baseline, 1.0] */
2124 reward = heurdata->rewardbaseline + (1.0 - heurdata->rewardbaseline) * reward;
2125 }
2126 else
2127 {
2128 /* linearly decrease the reward based on the number of nodes spent */
2129 SCIP_Real maxeffort = heurdata->targetnodes;
2130 SCIP_Real usednodes = runstats->usednodes;
2131
2132 if( ndiscretevars > 0 )
2133 usednodes *= (1.0 - (runstats->nfixings / (SCIP_Real)ndiscretevars));
2134
2135 rewardptr[REWARDTYPE_NOSOLPENALTY] = 1 - (usednodes / maxeffort);
2136 rewardptr[REWARDTYPE_NOSOLPENALTY] = MAX(0.0, rewardptr[REWARDTYPE_NOSOLPENALTY]);
2137 reward = heurdata->rewardbaseline * rewardptr[REWARDTYPE_NOSOLPENALTY];
2138 }
2139
2140 rewardptr[REWARDTYPE_TOTAL] = reward;
2141
2142 return SCIP_OKAY;
2143}
2144
2145/** update internal bandit algorithm statistics for future draws */
2146static
2148 SCIP* scip, /**< SCIP data structure */
2149 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
2150 SCIP_Real reward, /**< measured reward */
2151 int neighborhoodidx /**< the neighborhood that was chosen */
2152 )
2153{
2154 SCIP_BANDIT* bandit;
2155 assert(scip != NULL);
2156 assert(heurdata != NULL);
2157 assert(neighborhoodidx >= 0);
2158 assert(neighborhoodidx < heurdata->nactiveneighborhoods);
2159
2160 bandit = getBandit(heurdata);
2161
2162 SCIPdebugMsg(scip, "Rewarding bandit algorithm action %d with reward %.2f\n", neighborhoodidx, reward);
2163 SCIP_CALL( SCIPbanditUpdate(bandit, neighborhoodidx, reward) );
2164
2165 return SCIP_OKAY;
2166}
2167
2168/** set up the sub-SCIP parameters, objective cutoff, and solution limits */
2169static
2171 SCIP* scip, /**< SCIP data structure */
2172 SCIP* subscip, /**< sub-SCIP data structure */
2173 SCIP_VAR** subvars, /**< array of sub-SCIP variables in the order of the main SCIP */
2174 SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
2175 SCIP_HEUR* heur, /**< this heuristic */
2176 SCIP_Bool objchgd /**< did the objective change between the source and the target SCIP? */
2177 )
2178{
2179 SCIP_HEURDATA* heurdata;
2180 SCIP_Real cutoff;
2181 SCIP_Real upperbound;
2182
2183 heurdata = SCIPheurGetData(heur);
2184
2185 /* do not abort subproblem on CTRL-C */
2186 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
2187
2188 /* disable output to console unless we are in debug mode */
2189 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
2190
2191 /* disable statistic timing inside sub SCIP */
2192 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
2193
2194#ifdef ALNS_SUBSCIPOUTPUT
2195 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
2196 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 1) );
2197 /* enable statistic timing inside sub SCIP */
2198 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", TRUE) );
2199#endif
2200
2201 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->nsolslim) );
2202
2203 /* forbid recursive call of heuristics and separators solving subMIPs */
2204 if( ! heurdata->usesubscipheurs )
2205 {
2206 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
2207 }
2208
2209 /* disable cutting plane separation */
2211
2212 /* disable expensive presolving */
2214
2215 /* use best estimate node selection */
2216 if( SCIPfindNodesel(subscip, "estimate") != NULL && ! SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
2217 {
2218 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
2219 }
2220
2221 /* use inference branching */
2222 if( SCIPfindBranchrule(subscip, "inference") != NULL && ! SCIPisParamFixed(subscip, "branching/inference/priority") )
2223 {
2224 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
2225 }
2226
2227 /* enable conflict analysis and restrict conflict pool */
2228 if( ! SCIPisParamFixed(subscip, "conflict/enable") )
2229 {
2230 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
2231 }
2232
2233 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
2234 {
2235 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
2236 }
2237
2238 if( ! SCIPisParamFixed(subscip, "conflict/maxstoresize") )
2239 {
2240 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
2241 }
2242
2243 /* speed up sub-SCIP by not checking dual LP feasibility */
2244 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
2245
2246 /* add an objective cutoff */
2248 {
2249 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
2250 if( ! SCIPisInfinity(scip, -1.0 * SCIPgetLowerbound(scip)) )
2251 {
2252 cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip)
2253 + heurdata->minimprove * SCIPgetLowerbound(scip);
2254 }
2255 else
2256 {
2257 if( SCIPgetUpperbound(scip) >= 0 )
2258 cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
2259 else
2260 cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
2261 }
2262 cutoff = MIN(upperbound, cutoff);
2263
2264 if( SCIPisObjIntegral(scip) )
2265 cutoff = SCIPfloor(scip, cutoff);
2266
2267 SCIPdebugMsg(scip, "Sub-SCIP cutoff: %15.9" SCIP_REAL_FORMAT " (%15.9" SCIP_REAL_FORMAT " in original space)\n",
2268 cutoff, SCIPretransformObj(scip, cutoff));
2269
2270 /* if the objective changed between the source and the target SCIP, encode the cutoff as a constraint */
2271 if( ! objchgd )
2272 {
2273 SCIP_CALL(SCIPsetObjlimit(subscip, cutoff));
2274
2275 SCIPdebugMsg(scip, "Cutoff added as Objective Limit\n");
2276 }
2277 else
2278 {
2279 SCIP_CONS* objcons;
2280 int nvars;
2281 SCIP_VAR** vars;
2282 int i;
2283
2284 vars = SCIPgetVars(scip);
2285 nvars = SCIPgetNVars(scip);
2286
2287 SCIP_CALL( SCIPcreateConsLinear(subscip, &objcons, "objbound_of_origscip", 0, NULL, NULL, -SCIPinfinity(subscip), cutoff,
2289 for( i = 0; i < nvars; ++i)
2290 {
2291 if( ! SCIPisFeasZero(subscip, SCIPvarGetObj(vars[i])) )
2292 {
2293 assert(subvars[i] != NULL);
2294 SCIP_CALL( SCIPaddCoefLinear(subscip, objcons, subvars[i], SCIPvarGetObj(vars[i])) );
2295 }
2296 }
2297 SCIP_CALL( SCIPaddCons(subscip, objcons) );
2298 SCIP_CALL( SCIPreleaseCons(subscip, &objcons) );
2299
2300 SCIPdebugMsg(scip, "Cutoff added as constraint\n");
2301 }
2302 }
2303
2304 /* set solve limits for sub-SCIP */
2305 SCIP_CALL( setLimits(subscip, solvelimits) );
2306
2307 /* change random seed of sub-SCIP */
2308 if( heurdata->subsciprandseeds )
2309 {
2310 SCIP_CALL( SCIPsetIntParam(subscip, "randomization/randomseedshift", (int)SCIPheurGetNCalls(heur)) );
2311 }
2312
2313 SCIPdebugMsg(scip, "Solve Limits: %lld (%lld) nodes (stall nodes), %.1f sec., %d sols\n",
2314 solvelimits->nodelimit, solvelimits->stallnodes, solvelimits->timelimit, heurdata->nsolslim);
2315
2316 return SCIP_OKAY;
2317}
2318
2319/** execution method of primal heuristic */
2320static
2322{ /*lint --e{715}*/
2323 SCIP_HEURDATA* heurdata;
2324 SCIP_VAR** varbuf;
2325 SCIP_Real* valbuf;
2326 SCIP_VAR** vars;
2327 SCIP_VAR** subvars;
2328 NH_STATS runstats[NNEIGHBORHOODS];
2329 SCIP_STATUS subscipstatus[NNEIGHBORHOODS];
2330 SCIP* subscip = NULL;
2331
2332 int nfixings;
2333 int nvars;
2334 int neighborhoodidx;
2335 int ntries;
2336 SCIP_Bool tryagain;
2337 NH* neighborhood;
2338 SOLVELIMITS solvelimits;
2339 SCIP_Bool success;
2340 SCIP_Bool run;
2341 SCIP_Bool allrewardsmode;
2342 SCIP_Real rewards[NNEIGHBORHOODS][NREWARDTYPES] = {{0}};
2343 int banditidx;
2344
2345 int i;
2346
2347 heurdata = SCIPheurGetData(heur);
2348 assert(heurdata != NULL);
2349
2350 *result = SCIP_DIDNOTRUN;
2351
2352 if( heurdata->nactiveneighborhoods == 0 )
2353 return SCIP_OKAY;
2354
2355 /* we only allow to run multiple times at a node during the root */
2356 if( (heurtiming & SCIP_HEURTIMING_DURINGLPLOOP) && (SCIPgetDepth(scip) > 0 || !heurdata->initduringroot) )
2357 return SCIP_OKAY;
2358
2359 /* update internal incumbent solution */
2360 if( SCIPgetBestSol(scip) != heurdata->lastcallsol )
2361 {
2362 heurdata->lastcallsol = SCIPgetBestSol(scip);
2363 heurdata->firstcallthissol = SCIPheurGetNCalls(heur);
2364 }
2365
2366 /* do not run more than a user-defined number of times on each incumbent (-1: no limit) */
2367 if( heurdata->maxcallssamesol != -1 )
2368 {
2369 SCIP_Longint samesollimit = (heurdata->maxcallssamesol > 0) ?
2370 heurdata->maxcallssamesol :
2371 heurdata->nactiveneighborhoods;
2372
2373 if( SCIPheurGetNCalls(heur) - heurdata->firstcallthissol >= samesollimit )
2374 {
2375 SCIPdebugMsg(scip, "Heuristic already called %" SCIP_LONGINT_FORMAT " times on current incumbent\n", SCIPheurGetNCalls(heur) - heurdata->firstcallthissol);
2376 return SCIP_OKAY;
2377 }
2378 }
2379
2380 /* wait for a sufficient number of nodes since last incumbent solution */
2381 if( SCIPgetDepth(scip) > 0 && SCIPgetBestSol(scip) != NULL
2382 && (SCIPgetNNodes(scip) - SCIPsolGetNodenum(SCIPgetBestSol(scip))) < heurdata->waitingnodes )
2383 {
2384 SCIPdebugMsg(scip, "Waiting nodes not satisfied\n");
2385 return SCIP_OKAY;
2386 }
2387
2388 run = TRUE;
2389 /* check if budget allows a run of the next selected neighborhood */
2390 SCIP_CALL( determineLimits(scip, heur, &solvelimits, &run) );
2391 SCIPdebugMsg(scip, "Budget check: %" SCIP_LONGINT_FORMAT " (%" SCIP_LONGINT_FORMAT ") %s\n", solvelimits.nodelimit, heurdata->targetnodes, run ? "passed" : "must wait");
2392
2393 if( ! run )
2394 return SCIP_OKAY;
2395
2396 /* delay the heuristic if local reduced costs should be used for generic variable unfixing */
2397 if( heurdata->uselocalredcost && (nodeinfeasible || ! SCIPhasCurrentNodeLP(scip) || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL) )
2398 {
2399 *result = SCIP_DELAYED;
2400
2401 return SCIP_OKAY;
2402 }
2403
2404 allrewardsmode = heurdata->rewardfile != NULL;
2405
2406 /* apply some other rules for a fair all rewards mode; in normal execution mode, neighborhoods are iterated through */
2407 if( allrewardsmode )
2408 {
2409 /* most neighborhoods require an incumbent solution */
2410 if( SCIPgetNSols(scip) < 2 )
2411 {
2412 SCIPdebugMsg(scip, "Not enough solutions for all rewards mode\n");
2413 return SCIP_OKAY;
2414 }
2415
2416 /* if the node is infeasible, or has no LP solution, which is required by some neighborhoods
2417 * if we are not in all rewards mode, the neighborhoods delay themselves individually
2418 */
2419 if( nodeinfeasible || ! SCIPhasCurrentNodeLP(scip) || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
2420 {
2421 SCIPdebugMsg(scip, "Delay ALNS heuristic until a feasible node with optimally solved LP relaxation\n");
2422 *result = SCIP_DELAYED;
2423 return SCIP_OKAY;
2424 }
2425 }
2426
2427 /* use the neighborhood that requested a delay or select the next neighborhood to run based on the selected bandit algorithm */
2428 if( heurdata->currneighborhood >= 0 )
2429 {
2430 assert(! allrewardsmode);
2431 banditidx = heurdata->currneighborhood;
2432 SCIPdebugMsg(scip, "Select delayed neighborhood %d (was delayed %d times)\n", banditidx, heurdata->ndelayedcalls);
2433 }
2434 else
2435 {
2436 SCIP_CALL( selectNeighborhood(scip, heurdata, &banditidx) );
2437 SCIPdebugMsg(scip, "Selected neighborhood %d with bandit algorithm\n", banditidx);
2438 }
2439
2440 /* in all rewards mode, we simply loop over all heuristics */
2441 if( ! allrewardsmode )
2442 neighborhoodidx = banditidx;
2443 else
2444 neighborhoodidx = 0;
2445
2446 assert(0 <= neighborhoodidx && neighborhoodidx < NNEIGHBORHOODS);
2447 assert(heurdata->nactiveneighborhoods > neighborhoodidx);
2448
2449 /* allocate memory for variable fixings buffer */
2450 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2451 SCIP_CALL( SCIPallocBufferArray(scip, &varbuf, nvars) );
2452 SCIP_CALL( SCIPallocBufferArray(scip, &valbuf, nvars) );
2453 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
2454
2455 /* initialize neighborhood statistics for a run */
2456 ntries = 1;
2457 do
2458 {
2459 SCIP_HASHMAP* varmapf;
2460 SCIP_EVENTHDLR* eventhdlr;
2461 SCIP_EVENTDATA eventdata;
2462 char probnamesuffix[SCIP_MAXSTRLEN];
2463 SCIP_Real allfixingrate;
2464 int ndomchgs;
2465 int nchgobjs;
2466 int naddedconss;
2467 int v;
2468 SCIP_RETCODE retcode;
2469 SCIP_RESULT fixresult;
2470
2471 tryagain = FALSE;
2472 neighborhood = heurdata->neighborhoods[neighborhoodidx];
2473 SCIPdebugMsg(scip, "Running '%s' neighborhood %d\n", neighborhood->name, neighborhoodidx);
2474
2475 initRunStats(scip, &runstats[neighborhoodidx]);
2476 rewards[neighborhoodidx][REWARDTYPE_TOTAL] = 0.0;
2477
2478 subscipstatus[neighborhoodidx] = SCIP_STATUS_UNKNOWN;
2479 SCIP_CALL( SCIPstartClock(scip, neighborhood->stats.setupclock) );
2480
2481 /* determine variable fixings and objective coefficients of this neighborhood */
2482 SCIP_CALL( neighborhoodFixVariables(scip, heurdata, neighborhood, varbuf, valbuf, &nfixings, &fixresult) );
2483
2484 SCIPdebugMsg(scip, "Fix %d/%d variables, result code %d\n", nfixings, nvars,fixresult);
2485
2486 /* Fixing was not successful, either because the fixing rate was not reached (and no additional variable
2487 * prioritization was used), or the neighborhood requested a delay, e.g., because no LP relaxation solution exists
2488 * at the current node
2489 *
2490 * The ALNS heuristic keeps a delayed neighborhood active and delays itself.
2491 */
2492 if( fixresult != SCIP_SUCCESS )
2493 {
2494 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
2495
2496 /* to determine all rewards, we cannot delay neighborhoods */
2497 if( allrewardsmode )
2498 {
2499 if( ntries == heurdata->nactiveneighborhoods )
2500 break;
2501
2502 neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
2503 ntries++;
2504 tryagain = TRUE;
2505
2506 continue;
2507 }
2508
2509 /* delay the heuristic along with the selected neighborhood
2510 *
2511 * if the neighborhood has been delayed for too many consecutive calls, the delay is treated as a failure */
2512 if( fixresult == SCIP_DELAYED )
2513 {
2514 if( heurdata->ndelayedcalls > (SCIPheurGetFreq(heur) / 4 + 1) )
2515 {
2516 resetCurrentNeighborhood(heurdata);
2517
2518 /* use SCIP_DIDNOTFIND to penalize the neighborhood with a bad reward */
2519 fixresult = SCIP_DIDNOTFIND;
2520 }
2521 else if( heurdata->currneighborhood == -1 )
2522 {
2523 heurdata->currneighborhood = neighborhoodidx;
2524 heurdata->ndelayedcalls = 1;
2525 }
2526 else
2527 {
2528 heurdata->ndelayedcalls++;
2529 }
2530 }
2531
2532 if( fixresult == SCIP_DIDNOTRUN )
2533 {
2534 if( ntries < heurdata->nactiveneighborhoods )
2535 {
2536 SCIP_CALL( updateBanditAlgorithm(scip, heurdata, 0.0, neighborhoodidx) );
2537 SCIP_CALL( selectNeighborhood(scip, heurdata, &neighborhoodidx) );
2538 ntries++;
2539 tryagain = TRUE;
2540
2541 SCIPdebugMsg(scip, "Neighborhood cannot run -> try next neighborhood %d\n", neighborhoodidx);
2542 continue;
2543 }
2544 else
2545 break;
2546 }
2547
2548 assert(fixresult == SCIP_DIDNOTFIND || fixresult == SCIP_DELAYED);
2549 *result = fixresult;
2550 break;
2551 }
2552
2553 *result = SCIP_DIDNOTFIND;
2554
2555 neighborhood->stats.nfixings += nfixings;
2556 runstats[neighborhoodidx].nfixings = nfixings;
2557
2558 SCIP_CALL( SCIPcreate(&subscip) );
2559 SCIP_CALL( SCIPhashmapCreate(&varmapf, SCIPblkmem(scip), nvars) );
2560 (void) SCIPsnprintf(probnamesuffix, SCIP_MAXSTRLEN, "alns_%s", neighborhood->name);
2561
2562 /* todo later: run global propagation for this set of fixings */
2563 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapf, probnamesuffix, varbuf, valbuf, nfixings, FALSE, heurdata->copycuts, &success, NULL) );
2564
2565 /* store sub-SCIP variables in array for faster access */
2566 for( v = 0; v < nvars; ++v )
2567 {
2568 subvars[v] = (SCIP_VAR*)SCIPhashmapGetImage(varmapf, (void *)vars[v]);
2569 }
2570
2571 SCIPhashmapFree(&varmapf);
2572
2573 /* let the neighborhood add additional constraints, or restrict domains */
2574 SCIP_CALL( neighborhoodChangeSubscip(scip, subscip, neighborhood, subvars, &ndomchgs, &nchgobjs, &naddedconss, &success) );
2575
2576 if( ! success )
2577 {
2578 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
2579
2580 if( ! allrewardsmode || ntries == heurdata->nactiveneighborhoods )
2581 break;
2582
2583 neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
2584 ntries++;
2585 tryagain = TRUE;
2586
2587 SCIP_CALL( SCIPfree(&subscip) );
2588
2589 continue;
2590 }
2591
2592 /* set up sub-SCIP parameters */
2593 SCIP_CALL( setupSubScip(scip, subscip, subvars, &solvelimits, heur, nchgobjs > 0) );
2594
2595 /* copy the necessary data into the event data to create new solutions */
2596 eventdata.nodelimit = solvelimits.nodelimit; /*lint !e644*/
2597 eventdata.lplimfac = heurdata->lplimfac;
2598 eventdata.heur = heur;
2599 eventdata.sourcescip = scip;
2600 eventdata.subvars = subvars;
2601 eventdata.runstats = &runstats[neighborhoodidx];
2602 eventdata.allrewardsmode = allrewardsmode;
2603
2604 /* include an event handler to transfer solutions into the main SCIP */
2605 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecAlns, NULL) );
2606
2607 /* transform the problem before catching the events */
2608 SCIP_CALL( SCIPtransformProb(subscip) );
2609 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_ALNS, eventhdlr, &eventdata, NULL) );
2610
2611 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
2612
2613 SCIP_CALL( SCIPstartClock(scip, neighborhood->stats.submipclock) );
2614
2615 /* set up sub-SCIP and run presolving */
2616 retcode = SCIPpresolve(subscip);
2617 if( retcode != SCIP_OKAY )
2618 {
2619 SCIPwarningMessage(scip, "Error while presolving subproblem in ALNS heuristic; sub-SCIP terminated with code <%d>\n", retcode);
2620 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.submipclock) );
2621
2622 SCIPABORT(); /*lint --e{527}*/
2623 break;
2624 }
2625
2626 /* was presolving successful enough regarding fixings? otherwise, terminate */
2627 allfixingrate = (SCIPgetNOrigVars(subscip) - SCIPgetNVars(subscip)) / (SCIP_Real)SCIPgetNOrigVars(subscip);
2628
2629 /* additional variables added in presolving may lead to the subSCIP having more variables than the original */
2630 allfixingrate = MAX(allfixingrate, 0.0);
2631
2632 if( allfixingrate >= neighborhood->fixingrate.targetfixingrate / 2.0 )
2633 {
2634 /* run sub-SCIP for the given budget, and collect statistics */
2635 SCIP_CALL_ABORT( SCIPsolve(subscip) );
2636 }
2637 else
2638 {
2639 SCIPdebugMsg(scip, "Fixed only %.3f of all variables after presolving -> do not solve sub-SCIP\n", allfixingrate);
2640 }
2641
2642#ifdef ALNS_SUBSCIPOUTPUT
2643 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
2644#endif
2645
2646 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.submipclock) );
2647
2648 /* update statistics based on the sub-SCIP run results */
2649 updateRunStats(&runstats[neighborhoodidx], subscip);
2650 subscipstatus[neighborhoodidx] = SCIPgetStatus(subscip);
2651 SCIPdebugMsg(scip, "Status of sub-SCIP run: %d\n", subscipstatus[neighborhoodidx]);
2652
2653 SCIP_CALL( getReward(scip, heurdata, &runstats[neighborhoodidx], rewards[neighborhoodidx]) );
2654
2655 /* in all rewards mode, continue with the next neighborhood */
2656 if( allrewardsmode && ntries < heurdata->nactiveneighborhoods )
2657 {
2658 neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
2659 ntries++;
2660 tryagain = TRUE;
2661
2662 SCIP_CALL( SCIPfree(&subscip) );
2663 }
2664 }
2665 while( tryagain && ! SCIPisStopped(scip) );
2666
2667 if( subscip != NULL )
2668 {
2669 SCIP_CALL( SCIPfree(&subscip) );
2670 }
2671
2672 SCIPfreeBufferArray(scip, &subvars);
2673 SCIPfreeBufferArray(scip, &valbuf);
2674 SCIPfreeBufferArray(scip, &varbuf);
2675
2676 /* update bandit index that may have changed unless we are in all rewards mode */
2677 if( ! allrewardsmode )
2678 banditidx = neighborhoodidx;
2679
2680 if( *result != SCIP_DELAYED )
2681 {
2682 /* decrease the number of neighborhoods that have not been initialized */
2683 if( neighborhood->stats.nruns == 0 )
2684 --heurdata->ninitneighborhoods;
2685
2686 heurdata->usednodes += runstats[banditidx].usednodes;
2687
2688 /* determine the success of this neighborhood, and update the target fixing rate for the next time */
2689 updateNeighborhoodStats(&runstats[banditidx], heurdata->neighborhoods[banditidx], subscipstatus[banditidx]);
2690
2691 /* adjust the fixing rate for this neighborhood
2692 * make no adjustments in all rewards mode, because this only affects 1 of 8 heuristics
2693 */
2694 if( heurdata->adjustfixingrate && ! allrewardsmode )
2695 {
2696 SCIPdebugMsg(scip, "Update fixing rate: %.2f\n", heurdata->neighborhoods[banditidx]->fixingrate.targetfixingrate);
2697 updateFixingRate(heurdata->neighborhoods[banditidx], subscipstatus[banditidx], &runstats[banditidx]);
2698 SCIPdebugMsg(scip, "New fixing rate: %.2f\n", heurdata->neighborhoods[banditidx]->fixingrate.targetfixingrate);
2699 }
2700 /* similarly, update the minimum improvement for the ALNS heuristic */
2701 if( heurdata->adjustminimprove )
2702 {
2703 SCIPdebugMsg(scip, "Update Minimum Improvement: %.4f\n", heurdata->minimprove);
2704 updateMinimumImprovement(heurdata, subscipstatus[banditidx], &runstats[banditidx]);
2705 SCIPdebugMsg(scip, "--> %.4f\n", heurdata->minimprove);
2706 }
2707
2708 /* update the target node limit based on the status of the selected algorithm */
2709 if( heurdata->adjusttargetnodes && SCIPheurGetNCalls(heur) >= heurdata->nactiveneighborhoods )
2710 {
2711 updateTargetNodeLimit(heurdata, &runstats[banditidx], subscipstatus[banditidx]);
2712 }
2713
2714 /* update the bandit algorithm by the measured reward */
2715 SCIP_CALL( updateBanditAlgorithm(scip, heurdata, rewards[banditidx][REWARDTYPE_TOTAL], banditidx) );
2716
2717 resetCurrentNeighborhood(heurdata);
2718 }
2719
2720 /* write single, measured rewards and the bandit index to the reward file */
2721 if( allrewardsmode )
2722 {
2723 int j;
2724 for( j = 0; j < (int)NREWARDTYPES; j++ )
2725 for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
2726 fprintf(heurdata->rewardfile, "%.4f,", rewards[i][j]);
2727
2728 fprintf(heurdata->rewardfile, "%d\n", banditidx);
2729 }
2730
2731 return SCIP_OKAY;
2732}
2733
2734/** callback to collect variable fixings of RENS */
2735static
2736DECL_VARFIXINGS(varFixingsRens)
2737{ /*lint --e{715}*/
2738 int nbinvars;
2739 int nintvars;
2740 SCIP_VAR** vars;
2741 int i;
2742 int *fracidx = NULL;
2743 SCIP_Real* frac = NULL;
2744 int nfracs;
2745
2746 assert(scip != NULL);
2747 assert(varbuf != NULL);
2748 assert(nfixings != NULL);
2749 assert(valbuf != NULL);
2750
2751 *result = SCIP_DELAYED;
2752
2753 if( ! SCIPhasCurrentNodeLP(scip) )
2754 return SCIP_OKAY;
2756 return SCIP_OKAY;
2757
2758 *result = SCIP_DIDNOTRUN;
2759
2760 /* get variable information */
2761 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
2762
2763 /* return if no binary or integer variables are present */
2764 if( nbinvars + nintvars == 0 )
2765 return SCIP_OKAY;
2766
2767 SCIP_CALL( SCIPallocBufferArray(scip, &fracidx, nbinvars + nintvars) );
2768 SCIP_CALL( SCIPallocBufferArray(scip, &frac, nbinvars + nintvars) );
2769
2770 /* loop over binary and integer variables; determine those that should be fixed in the sub-SCIP */
2771 for( nfracs = 0, i = 0; i < nbinvars + nintvars; ++i )
2772 {
2773 SCIP_VAR* var;
2774 SCIP_Real lpsolval;
2775
2776 var = vars[i];
2778 assert((i < nbinvars) == (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY));
2779 lpsolval = SCIPvarGetLPSol(var);
2780
2781 /* fix all binary and integer variables with integer LP solution value */
2782 if( SCIPisFeasIntegral(scip, lpsolval) )
2783 {
2784 tryAdd2variableBuffer(scip, var, lpsolval, varbuf, valbuf, nfixings, TRUE);
2785 }
2786 else
2787 {
2788 frac[nfracs] = SCIPfrac(scip, lpsolval);
2789 frac[nfracs] = MIN(frac[nfracs], 1.0 - frac[nfracs]);
2790 fracidx[nfracs++] = i;
2791 }
2792 }
2793
2794 /* do some additional fixing */
2795 if( *nfixings < neighborhood->fixingrate.targetfixingrate * (nbinvars + nintvars) && nfracs > 0 )
2796 {
2797 SCIPsortDownRealInt(frac, fracidx, nfracs);
2798
2799 /* prefer variables that are almost integer */
2800 for( i = 0; i < nfracs && *nfixings < neighborhood->fixingrate.targetfixingrate * (nbinvars + nintvars); i++ )
2801 {
2802 tryAdd2variableBuffer(scip, vars[fracidx[i]], SCIPround(scip, SCIPvarGetLPSol(vars[fracidx[i]])), varbuf, valbuf, nfixings, TRUE);
2803 }
2804 }
2805
2806 SCIPfreeBufferArray(scip, &frac);
2807 SCIPfreeBufferArray(scip, &fracidx);
2808
2809 *result = SCIP_SUCCESS;
2810
2811 return SCIP_OKAY;
2812}
2813
2814/** callback for RENS subproblem changes */
2815static
2816DECL_CHANGESUBSCIP(changeSubscipRens)
2817{ /*lint --e{715}*/
2818 SCIP_VAR** vars;
2819 int nintvars;
2820 int nbinvars;
2821 int i;
2822
2823 assert(SCIPhasCurrentNodeLP(sourcescip));
2824 assert(SCIPgetLPSolstat(sourcescip) == SCIP_LPSOLSTAT_OPTIMAL);
2825
2826 /* get variable information */
2827 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
2828
2829 /* restrict bounds of integer variables with fractional solution value */
2830 for( i = nbinvars; i < nbinvars + nintvars; ++i )
2831 {
2832 SCIP_VAR* var = vars[i];
2833 SCIP_Real lpsolval = SCIPgetSolVal(sourcescip, NULL, var);
2834
2835 if( subvars[i] == NULL )
2836 continue;
2837
2838 if( ! SCIPisFeasIntegral(sourcescip, lpsolval) )
2839 {
2840 SCIP_Real newlb = SCIPfloor(sourcescip, lpsolval);
2841 SCIP_Real newub = newlb + 1.0;
2842
2843 /* only count this as a domain change if the new lower and upper bound are a further restriction */
2844 if( newlb > SCIPvarGetLbGlobal(subvars[i]) + 0.5 || newub < SCIPvarGetUbGlobal(subvars[i]) - 0.5 )
2845 {
2846 SCIP_CALL( SCIPchgVarLbGlobal(targetscip, subvars[i], newlb) );
2847 SCIP_CALL( SCIPchgVarUbGlobal(targetscip, subvars[i], newub) );
2848 (*ndomchgs)++;
2849 }
2850 }
2851 }
2852
2853 *success = TRUE;
2854
2855 return SCIP_OKAY;
2856}
2857
2858/** collect fixings by matching solution values in a collection of solutions for all binary and integer variables,
2859 * or for a custom set of variables
2860 */
2861static
2863 SCIP* scip, /**< SCIP data structure */
2864 SCIP_SOL** sols, /**< array of 2 or more solutions. It is okay for the array to contain one element
2865 * equal to NULL to represent the current LP solution */
2866 int nsols, /**< number of solutions in the array */
2867 SCIP_VAR** vars, /**< variable array for which solution values must agree */
2868 int nvars, /**< number of variables, or -1 for all binary and integer variables */
2869 SCIP_VAR** varbuf, /**< buffer storage for variable fixings */
2870 SCIP_Real* valbuf, /**< buffer storage for fixing values */
2871 int* nfixings /**< pointer to store the number of fixings */
2872 )
2873{
2874 int v;
2875 int nbinintvars;
2876 SCIP_SOL* firstsol;
2877
2878 assert(scip != NULL);
2879 assert(sols != NULL);
2880 assert(nsols >= 2);
2881 assert(varbuf != NULL);
2882 assert(valbuf != NULL);
2883 assert(nfixings != NULL);
2884 assert(*nfixings == 0);
2885
2886 if( nvars == -1 || vars == NULL )
2887 {
2888 int nbinvars;
2889 int nintvars;
2890 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
2891 nbinintvars = nbinvars + nintvars;
2892 nvars = nbinintvars;
2893 }
2894 firstsol = sols[0];
2895 assert(nvars > 0);
2896
2897 /* loop over integer and binary variables and check if their solution values match in all solutions */
2898 for( v = 0; v < nvars; ++v )
2899 {
2900 SCIP_VAR* var;
2901 SCIP_Real solval;
2902 int s;
2903
2904 var = vars[v];
2906 assert((v < SCIPgetNBinVars(scip)) == (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY));
2907 solval = SCIPgetSolVal(scip, firstsol, var);
2908
2909 /* determine if solution values match in all given solutions */
2910 for( s = 1; s < nsols; ++s )
2911 {
2912 if( !SCIPisFeasZero(scip, solval - SCIPgetSolVal(scip, sols[s], var)) )
2913 break;
2914 }
2915
2916 /* if we did not break early, all solutions agree on the solution value of this variable */
2917 if( s == nsols )
2918 {
2919 tryAdd2variableBuffer(scip, var, solval, varbuf, valbuf, nfixings, TRUE);
2920 }
2921 }
2922
2923 return SCIP_OKAY;
2924}
2925
2926/** callback to collect variable fixings of RINS */
2927static
2928DECL_VARFIXINGS(varFixingsRins)
2929{
2930 /*lint --e{715}*/
2931 int nbinvars;
2932 int nintvars;
2933 SCIP_VAR** vars;
2934 SCIP_SOL* incumbent;
2935 SCIP_SOL* sols[2];
2936 assert(scip != NULL);
2937 assert(varbuf != NULL);
2938 assert(nfixings != NULL);
2939 assert(valbuf != NULL);
2940
2941 *result = SCIP_DELAYED;
2942
2943 if( ! SCIPhasCurrentNodeLP(scip) )
2944 return SCIP_OKAY;
2946 return SCIP_OKAY;
2947
2948 *result = SCIP_DIDNOTRUN;
2949
2950 incumbent = SCIPgetBestSol(scip);
2951 if( incumbent == NULL )
2952 return SCIP_OKAY;
2953
2954 if( SCIPsolGetOrigin(incumbent) == SCIP_SOLORIGIN_ORIGINAL )
2955 return SCIP_OKAY;
2956
2957 /* get variable information */
2958 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
2959
2960 /* return if no binary or integer variables are present */
2961 if( nbinvars + nintvars == 0 )
2962 return SCIP_OKAY;
2963
2964 /* incumbent is reference */
2965 sols[0] = incumbent;
2966 sols[1] = NULL;
2967
2968 SCIP_CALL( fixMatchingSolutionValues(scip, sols, 2, vars, nbinvars + nintvars, varbuf, valbuf, nfixings) );
2969
2970 *result = SCIP_SUCCESS;
2971
2972 return SCIP_OKAY;
2973}
2974
2975/** initialization callback for crossover when a new problem is read */
2976static
2977DECL_NHINIT(nhInitCrossover)
2978{ /*lint --e{715}*/
2979 DATA_CROSSOVER* data;
2980
2981 data = neighborhood->data.crossover;
2982 assert(data != NULL);
2983
2984 if( data->rng != NULL )
2985 SCIPfreeRandom(scip, &data->rng);
2986
2987 data->selsol = NULL;
2988
2989 SCIP_CALL( SCIPcreateRandom(scip, &data->rng, CROSSOVERSEED + (unsigned int)SCIPgetNVars(scip), TRUE) );
2990
2991 return SCIP_OKAY;
2992}
2993
2994/** deinitialization callback for crossover when exiting a problem */
2995static
2996DECL_NHEXIT(nhExitCrossover)
2997{ /*lint --e{715}*/
2998 DATA_CROSSOVER* data;
2999 data = neighborhood->data.crossover;
3000
3001 assert(neighborhood != NULL);
3002 assert(data->rng != NULL);
3003
3004 SCIPfreeRandom(scip, &data->rng);
3005
3006 return SCIP_OKAY;
3007}
3008
3009/** deinitialization callback for crossover before SCIP is freed */
3010static
3011DECL_NHFREE(nhFreeCrossover)
3012{ /*lint --e{715}*/
3013 assert(neighborhood->data.crossover != NULL);
3014 SCIPfreeBlockMemory(scip, &neighborhood->data.crossover);
3015
3016 return SCIP_OKAY;
3017}
3018
3019/** callback to collect variable fixings of crossover */
3020static
3021DECL_VARFIXINGS(varFixingsCrossover)
3022{ /*lint --e{715}*/
3023 DATA_CROSSOVER* data;
3024 SCIP_RANDNUMGEN* rng;
3025 SCIP_SOL** sols;
3026 SCIP_SOL** scipsols;
3027 int nsols;
3028 int lastdraw;
3029 assert(scip != NULL);
3030 assert(varbuf != NULL);
3031 assert(nfixings != NULL);
3032 assert(valbuf != NULL);
3033
3034 data = neighborhood->data.crossover;
3035
3036 assert(data != NULL);
3037 nsols = data->nsols;
3038 data->selsol = NULL;
3039
3040 *result = SCIP_DIDNOTRUN;
3041
3042 /* return if the pool has not enough solutions */
3043 if( nsols > SCIPgetNSols(scip) )
3044 return SCIP_OKAY;
3045
3046 /* return if no binary or integer variables are present */
3048 return SCIP_OKAY;
3049
3050 rng = data->rng;
3051 lastdraw = SCIPgetNSols(scip);
3052 SCIP_CALL( SCIPallocBufferArray(scip, &sols, nsols) );
3053 scipsols = SCIPgetSols(scip);
3054
3055 /* draw as many solutions from the pool as required by crossover, biased towards
3056 * better solutions; therefore, the sorting of the solutions by objective is implicitly used
3057 */
3058 while( nsols > 0 )
3059 {
3060 /* no need for randomization anymore, exactly nsols many solutions remain for the selection */
3061 if( lastdraw == nsols )
3062 {
3063 int s;
3064
3065 /* fill the remaining slots 0,...,nsols - 1 by the solutions at the same places */
3066 for( s = 0; s < nsols; ++s )
3067 sols[s] = scipsols[s];
3068
3069 nsols = 0;
3070 }
3071 else
3072 {
3073 int nextdraw;
3074
3075 assert(nsols < lastdraw);
3076
3077 /* draw from the lastdraw - nsols many solutions nsols - 1, ... lastdraw - 1 such that nsols many solution */
3078 nextdraw = SCIPrandomGetInt(rng, nsols - 1, lastdraw - 1);
3079 assert(nextdraw >= 0);
3080
3081 sols[nsols - 1] = scipsols[nextdraw];
3082 nsols--;
3083 lastdraw = nextdraw;
3084 }
3085 }
3086
3087 SCIP_CALL( fixMatchingSolutionValues(scip, sols, data->nsols, NULL, -1, varbuf, valbuf, nfixings) );
3088
3089 /* store best selected solution as reference solution */
3090 data->selsol = sols[0];
3091 assert(data->selsol != NULL);
3092
3093 *result = SCIP_SUCCESS;
3094
3095 SCIPfreeBufferArray(scip, &sols);
3096
3097 return SCIP_OKAY;
3098}
3099
3100/** callback for crossover reference solution */
3101static
3102DECL_NHREFSOL(nhRefsolCrossover)
3103{ /*lint --e{715}*/
3104 DATA_CROSSOVER* data;
3105
3106 data = neighborhood->data.crossover;
3107
3108 if( data->selsol != NULL )
3109 {
3110 *solptr = data->selsol;
3111 *result = SCIP_SUCCESS;
3112 }
3113 else
3114 {
3115 *result = SCIP_DIDNOTFIND;
3116 }
3117
3118 return SCIP_OKAY;
3119}
3120
3121/** initialization callback for mutation when a new problem is read */
3122static
3123DECL_NHINIT(nhInitMutation)
3124{ /*lint --e{715}*/
3125 DATA_MUTATION* data;
3126 assert(scip != NULL);
3127 assert(neighborhood != NULL);
3128
3129 SCIP_CALL( SCIPallocBlockMemory(scip, &neighborhood->data.mutation) );
3130
3131 data = neighborhood->data.mutation;
3132 assert(data != NULL);
3133
3134 SCIP_CALL( SCIPcreateRandom(scip, &data->rng, MUTATIONSEED + (unsigned int)SCIPgetNVars(scip), TRUE) );
3135
3136 return SCIP_OKAY;
3137}
3138
3139/** deinitialization callback for mutation when exiting a problem */
3140static
3141DECL_NHEXIT(nhExitMutation)
3142{ /*lint --e{715}*/
3143 DATA_MUTATION* data;
3144 assert(scip != NULL);
3145 assert(neighborhood != NULL);
3146 data = neighborhood->data.mutation;
3147 assert(data != NULL);
3148
3149 SCIPfreeRandom(scip, &data->rng);
3150
3151 SCIPfreeBlockMemory(scip, &neighborhood->data.mutation);
3152
3153 return SCIP_OKAY;
3154}
3155
3156/** callback to collect variable fixings of mutation */
3157static
3158DECL_VARFIXINGS(varFixingsMutation)
3159{ /*lint --e{715}*/
3160 SCIP_RANDNUMGEN* rng;
3161
3162 SCIP_VAR** vars;
3163 SCIP_VAR** varscpy;
3164 int i;
3165 int nvars;
3166 int nbinvars;
3167 int nintvars;
3168 int nbinintvars;
3169 int ntargetfixings;
3170 SCIP_SOL* incumbentsol;
3171 SCIP_Real targetfixingrate;
3172
3173 assert(scip != NULL);
3174 assert(neighborhood != NULL);
3175 assert(neighborhood->data.mutation != NULL);
3176 assert(neighborhood->data.mutation->rng != NULL);
3177 rng = neighborhood->data.mutation->rng;
3178
3179 *result = SCIP_DIDNOTRUN;
3180
3181 /* get the problem variables */
3182 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
3183
3184 nbinintvars = nbinvars + nintvars;
3185 if( nbinintvars == 0 )
3186 return SCIP_OKAY;
3187
3188 incumbentsol = SCIPgetBestSol(scip);
3189 if( incumbentsol == NULL )
3190 return SCIP_OKAY;
3191
3192 targetfixingrate = neighborhood->fixingrate.targetfixingrate;
3193 ntargetfixings = (int)(targetfixingrate * nbinintvars) + 1;
3194
3195 /* don't continue if number of discrete variables is too small to reach target fixing rate */
3196 if( nbinintvars <= ntargetfixings )
3197 return SCIP_OKAY;
3198
3199 *result = SCIP_DIDNOTFIND;
3200
3201 /* copy variables into a buffer array */
3202 SCIP_CALL( SCIPduplicateBufferArray(scip, &varscpy, vars, nbinintvars) );
3203
3204 /* partially perturb the array until the number of target fixings is reached */
3205 for( i = 0; *nfixings < ntargetfixings && i < nbinintvars; ++i )
3206 {
3207 int randint = SCIPrandomGetInt(rng, i, nbinintvars - 1);
3208 assert(randint < nbinintvars);
3209
3210 if( randint > i )
3211 {
3212 SCIPswapPointers((void**)&varscpy[i], (void**)&varscpy[randint]);
3213 }
3214 /* copy the selected variables and their solution values into the buffer */
3215 tryAdd2variableBuffer(scip, varscpy[i], SCIPgetSolVal(scip, incumbentsol, varscpy[i]), varbuf, valbuf, nfixings, TRUE);
3216 }
3217
3218 assert(i == nbinintvars || *nfixings == ntargetfixings);
3219
3220 /* Not reaching the number of target fixings means that there is a significant fraction (at least 1 - targetfixingrate)
3221 * of variables for which the incumbent solution value does not lie within the global bounds anymore. This is a nonsuccess
3222 * for the neighborhood (additional fixings are not possible), which is okay because the incumbent solution is
3223 * significantly outdated
3224 */
3225 if( *nfixings == ntargetfixings )
3226 *result = SCIP_SUCCESS;
3227
3228 /* free the buffer array */
3229 SCIPfreeBufferArray(scip, &varscpy);
3230
3231 return SCIP_OKAY;
3232}
3233
3234/** add local branching constraint */
3235static
3237 SCIP* sourcescip, /**< source SCIP data structure */
3238 SCIP* targetscip, /**< target SCIP data structure */
3239 SCIP_VAR** subvars, /**< array of sub SCIP variables in same order as source SCIP variables */
3240 int distance, /**< right hand side of the local branching constraint */
3241 SCIP_Bool* success, /**< pointer to store of a local branching constraint has been successfully added */
3242 int* naddedconss /**< pointer to increase the number of added constraints */
3243 )
3244{
3245 int nbinvars;
3246 int i;
3247 SCIP_SOL* referencesol;
3248 SCIP_CONS* localbranchcons;
3249 SCIP_VAR** vars;
3250 SCIP_Real* consvals;
3251 SCIP_Real rhs;
3252
3253 assert(sourcescip != NULL);
3254 assert(*success == FALSE);
3255
3256 nbinvars = SCIPgetNBinVars(sourcescip);
3257 vars = SCIPgetVars(sourcescip);
3258
3259 if( nbinvars <= 3 )
3260 return SCIP_OKAY;
3261
3262 referencesol = SCIPgetBestSol(sourcescip);
3263 if( referencesol == NULL )
3264 return SCIP_OKAY;
3265
3266 rhs = (SCIP_Real)distance;
3267 rhs = MAX(rhs, 2.0);
3268
3269 SCIP_CALL( SCIPallocBufferArray(sourcescip, &consvals, nbinvars) );
3270
3271 /* loop over binary variables and fill the local branching constraint */
3272 for( i = 0; i < nbinvars; ++i )
3273 {
3274 /* skip variables that are not present in sub-SCIP */
3275 if( subvars[i] == NULL )
3276 continue;
3277
3278 if( SCIPisEQ(sourcescip, SCIPgetSolVal(sourcescip, referencesol, vars[i]), 0.0) )
3279 consvals[i] = 1.0;
3280 else
3281 {
3282 consvals[i] = -1.0;
3283 rhs -= 1.0;
3284 }
3285 }
3286
3287 /* create the local branching constraint in the target scip */
3288 SCIP_CALL( SCIPcreateConsBasicLinear(targetscip, &localbranchcons, "localbranch", nbinvars, subvars, consvals, -SCIPinfinity(sourcescip), rhs) );
3289 SCIP_CALL( SCIPaddCons(targetscip, localbranchcons) );
3290 SCIP_CALL( SCIPreleaseCons(targetscip, &localbranchcons) );
3291
3292 *naddedconss = 1;
3293 *success = TRUE;
3294
3295 SCIPfreeBufferArray(sourcescip, &consvals);
3296
3297 return SCIP_OKAY;
3298}
3299
3300/** callback for local branching subproblem changes */
3301static
3302DECL_CHANGESUBSCIP(changeSubscipLocalbranching)
3303{ /*lint --e{715}*/
3304
3305 SCIP_CALL( addLocalBranchingConstraint(sourcescip, targetscip, subvars, (int)(0.2 * SCIPgetNBinVars(sourcescip)), success, naddedconss) );
3306
3307 return SCIP_OKAY;
3308}
3309
3310/** callback for proximity subproblem changes */
3311static
3312DECL_CHANGESUBSCIP(changeSubscipProximity)
3313{ /*lint --e{715}*/
3314 SCIP_SOL* referencesol;
3315 SCIP_VAR** vars;
3316 int nbinvars;
3317 int nintvars;
3318 int nvars;
3319 int i;
3320
3321 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
3322
3323 if( nbinvars == 0 )
3324 return SCIP_OKAY;
3325
3326 referencesol = SCIPgetBestSol(sourcescip);
3327 if( referencesol == NULL )
3328 return SCIP_OKAY;
3329
3330 /* loop over binary variables, set objective coefficients based on reference solution in a local branching fashion */
3331 for( i = 0; i < nbinvars; ++i )
3332 {
3333 SCIP_Real newobj;
3334
3335 /* skip variables not present in sub-SCIP */
3336 if( subvars[i] == NULL )
3337 continue;
3338
3339 if( SCIPgetSolVal(sourcescip, referencesol, vars[i]) < 0.5 )
3340 newobj = -1.0;
3341 else
3342 newobj = 1.0;
3343 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], newobj) );
3344 }
3345
3346 /* loop over the remaining variables and change their objective coefficients to 0 */
3347 for( ; i < nvars; ++i )
3348 {
3349 /* skip variables not present in sub-SCIP */
3350 if( subvars[i] == NULL )
3351 continue;
3352
3353 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], 0.0) );
3354 }
3355
3356 *nchgobjs = nvars;
3357 *success = TRUE;
3358
3359 return SCIP_OKAY;
3360}
3361
3362/** callback for zeroobjective subproblem changes */
3363static
3364DECL_CHANGESUBSCIP(changeSubscipZeroobjective)
3365{ /*lint --e{715}*/
3366 SCIP_CONSHDLR* conshdlrnl;
3367 SCIP_VAR** vars;
3368 int nvars;
3369 int i;
3370
3371 assert(*success == FALSE);
3372
3373 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, NULL, NULL, NULL, NULL) );
3374
3375 /* do not run if no objective variables are present */
3376 if( SCIPgetNObjVars(sourcescip) == 0 )
3377 return SCIP_OKAY;
3378
3379 /* zeroobj may trigger fixing objvar in nonlinear constraint to infinity,
3380 * which expr_var.c:simplify cannot handle at the moment; also #3273
3381 */
3382 conshdlrnl = SCIPfindConshdlr(sourcescip, "nonlinear");
3383 if( conshdlrnl != NULL && SCIPconshdlrGetNActiveConss(conshdlrnl) > 0 )
3384 return SCIP_OKAY;
3385
3386 /* loop over the variables and change their objective coefficients to 0 */
3387 for( i = 0; i < nvars; ++i )
3388 {
3389 /* skip variables not present in sub-SCIP */
3390 if( subvars[i] == NULL )
3391 continue;
3392
3393 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], 0.0) );
3394 }
3395
3396 *nchgobjs = nvars;
3397 *success = TRUE;
3398
3399 return SCIP_OKAY;
3400}
3401
3402/** compute tightened bounds for integer variables depending on how much the LP and the incumbent solution values differ */
3403static
3405 SCIP* scip, /**< SCIP data structure of the original problem */
3406 SCIP_VAR* var, /**< the variable for which bounds should be computed */
3407 SCIP_Real* lbptr, /**< pointer to store the lower bound in the DINS sub-SCIP */
3408 SCIP_Real* ubptr /**< pointer to store the upper bound in the DINS sub-SCIP */
3409 )
3410{
3411 SCIP_Real mipsol;
3412 SCIP_Real lpsol;
3413
3414 SCIP_Real lbglobal;
3415 SCIP_Real ubglobal;
3416 SCIP_SOL* bestsol;
3417
3418 /* get the bounds for each variable */
3419 lbglobal = SCIPvarGetLbGlobal(var);
3420 ubglobal = SCIPvarGetUbGlobal(var);
3421
3422 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
3423 /* get the current LP solution for each variable */
3424 lpsol = SCIPvarGetLPSol(var);
3425
3426 /* get the current MIP solution for each variable */
3427 bestsol = SCIPgetBestSol(scip);
3428 mipsol = SCIPgetSolVal(scip, bestsol, var);
3429
3430 /* if the solution values differ by 0.5 or more, the variable is rebounded, otherwise it is just copied */
3431 if( REALABS(lpsol - mipsol) >= 0.5 )
3432 {
3433 SCIP_Real range;
3434
3435 *lbptr = lbglobal;
3436 *ubptr = ubglobal;
3437
3438 /* create an equally sized range around lpsol for general integers: bounds are lpsol +- (mipsol-lpsol) */
3439 range = 2 * lpsol - mipsol;
3440
3441 if( mipsol >= lpsol )
3442 {
3443 range = SCIPfeasCeil(scip, range);
3444 *lbptr = MAX(*lbptr, range);
3445
3446 /* when the bound new upper bound is equal to the current MIP solution, we set both bounds to the integral bound (without eps) */
3447 if( SCIPisFeasEQ(scip, mipsol, *lbptr) )
3448 *ubptr = *lbptr;
3449 else
3450 *ubptr = mipsol;
3451 }
3452 else
3453 {
3454 range = SCIPfeasFloor(scip, range);
3455 *ubptr = MIN(*ubptr, range);
3456
3457 /* when the bound new upper bound is equal to the current MIP solution, we set both bounds to the integral bound (without eps) */
3458 if( SCIPisFeasEQ(scip, mipsol, *ubptr) )
3459 *lbptr = *ubptr;
3460 else
3461 *lbptr = mipsol;
3462 }
3463
3464 /* the global domain of variables might have been reduced since incumbent was found: adjust lb and ub accordingly */
3465 *lbptr = MAX(*lbptr, lbglobal);
3466 *ubptr = MIN(*ubptr, ubglobal);
3467 }
3468 else
3469 {
3470 /* the global domain of variables might have been reduced since incumbent was found: adjust it accordingly */
3471 *lbptr = MAX(mipsol, lbglobal);
3472 *ubptr = MIN(mipsol, ubglobal);
3473 }
3474}
3475
3476/** callback to collect variable fixings of DINS */
3477static
3478DECL_VARFIXINGS(varFixingsDins)
3479{
3480 DATA_DINS* data;
3481 SCIP_SOL* rootlpsol;
3482 SCIP_SOL** sols;
3483 int nsols;
3484 int nmipsols;
3485 int nbinvars;
3486 int nintvars;
3487 SCIP_VAR** vars;
3488 int v;
3489
3490 data = neighborhood->data.dins;
3491 assert(data != NULL);
3492 nmipsols = SCIPgetNSols(scip);
3493 nmipsols = MIN(nmipsols, data->npoolsols);
3494
3495 *result = SCIP_DELAYED;
3496
3498 return SCIP_OKAY;
3499
3500 *result = SCIP_DIDNOTRUN;
3501
3502 if( nmipsols == 0 )
3503 return SCIP_OKAY;
3504
3505 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
3506
3507 if( nbinvars + nintvars == 0 )
3508 return SCIP_OKAY;
3509
3510 SCIP_CALL( SCIPcreateSol(scip, &rootlpsol, NULL) );
3511
3512 /* save root solution LP values in solution */
3513 for( v = 0; v < nbinvars + nintvars; ++v )
3514 {
3515 SCIP_CALL( SCIPsetSolVal(scip, rootlpsol, vars[v], SCIPvarGetRootSol(vars[v])) );
3516 }
3517
3518 /* add the node and the root LP solution */
3519 nsols = nmipsols + 2;
3520
3521 SCIP_CALL( SCIPallocBufferArray(scip, &sols, nsols) );
3522
3523 /* incumbent is reference */
3524 BMScopyMemoryArray(sols, SCIPgetSols(scip), nmipsols); /*lint !e866*/
3525 sols[nmipsols] = NULL;
3526 sols[nmipsols + 1] = rootlpsol;
3527
3528 /* 1. Binary variables are fixed if their values agree in all the solutions */
3529 if( nbinvars > 0 )
3530 {
3531 SCIP_CALL( fixMatchingSolutionValues(scip, sols, nsols, vars, nbinvars, varbuf, valbuf, nfixings) );
3532 }
3533
3534 /* 2. Integer variables are fixed if they have a very low distance between the incumbent and the root LP solution */
3535 for( v = nbinvars; v < nintvars; ++v )
3536 {
3537 SCIP_Real lb;
3538 SCIP_Real ub;
3539 computeIntegerVariableBoundsDins(scip, vars[v], &lb, &ub);
3540
3541 if( ub - lb < 0.5 )
3542 {
3543 assert(SCIPisFeasIntegral(scip, lb));
3544 tryAdd2variableBuffer(scip, vars[v], lb, varbuf, valbuf, nfixings, TRUE);
3545 }
3546 }
3547
3548 *result = SCIP_SUCCESS;
3549
3550 SCIPfreeBufferArray(scip, &sols);
3551
3552 SCIP_CALL( SCIPfreeSol(scip, &rootlpsol) );
3553
3554 return SCIP_OKAY;
3555}
3556
3557/** callback for DINS subproblem changes */
3558static
3559DECL_CHANGESUBSCIP(changeSubscipDins)
3560{ /*lint --e{715}*/
3561 SCIP_VAR** vars;
3562 int nintvars;
3563 int nbinvars;
3564 int v;
3565
3566 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
3567
3568 /* 1. loop over integer variables and tighten the bounds */
3569 for( v = nbinvars; v < nintvars; ++v )
3570 {
3571 SCIP_Real lb;
3572 SCIP_Real ub;
3573
3574 /* skip variables not present in sub-SCIP */
3575 if( subvars[v] == NULL )
3576 continue;
3577
3578 computeIntegerVariableBoundsDins(sourcescip, vars[v], &lb, &ub);
3579
3580 SCIP_CALL( SCIPchgVarLbGlobal(targetscip, subvars[v], lb) );
3581 SCIP_CALL( SCIPchgVarUbGlobal(targetscip, subvars[v], ub) );
3582 ++(*ndomchgs);
3583 }
3584
3585 /* 2. add local branching constraint for binary variables */
3586 SCIP_CALL( addLocalBranchingConstraint(sourcescip, targetscip, subvars, (int)(0.1 * SCIPgetNBinVars(sourcescip)), success, naddedconss) );
3587
3588 *success = TRUE;
3589
3590 return SCIP_OKAY;
3591}
3592
3593/** deinitialization callback for DINS before SCIP is freed */
3594static
3595DECL_NHFREE(nhFreeDins)
3596{
3597 assert(neighborhood->data.dins != NULL);
3598
3599 SCIPfreeBlockMemory(scip, &neighborhood->data.dins);
3600
3601 return SCIP_OKAY;
3602}
3603
3604/** deinitialization callback for trustregion before SCIP is freed */
3605static
3606DECL_NHFREE(nhFreeTrustregion)
3607{
3608 assert(neighborhood->data.trustregion != NULL);
3609
3610 SCIPfreeBlockMemory(scip, &neighborhood->data.trustregion);
3611
3612 return SCIP_OKAY;
3613}
3614
3615/** add trust region neighborhood constraint and auxiliary objective variable */
3616static
3617DECL_CHANGESUBSCIP(changeSubscipTrustregion)
3618{ /*lint --e{715}*/
3619 DATA_TRUSTREGION* data;
3620
3621 assert(success != NULL);
3622
3623 if( !SCIPgetBestSol(sourcescip) )
3624 {
3625 SCIPdebugMsg(sourcescip, "changeSubscipTrustregion unsuccessful, because it was called without incumbent being present\n");
3626 *success = FALSE;
3627
3628 return SCIP_OKAY;
3629 }
3630
3631 data = neighborhood->data.trustregion;
3632
3633 /* adding the neighborhood constraint for the trust region heuristic */
3634 SCIP_CALL( SCIPaddTrustregionNeighborhoodConstraint(sourcescip, targetscip, subvars, data->violpenalty) );
3635
3636 /* incrementing the change in objective since an additional variable is added to the objective to penalize the
3637 * violation of the trust region.
3638 */
3639 ++(*nchgobjs);
3640
3641 return SCIP_OKAY;
3642}
3643
3644/** callback that returns the incumbent solution as a reference point */
3645static
3646DECL_NHREFSOL(nhRefsolIncumbent)
3647{ /*lint --e{715}*/
3648 assert(scip != NULL);
3649
3650 if( SCIPgetBestSol(scip) != NULL )
3651 {
3652 *result = SCIP_SUCCESS;
3653 *solptr = SCIPgetBestSol(scip);
3654 }
3655 else
3656 {
3657 *result = SCIP_DIDNOTFIND;
3658 }
3659
3660 return SCIP_OKAY;
3661}
3662
3663
3664/** callback function that deactivates a neighborhood on problems with no discrete variables */
3665static
3666DECL_NHDEACTIVATE(nhDeactivateDiscreteVars)
3667{ /*lint --e{715}*/
3668 assert(scip != NULL);
3669 assert(deactivate != NULL);
3670
3671 /* deactivate if no discrete variables are present */
3672 *deactivate = (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip) == 0);
3673
3674 return SCIP_OKAY;
3675}
3676
3677/** callback function that deactivates a neighborhood on problems with no binary variables */
3678static
3679DECL_NHDEACTIVATE(nhDeactivateBinVars)
3680{ /*lint --e{715}*/
3681 assert(scip != NULL);
3682 assert(deactivate != NULL);
3683
3684 /* deactivate if no discrete variables are present */
3685 *deactivate = (SCIPgetNBinVars(scip) == 0);
3686
3687 return SCIP_OKAY;
3688}
3689
3690/** callback function that deactivates a neighborhood on problems with no objective variables */
3691static
3692DECL_NHDEACTIVATE(nhDeactivateObjVars)
3693{ /*lint --e{715}*/
3694 assert(scip != NULL);
3695 assert(deactivate != NULL);
3696
3697 /* deactivate if no discrete variables are present */
3698 *deactivate = (SCIPgetNObjVars(scip) == 0);
3699
3700 return SCIP_OKAY;
3701}
3702
3703
3704/** include all neighborhoods */
3705static
3707 SCIP* scip, /**< SCIP data structure */
3708 SCIP_HEURDATA* heurdata /**< heuristic data of the ALNS heuristic */
3709 )
3710{
3711 NH* rens;
3712 NH* rins;
3713 NH* mutation;
3714 NH* localbranching;
3715 NH* crossover;
3716 NH* proximity;
3717 NH* zeroobjective;
3718 NH* dins;
3719 NH* trustregion;
3720
3721 heurdata->nneighborhoods = 0;
3722
3723 /* include the RENS neighborhood */
3724 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &rens, "rens",
3726 varFixingsRens, changeSubscipRens, NULL, NULL, NULL, NULL, nhDeactivateDiscreteVars) );
3727
3728 /* include the RINS neighborhood */
3729 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &rins, "rins",
3731 varFixingsRins, NULL, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateDiscreteVars) );
3732
3733 /* include the mutation neighborhood */
3734 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &mutation, "mutation",
3736 varFixingsMutation, NULL, nhInitMutation, nhExitMutation, NULL, nhRefsolIncumbent, nhDeactivateDiscreteVars) );
3737
3738 /* include the local branching neighborhood */
3739 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &localbranching, "localbranching",
3741 NULL, changeSubscipLocalbranching, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateBinVars) );
3742
3743 /* include the crossover neighborhood */
3744 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &crossover, "crossover",
3746 varFixingsCrossover, NULL,
3747 nhInitCrossover, nhExitCrossover, nhFreeCrossover, nhRefsolCrossover, nhDeactivateDiscreteVars) );
3748
3749 /* allocate data for crossover to include the parameter */
3751 crossover->data.crossover->rng = NULL;
3752
3753 /* add crossover neighborhood parameters */
3754 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/alns/crossover/nsols", "the number of solutions that crossover should combine",
3755 &crossover->data.crossover->nsols, TRUE, DEFAULT_NSOLS_CROSSOVER, 2, 10, NULL, NULL) );
3756
3757 /* include the Proximity neighborhood */
3758 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &proximity, "proximity",
3760 NULL, changeSubscipProximity, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateBinVars) );
3761
3762 /* include the Zeroobjective neighborhood */
3763 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &zeroobjective, "zeroobjective",
3765 NULL, changeSubscipZeroobjective, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateObjVars) );
3766
3767 /* include the DINS neighborhood */
3768 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &dins, "dins",
3770 varFixingsDins, changeSubscipDins, NULL, NULL, nhFreeDins, nhRefsolIncumbent, nhDeactivateBinVars) );
3771
3772 /* allocate data for DINS to include the parameter */
3774
3775 /* add DINS neighborhood parameters */
3776 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/alns/dins/npoolsols",
3777 "number of pool solutions where binary solution values must agree",
3778 &dins->data.dins->npoolsols, TRUE, DEFAULT_NPOOLSOLS_DINS, 1, 100, NULL, NULL) );
3779
3780 /* include the trustregion neighborhood */
3781 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &trustregion, "trustregion",
3783 NULL, changeSubscipTrustregion, NULL, NULL, nhFreeTrustregion, nhRefsolIncumbent, nhDeactivateBinVars) );
3784
3785 /* allocate data for trustregion to include the parameter */
3787
3788 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/trustregion/violpenalty",
3789 "the penalty for each change in the binary variables from the candidate solution",
3791
3792 return SCIP_OKAY;
3793}
3794
3795/** initialization method of primal heuristic (called after problem was transformed) */
3796static
3798{ /*lint --e{715}*/
3799 SCIP_HEURDATA* heurdata;
3800 int i;
3801
3802 assert(scip != NULL);
3803 assert(heur != NULL);
3804
3805 heurdata = SCIPheurGetData(heur);
3806 assert(heurdata != NULL);
3807
3808 /* reactivate all neighborhoods if a new problem is read in */
3809 heurdata->nactiveneighborhoods = heurdata->nneighborhoods;
3810
3811 /* initialize neighborhoods for new problem */
3812 for( i = 0; i < heurdata->nneighborhoods; ++i )
3813 {
3814 NH* neighborhood = heurdata->neighborhoods[i];
3815
3816 SCIP_CALL( neighborhoodInit(scip, neighborhood) );
3817
3818 SCIP_CALL( resetFixingRate(scip, &neighborhood->fixingrate) );
3819
3820 SCIP_CALL( neighborhoodStatsReset(scip, &neighborhood->stats) );
3821 }
3822
3823 /* open reward file for reading */
3824 if( strcmp(heurdata->rewardfilename, DEFAULT_REWARDFILENAME) != 0 )
3825 {
3826 heurdata->rewardfile = fopen(heurdata->rewardfilename, "w");
3827
3828 if( heurdata->rewardfile == NULL )
3829 {
3830 SCIPerrorMessage("Error: Could not open reward file <%s>\n", heurdata->rewardfilename);
3831 return SCIP_FILECREATEERROR;
3832 }
3833
3834 SCIPdebugMsg(scip, "Writing reward information to <%s>\n", heurdata->rewardfilename);
3835 }
3836 else
3837 heurdata->rewardfile = NULL;
3838
3839 return SCIP_OKAY;
3840}
3841
3842
3843/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
3844static
3846{ /*lint --e{715}*/
3847 SCIP_HEURDATA* heurdata;
3848 int i;
3849 SCIP_Real* priorities;
3850 unsigned int initseed;
3851
3852 assert(scip != NULL);
3853 assert(heur != NULL);
3854
3855 heurdata = SCIPheurGetData(heur);
3856 assert(heurdata != NULL);
3857 heurdata->nactiveneighborhoods = heurdata->nneighborhoods;
3858
3859 SCIP_CALL( SCIPallocBufferArray(scip, &priorities, heurdata->nactiveneighborhoods) );
3860
3861 /* init neighborhoods for new problem by resetting their statistics and fixing rate */
3862 for( i = heurdata->nneighborhoods - 1; i >= 0; --i )
3863 {
3864 NH* neighborhood = heurdata->neighborhoods[i];
3865 SCIP_Bool deactivate;
3866
3867 SCIP_CALL( neighborhood->nhdeactivate(scip, &deactivate) );
3868
3869 /* disable inactive neighborhoods */
3870 if( deactivate || ! neighborhood->active )
3871 {
3872 if( heurdata->nactiveneighborhoods - 1 > i )
3873 {
3874 assert(heurdata->neighborhoods[heurdata->nactiveneighborhoods - 1]->active);
3875 SCIPswapPointers((void **)&heurdata->neighborhoods[i], (void **)&heurdata->neighborhoods[heurdata->nactiveneighborhoods - 1]);
3876 }
3877 heurdata->nactiveneighborhoods--;
3878 }
3879 }
3880
3881 /* collect neighborhood priorities */
3882 for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
3883 priorities[i] = heurdata->neighborhoods[i]->priority;
3884
3885 initseed = (unsigned int)(heurdata->seed + SCIPgetNVars(scip));
3886
3887 /* active neighborhoods might change between init calls, reset functionality must take this into account */
3888 if( heurdata->bandit != NULL && SCIPbanditGetNActions(heurdata->bandit) != heurdata->nactiveneighborhoods )
3889 {
3890 SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
3891
3892 heurdata->bandit = NULL;
3893 }
3894
3895 if( heurdata->nactiveneighborhoods > 0 )
3896 { /* create or reset bandit algorithm */
3897 if( heurdata->bandit == NULL )
3898 {
3899 SCIP_CALL( createBandit(scip, heurdata, priorities, initseed) );
3900
3901 resetMinimumImprovement(heurdata);
3902 resetTargetNodeLimit(heurdata);
3903 }
3904 else if( heurdata->resetweights )
3905 {
3906 SCIP_CALL( SCIPresetBandit(scip, heurdata->bandit, priorities, initseed) );
3907
3908 resetMinimumImprovement(heurdata);
3909 resetTargetNodeLimit(heurdata);
3910 }
3911 }
3912
3913 heurdata->usednodes = 0;
3914 heurdata->ninitneighborhoods = heurdata->nactiveneighborhoods;
3915
3916 heurdata->lastcallsol = NULL;
3917 heurdata->firstcallthissol = 0;
3918
3919 resetCurrentNeighborhood(heurdata);
3920
3921 SCIPfreeBufferArray(scip, &priorities);
3922
3923 return SCIP_OKAY;
3924}
3925
3926
3927/** deinitialization method of primal heuristic (called before transformed problem is freed) */
3928static
3930{ /*lint --e{715}*/
3931 SCIP_HEURDATA* heurdata;
3932 int i;
3933
3934 assert(scip != NULL);
3935 assert(heur != NULL);
3936
3937 heurdata = SCIPheurGetData(heur);
3938 assert(heurdata != NULL);
3939
3940 /* free neighborhood specific data */
3941 for( i = 0; i < heurdata->nneighborhoods; ++i )
3942 {
3943 NH* neighborhood = heurdata->neighborhoods[i];
3944
3945 SCIP_CALL( neighborhoodExit(scip, neighborhood) );
3946 }
3947
3948 if( heurdata->rewardfile != NULL )
3949 {
3950 fclose(heurdata->rewardfile);
3951 heurdata->rewardfile = NULL;
3952 }
3953
3954 return SCIP_OKAY;
3955}
3956
3957/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
3958static
3960{ /*lint --e{715}*/
3961 SCIP_HEURDATA* heurdata;
3962 int i;
3963
3964 assert(scip != NULL);
3965 assert(heur != NULL);
3966
3967 heurdata = SCIPheurGetData(heur);
3968 assert(heurdata != NULL);
3969
3970 /* bandits are only initialized if a problem has been read */
3971 if( heurdata->bandit != NULL )
3972 {
3973 SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
3974 }
3975
3976 /* free neighborhoods */
3977 for( i = 0; i < heurdata->nneighborhoods; ++i )
3978 {
3979 SCIP_CALL( alnsFreeNeighborhood(scip, &(heurdata->neighborhoods[i])) );
3980 }
3981
3982 SCIPfreeBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS);
3983
3984 SCIPfreeBlockMemory(scip, &heurdata);
3985
3986 return SCIP_OKAY;
3987}
3988
3989/** output method of statistics table to output file stream 'file' */
3990static
3991SCIP_DECL_TABLEOUTPUT(tableOutputNeighborhood)
3992{ /*lint --e{715}*/
3993 SCIP_HEURDATA* heurdata;
3994
3995 assert(SCIPfindHeur(scip, HEUR_NAME) != NULL);
3997 assert(heurdata != NULL);
3998
3999 printNeighborhoodStatistics(scip, heurdata, file);
4000
4001 return SCIP_OKAY;
4002}
4003
4004/*
4005 * primal heuristic specific interface methods
4006 */
4007
4008/** creates the alns primal heuristic and includes it in SCIP */
4010 SCIP* scip /**< SCIP data structure */
4011 )
4012{
4013 SCIP_HEURDATA* heurdata;
4014 SCIP_HEUR* heur;
4015
4016 /* create alns primal heuristic data */
4017 heurdata = NULL;
4018 heur = NULL;
4019
4020 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
4021 BMSclearMemory(heurdata);
4022
4023 /* TODO make this a user parameter? */
4024 heurdata->lplimfac = LPLIMFAC;
4025
4026 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS) );
4027
4028 /* include primal heuristic */
4031 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecAlns, heurdata) );
4032
4033 assert(heur != NULL);
4034
4035 /* include all neighborhoods */
4036 SCIP_CALL( includeNeighborhoods(scip, heurdata) );
4037
4038 /* set non fundamental callbacks via setter functions */
4039 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyAlns) );
4040 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeAlns) );
4041 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitAlns) );
4042 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolAlns) );
4043 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitAlns) );
4044
4045 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/shownbstats",
4046 "show statistics on neighborhoods?",
4047 &heurdata->shownbstats, TRUE, DEFAULT_SHOWNBSTATS, NULL, NULL) );
4048
4049 /* add alns primal heuristic parameters */
4050 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
4051 "maximum number of nodes to regard in the subproblem",
4052 &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
4053
4054 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
4055 "offset added to the nodes budget",
4056 &heurdata->nodesoffset, FALSE, DEFAULT_NODESOFFSET, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
4057
4058 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
4059 "minimum number of nodes required to start a sub-SCIP",
4060 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
4061
4062 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/waitingnodes",
4063 "number of nodes since last incumbent solution that the heuristic should wait",
4064 &heurdata->waitingnodes, TRUE, DEFAULT_WAITINGNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
4065
4066 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
4067 "fraction of nodes compared to the main SCIP for budget computation",
4068 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
4069 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquotmin",
4070 "lower bound fraction of nodes compared to the main SCIP for budget computation",
4071 &heurdata->nodesquotmin, FALSE, DEFAULT_NODESQUOTMIN, 0.0, 1.0, NULL, NULL) );
4072
4073 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/startminimprove",
4074 "initial factor by which ALNS should at least improve the incumbent",
4075 &heurdata->startminimprove, TRUE, DEFAULT_STARTMINIMPROVE, 0.0, 1.0, NULL, NULL) );
4076
4077 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprovelow",
4078 "lower threshold for the minimal improvement over the incumbent",
4079 &heurdata->minimprovelow, TRUE, DEFAULT_MINIMPROVELOW, 0.0, 1.0, NULL, NULL) );
4080
4081 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprovehigh",
4082 "upper bound for the minimal improvement over the incumbent",
4083 &heurdata->minimprovehigh, TRUE, DEFAULT_MINIMPROVEHIGH, 0.0, 1.0, NULL, NULL) );
4084
4085 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nsolslim",
4086 "limit on the number of improving solutions in a sub-SCIP call",
4087 &heurdata->nsolslim, FALSE, DEFAULT_NSOLSLIM, -1, INT_MAX, NULL, NULL) );
4088
4089 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/banditalgo",
4090 "the bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy, exp.3-(i)x",
4091 &heurdata->banditalgo, TRUE, DEFAULT_BANDITALGO, "uegi", NULL, NULL) );
4092
4093 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/gamma",
4094 "weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3",
4095 &heurdata->exp3_gamma, TRUE, DEFAULT_GAMMA, 0.0, 1.0, NULL, NULL) );
4096
4097 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/beta",
4098 "reward offset between 0 and 1 at every observation for Exp.3",
4099 &heurdata->exp3_beta, TRUE, DEFAULT_BETA, 0.0, 1.0, NULL, NULL) );
4100
4101 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/alpha",
4102 "parameter to increase the confidence width in UCB",
4103 &heurdata->ucb_alpha, TRUE, DEFAULT_ALPHA, 0.0, 100.0, NULL, NULL) );
4104
4105 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usedistances",
4106 "distances from fixed variables be used for variable prioritization",
4107 &heurdata->usedistances, TRUE, DEFAULT_USEDISTANCES, NULL, NULL) );
4108
4109 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useredcost",
4110 "should reduced cost scores be used for variable prioritization?",
4111 &heurdata->useredcost, TRUE, DEFAULT_USEREDCOST, NULL, NULL) );
4112
4113 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/domorefixings",
4114 "should the ALNS heuristic do more fixings by itself based on variable prioritization "
4115 "until the target fixing rate is reached?",
4116 &heurdata->domorefixings, TRUE, DEFAULT_DOMOREFIXINGS, NULL, NULL) );
4117
4118 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/adjustfixingrate",
4119 "should the heuristic adjust the target fixing rate based on the success?",
4120 &heurdata->adjustfixingrate, TRUE, DEFAULT_ADJUSTFIXINGRATE, NULL, NULL) );
4121
4122 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usesubscipheurs",
4123 "should the heuristic activate other sub-SCIP heuristics during its search?",
4124 &heurdata->usesubscipheurs, TRUE, DEFAULT_USESUBSCIPHEURS, NULL, NULL) );
4125
4126 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/rewardcontrol",
4127 "reward control to increase the weight of the simple solution indicator and decrease the weight of the closed gap reward",
4128 &heurdata->rewardcontrol, TRUE, DEFAULT_REWARDCONTROL, 0.0, 1.0, NULL, NULL) );
4129
4130 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/targetnodefactor",
4131 "factor by which target node number is eventually increased",
4132 &heurdata->targetnodefactor, TRUE, DEFAULT_TARGETNODEFACTOR, 1.0, 1e+5, NULL, NULL) );
4133
4134 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/seed",
4135 "initial random seed for bandit algorithms and random decisions by neighborhoods",
4136 &heurdata->seed, FALSE, DEFAULT_SEED, 0, INT_MAX, NULL, NULL) );
4137 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxcallssamesol",
4138 "number of allowed executions of the heuristic on the same incumbent solution (-1: no limit, 0: number of active neighborhoods)",
4139 &heurdata->maxcallssamesol, TRUE, DEFAULT_MAXCALLSSAMESOL, -1, 100, NULL, NULL) );
4140
4141 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/adjustminimprove",
4142 "should the factor by which the minimum improvement is bound be dynamically updated?",
4143 &heurdata->adjustminimprove, TRUE, DEFAULT_ADJUSTMINIMPROVE, NULL, NULL) );
4144
4145 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/adjusttargetnodes",
4146 "should the target nodes be dynamically adjusted?",
4147 &heurdata->adjusttargetnodes, TRUE, DEFAULT_ADJUSTTARGETNODES, NULL, NULL) );
4148
4149 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/eps",
4150 "increase exploration in epsilon-greedy bandit algorithm",
4151 &heurdata->epsgreedy_eps, TRUE, DEFAULT_EPS, 0.0, 1.0, NULL, NULL) );
4152
4153 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/rewardbaseline",
4154 "the reward baseline to separate successful and failed calls",
4155 &heurdata->rewardbaseline, TRUE, DEFAULT_REWARDBASELINE, 0.0, 0.99, NULL, NULL) );
4156
4157 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/resetweights",
4158 "should the bandit algorithms be reset when a new problem is read?",
4159 &heurdata->resetweights, TRUE, DEFAULT_RESETWEIGHTS, NULL, NULL) );
4160
4161 SCIP_CALL( SCIPaddStringParam(scip, "heuristics/" HEUR_NAME "/rewardfilename", "file name to store all rewards and the selection of the bandit",
4162 &heurdata->rewardfilename, TRUE, DEFAULT_REWARDFILENAME, NULL, NULL) );
4163
4164 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/subsciprandseeds",
4165 "should random seeds of sub-SCIPs be altered to increase diversification?",
4166 &heurdata->subsciprandseeds, TRUE, DEFAULT_SUBSCIPRANDSEEDS, NULL, NULL) );
4167
4168 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/scalebyeffort",
4169 "should the reward be scaled by the effort?",
4170 &heurdata->scalebyeffort, TRUE, DEFAULT_SCALEBYEFFORT, NULL, NULL) );
4171
4172 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
4173 "should cutting planes be copied to the sub-SCIP?",
4174 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
4175
4176 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/fixtol",
4177 "tolerance by which the fixing rate may be missed without generic fixing",
4178 &heurdata->fixtol, TRUE, DEFAULT_FIXTOL, 0.0, 1.0, NULL, NULL) );
4179
4180 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/unfixtol",
4181 "tolerance by which the fixing rate may be exceeded without generic unfixing",
4182 &heurdata->unfixtol, TRUE, DEFAULT_UNFIXTOL, 0.0, 1.0, NULL, NULL) );
4183
4184 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselocalredcost",
4185 "should local reduced costs be used for generic (un)fixing?",
4186 &heurdata->uselocalredcost, TRUE, DEFAULT_USELOCALREDCOST, NULL, NULL) );
4187
4188 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usepscost",
4189 "should pseudo cost scores be used for variable priorization?",
4190 &heurdata->usepscost, TRUE, DEFAULT_USEPSCOST, NULL, NULL) );
4191
4192 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/initduringroot",
4193 "should the heuristic be executed multiple times during the root node?",
4194 &heurdata->initduringroot, TRUE, DEFAULT_INITDURINGROOT, NULL, NULL) );
4195
4198 NULL, NULL, NULL, NULL, NULL, NULL, tableOutputNeighborhood,
4200
4201 return SCIP_OKAY;
4202}
static GRAPHNODE ** active
SCIP_VAR ** b
Definition: circlepacking.c:65
Constraint handler for linear constraints in their most general form, .
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define SCIP_Longint
Definition: def.h:157
#define SCIP_REAL_MAX
Definition: def.h:173
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define SCIP_ALLOC(x)
Definition: def.h:384
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define SCIP_LONGINT_MAX
Definition: def.h:158
#define SCIP_REAL_FORMAT
Definition: def.h:175
#define SCIP_CALL(x)
Definition: def.h:373
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 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 SCIPtranslateSubSol(SCIP *scip, SCIP *subscip, SCIP_SOL *subsol, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_SOL **newsol)
Definition: scip_copy.c:1408
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:606
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:734
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:349
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:317
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:508
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2220
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2082
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
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip_prob.c:2432
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:3111
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3264
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3077
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:250
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 SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:167
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 SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:194
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 SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip_param.c:307
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:953
SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
Definition: scip_param.c:661
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 SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:979
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10399
SCIP_RETCODE SCIPincludeHeurAlns(SCIP *scip)
Definition: heur_alns.c:4009
SCIP_RETCODE SCIPresetBandit(SCIP *scip, SCIP_BANDIT *bandit, SCIP_Real *priorities, unsigned int seed)
Definition: scip_bandit.c:91
SCIP_RETCODE SCIPbanditUpdate(SCIP_BANDIT *bandit, int action, SCIP_Real score)
Definition: bandit.c:174
int SCIPbanditGetNActions(SCIP_BANDIT *bandit)
Definition: bandit.c:303
SCIP_Real SCIPgetProbabilityExp3IX(SCIP_BANDIT *exp3ix, int action)
SCIP_Real * SCIPgetWeightsEpsgreedy(SCIP_BANDIT *epsgreedy)
SCIP_RANDNUMGEN * SCIPbanditGetRandnumgen(SCIP_BANDIT *bandit)
Definition: bandit.c:293
SCIP_RETCODE SCIPcreateBanditExp3(SCIP *scip, SCIP_BANDIT **exp3, SCIP_Real *priorities, SCIP_Real gammaparam, SCIP_Real beta, int nactions, unsigned int initseed)
Definition: bandit_exp3.c:311
SCIP_RETCODE SCIPcreateBanditEpsgreedy(SCIP *scip, SCIP_BANDIT **epsgreedy, SCIP_Real *priorities, SCIP_Real eps, SCIP_Bool usemodification, SCIP_Bool preferrecent, SCIP_Real decayfactor, int avglim, int nactions, unsigned int initseed)
SCIP_Real SCIPgetConfidenceBoundUcb(SCIP_BANDIT *ucb, int action)
Definition: bandit_ucb.c:264
SCIP_RETCODE SCIPcreateBanditExp3IX(SCIP *scip, SCIP_BANDIT **exp3ix, SCIP_Real *priorities, int nactions, unsigned int initseed)
SCIP_RETCODE SCIPbanditSelect(SCIP_BANDIT *bandit, int *action)
Definition: bandit.c:153
SCIP_RETCODE SCIPcreateBanditUcb(SCIP *scip, SCIP_BANDIT **ucb, SCIP_Real *priorities, SCIP_Real alpha, int nactions, unsigned int initseed)
Definition: bandit_ucb.c:339
SCIP_RETCODE SCIPfreeBandit(SCIP *scip, SCIP_BANDIT **bandit)
Definition: scip_bandit.c:107
SCIP_Real SCIPgetProbabilityExp3(SCIP_BANDIT *exp3, int action)
Definition: bandit_exp3.c:363
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip_branch.c:304
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4678
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
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:293
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: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:122
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:183
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip_heur.c:215
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1599
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1579
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip_heur.c:231
SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition: scip_heur.c:263
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:199
int SCIPheurGetFreq(SCIP_HEUR *heur)
Definition: heur.c:1538
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1453
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:168
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip_mem.c:126
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip_mem.c:100
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#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_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip_nodesel.c:242
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2165
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:180
SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
Definition: sol.c:2711
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:837
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:2784
int SCIPgetNSols(SCIP *scip)
Definition: scip_sol.c:2066
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_sol.c:1250
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip_sol.c:2115
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:3247
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:3046
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip_sol.c:1073
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1343
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip_sol.c:1428
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip_solve.c:223
SCIP_RETCODE SCIPpresolve(SCIP *scip)
Definition: scip_solve.c:2332
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip_solve.c:3436
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2502
SCIP_Real SCIPgetUpperbound(SCIP *scip)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
SCIP_Longint SCIPgetNLPs(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(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_TABLE * SCIPfindTable(SCIP *scip, const char *name)
Definition: scip_table.c:99
SCIP_RETCODE SCIPincludeTable(SCIP *scip, const char *name, const char *desc, SCIP_Bool active, SCIP_DECL_TABLECOPY((*tablecopy)), SCIP_DECL_TABLEFREE((*tablefree)), SCIP_DECL_TABLEINIT((*tableinit)), SCIP_DECL_TABLEEXIT((*tableexit)), SCIP_DECL_TABLEINITSOL((*tableinitsol)), SCIP_DECL_TABLEEXITSOL((*tableexitsol)), SCIP_DECL_TABLEOUTPUT((*tableoutput)), SCIP_TABLEDATA *tabledata, int position, SCIP_STAGE earlieststage)
Definition: scip_table.c:61
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip_timing.c:76
SCIP_RETCODE SCIPresetClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip_timing.c:144
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip_timing.c:178
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip_timing.c:378
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip_timing.c:127
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip_timing.c:319
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip_timing.c:161
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisDualfeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisDualfeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisDualfeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPsumepsilon(SCIP *scip)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_RETCODE SCIPvariablegraphBreadthFirst(SCIP *scip, SCIP_VGRAPH *vargraph, SCIP_VAR **startvars, int nstartvars, int *distances, int maxdistance, int maxvars, int maxbinintvars)
Definition: heur.c:1690
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17546
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13723
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17934
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17592
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18096
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17776
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17427
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13358
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5066
SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
Definition: scip_var.c:8907
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18460
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5155
SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1864
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18086
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13790
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4636
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:10133
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10111
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
void SCIPselectInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int k, int len)
void SCIPselectDownInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int k, int len)
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10880
static void tryAdd2variableBuffer(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, SCIP_Bool integer)
Definition: heur_alns.c:1363
static void updateRunStats(NH_STATS *stats, SCIP *subscip)
Definition: heur_alns.c:1054
#define DEFAULT_ACTIVE_MUTATION
Definition: heur_alns.c:169
#define DEFAULT_MINFIXINGRATE_ZEROOBJECTIVE
Definition: heur_alns.c:187
enum HistIndex HISTINDEX
Definition: heur_alns.c:335
static SCIP_RETCODE alnsFixMoreVariables(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_SOL *refsol, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, int ntargetfixings, SCIP_Bool *success)
Definition: heur_alns.c:1429
#define DECL_NHEXIT(x)
Definition: heur_alns.c:292
static SCIP_RETCODE alnsFreeNeighborhood(SCIP *scip, NH **neighborhood)
Definition: heur_alns.c:861
#define TABLE_POSITION_NEIGHBORHOOD
Definition: heur_alns.c:215
#define DEFAULT_NODESQUOT
Definition: heur_alns.c:91
static void increaseFixingRate(NH_FIXINGRATE *fx)
Definition: heur_alns.c:558
#define DEFAULT_MINIMPROVEHIGH
Definition: heur_alns.c:108
#define DEFAULT_MAXCALLSSAMESOL
Definition: heur_alns.c:102
#define NNEIGHBORHOODS
Definition: heur_alns.c:84
#define DEFAULT_NSOLSLIM
Definition: heur_alns.c:94
#define DECL_NHDEACTIVATE(x)
Definition: heur_alns.c:319
static SCIP_DECL_HEURINIT(heurInitAlns)
Definition: heur_alns.c:3797
static SCIP_RETCODE neighborhoodStatsReset(SCIP *scip, NH_STATS *stats)
Definition: heur_alns.c:773
#define DEFAULT_MINIMPROVELOW
Definition: heur_alns.c:107
#define DEFAULT_REWARDBASELINE
Definition: heur_alns.c:123
#define DEFAULT_PRIORITY_RENS
Definition: heur_alns.c:160
#define DEFAULT_ACTIVE_PROXIMITY
Definition: heur_alns.c:179
#define DEFAULT_NODESQUOTMIN
Definition: heur_alns.c:92
#define DEFAULT_MINFIXINGRATE_DINS
Definition: heur_alns.c:192
#define DEFAULT_SEED
Definition: heur_alns.c:152
#define DEFAULT_ACTIVE_RINS
Definition: heur_alns.c:164
static void updateNeighborhoodStats(NH_STATS *runstats, NH *neighborhood, SCIP_STATUS subscipstatus)
Definition: heur_alns.c:1172
#define TABLE_NAME_NEIGHBORHOOD
Definition: heur_alns.c:213
#define DEFAULT_COPYCUTS
Definition: heur_alns.c:148
#define DEFAULT_MAXNODES
Definition: heur_alns.c:96
static SCIP_RETCODE neighborhoodGetRefsol(SCIP *scip, NH *neighborhood, SCIP_SOL **solptr)
Definition: heur_alns.c:1395
#define DEFAULT_USEREDCOST
Definition: heur_alns.c:139
#define HEUR_TIMING
Definition: heur_alns.c:81
#define DEFAULT_MINNODES
Definition: heur_alns.c:95
#define DEFAULT_ADJUSTFIXINGRATE
Definition: heur_alns.c:144
#define DEFAULT_ADJUSTMINIMPROVE
Definition: heur_alns.c:111
static void decreaseFixingRate(NH_FIXINGRATE *fx)
Definition: heur_alns.c:571
#define DECL_NHINIT(x)
Definition: heur_alns.c:286
static void increaseMinimumImprovement(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:697
#define DECL_NHFREE(x)
Definition: heur_alns.c:298
#define MINIMPROVEFAC
Definition: heur_alns.c:109
#define DEFAULT_FIXTOL
Definition: heur_alns.c:124
static SCIP_RETCODE updateBanditAlgorithm(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Real reward, int neighborhoodidx)
Definition: heur_alns.c:2147
#define HEUR_FREQOFS
Definition: heur_alns.c:79
#define FIXINGRATE_STARTINC
Definition: heur_alns.c:146
#define HEUR_DESC
Definition: heur_alns.c:75
static void resetMinimumImprovement(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:687
#define DEFAULT_MAXFIXINGRATE_RENS
Definition: heur_alns.c:158
#define DEFAULT_PRIORITY_PROXIMITY
Definition: heur_alns.c:180
static void resetTargetNodeLimit(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:641
static SCIP_RETCODE neighborhoodInit(SCIP *scip, NH *neighborhood)
Definition: heur_alns.c:892
#define DEFAULT_STARTMINIMPROVE
Definition: heur_alns.c:110
#define DEFAULT_ACTIVE_TRUSTREGION
Definition: heur_alns.c:199
#define DEFAULT_MINFIXINGRATE_RENS
Definition: heur_alns.c:157
#define DEFAULT_MAXFIXINGRATE_DINS
Definition: heur_alns.c:193
#define FIXINGRATE_DECAY
Definition: heur_alns.c:145
#define DEFAULT_MINFIXINGRATE_RINS
Definition: heur_alns.c:162
static SCIP_DECL_EVENTEXEC(eventExecAlns)
Definition: heur_alns.c:1005
#define DEFAULT_PRIORITY_ZEROOBJECTIVE
Definition: heur_alns.c:190
static void updateMinimumImprovement(SCIP_HEURDATA *heurdata, SCIP_STATUS subscipstatus, NH_STATS *runstats)
Definition: heur_alns.c:722
#define DEFAULT_WAITINGNODES
Definition: heur_alns.c:97
#define DEFAULT_NODESOFFSET
Definition: heur_alns.c:93
#define TABLE_DESC_NEIGHBORHOOD
Definition: heur_alns.c:214
#define DECL_CHANGESUBSCIP(x)
Definition: heur_alns.c:274
RewardType
Definition: heur_alns.c:219
@ REWARDTYPE_NOSOLPENALTY
Definition: heur_alns.c:223
@ REWARDTYPE_BESTSOL
Definition: heur_alns.c:221
@ REWARDTYPE_TOTAL
Definition: heur_alns.c:220
@ NREWARDTYPES
Definition: heur_alns.c:224
@ REWARDTYPE_CLOSEDGAP
Definition: heur_alns.c:222
static SCIP_DECL_HEURINITSOL(heurInitsolAlns)
Definition: heur_alns.c:3845
#define DEFAULT_RESETWEIGHTS
Definition: heur_alns.c:121
#define HEUR_DISPCHAR
Definition: heur_alns.c:76
#define HEUR_MAXDEPTH
Definition: heur_alns.c:80
static void increaseTargetNodeLimit(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:628
#define HEUR_PRIORITY
Definition: heur_alns.c:77
#define DEFAULT_MAXFIXINGRATE_MUTATION
Definition: heur_alns.c:168
#define TABLE_EARLIEST_STAGE_NEIGHBORHOOD
Definition: heur_alns.c:216
static SCIP_DECL_HEURFREE(heurFreeAlns)
Definition: heur_alns.c:3959
#define DEFAULT_ADJUSTTARGETNODES
Definition: heur_alns.c:112
static void updateTargetNodeLimit(SCIP_HEURDATA *heurdata, NH_STATS *runstats, SCIP_STATUS subscipstatus)
Definition: heur_alns.c:650
#define DECL_NHREFSOL(x)
Definition: heur_alns.c:311
#define DEFAULT_USELOCALREDCOST
Definition: heur_alns.c:126
#define DEFAULT_MAXFIXINGRATE_TRUSTREGION
Definition: heur_alns.c:198
#define DEFAULT_MAXFIXINGRATE_ZEROOBJECTIVE
Definition: heur_alns.c:188
static void updateFixingRate(NH *neighborhood, SCIP_STATUS subscipstatus, NH_STATS *runstats)
Definition: heur_alns.c:581
#define HEUR_NAME
Definition: heur_alns.c:74
static SCIP_DECL_SORTINDCOMP(sortIndCompAlns)
Definition: heur_alns.c:1212
static void initRunStats(SCIP *scip, NH_STATS *stats)
Definition: heur_alns.c:1039
static SCIP_DECL_HEURCOPY(heurCopyAlns)
Definition: heur_alns.c:1642
static SCIP_BANDIT * getBandit(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:2033
static SCIP_RETCODE selectNeighborhood(SCIP *scip, SCIP_HEURDATA *heurdata, int *neighborhoodidx)
Definition: heur_alns.c:2043
#define DEFAULT_ACTIVE_RENS
Definition: heur_alns.c:159
#define NHISTENTRIES
Definition: heur_alns.c:336
static void updateFixingRateIncrement(NH_FIXINGRATE *fx)
Definition: heur_alns.c:544
#define DEFAULT_MINFIXINGRATE_CROSSOVER
Definition: heur_alns.c:182
static SCIP_RETCODE addLocalBranchingConstraint(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **subvars, int distance, SCIP_Bool *success, int *naddedconss)
Definition: heur_alns.c:3236
#define DEFAULT_REWARDCONTROL
Definition: heur_alns.c:119
#define DEFAULT_ACTIVE_ZEROOBJECTIVE
Definition: heur_alns.c:189
#define DEFAULT_MINFIXINGRATE_LOCALBRANCHING
Definition: heur_alns.c:172
#define SCIP_EVENTTYPE_ALNS
Definition: heur_alns.c:210
HistIndex
Definition: heur_alns.c:326
@ HIDX_STALLNODE
Definition: heur_alns.c:330
@ HIDX_OTHER
Definition: heur_alns.c:333
@ HIDX_SOLLIM
Definition: heur_alns.c:332
@ HIDX_USR
Definition: heur_alns.c:328
@ HIDX_OPT
Definition: heur_alns.c:327
@ HIDX_INFEAS
Definition: heur_alns.c:331
@ HIDX_NODELIM
Definition: heur_alns.c:329
static SCIP_RETCODE determineLimits(SCIP *scip, SCIP_HEUR *heur, SOLVELIMITS *solvelimits, SCIP_Bool *runagain)
Definition: heur_alns.c:1965
#define DEFAULT_PRIORITY_CROSSOVER
Definition: heur_alns.c:185
#define DEFAULT_DOMOREFIXINGS
Definition: heur_alns.c:142
static SCIP_RETCODE setLimits(SCIP *subscip, SOLVELIMITS *solvelimits)
Definition: heur_alns.c:1945
#define DEFAULT_INITDURINGROOT
Definition: heur_alns.c:101
#define DEFAULT_VIOLPENALTY_TRUSTREGION
Definition: heur_alns.c:205
#define DEFAULT_UNFIXTOL
Definition: heur_alns.c:125
static SCIP_RETCODE resetFixingRate(SCIP *scip, NH_FIXINGRATE *fixingrate)
Definition: heur_alns.c:516
#define DEFAULT_ALPHA
Definition: heur_alns.c:134
static SCIP_DECL_HEUREXIT(heurExitAlns)
Definition: heur_alns.c:3929
#define MUTATIONSEED
Definition: heur_alns.c:153
#define DEFAULT_ACTIVE_LOCALBRANCHING
Definition: heur_alns.c:174
static void decreaseMinimumImprovement(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:709
static SCIP_RETCODE fixMatchingSolutionValues(SCIP *scip, SCIP_SOL **sols, int nsols, SCIP_VAR **vars, int nvars, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings)
Definition: heur_alns.c:2862
#define DEFAULT_PRIORITY_MUTATION
Definition: heur_alns.c:170
#define DEFAULT_PRIORITY_RINS
Definition: heur_alns.c:165
#define DEFAULT_REWARDFILENAME
Definition: heur_alns.c:149
static SCIP_Real getVariablePscostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real refsolval, SCIP_Bool uselocallpsol)
Definition: heur_alns.c:1334
static int getHistIndex(SCIP_STATUS subscipstatus)
Definition: heur_alns.c:1068
#define DEFAULT_ACTIVE_DINS
Definition: heur_alns.c:194
#define EVENTHDLR_DESC
Definition: heur_alns.c:209
#define DEFAULT_PRIORITY_TRUSTREGION
Definition: heur_alns.c:200
#define LPLIMFAC
Definition: heur_alns.c:100
#define CROSSOVERSEED
Definition: heur_alns.c:154
#define DEFAULT_MAXFIXINGRATE_LOCALBRANCHING
Definition: heur_alns.c:173
#define HEUR_FREQ
Definition: heur_alns.c:78
#define DEFAULT_SUBSCIPRANDSEEDS
Definition: heur_alns.c:122
#define DEFAULT_NPOOLSOLS_DINS
Definition: heur_alns.c:204
static void computeIntegerVariableBoundsDins(SCIP *scip, SCIP_VAR *var, SCIP_Real *lbptr, SCIP_Real *ubptr)
Definition: heur_alns.c:3404
#define DEFAULT_MAXFIXINGRATE_RINS
Definition: heur_alns.c:163
static SCIP_RETCODE includeNeighborhoods(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:3706
#define DEFAULT_MINFIXINGRATE_MUTATION
Definition: heur_alns.c:167
#define DEFAULT_EPS
Definition: heur_alns.c:133
#define DEFAULT_TARGETNODEFACTOR
Definition: heur_alns.c:98
#define DEFAULT_MAXFIXINGRATE_CROSSOVER
Definition: heur_alns.c:183
#define DEFAULT_NSOLS_CROSSOVER
Definition: heur_alns.c:203
#define DEFAULT_USEDISTANCES
Definition: heur_alns.c:141
#define DEFAULT_SCALEBYEFFORT
Definition: heur_alns.c:120
static void resetCurrentNeighborhood(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:533
static SCIP_RETCODE getReward(SCIP *scip, SCIP_HEURDATA *heurdata, NH_STATS *runstats, SCIP_Real *rewardptr)
Definition: heur_alns.c:2066
static SCIP_Real getVariableRedcostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real refsolval, SCIP_Bool uselocalredcost)
Definition: heur_alns.c:1281
#define HEUR_USESSUBSCIP
Definition: heur_alns.c:82
static SCIP_DECL_HEUREXEC(heurExecAlns)
Definition: heur_alns.c:2321
#define DEFAULT_BETA
Definition: heur_alns.c:127
#define DEFAULT_SHOWNBSTATS
Definition: heur_alns.c:86
static SCIP_RETCODE alnsUnfixVariables(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, int ntargetfixings, SCIP_Bool *success)
Definition: heur_alns.c:1660
static SCIP_RETCODE neighborhoodExit(SCIP *scip, NH *neighborhood)
Definition: heur_alns.c:911
#define DEFAULT_ACTIVE_CROSSOVER
Definition: heur_alns.c:184
#define DEFAULT_USESUBSCIPHEURS
Definition: heur_alns.c:147
#define DEFAULT_PRIORITY_DINS
Definition: heur_alns.c:195
#define EVENTHDLR_NAME
Definition: heur_alns.c:208
static void printNeighborhoodStatistics(SCIP *scip, SCIP_HEURDATA *heurdata, FILE *file)
Definition: heur_alns.c:1094
static SCIP_RETCODE setupSubScip(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SOLVELIMITS *solvelimits, SCIP_HEUR *heur, SCIP_Bool objchgd)
Definition: heur_alns.c:2170
#define DEFAULT_MAXFIXINGRATE_PROXIMITY
Definition: heur_alns.c:178
static SCIP_RETCODE neighborhoodChangeSubscip(SCIP *sourcescip, SCIP *targetscip, NH *neighborhood, SCIP_VAR **targetvars, int *ndomchgs, int *nchgobjs, int *naddedconss, SCIP_Bool *success)
Definition: heur_alns.c:1905
#define DECL_VARFIXINGS(x)
Definition: heur_alns.c:257
#define DEFAULT_PRIORITY_LOCALBRANCHING
Definition: heur_alns.c:175
#define DEFAULT_MINFIXINGRATE_TRUSTREGION
Definition: heur_alns.c:197
#define DEFAULT_BESTSOLWEIGHT
Definition: heur_alns.c:117
#define DEFAULT_BANDITALGO
Definition: heur_alns.c:118
#define DEFAULT_MINFIXINGRATE_PROXIMITY
Definition: heur_alns.c:177
static SCIP_RETCODE createBandit(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Real *priorities, unsigned int initseed)
Definition: heur_alns.c:1599
static SCIP_RETCODE neighborhoodFixVariables(SCIP *scip, SCIP_HEURDATA *heurdata, NH *neighborhood, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, SCIP_RESULT *result)
Definition: heur_alns.c:1807
#define DEFAULT_GAMMA
Definition: heur_alns.c:135
static SCIP_DECL_TABLEOUTPUT(tableOutputNeighborhood)
Definition: heur_alns.c:3991
#define LRATEMIN
Definition: heur_alns.c:99
#define DEFAULT_USEPSCOST
Definition: heur_alns.c:140
static SCIP_RETCODE alnsIncludeNeighborhood(SCIP *scip, SCIP_HEURDATA *heurdata, NH **neighborhood, const char *name, SCIP_Real minfixingrate, SCIP_Real maxfixingrate, SCIP_Bool active, SCIP_Real priority, DECL_VARFIXINGS((*varfixings)), DECL_CHANGESUBSCIP((*changesubscip)), DECL_NHINIT((*nhinit)), DECL_NHEXIT((*nhexit)), DECL_NHFREE((*nhfree)), DECL_NHREFSOL((*nhrefsol)), DECL_NHDEACTIVATE((*nhdeactivate)))
Definition: heur_alns.c:798
static SCIP_RETCODE transferSolution(SCIP *subscip, SCIP_EVENTDATA *eventdata)
Definition: heur_alns.c:929
Adaptive large neighborhood search heuristic that orchestrates popular LNS heuristics.
methods commonly used by primal heuristics
static const char * paramname[]
Definition: lpi_msk.c:5171
memory allocation routines
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:143
#define BMSclearMemory(ptr)
Definition: memory.h:129
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:147
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
public methods for bandit algorithms
public methods for the epsilon greedy bandit selector
public methods for Exp.3
public methods for Exp.3-IX
public methods for UCB bandit selection
public methods for managing constraints
public methods for managing events
public methods for primal heuristics
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebugMessage
Definition: pub_message.h:96
public data structures and miscellaneous methods
methods for selecting (weighted) k-medians
public methods for primal CIP solutions
public methods for problem variables
public methods for bandit algorithms
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 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 random numbers
public methods for solutions
public solving methods
public methods for querying solving statistics
public methods for statistics table plugins
public methods for timing
public methods for the branch-and-bound tree
public methods for SCIP variables
SCIP_Real targetfixingrate
Definition: heur_alns.c:360
SCIP_Real increment
Definition: heur_alns.c:361
SCIP_Real minfixingrate
Definition: heur_alns.c:359
SCIP_Real maxfixingrate
Definition: heur_alns.c:362
SCIP_Longint nsolsfound
Definition: heur_alns.c:349
SCIP_Real newupperbound
Definition: heur_alns.c:346
int statushist[NHISTENTRIES]
Definition: heur_alns.c:352
SCIP_CLOCK * submipclock
Definition: heur_alns.c:343
SCIP_CLOCK * setupclock
Definition: heur_alns.c:342
int nruns
Definition: heur_alns.c:347
SCIP_Longint nbestsolsfound
Definition: heur_alns.c:350
SCIP_Longint usednodes
Definition: heur_alns.c:344
SCIP_Real oldupperbound
Definition: heur_alns.c:345
int nrunsbestsol
Definition: heur_alns.c:348
int nfixings
Definition: heur_alns.c:351
Definition: heur_alns.c:367
NH_FIXINGRATE fixingrate
Definition: heur_alns.c:369
DECL_NHINIT((*nhinit))
DATA_MUTATION * mutation
Definition: heur_alns.c:382
DECL_CHANGESUBSCIP((*changesubscip))
SCIP_Bool active
Definition: heur_alns.c:378
NH_STATS stats
Definition: heur_alns.c:370
DECL_NHFREE((*nhfree))
DATA_CROSSOVER * crossover
Definition: heur_alns.c:383
DECL_NHEXIT((*nhexit))
DECL_NHDEACTIVATE((*nhdeactivate))
DATA_TRUSTREGION * trustregion
Definition: heur_alns.c:385
DECL_VARFIXINGS((*varfixings))
DECL_NHREFSOL((*nhrefsol))
DATA_DINS * dins
Definition: heur_alns.c:384
char * name
Definition: heur_alns.c:368
SCIP_Real priority
Definition: heur_alns.c:379
union Nh::@5 data
SCIP_Real timelimit
Definition: heur_alns.c:491
SCIP_Longint stallnodes
Definition: heur_alns.c:492
SCIP_Longint nodelimit
Definition: heur_alns.c:489
SCIP_Real memorylimit
Definition: heur_alns.c:490
SCIP * scip
Definition: heur_alns.c:500
unsigned int useredcost
Definition: heur_alns.c:505
SCIP_Real * randscores
Definition: heur_alns.c:501
int * distances
Definition: heur_alns.c:502
SCIP_Real * pscostscores
Definition: heur_alns.c:504
unsigned int usedistances
Definition: heur_alns.c:506
SCIP_Real * redcostscores
Definition: heur_alns.c:503
unsigned int usepscost
Definition: heur_alns.c:507
SCIP_SOL * selsol
Definition: heur_alns.c:400
SCIP_RANDNUMGEN * rng
Definition: heur_alns.c:399
int npoolsols
Definition: heur_alns.c:406
SCIP_RANDNUMGEN * rng
Definition: heur_alns.c:392
SCIP_Real violpenalty
Definition: heur_alns.c:411
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
#define SCIP_EVENTTYPE_BESTSOLFOUND
Definition: type_event.h:105
#define SCIP_EVENTTYPE_SOLFOUND
Definition: type_event.h:144
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:101
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:77
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:43
@ SCIP_PARAMSETTING_OFF
Definition: type_paramset.h:63
@ SCIP_PARAMSETTING_FAST
Definition: type_paramset.h:62
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_DELAYED
Definition: type_result.h:43
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_SUCCESS
Definition: type_result.h:58
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_FILECREATEERROR
Definition: type_retcode.h:48
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_SOLORIGIN_ORIGINAL
Definition: type_sol.h:42
@ SCIP_STATUS_OPTIMAL
Definition: type_stat.h:61
@ SCIP_STATUS_TOTALNODELIMIT
Definition: type_stat.h:45
@ SCIP_STATUS_BESTSOLLIMIT
Definition: type_stat.h:57
@ SCIP_STATUS_SOLLIMIT
Definition: type_stat.h:56
@ SCIP_STATUS_UNBOUNDED
Definition: type_stat.h:63
@ SCIP_STATUS_UNKNOWN
Definition: type_stat.h:42
@ SCIP_STATUS_PRIMALLIMIT
Definition: type_stat.h:54
@ SCIP_STATUS_GAPLIMIT
Definition: type_stat.h:53
@ SCIP_STATUS_USERINTERRUPT
Definition: type_stat.h:43
@ SCIP_STATUS_TERMINATE
Definition: type_stat.h:65
@ 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_DUALLIMIT
Definition: type_stat.h:55
@ SCIP_STATUS_MEMLIMIT
Definition: type_stat.h:52
@ SCIP_STATUS_RESTARTLIMIT
Definition: type_stat.h:60
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:67
#define SCIP_HEURTIMING_DURINGLPLOOP
Definition: type_timing.h:79
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:63
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:62
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:51