Scippy

SCIP

Solving Constraint Integer Programs

heur_mutation.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_mutation.c
17  * @brief LNS heuristic that tries to randomly mutate the incumbent solution
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_mutation.h"
29 #include "scip/pub_misc.h"
30 
31 #define HEUR_NAME "mutation"
32 #define HEUR_DESC "mutation heuristic randomly fixing variables"
33 #define HEUR_DISPCHAR 'M'
34 #define HEUR_PRIORITY -1103000
35 #define HEUR_FREQ -1
36 #define HEUR_FREQOFS 8
37 #define HEUR_MAXDEPTH -1
38 #define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
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_MINIMPROVE 0.01 /* factor by which Mutation should at least improve the incumbent */
44 #define DEFAULT_MINNODES 500 /* minimum number of nodes to regard in the subproblem */
45 #define DEFAULT_MINFIXINGRATE 0.8 /* 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_NWAITINGNODES 200 /* number of nodes without incumbent change that heuristic should wait */
48 #define DEFAULT_USELPROWS FALSE /* should subproblem be created out of the rows in the LP rows,
49  * otherwise, the copy constructors of the constraints handlers are used */
50 #define DEFAULT_COPYCUTS TRUE /* if DEFAULT_USELPROWS is FALSE, then should all active cuts from the
51  * cutpool of the original scip be copied to constraints of the subscip */
52 #define DEFAULT_BESTSOLLIMIT -1 /* limit on number of improving incumbent solutions in sub-CIP */
53 #define DEFAULT_USEUCT FALSE /* should uct node selection be used at the beginning of the search? */
54 #define DEFAULT_RANDSEED 19 /* initial random seed */
55 /*
56  * Data structures
57  */
58 
59 /** primal heuristic data */
60 struct SCIP_HeurData
61 {
62  int nodesofs; /**< number of nodes added to the contingent of the total nodes */
63  int maxnodes; /**< maximum number of nodes to regard in the subproblem */
64  int minnodes; /**< minimum number of nodes to regard in the subproblem */
65  SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
66  int nwaitingnodes; /**< number of nodes without incumbent change that heuristic should wait */
67  SCIP_Real minimprove; /**< factor by which Mutation should at least improve the incumbent */
68  SCIP_Longint usednodes; /**< nodes already used by Mutation in earlier calls */
69  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
70  SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
71  SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
72  SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
73  * to constraints in subproblem?
74  */
75  int bestsollimit; /**< limit on number of improving incumbent solutions in sub-CIP */
76  SCIP_Bool useuct; /**< should uct node selection be used at the beginning of the search? */
77 };
78 
79 
80 /*
81  * Local methods
82  */
83 
84 /** determine variables and values which should be fixed in the mutation subproblem */
85 static
87  SCIP* scip, /**< original SCIP data structure */
88  SCIP_VAR** fixedvars, /**< array to store the variables that should be fixed in the subproblem */
89  SCIP_Real* fixedvals, /**< array to store the fixing values to fix variables in the subproblem */
90  int* nfixedvars, /**< pointer to store the number of variables that should be fixed */
91  SCIP_Real minfixingrate, /**< percentage of integer variables that have to be fixed */
92  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
93  SCIP_Bool* success /**< used to store whether the creation of the subproblem worked */
94  )
95 {
96  SCIP_VAR** vars; /* original scip variables */
97  SCIP_SOL* sol; /* pool of solutions */
98 
99  int nvars;
100  int nbinvars;
101  int nintvars;
102  int ndiscretevars;
103  int i;
104 
105  assert(fixedvars != NULL);
106  assert(fixedvals != NULL);
107 
108  /* get required data of the original problem */
109  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
110  sol = SCIPgetBestSol(scip);
111  assert(sol != NULL);
112 
113  /* compute the number of variables that should be fixed in the subproblem */
114  *nfixedvars = (int)(minfixingrate * (nbinvars + nintvars));
115 
116  /* avoid the two corner cases that no or all discrete variables should be fixed */
117  if( *nfixedvars == 0 || *nfixedvars == nbinvars + nintvars )
118  {
119  *success = FALSE;
120  return SCIP_OKAY;
121  }
122  assert(*nfixedvars < nbinvars + nintvars);
123 
124  ndiscretevars = nbinvars + nintvars;
125  /* copy the binary and integer variables into fixedvars */
126  BMScopyMemoryArray(fixedvars, vars, ndiscretevars);
127 
128  /* shuffle the array randomly */
129  SCIPrandomPermuteArray(randnumgen, (void **)fixedvars, 0, nbinvars + nintvars);
130 
131  *success = TRUE;
132  /* store the fixing values for the subset of variables that should be fixed */
133  for( i = 0; i < *nfixedvars; ++i )
134  {
135  /* fix all randomly marked variables */
136  SCIP_Real solval;
137  SCIP_Real lb;
138  SCIP_Real ub;
139 
140  solval = SCIPgetSolVal(scip, sol, fixedvars[i]);
141  lb = SCIPvarGetLbGlobal(fixedvars[i]);
142  ub = SCIPvarGetUbGlobal(fixedvars[i]);
143  assert(SCIPisLE(scip, lb, ub));
144 
145  /* due to dual reductions, it may happen that the solution value is not in
146  the variable's domain anymore */
147  if( SCIPisLT(scip, solval, lb) )
148  solval = lb;
149  else if( SCIPisGT(scip, solval, ub) )
150  solval = ub;
151 
152  /* we cannot fix to infinite solution values, better break in this case */
153  if( SCIPisInfinity(scip, REALABS(solval)) )
154  {
155  *success = FALSE;
156  break;
157  }
158 
159  /* store the possibly adjusted solution value as fixing value */
160  fixedvals[i] = solval;
161  }
162 
163  return SCIP_OKAY;
164 }
165 
166 /** creates a new solution for the original problem by copying the solution of the subproblem */
167 static
169  SCIP* scip, /**< original SCIP data structure */
170  SCIP* subscip, /**< SCIP structure of the subproblem */
171  SCIP_VAR** subvars, /**< the variables of the subproblem */
172  SCIP_HEUR* heur, /**< mutation heuristic structure */
173  SCIP_SOL* subsol, /**< solution of the subproblem */
174  SCIP_Bool* success /**< used to store whether new solution was found or not */
175  )
176 {
177  SCIP_VAR** vars; /* the original problem's variables */
178  int nvars;
179  SCIP_Real* subsolvals; /* solution values of the subproblem */
180  SCIP_SOL* newsol; /* solution to be created for the original problem */
181 
182  assert(scip != NULL);
183  assert(subscip != NULL);
184  assert(subvars != NULL);
185  assert(subsol != NULL);
186 
187  /* get variables' data */
188  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
189  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
190  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
191  */
192  assert(nvars <= SCIPgetNOrigVars(subscip));
193 
194  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
195 
196  /* copy the solution */
197  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
198 
199  /* create new solution for the original problem */
200  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
201  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
202 
203  /* try to add new solution to scip and free it immediately */
204  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
205 
206  SCIPfreeBufferArray(scip, &subsolvals);
207 
208  return SCIP_OKAY;
209 }
210 
211 /** setup and solve mutation sub-SCIP */
212 static
214  SCIP* scip, /**< SCIP data structure */
215  SCIP* subscip, /**< sub-SCIP data structure */
216  SCIP_HEUR* heur, /**< mutation heuristic */
217  SCIP_VAR** fixedvars, /**< array to store the variables that should be fixed in the subproblem */
218  SCIP_Real* fixedvals, /**< array to store the fixing values to fix variables in the subproblem */
219  int nfixedvars, /**< the number of variables that should be fixed */
220  SCIP_Longint nsubnodes, /**< node limit for the subproblem */
221  SCIP_RESULT* result /**< pointer to store the result */
222  )
223 {
224  SCIP_VAR** subvars; /* subproblem's variables */
225  SCIP_VAR** vars; /* original problem's variables */
226  SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */
227  SCIP_HEURDATA* heurdata;
228  SCIP_Real cutoff; /* objective cutoff for the subproblem */
229  SCIP_Real upperbound;
230  int nvars; /* number of original problem's variables */
231  int i;
232  SCIP_Bool success;
233 
234  assert(scip != NULL);
235  assert(subscip != NULL);
236  assert(heur != NULL);
237  assert(fixedvars != NULL);
238  assert(fixedvals != NULL);
239 
240  heurdata = SCIPheurGetData(heur);
241  assert(heurdata != NULL);
242 
243  vars = SCIPgetVars(scip);
244  nvars = SCIPgetNVars(scip);
245 
246  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
247 
248  /* create the variable mapping hash map */
249  SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
250 
251  /* create a problem copy as sub SCIP */
252  SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "mutation", fixedvars, fixedvals, nfixedvars,
253  heurdata->uselprows, heurdata->copycuts, &success, NULL) );
254 
255  for( i = 0; i < nvars; i++ )
256  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
257 
258  /* free hash map */
259  SCIPhashmapFree(&varmapfw);
260 
261  /* do not abort subproblem on CTRL-C */
262  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
263 
264 #ifdef SCIP_DEBUG
265  /* for debugging, enable full output */
266  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
267  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
268 #else
269  /* disable statistic timing inside sub SCIP and output to console */
270  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
271  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
272 #endif
273 
274  /* set limits for the subproblem */
275  SCIP_CALL( SCIPcopyLimits(scip, subscip) );
276  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nsubnodes) );
277  SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->bestsollimit) );
278 
279  /* forbid recursive call of heuristics and separators solving subMIPs */
280  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
281 
282  /* disable cutting plane separation */
284 
285  /* disable expensive presolving */
287 
288  /* use best estimate node selection */
289  if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
290  {
291  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
292  }
293 
294  /* activate uct node selection at the top of the tree */
295  if( heurdata->useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
296  {
297  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
298  }
299 
300  /* use inference branching */
301  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
302  {
303  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
304  }
305 
306  /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
307  if( !SCIPisParamFixed(subscip, "conflict/enable") )
308  {
309  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
310  }
311  if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
312  {
313  SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
314  }
315  if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
316  {
317  SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
318  }
319 
320  /* speed up sub-SCIP by not checking dual LP feasibility */
321  SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
322 
323  /* employ a limit on the number of enforcement rounds in the quadratic constraint handlers; this fixes the issue that
324  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
325  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
326  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no decutions shall be
327  * made for the original SCIP
328  */
329  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
330  {
331  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 10) );
332  }
333 
334  /* add an objective cutoff */
335  assert( !SCIPisInfinity(scip, SCIPgetUpperbound(scip)) );
336 
337  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
338  if( !SCIPisInfinity(scip, -1.0 * SCIPgetLowerbound(scip)) )
339  {
340  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip)
341  + heurdata->minimprove * SCIPgetLowerbound(scip);
342  }
343  else
344  {
345  if( SCIPgetUpperbound(scip) >= 0 )
346  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
347  else
348  cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
349  }
350  cutoff = MIN(upperbound, cutoff);
351  SCIP_CALL(SCIPsetObjlimit(subscip, cutoff));
352 
353  /* solve the subproblem
354  *
355  * Errors in solving the subproblem should not kill the overall solving process
356  * Hence, the return code is caught but only in debug mode, SCIP will stop.
357  */
358  SCIPdebugMsg(scip, "Solve Mutation subMIP\n");
359  SCIP_CALL_ABORT( SCIPsolve(subscip) );
360 
361  /* transfer variable statistics from sub-SCIP */
362  SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
363 
364  /* print solving statistics of subproblem if we are in SCIP's debug mode */
365  SCIPdebug( SCIP_CALL( SCIPprintStatistics(subscip, NULL) ) );
366 
367  heurdata->usednodes += SCIPgetNNodes(subscip);
368 
369  /* check, whether a solution was found */
370  if( SCIPgetNSols(subscip) > 0 )
371  {
372  SCIP_SOL** subsols;
373  int nsubsols;
374 
375  /* check, whether a solution was found;
376  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
377  */
378  nsubsols = SCIPgetNSols(subscip);
379  subsols = SCIPgetSols(subscip);
380  success = FALSE;
381  for( i = 0; i < nsubsols && !success; ++i )
382  {
383  SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) );
384  }
385  if( success )
386  *result = SCIP_FOUNDSOL;
387  }
388 
389  /* free subproblem */
390  SCIPfreeBufferArray(scip, &subvars);
391 
392  return SCIP_OKAY;
393 }
394 
395 
396 /*
397  * Callback methods of primal heuristic
398  */
399 
400 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
401 static
402 SCIP_DECL_HEURCOPY(heurCopyMutation)
403 { /*lint --e{715}*/
404  assert(scip != NULL);
405  assert(heur != NULL);
406  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
407 
408  /* call inclusion method of primal heuristic */
410 
411  return SCIP_OKAY;
412 }
413 
414 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
415 static
416 SCIP_DECL_HEURFREE(heurFreeMutation)
417 { /*lint --e{715}*/
418  SCIP_HEURDATA* heurdata;
419 
420  assert(heur != NULL);
421  assert(scip != NULL);
422 
423  /* get heuristic data */
424  heurdata = SCIPheurGetData(heur);
425  assert(heurdata != NULL);
426 
427  /* free heuristic data */
428  SCIPfreeBlockMemory(scip, &heurdata);
429  SCIPheurSetData(heur, NULL);
430 
431  return SCIP_OKAY;
432 }
433 
434 /** initialization method of primal heuristic (called after problem was transformed) */
435 static
436 SCIP_DECL_HEURINIT(heurInitMutation)
437 { /*lint --e{715}*/
438  SCIP_HEURDATA* heurdata;
439 
440  assert(heur != NULL);
441  assert(scip != NULL);
442 
443  /* get heuristic's data */
444  heurdata = SCIPheurGetData(heur);
445  assert(heurdata != NULL);
446 
447  /* initialize data */
448  heurdata->usednodes = 0;
449 
450  /* create random number generator */
451  SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
452  DEFAULT_RANDSEED) );
453 
454  return SCIP_OKAY;
455 }
456 
457 /** deinitialization method of primal heuristic */
458 static
459 SCIP_DECL_HEUREXIT(heurExitMutation)
460 { /*lint --e{715}*/
461  SCIP_HEURDATA* heurdata;
462 
463  assert(heur != NULL);
464  assert(scip != NULL);
465 
466  /* get heuristic data */
467  heurdata = SCIPheurGetData(heur);
468  assert(heurdata != NULL);
469 
470  /* free random number generator */
471  SCIPfreeRandom(scip, &heurdata->randnumgen);
472 
473  return SCIP_OKAY;
474 }
475 
476 /** execution method of primal heuristic */
477 static
478 SCIP_DECL_HEUREXEC(heurExecMutation)
479 { /*lint --e{715}*/
480  SCIP_Longint maxnnodes;
481  SCIP_Longint nsubnodes; /* node limit for the subproblem */
482 
483  SCIP_HEURDATA* heurdata; /* heuristic's data */
484  SCIP* subscip; /* the subproblem created by mutation */
485  SCIP_VAR** fixedvars; /* array to store variables that should be fixed in the subproblem */
486  SCIP_Real* fixedvals; /* array to store fixing values for the variables */
487 
488  SCIP_Real maxnnodesr;
489 
490  int nfixedvars;
491  int nbinvars;
492  int nintvars;
493 
494  SCIP_Bool success;
495 
496  SCIP_RETCODE retcode;
497 
498  assert( heur != NULL );
499  assert( scip != NULL );
500  assert( result != NULL );
501 
502  /* get heuristic's data */
503  heurdata = SCIPheurGetData(heur);
504  assert(heurdata != NULL);
505 
506  *result = SCIP_DELAYED;
507 
508  /* only call heuristic, if feasible solution is available */
509  if( SCIPgetNSols(scip) <= 0 )
510  return SCIP_OKAY;
511 
512  /* only call heuristic, if the best solution comes from transformed problem */
513  assert(SCIPgetBestSol(scip) != NULL);
515  return SCIP_OKAY;
516 
517  /* only call heuristic, if enough nodes were processed since last incumbent */
518  if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip,SCIPgetBestSol(scip)) < heurdata->nwaitingnodes)
519  return SCIP_OKAY;
520 
521  *result = SCIP_DIDNOTRUN;
522 
523  SCIP_CALL( SCIPgetVarsData(scip, NULL, NULL, &nbinvars, &nintvars, NULL, NULL) );
524 
525  /* only call heuristic, if discrete variables are present */
526  if( nbinvars + nintvars == 0 )
527  return SCIP_OKAY;
528 
529  /* calculate the maximal number of branching nodes until heuristic is aborted */
530  maxnnodesr = heurdata->nodesquot * SCIPgetNNodes(scip);
531 
532  /* reward mutation if it succeeded often, count the setup costs for the sub-MIP as 100 nodes */
533  maxnnodesr *= 1.0 + 2.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0);
534  maxnnodes = (SCIP_Longint) maxnnodesr - 100 * SCIPheurGetNCalls(heur);
535  maxnnodes += heurdata->nodesofs;
536 
537  /* determine the node limit for the current process */
538  nsubnodes = maxnnodes - heurdata->usednodes;
539  nsubnodes = MIN(nsubnodes, heurdata->maxnodes);
540 
541  /* check whether we have enough nodes left to call subproblem solving */
542  if( nsubnodes < heurdata->minnodes )
543  return SCIP_OKAY;
544 
545  if( SCIPisStopped(scip) )
546  return SCIP_OKAY;
547 
548  /* check whether there is enough time and memory left */
549  SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
550 
551  if( !success )
552  return SCIP_OKAY;
553 
554  SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nbinvars + nintvars) );
555  SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nbinvars + nintvars) );
556 
557  /* determine variables that should be fixed in the mutation subproblem */
558  SCIP_CALL( determineVariableFixings(scip, fixedvars, fixedvals, &nfixedvars, heurdata->minfixingrate, heurdata->randnumgen, &success) );
559 
560  /* terminate if it is not possible to create the subproblem */
561  if( !success )
562  {
563  SCIPdebugMsg(scip, "Could not create the subproblem -> skip call\n");
564  goto TERMINATE;
565  }
566 
567  *result = SCIP_DIDNOTFIND;
568 
569  /* initializing the subproblem */
570  SCIP_CALL( SCIPcreate(&subscip) );
571 
572  /* setup and solve the subproblem and catch the return code */
573  retcode = setupAndSolveSubscipMutation(scip, subscip, heur, fixedvars, fixedvals, nfixedvars, nsubnodes, result);
574 
575  /* free the subscip in any case */
576  SCIP_CALL( SCIPfree(&subscip) );
577  SCIP_CALL( retcode );
578 
579  /* free storage for subproblem fixings */
580  TERMINATE:
581  SCIPfreeBufferArray(scip, &fixedvals);
582  SCIPfreeBufferArray(scip, &fixedvars);
583 
584  return SCIP_OKAY;
585 }
586 
587 /*
588  * primal heuristic specific interface methods
589  */
590 
591 /** creates the mutation primal heuristic and includes it in SCIP */
593  SCIP* scip /**< SCIP data structure */
594  )
595 {
596  SCIP_HEURDATA* heurdata;
597  SCIP_HEUR* heur;
598 
599  /* create Mutation primal heuristic data */
600  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
601 
602  /* include primal heuristic */
603  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
605  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecMutation, heurdata) );
606 
607  assert(heur != NULL);
608 
609  /* set non-NULL pointers to callback methods */
610  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyMutation) );
611  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeMutation) );
612  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitMutation) );
613  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitMutation) );
614 
615  /* add mutation primal heuristic parameters */
616  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
617  "number of nodes added to the contingent of the total nodes",
618  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0, INT_MAX, NULL, NULL) );
619 
620  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
621  "maximum number of nodes to regard in the subproblem",
622  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0, INT_MAX, NULL, NULL) );
623 
624  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minnodes",
625  "minimum number of nodes required to start the subproblem",
626  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0, INT_MAX, NULL, NULL) );
627 
628  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
629  "number of nodes without incumbent change that heuristic should wait",
630  &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0, INT_MAX, NULL, NULL) );
631 
632  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
633  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
634  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
635 
636  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
637  "percentage of integer variables that have to be fixed",
638  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, SCIPsumepsilon(scip), 1.0-SCIPsumepsilon(scip), NULL, NULL) );
639 
640  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
641  "factor by which " HEUR_NAME " should at least improve the incumbent",
642  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
643 
644  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
645  "should subproblem be created out of the rows in the LP rows?",
646  &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
647 
648  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
649  "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
650  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
651 
652  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/bestsollimit",
653  "limit on number of improving incumbent solutions in sub-CIP",
654  &heurdata->bestsollimit, FALSE, DEFAULT_BESTSOLLIMIT, -1, INT_MAX, NULL, NULL) );
655 
656  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useuct",
657  "should uct node selection be used at the beginning of the search?",
658  &heurdata->useuct, TRUE, DEFAULT_USEUCT, NULL, NULL) );
659 
660 
661  return SCIP_OKAY;
662 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2465
#define DEFAULT_COPYCUTS
Definition: heur_mutation.c:50
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
Definition: scip.c:48626
static SCIP_DECL_HEURCOPY(heurCopyMutation)
static SCIP_DECL_HEUREXIT(heurExitMutation)
SCIP_RETCODE SCIPincludeHeurMutation(SCIP *scip)
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5158
static SCIP_DECL_HEURFREE(heurFreeMutation)
#define DEFAULT_NWAITINGNODES
Definition: heur_mutation.c:47
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1344
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed)
Definition: scip.c:48608
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:8177
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12252
#define DEFAULT_MINNODES
Definition: heur_mutation.c:44
#define DEFAULT_RANDSEED
Definition: heur_mutation.c:54
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEUR *heur, SCIP_SOL *subsol, SCIP_Bool *success)
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
#define HEUR_DISPCHAR
Definition: heur_mutation.c:33
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip.c:4192
#define TRUE
Definition: def.h:63
void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
Definition: misc.c:9437
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define DEFAULT_MINFIXINGRATE
Definition: heur_mutation.c:45
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
static SCIP_RETCODE setupAndSolveSubscipMutation(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Longint nsubnodes, SCIP_RESULT *result)
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#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 HEUR_NAME
Definition: heur_mutation.c:31
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
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
static SCIP_DECL_HEUREXEC(heurExecMutation)
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:16115
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1198
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
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
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
#define DEFAULT_NODESQUOT
Definition: heur_mutation.c:46
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
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
LNS heuristic that tries to randomly mutate the incumbent solution.
#define REALABS(x)
Definition: def.h:173
#define DEFAULT_MAXNODES
Definition: heur_mutation.c:42
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:43277
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1324
#define DEFAULT_MINIMPROVE
Definition: heur_mutation.c:43
#define HEUR_MAXDEPTH
Definition: heur_mutation.c:37
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
public data structures and miscellaneous methods
#define SCIP_Bool
Definition: def.h:61
#define HEUR_USESSUBSCIP
Definition: heur_mutation.c:39
#define HEUR_PRIORITY
Definition: heur_mutation.c:34
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11246
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
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39783
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
#define DEFAULT_USELPROWS
Definition: heur_mutation.c:48
SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
Definition: scip.c:4862
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
#define HEUR_FREQOFS
Definition: heur_mutation.c:36
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:39882
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:8161
#define HEUR_DESC
Definition: heur_mutation.c:32
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
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11767
#define HEUR_TIMING
Definition: heur_mutation.c:38
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
#define HEUR_FREQ
Definition: heur_mutation.c:35
static SCIP_DECL_HEURINIT(heurInitMutation)
#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_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46989
#define DEFAULT_BESTSOLLIMIT
Definition: heur_mutation.c:52
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8129
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:46429
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:43426
#define DEFAULT_USEUCT
Definition: heur_mutation.c:53
#define SCIP_CALL_ABORT(x)
Definition: def.h:329
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1109
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:42133
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
default SCIP plugins
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 DEFAULT_NODESOFS
Definition: heur_mutation.c:41
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
static SCIP_RETCODE determineVariableFixings(SCIP *scip, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *nfixedvars, SCIP_Real minfixingrate, SCIP_RANDNUMGEN *randnumgen, SCIP_Bool *success)
Definition: heur_mutation.c:86