Scippy

SCIP

Solving Constraint Integer Programs

heur_guideddiving.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 visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_guideddiving.c
17  * @brief LP diving heuristic that chooses fixings in direction of incumbent solutions
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include "scip/heur_guideddiving.h"
24 #include "scip/heuristics.h"
25 #include "scip/pub_heur.h"
26 #include "scip/pub_message.h"
27 #include "scip/pub_sol.h"
28 #include "scip/pub_var.h"
29 #include "scip/scip_heur.h"
30 #include "scip/scip_lp.h"
31 #include "scip/scip_mem.h"
32 #include "scip/scip_numerics.h"
33 #include "scip/scip_prob.h"
34 #include "scip/scip_sol.h"
35 #include <string.h>
36 
37 #define HEUR_NAME "guideddiving"
38 #define HEUR_DESC "LP diving heuristic that chooses fixings in direction of incumbent solutions"
39 #define HEUR_DISPCHAR 'g'
40 #define HEUR_PRIORITY -1007000
41 #define HEUR_FREQ 10
42 #define HEUR_FREQOFS 7
43 #define HEUR_MAXDEPTH -1
44 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
45 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
46 #define DIVESET_DIVETYPES SCIP_DIVETYPE_INTEGRALITY /**< bit mask that represents all supported dive types */
47 
48 
49 /*
50  * Default parameter settings
51  */
52 
53 #define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
54 #define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
55 #define DEFAULT_MAXLPITERQUOT 0.05 /**< maximal fraction of diving LP iterations compared to node LP iterations */
56 #define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
57 #define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
58  * where diving is performed (0.0: no limit) */
59 #define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
60  * where diving is performed (0.0: no limit) */
61 #define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
62 #define DEFAULT_LPRESOLVEDOMCHGQUOT 0.15 /**< percentage of immediate domain changes during probing to trigger LP resolve */
63 #define DEFAULT_LPSOLVEFREQ 0 /**< LP solve frequency for diving heuristics */
64 #define DEFAULT_ONLYLPBRANCHCANDS FALSE /**< should only LP branching candidates be considered instead of the slower but
65  * more general constraint handler diving variable selection? */
66 #define DEFAULT_RANDSEED 127 /**< initial seed for random number generation */
67 
68 /* locally defined heuristic data */
69 struct SCIP_HeurData
70 {
71  SCIP_SOL* sol; /**< working solution */
72 };
73 
74 /*
75  * local methods
76  */
77 
78 /*
79  * Callback methods
80  */
81 
82 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
83 static
84 SCIP_DECL_HEURCOPY(heurCopyGuideddiving)
85 { /*lint --e{715}*/
86  assert(scip != NULL);
87  assert(heur != NULL);
88  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
89 
90  /* call inclusion method of primal heuristic */
92 
93  return SCIP_OKAY;
94 }
95 
96 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
97 static
98 SCIP_DECL_HEURFREE(heurFreeGuideddiving) /*lint --e{715}*/
99 { /*lint --e{715}*/
100  SCIP_HEURDATA* heurdata;
102  assert(heur != NULL);
103  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
104  assert(scip != NULL);
105 
106  /* free heuristic data */
107  heurdata = SCIPheurGetData(heur);
108  assert(heurdata != NULL);
109 
110  SCIPfreeBlockMemory(scip, &heurdata);
111  SCIPheurSetData(heur, NULL);
112 
113  return SCIP_OKAY;
114 }
115 
116 
117 /** initialization method of primal heuristic (called after problem was transformed) */
118 static
119 SCIP_DECL_HEURINIT(heurInitGuideddiving) /*lint --e{715}*/
120 { /*lint --e{715}*/
121  SCIP_HEURDATA* heurdata;
123  assert(heur != NULL);
124  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
125 
126  /* get heuristic data */
127  heurdata = SCIPheurGetData(heur);
128  assert(heurdata != NULL);
129 
130  /* create working solution */
131  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
132 
133  return SCIP_OKAY;
134 }
135 
136 
137 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
138 static
139 SCIP_DECL_HEUREXIT(heurExitGuideddiving) /*lint --e{715}*/
140 { /*lint --e{715}*/
141  SCIP_HEURDATA* heurdata;
143  assert(heur != NULL);
144  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
145 
146  /* get heuristic data */
147  heurdata = SCIPheurGetData(heur);
148  assert(heurdata != NULL);
149 
150  /* free working solution */
151  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
152 
153  return SCIP_OKAY;
154 }
155 
156 
157 /** execution method of primal heuristic */
158 static
159 SCIP_DECL_HEUREXEC(heurExecGuideddiving) /*lint --e{715}*/
160 { /*lint --e{715}*/
161  SCIP_HEURDATA* heurdata;
162  SCIP_DIVESET* diveset;
163 
164  assert(heur != NULL);
165  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
166  assert(scip != NULL);
167  assert(result != NULL);
168  assert(SCIPhasCurrentNodeLP(scip));
169 
170  *result = SCIP_DIDNOTRUN;
171 
172  /* don't dive, if no feasible solutions exist */
173  if( SCIPgetNSols(scip) == 0 )
174  return SCIP_OKAY;
175 
176  /* get best solution that should guide the search; if this solution lives in the original variable space,
177  * we cannot use it since it might violate the global bounds of the current problem
178  */
180  return SCIP_OKAY;
181 
182  /* get heuristic's data */
183  heurdata = SCIPheurGetData(heur);
184  assert(heurdata != NULL);
185 
186  /* if there are no integer variables (note that, e.g., SOS1 variables may be present) */
187  if ( SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip) == 0 )
188  return SCIP_OKAY;
189 
190  assert(SCIPheurGetNDivesets(heur) > 0);
191  assert(SCIPheurGetDivesets(heur) != NULL);
192  diveset = SCIPheurGetDivesets(heur)[0];
193  assert(diveset != NULL);
194 
195  /* call generic diving algorithm */
196  SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible) );
197 
198  return SCIP_OKAY;
199 }
200 
201 /* callbacks for diving */
202 
203 /** calculate score and preferred rounding direction for the candidate variable; the best candidate maximizes the
204  * score
205  */
206 static
207 SCIP_DECL_DIVESETGETSCORE(divesetGetScoreGuideddiving)
208 {
209  SCIP_SOL* bestsol;
210  SCIP_Real bestsolval;
211  SCIP_Real obj;
212  SCIP_Real objnorm;
213  SCIP_Real objgain;
214 
215  bestsol = SCIPgetBestSol(scip);
216  assert(bestsol != NULL);
217  assert(!SCIPsolIsOriginal(bestsol));
218 
219  bestsolval = SCIPgetSolVal(scip, bestsol, cand);
220 
221  /* variable should be rounded (guided) into the direction of its incumbent solution value */
222  if( candsol < bestsolval )
223  *roundup = TRUE;
224  else
225  *roundup = FALSE;
226 
227  obj = SCIPvarGetObj(cand);
228  objnorm = SCIPgetObjNorm(scip);
229 
230  /* divide by objective norm to normalize obj into [-1,1] */
231  if( SCIPisPositive(scip, objnorm) )
232  obj /= objnorm;
233 
234  /* calculate objective gain and fractionality for the selected rounding direction */
235  if( *roundup )
236  {
237  candsfrac = 1.0 - candsfrac;
238  objgain = obj * candsfrac;
239  }
240  else
241  objgain = -obj * candsfrac;
242 
243  assert(objgain >= -1.0 && objgain <= 1.0);
244 
245  /* penalize too small fractions */
246  if( candsfrac < 0.01 )
247  candsfrac *= 0.1;
248 
249  /* prefer decisions on binary variables */
250  if( !SCIPvarIsBinary(cand) )
251  candsfrac *= 0.1;
252 
253  /* prefer variables which cannot be rounded by scoring their fractionality */
254  if( !(SCIPvarMayRoundDown(cand) || SCIPvarMayRoundUp(cand)) )
255  *score = -candsfrac;
256  else
257  *score = -2.0 - objgain;
258 
259  return SCIP_OKAY;
260 }
261 
262 /*
263  * heuristic specific interface methods
264  */
265 
266 /** creates the guideddiving heuristic and includes it in SCIP */
268  SCIP* scip /**< SCIP data structure */
269  )
270 {
271  SCIP_HEURDATA* heurdata;
272  SCIP_HEUR* heur;
273 
274  /* create Guideddiving primal heuristic data */
275  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
276 
277  /* include primal heuristic */
278  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
280  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecGuideddiving, heurdata) );
281 
282  assert(heur != NULL);
283 
284  /* set non-NULL pointers to callback methods */
285  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyGuideddiving) );
286  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeGuideddiving) );
287  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitGuideddiving) );
288  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitGuideddiving) );
289 
290  /* create a diveset (this will automatically install some additional parameters for the heuristic)*/
294 
295  return SCIP_OKAY;
296 }
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2470
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2134
SCIP_RETCODE SCIPincludeHeurGuideddiving(SCIP *scip)
#define DEFAULT_LPSOLVEFREQ
#define NULL
Definition: def.h:239
#define DEFAULT_MINRELDEPTH
#define HEUR_MAXDEPTH
public methods for memory management
static SCIP_DECL_HEURINIT(heurInitGuideddiving)
#define HEUR_PRIORITY
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip_heur.c:280
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_DIVESET ** SCIPheurGetDivesets(SCIP_HEUR *heur)
Definition: heur.c:1452
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16909
static SCIP_DECL_DIVESETGETSCORE(divesetGetScoreGuideddiving)
#define FALSE
Definition: def.h:65
#define DEFAULT_ONLYLPBRANCHCANDS
#define DEFAULT_LPRESOLVEDOMCHGQUOT
#define DEFAULT_MAXDIVEAVGQUOT
#define TRUE
Definition: def.h:64
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
methods commonly used by primal heuristics
LP diving heuristic that chooses fixings in direction of incumbent solutions.
static SCIP_DECL_HEURCOPY(heurCopyGuideddiving)
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
public methods for problem variables
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:114
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip_heur.c:187
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1175
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:97
#define DEFAULT_MAXLPITERQUOT
SCIP_Real SCIPgetObjNorm(SCIP *scip)
Definition: scip_prob.c:1697
public methods for numerical tolerances
#define HEUR_TIMING
static SCIP_DECL_HEURFREE(heurFreeGuideddiving)
#define DIVESET_DIVETYPES
#define HEUR_USESSUBSCIP
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1254
#define HEUR_FREQOFS
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:248
#define DEFAULT_MAXRELDEPTH
SCIP_SOL * sol
Definition: struct_heur.h:41
public methods for primal CIP solutions
#define SCIP_CALL(x)
Definition: def.h:351
int SCIPheurGetNDivesets(SCIP_HEUR *heur)
Definition: heur.c:1462
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:141
public methods for primal heuristic plugins and divesets
#define DEFAULT_MAXLPITEROFS
SCIP_RETCODE SCIPcreateDiveset(SCIP *scip, SCIP_DIVESET **diveset, SCIP_HEUR *heur, const char *name, SCIP_Real minreldepth, SCIP_Real maxreldepth, SCIP_Real maxlpiterquot, SCIP_Real maxdiveubquot, SCIP_Real maxdiveavgquot, SCIP_Real maxdiveubquotnosol, SCIP_Real maxdiveavgquotnosol, SCIP_Real lpresolvedomchgquot, int lpsolvefreq, int maxlpiterofs, unsigned int initialseed, SCIP_Bool backtrack, SCIP_Bool onlylpbranchcands, SCIP_Bool specificsos1score, SCIP_DECL_DIVESETGETSCORE((*divesetgetscore)))
Definition: scip_heur.c:390
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1034
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17191
static SCIP_DECL_HEUREXIT(heurExitGuideddiving)
int SCIPgetNSols(SCIP *scip)
Definition: scip_sol.c:2280
#define HEUR_DESC
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2089
#define DEFAULT_MAXDIVEUBQUOT
public methods for the LP relaxation, rows and columns
SCIP_RETCODE SCIPperformGenericDivingAlgorithm(SCIP *scip, SCIP_DIVESET *diveset, SCIP_SOL *worksol, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_Bool nodeinfeasible)
Definition: heuristics.c:192
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2379
#define DEFAULT_RANDSEED
public methods for solutions
static SCIP_DECL_HEUREXEC(heurExecGuideddiving)
#define HEUR_FREQ
public methods for message output
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:264
#define DEFAULT_BACKTRACK
#define SCIP_Real
Definition: def.h:150
#define HEUR_DISPCHAR
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:232
public methods for primal heuristics
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1165
public methods for global and local (sub)problems
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1410
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3330
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3319
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:377
#define HEUR_NAME