Scippy

SCIP

Solving Constraint Integer Programs

heur_completesol.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-2017 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_completesol.c
17  * @brief COMPLETESOL - primal heuristic trying to complete given partial solutions
18  * @author Jakob Witzig
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 <stdio.h>
26 
27 #include "scip/heur_completesol.h"
28 #include "scip/scipdefplugins.h" /* needed for the secondary SCIP instance */
29 #include "scip/pub_misc.h"
30 #include "scip/def.h"
31 
32 #define HEUR_NAME "completesol"
33 #define HEUR_DESC "primal heuristic trying to complete given partial solutions"
34 #define HEUR_DISPCHAR 'h'
35 #define HEUR_PRIORITY 0
36 #define HEUR_FREQ 1
37 #define HEUR_FREQOFS 0
38 #define HEUR_MAXDEPTH 0
39 #define HEUR_TIMING SCIP_HEURTIMING_BEFOREPRESOL
40 #define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
41 
42 /* default values for heuristic plugins */
43 #define DEFAULT_MAXNODES 5000LL /**< maximum number of nodes to regard in the subproblem */
44 #define DEFAULT_MAXUNKRATE 0.85 /**< maximum percentage of unknown solution values */
45 #define DEFAULT_ADDALLSOLS FALSE /**< should all subproblem solutions be added to the original SCIP? */
46 #define DEFAULT_MINNODES 50LL /**< minimum number of nodes to regard in the subproblem */
47 #define DEFAULT_NODESOFS 500LL /**< number of nodes added to the contingent of the total nodes */
48 #define DEFAULT_NODESQUOT 0.1 /**< subproblem nodes in relation to nodes of the original problem */
49 #define DEFAULT_LPLIMFAC 2.0 /**< factor by which the limit on the number of LP depends on the node limit */
50 #define DEFAULT_OBJWEIGHT 1.0 /**< weight of the original objective function (1: only original objective) */
51 #define DEFAULT_BOUNDWIDENING 0.1 /**< bound widening factor applied to continuous variables
52  * (0: round bounds to next integer, 1: relax to global bounds)
53  */
54 #define DEFAULT_MINIMPROVE 0.01 /**< factor by which the incumbent should be improved at least */
55 #define DEFAULT_MINOBJWEIGHT 1e-3 /**< minimal weight for original objective function (zero could lead to infinite solutions) */
56 #define DEFAULT_IGNORECONT FALSE /**< should solution values for continuous variables be ignored? */
57 #define DEFAULT_BESTSOLS 5 /**< heuristic stops, if the given number of improving solutions were found (-1: no limit) */
58 #define DEFAULT_MAXPROPROUNDS 10 /**< maximal number of iterations in propagation (-1: no limit) */
59 
60 /* event handler properties */
61 #define EVENTHDLR_NAME "Completesol"
62 #define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
63 
64 
65 /** primal heuristic data */
66 struct SCIP_HeurData
67 {
68  SCIP_Real maxunknownrate; /**< maximal rate of changed coefficients in the objective function */
69  SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
70  SCIP_Bool addallsols; /**< should all subproblem solutions be added to the original SCIP? */
71  SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
72  SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
73  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
74  SCIP_Real nodelimit; /**< the nodelimit employed in the current sub-SCIP, for the event handler*/
75  SCIP_Real lplimfac; /**< factor by which the limit on the number of LP depends on the node limit */
76  SCIP_Real objweight; /**< weight of the original objective function (1: only original obj, 0: try to keep to given solution) */
77  SCIP_Real boundwidening; /**< bound widening factor applied to continuous variables
78  * (0: fix variables to given solution values, 1: relax to global bounds)
79  */
80  SCIP_Real minimprove; /**< factor by which the incumbent should be improved at least */
81  SCIP_Bool ignorecont; /**< should solution values for continuous variables be ignored? */
82  int bestsols; /**< heuristic stops, if the given number of improving solutions were found (-1: no limit) */
83  int maxproprounds; /**< maximal number of iterations in propagation (-1: no limit) */
84 };
85 
86 /* ---------------- Callback methods of event handler ---------------- */
87 
88 /* exec the event handler
89  *
90  * we interrupt the solution process
91  */
92 static
93 SCIP_DECL_EVENTEXEC(eventExecCompletesol)
94 {
95  SCIP_HEURDATA* heurdata;
96 
97  assert(eventhdlr != NULL);
98  assert(eventdata != NULL);
99  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
100  assert(event != NULL);
101  assert(SCIPeventGetType(event) & SCIP_EVENTTYPE_LPSOLVED);
102 
103  heurdata = (SCIP_HEURDATA*)eventdata;
104  assert(heurdata != NULL);
105 
106  /* interrupt solution process of sub-SCIP */
107  if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
108  {
109  SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n",SCIPgetNLPs(scip));
111  }
112 
113  return SCIP_OKAY;
114 }
115 
116 /** creates a subproblem by fixing a number of variables */
117 static
119  SCIP* scip, /**< original SCIP data structure */
120  SCIP* subscip, /**< SCIP data structure for the subproblem */
121  SCIP_HEURDATA* heurdata, /**< heuristic's private data structure */
122  SCIP_VAR** subvars, /**< the variables of the subproblem */
123  SCIP_SOL* partialsol, /**< partial solution */
124  SCIP_Bool* tightened, /**< array to store for which variables we have found bound tightenings */
125  SCIP_Bool* success /**< pointer to store whether the creation was successful */
126  )
127 {
128  SCIP_VAR** vars;
129  SCIP_CONS* objcons;
130  SCIP_Real epsobj;
131  SCIP_Real cutoff;
132  SCIP_Real upperbound;
133  char consobjname[SCIP_MAXSTRLEN];
134  int nvars;
135  int i;
136 
137  assert(scip != NULL);
138  assert(subscip != NULL);
139  assert(subvars != NULL);
140  assert(heurdata != NULL);
141 
142  *success = TRUE;
143 
144  /* if there is already a solution, add an objective cutoff */
145  if( SCIPgetNSols(scip) > 0 )
146  {
147  assert(!SCIPisInfinity(scip, SCIPgetUpperbound(scip)));
148 
149  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
150 
151  if( !SCIPisInfinity(scip, -1.0 * SCIPgetLowerbound(scip)) )
152  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip) + heurdata->minimprove * SCIPgetLowerbound(scip);
153  else
154  {
155  if( SCIPgetUpperbound(scip) >= 0 )
156  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
157  else
158  cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
159  }
160  cutoff = MIN(upperbound, cutoff);
161  SCIPdebugMsg(scip, "set cutoff=%g for sub-SCIP\n", cutoff);
162  }
163  else
164  cutoff = SCIPinfinity(scip);
165 
166  /* calculate objective coefficients for all potential epsilons */
167  if( SCIPisEQ(scip, heurdata->objweight, 1.0) )
168  return SCIP_OKAY;
169  else if( !SCIPisInfinity(scip, cutoff) )
170  epsobj = 1.0;
171  else
172  {
173  /* divide by objweight to avoid changing objective coefficient of original problem variables */
174  epsobj = (1.0 - heurdata->objweight)/heurdata->objweight;
175 
176  /* scale with -1 if we have a maximization problem */
178  epsobj *= -1.0;
179  }
180 
181  /* get active variables */
182  vars = SCIPgetVars(scip);
183  nvars = SCIPgetNVars(scip);
184 
185  objcons = NULL;
186 
187  /* add constraints to measure the distance to the given partial solution */
188  for( i = 0; i < nvars; i++ )
189  {
190  SCIP_Real solval;
191  int idx;
192 
193  assert(SCIPvarIsActive(vars[i]));
194 
195  /* add objective function as a constraint, if a primal bound exists */
196  if( SCIPisInfinity(scip, cutoff) )
197  {
198  /* create the constraints */
199  if( objcons == NULL )
200  {
201  SCIP_Real lhs;
202  SCIP_Real rhs;
203 
204  if( SCIPgetObjsense(subscip) == SCIP_OBJSENSE_MINIMIZE )
205  {
206  lhs = -SCIPinfinity(subscip);
207  rhs = cutoff;
208  }
209  else
210  {
211  lhs = cutoff;
212  rhs = SCIPinfinity(subscip);
213  }
214 
215  (void)SCIPsnprintf(consobjname, SCIP_MAXSTRLEN, "obj");
216  SCIP_CALL( SCIPcreateConsBasicLinear(subscip, &objcons, consobjname, 0, NULL, NULL, lhs, rhs) );
217  }
218 
219  /* add the variable to the constraints */
220  SCIP_CALL( SCIPaddCoefLinear(subscip, objcons, subvars[i], SCIPvarGetObj(subvars[i])) );
221 
222  /* set objective coefficient to 0.0 */
223  SCIP_CALL( SCIPchgVarObj(subscip, subvars[i], 0.0) );
224  }
225 
226  solval = SCIPgetSolVal(scip, partialsol, vars[i]);
227 
228  /* skip variables with unknown solution value */
229  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
230  continue;
231 
232  idx = SCIPvarGetProbindex(vars[i]);
233  assert(idx >= 0);
234 
235  /* skip variables where we already found some bound tightenings */
236  if( tightened[idx] == FALSE )
237  {
238  /* special case: vars[i] is binary; we do not add an extra variable, but we mimic the behavior we would get with it.
239  * E.g., if the solval is 0.3, setting the variable to 0 would give a cost of 0.3 * epsobj, setting it to 1 gives
240  * 0.7 * epsobj. Thus, 0.3 * epsobj can be treated as a constant in the objective function and the variable gets
241  * an objective coefficient of 0.4 * epsobj.
242  */
243  if( SCIPvarIsBinary(vars[i]) )
244  {
245  SCIP_Real frac = SCIPfeasFrac(scip, solval);
246  SCIP_Real objcoef;
247 
248  frac = MIN(frac, 1-frac);
249  objcoef = (1 - 2*frac) * epsobj * (int)SCIPgetObjsense(scip);
250 
251  if( solval > 0.5 )
252  {
253  SCIP_CALL( SCIPchgVarObj(scip, vars[i], -objcoef) );
254  }
255  else
256  {
257  SCIP_CALL( SCIPchgVarObj(scip, vars[i], objcoef) );
258  }
259  }
260  else
261  {
262  SCIP_CONS* conspos;
263  SCIP_CONS* consneg;
264  SCIP_VAR* eps;
265  char consnamepos[SCIP_MAXSTRLEN];
266  char consnameneg[SCIP_MAXSTRLEN];
267  char epsname[SCIP_MAXSTRLEN];
268 
269  /* create two new variables */
270  (void)SCIPsnprintf(epsname, SCIP_MAXSTRLEN, "eps_%s", SCIPvarGetName(subvars[i]));
271 
272  SCIP_CALL( SCIPcreateVarBasic(subscip, &eps, epsname, 0.0, SCIPinfinity(scip), epsobj, SCIP_VARTYPE_CONTINUOUS) );
273  SCIP_CALL( SCIPaddVar(subscip, eps) );
274 
275  /* create two constraints */
276  (void)SCIPsnprintf(consnamepos, SCIP_MAXSTRLEN, "cons_%s_pos", SCIPvarGetName(subvars[i]));
277  (void)SCIPsnprintf(consnameneg, SCIP_MAXSTRLEN, "cons_%s_neq", SCIPvarGetName(subvars[i]));
278 
279  /* x_{i} - s_{i} <= e_{i} <==> x_{i} - e_{i} <= s_{i} */
280  SCIP_CALL( SCIPcreateConsBasicLinear(subscip, &conspos, consnamepos, 0, NULL, NULL, -SCIPinfinity(scip), solval) );
281  SCIP_CALL( SCIPaddCoefLinear(subscip, conspos, subvars[i], 1.0) );
282  SCIP_CALL( SCIPaddCoefLinear(subscip, conspos, eps, -1.0) );
283  SCIP_CALL( SCIPaddCons(subscip, conspos) );
284  SCIP_CALL( SCIPreleaseCons(subscip, &conspos) );
285 
286  /* s_{i} - x_{i} <= e_{i} <==> e_{i} - x_{i} >= s_{i} */
287  SCIP_CALL( SCIPcreateConsBasicLinear(subscip, &consneg, consnameneg, 0, NULL, NULL, solval, SCIPinfinity(scip)) );
288  SCIP_CALL( SCIPaddCoefLinear(subscip, consneg, subvars[i], -1.0) );
289  SCIP_CALL( SCIPaddCoefLinear(subscip, consneg, eps, 1.0) );
290  SCIP_CALL( SCIPaddCons(subscip, consneg) );
291  SCIP_CALL( SCIPreleaseCons(subscip, &consneg) );
292 
293  /* release the variables */
294  SCIP_CALL( SCIPreleaseVar(subscip, &eps) );
295  }
296  }
297  }
298 
299  /* add and release the constraint representing the original objective function */
300  if( objcons != NULL )
301  {
302  SCIP_CALL( SCIPaddCons(subscip, objcons) );
303  SCIP_CALL( SCIPreleaseCons(subscip, &objcons) );
304  }
305 
306  return SCIP_OKAY;
307 }
308 
309 /** creates a new solution for the original problem by copying the solution of the subproblem */
310 static
312  SCIP* scip, /**< original SCIP data structure */
313  SCIP* subscip, /**< SCIP structure of the subproblem */
314  SCIP_VAR** subvars, /**< the variables of the subproblem */
315  SCIP_HEUR* heur, /**< Completesol heuristic structure */
316  SCIP_SOL* subsol, /**< solution of the subproblem or the partial */
317  SCIP_Bool* success /**< used to store whether new solution was found or not */
318  )
319 {
320  SCIP_VAR** vars; /* the original problem's variables */
321  int nvars; /* the original problem's number of variables */
322  SCIP_SOL* newsol; /* solution to be created for the original problem */
323  int v;
324 
325  assert(scip != NULL);
326  assert(subscip != NULL);
327  assert(subvars != NULL);
328  assert(subsol != NULL);
329 
330  /* get variables' data */
331  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
332 
333  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
334  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
335  */
336  assert(nvars <= SCIPgetNOrigVars(subscip));
337 
338  /* create new solution for the original problem */
339  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
340 
341  for( v = 0; v < nvars; v++ )
342  {
343  SCIP_Real solval = SCIPgetSolVal(subscip, subsol, subvars[v]);
344 
345  assert(!SCIPisInfinity(subscip, solval) && !SCIPisInfinity(subscip, -solval));
346  assert(solval != SCIP_UNKNOWN); /*lint !e777*/
347 
348  SCIP_CALL( SCIPsetSolVal(scip, newsol, vars[v], solval) );
349  }
350 
351  /* try to add new solution to SCIP and free it immediately */
352  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
353 
354  return SCIP_OKAY;
355 }
356 
357 /** perform a probing bound change or fixes the variable */
358 static
360  SCIP* scip, /**< original SCIP data structure */
361  SCIP_VAR* var, /**< problem variable */
362  SCIP_Real newval, /**< new bound */
363  SCIP_BRANCHDIR branchdir, /**< bound change direction */
364  SCIP_Bool* success /**< pointer to store whether the bound could be tightened */
365  )
366 {
367  SCIP_Real ub;
368  SCIP_Real lb;
369 
370  assert(scip != NULL);
371  assert(var != NULL);
372 
373  (*success) = FALSE;
374 
375  ub = SCIPvarGetUbLocal(var);
376  lb = SCIPvarGetLbLocal(var);
377 
378  switch (branchdir) {
380  if( SCIPisLT(scip, newval, ub) && SCIPisGE(scip, newval, lb) )
381  {
382  SCIP_CALL( SCIPchgVarUbProbing(scip, var, newval) );
383  (*success) = TRUE;
384  }
385  break;
387  if( SCIPisLE(scip, newval, ub) && SCIPisGT(scip, newval, lb) )
388  {
389  SCIP_CALL( SCIPchgVarLbProbing(scip, var, newval) );
390  (*success) = TRUE;
391  }
392  break;
394  if( SCIPisLE(scip, newval, ub) && SCIPisGE(scip, newval, lb) )
395  {
396  SCIP_CALL( SCIPfixVarProbing(scip, var, newval) );
397  (*success) = TRUE;
398  }
399  break;
400  default:
401  return SCIP_INVALIDDATA;
402  }/*lint !e788*/
403 
404  return SCIP_OKAY;
405 }
406 
407 /** tries variables bound changes guided by the given solution */
408 static
410  SCIP* scip, /**< original SCIP data structure */
411  SCIP_HEURDATA* heurdata, /**< heuristic's private data structure */
412  SCIP_VAR** vars, /**< problem variables */
413  int nvars, /**< number of problem variables */
414  SCIP_SOL* sol, /**< solution to guide the bound changes */
415  SCIP_Bool* tightened /**< array to store if variable bound could be tightened */
416  )
417 {
418 #ifndef NDEBUG
419  SCIP_Bool incontsection;
420 #endif
421  SCIP_Bool abortearly;
422  SCIP_Bool cutoff;
423  SCIP_Bool success;
424  SCIP_Longint ndomreds;
425  SCIP_Longint ndomredssum;
426  int nbndtightenings;
427  int v;
428 
429  assert(scip != NULL);
430  assert(heurdata != NULL);
431  assert(vars != NULL);
432  assert(nvars >= 0);
433  assert(sol != NULL);
434  assert(tightened != NULL);
435 
437 
438  SCIPdebugMsg(scip, "> start probing along the solution values\n");
439 
440  abortearly = FALSE;
441  nbndtightenings = 0;
442  ndomredssum = 0;
443 #ifndef NDEBUG
444  incontsection = FALSE;
445 #endif
446 
447  /* there is at least one integral variable; open one probing node for all non-continuous variables */
448  if( nvars - SCIPgetNContVars(scip) > 0 )
449  {
450  SCIP_CALL( SCIPnewProbingNode(scip) );
451  }
452 
453  for( v = 0; v < nvars && !abortearly; v++ )
454  {
455  SCIP_Real solval;
456 
457  assert(SCIPvarIsActive(vars[v]));
458 
459  cutoff = FALSE;
460  ndomreds = 0;
461 
462 #ifndef NDEBUG
463  incontsection |= (!SCIPvarIsIntegral(vars[v])); /*lint !e514*/
464  assert(!incontsection || !SCIPvarIsIntegral(vars[v]));
465 #endif
466 
467  /* return if continuous variables should ignored */
468  if( heurdata->ignorecont && SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
469  break;
470 
471  /* return if we have found enough domain reductions tightenings */
472  if( ndomredssum > 0.3*nvars )
473  break;
474 
475  solval = SCIPgetSolVal(scip, sol, vars[v]);
476 
477  /* skip unknown variables */
478  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
479  continue;
480  assert(!SCIPisInfinity(scip, solval) && !SCIPisInfinity(scip, -solval));
481 
482  /* variable is binary or integer */
483  if( SCIPvarIsIntegral(vars[v]) )
484  {
485  /* the solution value is integral, try to fix them */
486  if( SCIPisIntegral(scip, solval) )
487  {
488  SCIP_CALL( chgProbingBound(scip, vars[v], solval, SCIP_BRANCHDIR_FIXED, &success) );
489  tightened[SCIPvarGetProbindex(vars[v])] = TRUE;
490  ++nbndtightenings;
491 
492 #ifdef SCIP_MORE_DEBUG
493  SCIPdebugMsg(scip, "> fix variable <%s> = [%g,%g] to %g \n", SCIPvarGetName(vars[v]),
494  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), solval);
495 #endif
496  }
497  else
498  {
499  SCIP_Real ub = SCIPceil(scip, solval) + 1.0;
500  SCIP_Real lb = SCIPfloor(scip, solval) - 1.0;
501 
502  /* try tightening of upper bound */
503  if( SCIPisLT(scip, ub, SCIPvarGetUbLocal(vars[v])) )
504  {
505  SCIP_CALL( chgProbingBound(scip, vars[v], solval, SCIP_BRANCHDIR_DOWNWARDS, &success) );
506  tightened[SCIPvarGetProbindex(vars[v])] = TRUE;
507  ++nbndtightenings;
508 
509 #ifdef SCIP_MORE_DEBUG
510  SCIPdebugMsg(scip, "> tighten upper bound of variable <%s>: %g to %g\n", SCIPvarGetName(vars[v]),
511  SCIPvarGetUbGlobal(vars[v]), ub);
512 #endif
513  }
514 
515  /* try tightening of lower bound */
516  if( SCIPisGT(scip, lb, SCIPvarGetLbLocal(vars[v])) )
517  {
518  SCIP_CALL( chgProbingBound(scip, vars[v], solval, SCIP_BRANCHDIR_UPWARDS, &success) );
519  tightened[SCIPvarGetProbindex(vars[v])] = TRUE;
520  ++nbndtightenings;
521 
522 #ifdef SCIP_MORE_DEBUG
523  SCIPdebugMsg(scip, "> tighten lower bound of variable <%s>: %g to %g\n", SCIPvarGetName(vars[v]),
524  SCIPvarGetLbGlobal(vars[v]), ub);
525 #endif
526  }
527  }
528  }
529  /* variable is continuous */
530  else
531  {
532  /* fix to lb or ub */
533  if( SCIPisEQ(scip, solval, SCIPvarGetLbLocal(vars[v])) || SCIPisEQ(scip, solval, SCIPvarGetUbLocal(vars[v])) )
534  {
535  /* open a new probing node */
536  if( SCIPgetProbingDepth(scip) < SCIP_MAXTREEDEPTH-10 )
537  {
538  SCIP_CALL( SCIPnewProbingNode(scip) );
539 
540  SCIP_CALL( chgProbingBound(scip, vars[v], solval, SCIP_BRANCHDIR_FIXED, &success) );
541 
542  /* skip propagation if the bound could not be changed, e.g., already tightened due to previous
543  * domain propagation
544  */
545  if( success )
546  {
547  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, &cutoff, &ndomreds) );
548  }
549 
550  if( cutoff )
551  {
552  ndomreds = 0;
554  }
555  else
556  {
557  assert(SCIPvarGetProbindex(vars[v]) >= 0);
558  tightened[SCIPvarGetProbindex(vars[v])] = TRUE;
559  ++nbndtightenings;
560 #ifdef SCIP_MORE_DEBUG
561  SCIPdebugMsg(scip, "> fix variable <%s> = [%g,%g] to %g (ndomreds=%lld)\n", SCIPvarGetName(vars[v]),
562  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), solval, ndomreds);
563 #endif
564  }
565  }
566  else
567  /* abort probing */
568  abortearly = TRUE;
569  }
570  else
571  {
572  SCIP_Real offset;
573  SCIP_Real newub = SCIPvarGetUbGlobal(vars[v]);
574  SCIP_Real newlb = SCIPvarGetLbGlobal(vars[v]);
575 
576  /* both bound are finite */
577  if( !SCIPisInfinity(scip, -newlb) && !SCIPisInfinity(scip, newub) )
578  offset = REALABS(heurdata->boundwidening * (newub-newlb));
579  else
580  {
581  /* if one bound is finite, widen bound w.r.t. solution value and finite bound */
582  if( !SCIPisInfinity(scip, -newlb) )
583  offset = REALABS(heurdata->boundwidening * (solval-newlb));
584  else
585  {
586  assert(!SCIPisInfinity(scip, newub));
587  offset = REALABS(heurdata->boundwidening * (newub-solval));
588  }
589  }
590 
591  /* update bounds */
592  newub = SCIPceil(scip, solval) + offset;
593  newlb = SCIPfloor(scip, solval) - offset;
594 
595  /* try tightening of upper bound */
596  if( SCIPisLT(scip, newub, SCIPvarGetUbLocal(vars[v])) )
597  {
598  /* open a new probing node */
599  if( SCIPgetProbingDepth(scip) < SCIP_MAXTREEDEPTH-10 )
600  {
601  SCIP_CALL( SCIPnewProbingNode(scip) );
602  SCIP_CALL( chgProbingBound(scip, vars[v], newub, SCIP_BRANCHDIR_DOWNWARDS, &success) );
603 
604  /* skip propagation if the bound could not be changed, e.g., already tightened due to previous
605  * domain propagation
606  */
607  if( success )
608  {
609  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, &cutoff, &ndomreds) );
610  }
611 
612  if( cutoff )
613  {
614  ndomreds = 0;
615 
616  /* backtrack to last feasible probing node */
618 
619  /* we can tighten the lower bound by newub */
620  SCIP_CALL( chgProbingBound(scip, vars[v], newub, SCIP_BRANCHDIR_UPWARDS, &success) );
621 #ifdef SCIP_MORE_DEBUG
622  SCIPdebugMsg(scip, "> tighten lower bound of variable <%s>: %g to %g\n",
623  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]), newub);
624 #endif
625  }
626  else
627  {
628  assert(SCIPvarGetProbindex(vars[v]) >= 0);
629  tightened[SCIPvarGetProbindex(vars[v])] = TRUE;
630  ++nbndtightenings;
631 #ifdef SCIP_MORE_DEBUG
632  SCIPdebugMsg(scip, "> tighten upper bound of variable <%s>: %g to %g (ndomreds=%lld)\n",
633  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]), newub, ndomreds);
634 #endif
635  }
636  }
637  else
638  /* abort probing */
639  abortearly = TRUE;
640  }
641 
642  /* try tightening of lower bound */
643  if( SCIPisGT(scip, newlb, SCIPvarGetLbLocal(vars[v])) )
644  {
645  /* open a new probing node */
646  if( SCIPgetProbingDepth(scip) < SCIP_MAXTREEDEPTH-10 )
647  {
648  SCIP_CALL( SCIPnewProbingNode(scip) );
649  SCIP_CALL( chgProbingBound(scip, vars[v], newlb, SCIP_BRANCHDIR_UPWARDS, &success) );
650 
651  /* skip propagation if the bound could not be changed, e.g., already tightened due to previous
652  * domain propagation
653  */
654  if( success )
655  {
656  SCIP_CALL( SCIPpropagateProbing(scip, -1, &cutoff, &ndomreds) );
657  }
658 
659  if( cutoff )
660  {
661  ndomreds = 0;
662 
663  /* backtrack to last feasible probing node */
665 
666  /* we can tighten the upper bound by newlb */
667  SCIP_CALL( chgProbingBound(scip, vars[v], newlb, SCIP_BRANCHDIR_DOWNWARDS, &success) );
668 #ifdef SCIP_MORE_DEBUG
669  SCIPdebugMsg(scip, "> tighten upper bound of variable <%s>: %g to %g\n",
670  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]), newlb);
671 #endif
672  }
673  else
674  {
675  assert(SCIPvarGetProbindex(vars[v]) >= 0);
676  tightened[SCIPvarGetProbindex(vars[v])] = TRUE;
677  ++nbndtightenings;
678 #ifdef SCIP_MORE_DEBUG
679  SCIPdebugMsg(scip, "> tighten lower bound of variable <%s>: %g to %g (ndomreds=%lld)\n",
680  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]), newlb, ndomreds);
681 #endif
682  }
683  }
684  else
685  /* abort probing */
686  abortearly = TRUE;
687  }
688  }
689  }
690 
691  ndomredssum += ndomreds;
692  }
693 
694  SCIPdebugMsg(scip, "> found %d bound tightenings and %lld induced domain reductions (abort=%u).\n", nbndtightenings,
695  ndomredssum, abortearly);
696 
697  return SCIP_OKAY;
698 }
699 
700 /** main procedure of the completesol heuristic, creates and solves a sub-SCIP */
701 static
703  SCIP* scip, /**< original SCIP data structure */
704  SCIP_HEUR* heur, /**< heuristic data structure */
705  SCIP_HEURDATA* heurdata, /**< heuristic's private data structure */
706  SCIP_RESULT* result, /**< result data structure */
707  SCIP_Longint nstallnodes, /**< number of stalling nodes for the subproblem */
708  SCIP_SOL* partialsol /**< partial solutions */
709  )
710 {
711  SCIP* subscip;
712  SCIP_HASHMAP* varmapf;
713  SCIP_VAR** vars;
714  SCIP_VAR** subvars = NULL;
715  SCIP_Bool* tightened;
716  SCIP_EVENTHDLR* eventhdlr;
717  int nvars;
718  int i;
719 
720  SCIP_SOL** subsols;
721  int nsubsols;
722 
723  SCIP_Bool valid;
724  SCIP_Bool success;
725 
726  assert(scip != NULL);
727  assert(heur != NULL);
728  assert(heurdata != NULL);
729  assert(result != NULL);
730  assert(partialsol != NULL);
731 
732  *result = SCIP_DIDNOTRUN;
733 
734  SCIPdebugMsg(scip, "+---+ Start Completesol heuristic +---+\n");
735 
736  /* check whether there is enough time and memory left */
737  SCIP_CALL( SCIPcheckCopyLimits(scip, &valid) );
738 
739  if( ! valid )
740  return SCIP_OKAY;
741 
742  *result = SCIP_DIDNOTFIND;
743 
744  /* get variable data */
745  vars = SCIPgetVars(scip);
746  nvars = SCIPgetNVars(scip);
747 
748  /* get buffer memory and initialize it to FALSE */
749  SCIP_CALL( SCIPallocClearBufferArray(scip, &tightened, nvars) );
750 
751  SCIP_CALL( SCIPstartProbing(scip) );
752 
753  SCIP_CALL( tightenVariables(scip, heurdata, vars, nvars, partialsol, tightened) );
754 
755  /* initialize the subproblem */
756  SCIP_CALL( SCIPcreate(&subscip) );
757 
758  /* create the variable mapping hash map */
759  SCIP_CALL( SCIPhashmapCreate(&varmapf, SCIPblkmem(subscip), nvars) );
760 
761  /* allocate memory to align the SCIP and the sub-SCIP variables */
762  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
763 
764  eventhdlr = NULL;
765  valid = FALSE;
766 
767  /* copy complete SCIP instance */
768  SCIP_CALL( SCIPcopyConsCompression(scip, subscip, varmapf, NULL, "completesol", NULL, NULL, 0, FALSE, FALSE, TRUE, &valid) );
769  SCIPdebugMsg(scip, "Copying the SCIP instance was %s complete.\n", valid ? "" : "not ");
770 
771  /* create event handler for LP events */
772  SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecCompletesol, NULL) );
773  if( eventhdlr == NULL )
774  {
775  SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
776  return SCIP_PLUGINNOTFOUND;
777  }
778 
779  /* map all variables */
780  for( i = 0; i < nvars; i++ )
781  {
782  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapf, vars[i]);
783  assert(subvars[i] != NULL);
784  }
785 
786  /* free hash map */
787  SCIPhashmapFree(&varmapf);
788 
789  /* create a new problem, which fixes variables with same value in bestsol and LP relaxation */
790  SCIP_CALL( createSubproblem(scip, subscip, heurdata, subvars, partialsol, tightened, &success) );
791  if( !success )
792  {
793  SCIPdebugMsg(scip, "Error while creating completesol subproblem w.r.t. partial solution <%p>.\n", (void*)partialsol);
794  goto TERMINATE;
795  }
796  SCIPdebugMsg(scip, "Completesol subproblem: %d vars, %d cons\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip));
797 
798  /* do not abort subproblem on CTRL-C */
799  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
800 
801 #ifdef SCIP_DEBUG
802  /* for debugging, enable full output */
803  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", SCIP_VERBLEVEL_FULL) );
804  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", -1) );
805 #else
806  /* disable statistic timing inside sub SCIP and output to console */
807  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", (int) SCIP_VERBLEVEL_NONE) );
808  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
809 #endif
810 
811  /* set limits for the subproblem */
812  SCIP_CALL( SCIPcopyLimits(scip, subscip) );
813  heurdata->nodelimit = heurdata->maxnodes;
814  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
815  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", heurdata->maxnodes) );
816  SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->bestsols) );
817 
818  /* forbid recursive call of heuristics and separators solving sub-SCIPs */
819  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
820 
821  /* disable cutting plane separation */
823 
824  /* disable expensive presolving */
826 
827  /* use best estimate node selection */
828  if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
829  {
830  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
831  }
832 
833  /* use inference branching */
834  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
835  {
836  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
837  }
838 
839  /* disable conflict analysis */
840  if( !SCIPisParamFixed(subscip, "conflict/enable") )
841  {
842  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", FALSE) );
843  }
844 
845  /* speed up sub-SCIP by not checking dual LP feasibility */
846  SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
847 
848  SCIP_CALL( SCIPtransformProb(subscip) );
849  SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
850 
851  /* solve the subproblem */
852  SCIPdebugMsg(scip, "solving subproblem: nstallnodes=%" SCIP_LONGINT_FORMAT ", maxnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->maxnodes);
853 
854  /* errors in solving the subproblem should not kill the overall solving process;
855  * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
856  */
857  SCIP_CALL_ABORT( SCIPsolve(subscip) );
858 
859  SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
860 
861  /* print solving statistics of subproblem if we are in SCIP's debug mode */
863 
864  /* check, whether a solution was found;
865  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
866  */
867  nsubsols = SCIPgetNSols(subscip);
868  subsols = SCIPgetSols(subscip);
869  success = FALSE;
870  for( i = 0; i < nsubsols && (!success || heurdata->addallsols); i++ )
871  {
872  SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) );
873  if( success )
874  *result = SCIP_FOUNDSOL;
875  }
876 
877  SCIPstatisticPrintf("%s statistic: fixed %6.3f integer variables, needed %6.1f seconds, %" SCIP_LONGINT_FORMAT " nodes, solution %10.4f found at node %" SCIP_LONGINT_FORMAT "\n",
878  HEUR_NAME, 0.0, SCIPgetSolvingTime(subscip), SCIPgetNNodes(subscip), success ? SCIPgetPrimalbound(scip) : SCIPinfinity(scip),
879  nsubsols > 0 ? SCIPsolGetNodenum(SCIPgetBestSol(subscip)) : -1 );
880 
881  TERMINATE:
882  /* free subproblem */
883  SCIPfreeBufferArray(scip, &subvars);
884  SCIPfreeBufferArray(scip, &tightened);
885  SCIP_CALL( SCIPfree(&subscip) );
886 
887  SCIP_CALL( SCIPendProbing(scip) );
888 
889  return SCIP_OKAY;
890 }
891 
892 
893 /*
894  * Callback methods of primal heuristic
895  */
896 
897 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
898 static
899 SCIP_DECL_HEURCOPY(heurCopyCompletesol)
900 { /*lint --e{715}*/
901  assert(scip != NULL);
902  assert(heur != NULL);
903  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
904 
905  /* call inclusion method of primal heuristic */
907 
908  return SCIP_OKAY;
909 }
910 
911 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
912 static
913 SCIP_DECL_HEURFREE(heurFreeCompletesol)
914 { /*lint --e{715}*/
915  SCIP_HEURDATA* heurdata;
916 
917  assert(heur != NULL);
918  assert(scip != NULL);
919 
920  /* get heuristic data */
921  heurdata = SCIPheurGetData(heur);
922  assert(heurdata != NULL);
923 
924  /* free heuristic data */
925  SCIPfreeBlockMemory(scip, &heurdata);
926  SCIPheurSetData(heur, NULL);
927 
928  return SCIP_OKAY;
929 }
930 
931 /** execution method of primal heuristic */
932 static
933 SCIP_DECL_HEUREXEC(heurExecCompletesol)
934 {/*lint --e{715}*/
935  SCIP_HEURDATA* heurdata;
936  SCIP_VAR** vars;
937  SCIP_SOL** partialsols;
938  SCIP_Longint nstallnodes;
939  int npartialsols;
940  int nunknown;
941  int nfracints;
942  int nvars;
943  int s;
944  int v;
945 
946  assert( heur != NULL );
947  assert( scip != NULL );
948  assert( result != NULL );
949 
950  *result = SCIP_DELAYED;
951 
952  /* do not call heuristic of node was already detected to be infeasible */
953  if( nodeinfeasible )
954  return SCIP_OKAY;
955 
956  /* get heuristic data */
957  heurdata = SCIPheurGetData(heur);
958  assert( heurdata != NULL );
959 
960  *result = SCIP_DIDNOTRUN;
961 
962  if( SCIPisStopped(scip) )
963  return SCIP_OKAY;
964 
965  /* do not run after restart */
966  if( SCIPgetNRuns(scip) > 1 )
967  return SCIP_OKAY;
968 
969  /* get variable data and return of no variables are left in the problem */
970  vars = SCIPgetVars(scip);
971  nvars = SCIPgetNVars(scip);
972 
973  if( nvars == 0 )
974  return SCIP_OKAY;
975 
976  /* calculate the maximal number of branching nodes until heuristic is aborted */
977  nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
978 
979  /* reward Completesol if it succeeded often */
980  nstallnodes = (SCIP_Longint)(nstallnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
981  nstallnodes -= 100 * SCIPheurGetNCalls(heur); /* count the setup costs for the sub-SCIP as 100 nodes */
982  nstallnodes += heurdata->nodesofs;
983 
984  /* determine the node limit for the current process */
985  nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
986 
987  /* check whether we have enough nodes left to call subproblem solving */
988  if( nstallnodes < heurdata->minnodes )
989  {
990  SCIPdebugMsg(scip, "skipping Complete: nstallnodes=%" SCIP_LONGINT_FORMAT ", minnodes=%" SCIP_LONGINT_FORMAT "\n",
991  nstallnodes, heurdata->minnodes);
992  return SCIP_OKAY;
993  }
994 
995  /* check the number of variables with unknown value and continuous variables with fractional value */
996  nfracints = 0;
997 
998  /* get all partial sols */
999  npartialsols = SCIPgetNPartialSols(scip);
1000  partialsols = SCIPgetPartialSols(scip);
1001 
1002  /* loop over all partial solutions */
1003  for( s = 0; s < npartialsols; s++ )
1004  {
1005  SCIP_SOL* sol;
1006  SCIP_Real solval;
1007  SCIP_Real unknownrate;
1008 
1009  sol = partialsols[s];
1010  assert(sol != NULL);
1011  assert(SCIPsolIsPartial(sol));
1012 
1013  nunknown = 0;
1014  /* loop over all variables */
1015  for( v = 0; v < nvars; v++ )
1016  {
1017  assert(SCIPvarIsActive(vars[v]));
1018 
1019  /* skip continuous variables if they should ignored */
1020  if( !SCIPvarIsIntegral(vars[v]) && heurdata->ignorecont )
1021  continue;
1022 
1023  solval = SCIPgetSolVal(scip, sol, vars[v]);
1024 
1025  /* we only want to count variables that are unfixed after the presolving */
1026  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1027  ++nunknown;
1028  else if( SCIPvarIsIntegral(vars[v]) && !SCIPisIntegral(scip, solval) )
1029  ++nfracints;
1030  }
1031 
1032  if( heurdata->ignorecont )
1033  unknownrate = nunknown/((SCIP_Real)SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip) + SCIPgetNImplVars(scip));
1034  else
1035  unknownrate = nunknown/((SCIP_Real)nvars);
1036  SCIPdebugMsg(scip, "%d (rate %.4f) unknown solution values\n", nunknown, unknownrate);
1037 
1038  /* run the heuristic, if not too many unknown variables exist */
1039  if( unknownrate > heurdata->maxunknownrate )
1040  continue;
1041 
1042  /* all variables have a finite/known solution value and the all integer variables have an integral solution value,
1043  * create a new solution without solving a sub-SCIP
1044  */
1045  if( nunknown == 0 && nfracints == 0 )
1046  {
1047  SCIP_VAR** origvars;
1048  SCIP_SOL* newsol;
1049  SCIP_Bool stored;
1050  int norigvars;
1051 
1052  origvars = SCIPgetOrigVars(scip);
1053  norigvars = SCIPgetNOrigVars(scip);
1054 
1055  SCIP_CALL( SCIPcreateOrigSol(scip, &newsol, heur) );
1056 
1057  for( v = 0; v < norigvars; v++ )
1058  {
1059  solval = SCIPgetSolVal(scip, sol, origvars[v]);
1060  assert(solval != SCIP_UNKNOWN); /*lint !e777*/
1061 
1062  SCIP_CALL( SCIPsetSolVal(scip, newsol, origvars[v], solval) );
1063  }
1064 
1065  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
1066  if( stored )
1067  *result = SCIP_FOUNDSOL;
1068  }
1069  else
1070  {
1071  /* run the heuristic */
1072  SCIP_CALL( applyCompletesol(scip, heur, heurdata, result, nstallnodes, sol) );
1073  }
1074  }
1075 
1076  return SCIP_OKAY;
1077 }
1078 
1079 
1080 /*
1081  * primal heuristic specific interface methods
1082  */
1083 
1084 /** creates the completesol primal heuristic and includes it in SCIP */
1086  SCIP* scip /**< SCIP data structure */
1087  )
1088 {
1089  SCIP_HEURDATA* heurdata;
1090  SCIP_HEUR* heur;
1091 
1092  /* create completesol primal heuristic data */
1093  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1094  assert(heurdata != NULL);
1095 
1096  /* include primal heuristic */
1099  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecCompletesol, heurdata) );
1100 
1101  assert(heur != NULL);
1102 
1103  /* set non fundamental callbacks via setter functions */
1104  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyCompletesol) );
1105  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeCompletesol) );
1106 
1107  /* add completesol primal heuristic parameters */
1108 
1109  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1110  "maximum number of nodes to regard in the subproblem",
1111  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1112 
1113  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1114  "minimum number of nodes required to start the subproblem",
1115  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1116 
1117  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/maxunkownrate",
1118  "maximal rate of unknown solution values",
1119  &heurdata->maxunknownrate, FALSE, DEFAULT_MAXUNKRATE, 0.0, 1.0, NULL, NULL) );
1120 
1121  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/addallsols",
1122  "should all subproblem solutions be added to the original SCIP?",
1123  &heurdata->addallsols, TRUE, DEFAULT_ADDALLSOLS, NULL, NULL) );
1124 
1125  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1126  "number of nodes added to the contingent of the total nodes",
1127  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1128 
1129  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1130  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1131  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1132 
1133  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
1134  "factor by which the limit on the number of LP depends on the node limit",
1135  &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
1136 
1137  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/objweight",
1138  "weight of the original objective function (1: only original objective)",
1139  &heurdata->objweight, TRUE, DEFAULT_OBJWEIGHT, DEFAULT_MINOBJWEIGHT, 1.0, NULL, NULL) );
1140 
1141  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/boundwidening",
1142  "bound widening factor applied to continuous variables (0: fix variables to given solution values, 1: relax to global bounds)",
1143  &heurdata->boundwidening, TRUE, DEFAULT_BOUNDWIDENING, 0.0, 1.0, NULL, NULL) );
1144 
1145  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1146  "factor by which the incumbent should be improved at least",
1147  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1148 
1149  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/ignorecont",
1150  "should solution values for continuous variables be ignored?",
1151  &heurdata->ignorecont, FALSE, DEFAULT_IGNORECONT, NULL, NULL) );
1152 
1153  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/solutions",
1154  "heuristic stops, if the given number of improving solutions were found (-1: no limit)",
1155  &heurdata->bestsols, FALSE, DEFAULT_BESTSOLS, -1, INT_MAX, NULL, NULL) );
1156 
1157  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxproprounds",
1158  "maximal number of iterations in propagation (-1: no limit)",
1159  &heurdata->maxproprounds, FALSE, DEFAULT_MAXPROPROUNDS, -1, INT_MAX, NULL, NULL) );
1160 
1161  return SCIP_OKAY;
1162 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11721
#define EVENTHDLR_DESC
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:45137
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:84
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5095
#define DEFAULT_NODESQUOT
static SCIP_RETCODE createSubproblem(SCIP *scip, SCIP *subscip, SCIP_HEURDATA *heurdata, SCIP_VAR **subvars, SCIP_SOL *partialsol, SCIP_Bool *tightened, SCIP_Bool *success)
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:35152
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)
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:35125
#define DEFAULT_MINOBJWEIGHT
SCIP_Real SCIPgetPrimalbound(SCIP *scip)
Definition: scip.c:42448
#define SCIPallocClearBufferArray(scip, ptr, num)
Definition: scip.h:21927
primal heuristic trying to complete given partial solutions
#define HEUR_MAXDEPTH
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17166
#define SCIP_MAXSTRLEN
Definition: def.h:215
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1327
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12071
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17222
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45803
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8526
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18384
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16732
#define DEFAULT_MINIMPROVE
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:11505
#define DEFAULT_MAXPROPROUNDS
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:38881
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2765
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
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.c:4230
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip.c:4126
int SCIPgetNPartialSols(SCIP *scip)
Definition: scip.c:40002
SCIP_RETCODE SCIPcopyConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip.c:3843
static SCIP_DECL_HEURCOPY(heurCopyCompletesol)
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:45816
#define DEFAULT_ADDALLSOLS
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
#define DEFAULT_BOUNDWIDENING
#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:5069
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:9184
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16859
SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
Definition: scip.c:17317
SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
Definition: scip.c:12044
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21907
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:7999
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:35220
#define DEFAULT_BESTSOLS
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2903
SCIP_Real SCIPfeasFrac(SCIP *scip, SCIP_Real val)
Definition: scip.c:46247
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45751
#define SCIP_LONGINT_MAX
Definition: def.h:121
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:21937
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:696
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1102
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21890
#define HEUR_DISPCHAR
SCIP_SOL ** SCIPgetPartialSols(SCIP *scip)
Definition: scip.c:39979
#define SCIPdebugMsg
Definition: scip.h:451
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:4202
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:44425
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:11811
SCIP_RETCODE SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37242
#define DEFAULT_MINNODES
#define EVENTHDLR_NAME
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17176
static SCIP_DECL_EVENTEXEC(eventExecCompletesol)
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:15777
static SCIP_RETCODE tightenVariables(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **vars, int nvars, SCIP_SOL *sol, SCIP_Bool *tightened)
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1181
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:4338
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12410
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8060
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45764
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:35477
SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
Definition: scip.c:35337
#define HEUR_USESSUBSCIP
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:4567
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45519
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:35187
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16552
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2798
#define NULL
Definition: lpi_spx1.cpp:137
#define HEUR_TIMING
#define REALABS(x)
Definition: def.h:159
static SCIP_DECL_HEURFREE(heurFreeCompletesol)
#define SCIP_CALL(x)
Definition: def.h:306
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:42323
static SCIP_RETCODE applyCompletesol(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_RESULT *result, SCIP_Longint nstallnodes, SCIP_SOL *partialsol)
#define SCIPstatisticPrintf
Definition: pub_message.h:107
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1307
#define DEFAULT_MAXUNKRATE
#define DEFAULT_IGNORECONT
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:21448
#define HEUR_PRIORITY
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21925
#define SCIP_UNKNOWN
Definition: def.h:156
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:37867
public data structures and miscellaneous methods
#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:40207
int SCIPgetNImplVars(SCIP *scip)
Definition: scip.c:11766
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:2362
#define DEFAULT_OBJWEIGHT
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:39843
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4625
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:40241
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17014
#define DEFAULT_NODESOFS
SCIP_RETCODE SCIPincludeHeurCompletesol(SCIP *scip)
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:38832
int SCIPgetNRuns(SCIP *scip)
Definition: scip.c:41099
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:45827
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEUR *heur, SCIP_SOL *subsol, SCIP_Bool *success)
#define SCIP_MAXTREEDEPTH
Definition: def.h:242
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11676
static SCIP_RETCODE chgProbingBound(SCIP *scip, SCIP_VAR *var, SCIP_Real newval, SCIP_BRANCHDIR branchdir, SCIP_Bool *success)
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11631
#define SCIP_REAL_MAX
Definition: def.h:136
#define HEUR_FREQ
static SCIP_DECL_HEUREXEC(heurExecCompletesol)
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:38931
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45790
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:45900
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11311
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:12679
#define DEFAULT_LPLIMFAC
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27323
#define HEUR_DESC
SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
Definition: sol.c:2289
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8872
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11586
#define SCIP_Real
Definition: def.h:135
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1138
#define MIN(x, y)
Definition: memory.c:75
#define SCIP_Longint
Definition: def.h:120
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip.c:4090
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16717
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip.c:10881
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip.c:13668
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45777
#define HEUR_NAME
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8044
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17232
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:35092
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:45260
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip.c:16942
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:42472
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:35055
SCIP_Bool SCIPsolIsPartial(SCIP_SOL *sol)
Definition: sol.c:2309
common defines and data types used in all packages of SCIP
#define SCIP_CALL_ABORT(x)
Definition: def.h:285
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:45949
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1092
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:41182
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:41363
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16743
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:35264
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38007
default SCIP plugins
#define DEFAULT_MAXNODES
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:4258
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:5020
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:45937
#define HEUR_FREQOFS
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4683
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:4176
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16839
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:774
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37005