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