Scippy

SCIP

Solving Constraint Integer Programs

heur_rins.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-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_rins.c
17  * @brief LNS heuristic that combines the incumbent with the LP optimum
18  * @author Timo Berthold
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 #include "scip/scip.h"
26 #include "scip/scipdefplugins.h"
27 #include "scip/cons_linear.h"
28 #include "scip/heur_rins.h"
29 #include "scip/pub_misc.h"
30 
31 #define HEUR_NAME "rins"
32 #define HEUR_DESC "relaxation induced neighborhood search by Danna, Rothberg, and Le Pape"
33 #define HEUR_DISPCHAR 'N'
34 #define HEUR_PRIORITY -1101000
35 #define HEUR_FREQ 25
36 #define HEUR_FREQOFS 0
37 #define HEUR_MAXDEPTH -1
38 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPNODE
39 #define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
40 
41 #define DEFAULT_NODESOFS 500 /* number of nodes added to the contingent of the total nodes */
42 #define DEFAULT_MAXNODES 5000 /* maximum number of nodes to regard in the subproblem */
43 #define DEFAULT_MINNODES 50 /* minimum number of nodes to regard in the subproblem */
44 #define DEFAULT_MINIMPROVE 0.01 /* factor by which RINS should at least improve the incumbent */
45 #define DEFAULT_MINFIXINGRATE 0.3 /* minimum percentage of integer variables that have to be fixed */
46 #define DEFAULT_NODESQUOT 0.1 /* subproblem nodes in relation to nodes of the original problem */
47 #define DEFAULT_LPLIMFAC 2.0 /* factor by which the limit on the number of LP depends on the node limit */
48 #define DEFAULT_NWAITINGNODES 200 /* number of nodes without incumbent change that heuristic should wait */
49 #define DEFAULT_USELPROWS FALSE /* should subproblem be created out of the rows in the LP rows,
50  * otherwise, the copy constructors of the constraints handlers are used */
51 #define DEFAULT_COPYCUTS TRUE /* if DEFAULT_USELPROWS is FALSE, then should all active cuts from the cutpool
52  * of the original scip be copied to constraints of the subscip
53  */
54 #define DEFAULT_USEUCT FALSE /* should uct node selection be used at the beginning of the search? */
55 
56 /* event handler properties */
57 #define EVENTHDLR_NAME "Rins"
58 #define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
59 
60 /*
61  * Data structures
62  */
63 
64 /** primal heuristic data */
65 struct SCIP_HeurData
66 {
67  int nodesofs; /**< number of nodes added to the contingent of the total nodes */
68  int maxnodes; /**< maximum number of nodes to regard in the subproblem */
69  int minnodes; /**< minimum number of nodes to regard in the subproblem */
70  SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
71  int nwaitingnodes; /**< number of nodes without incumbent change that heuristic should wait */
72  SCIP_Real minimprove; /**< factor by which RINS should at least improve the incumbent */
73  SCIP_Real nodelimit; /**< the nodelimit employed in the current sub-SCIP, for the event handler*/
74  SCIP_Real lplimfac; /**< factor by which the limit on the number of LP depends on the node limit */
75  SCIP_Longint usednodes; /**< nodes already used by RINS in earlier calls */
76  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
77  SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
78  SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
79  * to constraints in subproblem?
80  */
81  SCIP_Bool useuct; /**< should uct node selection be used at the beginning of the search? */
82 };
83 
84 /*
85  * Local methods
86  */
87 
88 
89 
90 
91 /** determines variable fixings for RINS
92  *
93  * RINS fixes variables with matching solution values in the current LP and the
94  * incumbent solution
95  */
96 static
98  SCIP* scip, /**< original SCIP data structure */
99  SCIP_VAR** fixedvars, /**< array to store source SCIP variables that should be fixed in the copy */
100  SCIP_Real* fixedvals, /**< array to store fixing values for variables that should be fixed in the copy */
101  int* nfixedvars, /**< pointer to store the number of variables that RINS can fix */
102  int fixedvarssize, /**< size of the buffer arrays to store potential fixings */
103  SCIP_Real minfixingrate, /**< percentage of integer variables that have to be fixed */
104  SCIP_Bool* success /**< pointer to store whether sufficiently many variable fixings were found */
105  )
106 {
107  SCIP_SOL* bestsol; /* incumbent solution of the original problem */
108  SCIP_VAR** vars; /* original scip variables */
109  SCIP_Real fixingrate;
110 
111  int nvars;
112  int nbinvars;
113  int nintvars;
114  int i;
115  int fixingcounter;
116 
117  assert(fixedvals != NULL);
118  assert(fixedvars != NULL);
119  assert(nfixedvars != NULL);
120 
121  /* get required data of the original problem */
122  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
123  bestsol = SCIPgetBestSol(scip);
124  assert(bestsol != NULL);
125 
126  fixingcounter = 0;
127  assert(fixedvarssize >= nbinvars + nintvars);
128 
129  /* determine variables to fix in the subproblem */
130  for( i = 0; i < nbinvars + nintvars; i++ )
131  {
132  SCIP_Real lpsolval;
133  SCIP_Real solval;
134 
135  /* get the current LP solution and the incumbent solution for each variable */
136  lpsolval = SCIPvarGetLPSol(vars[i]);
137  solval = SCIPgetSolVal(scip, bestsol, vars[i]);
138 
139  /* iff both solutions are equal, variable is stored to be fixed */
140  if( SCIPisFeasEQ(scip, lpsolval, solval) )
141  {
142  /* store the fixing and increase the number of fixed variables */
143  fixedvars[fixingcounter] = vars[i];
144  fixedvals[fixingcounter] = solval;
145  fixingcounter++;
146  }
147  }
148 
149  /* store the number of fixings */
150  *nfixedvars = fixingcounter;
151 
152  /* abort, if all variables should be fixed */
153  if( fixingcounter == nbinvars + nintvars )
154  {
155  *success = FALSE;
156  return SCIP_OKAY;
157  }
158  else
159  fixingrate = (SCIP_Real)fixingcounter / (SCIP_Real)(MAX(nbinvars + nintvars, 1));
160 
161  /* abort, if the amount of fixed variables is insufficient */
162  if( fixingrate < minfixingrate )
163  {
164  *success = FALSE;
165  return SCIP_OKAY;
166  }
167 
168  *success = TRUE;
169  return SCIP_OKAY;
170 }
171 
172 
173 /** creates a new solution for the original problem by copying the solution of the subproblem */
174 static
176  SCIP* scip, /**< original SCIP data structure */
177  SCIP* subscip, /**< SCIP structure of the subproblem */
178  SCIP_VAR** subvars, /**< the variables of the subproblem */
179  SCIP_HEUR* heur, /**< RINS heuristic structure */
180  SCIP_SOL* subsol, /**< solution of the subproblem */
181  SCIP_Bool* success /**< used to store whether new solution was found or not */
182  )
183 {
184  SCIP_VAR** vars; /* the original problem's variables */
185  int nvars;
186  SCIP_Real* subsolvals; /* solution values of the subproblem */
187  SCIP_SOL* newsol; /* solution to be created for the original problem */
188 
189  assert( scip != NULL );
190  assert( subscip != NULL );
191  assert( subvars != NULL );
192  assert( subsol != NULL );
193 
194  /* get variables' data */
195  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
196  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
197  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
198  */
199  assert(nvars <= SCIPgetNOrigVars(subscip));
200 
201  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
202 
203  /* copy the solution */
204  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
205 
206  /* create new solution for the original problem */
207  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
208  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
209 
210  /* try to add new solution to scip and free it immediately */
211  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
212 
213  SCIPfreeBufferArray(scip, &subsolvals);
214 
215  return SCIP_OKAY;
216 }
217 
218 static
219 SCIP_DECL_EVENTEXEC(eventExecRins);
220 
221 /** wrapper for the part of heuristic that runs a subscip. Wrapper is needed to avoid possible ressource leaks */
222 static
224  SCIP* scip, /**< original SCIP data structure */
225  SCIP* subscip, /**< SCIP structure of the subproblem */
226  SCIP_HEUR* heur, /**< Heuristic pointer */
227  SCIP_HEURDATA* heurdata, /**< Heuristic's data */
228  SCIP_VAR** vars, /**< original problem's variables */
229  SCIP_VAR** fixedvars, /**< Fixed variables of original SCIP */
230  SCIP_Real* fixedvals, /**< Fixed values of original SCIP */
231  SCIP_RESULT* result, /**< Result pointer */
232  int nvars, /**< Number of variables */
233  int nfixedvars, /**< Number of fixed variables */
234  SCIP_Longint nnodes /**< Number of nodes in the b&b tree */
235  )
236 {
237  SCIP_VAR** subvars; /* variables of the subscip */
238  SCIP_HASHMAP* varmapfw; /* hashmap for mapping between vars of scip and subscip */
239  SCIP_EVENTHDLR* eventhdlr; /* event handler for LP events */
240  SCIP_Real upperbound; /* upperbound of the original SCIP */
241  SCIP_Real cutoff; /* objective cutoff for the subproblem */
242 
243  SCIP_Bool success;
244 
245  int i;
246 
247  /* create the variable mapping hash map */
248  SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
249 
250  /* create a problem copy as sub SCIP */
251  SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "rins", fixedvars, fixedvals, nfixedvars,
252  heurdata->uselprows, heurdata->copycuts, &success, NULL) );
253 
254  eventhdlr = NULL;
255  /* create event handler for LP events */
256  SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecRins, NULL) );
257  if( eventhdlr == NULL )
258  {
259  SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
260  return SCIP_PLUGINNOTFOUND;
261  }
262 
263  /* copy subproblem variables from map to obtain the same order */
264  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
265  for( i = 0; i < nvars; i++ )
266  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
267 
268  /* free hash map */
269  SCIPhashmapFree(&varmapfw);
270 
271  /* do not abort subproblem on CTRL-C */
272  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
273 
274 #ifdef SCIP_DEBUG
275  /* for debugging, enable full output */
276  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", SCIP_VERBLEVEL_FULL) );
277  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
278 #else
279  /* disable statistic timing inside sub SCIP and output to console */
280  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", (int) SCIP_VERBLEVEL_NONE) );
281  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
282 #endif
283 
284  /* set limits for the subproblem */
285  SCIP_CALL( SCIPcopyLimits(scip, subscip) );
286  heurdata->nodelimit = nnodes;
287  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nnodes) );
288  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", MAX(10, nnodes/10)) );
289  SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", 3) );
290 
291  /* forbid recursive call of heuristics and separators solving subMIPs */
292  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
293 
294  /* disable cutting plane separation */
296 
297  /* disable expensive presolving */
299 
300  /* use best estimate node selection */
301  if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
302  {
303  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
304  }
305 
306  /* activate uct node selection at the top of the tree */
307  if( heurdata->useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
308  {
309  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
310  }
311 
312  /* use inference branching */
313  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
314  {
315  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
316  }
317 
318  /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
319  if( !SCIPisParamFixed(subscip, "conflict/enable") )
320  {
321  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
322  }
323  if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
324  {
325  SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
326  }
327  if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
328  {
329  SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
330  }
331 
332  /* speed up sub-SCIP by not checking dual LP feasibility */
333  SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
334 
335  /* employ a limit on the number of enforcement rounds in the quadratic constraint handler; this fixes the issue that
336  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
337  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
338  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no deductions shall be
339  * made for the original SCIP
340  */
341  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
342  {
343  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 500) );
344  }
345 
346  /* add an objective cutoff */
347  assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) );
348 
349  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
350  if( !SCIPisInfinity(scip, -1.0 * SCIPgetLowerbound(scip)) )
351  {
352  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip) + heurdata->minimprove * SCIPgetLowerbound(scip);
353  }
354  else
355  {
356  if( SCIPgetUpperbound(scip) >= 0 )
357  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
358  else
359  cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
360  }
361  cutoff = MIN(upperbound, cutoff);
362  SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
363 
364  /* catch LP events of sub-SCIP */
365  SCIP_CALL( SCIPtransformProb(subscip) );
366  SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
367 
368  /* Errors in solving the subproblem should not kill the overall solving process
369  * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
370  */
371  /* solve the subproblem */
372  SCIP_CALL_ABORT( SCIPsolve(subscip) );
373 
374  /* drop LP events of sub-SCIP */
375  SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
376 
377  /* we try to merge variable statistics with those of our main SCIP */
378  SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
379 
380  /* print solving statistics of subproblem if we are in SCIP's debug mode */
381  SCIPdebug( SCIP_CALL( SCIPprintStatistics(subscip, NULL) ) );
382 
383  heurdata->usednodes += SCIPgetNNodes(subscip);
384 
385  /* check, whether a solution was found */
386  if( SCIPgetNSols(subscip) > 0 )
387  {
388  SCIP_SOL** subsols;
389  int nsubsols;
390 
391  /* check, whether a solution was found;
392  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
393  */
394  nsubsols = SCIPgetNSols(subscip);
395  subsols = SCIPgetSols(subscip);
396  success = FALSE;
397  for( i = 0; i < nsubsols && !success; ++i )
398  {
399  SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) );
400  }
401  if( success )
402  *result = SCIP_FOUNDSOL;
403  }
404  /* free subproblem */
405  SCIPfreeBufferArray(scip, &subvars);
406 
407  return SCIP_OKAY;
408 }
409 
410 /* ---------------- Callback methods of event handler ---------------- */
411 
412 /* exec the event handler
413  *
414  * we interrupt the solution process
415  */
416 static
417 SCIP_DECL_EVENTEXEC(eventExecRins)
418 {
419  SCIP_HEURDATA* heurdata;
420 
421  assert(eventhdlr != NULL);
422  assert(eventdata != NULL);
423  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
424  assert(event != NULL);
425  assert(SCIPeventGetType(event) & SCIP_EVENTTYPE_LPSOLVED);
426 
427  heurdata = (SCIP_HEURDATA*)eventdata;
428  assert(heurdata != NULL);
429 
430  /* interrupt solution process of sub-SCIP */
431  if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
432  {
433  SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n",SCIPgetNLPs(scip));
435  }
436 
437  return SCIP_OKAY;
438 }
439 
440 
441 /*
442  * Callback methods of primal heuristic
443  */
444 
445 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
446 static
447 SCIP_DECL_HEURCOPY(heurCopyRins)
448 { /*lint --e{715}*/
449  assert(scip != NULL);
450  assert(heur != NULL);
451  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
452 
453  /* call inclusion method of primal heuristic */
455 
456  return SCIP_OKAY;
457 }
458 
459 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
460 static
461 SCIP_DECL_HEURFREE(heurFreeRins)
462 { /*lint --e{715}*/
463  SCIP_HEURDATA* heurdata;
464 
465  assert( heur != NULL );
466  assert( scip != NULL );
467 
468  /* get heuristic data */
469  heurdata = SCIPheurGetData(heur);
470  assert( heurdata != NULL );
471 
472  /* free heuristic data */
473  SCIPfreeBlockMemory(scip, &heurdata);
474  SCIPheurSetData(heur, NULL);
475 
476  return SCIP_OKAY;
477 }
478 
479 
480 /** initialization method of primal heuristic (called after problem was transformed) */
481 static
482 SCIP_DECL_HEURINIT(heurInitRins)
483 { /*lint --e{715}*/
484  SCIP_HEURDATA* heurdata;
485 
486  assert( heur != NULL );
487  assert( scip != NULL );
488 
489  /* get heuristic's data */
490  heurdata = SCIPheurGetData(heur);
491  assert( heurdata != NULL );
492 
493  /* initialize data */
494  heurdata->usednodes = 0;
495 
496  return SCIP_OKAY;
497 }
498 
499 
500 /** execution method of primal heuristic */
501 static
502 SCIP_DECL_HEUREXEC(heurExecRins)
503 { /*lint --e{715}*/
505 
506  SCIP_HEURDATA* heurdata; /* heuristic's data */
507  SCIP* subscip; /* the subproblem created by RINS */
508  SCIP_VAR** vars; /* original problem's variables */
509  SCIP_VAR** fixedvars;
510  SCIP_Real* fixedvals;
511 
512  SCIP_RETCODE retcode; /* retcode needed for wrapper method */
513 
514  int nvars;
515  int nbinvars;
516  int nintvars;
517  int nfixedvars;
518 
519  SCIP_Bool success;
520 
521  assert( heur != NULL );
522  assert( scip != NULL );
523  assert( result != NULL );
524  assert( SCIPhasCurrentNodeLP(scip) );
525 
526  *result = SCIP_DELAYED;
527 
528  /* do not call heuristic of node was already detected to be infeasible */
529  if( nodeinfeasible )
530  return SCIP_OKAY;
531 
532  /* get heuristic's data */
533  heurdata = SCIPheurGetData(heur);
534  assert( heurdata != NULL );
535 
536  /* only call heuristic, if an optimal LP solution and a feasible solution are at hand */
538  return SCIP_OKAY;
539 
540  /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
542  return SCIP_OKAY;
543 
544  /* only call heuristic, if the best solution comes from transformed problem */
545  assert( SCIPgetBestSol(scip) != NULL );
547  return SCIP_OKAY;
548 
549  /* only call heuristic, if enough nodes were processed since last incumbent */
550  if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip,SCIPgetBestSol(scip)) < heurdata->nwaitingnodes)
551  return SCIP_OKAY;
552 
553  *result = SCIP_DIDNOTRUN;
554 
555  /* calculate the maximal number of branching nodes until heuristic is aborted */
556  nnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
557 
558  /* reward RINS if it succeeded often */
559  nnodes = (SCIP_Longint)(nnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
560  nnodes -= (SCIP_Longint)(100.0 * SCIPheurGetNCalls(heur)); /* count the setup costs for the sub-MIP as 100 nodes */
561  nnodes += heurdata->nodesofs;
562 
563  /* determine the node limit for the current process */
564  nnodes -= heurdata->usednodes;
565  nnodes = MIN(nnodes, heurdata->maxnodes);
566 
567  /* check whether we have enough nodes left to call subproblem solving */
568  if( nnodes < heurdata->minnodes )
569  return SCIP_OKAY;
570 
571  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
572 
573  /* check whether discrete variables are available */
574  if( nbinvars == 0 && nintvars == 0 )
575  return SCIP_OKAY;
576 
577  if( SCIPisStopped(scip) )
578  return SCIP_OKAY;
579 
580  /* allocate buffer storage to hold the RINS fixings */
581  SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nbinvars + nintvars) );
582  SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nbinvars + nintvars) );
583 
584  success = FALSE;
585 
586  nfixedvars = 0;
587  /* determine possible fixings for RINS: variables with same value in bestsol and LP relaxation */
588  SCIP_CALL( determineFixings(scip, fixedvars, fixedvals, &nfixedvars, nbinvars + nintvars, heurdata->minfixingrate, &success) );
589 
590  /* too few variables could be fixed by the RINS scheme */
591  if( !success )
592  goto TERMINATE;
593 
594  /* check whether there is enough time and memory left */
595  SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
596 
597  /* abort if no time is left or not enough memory to create a copy of SCIP */
598  if( !success )
599  goto TERMINATE;
600 
601  assert(nfixedvars > 0 && nfixedvars < nbinvars + nintvars);
602 
603  *result = SCIP_DIDNOTFIND;
604 
605  SCIPdebugMsg(scip, "RINS heuristic fixes %d out of %d binary+integer variables\n", nfixedvars, nbinvars + nintvars);
606  SCIP_CALL( SCIPcreate(&subscip) );
607 
608  retcode = wrapperRins(scip, subscip, heur, heurdata, vars, fixedvars, fixedvals, result, nvars, nfixedvars, nnodes);
609 
610  SCIP_CALL( SCIPfree(&subscip) );
611 
612  SCIP_CALL( retcode );
613 
614 TERMINATE:
615  SCIPfreeBufferArray(scip, &fixedvals);
616  SCIPfreeBufferArray(scip, &fixedvars);
617 
618  return SCIP_OKAY;
619 }
620 
621 /*
622  * primal heuristic specific interface methods
623  */
624 
625 /** creates the RINS primal heuristic and includes it in SCIP */
627  SCIP* scip /**< SCIP data structure */
628  )
629 {
630  SCIP_HEURDATA* heurdata;
631  SCIP_HEUR* heur;
632 
633  /* create Rins primal heuristic data */
634  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
635 
636  /* include primal heuristic */
637  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
639  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRins, heurdata) );
640 
641  assert(heur != NULL);
642 
643  /* set non-NULL pointers to callback methods */
644  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRins) );
645  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRins) );
646  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRins) );
647 
648  /* add RINS primal heuristic parameters */
649  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
650  "number of nodes added to the contingent of the total nodes",
651  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0, INT_MAX, NULL, NULL) );
652 
653  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
654  "maximum number of nodes to regard in the subproblem",
655  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0, INT_MAX, NULL, NULL) );
656 
657  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minnodes",
658  "minimum number of nodes required to start the subproblem",
659  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0, INT_MAX, NULL, NULL) );
660 
661  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
662  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
663  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
664 
665  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
666  "number of nodes without incumbent change that heuristic should wait",
667  &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0, INT_MAX, NULL, NULL) );
668 
669  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
670  "factor by which " HEUR_NAME " should at least improve the incumbent",
671  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
672 
673  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
674  "minimum percentage of integer variables that have to be fixed",
675  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
676 
677  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
678  "factor by which the limit on the number of LP depends on the node limit",
679  &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
680 
681  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
682  "should subproblem be created out of the rows in the LP rows?",
683  &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
684 
685  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
686  "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
687  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
688 
689  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useuct",
690  "should uct node selection be used at the beginning of the search?",
691  &heurdata->useuct, TRUE, DEFAULT_USEUCT, NULL, NULL) );
692 
693 
694  return SCIP_OKAY;
695 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2465
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:84
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5158
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
static SCIP_DECL_HEUREXEC(heurExecRins)
Definition: heur_rins.c:502
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:43453
#define HEUR_PRIORITY
Definition: heur_rins.c:34
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1344
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12252
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47015
#define DEFAULT_MINNODES
Definition: heur_rins.c:43
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:11686
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:39832
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip.c:4192
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5132
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:9269
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#define HEUR_FREQ
Definition: heur_rins.c:35
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
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.c:8084
#define EVENTHDLR_NAME
Definition: heur_rins.c:57
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:748
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1119
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
#define SCIPdebugMsg
Definition: scip.h:455
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.c:4265
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:45651
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEUR *heur, SCIP_SOL *subsol, SCIP_Bool *success)
Definition: heur_rins.c:175
#define DEFAULT_MINIMPROVE
Definition: heur_rins.c:44
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:16115
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1198
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:4401
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8145
#define HEUR_USESSUBSCIP
Definition: heur_rins.c:39
#define DEFAULT_USELPROWS
Definition: heur_rins.c:49
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38948
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:4630
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
#define DEFAULT_MAXNODES
Definition: heur_rins.c:42
SCIP_RETCODE SCIPincludeHeurRins(SCIP *scip)
Definition: heur_rins.c:626
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
Definition: scip.c:2428
#define DEFAULT_USEUCT
Definition: heur_rins.c:54
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17650
#define DEFAULT_LPLIMFAC
Definition: heur_rins.c:47
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:43277
static SCIP_DECL_HEURCOPY(heurCopyRins)
Definition: heur_rins.c:447
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1324
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:29208
#define DEFAULT_MINFIXINGRATE
Definition: heur_rins.c:45
#define HEUR_TIMING
Definition: heur_rins.c:38
static SCIP_RETCODE determineFixings(SCIP *scip, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *nfixedvars, int fixedvarssize, SCIP_Real minfixingrate, SCIP_Bool *success)
Definition: heur_rins.c:97
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
#define HEUR_MAXDEPTH
Definition: heur_rins.c:37
public data structures and miscellaneous methods
#define DEFAULT_NODESOFS
Definition: heur_rins.c:41
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41158
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:29293
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
#define HEUR_DESC
Definition: heur_rins.c:32
#define HEUR_NAME
Definition: heur_rins.c:31
#define DEFAULT_NWAITINGNODES
Definition: heur_rins.c:48
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11246
LNS heuristic that combines the incumbent with the LP optimum.
#define MAX(x, y)
Definition: tclique_def.h:75
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.c:40794
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4688
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41192
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39783
static SCIP_DECL_EVENTEXEC(eventExecRins)
Definition: heur_rins.c:417
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
static SCIP_DECL_HEURINIT(heurInitRins)
Definition: heur_rins.c:482
SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
Definition: scip.c:4862
#define SCIP_REAL_MAX
Definition: def.h:150
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:29372
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:39882
#define HEUR_DISPCHAR
Definition: heur_rins.c:33
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:8161
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8957
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:903
#define SCIP_Real
Definition: def.h:149
#define HEUR_FREQOFS
Definition: heur_rins.c:36
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
#define SCIP_Longint
Definition: def.h:134
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip.c:4156
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38813
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip.c:13935
static SCIP_RETCODE wrapperRins(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_VAR **vars, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, SCIP_RESULT *result, int nvars, int nfixedvars, SCIP_Longint nnodes)
Definition: heur_rins.c:223
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8129
#define nnodes
Definition: gastrans.c:65
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:46429
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip.c:17324
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:43426
#define SCIP_CALL_ABORT(x)
Definition: def.h:329
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1109
#define DEFAULT_COPYCUTS
Definition: heur_rins.c:51
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:42133
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:42314
static SCIP_DECL_HEURFREE(heurFreeRins)
Definition: heur_rins.c:461
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
default SCIP plugins
#define DEFAULT_NODESQUOT
Definition: heur_rins.c:46
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.c:4321
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:5083
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4746
SCIP callable library.
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.c:4239
#define EVENTHDLR_DESC
Definition: heur_rins.c:58
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:780
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37878
SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:39207