Scippy

GCG

Branch-and-Price & Column Generation for Everyone

cons_origbranch.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file cons_origbranch.c
29  * @ingroup CONSHDLRS
30  * @brief constraint handler for storing the branching decisions at each node of the tree
31  * @author Gerald Gamrath
32  * @author Martin Bergner
33  */
34 
35 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 /* #define SCIP_DEBUG */
37 /* #define CHECKCONSISTENCY */
38 #include <assert.h>
39 #include <string.h>
40 
41 #include "gcg.h"
42 #include "branch_generic.h"
43 #include "cons_masterbranch.h"
44 #include "cons_origbranch.h"
45 
46 #include "scip/nodesel_bfs.h"
47 #include "scip/nodesel_dfs.h"
48 #include "scip/nodesel_estimate.h"
49 #include "scip/nodesel_hybridestim.h"
50 #include "scip/nodesel_restartdfs.h"
51 #include "scip/branch_allfullstrong.h"
52 #include "scip/branch_fullstrong.h"
53 #include "scip/branch_inference.h"
54 #include "scip/branch_mostinf.h"
55 #include "scip/branch_leastinf.h"
56 #include "scip/branch_pscost.h"
57 #include "scip/branch_random.h"
58 #include "scip/branch_relpscost.h"
59 #include "scip/cons_linear.h"
60 
61 /* constraint handler properties */
62 #define CONSHDLR_NAME "origbranch"
63 #define CONSHDLR_DESC "store branching decision at nodes of the tree constraint handler"
64 #define CONSHDLR_ENFOPRIORITY 0 /**< priority of the constraint handler for constraint enforcing */
65 #define CONSHDLR_CHECKPRIORITY 2000000 /**< priority of the constraint handler for checking feasibility */
66 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
67  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
68 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
69 
70 
71 /** constraint data for branch orig constraints */
72 struct SCIP_ConsData
73 {
74  SCIP_NODE* node; /**< the node at which the cons is sticking */
75  SCIP_CONS* parentcons; /**< the origbranch constraint of the parent node */
76  SCIP_CONS** childconss; /**< array of the masterbranch constraints of child nodes */
77  int nchildconss; /**< number of the masterbranch constraints of child nodes */
78  int maxchildconss; /**< capacity of childconss */
79  SCIP_CONS* probingtmpcons; /**< pointer to save the last child in the childconss array if it is overwritten in probing mode */
80  SCIP_CONS* mastercons; /**< the masterbranch constraint of the corresponding node
81  * in the master program */
82  GCG_BRANCHDATA* branchdata; /**< branching data stored by the branching rule containing information
83  * about the branching restrictions */
84  SCIP_BRANCHRULE* branchrule; /**< branching rule that created the corresponding node and imposed
85  * branching restrictions */
86 };
87 
88 /** constraint handler data */
89 struct SCIP_ConshdlrData
90 {
91  SCIP_CONS** stack; /**< stack for storing active constraints */
92  int nstack; /**< number of elements on the stack */
93  int maxstacksize; /**< maximum size of the stack */
94  SCIP_CONS* rootcons; /**< constraint in the root node */
95 };
96 
97 
98 /*
99  * Callback methods of constraint handler
100  */
101 
102 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
103 static
104 SCIP_DECL_CONSFREE(consFreeOrigbranch)
105 { /*lint --e{715}*/
106  SCIP_CONSHDLRDATA* conshdlrData;
107 
108  assert(scip != NULL);
109  assert(conshdlr != NULL);
110  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
111 
112  conshdlrData = SCIPconshdlrGetData(conshdlr);
113  assert(conshdlrData != NULL);
114 
115  SCIPdebugMessage("freeing branch orig constraint handler (nconss = %d)\n", SCIPconshdlrGetNConss(conshdlr));
116 
117  /* free constraint handler storage */
118  assert(conshdlrData->stack == NULL);
119  if( conshdlrData->rootcons != NULL )
120  {
121  SCIP_CALL( SCIPreleaseCons(scip, &conshdlrData->rootcons) );
122  }
123 
124  SCIPfreeMemory(scip, &conshdlrData);
125 
126  return SCIP_OKAY;
127 }
128 
129 
130 /** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
131 static
132 SCIP_DECL_CONSINITSOL(consInitsolOrigbranch)
133 { /*lint --e{715}*/
134  SCIP_CONSHDLRDATA* conshdlrData;
135 
136  assert(scip != NULL);
137  assert(conshdlr != NULL);
138  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
139 
140  conshdlrData = SCIPconshdlrGetData(conshdlr);
141  assert(conshdlrData != NULL);
142 
143  /* prepare stack */
144  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &conshdlrData->stack, conshdlrData->maxstacksize) );
145  assert(conshdlrData->nstack >= 0);
146 
147  /* check consistency */
148  if( conshdlrData->rootcons != NULL )
149  {
150  SCIP_CALL( SCIPreleaseCons(scip, &conshdlrData->rootcons) );
151  conshdlrData->rootcons = NULL;
152  --(conshdlrData->nstack);
153  }
154 
156 
157  return SCIP_OKAY;
158 }
159 
160 
161 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
162 static
163 SCIP_DECL_CONSEXITSOL(consExitsolOrigbranch)
164 { /*lint --e{715}*/
165  SCIP_CONSHDLRDATA* conshdlrdata;
166  GCG_BRANCHDATA* branchdata;
167 
168  assert(scip != NULL);
169  assert(conshdlr != NULL);
170  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
171 
172  conshdlrdata = SCIPconshdlrGetData(conshdlr);
173  assert(conshdlrdata != NULL);
174  assert(conshdlrdata->nstack <= 1);
175 
176  SCIPdebugMessage("exiting solution process branch orig constraint handler (nconss = %d)\n", SCIPconshdlrGetNConss(conshdlr));
177 
178  /* check for root */
179  if( conshdlrdata->rootcons != NULL )
180  {
181  branchdata = GCGconsOrigbranchGetBranchdata(conshdlrdata->rootcons);
182 
183  SCIPfreeMemoryNull(scip, &branchdata );
184 
185  SCIP_CALL( SCIPreleaseCons(scip, &conshdlrdata->rootcons) );
186  conshdlrdata->rootcons = NULL;
187  }
188 
189  /* free stack */
190  SCIPfreeBlockMemoryArray(scip, &conshdlrdata->stack, conshdlrdata->maxstacksize);
191  conshdlrdata->stack = NULL;
192 
193  return SCIP_OKAY;
194 }
195 
196 /** exit method of constraint handler (called before problem is free transformed) */
197 static
198 SCIP_DECL_CONSEXIT(consExitOrigbranch)
199 { /*lint --e{715}*/
200  SCIP_CONSHDLRDATA* conshdlrdata;
201  assert(conshdlr != NULL);
202  assert(scip != NULL);
203  conshdlrdata = SCIPconshdlrGetData(conshdlr);
204  assert(conshdlrdata != NULL);
205 
206  SCIPdebugMessage("exiting transformed branch orig constraint handler (nconss = %d)\n", SCIPconshdlrGetNConss(conshdlr));
207 
208  if( conshdlrdata->rootcons != NULL )
209  {
210  SCIP_CALL( SCIPreleaseCons(scip, &conshdlrdata->rootcons) );
211  conshdlrdata->rootcons = NULL;
212  }
213  return SCIP_OKAY;
214 }
215 
216 /** frees specific constraint data */
217 static
218 SCIP_DECL_CONSDELETE(consDeleteOrigbranch)
219 { /*lint --e{715}*/
220  SCIP_CONSDATA* parentdata;
221  int i;
222 
223  assert(scip != NULL);
224  assert(conshdlr != NULL);
225  assert(cons != NULL);
226  assert(consdata != NULL);
227  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
228  assert(*consdata != NULL);
229 
230  SCIPdebugMessage("Deleting branch orig constraint: <%s>.\n", SCIPconsGetName(cons));
231 
232  /* set the origcons pointer of the corresponding mastercons to NULL */
233  if( (*consdata)->mastercons != NULL )
234  {
235  assert(GCGconsMasterbranchGetOrigcons((*consdata)->mastercons) == cons);
236  GCGconsMasterbranchSetOrigcons((*consdata)->mastercons, NULL);
237  }
238 
239  /* set the pointer in the parent constraint to NULL */
240  if( (*consdata)->parentcons != NULL )
241  {
242 #ifndef NDEBUG
243  SCIP_Bool childdeleted = FALSE;
244 #endif
245  parentdata = SCIPconsGetData((*consdata)->parentcons);
246 
247  if( SCIPinProbing(scip) )
248  parentdata->probingtmpcons = NULL;
249 
250  for( i = 0; i < parentdata->nchildconss; ++i )
251  {
252  if( parentdata->childconss[i] == cons )
253  {
254 
255  parentdata->childconss[i] = parentdata->childconss[parentdata->nchildconss-1];
256  parentdata->childconss[parentdata->nchildconss-1] = NULL;
257 #ifndef NDEBUG
258  childdeleted = TRUE;
259 #endif
260  (parentdata->nchildconss) -= 1;
261  break;
262  }
263  }
264  assert(childdeleted || SCIPinProbing(scip));
265  }
266 
267  /* no child nodes may exist */
268  for( i = 0; i < (*consdata)->nchildconss; ++i )
269  assert((*consdata)->childconss[i] == NULL);
270 
271  /* delete branchdata if no mastercons is linked which would still need the branchdata;
272  * otherwise, the mastercons deletes the branchdata when it is deleted itself
273  */
274  if( (*consdata)->mastercons == NULL && (*consdata)->branchdata != NULL && (*consdata)->branchrule != NULL )
275  {
276  (*consdata)->branchdata = NULL;
277  }
278 
279  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->childconss, (*consdata)->maxchildconss);
280  (*consdata)->childconss = NULL;
281  (*consdata)->nchildconss = 0;
282  (*consdata)->maxchildconss = 0;
283 
284  /* free constraint data */
285  SCIPfreeBlockMemory(scip, consdata);
286 
287  return SCIP_OKAY;
288 }
289 
290 
291 /** constraint activation notification method of constraint handler */
292 static
293 SCIP_DECL_CONSACTIVE(consActiveOrigbranch)
294 { /*lint --e{715}*/
295  SCIP_CONSHDLRDATA* conshdlrData;
296 
297  assert(scip != NULL);
298  assert(conshdlr != NULL);
299  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
300  assert(cons != NULL);
301 
302  conshdlrData = SCIPconshdlrGetData(conshdlr);
303  assert(conshdlrData != NULL);
304  assert(conshdlrData->stack != NULL);
305 
306  assert(SCIPconsGetData(cons) != NULL);
307 
308  if( SCIPconsGetData(cons)->node == NULL )
309  SCIPconsGetData(cons)->node = SCIPgetRootNode(scip);
310 
311  SCIPdebugMessage("Activating branch orig constraint: <%s>[stack size: %d].\n", SCIPconsGetName(cons),
312  conshdlrData->nstack+1);
313 
314  /* put constraint on the stack */
315  if( conshdlrData->nstack >= conshdlrData->maxstacksize )
316  {
317  int newsize = SCIPcalcMemGrowSize(scip, conshdlrData->nstack+1);
318  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(conshdlrData->stack), conshdlrData->maxstacksize, newsize) );
319  SCIPdebugMessage("reallocating Memory for stack! %d --> %d\n", conshdlrData->maxstacksize, newsize);
320  conshdlrData->maxstacksize = newsize;
321  }
322 
323  /* put constraint on the stack */
324  assert(conshdlrData->stack != NULL);
325  conshdlrData->stack[conshdlrData->nstack] = cons;
326  ++(conshdlrData->nstack);
327 
328  return SCIP_OKAY;
329 }
330 
331 
332 /** constraint deactivation notification method of constraint handler */
333 static
334 SCIP_DECL_CONSDEACTIVE(consDeactiveOrigbranch)
335 { /*lint --e{715}*/
336  SCIP_CONSHDLRDATA* conshdlrData;
337 
338  assert(scip != NULL);
339  assert(conshdlr != NULL);
340  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
341  assert(cons != NULL);
342 
343  conshdlrData = SCIPconshdlrGetData(conshdlr);
344  assert(conshdlrData != NULL);
345  assert(conshdlrData->stack != NULL || conshdlrData->nstack <= 1);
346  assert(conshdlrData->nstack <= 1 || cons == conshdlrData->stack[conshdlrData->nstack-1]);
347 
348  assert(SCIPconsGetData(cons) != NULL);
349 
350  SCIPdebugMessage("Deactivating branch orig constraint: <%s> [stack size: %d].\n",
351  SCIPconsGetName(cons), conshdlrData->nstack-1);
352 
353  /* remove constraint from the stack */
354  if( conshdlrData->nstack > 0 )
355  --(conshdlrData->nstack);
356 
357  return SCIP_OKAY;
358 }
359 
360 /** lp solution enforcement method */
361 static
362 SCIP_DECL_CONSENFOLP(consEnfolpOrigbranch)
363 { /*lint --e{715}*/
364  *result = SCIP_FEASIBLE;
365 
366  return SCIP_OKAY;
367 }
368 
369 /** lp solution enforcement method */
370 static
371 SCIP_DECL_CONSENFORELAX(consEnforeOrigbranch)
372 { /*lint --e{715}*/
373  *result = SCIP_FEASIBLE;
374 
375  return SCIP_OKAY;
376 }
377 
378 
379 /** pseudo solution enforcement method */
380 static
381 SCIP_DECL_CONSENFOPS(consEnfopsOrigbranch)
382 { /*lint --e{715}*/
383  *result = SCIP_FEASIBLE;
384 
385  return SCIP_OKAY;
386 }
387 
388 /** solution check method */
389 static
390 SCIP_DECL_CONSCHECK(consCheckOrigbranch)
391 { /*lint --e{715}*/
392  *result = SCIP_FEASIBLE;
393 
394  return SCIP_OKAY;
395 }
396 
397 /** variable lock method */
398 static
399 SCIP_DECL_CONSLOCK(consLockOrigbranch)
400 { /*lint --e{715}*/
401  return SCIP_OKAY;
402 }
403 
404 /*
405  * interface methods
406  */
407 
408 
409 /** creates the handler for origbranch constraints and includes it in SCIP */
411  SCIP* scip /**< SCIP data structure */
412  )
413 {
414  SCIP_CONSHDLRDATA* conshdlrData;
415  SCIP_CONSHDLR* conshdlr;
416 
417  SCIP_CALL( SCIPallocMemory(scip, &conshdlrData) );
418  conshdlrData->stack = NULL;
419  conshdlrData->nstack = 0;
420  conshdlrData->maxstacksize = 25;
421  conshdlrData->rootcons = NULL;
422 
423  /* include constraint handler */
424  SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC,
426  consEnfolpOrigbranch, consEnfopsOrigbranch, consCheckOrigbranch,
427  consLockOrigbranch, conshdlrData) );
428  assert(conshdlr != NULL);
429 
430  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforeOrigbranch) );
431  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOrigbranch) );
432  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitOrigbranch) );
433  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolOrigbranch) );
434  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolOrigbranch) );
435  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOrigbranch) );
436  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveOrigbranch) );
437  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveOrigbranch) );
438 
439  return SCIP_OKAY;
440 }
441 
442 
443 /** creates and captures a origbranch constraint */
445  SCIP* scip, /**< SCIP data structure */
446  SCIP_CONS** cons, /**< pointer to hold the created constraint */
447  const char* name, /**< name of constraint */
448  SCIP_NODE* node, /**< the node to which this origbranch constraint belongs */
449  SCIP_CONS* parentcons, /**< origbranch constraint associated with the father node */
450  SCIP_BRANCHRULE* branchrule, /**< the branching rule that created the b&b node the constraint belongs to */
451  GCG_BRANCHDATA* branchdata /**< branching data storing information about the branching restrictions at the
452  * corresponding node */
453  )
454 {
455  SCIP_CONSHDLR* conshdlr;
456  SCIP_CONSDATA* consdata;
457 
458  assert(scip != NULL);
459  assert((parentcons == NULL) == (node == NULL));
460 
461  /* find the origbranch constraint handler */
462  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
463  assert(conshdlr != NULL);
464 
465  /* create constraint data */
466  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
467 
468  if( branchdata == NULL && branchrule != NULL )
469  {
470  if( strcmp(SCIPbranchruleGetName(branchrule), "generic") == 0 )
471  {
472  SCIP_CALL( GCGbranchGenericCreateBranchdata(scip, &branchdata) );
473  }
474  }
475 
476  /* initialize the fields in the constraint data */
477  consdata->node = node;
478  consdata->parentcons = parentcons;
479  consdata->childconss = NULL;
480  consdata->nchildconss = 0;
481  consdata->maxchildconss = 0;
482  consdata->probingtmpcons = NULL;
483  consdata->mastercons = NULL;
484  consdata->branchdata = branchdata;
485  consdata->branchrule = branchrule;
486 
487  SCIPdebugMessage("Creating branch orig constraint: <%s> (nconss = %d).\n", name, SCIPconshdlrGetNConss(conshdlr));
488 
489  /* create constraint */
490  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, FALSE, FALSE, FALSE, FALSE, FALSE,
491  TRUE, FALSE, FALSE, FALSE, TRUE) );
492 
493  /* store the pointer to the new constraint in the origbranch constraint of the parent node */
494  if( parentcons != NULL )
495  {
496  SCIP_CONSDATA* parentdata;
497 
498  parentdata = SCIPconsGetData(parentcons);
499  assert(parentdata != NULL);
500 
501  if( SCIPinProbing(scip) )
502  {
503  parentdata->probingtmpcons = *cons;
504  }
505  else
506  {
507  int newsize;
508  ++parentdata->nchildconss;
509  newsize = SCIPcalcMemGrowSize(scip, parentdata->nchildconss);
510  if( parentdata->nchildconss == 1 )
511  {
512  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(parentdata->childconss), newsize) );
513  parentdata->childconss[0] = NULL;
514  }
515  else
516  {
517  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(parentdata->childconss), parentdata->maxchildconss, newsize) );
518  parentdata->childconss[parentdata->nchildconss - 1] = NULL;
519  }
520  parentdata->maxchildconss = newsize;
521  parentdata->childconss[parentdata->nchildconss-1] = *cons;
522  }
523  }
524 
525  return SCIP_OKAY;
526 }
527 
528 /** returns the branch orig constraint of the current node, only needs the pointer to scip */
530  SCIP* scip /**< SCIP data structure */
531  )
532 {
533  SCIP_CONSHDLR* conshdlr;
534  SCIP_CONSHDLRDATA* conshdlrData;
535 
536  assert(scip != NULL);
537  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
538  assert(conshdlr != NULL);
539 
540  conshdlrData = SCIPconshdlrGetData(conshdlr);
541  assert(conshdlrData != NULL);
542  assert(conshdlrData->stack != NULL);
543  assert(conshdlrData->nstack > 0);
544 
545  return conshdlrData->stack[conshdlrData->nstack-1];
546 }
547 
548 /** returns the stack and the number of elements on it */
550  SCIP* scip, /**< SCIP data structure */
551  SCIP_CONS*** stack, /**< return value: pointer to the stack */
552  int* nstackelements /**< return value: pointer to int, for number of elements on the stack */
553  )
554 {
555  SCIP_CONSHDLR* conshdlr;
556  SCIP_CONSHDLRDATA* conshdlrData;
557 
558  assert(scip != NULL);
559  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
560  assert(conshdlr != NULL);
561 
562  conshdlrData = SCIPconshdlrGetData(conshdlr);
563  assert(conshdlrData != NULL);
564  assert(conshdlrData->stack != NULL);
565 
566  *stack = conshdlrData->stack;
567  *nstackelements = conshdlrData->nstack;
568 }
569 
570 /** returns the branching data for a given origbranch constraint */
572  SCIP_CONS* cons, /**< origbranch constraint for which the branching data is requested */
573  GCG_BRANCHDATA* branchdata /**< branching data */
574  )
575 {
576  SCIP_CONSDATA* consdata;
577 
578  consdata = SCIPconsGetData(cons);
579  assert(consdata != NULL);
580 
581  consdata->branchdata = branchdata;
582 }
583 
584 /** returns the branching data for a given origbranch constraint */
586  SCIP_CONS* cons /**< origbranch constraint for which the branching data is requested */
587  )
588 {
589  SCIP_CONSDATA* consdata;
590 
591  consdata = SCIPconsGetData(cons);
592  assert(consdata != NULL);
593 
594  return consdata->branchdata;
595 }
596 
597 /** returns the branching rule for a given origbranch constraint */
599  SCIP_CONS* cons /**< origbranch constraint for which the branchrule is requested */
600  )
601 {
602  SCIP_CONSDATA* consdata;
603  assert(cons != NULL);
604 
605  consdata = SCIPconsGetData(cons);
606  assert(consdata != NULL);
607 
608  return consdata->branchrule;
609 }
610 
611 /** returns the node in the B&B tree at which the given origbranch constraint is sticking */
613  SCIP_CONS* cons /**< origbranch constraint for which the corresponding node is requested */
614  )
615 {
616  SCIP_CONSDATA* consdata;
617  assert(cons != NULL);
618 
619  consdata = SCIPconsGetData(cons);
620  assert(consdata != NULL);
621 
622  return consdata->node;
623 }
624 
625 /** returns the origbranch constraint of the B&B father of the node at which the
626  * given origbranch constraint is sticking
627  */
629  SCIP_CONS* cons /**< origbranch constraint for which the origbranch constraint of
630  * the father node is requested */
631  )
632 {
633  SCIP_CONSDATA* consdata;
634  assert(cons != NULL);
635 
636  consdata = SCIPconsGetData(cons);
637  assert(consdata != NULL);
638 
639  return consdata->parentcons;
640 }
641 
642 /** returns the number of origbranch constraints of the children of the node at which the
643  * given origbranch constraint is sticking
644  */
646  SCIP_CONS* cons /**< constraint */
647  )
648 {
649  SCIP_CONSDATA* consdata;
650 
651  consdata = SCIPconsGetData(cons);
652  assert(consdata != NULL);
653 
654  return consdata->nchildconss;
655 }
656 
657 /** returns an origbranch constraint of a child of the node at which the
658  * given origbranch constraint is sticking
659  */
661  SCIP_CONS* cons, /**< constraint */
662  int childnr /**< number of child */
663  )
664 {
665  SCIP_CONSDATA* consdata;
666 
667  consdata = SCIPconsGetData(cons);
668  assert(consdata != NULL);
669  assert(consdata->childconss != NULL);
670  assert(consdata->nchildconss > childnr);
671 
672  return consdata->childconss[childnr];
673 }
674 
675 /** sets the masterbranch constraint of the node in the master program corresponding to the node
676  * at which the given origbranchbranch constraint is sticking
677  */
679  SCIP_CONS* cons, /**< origbranch constraint for which the masterbranch constraint should be set */
680  SCIP_CONS* mastercons /**< masterbranch constraint corresponding to the given origbranch constraint */
681  )
682 {
683  SCIP_CONSDATA* consdata;
684  assert(cons != NULL);
685 
686  consdata = SCIPconsGetData(cons);
687  assert(consdata != NULL);
688 
689  consdata->mastercons = mastercons;
690 }
691 
692 /** returns the masterbranch constraint of the node in the master program corresponding to the node
693  * at which the given origbranchbranch constraint is sticking
694  */
696  SCIP_CONS* cons /**< origbranch constraint for which the corresponding masterbranch
697  * constraint is requested */
698  )
699 {
700  SCIP_CONSDATA* consdata;
701  assert(cons != NULL);
702 
703  consdata = SCIPconsGetData(cons);
704  assert(consdata != NULL);
705 
706  return consdata->mastercons;
707 }
708 
709 /** adds initial constraint to root node */
711  SCIP* scip /**< SCIP data structure */
712  )
713 {
714  SCIP_CONSHDLR* conshdlr;
715  SCIP_CONSHDLRDATA* conshdlrdata;
716  SCIP_CONS* cons;
717  SCIP_CONS** conss;
718  int nconss;
719  int i;
720 
721  assert(scip != NULL);
722 
723  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
724  assert(conshdlr != NULL);
725 
726  nconss = SCIPconshdlrGetNConss(conshdlr);
727  assert(nconss <= 1);
728  conss = SCIPconshdlrGetConss(conshdlr);
729  for( i = 0; i < nconss; ++i )
730  {
731  SCIP_CALL( SCIPdelCons(scip, conss[i]) );
732  }
733 
734  conshdlrdata = SCIPconshdlrGetData(conshdlr);
735  assert(conshdlrdata != NULL);
736  assert(SCIPconshdlrGetNConss(conshdlr) == 0);
737  if( conshdlrdata->rootcons == NULL )
738  {
739  SCIP_CALL( GCGcreateConsOrigbranch(scip, &cons, "root-origbranch", NULL, NULL, NULL, NULL) );
740  SCIP_CALL( SCIPaddConsNode(scip, SCIPgetRootNode(scip), cons, SCIPgetRootNode(scip)) );
741  conshdlrdata->rootcons = cons;
742  }
743 
744  /* check consistency */
746 
747  return SCIP_OKAY;
748 }
749 
750 /** checks the consistency of the origbranch constraints in the problem */
752  SCIP* scip /**< SCIP data structure */
753  )
754 {
755 #ifdef CHECKCONSISTENCY
756 
757  SCIP_CONSHDLR* conshdlr;
758 
759 #ifndef NDEBUG
760  SCIP_CONS** conss;
761  int nconss;
762  int i;
763 #endif
764 
765  assert(scip != NULL);
766  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
767  if( conshdlr == NULL )
768  {
769  SCIPerrorMessage("origbranch constraint handler not found\n");
770  return;
771  }
772 #ifndef NDEBUG
773  conss = SCIPconshdlrGetConss(conshdlr);
774  nconss = SCIPconshdlrGetNConss(conshdlr);
775 
776  for( i = 0; i < nconss; i++ )
777  {
778  SCIP_CONSDATA* consdata = SCIPconsGetData(conss[i]);
779  assert(consdata != NULL);
780  assert(consdata->node != NULL);
781  assert((consdata->parentcons == NULL) == (SCIPnodeGetDepth(consdata->node) == 0));
782  /** todo assertions for all nchildcons */
783  if( consdata->nchildconss == 2 )
784  assert(consdata->parentcons == NULL || SCIPconsGetData(consdata->parentcons)->childconss[0] == conss[i]
785  || SCIPconsGetData(consdata->parentcons)->childconss[1] == conss[i]
786  || ( SCIPinProbing(scip) && SCIPconsGetData(consdata->parentcons)->probingtmpcons == conss[i]));
787  if( consdata->nchildconss == 2 )
788  assert(consdata->childconss[0] == NULL || SCIPconsGetData(consdata->childconss[0])->parentcons == conss[i]);
789  if( consdata->nchildconss == 2 )
790  assert(consdata->childconss[1] == NULL || SCIPconsGetData(consdata->childconss[1])->parentcons == conss[i]);
791  assert(consdata->probingtmpcons == NULL || SCIPinProbing(scip));
792  assert(consdata->probingtmpcons == NULL || SCIPconsGetData(consdata->probingtmpcons)->parentcons == conss[i]);
793  assert(consdata->mastercons == NULL || GCGconsMasterbranchGetOrigcons(consdata->mastercons) == conss[i]);
794  }
795 #endif
796 #endif
797 }
SCIP_NODE * GCGconsOrigbranchGetNode(SCIP_CONS *cons)
GCG interface methods.
GCG_BRANCHDATA * GCGconsOrigbranchGetBranchdata(SCIP_CONS *cons)
void GCGconsOrigbranchCheckConsistency(SCIP *scip)
static SCIP_DECL_CONSENFOPS(consEnfopsOrigbranch)
SCIP_CONS * GCGconsMasterbranchGetOrigcons(SCIP_CONS *cons)
void GCGconsMasterbranchSetOrigcons(SCIP_CONS *cons, SCIP_CONS *origcons)
SCIP_RETCODE SCIPincludeConshdlrOrigbranch(SCIP *scip)
#define CONSHDLR_ENFOPRIORITY
SCIP_CONS * mastercons
SCIP_CONS * parentcons
SCIP_CONS * GCGconsOrigbranchGetChildcons(SCIP_CONS *cons, int childnr)
static SCIP_DECL_CONSACTIVE(consActiveOrigbranch)
void GCGconsOrigbranchSetMastercons(SCIP_CONS *cons, SCIP_CONS *mastercons)
static SCIP_DECL_CONSLOCK(consLockOrigbranch)
SCIP_RETCODE GCGbranchGenericCreateBranchdata(SCIP *scip, GCG_BRANCHDATA **branchdata)
SCIP_CONS * GCGconsOrigbranchGetActiveCons(SCIP *scip)
SCIP_RETCODE GCGconsOrigbranchAddRootCons(SCIP *scip)
SCIP_CONS * rootcons
SCIP_BRANCHRULE * GCGconsOrigbranchGetBranchrule(SCIP_CONS *cons)
constraint handler for storing the branching decisions at each node of the tree
static SCIP_DECL_CONSENFOLP(consEnfolpOrigbranch)
int GCGconsOrigbranchGetNChildconss(SCIP_CONS *cons)
branching rule based on vanderbeck's generic branching scheme
constraint handler for storing the branching decisions at each node of the tree
#define CONSHDLR_DESC
SCIP_CONS * probingtmpcons
SCIP_CONS ** childconss
SCIP_CONS * GCGconsOrigbranchGetParentcons(SCIP_CONS *cons)
static SCIP_DECL_CONSINITSOL(consInitsolOrigbranch)
static SCIP_DECL_CONSEXIT(consExitOrigbranch)
static SCIP_DECL_CONSDELETE(consDeleteOrigbranch)
void GCGconsOrigbranchSetBranchdata(SCIP_CONS *cons, GCG_BRANCHDATA *branchdata)
static SCIP_DECL_CONSDEACTIVE(consDeactiveOrigbranch)
void GCGconsOrigbranchGetStack(SCIP *scip, SCIP_CONS ***stack, int *nstackelements)
SCIP_RETCODE GCGcreateConsOrigbranch(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_NODE *node, SCIP_CONS *parentcons, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata)
static SCIP_DECL_CONSEXITSOL(consExitsolOrigbranch)
static SCIP_DECL_CONSENFORELAX(consEnforeOrigbranch)
#define CONSHDLR_NAME
GCG_BRANCHDATA * branchdata
SCIP_BRANCHRULE * branchrule
SCIP_NODE * node
#define CONSHDLR_NEEDSCONS
#define CONSHDLR_EAGERFREQ
SCIP_CONS * GCGconsOrigbranchGetMastercons(SCIP_CONS *cons)
static SCIP_DECL_CONSCHECK(consCheckOrigbranch)
static SCIP_DECL_CONSFREE(consFreeOrigbranch)
#define CONSHDLR_CHECKPRIORITY