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   nodesel.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  methods for node selectors
28   	 * @author Tobias Achterberg
29   	 * @author Timo Berthold
30   	 */
31   	
32   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33   	
34   	#include <assert.h>
35   	#include <string.h>
36   	
37   	#include "scip/def.h"
38   	#include "scip/set.h"
39   	#include "scip/clock.h"
40   	#include "scip/stat.h"
41   	#include "scip/visual.h"
42   	#include "scip/paramset.h"
43   	#include "scip/tree.h"
44   	#include "scip/reopt.h"
45   	#include "scip/lp.h"
46   	#include "scip/scip.h"
47   	#include "scip/nodesel.h"
48   	#include "scip/pub_message.h"
49   	#include "scip/pub_misc.h"
50   	
51   	#include "scip/struct_nodesel.h"
52   	#include "scip/struct_scip.h"
53   	
54   	/* 
55   	 * node priority queue methods
56   	 */
57   	
58   	#define PQ_PARENT(q) (((q)+1)/2-1)
59   	#define PQ_LEFTCHILD(p) (2*(p)+1)
60   	#define PQ_RIGHTCHILD(p) (2*(p)+2)
61   	
62   	
63   	/** node comparator for node numbers */
64   	static
65   	SCIP_DECL_SORTPTRCOMP(nodeCompNumber)
66   	{  /*lint --e{715}*/
67   	   assert(elem1 != NULL);
68   	   assert(elem2 != NULL);
69   	
70   	   if( ((SCIP_NODE*)elem1)->number < ((SCIP_NODE*)elem2)->number )
71   	      return -1;
72   	   else if( ((SCIP_NODE*)elem1)->number > ((SCIP_NODE*)elem2)->number )
73   	      return +1;
74   	   else
75   	   {
76   	      /* no such two nodes should have the same node number */
77   	      assert(elem1 == elem2);
78   	      return 0;
79   	   }
80   	}
81   	
82   	
83   	/** resizes node memory to hold at least the given number of nodes */
84   	static
85   	SCIP_RETCODE nodepqResize(
86   	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
87   	   SCIP_SET*             set,                /**< global SCIP settings */
88   	   int                   minsize             /**< minimal number of storable nodes */
89   	   )
90   	{
91   	   assert(nodepq != NULL);
92   	
93   	   if( minsize <= nodepq->size )
94   	      return SCIP_OKAY;
95   	
96   	   nodepq->size = SCIPsetCalcTreeGrowSize(set, minsize);
97   	   SCIP_ALLOC( BMSreallocMemoryArray(&nodepq->slots, nodepq->size) );
98   	   SCIP_ALLOC( BMSreallocMemoryArray(&nodepq->bfsposs, nodepq->size) );
99   	   SCIP_ALLOC( BMSreallocMemoryArray(&nodepq->bfsqueue, nodepq->size) );
100  	
101  	   return SCIP_OKAY;
102  	}
103  	
104  	/** creates node priority queue */
105  	SCIP_RETCODE SCIPnodepqCreate(
106  	   SCIP_NODEPQ**         nodepq,             /**< pointer to a node priority queue */
107  	   SCIP_SET*             set,                /**< global SCIP settings */
108  	   SCIP_NODESEL*         nodesel             /**< node selector to use for sorting the nodes in the queue */
109  	   )
110  	{  /*lint --e{715}*/
111  	   assert(nodepq != NULL);
112  	   assert(set != NULL);
113  	
114  	   SCIP_ALLOC( BMSallocMemory(nodepq) );
115  	   (*nodepq)->nodesel = nodesel;
116  	   (*nodepq)->slots = NULL;
117  	   (*nodepq)->bfsposs = NULL;
118  	   (*nodepq)->bfsqueue = NULL;
119  	   (*nodepq)->len = 0;
120  	   (*nodepq)->size = 0;
121  	   (*nodepq)->lowerboundsum = 0.0;
122  	
123  	   return SCIP_OKAY;
124  	}
125  	
126  	/** frees node priority queue, but not the data nodes themselves */
127  	void SCIPnodepqDestroy(
128  	   SCIP_NODEPQ**         nodepq              /**< pointer to a node priority queue */
129  	   )
130  	{
131  	   assert(nodepq != NULL);
132  	   assert(*nodepq != NULL);
133  	
134  	   BMSfreeMemoryArrayNull(&(*nodepq)->slots);
135  	   BMSfreeMemoryArrayNull(&(*nodepq)->bfsposs);
136  	   BMSfreeMemoryArrayNull(&(*nodepq)->bfsqueue);
137  	   BMSfreeMemory(nodepq);
138  	}
139  	
140  	/** frees node priority queue and all nodes in the queue */
141  	SCIP_RETCODE SCIPnodepqFree(
142  	   SCIP_NODEPQ**         nodepq,             /**< pointer to a node priority queue */
143  	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
144  	   SCIP_SET*             set,                /**< global SCIP settings */
145  	   SCIP_STAT*            stat,               /**< problem statistics */
146  	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
147  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
148  	   SCIP_TREE*            tree,               /**< branch and bound tree */
149  	   SCIP_LP*              lp                  /**< current LP data */
150  	   )
151  	{
152  	   assert(nodepq != NULL);
153  	   assert(*nodepq != NULL);
154  	
155  	   /* free the nodes of the queue */
156  	   SCIP_CALL( SCIPnodepqClear(*nodepq, blkmem, set, stat, eventfilter, eventqueue, tree, lp) );
157  	
158  	   /* free the queue data structure */
159  	   SCIPnodepqDestroy(nodepq);
160  	
161  	   return SCIP_OKAY;
162  	}
163  	
164  	/** deletes all nodes in the node priority queue */
165  	SCIP_RETCODE SCIPnodepqClear(
166  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
167  	   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
168  	   SCIP_SET*             set,                /**< global SCIP settings */
169  	   SCIP_STAT*            stat,               /**< problem statistics */
170  	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
171  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
172  	   SCIP_TREE*            tree,               /**< branch and bound tree */
173  	   SCIP_LP*              lp                  /**< current LP data */
174  	   )
175  	{
176  	   int i;
177  	
178  	   assert(nodepq != NULL);
179  	
180  	   if( nodepq->len > 0 )
181  	   {
182  	      /* sort the sorts downwards after their number to increase speed when freeing in debug mode */
183  	      /* @todo: if a node is freed, the parent will also be freed, if no children are left; maybe we want to free all
184  	       *        nodes in the order of decreasing node numbers
185  	       */
186  	      SCIPsortDownPtr((void**)nodepq->slots, nodeCompNumber, nodepq->len);
187  	
188  	      /* free the nodes of the queue */
189  	      for( i = 0; i < nodepq->len; ++i )
190  	      {
191  	         assert(nodepq->slots[i] != NULL);
192  	         assert(SCIPnodeGetType(nodepq->slots[i]) == SCIP_NODETYPE_LEAF);
193  	
194  	         SCIP_CALL( SCIPnodeFree(&nodepq->slots[i], blkmem, set, stat, eventfilter, eventqueue, tree, lp) );
195  	      }
196  	   }
197  	
198  	   /* reset data */
199  	   nodepq->len = 0;
200  	   nodepq->lowerboundsum = 0.0;
201  	
202  	   return SCIP_OKAY;
203  	}
204  	
205  	/** returns the node selector associated with the given node priority queue */
206  	SCIP_NODESEL* SCIPnodepqGetNodesel(
207  	   SCIP_NODEPQ*          nodepq              /**< node priority queue */
208  	   )
209  	{
210  	   assert(nodepq != NULL);
211  	
212  	   return nodepq->nodesel;
213  	}
214  	
215  	/** sets the node selector used for sorting the nodes in the queue, and resorts the queue if necessary */
216  	SCIP_RETCODE SCIPnodepqSetNodesel(
217  	   SCIP_NODEPQ**         nodepq,             /**< pointer to a node priority queue */
218  	   SCIP_SET*             set,                /**< global SCIP settings */
219  	   SCIP_NODESEL*         nodesel             /**< node selector to use for sorting the nodes in the queue */
220  	   )
221  	{
222  	   SCIP_NODEPQ* newnodepq;
223  	   SCIP_RETCODE retcode;
224  	   int i;
225  	
226  	   assert(nodepq != NULL);
227  	   assert(*nodepq != NULL);
228  	   assert((*nodepq)->len >= 0);
229  	   assert(nodesel != NULL);
230  	   assert(nodesel->nodeselcomp != NULL);
231  	
232  	   if( (*nodepq)->nodesel == nodesel )
233  	      return SCIP_OKAY;
234  	
235  	   /* create new node priority queue */
236  	   SCIP_CALL( SCIPnodepqCreate(&newnodepq, set, nodesel) );
237  	
238  	   /* resize the new node priority queue to be able to store all nodes */
239  	   retcode = nodepqResize(newnodepq, set, (*nodepq)->len);
240  	
241  	   /* insert all nodes in the new node priority queue */
242  	   for( i = 0; i < (*nodepq)->len && retcode == SCIP_OKAY; ++i )
243  	   {
244  	      retcode = SCIPnodepqInsert(newnodepq, set, (*nodepq)->slots[i]);
245  	   }
246  	
247  	   if( retcode != SCIP_OKAY )
248  	   {
249  	      SCIPnodepqDestroy(&newnodepq);
250  	
251  	      return retcode;
252  	   }
253  	
254  	   /* destroy the old node priority queue without freeing the nodes */
255  	   SCIPnodepqDestroy(nodepq);
256  	
257  	   /* use the new node priority queue */
258  	   *nodepq = newnodepq;
259  	
260  	   return SCIP_OKAY;
261  	}
262  	
263  	/** compares two nodes; returns -1/0/+1 if node1 better/equal/worse than node2 */
264  	int SCIPnodepqCompare(
265  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
266  	   SCIP_SET*             set,                /**< global SCIP settings */
267  	   SCIP_NODE*            node1,              /**< first node to compare */
268  	   SCIP_NODE*            node2               /**< second node to compare */
269  	   )
270  	{
271  	   assert(nodepq != NULL);
272  	   assert(nodepq->nodesel != NULL);
273  	   assert(nodepq->nodesel->nodeselcomp != NULL);
274  	   assert(set != NULL);
275  	
276  	   return SCIPnodeselCompare(nodepq->nodesel, set, node1, node2);
277  	}
278  	
279  	/** inserts node into node priority queue */
280  	SCIP_RETCODE SCIPnodepqInsert(
281  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
282  	   SCIP_SET*             set,                /**< global SCIP settings */
283  	   SCIP_NODE*            node                /**< node to be inserted */
284  	   )
285  	{
286  	   SCIP_NODESEL* nodesel;
287  	   SCIP_NODE** slots;
288  	   int* bfsposs;
289  	   int* bfsqueue;
290  	   SCIP_Real lowerbound;
291  	   int pos;
292  	   int bfspos;
293  	
294  	   assert(nodepq != NULL);
295  	   assert(nodepq->len >= 0);
296  	   assert(set != NULL);
297  	   assert(node != NULL);
298  	
299  	   nodesel = nodepq->nodesel;
300  	   assert(nodesel != NULL);
301  	   assert(nodesel->nodeselcomp != NULL);
302  	
303  	   SCIP_CALL( nodepqResize(nodepq, set, nodepq->len+1) );
304  	   slots = nodepq->slots;
305  	   bfsposs = nodepq->bfsposs;
306  	   bfsqueue = nodepq->bfsqueue;
307  	
308  	   /* insert node as leaf in the tree, move it towards the root as long it is better than its parent */
309  	   nodepq->len++;
310  	   nodepq->lowerboundsum += SCIPnodeGetLowerbound(node);
311  	   pos = nodepq->len-1;
312  	   while( pos > 0 && nodesel->nodeselcomp(set->scip, nodesel, node, slots[PQ_PARENT(pos)]) < 0 )
313  	   {
314  	      slots[pos] = slots[PQ_PARENT(pos)];
315  	      bfsposs[pos] = bfsposs[PQ_PARENT(pos)];
316  	      bfsqueue[bfsposs[pos]] = pos;
317  	      pos = PQ_PARENT(pos);
318  	   }
319  	   slots[pos] = node;
320  	
321  	   /* insert the final position into the bfs index queue */
322  	   lowerbound = SCIPnodeGetLowerbound(node);
323  	   bfspos = nodepq->len-1;
324  	   while( bfspos > 0 && lowerbound < SCIPnodeGetLowerbound(slots[bfsqueue[PQ_PARENT(bfspos)]]) )
325  	   {
326  	      bfsqueue[bfspos] = bfsqueue[PQ_PARENT(bfspos)];
327  	      bfsposs[bfsqueue[bfspos]] = bfspos;
328  	      bfspos = PQ_PARENT(bfspos);
329  	   }
330  	   bfsqueue[bfspos] = pos;
331  	   bfsposs[pos] = bfspos;
332  	
333  	   SCIPsetDebugMsg(set, "inserted node %p[%g] at pos %d and bfspos %d of node queue\n", (void*)node, lowerbound, pos, bfspos);
334  	
335  	   return SCIP_OKAY;
336  	}
337  	
338  	/** deletes node at given position from the node priority queue; returns TRUE, if the parent fell down to the
339  	 *  free position
340  	 */
341  	static
342  	SCIP_Bool nodepqDelPos(
343  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
344  	   SCIP_SET*             set,                /**< global SCIP settings */
345  	   int                   rempos              /**< queue position of node to remove */
346  	   )
347  	{
348  	   SCIP_NODESEL* nodesel;
349  	   SCIP_NODE** slots;
350  	   int* bfsposs;
351  	   int* bfsqueue;
352  	   SCIP_NODE* lastnode;
353  	   int lastbfspos;
354  	   int lastbfsqueueidx;
355  	   int freepos;
356  	   int freebfspos;
357  	   SCIP_Bool parentfelldown;
358  	   SCIP_Bool bfsparentfelldown;
359  	
360  	   assert(nodepq != NULL);
361  	   assert(nodepq->len > 0);
362  	   assert(set != NULL);
363  	   assert(0 <= rempos && rempos < nodepq->len);
364  	
365  	   nodesel = nodepq->nodesel;
366  	   assert(nodesel != NULL);
367  	   assert(nodesel->nodeselcomp != NULL);
368  	
369  	   slots = nodepq->slots;
370  	   bfsposs = nodepq->bfsposs;
371  	   bfsqueue = nodepq->bfsqueue;
372  	
373  	   nodepq->lowerboundsum -= SCIPnodeGetLowerbound(slots[rempos]);
374  	   freepos = rempos;
375  	   freebfspos = bfsposs[rempos];
376  	   assert(0 <= freebfspos && freebfspos < nodepq->len);
377  	
378  	   SCIPsetDebugMsg(set, "delete node %p[%g] at pos %d and bfspos %d of node queue\n",
379  	      (void*)slots[freepos], SCIPnodeGetLowerbound(slots[freepos]), freepos, freebfspos);
380  	
381  	   /* remove node of the tree and get a free slot,
382  	    * if the removed node was the last node of the queue
383  	    *  - do nothing
384  	    * if the last node of the queue is better than the parent of the removed node:
385  	    *  - move the parent to the free slot, until the last node can be placed in the free slot
386  	    * if the last node of the queue is not better than the parent of the free slot:
387  	    *  - move the better child to the free slot until the last node can be placed in the free slot
388  	    */
389  	   nodepq->len--;
390  	
391  	   /* process the slots queue ordered by the node selection comparator */
392  	   lastnode = slots[nodepq->len];
393  	   lastbfspos = bfsposs[nodepq->len];
394  	   parentfelldown = FALSE;
395  	   if( freepos < nodepq->len )
396  	   {
397  	      int parentpos;
398  	
399  	      /* try to move parents downwards to insert last node */
400  	      parentpos = PQ_PARENT(freepos);
401  	      while( freepos > 0 && nodesel->nodeselcomp(set->scip, nodesel, lastnode, slots[parentpos]) < 0 )
402  	      {
403  	         slots[freepos] = slots[parentpos];
404  	         bfsposs[freepos] = bfsposs[parentpos];
405  	         bfsqueue[bfsposs[freepos]] = freepos;
406  	         freepos = parentpos;
407  	         parentpos = PQ_PARENT(freepos);
408  	         parentfelldown = TRUE;
409  	      }
410  	      if( !parentfelldown )
411  	      {
412  	         /* downward moving of parents was not successful -> move children upwards */
413  	         while( freepos <= PQ_PARENT(nodepq->len-1) ) /* as long as free slot has children... */
414  	         {
415  	            int childpos;
416  	            int brotherpos;
417  	
418  	            /* select the better child of free slot */
419  	            childpos = PQ_LEFTCHILD(freepos);
420  	            assert(childpos < nodepq->len);
421  	            brotherpos = PQ_RIGHTCHILD(freepos);
422  	            if( brotherpos < nodepq->len
423  	               && nodesel->nodeselcomp(set->scip, nodesel, slots[brotherpos], slots[childpos]) < 0 )
424  	               childpos = brotherpos;
425  	
426  	            /* exit search loop if better child is not better than last node */
427  	            if( nodesel->nodeselcomp(set->scip, nodesel, lastnode, slots[childpos]) <= 0 )
428  	               break;
429  	
430  	            /* move better child upwards, free slot is now the better child's slot */
431  	            slots[freepos] = slots[childpos];
432  	            bfsposs[freepos] = bfsposs[childpos];
433  	            bfsqueue[bfsposs[freepos]] = freepos;
434  	            freepos = childpos;
435  	         }
436  	      }
437  	      assert(0 <= freepos && freepos < nodepq->len);
438  	      assert(!parentfelldown || PQ_LEFTCHILD(freepos) < nodepq->len);
439  	      slots[freepos] = lastnode;
440  	      bfsposs[freepos] = lastbfspos;
441  	      bfsqueue[lastbfspos] = freepos;
442  	   }
443  	
444  	   /* process the bfs queue ordered by the lower bound */
445  	   lastbfsqueueidx = bfsqueue[nodepq->len];
446  	   bfsparentfelldown = FALSE;
447  	   if( freebfspos < nodepq->len )
448  	   {
449  	      SCIP_Real lastlowerbound;
450  	      int parentpos;
451  	
452  	      /* try to move parents downwards to insert last queue index */
453  	      lastlowerbound = SCIPnodeGetLowerbound(slots[lastbfsqueueidx]);
454  	      parentpos = PQ_PARENT(freebfspos);
455  	      while( freebfspos > 0 && lastlowerbound < SCIPnodeGetLowerbound(slots[bfsqueue[parentpos]]) )
456  	      {
457  	         bfsqueue[freebfspos] = bfsqueue[parentpos];
458  	         bfsposs[bfsqueue[freebfspos]] = freebfspos;
459  	         freebfspos = parentpos;
460  	         parentpos = PQ_PARENT(freebfspos);
461  	         bfsparentfelldown = TRUE;
462  	      }
463  	      if( !bfsparentfelldown )
464  	      {
465  	         /* downward moving of parents was not successful -> move children upwards */
466  	         while( freebfspos <= PQ_PARENT(nodepq->len-1) ) /* as long as free slot has children... */
467  	         {
468  	            int childpos;
469  	            int brotherpos;
470  	
471  	            /* select the better child of free slot */
472  	            childpos = PQ_LEFTCHILD(freebfspos);
473  	            assert(childpos < nodepq->len);
474  	            brotherpos = PQ_RIGHTCHILD(freebfspos);
475  	            if( brotherpos < nodepq->len
476  	               && SCIPnodeGetLowerbound(slots[bfsqueue[brotherpos]]) < SCIPnodeGetLowerbound(slots[bfsqueue[childpos]]) )
477  	               childpos = brotherpos;
478  	
479  	            /* exit search loop if better child is not better than last node */
480  	            if( lastlowerbound <= SCIPnodeGetLowerbound(slots[bfsqueue[childpos]]) )
481  	               break;
482  	
483  	            /* move better child upwards, free slot is now the better child's slot */
484  	            bfsqueue[freebfspos] = bfsqueue[childpos];
485  	            bfsposs[bfsqueue[freebfspos]] = freebfspos;
486  	            freebfspos = childpos;
487  	         }
488  	      }
489  	      assert(0 <= freebfspos && freebfspos < nodepq->len);
490  	      assert(!bfsparentfelldown || PQ_LEFTCHILD(freebfspos) < nodepq->len);
491  	      bfsqueue[freebfspos] = lastbfsqueueidx;
492  	      bfsposs[lastbfsqueueidx] = freebfspos;
493  	   }
494  	
495  	   return parentfelldown;
496  	}
497  	
498  	/** returns the position of given node in the priority queue, or -1 if not existing */
499  	static
500  	int nodepqFindNode(
501  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
502  	   SCIP_SET*             set,                /**< global SCIP settings */
503  	   SCIP_NODE*            node                /**< node to find */
504  	   )
505  	{
506  	   int pos;
507  	
508  	   assert(nodepq != NULL);
509  	   assert(nodepq->len >= 0);
510  	   assert(set != NULL);
511  	   assert(node != NULL);
512  	
513  	   /* search the node in the queue */
514  	   for( pos = 0; pos < nodepq->len && node != nodepq->slots[pos]; ++pos )
515  	   {}
516  	
517  	   if( pos == nodepq->len )
518  	      pos = -1;
519  	
520  	   return pos;
521  	}
522  	
523  	/** removes node from the node priority queue */
524  	SCIP_RETCODE SCIPnodepqRemove(
525  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
526  	   SCIP_SET*             set,                /**< global SCIP settings */
527  	   SCIP_NODE*            node                /**< node to remove */
528  	   )
529  	{
530  	   int pos;
531  	
532  	   pos = nodepqFindNode(nodepq, set, node);
533  	   if( pos == -1 )
534  	   {
535  	      SCIPerrorMessage("node doesn't exist in node priority queue\n");
536  	      return SCIP_INVALIDDATA;
537  	   }
538  	
539  	   (void)nodepqDelPos(nodepq, set, pos);
540  	
541  	   return SCIP_OKAY;
542  	}
543  	
544  	/** returns the best node of the queue without removing it */
545  	SCIP_NODE* SCIPnodepqFirst(
546  	   const SCIP_NODEPQ*    nodepq              /**< node priority queue */
547  	   )
548  	{
549  	   assert(nodepq != NULL);
550  	   assert(nodepq->len >= 0);
551  	
552  	   if( nodepq->len == 0 )
553  	      return NULL;
554  	
555  	   assert(nodepq->slots[0] != NULL);
556  	
557  	   return nodepq->slots[0];
558  	}
559  	
560  	/** returns the nodes array of the queue */
561  	SCIP_NODE** SCIPnodepqNodes(
562  	   const SCIP_NODEPQ*    nodepq              /**< node priority queue */
563  	   )
564  	{
565  	   assert(nodepq != NULL);
566  	
567  	   return nodepq->slots;
568  	}
569  	
570  	/** returns the number of nodes stored in the node priority queue */
571  	int SCIPnodepqLen(
572  	   const SCIP_NODEPQ*    nodepq              /**< node priority queue */
573  	   )
574  	{
575  	   assert(nodepq != NULL);
576  	   assert(nodepq->len >= 0);
577  	
578  	   return nodepq->len;
579  	}
580  	
581  	/** gets the minimal lower bound of all nodes in the queue */
582  	SCIP_Real SCIPnodepqGetLowerbound(
583  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
584  	   SCIP_SET*             set                 /**< global SCIP settings */
585  	   )
586  	{
587  	   assert(nodepq != NULL);
588  	   assert(nodepq->nodesel != NULL);
589  	   assert(set != NULL);
590  	
591  	   if( nodepq->len > 0 )
592  	   {
593  	      int bfspos;
594  	
595  	      bfspos = nodepq->bfsqueue[0];
596  	      assert(0 <= bfspos && bfspos < nodepq->len);
597  	      assert(nodepq->slots[bfspos] != NULL);
598  	      return SCIPnodeGetLowerbound(nodepq->slots[bfspos]);
599  	   }
600  	   else
601  	      return SCIPsetInfinity(set);
602  	}
603  	
604  	/** gets the node with minimal lower bound of all nodes in the queue */
605  	SCIP_NODE* SCIPnodepqGetLowerboundNode(
606  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
607  	   SCIP_SET*             set                 /**< global SCIP settings */
608  	   )
609  	{
610  	   assert(nodepq != NULL);
611  	   assert(nodepq->nodesel != NULL);
612  	   assert(set != NULL);
613  	
614  	   /* the node selector's compare method sorts the minimal lower bound to the front */
615  	   if( nodepq->len > 0 )
616  	   {
617  	      int bfspos;
618  	
619  	      bfspos = nodepq->bfsqueue[0];
620  	      assert(0 <= bfspos && bfspos < nodepq->len);
621  	      assert(nodepq->slots[bfspos] != NULL);
622  	      return nodepq->slots[bfspos];
623  	   }
624  	   else
625  	      return NULL;
626  	}
627  	
628  	/** gets the sum of lower bounds of all nodes in the queue */
629  	SCIP_Real SCIPnodepqGetLowerboundSum(
630  	   SCIP_NODEPQ*          nodepq              /**< node priority queue */
631  	   )
632  	{
633  	   assert(nodepq != NULL);
634  	
635  	   return nodepq->lowerboundsum;
636  	}
637  	
638  	/** free all nodes from the queue that are cut off by the given upper bound */
639  	SCIP_RETCODE SCIPnodepqBound(
640  	   SCIP_NODEPQ*          nodepq,             /**< node priority queue */
641  	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
642  	   SCIP_SET*             set,                /**< global SCIP settings */
643  	   SCIP_STAT*            stat,               /**< dynamic problem statistics */
644  	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global (not variable dependent) events */
645  	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
646  	   SCIP_TREE*            tree,               /**< branch and bound tree */
647  	   SCIP_REOPT*           reopt,              /**< reoptimization data structure */
648  	   SCIP_LP*              lp,                 /**< current LP data */
649  	   SCIP_Real             cutoffbound         /**< cutoff bound: all nodes with lowerbound >= cutoffbound are cut off */
650  	   )
651  	{
652  	   SCIP_NODE* node;
653  	   int pos;
654  	   SCIP_Bool parentfelldown;
655  	
656  	   assert(nodepq != NULL);
657  	
658  	   SCIPsetDebugMsg(set, "bounding node queue of length %d with cutoffbound=%g\n", nodepq->len, cutoffbound);
659  	   pos = nodepq->len-1;
660  	   while( pos >= 0 )
661  	   {
662  	      assert(pos < nodepq->len);
663  	      node = nodepq->slots[pos];
664  	      assert(node != NULL);
665  	      assert(SCIPnodeGetType(node) == SCIP_NODETYPE_LEAF);
666  	      if( SCIPsetIsInfinity(set, SCIPnodeGetLowerbound(node)) || SCIPsetIsGE(set, SCIPnodeGetLowerbound(node), cutoffbound) )
667  	      {
668  	         SCIPsetDebugMsg(set, "free node in slot %d (len=%d) at depth %d with lowerbound=%g\n",
669  	            pos, nodepq->len, SCIPnodeGetDepth(node), SCIPnodeGetLowerbound(node));
670  	
671  	         /* cut off node; because we looped from back to front, the existing children of the node must have a smaller
672  	          * lower bound than the cut off value
673  	          */
674  	         assert(PQ_LEFTCHILD(pos) >= nodepq->len
675  	            || SCIPsetIsLT(set, SCIPnodeGetLowerbound(nodepq->slots[PQ_LEFTCHILD(pos)]), cutoffbound));
676  	         assert(PQ_RIGHTCHILD(pos) >= nodepq->len
677  	            || SCIPsetIsLT(set, SCIPnodeGetLowerbound(nodepq->slots[PQ_RIGHTCHILD(pos)]), cutoffbound));
678  	
679  	         /* free the slot in the node PQ */
680  	         parentfelldown = nodepqDelPos(nodepq, set, pos);
681  	
682  	         /* - if the slot was occupied by the parent, we have to check this slot (the parent) again; unfortunately,
683  	          *   we will check the node which occupied the parent's slot again, even though it cannot be cut off;
684  	          * - otherwise, the slot was the last slot or it was occupied by a node with a position greater than
685  	          *   the current position; this node was already checked and we can decrease the position
686  	          */
687  	         if( !parentfelldown )
688  	            pos--;
689  	
690  	         SCIPvisualCutoffNode(stat->visual, set, stat, node, FALSE);
691  	
692  	         if( set->reopt_enable )
693  	         {
694  	            assert(reopt != NULL);
695  	            SCIP_CALL( SCIPreoptCheckCutoff(reopt, set, blkmem, node, SCIP_EVENTTYPE_NODEINFEASIBLE, lp,
696  	                  SCIPlpGetSolstat(lp), SCIPnodeGetDepth(node) == 0, SCIPtreeGetFocusNode(tree) == node,
697  	                  SCIPnodeGetLowerbound(node), SCIPtreeGetEffectiveRootDepth(tree)));
698  	         }
699  	
700  	         /* free memory of the node */
701  	         SCIP_CALL( SCIPnodeFree(&node, blkmem, set, stat, eventfilter, eventqueue, tree, lp) );
702  	      }
703  	      else
704  	         pos--;
705  	   }
706  	   SCIPsetDebugMsg(set, " -> bounded node queue has length %d\n", nodepq->len);
707  	
708  	   return SCIP_OKAY;
709  	}
710  	
711  	
712  	
713  	
714  	/*
715  	 * node selector methods 
716  	 */
717  	
718  	/** method to call, when the standard mode priority of a node selector was changed */
719  	static
720  	SCIP_DECL_PARAMCHGD(paramChgdNodeselStdPriority)
721  	{  /*lint --e{715}*/
722  	   SCIP_PARAMDATA* paramdata;
723  	
724  	   paramdata = SCIPparamGetData(param);
725  	   assert(paramdata != NULL);
726  	
727  	   /* use SCIPsetNodeselStdPriority() to mark the nodesels unsorted */
728  	   SCIP_CALL( SCIPsetNodeselStdPriority(scip, (SCIP_NODESEL*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
729  	
730  	   return SCIP_OKAY;
731  	}
732  	
733  	/** method to call, when the memory saving mode priority of a node selector was changed */
734  	static
735  	SCIP_DECL_PARAMCHGD(paramChgdNodeselMemsavePriority)
736  	{  /*lint --e{715}*/
737  	   SCIP_PARAMDATA* paramdata;
738  	
739  	   paramdata = SCIPparamGetData(param);
740  	   assert(paramdata != NULL);
741  	
742  	   /* use SCIPsetNodeselMemsavePriority() to mark the nodesels unsorted */
743  	   SCIP_CALL( SCIPsetNodeselMemsavePriority(scip, (SCIP_NODESEL*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
744  	
745  	   return SCIP_OKAY;
746  	}
747  	
748  	/** copies the given node selector to a new scip */
749  	SCIP_RETCODE SCIPnodeselCopyInclude(
750  	   SCIP_NODESEL*         nodesel,            /**< node selector */
751  	   SCIP_SET*             set                 /**< SCIP_SET of SCIP to copy to */
752  	   )
753  	{
754  	   assert(nodesel != NULL);
755  	   assert(set != NULL);
756  	   assert(set->scip != NULL);
757  	
758  	   if( nodesel->nodeselcopy != NULL )
759  	   {
760  	      SCIPsetDebugMsg(set, "including node selector %s in subscip %p\n", SCIPnodeselGetName(nodesel), (void*)set->scip);
761  	      SCIP_CALL( nodesel->nodeselcopy(set->scip, nodesel) );
762  	   }
763  	   return SCIP_OKAY;
764  	}
765  	
766  	/** internal method for creating a node selector */
767  	static
768  	SCIP_RETCODE doNodeselCreate(
769  	   SCIP_NODESEL**        nodesel,            /**< pointer to store node selector */
770  	   SCIP_SET*             set,                /**< global SCIP settings */
771  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
772  	   BMS_BLKMEM*           blkmem,             /**< block memory for parameter settings */
773  	   const char*           name,               /**< name of node selector */
774  	   const char*           desc,               /**< description of node selector */
775  	   int                   stdpriority,        /**< priority of the node selector in standard mode */
776  	   int                   memsavepriority,    /**< priority of the node selector in memory saving mode */
777  	   SCIP_DECL_NODESELCOPY ((*nodeselcopy)),   /**< copy method of node selector or NULL if you don't want to copy your plugin into sub-SCIPs */
778  	   SCIP_DECL_NODESELFREE ((*nodeselfree)),   /**< destructor of node selector */
779  	   SCIP_DECL_NODESELINIT ((*nodeselinit)),   /**< initialize node selector */
780  	   SCIP_DECL_NODESELEXIT ((*nodeselexit)),   /**< deinitialize node selector */
781  	   SCIP_DECL_NODESELINITSOL((*nodeselinitsol)),/**< solving process initialization method of node selector */
782  	   SCIP_DECL_NODESELEXITSOL((*nodeselexitsol)),/**< solving process deinitialization method of node selector */
783  	   SCIP_DECL_NODESELSELECT((*nodeselselect)),/**< node selection method */
784  	   SCIP_DECL_NODESELCOMP ((*nodeselcomp)),   /**< node comparison method */
785  	   SCIP_NODESELDATA*     nodeseldata         /**< node selector data */
786  	   )
787  	{
788  	   char paramname[SCIP_MAXSTRLEN];
789  	   char paramdesc[SCIP_MAXSTRLEN];
790  	
791  	   assert(nodesel != NULL);
792  	   assert(name != NULL);
793  	   assert(desc != NULL);
794  	   assert(nodeselselect != NULL);
795  	   assert(nodeselcomp != NULL);
796  	
797  	   SCIP_ALLOC( BMSallocMemory(nodesel) );
798  	   BMSclearMemory(*nodesel);
799  	
800  	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*nodesel)->name, name, strlen(name)+1) );
801  	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*nodesel)->desc, desc, strlen(desc)+1) );
802  	   (*nodesel)->stdpriority = stdpriority;
803  	   (*nodesel)->memsavepriority = memsavepriority;
804  	   (*nodesel)->nodeselcopy = nodeselcopy;
805  	   (*nodesel)->nodeselfree = nodeselfree;
806  	   (*nodesel)->nodeselinit = nodeselinit;
807  	   (*nodesel)->nodeselexit = nodeselexit;
808  	   (*nodesel)->nodeselinitsol = nodeselinitsol;
809  	   (*nodesel)->nodeselexitsol = nodeselexitsol;
810  	   (*nodesel)->nodeselselect = nodeselselect;
811  	   (*nodesel)->nodeselcomp = nodeselcomp;
812  	   (*nodesel)->nodeseldata = nodeseldata;
813  	   (*nodesel)->initialized = FALSE;
814  	   /* create clocks */
815  	   SCIP_CALL( SCIPclockCreate(&(*nodesel)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
816  	   SCIP_CALL( SCIPclockCreate(&(*nodesel)->nodeseltime, SCIP_CLOCKTYPE_DEFAULT) );
817  	
818  	   /* add parameters */
819  	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "nodeselection/%s/stdpriority", name);
820  	   (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of node selection rule <%s> in standard mode", name);
821  	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
822  	                  &(*nodesel)->stdpriority, FALSE, stdpriority, INT_MIN/4, INT_MAX/2,
823  	                  paramChgdNodeselStdPriority, (SCIP_PARAMDATA*)(*nodesel)) ); /*lint !e740*/
824  	
825  	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "nodeselection/%s/memsavepriority", name);
826  	   (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of node selection rule <%s> in memory saving mode", name);
827  	   SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
828  	                  &(*nodesel)->memsavepriority, TRUE, memsavepriority, INT_MIN/4, INT_MAX/4,
829  	                  paramChgdNodeselMemsavePriority, (SCIP_PARAMDATA*)(*nodesel)) ); /*lint !e740*/
830  	
831  	   return SCIP_OKAY;
832  	}
833  	
834  	/** creates a node selector */
835  	SCIP_RETCODE SCIPnodeselCreate(
836  	   SCIP_NODESEL**        nodesel,            /**< pointer to store node selector */
837  	   SCIP_SET*             set,                /**< global SCIP settings */
838  	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
839  	   BMS_BLKMEM*           blkmem,             /**< block memory for parameter settings */
840  	   const char*           name,               /**< name of node selector */
841  	   const char*           desc,               /**< description of node selector */
842  	   int                   stdpriority,        /**< priority of the node selector in standard mode */
843  	   int                   memsavepriority,    /**< priority of the node selector in memory saving mode */
844  	   SCIP_DECL_NODESELCOPY ((*nodeselcopy)),   /**< copy method of node selector or NULL if you don't want to copy your plugin into sub-SCIPs */
845  	   SCIP_DECL_NODESELFREE ((*nodeselfree)),   /**< destructor of node selector */
846  	   SCIP_DECL_NODESELINIT ((*nodeselinit)),   /**< initialize node selector */
847  	   SCIP_DECL_NODESELEXIT ((*nodeselexit)),   /**< deinitialize node selector */
848  	   SCIP_DECL_NODESELINITSOL((*nodeselinitsol)),/**< solving process initialization method of node selector */
849  	   SCIP_DECL_NODESELEXITSOL((*nodeselexitsol)),/**< solving process deinitialization method of node selector */
850  	   SCIP_DECL_NODESELSELECT((*nodeselselect)),/**< node selection method */
851  	   SCIP_DECL_NODESELCOMP ((*nodeselcomp)),   /**< node comparison method */
852  	   SCIP_NODESELDATA*     nodeseldata         /**< node selector data */
853  	   )
854  	{
855  	   assert(nodesel != NULL);
856  	   assert(name != NULL);
857  	   assert(desc != NULL);
858  	   assert(nodeselselect != NULL);
859  	   assert(nodeselcomp != NULL);
860  	
861  	   SCIP_CALL_FINALLY( doNodeselCreate(nodesel, set, messagehdlr, blkmem, name, desc, stdpriority, memsavepriority,
862  	      nodeselcopy, nodeselfree, nodeselinit, nodeselexit, nodeselinitsol, nodeselexitsol, nodeselselect, nodeselcomp,
863  	      nodeseldata), (void) SCIPnodeselFree(nodesel, set) );
864  	
865  	   return SCIP_OKAY;
866  	}
867  	
868  	/** frees memory of node selector */
869  	SCIP_RETCODE SCIPnodeselFree(
870  	   SCIP_NODESEL**        nodesel,            /**< pointer to node selector data structure */
871  	   SCIP_SET*             set                 /**< global SCIP settings */
872  	   )
873  	{
874  	   assert(nodesel != NULL);
875  	   if( *nodesel == NULL )
876  	      return SCIP_OKAY;
877  	   assert(!(*nodesel)->initialized);
878  	   assert(set != NULL);
879  	
880  	   /* call destructor of node selector */
881  	   if( (*nodesel)->nodeselfree != NULL )
882  	   {
883  	      SCIP_CALL( (*nodesel)->nodeselfree(set->scip, *nodesel) );
884  	   }
885  	
886  	   /* free clocks */
887  	   SCIPclockFree(&(*nodesel)->nodeseltime);
888  	   SCIPclockFree(&(*nodesel)->setuptime);
889  	
890  	   BMSfreeMemoryArrayNull(&(*nodesel)->name);
891  	   BMSfreeMemoryArrayNull(&(*nodesel)->desc);
892  	   BMSfreeMemory(nodesel);
893  	
894  	   return SCIP_OKAY;
895  	}
896  	
897  	/** initializes node selector */
898  	SCIP_RETCODE SCIPnodeselInit(
899  	   SCIP_NODESEL*         nodesel,            /**< node selector */
900  	   SCIP_SET*             set                 /**< global SCIP settings */
901  	   )
902  	{
903  	   assert(nodesel != NULL);
904  	   assert(set != NULL);
905  	
906  	   if( nodesel->initialized )
907  	   {
908  	      SCIPerrorMessage("node selector <%s> already initialized", nodesel->name);
909  	      return SCIP_INVALIDCALL;
910  	   }
911  	
912  	   if( set->misc_resetstat )
913  	   {
914  	      SCIPclockReset(nodesel->setuptime);
915  	      SCIPclockReset(nodesel->nodeseltime);
916  	   }
917  	
918  	   if( nodesel->nodeselinit != NULL )
919  	   {
920  	      /* start timing */
921  	      SCIPclockStart(nodesel->setuptime, set);
922  	
923  	      SCIP_CALL( nodesel->nodeselinit(set->scip, nodesel) );
924  	
925  	      /* stop timing */
926  	      SCIPclockStop(nodesel->setuptime, set);
927  	   }
928  	   nodesel->initialized = TRUE;
929  	
930  	   return SCIP_OKAY;
931  	}
932  	
933  	/** deinitializes node selector */
934  	SCIP_RETCODE SCIPnodeselExit(
935  	   SCIP_NODESEL*         nodesel,            /**< node selector */
936  	   SCIP_SET*             set                 /**< global SCIP settings */
937  	   )
938  	{
939  	   assert(nodesel != NULL);
940  	   assert(set != NULL);
941  	
942  	   if( !nodesel->initialized )
943  	   {
944  	      SCIPerrorMessage("node selector <%s> not initialized", nodesel->name);
945  	      return SCIP_INVALIDCALL;
946  	   }
947  	
948  	   if( nodesel->nodeselexit != NULL )
949  	   {
950  	      /* start timing */
951  	      SCIPclockStart(nodesel->setuptime, set);
952  	
953  	      SCIP_CALL( nodesel->nodeselexit(set->scip, nodesel) );
954  	
955  	      /* stop timing */
956  	      SCIPclockStop(nodesel->setuptime, set);
957  	   }
958  	   nodesel->initialized = FALSE;
959  	
960  	   return SCIP_OKAY;
961  	}
962  	
963  	/** informs node selector that the branch and bound process is being started */
964  	SCIP_RETCODE SCIPnodeselInitsol(
965  	   SCIP_NODESEL*         nodesel,            /**< node selector */
966  	   SCIP_SET*             set                 /**< global SCIP settings */
967  	   )
968  	{
969  	   assert(nodesel != NULL);
970  	   assert(set != NULL);
971  	
972  	   /* call solving process initialization method of node selector */
973  	   if( nodesel->nodeselinitsol != NULL )
974  	   {
975  	      /* start timing */
976  	      SCIPclockStart(nodesel->setuptime, set);
977  	
978  	      SCIP_CALL( nodesel->nodeselinitsol(set->scip, nodesel) );
979  	
980  	      /* stop timing */
981  	      SCIPclockStop(nodesel->setuptime, set);
982  	   }
983  	
984  	   return SCIP_OKAY;
985  	}
986  	
987  	/** informs node selector that the branch and bound process data is being freed */
988  	SCIP_RETCODE SCIPnodeselExitsol(
989  	   SCIP_NODESEL*         nodesel,            /**< node selector */
990  	   SCIP_SET*             set                 /**< global SCIP settings */
991  	   )
992  	{
993  	   assert(nodesel != NULL);
994  	   assert(set != NULL);
995  	
996  	   /* call solving process deinitialization method of node selector */
997  	   if( nodesel->nodeselexitsol != NULL )
998  	   {
999  	      /* start timing */
1000 	      SCIPclockStart(nodesel->setuptime, set);
1001 	
1002 	      SCIP_CALL( nodesel->nodeselexitsol(set->scip, nodesel) );
1003 	
1004 	      /* stop timing */
1005 	      SCIPclockStop(nodesel->setuptime, set);
1006 	   }
1007 	
1008 	   return SCIP_OKAY;
1009 	}
1010 	
1011 	/** select next node to be processed */
1012 	SCIP_RETCODE SCIPnodeselSelect(
1013 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1014 	   SCIP_SET*             set,                /**< global SCIP settings */
1015 	   SCIP_NODE**           selnode             /**< pointer to store node to be processed next */
1016 	   )
1017 	{
1018 	   assert(nodesel != NULL);
1019 	   assert(nodesel->nodeselselect != NULL);
1020 	   assert(set != NULL);
1021 	   assert(selnode != NULL);
1022 	
1023 	   /* start timing */
1024 	   SCIPclockStart(nodesel->nodeseltime, set);
1025 	
1026 	   SCIP_CALL( nodesel->nodeselselect(set->scip, nodesel, selnode) );
1027 	
1028 	   /* stop timing */
1029 	   SCIPclockStop(nodesel->nodeseltime, set);
1030 	
1031 	   return SCIP_OKAY;
1032 	}
1033 	
1034 	/** compares two nodes; returns -1/0/+1 if node1 better/equal/worse than node2 */
1035 	int SCIPnodeselCompare(
1036 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1037 	   SCIP_SET*             set,                /**< global SCIP settings */
1038 	   SCIP_NODE*            node1,              /**< first node to compare */
1039 	   SCIP_NODE*            node2               /**< second node to compare */
1040 	   )
1041 	{
1042 	   assert(nodesel != NULL);
1043 	   assert(nodesel->nodeselcomp != NULL);
1044 	   assert(set != NULL);
1045 	   assert(node1 != NULL);
1046 	   assert(node2 != NULL);
1047 	
1048 	   return nodesel->nodeselcomp(set->scip, nodesel, node1, node2);
1049 	}
1050 	
1051 	/** gets name of node selector */
1052 	const char* SCIPnodeselGetName(
1053 	   SCIP_NODESEL*         nodesel             /**< node selector */
1054 	   )
1055 	{
1056 	   assert(nodesel != NULL);
1057 	
1058 	   return nodesel->name;
1059 	}
1060 	
1061 	/** gets description of node selector */
1062 	const char* SCIPnodeselGetDesc(
1063 	   SCIP_NODESEL*         nodesel             /**< node selector */
1064 	   )
1065 	{
1066 	   assert(nodesel != NULL);
1067 	
1068 	   return nodesel->desc;
1069 	}
1070 	
1071 	/** gets priority of node selector in standard mode */
1072 	int SCIPnodeselGetStdPriority(
1073 	   SCIP_NODESEL*         nodesel             /**< node selector */
1074 	   )
1075 	{
1076 	   assert(nodesel != NULL);
1077 	
1078 	   return nodesel->stdpriority;
1079 	}
1080 	
1081 	/** gets priority of node selector in standard mode */
1082 	void SCIPnodeselSetStdPriority(
1083 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1084 	   SCIP_SET*             set,                /**< global SCIP settings */
1085 	   int                   priority            /**< new priority of the node selector */
1086 	   )
1087 	{
1088 	   assert(nodesel != NULL);
1089 	   assert(set != NULL);
1090 	
1091 	   nodesel->stdpriority = priority;
1092 	   set->nodesel = NULL;
1093 	}
1094 	
1095 	/** gets priority of node selector in memory saving mode */
1096 	int SCIPnodeselGetMemsavePriority(
1097 	   SCIP_NODESEL*         nodesel             /**< node selector */
1098 	   )
1099 	{
1100 	   assert(nodesel != NULL);
1101 	
1102 	   return nodesel->memsavepriority;
1103 	}
1104 	
1105 	/** sets priority of node selector in memory saving mode */
1106 	void SCIPnodeselSetMemsavePriority(
1107 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1108 	   SCIP_SET*             set,                /**< global SCIP settings */
1109 	   int                   priority            /**< new priority of the node selector */
1110 	   )
1111 	{
1112 	   assert(nodesel != NULL);
1113 	   assert(set != NULL);
1114 	
1115 	   nodesel->memsavepriority = priority;
1116 	   set->nodesel = NULL;
1117 	}
1118 	
1119 	/** gets user data of node selector */
1120 	SCIP_NODESELDATA* SCIPnodeselGetData(
1121 	   SCIP_NODESEL*         nodesel             /**< node selector */
1122 	   )
1123 	{
1124 	   assert(nodesel != NULL);
1125 	
1126 	   return nodesel->nodeseldata;
1127 	}
1128 	
1129 	/** sets user data of node selector; user has to free old data in advance! */
1130 	void SCIPnodeselSetData(
1131 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1132 	   SCIP_NODESELDATA*     nodeseldata         /**< new node selector user data */
1133 	   )
1134 	{
1135 	   assert(nodesel != NULL);
1136 	
1137 	   nodesel->nodeseldata = nodeseldata;
1138 	}
1139 	
1140 	/* new callback/method setter methods */
1141 	
1142 	/** sets copy method of node selector */
1143 	void SCIPnodeselSetCopy(
1144 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1145 	   SCIP_DECL_NODESELCOPY ((*nodeselcopy))    /**< copy method of node selector or NULL if you don't want to copy your plugin into sub-SCIPs */
1146 	   )
1147 	{
1148 	   assert(nodesel != NULL);
1149 	
1150 	   nodesel->nodeselcopy = nodeselcopy;
1151 	}
1152 	
1153 	/** sets destructor method of node selector */
1154 	void SCIPnodeselSetFree(
1155 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1156 	   SCIP_DECL_NODESELFREE ((*nodeselfree))    /**< destructor of node selector */
1157 	   )
1158 	{
1159 	   assert(nodesel != NULL);
1160 	
1161 	   nodesel->nodeselfree = nodeselfree;
1162 	}
1163 	
1164 	/** sets initialization method of node selector */
1165 	void SCIPnodeselSetInit(
1166 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1167 	   SCIP_DECL_NODESELINIT ((*nodeselinit))    /**< initialize node selector */
1168 	   )
1169 	{
1170 	   assert(nodesel != NULL);
1171 	
1172 	   nodesel->nodeselinit = nodeselinit;
1173 	}
1174 	
1175 	/** sets deinitialization method of node selector */
1176 	void SCIPnodeselSetExit(
1177 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1178 	   SCIP_DECL_NODESELEXIT ((*nodeselexit))    /**< deinitialize node selector */
1179 	   )
1180 	{
1181 	   assert(nodesel != NULL);
1182 	
1183 	   nodesel->nodeselexit = nodeselexit;
1184 	}
1185 	
1186 	/** sets solving process initialization method of node selector */
1187 	void SCIPnodeselSetInitsol(
1188 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1189 	   SCIP_DECL_NODESELINITSOL ((*nodeselinitsol))/**< solving process initialization method of node selector */
1190 	   )
1191 	{
1192 	   assert(nodesel != NULL);
1193 	
1194 	   nodesel->nodeselinitsol = nodeselinitsol;
1195 	}
1196 	
1197 	/** sets solving process deinitialization method of node selector */
1198 	void SCIPnodeselSetExitsol(
1199 	   SCIP_NODESEL*         nodesel,            /**< node selector */
1200 	   SCIP_DECL_NODESELEXITSOL ((*nodeselexitsol))/**< solving process deinitialization method of node selector */
1201 	   )
1202 	{
1203 	   assert(nodesel != NULL);
1204 	
1205 	   nodesel->nodeselexitsol = nodeselexitsol;
1206 	}
1207 	
1208 	/** is node selector initialized? */
1209 	SCIP_Bool SCIPnodeselIsInitialized(
1210 	   SCIP_NODESEL*         nodesel             /**< node selector */
1211 	   )
1212 	{
1213 	   assert(nodesel != NULL);
1214 	
1215 	   return nodesel->initialized;
1216 	}
1217 	
1218 	/** enables or disables all clocks of \p nodesel, depending on the value of the flag */
1219 	void SCIPnodeselEnableOrDisableClocks(
1220 	   SCIP_NODESEL*         nodesel,            /**< the node selector for which all clocks should be enabled or disabled */
1221 	   SCIP_Bool             enable              /**< should the clocks of the node selector be enabled? */
1222 	   )
1223 	{
1224 	   assert(nodesel != NULL);
1225 	
1226 	   SCIPclockEnableOrDisable(nodesel->setuptime, enable);
1227 	   SCIPclockEnableOrDisable(nodesel->nodeseltime, enable);
1228 	}
1229 	
1230 	/** gets time in seconds used in this node selector for setting up for next stages */
1231 	SCIP_Real SCIPnodeselGetSetupTime(
1232 	   SCIP_NODESEL*         nodesel             /**< node selector */
1233 	   )
1234 	{
1235 	   assert(nodesel != NULL);
1236 	
1237 	   return SCIPclockGetTime(nodesel->setuptime);
1238 	}
1239 	
1240 	/** gets time in seconds used in this node selector */
1241 	SCIP_Real SCIPnodeselGetTime(
1242 	   SCIP_NODESEL*         nodesel             /**< node selector */
1243 	   )
1244 	{
1245 	   assert(nodesel != NULL);
1246 	
1247 	   return SCIPclockGetTime(nodesel->nodeseltime);
1248 	}
1249