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