Scippy

SCIP

Solving Constraint Integer Programs

branch_random.c
Go to the documentation of this file.
1 
2 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3 /* */
4 /* This file is part of the program and library */
5 /* SCIP --- Solving Constraint Integer Programs */
6 /* */
7 /* Copyright (C) 2002-2019 Konrad-Zuse-Zentrum */
8 /* fuer Informationstechnik Berlin */
9 /* */
10 /* SCIP is distributed under the terms of the ZIB Academic License. */
11 /* */
12 /* You should have received a copy of the ZIB Academic License */
13 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
14 /* */
15 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 
17 /**@file branch_random.c
18  * @brief random variable branching rule
19  * @author Tobias Achterberg
20  * @author Stefan Vigerske
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include "scip/branch_random.h"
26 #include "scip/pub_branch.h"
27 #include "scip/pub_message.h"
28 #include "scip/pub_misc.h"
29 #include "scip/pub_var.h"
30 #include "scip/scip_branch.h"
31 #include "scip/scip_message.h"
32 #include "scip/scip_mem.h"
33 #include "scip/scip_numerics.h"
34 #include "scip/scip_param.h"
35 #include "scip/scip_randnumgen.h"
36 #include "scip/scip_tree.h"
37 #include <string.h>
38 
39 
40 #define BRANCHRULE_NAME "random"
41 #define BRANCHRULE_DESC "random variable branching"
42 #define BRANCHRULE_PRIORITY -100000
43 #define BRANCHRULE_MAXDEPTH -1
44 #define BRANCHRULE_MAXBOUNDDIST 1.0
45 
46 #define DEFAULT_INITSEED 41 /**< initial random seed */
47 
48 /** branching rule data */
49 struct SCIP_BranchruleData
50 {
51  SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
52  int initseed; /**< initial random seed value */
53 };
54 
55 /*
56  * Local methods
57  */
58 
59 /** selects a random active variable from a given list of variables */
60 static
62  SCIP* scip, /**< SCIP data structure */
63  SCIP_BRANCHRULEDATA* branchruledata, /**< branchrule data */
64  SCIP_VAR** cands, /**< array of branching candidates */
65  SCIP_Real* candssol, /**< relaxation solution values of branching candidates, or NULL */
66  int ncands, /**< number of branching candidates */
67  SCIP_VAR** bestcand, /**< buffer to store pointer to best candidate */
68  SCIP_Real* bestcandsol /**< buffer to store solution value of best candidate */
69  )
70 {
71  int idx;
72  int firstidx;
73 
74  assert(scip != NULL);
75  assert(cands != NULL);
76  assert(ncands > 0);
77  assert(bestcand != NULL);
78  assert(bestcandsol != NULL);
79 
80  idx = SCIPrandomGetInt(branchruledata->randnumgen, 0, ncands-1);
81  assert(idx >= 0);
82 
83  /* handle case where cands[idx] is fixed by selecting next idx with unfixed var
84  * this may happen if we are inside a multi-aggregation */
85  firstidx = idx;
86  while( SCIPisEQ(scip, SCIPvarGetLbLocal(cands[idx]), SCIPvarGetUbLocal(cands[idx])) )
87  {
88  ++idx;
89  if( idx == ncands )
90  idx = 0;
91  if( idx == firstidx )
92  {
93  /* odd: all variables seem to be fixed */
94  SCIPdebugMsg(scip, "Warning: all branching candidates seem to be fixed\n");
95  return;
96  }
97  }
98 
99  /* a branching variable candidate should either be an active problem variable or a multi-aggregated variable */
100  assert(SCIPvarIsActive(SCIPvarGetProbvar(cands[idx])) ||
102 
104  {
105  /* for a multi-aggregated variable, we call the getRandomVariable function recursively with all variables in the multi-aggregation */
106  SCIP_VAR* cand;
107 
108  cand = SCIPvarGetProbvar(cands[idx]);
109 
110  getRandomVariable(scip, branchruledata, SCIPvarGetMultaggrVars(cand), NULL, SCIPvarGetMultaggrNVars(cand),
111  bestcand, bestcandsol);
112  return;
113  }
114 
115  assert(idx >= 0 && idx < ncands);
116 
117  *bestcand = cands[idx];
118  assert(*bestcand != NULL);
119 
120  if( candssol != NULL )
121  *bestcandsol = candssol[idx];
122 }
123 
124 /*
125  * Callback methods
126  */
127 
128 /** copy method for branchrule plugins (called when SCIP copies plugins) */
129 static
130 SCIP_DECL_BRANCHCOPY(branchCopyRandom)
131 { /*lint --e{715}*/
132  assert(scip != NULL);
133  assert(branchrule != NULL);
134  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
135 
136  /* call inclusion method of branchrule */
138 
139  return SCIP_OKAY;
140 }
141 
142 /** destructor of branching rule to free user data (called when SCIP is exiting) */
143 /**! [SnippetBranchFreeRandom] */
144 static
145 SCIP_DECL_BRANCHFREE(branchFreeRandom)
146 { /*lint --e{715}*/
147  SCIP_BRANCHRULEDATA* branchruledata;
148 
149  /* get branching rule data */
150  branchruledata = SCIPbranchruleGetData(branchrule);
151  assert(branchruledata != NULL);
152 
153  /* free branching rule data */
154  SCIPfreeBlockMemory(scip, &branchruledata);
155  SCIPbranchruleSetData(branchrule, NULL);
156 
157  return SCIP_OKAY;
158 }
159 /**! [SnippetBranchFreeRandom] */
160 
161 
162 /** initialization method of branching rule (called after problem was transformed) */
163 static
164 SCIP_DECL_BRANCHINIT(branchInitRandom)
165 { /*lint --e{715}*/
166  SCIP_BRANCHRULEDATA* branchruledata;
167 
168  branchruledata = SCIPbranchruleGetData(branchrule);
169  assert(branchruledata != NULL);
170  assert(branchruledata->initseed >= 0);
171 
172  /* create a random number generator */
173  SCIP_CALL( SCIPcreateRandom(scip, &branchruledata->randnumgen,
174  (unsigned int)branchruledata->initseed, TRUE) );
175 
176  return SCIP_OKAY;
177 }
178 
179 /** deinitialization method of branching rule */
180 static
181 SCIP_DECL_BRANCHEXIT(branchExitRandom)
182 { /*lint --e{715}*/
183  SCIP_BRANCHRULEDATA* branchruledata;
184 
185  /* get branching rule data */
186  branchruledata = SCIPbranchruleGetData(branchrule);
187  assert(branchruledata != NULL);
188 
189  /* free random number generator */
190  SCIPfreeRandom(scip, &branchruledata->randnumgen);
191 
192  return SCIP_OKAY;
193 }
194 
195 /** branching execution method for fractional LP solutions */
196 static
197 SCIP_DECL_BRANCHEXECLP(branchExeclpRandom)
198 { /*lint --e{715}*/
199  SCIP_BRANCHRULEDATA* branchruledata;
200  SCIP_VAR** lpcands;
201  int nlpcands;
202  int bestcand;
203 
204  assert(branchrule != NULL);
205  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
206  assert(scip != NULL);
207  assert(result != NULL);
208 
209  SCIPdebugMsg(scip, "Execlp method of random branching in depth %d\n", SCIPgetDepth(scip));
210 
211  branchruledata = SCIPbranchruleGetData(branchrule);
212  assert(branchruledata != NULL);
213 
214  /* get branching candidates */
215  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, NULL, NULL, &nlpcands, NULL) );
216  assert(nlpcands > 0);
217 
218  /* get random branching candidate */
219  bestcand = SCIPrandomGetInt(branchruledata->randnumgen, 0, nlpcands-1);
220  assert(bestcand >= 0);
221 
222  SCIPdebugMsg(scip, " -> %d candidates, selected candidate %d: variable <%s>\n",
223  nlpcands, bestcand, SCIPvarGetName(lpcands[bestcand]));
224 
225  /* perform the branching */
226  SCIP_CALL( SCIPbranchVar(scip, lpcands[bestcand], NULL, NULL, NULL) );
227  *result = SCIP_BRANCHED;
228 
229  return SCIP_OKAY;
230 }
231 
232 
233 /** branching execution method for external candidates */
234 static
235 SCIP_DECL_BRANCHEXECEXT(branchExecextRandom)
236 { /*lint --e{715}*/
237  SCIP_BRANCHRULEDATA* branchruledata;
238  SCIP_VAR** externcands;
239  SCIP_Real* externcandssol;
240  int nprioexterncands;
241  SCIP_VAR* bestcand;
242  SCIP_Real bestcandsol;
243  SCIP_Real brpoint;
244  SCIP_NODE* downchild;
245  SCIP_NODE* eqchild;
246  SCIP_NODE* upchild;
247 
248  assert(branchrule != NULL);
249  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
250  assert(scip != NULL);
251  assert(result != NULL);
252 
253  SCIPdebugMsg(scip, "Execrel method of random branching\n");
254 
255  branchruledata = SCIPbranchruleGetData(branchrule);
256  assert(branchruledata != NULL);
257 
258  bestcand = NULL;
259  bestcandsol = 0.0;
260 
261  /* get branching candidates */
262  SCIP_CALL( SCIPgetExternBranchCands(scip, &externcands, &externcandssol, NULL, NULL, &nprioexterncands, NULL, NULL, NULL) );
263  assert(nprioexterncands > 0);
264 
265  /* get random branching candidate
266  *
267  * since variables can occur several times in the list of candidates, variables that have been added more often have
268  * a higher probability to be chosen for branching
269  */
270  getRandomVariable(scip, branchruledata, externcands, externcandssol, nprioexterncands, &bestcand, &bestcandsol);
271 
272  if( bestcand == NULL )
273  {
274  SCIPerrorMessage("branchExecrelRandom failed to select a branching variable from %d candidates\n", nprioexterncands);
275  *result = SCIP_DIDNOTRUN;
276  return SCIP_OKAY;
277  }
278 
279  brpoint = SCIPgetBranchingPoint(scip, bestcand, bestcandsol);
280 
281  SCIPdebugMsg(scip, " -> %d candidates, selected variable <%s> with solution value %g, branching point=%g\n",
282  nprioexterncands, SCIPvarGetName(bestcand), bestcandsol, brpoint);
283 
284  SCIP_CALL( SCIPbranchVarVal(scip, bestcand, brpoint, &downchild, &eqchild, &upchild) );
285 
286  if( downchild != NULL || eqchild != NULL || upchild != NULL )
287  {
288  *result = SCIP_BRANCHED;
289  }
290  else
291  {
292  /* if there are no children, then variable should have been fixed by SCIPbranchVarVal */
293  assert(SCIPisEQ(scip, SCIPvarGetLbLocal(bestcand), SCIPvarGetUbLocal(bestcand)));
294  *result = SCIP_REDUCEDDOM;
295  }
296 
297  return SCIP_OKAY;
298 }
299 
300 /** branching execution method for not completely fixed pseudo solutions */
301 static
302 SCIP_DECL_BRANCHEXECPS(branchExecpsRandom)
303 { /*lint --e{715}*/
304  SCIP_BRANCHRULEDATA* branchruledata;
305  SCIP_VAR** pseudocands;
306  int npseudocands;
307  int bestcand;
308 
309  assert(branchrule != NULL);
310  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
311  assert(scip != NULL);
312  assert(result != NULL);
313 
314  SCIPdebugMsg(scip, "Execps method of random branching\n");
315 
316  branchruledata = SCIPbranchruleGetData(branchrule);
317  assert(branchruledata != NULL);
318 
319  /* get branching candidates */
320  SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, NULL, &npseudocands) );
321  assert(npseudocands > 0);
322 
323  /* get random branching candidate */
324  bestcand = SCIPrandomGetInt(branchruledata->randnumgen, 0, npseudocands-1);
325  assert(bestcand >= 0);
326 
327  SCIPdebugMsg(scip, " -> %d candidates, selected candidate %d: variable <%s>\n",
328  npseudocands, bestcand, SCIPvarGetName(pseudocands[bestcand]));
329 
330  /* perform the branching */
331  SCIP_CALL( SCIPbranchVar(scip, pseudocands[bestcand], NULL, NULL, NULL) );
332  *result = SCIP_BRANCHED;
333 
334  return SCIP_OKAY;
335 }
336 
337 
338 /*
339  * branching specific interface methods
340  */
341 
342 /** creates the random branching rule and includes it in SCIP */
344  SCIP* scip /**< SCIP data structure */
345  )
346 {
347  SCIP_BRANCHRULEDATA* branchruledata;
348  SCIP_BRANCHRULE* branchrule;
349 
350  /* create random branching rule data */
351  SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
352 
353  /* include allfullstrong branching rule */
355  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
356 
357  assert(branchrule != NULL);
358 
359  /* set non-fundamental callbacks via specific setter functions*/
360  SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyRandom) );
361  SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeRandom) );
362  SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitRandom) );
363  SCIP_CALL( SCIPsetBranchruleExit(scip, branchrule, branchExitRandom) );
364  SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpRandom) );
365  SCIP_CALL( SCIPsetBranchruleExecExt(scip, branchrule, branchExecextRandom) );
366  SCIP_CALL( SCIPsetBranchruleExecPs(scip, branchrule, branchExecpsRandom) );
367 
368  SCIP_CALL( SCIPaddIntParam(scip, "branching/" BRANCHRULE_NAME "/seed", "initial random seed value",
369  &branchruledata->initseed, FALSE, DEFAULT_INITSEED, 0, INT_MAX, NULL, NULL) );
370 
371  return SCIP_OKAY;
372 }
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip_branch.c:384
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
static SCIP_DECL_BRANCHFREE(branchFreeRandom)
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1848
#define NULL
Definition: def.h:246
#define BRANCHRULE_MAXDEPTH
Definition: branch_random.c:43
public methods for SCIP parameter handling
SCIP_RETCODE SCIPsetBranchruleExecPs(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECPS((*branchexecps)))
Definition: scip_branch.c:270
public methods for memory management
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17124
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17400
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:43
static SCIP_DECL_BRANCHEXECEXT(branchExecextRandom)
random variable branching rule
SCIP_Real SCIPgetBranchingPoint(SCIP *scip, SCIP_VAR *var, SCIP_Real suggestion)
Definition: scip_branch.c:886
SCIP_RETCODE SCIPsetBranchruleExit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXIT((*branchexit)))
Definition: scip_branch.c:190
static SCIP_DECL_BRANCHEXECLP(branchExeclpRandom)
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip_branch.c:158
static SCIP_DECL_BRANCHINIT(branchInitRandom)
#define FALSE
Definition: def.h:72
#define TRUE
Definition: def.h:71
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: scip_branch.c:142
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_DECL_BRANCHEXECPS(branchExecpsRandom)
public methods for problem variables
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:114
#define BRANCHRULE_MAXBOUNDDIST
Definition: branch_random.c:44
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:9608
public methods for branching rules
SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
Definition: scip_branch.c:105
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPgetExternBranchCands(SCIP *scip, SCIP_VAR ***externcands, SCIP_Real **externcandssol, SCIP_Real **externcandsscore, int *nexterncands, int *nprioexterncands, int *nprioexternbins, int *nprioexternints, int *nprioexternimpls)
Definition: scip_branch.c:500
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:97
#define SCIPdebugMsg
Definition: scip_message.h:88
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:155
public methods for numerical tolerances
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip_branch.c:238
public methods for the branch-and-bound tree
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11704
static SCIP_DECL_BRANCHEXIT(branchExitRandom)
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip_branch.c:992
#define SCIPerrorMessage
Definition: pub_message.h:45
#define BRANCHRULE_PRIORITY
Definition: branch_random.c:42
SCIP_RETCODE SCIPincludeBranchruleRandom(SCIP *scip)
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16730
#define SCIP_CALL(x)
Definition: def.h:358
SCIP_RETCODE SCIPbranchVarVal(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip_branch.c:1068
SCIP_RETCODE SCIPgetPseudoBranchCands(SCIP *scip, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
Definition: scip_branch.c:722
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
public data structures and miscellaneous methods
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:715
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1858
SCIP_RETCODE SCIPsetBranchruleExecExt(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECEXT((*branchexecext)))
Definition: scip_branch.c:254
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17112
public methods for branching rule plugins and branching
static void getRandomVariable(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR **cands, SCIP_Real *candssol, int ncands, SCIP_VAR **bestcand, SCIP_Real *bestcandsol)
Definition: branch_random.c:61
public methods for random numbers
#define BRANCHRULE_NAME
Definition: branch_random.c:40
public methods for message output
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16849
#define BRANCHRULE_DESC
Definition: branch_random.c:41
#define SCIP_Real
Definition: def.h:157
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1970
SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
Definition: scip_branch.c:174
public methods for message handling
#define DEFAULT_INITSEED
Definition: branch_random.c:46
static SCIP_DECL_BRANCHCOPY(branchCopyRandom)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17410
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17017