Scippy

SCIP

Solving Constraint Integer Programs

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