SCIP Doxygen Documentation
Loading...
Searching...
No Matches
event_shadowtree.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-2026 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 event_shadowtree.c
26 * @ingroup DEFPLUGINS_EVENT
27 * @brief event handler for maintaining the unmodified branch-and-bound tree
28 * @author Jasper van Doornmalen
29 *
30 * It is possible that SCIP detects that variable bounds can be restricted globally further than formerly known.
31 * In that case, it is decided to update the global bounds of these variables, and modify the history of the branching
32 * decisions this way. This breaks methods that depend on the assumption that historic choices in the branch-and-bound
33 * tree remain unmodified througout the search, e.g., dynamic symmetry handling constraints.
34 *
35 * This event handler registers decisions made by the branch-and-bound tree directly at the moment of branching, and
36 * does not modify those at later stages of the solve.
37 */
38
39/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
40
42#include "scip/debug.h"
43#include "scip/pub_cons.h"
44#include "scip/pub_message.h"
45#include "scip/pub_var.h"
46#include "scip/struct_var.h"
47#include "scip/type_var.h"
48#include "scip/scip.h"
49#include "scip/scip_branch.h"
50#include "scip/scip_conflict.h"
51#include "scip/scip_cons.h"
52#include "scip/scip_copy.h"
53#include "scip/scip_cut.h"
54#include "scip/scip_general.h"
55#include "scip/scip_lp.h"
56#include "scip/scip_mem.h"
57#include "scip/scip_message.h"
58#include "scip/scip_numerics.h"
59#include "scip/scip_param.h"
60#include "scip/scip_prob.h"
61#include "scip/scip_probing.h"
62#include "scip/scip_sol.h"
63#include "scip/scip_var.h"
64#include "scip/struct_scip.h"
65#include "scip/struct_mem.h"
66#include "scip/struct_tree.h"
67#include "scip/symmetry.h"
68#include <ctype.h>
69#include <memory.h>
71
72#define EVENTHDLR_NAME "event_shadowtree"
73#define EVENTHDLR_DESC "event handler for maintaining the unmodified branch-and-bound tree"
74#define NODEMAP_MAX_INITIAL_SIZE 10000
75#define NODEMAP_MAX_INITIAL_SIZE_2LOG 14
76
77
78/*
79 * Data structures
80 */
81
82
83/** wrapper for shadow tree eventhandler data */
84struct SCIP_EventhdlrData
85{
86#ifndef NDEBUG
87 SCIP* scip; /**< SCIP data structure */
88#endif
89 SCIP_SHADOWTREE* shadowtree; /**< Shadow tree structure */
90 SCIP_CLOCK* clock; /**< clock for measuring time in shadow tree events */
91 SCIP_Bool active; /**< whether a shadow tree should be maintained */
92};
93
94
95/*
96 * Local methods
97 */
98
99/** hash key for SCIP_SHADOWNODE */
100static
101SCIP_DECL_HASHGETKEY(hashGetKeyShadowNode)
102{ /*lint --e{715}*/
103 return elem;
104}
105
106/** returns TRUE iff the indices of both node numbers are equal */
107static
108SCIP_DECL_HASHKEYEQ(hashKeyEqShadowNode)
109{ /*lint --e{715}*/
110 return ((SCIP_SHADOWNODE*) key1)->nodeid == ((SCIP_SHADOWNODE*) key2)->nodeid;
111}
112
113/** returns the hash value of the key */
114static
115SCIP_DECL_HASHKEYVAL(hashKeyValShadowNode)
116{ /*lint --e{715}*/
117 return (unsigned int) ((SCIP_SHADOWNODE*) key)->nodeid;
118}
119
120
121/** get the time spent in the shadow tree eventhdlr */
123 SCIP* scip, /**< SCIP data structure */
124 SCIP_EVENTHDLR* eventhdlr /**< event handler */
125 )
126{
127 SCIP_EVENTHDLRDATA* eventhdlrdata;
128
129 eventhdlrdata = (SCIP_EVENTHDLRDATA*) SCIPeventhdlrGetData(eventhdlr);
130 assert( eventhdlrdata != NULL );
131 assert( eventhdlrdata->scip != NULL );
132 assert( eventhdlrdata->scip == scip );
133 assert( eventhdlrdata->clock != NULL );
134
135 return SCIPgetClockTime(scip, eventhdlrdata->clock);
136}
137
138
139/** given a node number, returns the node in the shadow tree, or NULL if it doesn't exist */
141 SCIP_SHADOWTREE* shadowtree, /**< pointer to the shadow tree */
142 SCIP_Longint nodeid /**< index of the node, equivalent to the standard branch and bound tree */
143 )
144{
145 SCIP_SHADOWNODE tmpnode;
146
147 assert( shadowtree != NULL );
148 assert( nodeid >= 0 );
149
150 tmpnode.nodeid = nodeid;
151
152 /* the following line of code returns NULL if it cannot find the entry in the hashtable */
153 return (SCIP_SHADOWNODE*) SCIPhashtableRetrieve(shadowtree->nodemap, (void*) &tmpnode);
154}
155
156/** given a node, returns the node in the shadowtree, or NULL if it doesn't exist */
158 SCIP_SHADOWTREE* shadowtree, /**< pointer to the shadow tree */
159 SCIP_NODE* node /**< node from the actual branch-and-bound tree */
160 )
161{
162 assert( shadowtree != NULL );
163 assert( node != NULL );
164
166}
167
168/*
169 * Callback methods of event handler
170 */
171
172/** event handler for branching event */
173static
174SCIP_DECL_EVENTEXEC(eventExecNodeBranched)
175{
176 SCIP_EVENTHDLRDATA* eventhdlrdata;
177 SCIP_SHADOWTREE* shadowtree;
178 SCIP_SHADOWNODE* eventshadownode;
179 SCIP_SHADOWNODE* childshadownode;
180 SCIP_NODE* eventnode;
181 SCIP_NODE** children;
182 SCIP_NODE* childnode;
183 SCIP_DOMCHG* domchg;
184 SCIP_BOUNDCHG* boundchg;
185 SCIP_SHADOWBOUNDUPDATE* branchingdecisions;
187 int maxnbranchingdecisions;
188 int nbranchingdecisions;
189 int nboundchgs;
190 int nchildren;
191 int i;
192 int c;
193
194 assert( scip != NULL );
195 assert( eventhdlr != NULL );
196 assert( event != NULL );
198
199 /* no branching during probing */
201
202 eventnode = SCIPeventGetNode(event);
203 assert( SCIPgetFocusNode(scip) == eventnode );
205
206 eventhdlrdata = (SCIP_EVENTHDLRDATA*) SCIPeventhdlrGetData(eventhdlr);
207 assert( eventhdlrdata != NULL );
208 assert( scip == eventhdlrdata->scip );
209
210 shadowtree = eventhdlrdata->shadowtree;
211 assert( shadowtree != NULL );
212
213 eventshadownode = SCIPshadowTreeGetShadowNode(shadowtree, eventnode);
214
215 /* only add children to the shadowtree if eventnode is in the shadowtree */
216 if ( eventshadownode == NULL )
217 return SCIP_OKAY;
218
219 assert( eventshadownode->nchildren == 0 );
220 assert( eventshadownode->children == NULL );
221
222 SCIP_CALL( SCIPgetChildren(scip, &children, &nchildren) );
223
224 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &eventshadownode->children, nchildren) );
225 eventshadownode->nchildren = nchildren;
226
227 maxnbranchingdecisions = 1; /* good guess that there's one branching variable, because that's likely the number */
228 SCIP_CALL( SCIPallocBufferArray(scip, &branchingdecisions, maxnbranchingdecisions) );
229
230 /* get all variables branched upon and check all branches */
231 for (c = 0; c < nchildren; ++c)
232 {
233 nbranchingdecisions = 0;
234
235 childnode = children[c];
236 domchg = SCIPnodeGetDomchg(childnode);
237
238 /* loop through all bound changes */
239 nboundchgs = SCIPdomchgGetNBoundchgs(domchg);
240 for (i = 0; i < nboundchgs; ++i)
241 {
242 /* get bound change info */
243 boundchg = SCIPdomchgGetBoundchg(domchg, i);
244 assert( boundchg != NULL );
245
246 /* branching decisions have to be in the beginning of the bound change array */
248 break;
249
250 if ( nbranchingdecisions >= maxnbranchingdecisions )
251 {
252 assert( nbranchingdecisions == maxnbranchingdecisions );
253 assert( maxnbranchingdecisions > 0 );
254 maxnbranchingdecisions = SCIPcalcMemGrowSize(scip, maxnbranchingdecisions + 1);
255 SCIP_CALL( SCIPreallocBufferArray(scip, &branchingdecisions, maxnbranchingdecisions) );
256 }
257 assert( nbranchingdecisions < maxnbranchingdecisions );
258
259 /* get corresponding branching step */
260 update = &branchingdecisions[nbranchingdecisions++];
261 update->var = SCIPboundchgGetVar(boundchg);
262 update->boundchgtype = SCIPboundchgGetBoundtype(boundchg);
263 update->newbound = SCIPboundchgGetNewbound(boundchg);
264 }
265
266 /* create the child in the shadow tree */
267 SCIP_CALL( SCIPallocBlockMemory(scip, &childshadownode) );
268 eventshadownode->children[c] = childshadownode;
269
270 childshadownode->nodeid = SCIPnodeGetNumber(childnode);
271 childshadownode->parent = eventshadownode;
272
273 /* children are only set after this node is focused and branched on */
274 childshadownode->children = NULL;
275 childshadownode->nchildren = 0;
276
277 if ( nbranchingdecisions <= 0 )
278 childshadownode->branchingdecisions = NULL;
279 else
280 {
281 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &childshadownode->branchingdecisions, nbranchingdecisions) );
282 for (i = 0; i < nbranchingdecisions; ++i)
283 {
284 /* this copies the whole struct */
285 childshadownode->branchingdecisions[i] = branchingdecisions[i];
286 }
287 }
288 childshadownode->nbranchingdecisions = nbranchingdecisions;
289
290 /* propagations are only set after this node is focused and branched on */
291 childshadownode->propagations = NULL;
292 childshadownode->npropagations = 0;
293
294 /* add childshadownode to the nodemap as well
295 *
296 * The hashtable only checks by the 'nodeid' field, so we just check if there's none with this nodeid.
297 */
298 assert( !SCIPhashtableExists(shadowtree->nodemap, (void*) childshadownode));
299 SCIP_CALL( SCIPhashtableInsert(shadowtree->nodemap, childshadownode) );
300 }
301 SCIPfreeBufferArray(scip, &branchingdecisions);
302
303 /* also store the propagations in the eventnode (the node that got solved by branching) */
304 domchg = SCIPnodeGetDomchg(eventnode);
305
306 /* loop through all bound changes in the focus node */
307 nboundchgs = SCIPdomchgGetNBoundchgs(domchg);
308 if ( nboundchgs <= 0 )
309 {
310 assert( nboundchgs == 0 );
311
312 /* this is set to NULL at initialization of this shadownode, already */
313 assert( eventshadownode->npropagations == 0 );
314 assert( eventshadownode->branchingdecisions == NULL );
315 }
316 else
317 {
318 /* just include everything, even the branching decisions! */
319 eventshadownode->npropagations = nboundchgs;
320 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &eventshadownode->propagations, nboundchgs) );
321 for (i = 0; i < nboundchgs; ++i)
322 {
323 boundchg = SCIPdomchgGetBoundchg(domchg, i);
324 assert( boundchg != NULL );
325 update = &(eventshadownode->propagations[i]);
326 update->var = SCIPboundchgGetVar(boundchg);
327 update->boundchgtype = SCIPboundchgGetBoundtype(boundchg);
328 update->newbound = SCIPboundchgGetNewbound(boundchg);
329 }
330 }
331
332 return SCIP_OKAY;
333} /*lint !e715*/
334
335
336/** event handler for node deletion event */
337static
338SCIP_DECL_EVENTEXEC(eventExecNodeDeleted)
339{ /*lint !e396*/
340 SCIP_EVENTHDLRDATA* eventhdlrdata;
341 SCIP_SHADOWTREE* shadowtree;
342 SCIP_NODE* deletednode;
343 SCIP_SHADOWNODE* deletedshadownode;
344 int c;
345 SCIP_SHADOWNODE* childshadownode;
346
347 assert( scip != NULL );
348 assert( eventhdlr != NULL );
349 assert( event != NULL );
351
352 deletednode = SCIPeventGetNode(event);
353 assert( deletednode != NULL );
354
355 /* probing nodes are not stored */
356 if( SCIPnodeGetType(deletednode) == SCIP_NODETYPE_PROBINGNODE )
357 return SCIP_OKAY;
358
359 eventhdlrdata = (SCIP_EVENTHDLRDATA*) SCIPeventhdlrGetData(eventhdlr);
360 assert( eventhdlrdata != NULL );
361 assert( scip == eventhdlrdata->scip );
362
363 shadowtree = eventhdlrdata->shadowtree;
364 assert( shadowtree != NULL );
365
366 deletedshadownode = SCIPshadowTreeGetShadowNode(shadowtree, deletednode);
367
368 /* no need to delete if not included in the shadowtree */
369 if ( deletedshadownode == NULL )
370 return SCIP_OKAY;
371 assert( deletedshadownode->nodeid == SCIPnodeGetNumber(deletednode) );
372
373 /* It is possible that deletedshadownode has a non-deleted sibling.
374 * If the branching variable of this sibling differs from deletedshadownode's,
375 * then in the variable branching order also the branching variables of deletedshadownode must be included,
376 * e.g., see `shadowtreeFillNodeDepthBranchIndices` in symmetry_lexred.c.
377 * As such, we may not delete deletedshadownode just yet. However, we can delete its children.
378 * So, mark deletedshadownode as 'ready to delete' by freeing its children, and setting nchildren to -1.
379 * SCIP always deletes leaf nodes only, so if `deletedshadownode` is removed,
380 * its children in the shadowtree (if they exist) in the 'ready to delete' state. */
381 assert( deletedshadownode->nchildren >= 0 );
382 assert( (deletedshadownode->nchildren == 0) == (deletedshadownode->children == NULL) );
383 for (c = 0; c < deletedshadownode->nchildren; ++c)
384 {
385 childshadownode = deletedshadownode->children[c];
386
387 /* remove from hashtable */
388 SCIP_CALL( SCIPhashtableRemove(shadowtree->nodemap, (void*) childshadownode) );
389
390 /* clean childshadownode */
391 assert( childshadownode->npropagations >= 0 );
392 assert( (childshadownode->npropagations > 0) != (childshadownode->propagations == NULL) );
393 SCIPfreeBlockMemoryArrayNull(scip, &childshadownode->propagations, childshadownode->npropagations);
394
395 assert( childshadownode->nbranchingdecisions >= 0 );
396 assert( (childshadownode->nbranchingdecisions > 0) != (childshadownode->branchingdecisions == NULL) );
397 SCIPfreeBlockMemoryArrayNull(scip, &childshadownode->branchingdecisions, childshadownode->nbranchingdecisions);
398
399 /* childshadownode must be in the 'ready to delete'-state */
400 assert( childshadownode->nchildren < 0 );
401
402 SCIPfreeBlockMemory(scip, &childshadownode);
403 }
404
405 assert( (deletedshadownode->nchildren > 0) != (deletedshadownode->children == NULL) );
406 if ( deletedshadownode->nchildren > 0 )
407 {
408 SCIPfreeBlockMemoryArray(scip, &deletedshadownode->children, deletedshadownode->nchildren);
409 }
410
411 /* mark deletedshadownode as 'ready to delete' */
412 deletedshadownode->children = NULL;
413 deletedshadownode->nchildren = -1;
414
415 return SCIP_OKAY;
416} /*lint !e715*/
417
418
419/** execution method for all events handled by this eventhandler */
420static
422{
423 SCIP_EVENTHDLRDATA* eventhdlrdata;
424
426
427 eventhdlrdata = (SCIP_EVENTHDLRDATA*) SCIPeventhdlrGetData(eventhdlr);
428 assert( eventhdlrdata != NULL );
429 assert( scip == eventhdlrdata->scip );
430 assert( eventhdlrdata->clock != NULL );
431
432 SCIP_CALL( SCIPstartClock(scip, eventhdlrdata->clock) );
433
434 switch (SCIPeventGetType(event))
435 {
437 SCIP_CALL( eventExecNodeBranched(scip, eventhdlr, event, eventdata) );
438 break;
440 SCIP_CALL( eventExecNodeDeleted(scip, eventhdlr, event, eventdata) );
441 break;
442 default:
443 SCIPerrorMessage("unrecognized eventtype in shadowtree event handler\n");
444 return SCIP_ERROR;
445 }
446
447 SCIP_CALL( SCIPstopClock(scip, eventhdlrdata->clock) );
448
449 return SCIP_OKAY;
450}
451
452
453/** frees shadow tree data structure */
454static
456 SCIP* scip, /**< SCIP data structure */
457 SCIP_SHADOWTREE* shadowtree /**< pointer to shadow tree*/
458 )
459{
460 int i;
461 int nentries;
462 SCIP_SHADOWNODE* shadownode;
463
464 assert( scip != NULL );
465 assert( shadowtree != NULL );
466 assert( shadowtree->nodemap != NULL );
467
468 nentries = SCIPhashtableGetNEntries(shadowtree->nodemap);
469
470 /* free all shadow tree nodes */
471 for (i = 0; i < nentries; ++i)
472 {
473 shadownode = (SCIP_SHADOWNODE*) SCIPhashtableGetEntry(shadowtree->nodemap, i);
474 if ( shadownode == NULL )
475 continue;
476
477 assert( shadownode != NULL );
478
479 assert( shadownode->npropagations >= 0 );
480 assert( (shadownode->npropagations > 0) != (shadownode->propagations == NULL) );
482
483 assert( shadownode->nbranchingdecisions >= 0 );
484 assert( (shadownode->nbranchingdecisions > 0) != (shadownode->branchingdecisions == NULL) );
486
487 assert( shadownode->nchildren >= -1 );
488 assert( (shadownode->nchildren > 0) != (shadownode->children == NULL) );
489 SCIPfreeBlockMemoryArrayNull(scip, &shadownode->children, shadownode->nchildren);
490
491 SCIPfreeBlockMemory(scip, &shadownode);
492 }
493 SCIPhashtableFree(&(shadowtree->nodemap));
494
495 return SCIP_OKAY;
496}
497
498
499/** destructor of event handler to free shadow tree data (called when SCIP is exiting) */
500static
501SCIP_DECL_EVENTFREE(eventFreeShadowTree)
502{
503 SCIP_EVENTHDLRDATA* eventhdlrdata;
504
505 assert( scip != NULL );
506 assert( eventhdlr != NULL );
508
509 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
510 assert( eventhdlrdata != NULL );
511 assert( eventhdlrdata->scip == scip );
512 assert( eventhdlrdata->clock != NULL );
513
514 SCIP_CALL( SCIPfreeClock(scip, &eventhdlrdata->clock) );
515
516 if ( eventhdlrdata->shadowtree != NULL )
517 {
518 SCIP_CALL( freeShadowTree(scip, eventhdlrdata->shadowtree) );
519 SCIPfreeBlockMemory(scip, &eventhdlrdata->shadowtree);
520 }
521
522 SCIPfreeBlockMemory(scip, &eventhdlrdata);
523
524 return SCIP_OKAY;
525}
526
527
528/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
529static
530SCIP_DECL_EVENTINITSOL(eventInitsolShadowTree)
531{
532 int initialnodemapsize;
533
534 SCIP_EVENTHDLRDATA* eventhdlrdata;
535 SCIP_SHADOWTREE* shadowtree;
536 SCIP_SHADOWNODE* rootnode;
537
538 assert( scip != NULL );
539 assert( eventhdlr != NULL );
540
541 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
542 assert( eventhdlrdata != NULL );
543 assert( eventhdlrdata->scip == scip );
544
545 assert( eventhdlrdata->shadowtree == NULL );
547
548 /* early termination */
549 if ( !eventhdlrdata->active )
550 return SCIP_OKAY;
551
552 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata->shadowtree) );
553 shadowtree = eventhdlrdata->shadowtree;
554
555 /* prevent unnecessary reallocations by having a good initial guess for the tree size
556 *
557 * By default, we initialize NODEMAP_MAX_INITIAL_SIZE slots, unless reasonably fewer nodes suffice.
558 * Knowing that a full enumeration tree on n binary variables has size 2^n, we base our guess on this number,
559 * counting with the number of binary and integer variables in the problem.
560 */
563 MIN(NODEMAP_MAX_INITIAL_SIZE, 1 << (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip))); /*lint !e666 !e701 !e747*/
564 SCIP_CALL( SCIPhashtableCreate(&shadowtree->nodemap, scip->mem->probmem, initialnodemapsize,
565 hashGetKeyShadowNode, hashKeyEqShadowNode, hashKeyValShadowNode, NULL) );
566
567 /* the root node is the only branch-and-bound tree node not created by branching, so add. */
568 SCIP_CALL( SCIPallocBlockMemory(scip, &rootnode) );
569 rootnode->nodeid = 1ll; /*lint !e620*/ /* root node has number 1 */
570 rootnode->parent = NULL;
571 rootnode->children = NULL;
572 rootnode->nchildren = 0;
573 rootnode->branchingdecisions = NULL;
574 rootnode->nbranchingdecisions = 0;
575 rootnode->propagations = NULL;
576 rootnode->npropagations = 0;
577
578 /* add to the nodemap structure */
579 SCIP_CALL( SCIPhashtableInsert(shadowtree->nodemap, rootnode) );
580
581 /* catch NODEBRANCHED and NODEDELETE events */
583
584 return SCIP_OKAY;
585}
586
587
588/** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
589static
590SCIP_DECL_EVENTEXITSOL(eventExitsolShadowTree)
591{
592 SCIP_EVENTHDLRDATA* eventhdlrdata;
593
594 assert( scip != NULL );
595 assert( eventhdlr != NULL );
596
597 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
598 assert( eventhdlrdata != NULL );
599 assert( eventhdlrdata->scip == scip );
601
602 /* early termination */
603 if ( !eventhdlrdata->active )
604 {
605 assert( eventhdlrdata->shadowtree == NULL );
606 return SCIP_OKAY;
607 }
608
609 assert( eventhdlrdata->shadowtree != NULL );
610
611 SCIP_CALL( freeShadowTree(scip, eventhdlrdata->shadowtree) );
612 SCIPfreeBlockMemory(scip, &eventhdlrdata->shadowtree);
613 eventhdlrdata->shadowtree = NULL;
614
615 /* do not listen for NODEBRANCHED events */
617
618 return SCIP_OKAY;
619}
620
621
622/** gets the shadow tree */
624 SCIP_EVENTHDLR* eventhdlr /**< event handler */
625 )
626{
627 SCIP_EVENTHDLRDATA* eventhdlrdata;
628 assert( eventhdlr != NULL );
629
631
632 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
633 assert( eventhdlrdata != NULL );
634
635 return eventhdlrdata->shadowtree;
636}
637
638
639/** activates shadow tree eventhandler if it is not already activated (which keeps a copy of the tree) */
641 SCIP* scip, /**< SCIP data structure */
642 SCIP_EVENTHDLR* eventhdlr /**< event handler */
643 )
644{
645 SCIP_EVENTHDLRDATA* eventhdlrdata;
646 assert( eventhdlr != NULL );
647
649
650 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
651 assert( eventhdlrdata != NULL );
652 assert( eventhdlrdata->scip == scip );
653 assert( eventhdlrdata->shadowtree == NULL );
654
655 /* active param may not be changed between (and including) the initsol and exitsol stages */
656 SCIP_CALL( SCIPcheckStage(scip, "SCIPactivateShadowTree", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE,
657 FALSE, FALSE, FALSE, FALSE, FALSE) );
658
659 eventhdlrdata->active = TRUE;
660
661 return SCIP_OKAY;
662}
663
664
665/** creates event handler for event */
667 SCIP* scip, /**< SCIP data structure */
668 SCIP_EVENTHDLR** eventhdlrptr /**< pointer to store the event handler */
669 )
670{
671 SCIP_EVENTHDLRDATA* eventhdlrdata;
672 SCIP_EVENTHDLR* eventhdlr;
673
674 /* create event handler data */
675 eventhdlrdata = NULL;
676 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
677
678#ifndef NDEBUG
679 /* only needed for assertions, to check whether we're working with the correct SCIP. */
680 eventhdlrdata->scip = scip;
681#endif
682
683 /* shadow tree must be activated */
684 eventhdlrdata->active = FALSE;
685
686 /* do not start with a shadow tree by default. Initialize at initsol, remove at exitsol. */
687 eventhdlrdata->shadowtree = NULL;
688 eventhdlr = NULL;
689
690 /* include event handler into SCIP */
691 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExec, eventhdlrdata) );
692 assert(eventhdlr != NULL);
693 *eventhdlrptr = eventhdlr;
694
695 /* clock */
696 SCIP_CALL( SCIPcreateClock(scip, &eventhdlrdata->clock) );
697
698 /* set non fundamental callbacks via setter functions */
699
700 /* frees the event handler */
701 SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeShadowTree) );
702
703 /* initialize the shadowtree data structure, initialize by setting the root node */
704 SCIP_CALL( SCIPsetEventhdlrInitsol(scip, eventhdlr, eventInitsolShadowTree) );
705
706 /* free the shadowtree data structure */
707 SCIP_CALL( SCIPsetEventhdlrExitsol(scip, eventhdlr, eventExitsolShadowTree) );
708
709 return SCIP_OKAY;
710}
static GRAPHNODE ** active
#define EVENTHDLR_NAME
#define EVENTHDLR_DESC
methods for debugging
#define SCIPcheckStage(scip, method, init, problem, transforming, transformed, initpresolve, presolving, exitpresolve, presolved, initsolve, solving, solved, exitsolve, freetrans, freescip)
Definition debug.h:365
#define NULL
Definition def.h:257
#define SCIP_Longint
Definition def.h:150
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPactivateShadowTree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr)
SCIP_SHADOWTREE * SCIPgetShadowTree(SCIP_EVENTHDLR *eventhdlr)
SCIP_SHADOWNODE * SCIPshadowTreeGetShadowNode(SCIP_SHADOWTREE *shadowtree, SCIP_NODE *node)
SCIP_SHADOWNODE * SCIPshadowTreeGetShadowNodeFromNodeNumber(SCIP_SHADOWTREE *shadowtree, SCIP_Longint nodeid)
SCIP_Real SCIPgetShadowTreeEventHandlerExecutionTime(SCIP *scip, SCIP_EVENTHDLR *eventhdlr)
#define NODEMAP_MAX_INITIAL_SIZE_2LOG
#define NODEMAP_MAX_INITIAL_SIZE
static SCIP_RETCODE freeShadowTree(SCIP *scip, SCIP_SHADOWTREE *shadowtree)
SCIP_RETCODE SCIPincludeEventHdlrShadowTree(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr)
struct SCIP_ShadowBoundUpdate SCIP_SHADOWBOUNDUPDATE
struct SCIP_ShadowTree SCIP_SHADOWTREE
struct SCIP_ShadowNode SCIP_SHADOWNODE
SCIP_Bool SCIPisTransformed(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
int SCIPgetNIntVars(SCIP *scip)
Definition scip_prob.c:2340
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2293
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition misc.c:2348
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2647
int SCIPhashtableGetNEntries(SCIP_HASHTABLE *hashtable)
Definition misc.c:2765
void * SCIPhashtableGetEntry(SCIP_HASHTABLE *hashtable, int entryidx)
Definition misc.c:2773
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition misc.c:2298
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition misc.c:2596
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2665
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2535
SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr,)
Definition scip_event.c:157
SCIP_RETCODE SCIPsetEventhdlrInitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr,)
Definition scip_event.c:199
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition scip_event.c:111
SCIP_RETCODE SCIPsetEventhdlrExitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr,)
Definition scip_event.c:213
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:396
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:406
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition event.c:1194
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition scip_event.c:293
SCIP_NODE * SCIPeventGetNode(SCIP_EVENT *event)
Definition event.c:1530
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition scip_event.c:333
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition tree.c:8503
SCIP_DOMCHG * SCIPnodeGetDomchg(SCIP_NODE *node)
Definition tree.c:8618
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition tree.c:8513
SCIP_Bool SCIPinProbing(SCIP *scip)
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition scip_timing.c:76
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
SCIP_RETCODE SCIPgetChildren(SCIP *scip, SCIP_NODE ***children, int *nchildren)
Definition scip_tree.c:164
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition scip_tree.c:72
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:23226
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition var.c:23206
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition var.c:23254
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:23216
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition var.c:23186
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition var.c:23246
return SCIP_OKAY
int c
assert(minobj< SCIPgetCutoffbound(scip))
memory allocation routines
public methods for managing constraints
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
public methods for problem variables
SCIP callable library.
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for SCIP variables
SCIP_BOUNDTYPE boundchgtype
SCIP_Longint nodeid
struct SCIP_ShadowNode ** children
SCIP_SHADOWBOUNDUPDATE * branchingdecisions
SCIP_SHADOWBOUNDUPDATE * propagations
struct SCIP_ShadowNode * parent
SCIP_HASHTABLE * nodemap
datastructures for block memory pools and memory buffers
SCIP main data structure.
data structures for branch and bound tree
datastructures for problem variables
methods for handling symmetries
struct SCIP_Clock SCIP_CLOCK
Definition type_clock.h:49
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
#define SCIP_DECL_EVENTINITSOL(x)
Definition type_event.h:224
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition type_event.h:160
#define SCIP_DECL_EVENTEXEC(x)
Definition type_event.h:259
#define SCIP_EVENTTYPE_NODEBRANCHED
Definition type_event.h:96
#define SCIP_DECL_EVENTFREE(x)
Definition type_event.h:197
#define SCIP_DECL_EVENTEXITSOL(x)
Definition type_event.h:235
#define SCIP_EVENTTYPE_NODEDELETE
Definition type_event.h:97
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:192
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
@ SCIP_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
struct SCIP_Node SCIP_NODE
Definition type_tree.h:63
@ SCIP_NODETYPE_PROBINGNODE
Definition type_tree.h:42
@ SCIP_NODETYPE_FOCUSNODE
Definition type_tree.h:41
type definitions for problem variables
union SCIP_DomChg SCIP_DOMCHG
Definition type_var.h:149
struct SCIP_BoundChg SCIP_BOUNDCHG
Definition type_var.h:150
@ SCIP_BOUNDCHGTYPE_BRANCHING
Definition type_var.h:131