1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /*                                                                           */
3 /*                  This file is part of the program and library             */
4 /*         SCIP --- Solving Constraint Integer Programs                      */
5 /*                                                                           */
6 /*    Copyright (C) 2002-2021 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 scipopt.org.         */
13 /*                                                                           */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file   scip_nodesel.c
17  * @ingroup OTHER_CFILES
18  * @brief  public methods for node selector plugins
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  * @author Gerald Gamrath
22  * @author Leona Gottwald
23  * @author Stefan Heinz
24  * @author Gregor Hendel
25  * @author Thorsten Koch
26  * @author Alexander Martin
27  * @author Marc Pfetsch
28  * @author Michael Winkler
29  * @author Kati Wolter
30  *
31  * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 #include "scip/debug.h"
37 #include "scip/nodesel.h"
38 #include "scip/pub_message.h"
39 #include "scip/scip_nodesel.h"
40 #include "scip/set.h"
41 #include "scip/struct_mem.h"
42 #include "scip/struct_scip.h"
43 #include "scip/struct_set.h"
44 
45 /** creates a node selector and includes it in SCIP.
46  *
47  *  @note method has all node selector callbacks as arguments and is thus changed every time a new
48  *        callback is added in future releases; consider using SCIPincludeNodeselBasic() and setter functions
49  *        if you seek for a method which is less likely to change in future releases
50  */
SCIPincludeNodesel(SCIP * scip,const char * name,const char * desc,int stdpriority,int memsavepriority,SCIP_DECL_NODESELCOPY ((* nodeselcopy)),SCIP_DECL_NODESELFREE ((* nodeselfree)),SCIP_DECL_NODESELINIT ((* nodeselinit)),SCIP_DECL_NODESELEXIT ((* nodeselexit)),SCIP_DECL_NODESELINITSOL ((* nodeselinitsol)),SCIP_DECL_NODESELEXITSOL ((* nodeselexitsol)),SCIP_DECL_NODESELSELECT ((* nodeselselect)),SCIP_DECL_NODESELCOMP ((* nodeselcomp)),SCIP_NODESELDATA * nodeseldata)51 SCIP_RETCODE SCIPincludeNodesel(
52    SCIP*                 scip,               /**< SCIP data structure */
53    const char*           name,               /**< name of node selector */
54    const char*           desc,               /**< description of node selector */
55    int                   stdpriority,        /**< priority of the node selector in standard mode */
56    int                   memsavepriority,    /**< priority of the node selector in memory saving mode */
57    SCIP_DECL_NODESELCOPY ((*nodeselcopy)),   /**< copy method of node selector or NULL if you don't want to copy your plugin into sub-SCIPs */
58    SCIP_DECL_NODESELFREE ((*nodeselfree)),   /**< destructor of node selector */
59    SCIP_DECL_NODESELINIT ((*nodeselinit)),   /**< initialize node selector */
60    SCIP_DECL_NODESELEXIT ((*nodeselexit)),   /**< deinitialize node selector */
61    SCIP_DECL_NODESELINITSOL((*nodeselinitsol)),/**< solving process initialization method of node selector */
62    SCIP_DECL_NODESELEXITSOL((*nodeselexitsol)),/**< solving process deinitialization method of node selector */
63    SCIP_DECL_NODESELSELECT((*nodeselselect)),/**< node selection method */
64    SCIP_DECL_NODESELCOMP ((*nodeselcomp)),   /**< node comparison method */
65    SCIP_NODESELDATA*     nodeseldata         /**< node selector data */
66    )
67 {
68    SCIP_NODESEL* nodesel;
69 
70    SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeNodesel", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
71 
72    /* check whether node selector is already present */
73    if( SCIPfindNodesel(scip, name) != NULL )
74    {
75       SCIPerrorMessage("node selector <%s> already included.\n", name);
76       return SCIP_INVALIDDATA;
77    }
78 
79    SCIP_CALL( SCIPnodeselCreate(&nodesel, scip->set, scip->messagehdlr, scip->mem->setmem, name, desc, stdpriority, memsavepriority,
80          nodeselcopy, nodeselfree, nodeselinit, nodeselexit, nodeselinitsol, nodeselexitsol,
81          nodeselselect, nodeselcomp, nodeseldata) );
82    SCIP_CALL( SCIPsetIncludeNodesel(scip->set, nodesel) );
83 
84    return SCIP_OKAY;
85 }
86 
87 /** Creates a node selector and includes it in SCIP with its most fundamental callbacks. All non-fundamental
88  *  (or optional) callbacks as, e.g., init and exit callbacks, will be set to NULL.
89  *  Optional callbacks can be set via specific setter functions, see SCIPsetNodeselCopy(), SCIPsetNodeselFree(),
90  *  SCIPsetNodeselInit(), SCIPsetNodeselExit(), SCIPsetNodeselInitsol(), and SCIPsetNodeselExitsol()
91  *
92  *  @note if you want to set all callbacks with a single method call, consider using SCIPincludeNodesel() instead
93  */
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)94 SCIP_RETCODE SCIPincludeNodeselBasic(
95    SCIP*                 scip,               /**< SCIP data structure */
96    SCIP_NODESEL**        nodesel,            /**< reference to a node selector, or NULL */
97    const char*           name,               /**< name of node selector */
98    const char*           desc,               /**< description of node selector */
99    int                   stdpriority,        /**< priority of the node selector in standard mode */
100    int                   memsavepriority,    /**< priority of the node selector in memory saving mode */
101    SCIP_DECL_NODESELSELECT((*nodeselselect)),/**< node selection method */
102    SCIP_DECL_NODESELCOMP ((*nodeselcomp)),   /**< node comparison method */
103    SCIP_NODESELDATA*     nodeseldata         /**< node selector data */
104    )
105 {
106    SCIP_NODESEL* nodeselptr;
107 
108    SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeNodeselBasic", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
109 
110    /* check whether node selector is already present */
111    if( SCIPfindNodesel(scip, name) != NULL )
112    {
113       SCIPerrorMessage("node selector <%s> already included.\n", name);
114       return SCIP_INVALIDDATA;
115    }
116 
117    SCIP_CALL( SCIPnodeselCreate(&nodeselptr, scip->set, scip->messagehdlr, scip->mem->setmem, name, desc, stdpriority, memsavepriority,
118          NULL, NULL, NULL, NULL, NULL, NULL,
119          nodeselselect, nodeselcomp, nodeseldata) );
120    SCIP_CALL( SCIPsetIncludeNodesel(scip->set, nodeselptr) );
121 
122    if( nodesel != NULL )
123       *nodesel = nodeselptr;
124 
125    return SCIP_OKAY;
126 }
127 
128 /** sets copy method of node selector */
SCIPsetNodeselCopy(SCIP * scip,SCIP_NODESEL * nodesel,SCIP_DECL_NODESELCOPY ((* nodeselcopy)))129 SCIP_RETCODE SCIPsetNodeselCopy(
130    SCIP*                 scip,               /**< SCIP data structure */
131    SCIP_NODESEL*         nodesel,            /**< node selector */
132    SCIP_DECL_NODESELCOPY ((*nodeselcopy))    /**< copy method of node selector or NULL if you don't want to copy your plugin into sub-SCIPs */
133    )
134 {
135    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetNodeselCopy", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
136 
137    assert(nodesel != NULL);
138 
139    SCIPnodeselSetCopy(nodesel, nodeselcopy);
140 
141    return SCIP_OKAY;
142 }
143 
144 /** sets destructor method of node selector */
SCIPsetNodeselFree(SCIP * scip,SCIP_NODESEL * nodesel,SCIP_DECL_NODESELFREE ((* nodeselfree)))145 SCIP_RETCODE SCIPsetNodeselFree(
146    SCIP*                 scip,               /**< SCIP data structure */
147    SCIP_NODESEL*         nodesel,            /**< node selector */
148    SCIP_DECL_NODESELFREE ((*nodeselfree))    /**< destructor of node selector */
149    )
150 {
151    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetNodeselFree", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
152 
153    assert(nodesel != NULL);
154 
155    SCIPnodeselSetFree(nodesel, nodeselfree);
156 
157    return SCIP_OKAY;
158 }
159 
160 /** sets initialization method of node selector */
SCIPsetNodeselInit(SCIP * scip,SCIP_NODESEL * nodesel,SCIP_DECL_NODESELINIT ((* nodeselinit)))161 SCIP_RETCODE SCIPsetNodeselInit(
162    SCIP*                 scip,               /**< SCIP data structure */
163    SCIP_NODESEL*         nodesel,            /**< node selector */
164    SCIP_DECL_NODESELINIT ((*nodeselinit))    /**< initialize node selector */
165    )
166 {
167    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetNodeselInit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
168 
169    assert(nodesel != NULL);
170 
171    SCIPnodeselSetInit(nodesel, nodeselinit);
172 
173    return SCIP_OKAY;
174 }
175 
176 /** sets deinitialization method of node selector */
SCIPsetNodeselExit(SCIP * scip,SCIP_NODESEL * nodesel,SCIP_DECL_NODESELEXIT ((* nodeselexit)))177 SCIP_RETCODE SCIPsetNodeselExit(
178    SCIP*                 scip,               /**< SCIP data structure */
179    SCIP_NODESEL*         nodesel,            /**< node selector */
180    SCIP_DECL_NODESELEXIT ((*nodeselexit))    /**< deinitialize node selector */
181    )
182 {
183    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetNodeselExit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
184 
185    assert(nodesel != NULL);
186 
187    SCIPnodeselSetExit(nodesel, nodeselexit);
188 
189    return SCIP_OKAY;
190 }
191 
192 /** sets solving process initialization method of node selector */
SCIPsetNodeselInitsol(SCIP * scip,SCIP_NODESEL * nodesel,SCIP_DECL_NODESELINITSOL ((* nodeselinitsol)))193 SCIP_RETCODE SCIPsetNodeselInitsol(
194    SCIP*                 scip,               /**< SCIP data structure */
195    SCIP_NODESEL*         nodesel,            /**< node selector */
196    SCIP_DECL_NODESELINITSOL ((*nodeselinitsol))/**< solving process initialization method of node selector */
197    )
198 {
199    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetNodeselInitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
200 
201    assert(nodesel != NULL);
202 
203    SCIPnodeselSetInitsol(nodesel, nodeselinitsol);
204 
205    return SCIP_OKAY;
206 }
207 
208 /** sets solving process deinitialization method of node selector */
SCIPsetNodeselExitsol(SCIP * scip,SCIP_NODESEL * nodesel,SCIP_DECL_NODESELEXITSOL ((* nodeselexitsol)))209 SCIP_RETCODE SCIPsetNodeselExitsol(
210    SCIP*                 scip,               /**< SCIP data structure */
211    SCIP_NODESEL*         nodesel,            /**< node selector */
212    SCIP_DECL_NODESELEXITSOL ((*nodeselexitsol))/**< solving process deinitialization method of node selector */
213    )
214 {
215    SCIP_CALL( SCIPcheckStage(scip, "SCIPsetNodeselExitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
216 
217    assert(nodesel != NULL);
218 
219    SCIPnodeselSetExitsol(nodesel, nodeselexitsol);
220 
221    return SCIP_OKAY;
222 }
223 
224 /** returns the node selector of the given name, or NULL if not existing */
SCIPfindNodesel(SCIP * scip,const char * name)225 SCIP_NODESEL* SCIPfindNodesel(
226    SCIP*                 scip,               /**< SCIP data structure */
227    const char*           name                /**< name of node selector */
228    )
229 {
230    assert(scip != NULL);
231    assert(scip->set != NULL);
232    assert(name != NULL);
233 
234    return SCIPsetFindNodesel(scip->set, name);
235 }
236 
237 /** returns the array of currently available node selectors */
SCIPgetNodesels(SCIP * scip)238 SCIP_NODESEL** SCIPgetNodesels(
239    SCIP*                 scip                /**< SCIP data structure */
240    )
241 {
242    assert(scip != NULL);
243    assert(scip->set != NULL);
244 
245    return scip->set->nodesels;
246 }
247 
248 /** returns the number of currently available node selectors */
SCIPgetNNodesels(SCIP * scip)249 int SCIPgetNNodesels(
250    SCIP*                 scip                /**< SCIP data structure */
251    )
252 {
253    assert(scip != NULL);
254    assert(scip->set != NULL);
255 
256    return scip->set->nnodesels;
257 }
258 
259 /** sets the priority of a node selector in standard mode */
SCIPsetNodeselStdPriority(SCIP * scip,SCIP_NODESEL * nodesel,int priority)260 SCIP_RETCODE SCIPsetNodeselStdPriority(
261    SCIP*                 scip,               /**< SCIP data structure */
262    SCIP_NODESEL*         nodesel,            /**< node selector */
263    int                   priority            /**< new standard priority of the node selector */
264    )
265 {
266    assert(scip != NULL);
267    assert(scip->set != NULL);
268 
269    SCIPnodeselSetStdPriority(nodesel, scip->set, priority);
270 
271    return SCIP_OKAY;
272 }
273 
274 /** sets the priority of a node selector in memory saving mode */
SCIPsetNodeselMemsavePriority(SCIP * scip,SCIP_NODESEL * nodesel,int priority)275 SCIP_RETCODE SCIPsetNodeselMemsavePriority(
276    SCIP*                 scip,               /**< SCIP data structure */
277    SCIP_NODESEL*         nodesel,            /**< node selector */
278    int                   priority            /**< new memory saving priority of the node selector */
279    )
280 {
281    assert(scip != NULL);
282    assert(scip->set != NULL);
283 
284    SCIPnodeselSetMemsavePriority(nodesel, scip->set, priority);
285 
286    return SCIP_OKAY;
287 }
288 
289 /** returns the currently used node selector */
SCIPgetNodesel(SCIP * scip)290 SCIP_NODESEL* SCIPgetNodesel(
291    SCIP*                 scip                /**< SCIP data structure */
292    )
293 {
294    assert(scip != NULL);
295    assert(scip->set != NULL);
296 
297    return SCIPsetGetNodesel(scip->set, scip->stat);
298 }
299