Scippy

SCIP

Solving Constraint Integer Programs

nodesel_restartdfs.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-2019 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 nodesel_restartdfs.c
17  * @brief node selector for depth first search with periodical selection of the best node
18  * @author Tobias Achterberg
19  * @author Stefan Heinz
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
25 #include "scip/pub_message.h"
26 #include "scip/pub_nodesel.h"
27 #include "scip/pub_tree.h"
28 #include "scip/scip_mem.h"
29 #include "scip/scip_nodesel.h"
30 #include "scip/scip_param.h"
31 #include "scip/scip_solvingstats.h"
32 #include "scip/scip_tree.h"
33 #include <string.h>
34 
35 #define NODESEL_NAME "restartdfs"
36 #define NODESEL_DESC "depth first search with periodical selection of the best node"
37 #define NODESEL_STDPRIORITY 10000
38 #define NODESEL_MEMSAVEPRIORITY 50000
39 
40 
41 /*
42  * Default parameter settings
43  */
44 
45 #define SELECTBESTFREQ 100 /**< frequency for selecting the best node instead of the deepest one */
46 #define COUNTONLYLEAVES TRUE /**< only count leaf nodes or all nodes */
47 
48 
49 /** node selector data for best first search node selection */
50 struct SCIP_NodeselData
51 {
52  SCIP_Longint lastrestart; /**< node number where the last best node was selected */
53  SCIP_Longint nprocessedleaves; /**< number of processed leafs since the last restart */
54  int selectbestfreq; /**< frequency for selecting the best node instead of the deepest one */
55  SCIP_Bool countonlyleaves; /**< only count leaf nodes or all nodes */
56 };
57 
58 
59 /*
60  * Callback methods
61  */
62 
63 /** copy method for node selector plugins (called when SCIP copies plugins) */
64 static
65 SCIP_DECL_NODESELCOPY(nodeselCopyRestartdfs)
66 { /*lint --e{715}*/
67  assert(scip != NULL);
68  assert(nodesel != NULL);
69  assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0);
70 
71  /* call inclusion method of node selector */
73 
74  return SCIP_OKAY;
75 }
76 
77 /** destructor of node selector to free user data (called when SCIP is exiting) */
78 static
79 SCIP_DECL_NODESELFREE(nodeselFreeRestartdfs)
80 { /*lint --e{715}*/
81  SCIP_NODESELDATA* nodeseldata;
82 
83  assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0);
84 
85  /* free user data of node selector */
86  nodeseldata = SCIPnodeselGetData(nodesel);
87  assert(nodeseldata != NULL);
88  SCIPfreeBlockMemory(scip, &nodeseldata);
89  SCIPnodeselSetData(nodesel, nodeseldata);
90 
91  return SCIP_OKAY;
92 }
93 
94 
95 /** solving process initialization method of node selector (called when branch and bound process is about to begin) */
96 static
97 SCIP_DECL_NODESELINITSOL(nodeselInitsolRestartdfs)
98 {
99  SCIP_NODESELDATA* nodeseldata;
100 
101  assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0);
102 
103  nodeseldata = SCIPnodeselGetData(nodesel);
104  assert(nodeseldata != NULL);
105 
106  /* reset counters */
107  nodeseldata->lastrestart = 0;
108  nodeseldata->nprocessedleaves = 0;
109 
110  return SCIP_OKAY;
111 }
112 
113 
114 /** node selection method of node selector */
115 static
116 SCIP_DECL_NODESELSELECT(nodeselSelectRestartdfs)
117 { /*lint --e{715}*/
118  assert(strcmp(SCIPnodeselGetName(nodesel), NODESEL_NAME) == 0);
119  assert(selnode != NULL);
120 
121  /* decide if we want to select the node with lowest bound or the deepest node; finish the current dive in any case */
122  *selnode = SCIPgetPrioChild(scip);
123  if( *selnode == NULL )
124  {
125  SCIP_NODESELDATA* nodeseldata;
127 
128  /* get node selector user data */
129  nodeseldata = SCIPnodeselGetData(nodesel);
130  assert(nodeseldata != NULL);
131 
132  /* increase the number of processed leafs since we are in a leaf */
133  nodeseldata->nprocessedleaves++;
134 
135  nnodes = SCIPgetNNodes(scip);
136 
137  /* check if in case of "only leaves" the number processed leaves exceeds the frequency or in the other case the
138  * number of processed node does it
139  */
140  if( (nodeseldata->countonlyleaves && nodeseldata->nprocessedleaves >= nodeseldata->selectbestfreq)
141  || (!nodeseldata->countonlyleaves && nnodes - nodeseldata->lastrestart >= nodeseldata->selectbestfreq ) )
142  {
143  nodeseldata->lastrestart = nnodes;
144  nodeseldata->nprocessedleaves = 0;
145  *selnode = SCIPgetBestboundNode(scip);
146  }
147  else
148  {
149  *selnode = SCIPgetPrioSibling(scip);
150  if( *selnode == NULL )
151  *selnode = SCIPgetBestLeaf(scip);
152  }
153  }
154 
155  return SCIP_OKAY;
156 }
157 
158 
159 /** node comparison method of node selector */
160 static
161 SCIP_DECL_NODESELCOMP(nodeselCompRestartdfs)
162 { /*lint --e{715}*/
163  return (int)(SCIPnodeGetNumber(node2) - SCIPnodeGetNumber(node1));
164 }
165 
166 
167 /*
168  * restartdfs specific interface methods
169  */
170 
171 /** creates the node selector for restarting depth first search and includes it in SCIP */
173  SCIP* scip /**< SCIP data structure */
174  )
175 {
176  SCIP_NODESELDATA* nodeseldata;
177  SCIP_NODESEL* nodesel;
178 
179  /* allocate and initialize node selector data; this has to be freed in the destructor */
180  SCIP_CALL( SCIPallocBlockMemory(scip, &nodeseldata) );
181  nodeseldata->lastrestart = 0;
182  nodeseldata->nprocessedleaves = 0;
183  nodeseldata->selectbestfreq = SELECTBESTFREQ;
184  nodeseldata->countonlyleaves = COUNTONLYLEAVES;
185 
186  /* include node selector */
188  nodeselSelectRestartdfs, nodeselCompRestartdfs, nodeseldata) );
189 
190  assert(nodesel != NULL);
191 
192  SCIP_CALL( SCIPsetNodeselCopy(scip, nodesel, nodeselCopyRestartdfs) );
193  SCIP_CALL( SCIPsetNodeselFree(scip, nodesel, nodeselFreeRestartdfs) );
194  SCIP_CALL( SCIPsetNodeselInitsol(scip, nodesel, nodeselInitsolRestartdfs) );
195 
196  /* add node selector parameters */
198  "nodeselection/restartdfs/selectbestfreq",
199  "frequency for selecting the best node instead of the deepest one",
200  &nodeseldata->selectbestfreq, FALSE, SELECTBESTFREQ, 0, INT_MAX, NULL, NULL) );
201 
202  /* add node selector parameters */
204  "nodeselection/restartdfs/countonlyleaves",
205  "count only leaf nodes (otherwise all nodes)?",
206  &nodeseldata->countonlyleaves, FALSE, COUNTONLYLEAVES, NULL, NULL) );
207 
208  return SCIP_OKAY;
209 }
210 
#define NULL
Definition: def.h:253
public methods for SCIP parameter handling
public methods for branch and bound tree
#define NODESEL_MEMSAVEPRIORITY
public methods for node selector plugins
public methods for memory management
SCIP_NODE * SCIPgetBestLeaf(SCIP *scip)
Definition: scip_tree.c:341
SCIP_RETCODE SCIPsetNodeselCopy(SCIP *scip, SCIP_NODESEL *nodesel, SCIP_DECL_NODESELCOPY((*nodeselcopy)))
Definition: scip_nodesel.c:128
SCIP_EXPORT SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7347
SCIP_NODE * SCIPgetPrioSibling(SCIP *scip)
Definition: scip_tree.c:293
SCIP_RETCODE SCIPsetNodeselFree(SCIP *scip, SCIP_NODESEL *nodesel, SCIP_DECL_NODESELFREE((*nodeselfree)))
Definition: scip_nodesel.c:144
#define FALSE
Definition: def.h:73
node selector for depth first search with periodical selection of the best node
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
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_param.c:47
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:95
SCIP_RETCODE SCIPsetNodeselInitsol(SCIP *scip, SCIP_NODESEL *nodesel, SCIP_DECL_NODESELINITSOL((*nodeselinitsol)))
Definition: scip_nodesel.c:192
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:78
static SCIP_DECL_NODESELINITSOL(nodeselInitsolRestartdfs)
public methods for querying solving statistics
public methods for the branch-and-bound tree
struct SCIP_NodeselData SCIP_NODESELDATA
Definition: type_nodesel.h:38
SCIP_Longint SCIPgetNNodes(SCIP *scip)
#define SELECTBESTFREQ
#define NODESEL_STDPRIORITY
#define COUNTONLYLEAVES
SCIP_NODESELDATA * SCIPnodeselGetData(SCIP_NODESEL *nodesel)
Definition: nodesel.c:1106
#define NODESEL_NAME
#define SCIP_CALL(x)
Definition: def.h:365
static SCIP_DECL_NODESELCOPY(nodeselCopyRestartdfs)
static SCIP_DECL_NODESELCOMP(nodeselCompRestartdfs)
SCIP_NODE * SCIPgetPrioChild(SCIP *scip)
Definition: scip_tree.c:277
public methods for node selectors
#define SCIP_Bool
Definition: def.h:70
void SCIPnodeselSetData(SCIP_NODESEL *nodesel, SCIP_NODESELDATA *nodeseldata)
Definition: nodesel.c:1116
SCIP_NODE * SCIPgetBestboundNode(SCIP *scip)
Definition: scip_tree.c:373
SCIP_RETCODE SCIPincludeNodeselBasic(SCIP *scip, SCIP_NODESEL **nodesel, const char *name, const char *desc, int stdpriority, int memsavepriority, SCIP_DECL_NODESELSELECT((*nodeselselect)), SCIP_DECL_NODESELCOMP((*nodeselcomp)), SCIP_NODESELDATA *nodeseldata)
Definition: scip_nodesel.c:93
const char * SCIPnodeselGetName(SCIP_NODESEL *nodesel)
Definition: nodesel.c:1038
public methods for message output
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:73
static SCIP_DECL_NODESELFREE(nodeselFreeRestartdfs)
SCIP_RETCODE SCIPincludeNodeselRestartdfs(SCIP *scip)
#define SCIP_Longint
Definition: def.h:149
#define nnodes
Definition: gastrans.c:65
static SCIP_DECL_NODESELSELECT(nodeselSelectRestartdfs)
#define NODESEL_DESC