Scippy

GCG

Branch-and-Price & Column Generation for Everyone

branch_generic.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 branch_generic.c
29  * @ingroup BRANCHINGRULES
30  * @brief branching rule based on vanderbeck's generic branching scheme
31  * @author Marcel Schmickerath
32  * @author Martin Bergner
33  * @author Jonas Witt
34  */
35 
36 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37 
38 /*#define SCIP_DEBUG*/
39 
40 #include "branch_generic.h"
41 #include "relax_gcg.h"
42 #include "cons_masterbranch.h"
43 #include "cons_origbranch.h"
44 #include "pricer_gcg.h"
45 #include "scip/cons_linear.h"
46 #include "type_branchgcg.h"
47 #include "gcg.h"
48 #include "cons_integralorig.h"
49 #include "gcgsort.h"
50 
51 #include "scip/nodesel_bfs.h"
52 #include "scip/nodesel_dfs.h"
53 #include "scip/nodesel_estimate.h"
54 #include "scip/nodesel_hybridestim.h"
55 #include "scip/nodesel_restartdfs.h"
56 #include "scip/branch_allfullstrong.h"
57 #include "scip/branch_fullstrong.h"
58 #include "scip/branch_inference.h"
59 #include "scip/branch_mostinf.h"
60 #include "scip/branch_leastinf.h"
61 #include "scip/branch_pscost.h"
62 #include "scip/branch_random.h"
63 #include "scip/branch_relpscost.h"
64 
65 #include <assert.h>
66 #include <string.h>
67 
68 
69 #define BRANCHRULE_NAME "generic"
70 #define BRANCHRULE_DESC "generic branching rule by Vanderbeck"
71 #define BRANCHRULE_PRIORITY -100
72 #define BRANCHRULE_MAXDEPTH -1
73 #define BRANCHRULE_MAXBOUNDDIST 1.0
74 
75 
76 #define EVENTHDLR_NAME "genericbranchvaradd"
77 #define EVENTHDLR_DESC "event handler for adding a new generated mastervar into the right branching constraints by using Vanderbecks generic branching scheme"
78 
79 /** branching data */
80 struct GCG_BranchData
81 {
82  GCG_COMPSEQUENCE** C; /**< S[k] bound sequence for block k */ /* !!! sort of each C[i] = S is important !!! */
83  SCIP_Real lhs; /**< lefthandside of the constraint corresponding to the bound sequence C */
84  SCIP_CONS* mastercons; /**< constraint enforcing the branching restriction in the master problem */
85  GCG_COMPSEQUENCE* consS; /**< component bound sequence which induce the current branching constraint */
86  int consSsize; /**< size of the component bound sequence */
87  int maxconsS; /**< size of consS */
88  int consblocknr; /**< id of the pricing problem (or block) to which this branching constraint belongs */
89  int nvars; /**< number of master variables the last time the node has been visited */
90 };
91 
92 /** set of component bounds in separate */
93 struct GCG_Record
94 {
95  GCG_COMPSEQUENCE** record; /**< array of component bound sequences in record */
96  int recordsize; /**< number of component bound sequences in record */
97  int recordcapacity; /**< capacity of record */
98  int* sequencesizes; /**< array of sizes of component bound sequences */
99  int* capacities; /**< array of capacities of component bound sequences */
100 };
101 typedef struct GCG_Record GCG_RECORD;
102 
103 /*
104  * Callback methods
105  */
106 
107 /* define not used callback as NULL*/
108 #define branchFreeGeneric NULL
109 #define branchExitGeneric NULL
110 #define branchInitsolGeneric NULL
111 #define branchExitsolGeneric NULL
112 
113 
114 /** computes the generator of mastervar for the entry in origvar
115  * @return entry of the generator corresponding to origvar */
116 static
118  SCIP_VAR* mastervar, /**< current mastervariable */
119  SCIP_VAR* origvar /**< corresponding origvar */
120  )
121 {
122  int i;
123  SCIP_VAR** origvars;
124  SCIP_Real* origvals;
125  int norigvars;
126 
127  assert(mastervar != NULL);
128  assert(origvar != NULL);
129 
130  origvars = GCGmasterVarGetOrigvars(mastervar);
131  norigvars = GCGmasterVarGetNOrigvars(mastervar);
132  origvals = GCGmasterVarGetOrigvals(mastervar);
133 
134  for( i = 0; i < norigvars; ++i )
135  {
136  if( origvars[i] == origvar )
137  {
138  return origvals[i];
139  }
140  }
141 
142  return 0.0;
143 }
144 
145 /** adds a variable to a branching constraint */
146 static
147 SCIP_RETCODE addVarToMasterbranch(
148  SCIP* scip, /**< SCIP data structure */
149  SCIP_VAR* mastervar, /**< the variable to add */
150  GCG_BRANCHDATA* branchdata, /**< branching data structure where the variable should be added */
151  SCIP_Bool* added /**< whether the variable was added */
152 )
153 {
154  int p;
155 
156  SCIP_Bool varinS = TRUE;
157 
158  assert(scip != NULL);
159  assert(mastervar != NULL);
160  assert(branchdata != NULL);
161  assert(added != NULL);
162 
163  *added = FALSE;
164 
165  if( GCGvarGetBlock(mastervar) == -1 || GCGbranchGenericBranchdataGetConsblocknr(branchdata) == -3 || !GCGisMasterVarInBlock(mastervar, GCGbranchGenericBranchdataGetConsblocknr(branchdata)) )
166  return SCIP_OKAY;
167 
168  SCIPdebugMessage("consSsize = %d\n", GCGbranchGenericBranchdataGetConsSsize(branchdata));
169 
170  for( p = 0; p < GCGbranchGenericBranchdataGetConsSsize(branchdata); ++p )
171  {
172  SCIP_Real generatorentry;
173 
174  generatorentry = getGeneratorEntry(mastervar, GCGbranchGenericBranchdataGetConsS(branchdata)[p].component);
175 
176  if( GCGbranchGenericBranchdataGetConsS(branchdata)[p].sense == GCG_COMPSENSE_GE )
177  {
178  if( SCIPisLT(scip, generatorentry, GCGbranchGenericBranchdataGetConsS(branchdata)[p].bound) )
179  {
180  varinS = FALSE;
181  break;
182  }
183  }
184  else
185  {
186  if( SCIPisGE(scip, generatorentry, GCGbranchGenericBranchdataGetConsS(branchdata)[p].bound) )
187  {
188  varinS = FALSE;
189  break;
190  }
191  }
192  }
193 
194  if( varinS )
195  {
196  SCIPdebugMessage("mastervar is added\n");
197  SCIP_CALL( SCIPaddCoefLinear(scip, GCGbranchGenericBranchdataGetMastercons(branchdata), mastervar, 1.0) );
198  *added = TRUE;
199  }
200 
201  return SCIP_OKAY;
202 }
203 
204 /** creates the constraint for branching directly on a master variable */
205 static
207  SCIP* scip, /**< SCIP data structure */
208  SCIP_NODE* node, /**< node to add constraint */
209  GCG_BRANCHDATA* branchdata /**< branching data structure */
210 )
211 {
212  char name[SCIP_MAXSTRLEN];
213 
214  assert(scip != NULL);
215  assert(node != NULL);
216  assert(branchdata->consblocknr == -3);
217  assert(branchdata->consSsize == 1);
218 
219  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "directchild(%d, %g) sense = %d", branchdata->consSsize, branchdata->consS[0].bound, branchdata->consS[0].sense);
220 
221  /* create constraint for child */
222  if( branchdata->consS[0].sense == GCG_COMPSENSE_GE )
223  {
224  SCIP_CALL( SCIPcreateConsLinear(scip, &(branchdata->mastercons), name, 0, NULL, NULL, branchdata->consS[0].bound, SCIPinfinity(scip), TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE) );
225  } else
226  {
227  SCIP_CALL( SCIPcreateConsLinear(scip, &(branchdata->mastercons), name, 0, NULL, NULL, -SCIPinfinity(scip), branchdata->consS[0].bound-1, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE) );
228  }
229  assert(GCGvarIsMaster(branchdata->consS[0].component));
230  SCIP_CALL( SCIPaddCoefLinear(scip, branchdata->mastercons, branchdata->consS[0].component, 1.0) );
231 
232  /* add constraint to the master problem that enforces the branching decision */
233  SCIP_CALL( SCIPaddConsNode(scip, node, branchdata->mastercons, NULL) );
234 
235  return SCIP_OKAY;
236 }
237 
238 /** creates the constraint for branching directly on a master variable */
239 static
240 SCIP_RETCODE createBranchingCons(
241  SCIP* scip, /**< SCIP data structure */
242  SCIP_NODE* node, /**< node to add constraint */
243  GCG_BRANCHDATA* branchdata /**< branching data structure */
244 )
245 {
246  char name[SCIP_MAXSTRLEN];
247 
248  assert(scip != NULL);
249  assert(node != NULL);
250  assert(branchdata != NULL);
251 
252  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "child(%d, %g)", branchdata->consSsize, branchdata->lhs);
253 
254  assert(branchdata->mastercons == NULL);
255 
256  /* create constraint for child */
257  SCIP_CALL( SCIPcreateConsLinear(scip, &(branchdata->mastercons), name, 0, NULL, NULL,
258  branchdata->lhs, SCIPinfinity(scip), TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE) );
259 
260  SCIP_CALL( SCIPaddConsNode(scip, node, branchdata->mastercons, NULL) );
261 
262  return SCIP_OKAY;
263 }
264 /** solving process initialization method of event handler (called when branch and bound process is about to begin) */
265 static
266 SCIP_DECL_EVENTINITSOL(eventInitsolGenericbranchvaradd)
267 { /*lint --e{715}*/
268  assert(scip != NULL);
269  assert(eventhdlr != NULL);
270  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
271 
272  /* notify SCIP that your event handler wants to react on the event type */
273  SCIP_CALL( SCIPcatchEvent( scip, SCIP_EVENTTYPE_VARADDED, eventhdlr, NULL, NULL) );
274 
275  return SCIP_OKAY;
276 }
277 
278 /** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
279 static
280 SCIP_DECL_EVENTEXITSOL(eventExitsolGenericbranchvaradd)
281 { /*lint --e{715}*/
282  assert(scip != NULL);
283  assert(eventhdlr != NULL);
284  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
285 
286  /* notify SCIP that your event handler wants to drop the event type */
287  SCIP_CALL( SCIPdropEvent( scip, SCIP_EVENTTYPE_VARADDED, eventhdlr, NULL, -1) );
288 
289  return SCIP_OKAY;
290 }
291 
292 /** execution method of event handler */
293 static
294 SCIP_DECL_EVENTEXEC(eventExecGenericbranchvaradd)
295 { /*lint --e{715}*/
296  SCIP* origscip;
297  SCIP_CONS* masterbranchcons;
298  SCIP_CONS* parentcons;
299  SCIP_VAR* mastervar;
300  SCIP_VAR** allorigvars;
301  SCIP_VAR** mastervars;
302  GCG_BRANCHDATA* branchdata;
303  int allnorigvars;
304  int nmastervars;
305 
306  assert(eventhdlr != NULL);
307  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
308  assert(event != NULL);
309  assert(scip != NULL);
310  assert(SCIPeventGetType(event) == SCIP_EVENTTYPE_VARADDED);
311 
312  mastervar = SCIPeventGetVar(event);
313  if( !GCGvarIsMaster(mastervar) )
314  return SCIP_OKAY;
315 
316  origscip = GCGmasterGetOrigprob(scip);
317  assert(origscip != NULL);
318 
319  /* SCIPdebugMessage("exec method of event_genericbranchvaradd\n"); */
320 
321  masterbranchcons = GCGconsMasterbranchGetActiveCons(scip);
322  assert(masterbranchcons != NULL);
323 
324  /* if branch rule is not generic, abort */
326  return SCIP_OKAY;
327 
328  SCIP_CALL( SCIPgetVarsData(origscip, &allorigvars, &allnorigvars, NULL, NULL, NULL, NULL) );
329  SCIP_CALL( SCIPgetVarsData(scip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
330 
331  parentcons = masterbranchcons;
332  branchdata = GCGconsMasterbranchGetBranchdata(parentcons);
333 
334 
335  if( GCGvarIsMaster(mastervar) && GCGconsMasterbranchGetBranchrule(parentcons) != NULL )
336  {
337  SCIP_Bool added = FALSE;
338  SCIPdebugMessage("Mastervar <%s>\n", SCIPvarGetName(mastervar));
339  while( parentcons != NULL && branchdata != NULL
340  && GCGbranchGenericBranchdataGetConsS(branchdata) != NULL && GCGbranchGenericBranchdataGetConsSsize(branchdata) > 0 )
341  {
342  if( GCGconsMasterbranchGetBranchrule(parentcons) == NULL || strcmp(SCIPbranchruleGetName(GCGconsMasterbranchGetBranchrule(parentcons)), "generic") != 0 )
343  break;
344 
345  assert(branchdata != NULL);
346 
347 
348  if( (GCGbranchGenericBranchdataGetConsblocknr(branchdata) != GCGvarGetBlock(mastervar) && GCGvarGetBlock(mastervar) != -1 )
349  || (GCGvarGetBlock(mastervar) == -1 && !GCGmasterVarIsLinking(mastervar)) )
350  {
351  parentcons = GCGconsMasterbranchGetParentcons(parentcons);
352 
353  if( parentcons != NULL )
354  branchdata = GCGconsMasterbranchGetBranchdata(parentcons);
355 
356  continue;
357  }
358 
359  SCIP_CALL( addVarToMasterbranch(scip, mastervar, branchdata, &added) );
360 
361  parentcons = GCGconsMasterbranchGetParentcons(parentcons);
362  branchdata = GCGconsMasterbranchGetBranchdata(parentcons);
363  }
364  }
365 
366  return SCIP_OKAY;
367 }
368 
369 
370 /*
371  * branching specific interface methods
372  */
373 
374 /** method for initializing the set of respected indices */
375 static
376 SCIP_RETCODE InitIndexSet(
377  SCIP* scip, /**< SCIP data structure */
378  SCIP_VAR** F, /**< array of fractional mastervars */
379  int Fsize, /**< number of fractional mastervars */
380  SCIP_VAR*** IndexSet, /**< set to initialize */
381  int* IndexSetSize /**< size of the index set */
382  )
383 {
384  int i;
385 
386  assert( scip != NULL);
387  assert( F != NULL);
388  assert( Fsize > 0);
389  assert( IndexSet != NULL);
390  assert( IndexSetSize != NULL);
391 
392  *IndexSet = NULL;
393  *IndexSetSize = 0;
394 
395 
396  for( i = 0; i < Fsize; ++i )
397  {
398  int j;
399  SCIP_VAR** origvars = GCGmasterVarGetOrigvars(F[i]);
400  int norigvars = GCGmasterVarGetNOrigvars(F[i]);
401 
402  if( *IndexSetSize == 0 && norigvars > 0 )
403  {
404  /* TODO: allocate memory for norigvars although there might be slots for continuous variables which are not needed? */
405  SCIP_CALL( SCIPallocBufferArray(scip, IndexSet, 1) );
406  for( j = 0; j < norigvars; ++j )
407  {
408  if( SCIPvarGetType(origvars[j]) > SCIP_VARTYPE_INTEGER )
409  continue;
410 
411  if( *IndexSetSize > 0 )
412  SCIP_CALL( SCIPreallocBufferArray(scip, IndexSet, *IndexSetSize + 1) );
413 
414  (*IndexSet)[*IndexSetSize] = origvars[j];
415  ++(*IndexSetSize);
416  }
417  }
418  else
419  {
420  for( j = 0; j < norigvars; ++j )
421  {
422  int k;
423  int oldsize = *IndexSetSize;
424 
425  if( SCIPvarGetType(origvars[j]) > SCIP_VARTYPE_INTEGER )
426  continue;
427 
428  for( k = 0; k < oldsize; ++k )
429  {
430  /* if variable already in union */
431  if( (*IndexSet)[k] == origvars[j] )
432  {
433  break;
434  }
435  if( k == oldsize-1 )
436  {
437  /* add variable to the end */
438  ++(*IndexSetSize);
439  SCIP_CALL( SCIPreallocBufferArray(scip, IndexSet, *IndexSetSize) );
440  (*IndexSet)[*IndexSetSize-1] = origvars[j];
441  }
442  }
443  }
444  }
445  }
446 
447  return SCIP_OKAY;
448 }
449 
450 /** method for calculating the median over all fractional components values using
451  * the quickselect algorithm (or a variant of it)
452  *
453  * This method will change the array
454  *
455  * @return median or if the median is the minimum return ceil(arithm middle)
456  */
457 static
458 SCIP_Real GetMedian(
459  SCIP* scip, /**< SCIP data structure */
460  SCIP_Real* array, /**< array to find the median in (will be destroyed) */
461  int arraysize, /**< size of the array */
462  SCIP_Real min /**< minimum of array */
463  )
464 {
465  SCIP_Real Median;
466  SCIP_Real swap;
467  int l;
468  int r;
469  int i;
470  int MedianIndex;
471  SCIP_Real arithmMiddle;
472 
473  assert(scip != NULL);
474  assert(array != NULL);
475  assert(arraysize > 0);
476 
477  r = arraysize -1;
478  l = 0;
479  arithmMiddle = 0;
480 
481  if( arraysize & 1 )
482  MedianIndex = arraysize/2;
483  else
484  MedianIndex = arraysize/2 -1;
485 
486  while( l < r-1 )
487  {
488  int j = r;
489  Median = array[MedianIndex];
490  i = l;
491 
492  do
493  {
494  while( SCIPisLT(scip, array[i], Median) )
495  ++i;
496  while( SCIPisGT(scip, array[j], Median) )
497  --j;
498  if( i <=j )
499  {
500  swap = array[i];
501  array[i] = array[j];
502  array[j] = swap;
503  ++i;
504  --j;
505  }
506  } while( i <=j );
507  if( j < MedianIndex )
508  l = i;
509  if( i > MedianIndex )
510  r = j;
511  }
512  Median = array[MedianIndex];
513 
514  if( SCIPisEQ(scip, Median, min) )
515  {
516  for( i=0; i<arraysize; ++i )
517  arithmMiddle += 1.0*array[i]/arraysize;
518 
519  Median = SCIPceil(scip, arithmMiddle);
520  }
521 
522  return Median;
523 }
524 
525 /** comparefunction for lexicographical sort */
526 static
528 {
529  SCIP* origprob = (SCIP *) userdata;
530  GCG_STRIP* strip1;
531  GCG_STRIP* strip2;
532  SCIP_VAR* mastervar1;
533  SCIP_VAR* mastervar2;
534  SCIP_VAR** origvars;
535  int norigvars;
536  int i;
537 
538  strip1 = (GCG_STRIP*) elem1;
539  strip2 = (GCG_STRIP*) elem2;
540 
541  mastervar1 = strip1->mastervar;
542  mastervar2 = strip2->mastervar;
543 
544  assert(mastervar1 != NULL);
545  assert(mastervar2 != NULL);
546 
547  if( GCGvarGetBlock(mastervar1) == -1 )
548  {
549  SCIPdebugMessage("linkingvar\n");
550  assert(GCGmasterVarIsLinking(mastervar1));
551  }
552  if( GCGvarGetBlock(mastervar2) == -1 )
553  {
554  SCIPdebugMessage("linkingvar\n");
555  assert(GCGmasterVarIsLinking(mastervar2));
556  }
557 
558  origvars = SCIPgetVars(origprob);
559  norigvars = SCIPgetNVars(origprob);
560 
561  for( i = 0; i < norigvars; ++i )
562  {
563  if( SCIPvarGetType(origvars[i]) > SCIP_VARTYPE_INTEGER )
564  continue;
565 
566  if( SCIPisFeasGT(origprob, getGeneratorEntry(mastervar1, origvars[i]), getGeneratorEntry(mastervar2, origvars[i])) )
567  return -1;
568 
569  if( SCIPisFeasLT(origprob, getGeneratorEntry(mastervar1, origvars[i]), getGeneratorEntry(mastervar2, origvars[i])) )
570  return 1;
571  }
572 
573  return 0;
574 }
575 
576 /** lexicographical sort using scipsort
577  * This method will change the array
578  */
579 static
580 SCIP_RETCODE LexicographicSort(
581  SCIP* scip, /**< SCIP data structure */
582  GCG_STRIP** array, /**< array to sort (will be changed) */
583  int arraysize /**< size of the array */
584  )
585 {
586 
587  assert(array != NULL);
588  assert(arraysize > 0);
589 
590  SCIPdebugMessage("Lexicographic sorting\n");
591 
592  GCGsortPtr((void**)array, ptrcomp, scip, arraysize );
593 
594  return SCIP_OKAY;
595 }
596 
597 
598 /** compare function for ILO: returns 1 if bd1 < bd2 else -1 with respect to bound sequence */
599 static
601  SCIP* scip, /**< SCIP data structure */
602  SCIP_VAR* mastervar1, /**< first strip */
603  SCIP_VAR* mastervar2, /**< second strip */
604  GCG_COMPSEQUENCE** C, /**< component bound sequence to compare with */
605  int NBoundsequences, /**< size of the bound sequence */
606  int* sequencesizes, /**< sizes of the bound sequences */
607  int p /**< current depth in C*/
608  )
609 {
610  SCIP_Real ivalue;
611  int j;
612  int k;
613  int Nupper;
614  int Nlower;
615  int returnvalue;
616  GCG_COMPSEQUENCE** CopyC;
617  SCIP_VAR* origvar;
618  int* newsequencesizes;
619  GCG_STRIP* strip1;
620  GCG_STRIP* strip2;
621 
622  k = 0;
623  Nupper = 0;
624  Nlower = 0;
625  newsequencesizes = NULL;
626  strip1 = NULL;
627  strip2 = NULL;
628 
629  /* lexicographic Order? */
630  if( C == NULL || NBoundsequences <= 1 )
631  {
632  SCIP_CALL_ABORT( SCIPallocBuffer(scip, &strip1) );
633  SCIP_CALL_ABORT( SCIPallocBuffer(scip, &strip2) );
634 
635  strip1->scip = scip;
636  strip2->scip = scip;
637  strip1->C = NULL;
638  strip2->C = NULL;
639  strip1->Csize = 0;
640  strip2->Csize = 0;
641  strip1->sequencesizes = NULL;
642  strip2->sequencesizes = NULL;
643  strip1->mastervar = mastervar1;
644  strip2->mastervar = mastervar2;
645 
646  returnvalue = (*ptrcomp)(scip, strip1, strip2);
647 
648  SCIPfreeBuffer(scip, &strip1);
649  SCIPfreeBuffer(scip, &strip2);
650 
651  return returnvalue;
652  }
653 
654  assert(C != NULL);
655  assert(NBoundsequences > 0);
656 
657  /* find i which is in all S in C on position p */
658  while( sequencesizes[k] < p )
659  {
660  ++k;
661  assert(k < NBoundsequences);
662  }
663  origvar = C[k][p-1].component;
664  assert(origvar != NULL);
665  assert(SCIPvarGetType(origvar) <= SCIP_VARTYPE_INTEGER);
666  ivalue = C[k][p-1].bound;
667 
668  /* calculate subset of C */
669  for( j=0; j< NBoundsequences; ++j )
670  {
671  if( sequencesizes[j] >= p )
672  {
673  assert(C[j][p-1].component == origvar);
674  if( C[j][p-1].sense == GCG_COMPSENSE_GE )
675  ++Nupper;
676  else
677  ++Nlower;
678  }
679  }
680 
681  if( SCIPisGE(scip, getGeneratorEntry(mastervar1, origvar), ivalue) && SCIPisGE(scip, getGeneratorEntry(mastervar2, origvar), ivalue) )
682  {
683  k = 0;
684  SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &CopyC, Nupper) );
685  SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &newsequencesizes, Nupper) );
686  for( j = 0; j < NBoundsequences; ++j )
687  {
688  if( sequencesizes[j] >= p )
689  assert(C[j][p-1].component == origvar);
690 
691  if( sequencesizes[j] >= p && C[j][p-1].sense == GCG_COMPSENSE_GE )
692  {
693  int l;
694  CopyC[k] = NULL;
695  SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &(CopyC[k]), sequencesizes[j]) ); /*lint !e866*/
696  for( l = 0; l < sequencesizes[j]; ++l )
697  {
698  CopyC[k][l] = C[j][l];
699  }
700  newsequencesizes[k] = sequencesizes[j];
701  ++k;
702  }
703  }
704 
705  if( k != Nupper )
706  {
707  SCIPdebugMessage("k = %d, Nupper+1 =%d\n", k, Nupper+1);
708  }
709 
710  if( Nupper != 0 )
711  assert( k == Nupper );
712 
713  returnvalue = ILOcomp(scip, mastervar1, mastervar2, CopyC, Nupper, newsequencesizes, p+1);
714 
715  for( j = Nupper - 1; j >= 0; --j )
716  {
717  SCIPfreeBufferArray(scip, &(CopyC[j]) );
718  }
719  SCIPfreeBufferArray(scip, &newsequencesizes);
720  SCIPfreeBufferArray(scip, &CopyC);
721 
722  return returnvalue;
723  }
724 
725 
726  if( SCIPisLT(scip, getGeneratorEntry(mastervar1, origvar), ivalue) && SCIPisLT(scip, getGeneratorEntry(mastervar2, origvar), ivalue) )
727  {
728  SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &CopyC, Nlower) );
729  SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &newsequencesizes, Nlower) );
730 
731  k = 0;
732  for( j = 0; j < NBoundsequences; ++j )
733  {
734  if( sequencesizes[j] >= p )
735  assert(C[j][p-1].component == origvar);
736 
737  if( sequencesizes[j] >= p && C[j][p-1].sense != GCG_COMPSENSE_GE )
738  {
739  int l;
740  CopyC[k] = NULL;
741  SCIP_CALL_ABORT( SCIPallocBufferArray(scip, &(CopyC[k]), sequencesizes[j]) ); /*lint !e866*/
742  for( l = 0; l < sequencesizes[j]; ++l )
743  {
744  CopyC[k][l] = C[j][l];
745  }
746  newsequencesizes[k] = sequencesizes[j];
747  ++k;
748  }
749  }
750 
751  if( k != Nlower )
752  {
753  SCIPdebugMessage("k = %d, Nlower+1 =%d\n", k, Nlower+1);
754  }
755 
756  if( Nlower != 0 )
757  assert( k == Nlower);
758 
759  returnvalue = ILOcomp( scip, mastervar1, mastervar2, CopyC, Nlower, newsequencesizes, p+1);
760 
761  for( j = Nlower - 1; j >= 0; --j )
762  {
763 
764  SCIPfreeBufferArray(scip, &(CopyC[j]) );
765  }
766  SCIPfreeBufferArray(scip, &newsequencesizes);
767  SCIPfreeBufferArray(scip, &CopyC);
768 
769  return returnvalue;
770  }
771  if( SCIPisGT(scip, getGeneratorEntry(mastervar1, origvar), getGeneratorEntry(mastervar2, origvar)) )
772  return 1;
773  else
774  return -1;
775 }
776 
777 /** comparefunction for induced lexicographical sort */
778 static
780 {
781  GCG_STRIP* strip1;
782  GCG_STRIP* strip2;
783  int returnvalue;
784 
785  strip1 = (GCG_STRIP*) elem1;
786  strip2 = (GCG_STRIP*) elem2;
787 
788  returnvalue = ILOcomp(strip1->scip, strip1->mastervar, strip2->mastervar, strip1->C, strip1->Csize, strip1->sequencesizes, 1);
789 
790  return returnvalue;
791 }
792 
793 /** induced lexicographical sort */
794 static
796  SCIP* scip, /**< SCIP ptr*/
797  GCG_STRIP** array, /**< array of strips to sort in ILO*/
798  int arraysize, /**< size of the array */
799  GCG_COMPSEQUENCE** C, /**< current set o comp bound sequences*/
800  int NBoundsequences, /**< size of C */
801  int* sequencesizes /**< sizes of the sequences in C */
802  )
803 {
804  int i;
805 
806  SCIPdebugMessage("Induced Lexicographic sorting\n");
807 
808  if( NBoundsequences == 0 )
809  return LexicographicSort( scip, array, arraysize );
810  assert( C!= NULL );
811 
812  assert(arraysize > 0);
813  if( arraysize <= 1 )
814  return SCIP_OKAY;
815 
816  assert(array != NULL);
817  for( i = 0; i < arraysize; ++i )
818  {
819  array[i]->scip = scip;
820  array[i]->Csize = NBoundsequences;
821  array[i]->sequencesizes = sequencesizes;
822  array[i]->C = C;
823  }
824 
825  SCIPsortPtr((void**)array, ptrilocomp, arraysize);
826 
827  return SCIP_OKAY;
828 }
829 
830 /** partitions the strip according to the priority */
831 static
832 SCIP_RETCODE partition(
833  SCIP* scip, /**< SCIP data structure */
834  SCIP_VAR** J, /**< array of variables which belong to the discriminating components */
835  int* Jsize, /**< pointer to the number of discriminating components */
836  SCIP_Longint* priority, /**< branching priorities */
837  SCIP_VAR** F, /**< set of fractional solutions satisfying bounds */
838  int Fsize, /**< size of list of fractional solutions satisfying bounds */
839  SCIP_VAR** origvar, /**< pointer to store the variable which belongs to a discriminating component with maximum priority */
840  SCIP_Real* median /**< pointer to store the median of fractional solutions satisfying bounds */
841  )
842 {
843  int j;
844  int l;
845  SCIP_Real min;
846  SCIP_Real* compvalues;
847 
848  do
849  {
850  SCIP_Longint maxPriority = SCIP_LONGINT_MIN;
851  min = SCIPinfinity(scip);
852 
853  /* max-min priority */
854  for ( j = 0; j < *Jsize; ++j )
855  {
856  assert(SCIPvarGetType(J[j]) <= SCIP_VARTYPE_INTEGER);
857 
858  if ( priority[j] > maxPriority )
859  {
860  maxPriority = priority[j];
861  *origvar = J[j];
862  }
863  }
864  SCIP_CALL( SCIPallocBufferArray(scip, &compvalues, Fsize) );
865  for ( l = 0; l < Fsize; ++l )
866  {
867  compvalues[l] = getGeneratorEntry(F[l], *origvar);
868  if ( SCIPisLT(scip, compvalues[l], min) )
869  min = compvalues[l];
870  }
871  *median = GetMedian(scip, compvalues, Fsize, min);
872  SCIPfreeBufferArray(scip, &compvalues);
873 
874  assert(!SCIPisInfinity(scip, min));
875 
876  if ( !SCIPisEQ(scip, *median, 0.0) )
877  {
878  SCIPdebugMessage("median = %g\n", *median);
879  SCIPdebugMessage("min = %g\n", min);
880  SCIPdebugMessage("Jsize = %d\n", *Jsize);
881  }
882 
883  if ( SCIPisEQ(scip, *median, min) )
884  {
885  /* here with max-min priority */
886  for ( j = 0; j < *Jsize; ++j )
887  {
888  if ( *origvar == J[j] )
889  {
890  assert(priority[j] == 0);
891  J[j] = J[*Jsize - 1];
892  priority[j] = priority[*Jsize - 1];
893  break;
894  }
895  }
896  if( j < *Jsize )
897  *Jsize = *Jsize-1;
898  }
899  assert(*Jsize >= 0);
900 
901  }while ( SCIPisEQ(scip, *median, min) && *Jsize > 0);
902 
903  return SCIP_OKAY;
904 }
905 
906 /** add identified sequence to record */
907 static
908 SCIP_RETCODE addToRecord(
909  SCIP* scip, /**< SCIP data structure */
910  GCG_RECORD* record, /**< record of identified sequences */
911  GCG_COMPSEQUENCE* S, /**< bound restriction sequence */
912  int Ssize /**< size of bound restriction sequence */
913 )
914 {
915  int i;
916 
917  SCIPdebugMessage("recordsize=%d, Ssize=%d\n", record->recordsize, Ssize);
918 
919  if(record->recordcapacity < record->recordsize + 1)
920  {
921  i = SCIPcalcMemGrowSize(scip, record->recordsize + 1);
922  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(record->record), record->recordcapacity, i) );
923  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(record->sequencesizes), record->recordcapacity, i) );
924  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(record->capacities), record->recordcapacity, i) );
925  record->recordcapacity = i;
926  }
927 
928  i = SCIPcalcMemGrowSize(scip, Ssize);
929  record->capacities[record->recordsize] = i;
930  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(record->record[record->recordsize]), i) ); /*lint !e866*/
931  for( i=0; i<Ssize;++i )
932  {
933  record->record[record->recordsize][i].component = S[i].component;
934  record->record[record->recordsize][i].sense = S[i].sense;
935  record->record[record->recordsize][i].bound = S[i].bound;
936  }
937 
938  record->sequencesizes[record->recordsize] = Ssize; /* +1 ? */
939 
940  record->recordsize++;
941 
942  return SCIP_OKAY;
943 }
944 
945 
946 /** separation at the root node */
947 static
948 SCIP_RETCODE Separate(
949  SCIP* scip, /**< SCIP data structure */
950  SCIP_VAR** F, /**< fractional strips respecting bound restrictions */
951  int Fsize, /**< size of the strips */
952  SCIP_VAR** IndexSet, /**< index set */
953  int IndexSetSize, /**< size of index set */
954  GCG_COMPSEQUENCE* S, /**< ordered set of bound restrictions */
955  int Ssize, /**< size of the ordered set */
956  GCG_RECORD* record /**< identified bound sequences */
957  )
958 {
959  int j;
960  int k;
961  int l;
962  int Jsize;
963  SCIP_VAR** J;
964  SCIP_Real median;
965  int Fupper;
966  int Flower;
967  SCIP_Longint* priority;
968  SCIP_VAR* origvar;
969  SCIP_VAR** copyF;
970  GCG_COMPSEQUENCE* upperLowerS;
971  GCG_COMPSEQUENCE* upperS;
972  SCIP_Real* alpha;
973  SCIP_Real* compvalues;
974  SCIP_Real muF;
975  SCIP_Bool found;
976 
977  assert(scip != NULL);
978  assert((Fsize == 0) == (F == NULL));
979 
980  Jsize = 0;
981  Fupper = 0;
982  Flower = 0;
983  found = FALSE;
984  priority = NULL;
985  compvalues = NULL;
986  J = NULL;
987  origvar = NULL;
988  copyF = NULL;
989  upperLowerS = NULL;
990  upperS = NULL;
991  alpha = NULL;
992 
993  SCIPdebugMessage("Separate with ");
994 
995  /* if there are no fractional columns or potential columns, return */
996  if( Fsize == 0 || IndexSetSize == 0 )
997  {
998  SCIPdebugPrintf("nothing, no fractional columns\n");
999  return SCIP_OKAY;
1000  }
1001 
1002  assert( F != NULL );
1003  assert( IndexSet != NULL );
1004 
1005  muF = 0.0;
1006  for( j = 0; j < Fsize; ++j )
1007  muF += SCIPgetSolVal(GCGgetMasterprob(scip), NULL, F[j]);
1008 
1009  SCIPdebugPrintf("Fsize = %d; Ssize = %d, IndexSetSize = %d, nuF=%.6g \n", Fsize, Ssize, IndexSetSize, muF);
1010 
1011  /* detect fractional alpha_i */
1012  SCIP_CALL( SCIPallocBufferArray(scip, &alpha, IndexSetSize) );
1013 
1014  for( k = 0; k < IndexSetSize; ++k )
1015  {
1016  GCG_COMPSEQUENCE* copyS;
1017  SCIP_Real min;
1018  min = SCIPinfinity(scip);
1019 
1020  origvar = IndexSet[k];
1021  copyS = NULL;
1022  alpha[k] = 0.0;
1023 
1024  if( SCIPvarGetType(origvar) > SCIP_VARTYPE_INTEGER )
1025  continue;
1026 
1027  SCIP_CALL( SCIPallocBufferArray(scip, &compvalues, Fsize) );
1028  for( l=0; l<Fsize; ++l )
1029  {
1030  compvalues[l] = getGeneratorEntry(F[l], origvar);
1031  if( SCIPisLT(scip, compvalues[l], min) )
1032  min = compvalues[l];
1033  }
1034 
1035  median = GetMedian(scip, compvalues, Fsize, min);
1036  SCIPfreeBufferArray(scip, &compvalues);
1037  compvalues = NULL;
1038 
1039  for( j = 0; j < Fsize; ++j )
1040  {
1041  SCIP_Real generatorentry;
1042 
1043  generatorentry = getGeneratorEntry(F[j], origvar);
1044 
1045  if( SCIPisGE(scip, generatorentry, median) )
1046  {
1047  alpha[k] += SCIPgetSolVal(GCGgetMasterprob(scip), NULL, F[j]);
1048  }
1049  }
1050 
1051  if( SCIPisGT(scip, alpha[k], 0.0) && SCIPisLT(scip, alpha[k], muF) )
1052  {
1053  ++Jsize;
1054  }
1055 
1056  if( !SCIPisFeasIntegral(scip, alpha[k]) )
1057  {
1058  SCIPdebugMessage("alpha[%d] = %g\n", k, alpha[k]);
1059  found = TRUE;
1060 
1061  /* ********************************** *
1062  * add the current pair to record *
1063  * ********************************** */
1064 
1065  /* copy S */
1066  SCIP_CALL( SCIPallocBufferArray(scip, &copyS, (size_t)Ssize+1) );
1067 
1068  for( l = 0; l < Ssize; ++l )
1069  {
1070  copyS[l] = S[l];
1071  }
1072 
1073  /* create temporary array to compute median */
1074  SCIP_CALL( SCIPallocBufferArray(scip, &compvalues, Fsize) );
1075 
1076  for( l = 0; l < Fsize; ++l )
1077  {
1078  compvalues[l] = getGeneratorEntry(F[l], origvar);
1079 
1080  if( SCIPisLT(scip, compvalues[l], min) )
1081  min = compvalues[l];
1082  }
1083 
1084  assert( SCIPisEQ(scip, median, GetMedian(scip, compvalues, Fsize, min)));
1085  median = GetMedian(scip, compvalues, Fsize, min);
1086  SCIPfreeBufferArray(scip, &compvalues);
1087  compvalues = NULL;
1088 
1089  SCIPdebugMessage("new median is %g, comp=%s, Ssize=%d\n", median, SCIPvarGetName(origvar), Ssize);
1090 
1091  /* add last bound change to the copy of S */
1092  copyS[Ssize].component = origvar;
1093  copyS[Ssize].sense = GCG_COMPSENSE_GE;
1094  copyS[Ssize].bound = median;
1095 
1096  /* add identified sequence to record */
1097  SCIP_CALL( addToRecord(scip, record, copyS, Ssize+1) );
1098 
1099 
1100  /* ********************************** *
1101  * end adding to record *
1102  * ********************************** */
1103  SCIPfreeBufferArrayNull(scip, &copyS);
1104  }
1105  }
1106 
1107  if( found )
1108  {
1109  SCIPfreeBufferArrayNull(scip, &alpha);
1110 
1111  SCIPdebugMessage("one S found with size %d\n", record->sequencesizes[record->recordsize-1]);
1112 
1113  return SCIP_OKAY;
1114  }
1115 
1116 
1117  /* ********************************** *
1118  * discriminating components *
1119  * ********************************** */
1120 
1121  /** @todo mb: this is a filter */
1122  SCIP_CALL( SCIPallocBufferArray(scip, &J, Jsize) );
1123  j=0;
1124  for( k = 0; k < IndexSetSize; ++k )
1125  {
1126  if( SCIPisGT(scip, alpha[k], 0.0) && SCIPisLT(scip, alpha[k], muF) )
1127  {
1128  J[j] = IndexSet[k];
1129  ++j;
1130  }
1131  }
1132  assert( j == Jsize );
1133 
1134  /* ********************************** *
1135  * compute priority (max-min) *
1136  * ********************************** */
1137 
1138  SCIP_CALL( SCIPallocBufferArray(scip, &priority, Jsize) );
1139 
1140  for( j = 0; j < Jsize; ++j )
1141  {
1142  SCIP_Longint maxcomp;
1143  SCIP_Longint mincomp;
1144 
1145  maxcomp = SCIP_LONGINT_MIN;
1146  mincomp = SCIP_LONGINT_MAX;
1147 
1148  origvar = J[j];
1149 
1150  for( l = 0; l < Fsize; ++l )
1151  {
1152  SCIP_Longint generatorentry;
1153 
1154  assert(SCIPisIntegral(scip, getGeneratorEntry(F[l], origvar)));
1155 
1156  generatorentry = (SCIP_Longint) (getGeneratorEntry(F[l], origvar) + 0.5);
1157 
1158  if( generatorentry > maxcomp )
1159  maxcomp = generatorentry;
1160 
1161  if( generatorentry < mincomp )
1162  mincomp = generatorentry;
1163  }
1164 
1165  priority[j] = maxcomp -mincomp;
1166  }
1167 
1168  SCIP_CALL( partition(scip, J, &Jsize, priority, F, Fsize, &origvar, &median) );
1169 
1170  /* this is a copy of S for the recursive call below */
1171  SCIP_CALL( SCIPallocBufferArray(scip, &upperLowerS, (size_t)Ssize+1) );
1172  SCIP_CALL( SCIPallocBufferArray(scip, &upperS, (size_t)Ssize+1) );
1173 
1174  for( l = 0; l < Ssize; ++l )
1175  {
1176  upperLowerS[l] = S[l];
1177  upperS[l] = S[l];
1178  }
1179 
1180  upperLowerS[Ssize].component = origvar;/* i; */
1181  upperS[Ssize].component = origvar;
1182  upperLowerS[Ssize].sense = GCG_COMPSENSE_LT;
1183  upperS[Ssize].sense = GCG_COMPSENSE_GE;
1184  upperLowerS[Ssize].bound = median;
1185  upperS[Ssize].bound = median;
1186 
1187  for( k = 0; k < Fsize; ++k )
1188  {
1189  if( SCIPisGE(scip, getGeneratorEntry(F[k], origvar), median) )
1190  ++Fupper;
1191  else
1192  ++Flower;
1193  }
1194 
1195  /* ********************************** *
1196  * choose smallest partition *
1197  * ********************************** */
1198 
1199  SCIP_CALL( SCIPallocBufferArray(scip, &copyF, Fsize) );
1200 
1201  if( Flower > 0 )
1202  {
1203  j = 0;
1204 
1205  for( k = 0; k < Fsize; ++k )
1206  {
1207  if( SCIPisLT(scip, getGeneratorEntry(F[k], origvar), median) )
1208  {
1209  copyF[j] = F[k];
1210  ++j;
1211  }
1212  }
1213 
1214  /*Fsize = Flower;*/
1215  assert(j < Fsize+1);
1216 
1217  SCIP_CALL( Separate( scip, copyF, Flower, J, Jsize, upperLowerS, Ssize+1, record) );
1218  }
1219 
1220  if( Fupper > 0 )
1221  {
1222  upperLowerS[Ssize].sense = GCG_COMPSENSE_GE;
1223  j = 0;
1224 
1225  for( k = 0; k < Fsize; ++k )
1226  {
1227  if( SCIPisGE(scip, getGeneratorEntry(F[k], origvar), median) )
1228  {
1229  copyF[j] = F[k];
1230  ++j;
1231  }
1232  }
1233 
1234  /*Fsize = Fupper;*/
1235  assert(j < Fsize+1);
1236 
1237  SCIP_CALL( Separate( scip, copyF, Fupper, J, Jsize, upperS, Ssize+1, record) );
1238  }
1239 
1240  SCIPfreeBufferArrayNull(scip, &copyF);
1241  SCIPfreeBufferArrayNull(scip, &upperS);
1242  SCIPfreeBufferArrayNull(scip, &upperLowerS);
1243  SCIPfreeBufferArray(scip, &priority);
1244  SCIPfreeBufferArrayNull(scip, &J);
1245  SCIPfreeBufferArray(scip, &alpha);
1246 
1247  return SCIP_OKAY;
1248 }
1249 
1250 /** choose a component bound sequence to create branching */
1251 static
1252 SCIP_RETCODE ChoseS(
1253  SCIP* scip, /**< SCIP data structure */
1254  GCG_RECORD** record, /**< candidate of bound sequences */
1255  GCG_COMPSEQUENCE** S, /**< pointer to return chosen bound sequence */
1256  int* Ssize /**< size of the chosen bound sequence */
1257  )
1258 {
1259  int minSizeOfMaxPriority; /* needed if the last comp priority is equal to the one in other bound sequences */
1260  SCIP_Longint maxPriority;
1261  int i;
1262  int Index;
1263 
1264  minSizeOfMaxPriority = INT_MAX;
1265  maxPriority = SCIP_LONGINT_MIN;
1266  Index = -1;
1267 
1268  SCIPdebugMessage("Chose S \n");
1269 
1270  assert((*record)->recordsize > 0);
1271 
1272  for( i = 0; i < (*record)->recordsize; ++i )
1273  {
1274  assert((*record)->sequencesizes != NULL );
1275  assert((*record)->sequencesizes[i] > 0);
1276 
1277  if( maxPriority <= 1 ) /* later by pseudocosts e.g. */
1278  {
1279  if( maxPriority < 1 )
1280  {
1281  maxPriority = 1; /* only choose here first smallest S */
1282  minSizeOfMaxPriority = (*record)->sequencesizes[i];
1283  Index = i;
1284  }
1285  else if( (*record)->sequencesizes[i] < minSizeOfMaxPriority )
1286  {
1287  minSizeOfMaxPriority = (*record)->sequencesizes[i];
1288  Index = i;
1289  }
1290  }
1291  }
1292  assert(maxPriority > SCIP_LONGINT_MIN);
1293  assert(minSizeOfMaxPriority < INT_MAX);
1294  assert(Index >= 0);
1295 
1296  *Ssize = minSizeOfMaxPriority;
1297  SCIP_CALL( SCIPallocBufferArray(scip, S, *Ssize) );
1298 
1299  for( i = 0; i < *Ssize; ++i )
1300  {
1301  (*S)[i] = (*record)->record[Index][i];
1302  }
1303 
1304  assert(S!=NULL);
1305  assert(*S!=NULL);
1306 
1307  /* free record */
1308  for( i = 0; i < (*record)->recordsize; ++i )
1309  {
1310  SCIPfreeBlockMemoryArray(scip, &((*record)->record[i]), (*record)->capacities[i] );
1311  }
1312  SCIPfreeBlockMemoryArray(scip, &((*record)->record), (*record)->recordcapacity );
1313 
1314  SCIPdebugMessage("with size %d \n", *Ssize);
1315 
1316  assert(*S!=NULL);
1317 
1318  return SCIP_OKAY;
1319 }
1320 
1321 /** updates the new set of sequences C in CopyC and the corresponding size array newsequencesizes
1322  * returns the size of CopyC */
1323 static
1325  int Csize, /**< size of the sequence */
1326  int p, /**< index of node */
1327  SCIP_VAR* origvar, /**< another index generatorentry */
1328  int* sequencesizes, /**< size of the sequences */
1329  GCG_COMPSEQUENCE** C, /**< original sequence */
1330  GCG_COMPSEQUENCE** CopyC, /**< new sequence */
1331  int* newsequencesizes, /**< output parameter for the new sequence */
1332  GCG_COMPSENSE sense /**< sense of the comparison */
1333  )
1334 {
1335  int j;
1336  int k;
1337 
1338  for( k = 0, j = 0; j < Csize; ++j )
1339  {
1340  if ( sequencesizes[j] >= p )
1341  assert(C[j][p-1].component == origvar);
1342 
1343  if ( sequencesizes[j] >= p && C[j][p-1].sense == sense )
1344  {
1345  CopyC[k] = C[j];
1346  newsequencesizes[k] = sequencesizes[j];
1347  ++k;
1348  }
1349  }
1350 
1351  return k;
1352 }
1353 
1354 /** auxilary function to compute alpha for given index */
1355 static
1357  SCIP* scip, /**< SCIP data structure */
1358  int Fsize, /**< size of F */
1359  GCG_COMPSENSE isense, /**< sense of the bound for origvar */
1360  double ivalue, /**< value of the bound for origvar */
1361  SCIP_VAR* origvar, /**< index of the variable */
1362  SCIP_VAR** F /**< current fractional mastervars*/
1363  )
1364 {
1365  int j;
1366  SCIP_Real alpha_i = 0.0;
1367 
1368  for ( j = 0; j < Fsize; ++j )
1369  {
1370  SCIP_Real generatorentry;
1371 
1372  generatorentry = getGeneratorEntry(F[j], origvar);
1373 
1374  if ( (isense == GCG_COMPSENSE_GE && SCIPisGE(scip, generatorentry, ivalue)) ||
1375  (isense == GCG_COMPSENSE_LT && SCIPisLT(scip, generatorentry, ivalue)) )
1376  {
1377  alpha_i += SCIPgetSolVal(GCGgetMasterprob(scip), NULL, F[j]);
1378  }
1379  }
1380 
1381  return alpha_i;
1382 }
1383 
1384 /** separation at a node other than the root node */
1385 static
1386 SCIP_RETCODE Explore(
1387  SCIP* scip, /**< SCIP data structure */
1388  GCG_COMPSEQUENCE** C, /**< array of component bounds sequences*/
1389  int Csize, /**< number of component bounds sequences*/
1390  int* sequencesizes, /**< array of sizes of component bounds sequences */
1391  int p, /**< depth of recursive call */
1392  SCIP_VAR** F, /**< strip of fractional columns */
1393  int Fsize, /**< size of the strips */
1394  SCIP_VAR** IndexSet, /**< array of original variables which belong to the fractional master columns */
1395  int IndexSetSize, /**< number of original variables which belong to fractional master columns. Note that IndexSetSize >= Fsize */
1396  GCG_COMPSEQUENCE** S, /**< component sequences */
1397  int* Ssize, /**< length of component sequences */
1398  GCG_RECORD* record /**< array of sets of component bounds which we might use for separation */
1399  )
1400 {
1401  int j;
1402  int k;
1403  SCIP_Real ivalue;
1404  GCG_COMPSENSE isense;
1405  SCIP_Real median;
1406  int Fupper;
1407  int Flower;
1408  int Cupper;
1409  int Clower;
1410  int lowerSsize;
1411  SCIP_VAR** copyF;
1412  GCG_COMPSEQUENCE* copyS;
1413  GCG_COMPSEQUENCE* lowerS;
1414  GCG_COMPSEQUENCE** CopyC;
1415  int* newsequencesizes;
1416  SCIP_VAR* origvar;
1417  SCIP_Real alpha_i;
1418  SCIP_Real muF;
1419  SCIP_Bool found;
1420 
1421  k = 0;
1422  muF = 0;
1423  Fupper = 0;
1424  Flower = 0;
1425  Cupper = 0;
1426  Clower = 0;
1427  newsequencesizes = NULL;
1428  copyF = NULL;
1429  CopyC = NULL;
1430  copyS = NULL;
1431  lowerS = NULL;
1432  found = FALSE;
1433 
1434  SCIPdebugMessage("Explore\n");
1435 
1436  SCIPdebugMessage("with Fsize = %d, Csize = %d, Ssize = %d, p = %d\n", Fsize, Csize, *Ssize, p);
1437 
1438  /* *************************************** *
1439  * if C=Ø, call separate and return that *
1440  * *************************************** */
1441 
1442  if( C == NULL || Fsize==0 || IndexSetSize==0 || Csize == 0 )
1443  {
1444  /* SCIPdebugMessage("go to Separate\n"); */
1445  assert(S != NULL);
1446 
1447  SCIP_CALL( Separate( scip, F, Fsize, IndexSet, IndexSetSize, *S, *Ssize, record) );
1448 
1449  if( *Ssize > 0 && *S != NULL )
1450  {
1451  SCIPfreeBufferArrayNull(scip, S);
1452  *S = NULL;
1453  *Ssize = 0;
1454  }
1455  return SCIP_OKAY;
1456  }
1457 
1458  assert(C != NULL);
1459  assert(Csize > 0);
1460  assert(F != NULL);
1461  assert(IndexSet != NULL);
1462  assert(sequencesizes != NULL);
1463 
1464  /* ******************************************* *
1465  * find i which is in all S in C on position p *
1466  * ******************************************* */
1467 
1468  while( sequencesizes[k] < p )
1469  {
1470  /* SCIPdebugMessage("sequencesizes[%d] = %d\n", k, sequencesizes[k]); */
1471  ++k;
1472 
1473  if( k >= Csize )
1474  {
1475  SCIPdebugMessage("no %dth element bounded\n", p);
1476  assert(S != NULL);
1477  SCIP_CALL( Separate( scip, F, Fsize, IndexSet, IndexSetSize, *S, *Ssize, record) );
1478 
1479  if( *Ssize > 0 && *S != NULL )
1480  {
1481  SCIPfreeBufferArrayNull(scip, S);
1482  *S = NULL;
1483  *Ssize = 0;
1484  }
1485 
1486  return SCIP_OKAY;
1487  }
1488 
1489  assert( k < Csize );
1490  }
1491 
1492  origvar = C[k][p-1].component;
1493  isense = C[k][p-1].sense;
1494  ivalue = C[k][p-1].bound;
1495 
1496  assert(origvar != NULL);
1497  assert(SCIPvarGetType(origvar) <= SCIP_VARTYPE_INTEGER);
1498 
1499  SCIPdebugMessage("orivar = %s; ivalue = %g\n", SCIPvarGetName(origvar), ivalue);
1500 
1501  for( j = 0; j < Fsize; ++j )
1502  {
1503  muF += SCIPgetSolVal(GCGgetMasterprob(scip), NULL, F[j]);
1504  }
1505 
1506  SCIPdebugMessage("muF = %g\n", muF);
1507 
1508  /* ******************************************* *
1509  * compute alpha_i *
1510  * ******************************************* */
1511 
1512  alpha_i = computeAlpha(scip, Fsize, isense, ivalue, origvar, F);
1513 
1514  SCIPdebugMessage("alpha(%s) = %g\n", SCIPvarGetName(origvar), alpha_i);
1515 
1516  /* ******************************************* *
1517  * if f > 0, add pair to record *
1518  * ******************************************* */
1519 
1520  if( !SCIPisFeasIntegral(scip, alpha_i) )
1521  {
1522  int l;
1523 
1524  found = TRUE;
1525  SCIPdebugMessage("fractional alpha(%s) = %g\n", SCIPvarGetName(origvar), alpha_i);
1526 
1527  /* ******************************************* *
1528  * add to record *
1529  * ******************************************* */
1530 
1531  SCIP_CALL( SCIPallocBufferArray(scip, &copyS, (size_t)*Ssize+1) );
1532  for( l = 0; l < *Ssize; ++l )
1533  {
1534  copyS[l] = (*S)[l];
1535  }
1536  copyS[*Ssize].component = origvar;
1537  copyS[*Ssize].sense = isense;
1538  copyS[*Ssize].bound = ivalue;
1539  SCIP_CALL( addToRecord(scip, record, copyS, *Ssize+1) );
1540  }
1541 
1542  if( found )
1543  {
1544  SCIPdebugMessage("found fractional alpha\n");
1545  SCIPfreeBufferArrayNull(scip, &copyS);
1546  return SCIP_OKAY;
1547  }
1548 
1549  /* add bound to the end of S */
1550  ++(*Ssize);
1551  assert(S != NULL );
1552 
1553  SCIP_CALL( SCIPreallocBufferArray(scip, S, *Ssize) );
1554 
1555  median = ivalue;
1556  (*S)[*Ssize-1].component = origvar;
1557  (*S)[*Ssize-1].sense = GCG_COMPSENSE_GE;
1558  (*S)[*Ssize-1].bound = median;
1559 
1560  SCIP_CALL( SCIPallocBufferArray(scip, &lowerS, *Ssize) );
1561 
1562  for( k = 0; k < *Ssize-1; ++k )
1563  {
1564  lowerS[k].component = (*S)[k].component;
1565  lowerS[k].sense = (*S)[k].sense;
1566  lowerS[k].bound = (*S)[k].bound;
1567  }
1568 
1569  lowerSsize = *Ssize;
1570  lowerS[lowerSsize-1].component = origvar;
1571  lowerS[lowerSsize-1].sense = GCG_COMPSENSE_LT;
1572  lowerS[lowerSsize-1].bound = median;
1573 
1574  for( k = 0; k < Fsize; ++k )
1575  {
1576  if( SCIPisGE(scip, getGeneratorEntry(F[k], origvar), median) )
1577  ++Fupper;
1578  else
1579  ++Flower;
1580  }
1581 
1582  /* calculate subset of C */
1583  for( j = 0; j < Csize; ++j )
1584  {
1585  if( sequencesizes[j] >= p )
1586  {
1587  if( C[j][p-1].sense == GCG_COMPSENSE_GE )
1588  {
1589  ++Cupper;
1590  }
1591  else
1592  {
1593  ++Clower;
1594  assert( C[j][p-1].sense == GCG_COMPSENSE_LT );
1595  }
1596  }
1597  }
1598 
1599  SCIPdebugMessage("Cupper = %d, Clower = %d\n", Cupper, Clower);
1600 
1601  if( SCIPisLE(scip, alpha_i, 0.0) && Fupper != 0 )
1602  Flower = INT_MAX;
1603  if( SCIPisEQ(scip, alpha_i, muF) && Flower != 0 )
1604  Fupper = INT_MAX;
1605 
1606  if( Fupper > 0 && Fupper != INT_MAX )
1607  {
1608  SCIPdebugMessage("chose upper bound Fupper = %d, Cupper = %d\n", Fupper, Cupper);
1609 
1610  SCIP_CALL( SCIPallocBufferArray(scip, &copyF, Fupper) );
1611  for( j = 0, k = 0; k < Fsize; ++k )
1612  {
1613  if( SCIPisGE(scip, getGeneratorEntry(F[k], origvar), median) )
1614  {
1615  copyF[j] = F[k];
1616  ++j;
1617  }
1618  }
1619 
1620  /* new C */
1621  if( Fupper > 0 )
1622  {
1623  SCIP_CALL( SCIPallocBufferArray(scip, &CopyC, Cupper) );
1624  SCIP_CALL( SCIPallocBufferArray(scip, &newsequencesizes, Cupper) );
1625  k = computeNewSequence(Csize, p, origvar, sequencesizes, C, CopyC, newsequencesizes, GCG_COMPSENSE_GE);
1626  if( k != Cupper )
1627  {
1628  SCIPdebugMessage("k = %d, p = %d\n", k, p);
1629  }
1630  assert(k == Cupper);
1631  }
1632  else
1633  {
1634  CopyC = NULL;
1635  }
1636 
1637  SCIP_CALL( Explore( scip, CopyC, Cupper, newsequencesizes, p+1, copyF, Fupper, IndexSet, IndexSetSize, S, Ssize, record) );
1638  }
1639 
1640  if( Flower > 0 && Flower != INT_MAX )
1641  {
1642  SCIPdebugMessage("chose lower bound Flower = %d Clower = %d\n", Flower, Clower);
1643 
1644  SCIP_CALL( SCIPreallocBufferArray(scip, &copyF, Flower) );
1645 
1646  j = 0;
1647  for( k = 0; k < Fsize; ++k )
1648  {
1649  if( SCIPisLT(scip, getGeneratorEntry(F[k], origvar), median) )
1650  {
1651  copyF[j] = F[k];
1652  ++j;
1653  }
1654  }
1655 
1656  /* new C */
1657  if( Flower > 0 )
1658  {
1659  SCIP_CALL( SCIPreallocBufferArray(scip, &CopyC, Clower) );
1660  SCIP_CALL( SCIPreallocBufferArray(scip, &newsequencesizes, Clower) );
1661  k = computeNewSequence(Csize, p, origvar, sequencesizes, C, CopyC, newsequencesizes, GCG_COMPSENSE_LT);
1662  if( k != Clower )
1663  {
1664  SCIPdebugMessage("k = %d, p = %d\n", k, p);
1665  }
1666  assert(k == Clower);
1667  }
1668  else
1669  {
1670  CopyC = NULL;
1671  }
1672 
1673  SCIP_CALL( Explore( scip, CopyC, Clower, newsequencesizes, p+1, copyF, Flower, IndexSet, IndexSetSize, &lowerS, &lowerSsize, record) );
1674  }
1675 
1676  SCIPfreeBufferArrayNull(scip, &newsequencesizes);
1677  SCIPfreeBufferArrayNull(scip, &CopyC);
1678  SCIPfreeBufferArrayNull(scip, &copyF);
1679  SCIPfreeBufferArrayNull(scip, &lowerS);
1680  SCIPfreeBufferArrayNull(scip, &copyS);
1681 
1682  if( *Ssize > 0 && *S != NULL )
1683  {
1684  SCIPfreeBufferArrayNull(scip, S);
1685 
1686  *Ssize = 0;
1687  }
1688 
1689  return SCIP_OKAY;
1690 }
1691 
1692 /** callup method for seperate
1693  * decides whether Separate or Explore should be done */
1694 static
1696  SCIP* scip, /**< SCIP data structure */
1697  SCIP_VAR** F /**< strip of fractional columns */,
1698  int Fsize, /**< size of the strips */
1699  GCG_COMPSEQUENCE** S, /**< array of existing bound sequences */
1700  int* Ssize, /**< size of existing bound sequences */
1701  GCG_COMPSEQUENCE** C, /**< array of component bounds sequences*/
1702  int Csize, /**< number of component bounds sequences*/
1703  int* CompSizes, /**< array of sizes of component bounds sequences */
1704  int blocknr, /**< id of the pricing problem (or block) in which we want to branch */
1705  SCIP_BRANCHRULE* branchrule, /**< branching rule */
1706  SCIP_RESULT* result, /**< pointer to store the result of the branching call */
1707  int** checkedblocks, /**< array to store which blocks have been checked */
1708  int* ncheckedblocks, /**< number of blocks that have beend checked */
1709  GCG_STRIP**** checkedblockssortstrips, /**< sorted strips of checked blocks */
1710  int** checkedblocksnsortstrips /**< size of the strips */
1711  )
1712 {
1713  int i;
1714  SCIP_VAR** IndexSet;
1715  SCIP_VAR** mastervars;
1716  int IndexSetSize;
1717  GCG_RECORD* record;
1718  int exploreSsize;
1719  GCG_COMPSEQUENCE* exploreS;
1720  GCG_STRIP** strips;
1721  int nstrips;
1722  int nmastervars;
1723 
1724  assert(Fsize > 0);
1725  assert(F != NULL);
1726  IndexSetSize = 0;
1727  exploreSsize = 0;
1728  exploreS = NULL;
1729  record = NULL;
1730  IndexSet = NULL;
1731  strips = NULL;
1732  nstrips = 0;
1733 
1734  SCIPdebugMessage("Calling Separate\n");
1735 
1736  SCIP_CALL( SCIPallocBuffer(scip, &record) );
1737  record->recordsize = 0;
1738  record->record = NULL;
1739  record->sequencesizes = NULL;
1740  record->capacities = NULL;
1741  record->recordcapacity = 0;
1742 
1743  /* calculate IndexSet */
1744  SCIP_CALL( InitIndexSet(scip, F, Fsize, &IndexSet, &IndexSetSize) );
1745  assert(IndexSetSize > 0);
1746  assert(IndexSet != NULL);
1747 
1748  /* rootnode? */
1749  if( Csize<=0 )
1750  SCIP_CALL( Separate( scip, F, Fsize, IndexSet, IndexSetSize, NULL, 0, record) );
1751  else
1752  {
1753  assert( C!=NULL );
1754  SCIP_CALL( Explore( scip, C, Csize, CompSizes, 1, F, Fsize, IndexSet, IndexSetSize, &exploreS, &exploreSsize, record) );
1755 
1756  SCIPfreeBufferArrayNull(scip, &exploreS);
1757  }
1758 
1759  assert(record != NULL);
1760 
1761  if( record->recordsize <= 0 )
1762  {
1763  SCIP_CALL( SCIPgetVarsData(GCGgetMasterprob(scip), &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
1764 
1765  ++(*ncheckedblocks);
1766  assert((*ncheckedblocks) <= GCGgetNPricingprobs(scip)+1);
1767 
1768  if( (*ncheckedblocks) > 1 )
1769  {
1770  SCIP_CALL( SCIPreallocBufferArray(scip, checkedblocks, *ncheckedblocks) );
1771  SCIP_CALL( SCIPreallocBufferArray(scip, checkedblocksnsortstrips, *ncheckedblocks) );
1772  SCIP_CALL( SCIPreallocBufferArray(scip, checkedblockssortstrips, *ncheckedblocks) );
1773  }
1774  else
1775  {
1776  SCIP_CALL( SCIPallocBufferArray(scip, checkedblocks, *ncheckedblocks) );
1777  SCIP_CALL( SCIPallocBufferArray(scip, checkedblocksnsortstrips, *ncheckedblocks) );
1778  SCIP_CALL( SCIPallocBufferArray(scip, checkedblockssortstrips, *ncheckedblocks) );
1779  }
1780 
1781  (*checkedblocks)[(*ncheckedblocks)-1] = blocknr;
1782 
1783  for( i=0; i<nmastervars; ++i )
1784  {
1785  if( GCGisMasterVarInBlock(mastervars[i], blocknr) )
1786  {
1787  ++nstrips;
1788 
1789  SCIP_CALL( SCIPreallocBufferArray(scip, &strips, nstrips) );
1790 
1791  assert(strips != NULL);
1792 
1793  SCIP_CALL( SCIPallocBuffer(scip, &(strips[nstrips-1])) ); /*lint !e866*/
1794  assert(strips[nstrips-1] != NULL);
1795 
1796  strips[nstrips-1]->C = NULL;
1797  strips[nstrips-1]->mastervar = mastervars[i];
1798  strips[nstrips-1]->Csize = 0;
1799  strips[nstrips-1]->sequencesizes = NULL;
1800  strips[nstrips-1]->scip = NULL;
1801  }
1802  }
1803 
1804  SCIP_CALL( InducedLexicographicSort(scip, strips, nstrips, C, Csize, CompSizes) );
1805 
1806  (*checkedblocksnsortstrips)[(*ncheckedblocks)-1] = nstrips;
1807 
1808  SCIP_CALL( SCIPallocBufferArray(scip, &((*checkedblockssortstrips)[(*ncheckedblocks)-1]), nstrips) ); /*lint !e866*/
1809 
1810  /* sort the direct copied origvars at the end */
1811 
1812  for( i = 0; i < nstrips; ++i )
1813  {
1814  assert(strips != NULL);
1815 
1816  SCIP_CALL( SCIPallocBuffer(scip, &(*checkedblockssortstrips[*ncheckedblocks-1][i])) ); /*lint !e866*/
1817  *checkedblockssortstrips[*ncheckedblocks-1][i] = strips[i];
1818  }
1819 
1820  for( i=0; i<nstrips; ++i )
1821  {
1822  assert(strips != NULL);
1823  SCIPfreeBuffer(scip, &(strips[i]));
1824  strips[i] = NULL;
1825  }
1826  SCIPfreeBufferArrayNull(scip, &strips);
1827 
1828  /*choose new block */
1829  SCIP_CALL( GCGbranchGenericInitbranch(GCGgetMasterprob(scip), branchrule, result, checkedblocks, ncheckedblocks, checkedblockssortstrips, checkedblocksnsortstrips) );
1830 
1831  }
1832  else
1833  {
1834  if( ncheckedblocks != NULL && (*ncheckedblocks) > 0 )
1835  {
1836  for( i = (*ncheckedblocks) - 1; i >= 0; --i )
1837  {
1838  int j;
1839 
1840  for( j = (*checkedblocksnsortstrips)[i] - 1; j >= 0; --j )
1841  {
1842  SCIPfreeBuffer(scip, &((*checkedblockssortstrips)[i][j]) );
1843  }
1844 
1845  SCIPfreeBufferArray(scip, &((*checkedblockssortstrips)[i]) );
1846  }
1847 
1848  SCIPfreeBufferArray(scip, checkedblockssortstrips);
1849  SCIPfreeBufferArray(scip, checkedblocksnsortstrips);
1850  SCIPfreeBufferArray(scip, checkedblocks);
1851  *ncheckedblocks = 0;
1852  }
1853  }
1854 
1855  if( record->recordsize > 0 )
1856  {
1857  SCIP_CALL( ChoseS( scip, &record, S, Ssize) );
1858  assert(*S != NULL);
1859  }
1860 
1861 
1862  SCIPfreeBufferArray(scip, &IndexSet);
1863  if( record != NULL )
1864  {
1865  SCIPfreeBlockMemoryArrayNull(scip, &record->capacities, record->recordcapacity);
1866  SCIPfreeBlockMemoryArrayNull(scip, &record->sequencesizes, record->recordcapacity);
1867  SCIPfreeBlockMemoryArrayNull(scip, &record->record, record->recordcapacity);
1868  SCIPfreeBuffer(scip, &record);
1869  }
1870  return SCIP_OKAY;
1871 }
1872 
1873 /** callback deletion method for branching data*/
1874 static
1875 GCG_DECL_BRANCHDATADELETE(branchDataDeleteGeneric)
1876 {
1877  assert(scip != NULL);
1878  assert(branchdata != NULL);
1879 
1880  if( *branchdata == NULL )
1881  {
1882  SCIPdebugMessage("branchDataDeleteGeneric: cannot delete empty branchdata\n");
1883 
1884  return SCIP_OKAY;
1885  }
1886 
1887  if( (*branchdata)->mastercons != NULL )
1888  {
1889  SCIPdebugMessage("branchDataDeleteGeneric: child blocknr %d, %s\n", (*branchdata)->consblocknr,
1890  SCIPconsGetName((*branchdata)->mastercons) );
1891  }
1892  else
1893  {
1894  SCIPdebugMessage("branchDataDeleteGeneric: child blocknr %d, empty mastercons\n", (*branchdata)->consblocknr);
1895  }
1896 
1897  /* release constraint that enforces the branching decision */
1898  if( (*branchdata)->mastercons != NULL )
1899  {
1900  SCIP_CALL( SCIPreleaseCons(GCGgetMasterprob(scip), &(*branchdata)->mastercons) );
1901  (*branchdata)->mastercons = NULL;
1902  }
1903 
1904  if( (*branchdata)->consS != NULL && (*branchdata)->consSsize > 0 )
1905  {
1906  SCIPfreeBlockMemoryArrayNull(scip, &((*branchdata)->consS), (*branchdata)->maxconsS);
1907  (*branchdata)->consS = NULL;
1908  (*branchdata)->consSsize = 0;
1909  }
1910 
1911  SCIPfreeBlockMemoryNull(scip, branchdata);
1912  *branchdata = NULL;
1913 
1914  return SCIP_OKAY;
1915 }
1916 
1917 /** check method for pruning ChildS directly on childnodes
1918  * @returns TRUE if node is pruned */
1919 static
1921  SCIP* scip, /**< SCIP data structure */
1922  SCIP_Real lhs, /**< lhs for childnode which is checkes to be pruned */
1923  GCG_COMPSEQUENCE* childS, /**< component bound sequence defining the childnode */
1924  int childSsize, /**< size of component bound sequence */
1925  SCIP_CONS* parentcons, /**< constraint of parent node in B&B tree */
1926  int childBlocknr /**< number of the block for the child node */
1927  )
1928 {
1929  int i;
1930  int nchildren;
1931 
1932  nchildren = GCGconsMasterbranchGetNChildconss(parentcons);
1933  assert(nchildren>0);
1934 
1935  for( i=0; i<nchildren; ++i )
1936  {
1937  SCIP_CONS* childcons;
1938  GCG_BRANCHDATA* branchdata;
1939  SCIP_Bool same;
1940  int j;
1941 
1942  same = TRUE;
1943  childcons = GCGconsMasterbranchGetChildcons(parentcons, i);
1944  if( childcons == NULL )
1945  continue;
1946 
1947  if( GCGconsMasterbranchGetBranchrule(childcons) != NULL && strcmp(SCIPbranchruleGetName(GCGconsMasterbranchGetBranchrule(childcons)), "generic") != 0 )
1948  continue;
1949 
1950  branchdata = GCGconsMasterbranchGetBranchdata(childcons);
1951  assert(branchdata != NULL);
1952 
1953  if( childBlocknr != branchdata->consblocknr || childSsize != branchdata->consSsize || !SCIPisEQ(scip, lhs, branchdata->lhs) )
1954  continue;
1955 
1956  assert(childSsize > 0 && branchdata->consSsize > 0);
1957 
1958  for( j=0; j< childSsize; ++j )
1959  {
1960  if( childS[j].component != branchdata->consS[j].component
1961  || childS[j].sense != branchdata->consS[j].sense
1962  || !SCIPisEQ(scip, childS[j].bound, branchdata->consS[j].bound) )
1963  {
1964  same = FALSE;
1965  break;
1966  }
1967  }
1968 
1969  if( same )
1970  {
1971  SCIPdebugMessage("child pruned \n");
1972  return TRUE;
1973  }
1974  }
1975  return FALSE;
1976 }
1977 
1978 /** check method for pruning ChildS indirectly by parentnodes
1979  * retrun TRUE if node is pruned */
1980 static
1982  SCIP* scip, /**< SCIP data structure */
1983  SCIP_Real lhs, /**< lhs for childnode which is checkes to be pruned */
1984  GCG_COMPSEQUENCE* childS, /**< Component Bound Sequence defining the childnode */
1985  int childSsize, /**< size of component bound sequence */
1986  SCIP_CONS* masterbranchcons, /**< master branching constraint */
1987  int childBlocknr /**< number of the block for the childnode */
1988  )
1989 {
1990  SCIP_CONS* cons;
1991 
1992  SCIPdebugMessage("Prune by dominance\n");
1993  cons = GCGconsMasterbranchGetParentcons(masterbranchcons);
1994 
1995  if( cons == NULL )
1996  {
1997  SCIPdebugMessage("cons == NULL, not pruned\n");
1998  return FALSE;
1999  }
2000  while( cons != NULL )
2001  {
2002  GCG_BRANCHDATA* parentdata;
2003  SCIP_Bool ispruned;
2004 
2005  parentdata = GCGconsMasterbranchGetBranchdata(cons);
2006  if( parentdata == NULL )
2007  {
2008  /* root node: check children for pruning */
2009  return checkchildconsS(scip, lhs, childS, childSsize, cons, childBlocknr);
2010  }
2011  if( strcmp(SCIPbranchruleGetName(GCGconsMasterbranchGetBranchrule(cons)), "generic") != 0 )
2012  return checkchildconsS(scip, lhs, childS, childSsize, cons, childBlocknr);
2013 
2014  ispruned = checkchildconsS(scip, lhs, childS, childSsize, cons, childBlocknr);
2015 
2016  if( ispruned )
2017  {
2018  return TRUE;
2019  }
2020 
2021  cons = GCGconsMasterbranchGetParentcons(cons);
2022  }
2023 
2024  SCIPdebugMessage("child not pruned\n");
2025  return FALSE;
2026 }
2027 
2028 /** initialize branchdata at the node */
2029 static
2030 SCIP_RETCODE initNodeBranchdata(
2031  SCIP* scip, /**< SCIP data structure */
2032  GCG_BRANCHDATA** nodebranchdata, /**< branching data to set */
2033  int blocknr /**< block we are branching in */
2034  )
2035 {
2036  SCIP_CALL( SCIPallocBlockMemory(scip, nodebranchdata) );
2037 
2038  (*nodebranchdata)->consblocknr = blocknr;
2039  (*nodebranchdata)->mastercons = NULL;
2040  (*nodebranchdata)->consS = NULL;
2041  (*nodebranchdata)->C = NULL;
2042  (*nodebranchdata)->maxconsS = 0;
2043  (*nodebranchdata)->consSsize = 0;
2044  (*nodebranchdata)->nvars = 0;
2045 
2046  return SCIP_OKAY;
2047 }
2048 
2049 /** for given component bound sequence S, create |S|+1 Vanderbeck branching nodes */
2050 static
2052  SCIP* scip, /**< SCIP data structure */
2053  SCIP_BRANCHRULE* branchrule, /**< branching rule */
2054  GCG_COMPSEQUENCE* S, /**< Component Bound Sequence defining the nodes */
2055  int Ssize, /**< size of S */
2056  int blocknr, /**< number of the block */
2057  SCIP_CONS* masterbranchcons, /**< current masterbranchcons*/
2058  SCIP_RESULT* result /**< pointer to store the result of the branching call */
2059  )
2060 {
2061 #ifdef SCIP_DEBUG
2062  SCIP_Real identicalcontrol = 0;
2063 #endif
2064  SCIP* masterscip;
2065  int i;
2066  int p;
2067  SCIP_Real pL;
2068  SCIP_Real L;
2069  SCIP_Real lhsSum;
2070  int nmastervars;
2071  int nmastervars2;
2072  int ncopymastervars;
2073  int nbranchcands;
2074  int nchildnodes;
2075  SCIP_VAR** mastervars;
2076  SCIP_VAR** mastervars2;
2077  SCIP_VAR** branchcands;
2078 
2079  assert(scip != NULL);
2080  assert(Ssize > 0);
2081  assert(S != NULL);
2082 
2083  lhsSum = 0;
2084  nchildnodes = 0;
2085  L = 0;
2086 
2087  pL = GCGgetNIdenticalBlocks(scip, blocknr);
2088  SCIPdebugMessage("Vanderbeck branching rule Node creation for blocknr %d with %.1f identical blocks \n", blocknr, pL);
2089 
2090 
2091  /* get variable data of the master problem */
2092  masterscip = GCGgetMasterprob(scip);
2093  assert(masterscip != NULL);
2094  SCIP_CALL( SCIPgetVarsData(masterscip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
2095  nmastervars2 = nmastervars;
2096  assert(nmastervars >= 0);
2097  SCIP_CALL( SCIPduplicateBufferArray(scip, &mastervars2, mastervars, nmastervars) );
2098 
2099  SCIP_CALL( SCIPgetLPBranchCands(masterscip, &branchcands, NULL, NULL, &nbranchcands, NULL, NULL) );
2100 
2101  SCIPdebugMessage("Vanderbeck branching rule: creating %d nodes\n", Ssize+1);
2102 
2103  for( p=0; p<Ssize+1; ++p )
2104  {
2105  GCG_BRANCHDATA* branchchilddata;
2106  SCIP_NODE* child;
2107  SCIP_CONS* childcons;
2108  int k;
2109 
2110  SCIP_Real lhs;
2111  branchchilddata = NULL;
2112 
2113  /* allocate branchdata for child and store information */
2114  SCIP_CALL( initNodeBranchdata(scip, &branchchilddata, blocknr) );
2115 
2116  if( p == Ssize )
2117  {
2118  branchchilddata->maxconsS = SCIPcalcMemGrowSize(scip, Ssize);
2119  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(branchchilddata->consS), branchchilddata->maxconsS) );
2120  branchchilddata->consSsize = Ssize;
2121  }
2122  else
2123  {
2124  branchchilddata->maxconsS = SCIPcalcMemGrowSize(scip, p+1);
2125  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(branchchilddata->consS), branchchilddata->maxconsS) );
2126  branchchilddata->consSsize = p+1;
2127  }
2128  for( k = 0; k <= p; ++k )
2129  {
2130  GCG_COMPSEQUENCE compBound;
2131 
2132  if( k == Ssize )
2133  {
2134  assert( p == Ssize );
2135  compBound = S[k-1];
2136  branchchilddata->consS[k-1] = compBound;
2137  }
2138  else
2139  {
2140  compBound = S[k];
2141  if( k >= p )
2142  {
2143  if( S[p].sense == GCG_COMPSENSE_GE )
2144  compBound.sense = GCG_COMPSENSE_LT;
2145  else
2146  compBound.sense = GCG_COMPSENSE_GE;
2147  }
2148  branchchilddata->consS[k] = compBound;
2149  }
2150  }
2151 
2152  /* last node? */
2153  if( p == Ssize )
2154  {
2155  lhs = pL;
2156  }
2157  else
2158  {
2159  /* calculate mu */
2160  SCIP_Real mu = 0.0;
2161 
2162  ncopymastervars = nmastervars2;
2163  for( i = 0; i < ncopymastervars; ++i )
2164  {
2165  SCIP_VAR* swap;
2166 
2167  if( i >= nmastervars2 )
2168  break;
2169 
2170  if( GCGisMasterVarInBlock(mastervars2[i], blocknr) )
2171  {
2172  SCIP_Real generator_i = getGeneratorEntry(mastervars2[i], S[p].component);
2173 
2174  if( (S[p].sense == GCG_COMPSENSE_GE && SCIPisGE(scip, generator_i, S[p].bound)) ||
2175  (S[p].sense == GCG_COMPSENSE_LT && SCIPisLT(scip, generator_i, S[p].bound) ) )
2176  {
2177  mu += SCIPgetSolVal(masterscip, NULL, mastervars2[i]);
2178  }
2179  else if( ncopymastervars > 0 )
2180  {
2181  swap = mastervars2[i];
2182  mastervars2[i] = mastervars2[nmastervars2-1];
2183  mastervars2[nmastervars2-1] = swap;
2184  --nmastervars2;
2185  --i;
2186  }
2187  }
2188  else if( nmastervars2 > 0 )
2189  {
2190  swap = mastervars2[i];
2191  mastervars2[i] = mastervars2[nmastervars2-1];
2192  mastervars2[nmastervars2-1] = swap;
2193  --nmastervars2;
2194  --i;
2195  }
2196  }
2197 
2198  if( p == Ssize-1 ) /*lint !e866 !e850*/
2199  {
2200  L = SCIPceil(scip, mu);
2201  SCIPdebugMessage("mu = %g, \n", mu);
2202  assert(!SCIPisFeasIntegral(scip,mu));
2203  }
2204  else
2205  {
2206  L = mu;
2207  SCIPdebugMessage("mu = %g should be integer, \n", mu);
2208  assert(SCIPisFeasIntegral(scip,mu));
2209  }
2210  lhs = pL-L+1;
2211  }
2212  SCIPdebugMessage("pL = %g \n", pL);
2213  pL = L;
2214 
2215  branchchilddata->lhs = lhs;
2216  SCIPdebugMessage("L = %g, \n", L);
2217  SCIPdebugMessage("lhs set to %g \n", lhs);
2218  assert(SCIPisFeasIntegral(scip, lhs));
2219  lhsSum += lhs;
2220 
2221 
2222  if( masterbranchcons == NULL || !pruneChildNodeByDominanceGeneric(scip, lhs, branchchilddata->consS, branchchilddata->consSsize, masterbranchcons, blocknr) )
2223  {
2224  if( masterbranchcons != NULL )
2225  {
2226  char childname[SCIP_MAXSTRLEN];
2227  ++nchildnodes;
2228 
2229  assert(branchchilddata != NULL);
2230 
2231  /* define names for origbranch constraints */
2232  (void) SCIPsnprintf(childname, SCIP_MAXSTRLEN, "node(%d, %d) (last comp=%s %s %g) >= %g", blocknr, p+1,
2233  SCIPvarGetName(branchchilddata->consS[branchchilddata->consSsize-1].component),
2234  branchchilddata->consS[branchchilddata->consSsize-1].sense == GCG_COMPSENSE_GE? ">=": "<",
2235  branchchilddata->consS[branchchilddata->consSsize-1].bound,
2236  branchchilddata->lhs);
2237 
2238  SCIP_CALL( SCIPcreateChild(masterscip, &child, 0.0, SCIPgetLocalTransEstimate(masterscip)) );
2239  SCIP_CALL( GCGcreateConsMasterbranch(masterscip, &childcons, childname, child,
2240  GCGconsMasterbranchGetActiveCons(masterscip), branchrule, branchchilddata, NULL, 0, 0) );
2241  SCIP_CALL( SCIPaddConsNode(masterscip, child, childcons, NULL) );
2242 
2243  SCIP_CALL( createBranchingCons(masterscip, child, branchchilddata) );
2244 
2245  /* release constraints */
2246  SCIP_CALL( SCIPreleaseCons(masterscip, &childcons) );
2247  }
2248  }
2249  else
2250  {
2251  SCIPfreeBlockMemoryArrayNull(scip, &(branchchilddata->consS), branchchilddata->maxconsS);
2252  SCIPfreeBlockMemoryNull(scip, &branchchilddata);
2253  }
2254  }
2255  SCIPdebugMessage("lhsSum = %g\n", lhsSum);
2256 
2257 #ifdef SCIP_DEBUG
2258  SCIP_CALL( SCIPgetVarsData(masterscip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
2259 
2260  for( i = 0; i < nmastervars; ++i )
2261  {
2262  SCIP_VAR* mastervar = mastervars[i];
2263 
2264  if( GCGisMasterVarInBlock(mastervar, blocknr) )
2265  {
2266  identicalcontrol += SCIPgetSolVal(masterscip, NULL, mastervar);
2267  }
2268 
2269  }
2270  if( !SCIPisEQ(scip, identicalcontrol, GCGgetNIdenticalBlocks(scip, blocknr)) )
2271  {
2272  SCIPdebugMessage("width of the block is only %g\n", identicalcontrol);
2273  }
2274 
2275  assert( SCIPisEQ(scip, identicalcontrol, GCGgetNIdenticalBlocks(scip, blocknr)) );
2276 #endif
2277 
2278  assert( SCIPisEQ(scip, lhsSum, 1.0*(GCGgetNIdenticalBlocks(scip, blocknr) + Ssize)) );
2279 
2280  SCIPfreeBufferArray(scip, &mastervars2);
2281 
2282  if( nchildnodes <= 0 )
2283  {
2284  SCIPdebugMessage("node cut off, since all childnodes have been pruned\n");
2285 
2286  *result = SCIP_CUTOFF;
2287  }
2288 
2289  return SCIP_OKAY;
2290 }
2291 
2292 /** branching on copied origvar directly in master */
2293 static
2295  SCIP* scip, /**< SCIP data structure */
2296  SCIP_VAR* mastervar, /**< master variable */
2297  SCIP_BRANCHRULE* branchrule /**< branching rule */
2298  )
2299 {
2300  SCIP* masterscip;
2301  GCG_BRANCHDATA* branchupchilddata;
2302  GCG_BRANCHDATA* branchdownchilddata;
2303  SCIP_NODE* upchild;
2304  SCIP_NODE* downchild;
2305  SCIP_CONS* upchildcons;
2306  SCIP_CONS* downchildcons;
2307  char upchildname[SCIP_MAXSTRLEN];
2308  char downchildname[SCIP_MAXSTRLEN];
2309  int bound;
2310 
2311  masterscip = GCGgetMasterprob(scip);
2312  assert(masterscip != NULL);
2313 
2314  bound = (int) (SCIPceil( scip, SCIPgetSolVal(masterscip, NULL, mastervar)) + 0.5); /*lint -e524*/
2315 
2316  /* allocate branchdata for child and store information */
2317  SCIP_CALL( initNodeBranchdata(scip, &branchupchilddata, -3) );
2318  SCIP_CALL( initNodeBranchdata(scip, &branchdownchilddata, -3) );
2319 
2320  branchupchilddata->maxconsS = SCIPcalcMemGrowSize(scip, 1);
2321  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(branchupchilddata->consS), branchupchilddata->maxconsS) ); /*lint !e506*/
2322  branchupchilddata->consSsize = 1;
2323 
2324  branchdownchilddata->maxconsS = branchupchilddata->maxconsS;
2325  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(branchdownchilddata->consS), branchdownchilddata->maxconsS) ); /*lint !e506*/
2326  branchdownchilddata->consSsize = 1;
2327 
2328  branchupchilddata->consS[0].component = mastervar;
2329  branchupchilddata->consS[0].sense = GCG_COMPSENSE_GE;
2330  branchupchilddata->consS[0].bound = bound;
2331 
2332  branchdownchilddata->consS[0].component = mastervar;
2333  branchdownchilddata->consS[0].sense = GCG_COMPSENSE_LT;
2334  branchdownchilddata->consS[0].bound = bound;
2335 
2336 
2337  assert(branchupchilddata != NULL);
2338  assert(branchdownchilddata != NULL);
2339 
2340  (void) SCIPsnprintf(upchildname, SCIP_MAXSTRLEN, "node(-3, %f) direct up on comp=%s", branchupchilddata->consS[0].bound,
2341  SCIPvarGetName(branchupchilddata->consS[branchupchilddata->consSsize-1].component));
2342  (void) SCIPsnprintf(downchildname, SCIP_MAXSTRLEN, "node(-3, %f) direct up on comp=%s", branchdownchilddata->consS[0].bound,
2343  SCIPvarGetName(branchdownchilddata->consS[branchdownchilddata->consSsize-1].component));
2344 
2345  SCIP_CALL( SCIPcreateChild(masterscip, &upchild, 0.0, SCIPgetLocalTransEstimate(masterscip)) );
2346  SCIP_CALL( GCGcreateConsMasterbranch(masterscip, &upchildcons, upchildname, upchild,
2347  GCGconsMasterbranchGetActiveCons(masterscip), branchrule, branchupchilddata, NULL, 0, 0) );
2348  SCIP_CALL( SCIPaddConsNode(masterscip, upchild, upchildcons, NULL) );
2349 
2350  SCIP_CALL( SCIPcreateChild(masterscip, &downchild, 0.0, SCIPgetLocalTransEstimate(masterscip)) );
2351  SCIP_CALL( GCGcreateConsMasterbranch(masterscip, &downchildcons, downchildname, downchild,
2352  GCGconsMasterbranchGetActiveCons(masterscip), branchrule, branchdownchilddata, NULL, 0, 0) );
2353  SCIP_CALL( SCIPaddConsNode(masterscip, downchild, downchildcons, NULL) );
2354 
2355  /* create branching constraint in master */
2356  SCIP_CALL( createDirectBranchingCons(masterscip, upchild, branchupchilddata) );
2357  SCIP_CALL( createDirectBranchingCons(masterscip, downchild, branchdownchilddata) );
2358 
2359  /* release constraints */
2360  SCIP_CALL( SCIPreleaseCons(masterscip, &upchildcons) );
2361  SCIP_CALL( SCIPreleaseCons(masterscip, &downchildcons) );
2362 
2363  return SCIP_OKAY;
2364 }
2365 
2366 /** prepares information for using the generic branching scheme */
2368  SCIP* masterscip, /**< SCIP data structure */
2369  SCIP_BRANCHRULE* branchrule, /**< branching rule */
2370  SCIP_RESULT* result, /**< pointer to store the result of the branching call */
2371  int** checkedblocks, /**< blocks that have been checked */
2372  int* ncheckedblocks, /**< number of checked blocks */
2373  GCG_STRIP**** checkedblockssortstrips, /**< sorted strips of checked blocks */
2374  int** checkedblocksnsortstrips /**< sizes of the strips */
2375  )
2376 {
2377  SCIP* origscip;
2378  SCIP_VAR** branchcands;
2379  SCIP_VAR** allorigvars;
2380  SCIP_VAR** mastervars;
2381  int nmastervars;
2382  SCIP_CONS* masterbranchcons;
2383  int nbranchcands;
2384  GCG_BRANCHDATA* branchdata;
2385  SCIP_VAR* mastervar;
2386  SCIP_Real mastervarValue;
2387  GCG_COMPSEQUENCE* S;
2388  GCG_COMPSEQUENCE** C;
2389  SCIP_VAR** F;
2390  int Ssize;
2391  int Fsize;
2392  int* sequencesizes;
2393  int blocknr;
2394  int i;
2395  int j;
2396  int allnorigvars;
2397 #ifndef NDEBUG
2398  SCIP_Bool foundblocknr = FALSE;
2399 #endif
2400 
2401  SCIP_Bool discretization;
2402 
2403  blocknr = -2;
2404  Ssize = 0;
2405  Fsize = 0;
2406  S = NULL;
2407  C = NULL;
2408  F = NULL;
2409  sequencesizes = NULL;
2410 
2411  assert(masterscip != NULL);
2412 
2413  SCIPdebugMessage("get information for Vanderbecks generic branching\n");
2414 
2415  origscip = GCGmasterGetOrigprob(masterscip);
2416 
2417  SCIP_CALL( SCIPgetBoolParam(origscip, "relaxing/gcg/discretization", &discretization) );
2418 
2419  assert(origscip != NULL);
2420  SCIP_CALL( SCIPgetLPBranchCands(masterscip, &branchcands, NULL, NULL, &nbranchcands, NULL, NULL) );
2421 
2422  SCIP_CALL( SCIPgetVarsData(origscip, &allorigvars, &allnorigvars, NULL, NULL, NULL, NULL) );
2423  SCIP_CALL( SCIPgetVarsData(masterscip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
2424 
2425  /* in case original problem contains continuous variables, there are no branching cands */
2426  assert(nbranchcands > 0 || (discretization && SCIPgetNContVars(origscip) > 0));
2427  mastervar = NULL;
2428 
2429  /* loop over all branching candidates */
2430  for( i = 0; i < nbranchcands && (!discretization || SCIPgetNContVars(origscip) == 0); ++i )
2431  {
2432  int k;
2433  mastervar = branchcands[i];
2434  assert(GCGvarIsMaster(mastervar));
2435 
2436  /* if we have a master variable, we branch on it */
2437  if( GCGvarGetBlock(mastervar) == -1 )
2438  {
2439  assert(!GCGmasterVarIsArtificial(mastervar));
2440 #ifndef NDEBUG
2441  foundblocknr = TRUE;
2442 #endif
2443  blocknr = -1;
2444  break;
2445  }
2446 
2447  /* else, check if the candidate is in an unchecked block */
2448  for( j = 0; j < GCGgetNPricingprobs(origscip); ++j )
2449  {
2450  SCIP_Bool checked = FALSE;
2451  for( k = 0; ncheckedblocks != NULL && k < (*ncheckedblocks); ++k )
2452  {
2453  /* if the block has been checked, no need to check master variable */
2454  if( (*checkedblocks)[k] == j )
2455  {
2456  checked = TRUE;
2457  break;
2458  }
2459  }
2460 
2461  if( checked )
2462  continue;
2463  /* else the block has not been checked and the variable is in it , we have a candidate */
2464  else if( GCGisMasterVarInBlock(mastervar, j) )
2465  {
2466 #ifndef NDEBUG
2467  foundblocknr = TRUE;
2468 #endif
2469  blocknr = j;
2470  break;
2471  }
2472  }
2473  }
2474  assert(foundblocknr || blocknr == -1 || (discretization && SCIPgetNContVars(origscip) > 0));
2475  assert(i <= nbranchcands); /* else all blocks has been checked and we can observe an integer solution */
2476 
2477  /* in case of continuous origvar look for "fractional" blocks using the representation (currentorigsol) in the original problem */
2478  if(discretization && SCIPgetNContVars(origscip) > 0)
2479  {
2480  int norigvars;
2481  SCIP_VAR** origvars;
2482  SCIP_VAR* origvar;
2483 
2484  norigvars = SCIPgetNVars(origscip);
2485  origvars = SCIPgetVars(origscip);
2486 
2487  nbranchcands = SCIPgetNVars(masterscip);
2488  branchcands = SCIPgetVars(masterscip);
2489 
2490  assert(nbranchcands > 0);
2491 
2492  for( i = 0; i < norigvars; ++i )
2493  {
2494  int k;
2495  SCIP_Bool checked;
2496  origvar = origvars[i];
2497 
2498  if( SCIPvarGetType(origvar) > SCIP_VARTYPE_INTEGER )
2499  continue;
2500 
2501  if( SCIPisIntegral(origscip, SCIPgetSolVal(origscip, GCGrelaxGetCurrentOrigSol(origscip), origvar)) )
2502  continue;
2503 
2504  blocknr = GCGgetBlockRepresentative(origscip, GCGvarGetBlock(origvar));
2505 
2506  SCIPdebugMessage("Variable %s belonging to block %d with representative %d is not integral!\n", SCIPvarGetName(origvar), GCGvarGetBlock(origvar), blocknr);
2507 
2508  if( blocknr == -1 )
2509  {
2510  assert(GCGoriginalVarGetNMastervars(origvar) == 1);
2511  mastervar = GCGoriginalVarGetMastervars(origvar)[0];
2512  break;
2513  }
2514 
2515  checked = FALSE;
2516  for( k = 0; ncheckedblocks != NULL && k < (*ncheckedblocks); ++k )
2517  {
2518  /* if the block has been checked, no need to check master variable */
2519  if( (*checkedblocks)[k] == blocknr )
2520  {
2521  checked = TRUE;
2522  break;
2523  }
2524  }
2525 
2526  if( checked )
2527  {
2528  continue;
2529  }
2530  else
2531  {
2532  break;
2533  }
2534  }
2535  }
2536 
2537  if( blocknr < -1 )
2538  {
2539  SCIP_Bool rays;
2540 
2541  SCIPdebugMessage("Generic branching rule could not find variables to branch on!\n");
2542 
2543  SCIP_CALL( GCGpricerExistRays(masterscip, &rays) );
2544 
2545  if( rays )
2546  SCIPwarningMessage(masterscip, "Generic branching is not compatible with unbounded problems!\n");
2547 
2548  return SCIP_ERROR;
2549  }
2550 
2551  /* a special case; branch on copy of an origvar directly */
2552  if( blocknr == -1 )
2553  {
2554  assert(!GCGmasterVarIsLinking(mastervar));
2555  SCIPdebugMessage("branching on master variable\n");
2556  SCIP_CALL( branchDirectlyOnMastervar(origscip, mastervar, branchrule) );
2557  return SCIP_OKAY;
2558  }
2559 
2560  masterbranchcons = GCGconsMasterbranchGetActiveCons(masterscip);
2561  SCIPdebugMessage("branching in block %d \n", blocknr);
2562 
2563  /* calculate F and the strips */
2564  for( i = 0; i < nbranchcands; ++i )
2565  {
2566  mastervar = branchcands[i];
2567  assert(GCGvarIsMaster(mastervar));
2568 
2569  if( GCGisMasterVarInBlock(mastervar, blocknr) )
2570  {
2571  mastervarValue = SCIPgetSolVal(masterscip, NULL, mastervar);
2572  if( !SCIPisFeasIntegral(masterscip, mastervarValue) )
2573  {
2574 
2575  SCIP_CALL( SCIPreallocBufferArray(origscip, &F, (size_t)Fsize+1) );
2576 
2577  F[Fsize] = mastervar;
2578  ++Fsize;
2579  }
2580  }
2581  }
2582 
2583  /* old data to regard? */
2584  if( masterbranchcons != NULL && GCGconsMasterbranchGetBranchdata(masterbranchcons) != NULL )
2585  {
2586  /* calculate C */
2587  int c;
2588  int Csize = 0;
2589  SCIP_CONS* parentcons = masterbranchcons;
2590 
2591  while( parentcons != NULL && GCGconsMasterbranchGetBranchrule(parentcons) != NULL
2592  && strcmp(SCIPbranchruleGetName(GCGconsMasterbranchGetBranchrule(parentcons)), "generic") == 0)
2593  {
2594  branchdata = GCGconsMasterbranchGetBranchdata(parentcons);
2595  if( branchdata == NULL )
2596  {
2597  SCIPdebugMessage("branchdata is NULL\n");
2598  break;
2599  }
2600  if( branchdata->consS == NULL || branchdata->consSsize == 0 )
2601  break;
2602  if( branchdata->consblocknr != blocknr )
2603  {
2604  parentcons = GCGconsMasterbranchGetParentcons(parentcons);
2605  continue;
2606  }
2607 
2608  if( Csize == 0 )
2609  {
2610  assert(branchdata != NULL);
2611  assert(branchdata->consSsize > 0);
2612  Csize = 1;
2613  SCIP_CALL( SCIPallocBufferArray(origscip, &C, Csize) );
2614  SCIP_CALL( SCIPallocBufferArray(origscip, &sequencesizes, Csize) );
2615  assert(sequencesizes != NULL);
2616  C[0] = NULL;
2617  SCIP_CALL( SCIPallocBufferArray(origscip, &(C[0]), branchdata->consSsize) );
2618  for( i = 0; i < branchdata->consSsize; ++i )
2619  {
2620  C[0][i] = branchdata->consS[i];
2621  }
2622  sequencesizes[0] = branchdata->consSsize;
2623  parentcons = GCGconsMasterbranchGetParentcons(parentcons);
2624  }
2625  else
2626  {
2627  /* S not yet in C ? */
2628  SCIP_Bool SinC = FALSE;
2629  for( c = 0; c < Csize && !SinC; ++c )
2630  {
2631  SinC = TRUE;
2632  assert(sequencesizes != NULL);
2633  if( branchdata->consSsize == sequencesizes[c] )
2634  {
2635  for( i = 0; i < branchdata->consSsize; ++i )
2636  {
2637  assert(C != NULL);
2638  if( branchdata->consS[i].component != C[c][i].component || branchdata->consS[i].sense != C[c][i].sense || !SCIPisEQ(origscip, branchdata->consS[i].bound, C[c][i].bound) )
2639  {
2640  SinC = FALSE;
2641  break;
2642  }
2643  }
2644  }
2645  else
2646  SinC = FALSE;
2647  }
2648  if( !SinC )
2649  {
2650  ++Csize;
2651  SCIP_CALL( SCIPreallocBufferArray(origscip, &C, Csize) );
2652  SCIP_CALL( SCIPreallocBufferArray(origscip, &sequencesizes, Csize) );
2653  assert(sequencesizes != NULL);
2654  C[Csize-1] = NULL;
2655  SCIP_CALL( SCIPallocBufferArray(origscip, &(C[Csize-1]), branchdata->consSsize) ); /*lint !e866*/
2656 
2657  /** @todo copy memory */
2658  for( i = 0; i < branchdata->consSsize; ++i )
2659  {
2660  C[Csize-1][i] = branchdata->consS[i];
2661  }
2662  sequencesizes[Csize-1] = branchdata->consSsize;
2663  }
2664  parentcons = GCGconsMasterbranchGetParentcons(parentcons);
2665  }
2666  }
2667 
2668  if( C != NULL )
2669  {
2670  SCIPdebugMessage("Csize = %d\n", Csize);
2671 
2672  for( i = 0; i < Csize; ++i )
2673  {
2674  assert(sequencesizes != NULL);
2675 
2676  for( c = 0; c < sequencesizes[i]; ++c )
2677  {
2678  SCIPdebugMessage("C[%d][%d].component = %s\n", i, c, SCIPvarGetName(C[i][c].component) );
2679  SCIPdebugMessage("C[%d][%d].sense = %d\n", i, c, C[i][c].sense);
2680  SCIPdebugMessage("C[%d][%d].bound = %.6g\n", i, c, C[i][c].bound);
2681  }
2682  }
2683  /* SCIP_CALL( InducedLexicographicSort(scip, F, Fsize, C, Csize, sequencesizes) ); */
2684  SCIP_CALL( ChooseSeparateMethod(origscip, F, Fsize, &S, &Ssize, C, Csize, sequencesizes, blocknr, branchrule, result, checkedblocks,
2685  ncheckedblocks, checkedblockssortstrips, checkedblocksnsortstrips) );
2686  }
2687  else
2688  {
2689  SCIPdebugMessage("C == NULL\n");
2690  /* SCIP_CALL( InducedLexicographicSort( scip, F, Fsize, NULL, 0, NULL ) ); */
2691  SCIP_CALL( ChooseSeparateMethod( origscip, F, Fsize, &S, &Ssize, NULL, 0, NULL, blocknr, branchrule, result,
2692  checkedblocks, ncheckedblocks, checkedblockssortstrips, checkedblocksnsortstrips) );
2693  }
2694  if( sequencesizes != NULL )
2695  {
2696  assert(Csize > 0);
2697  SCIPfreeBufferArray(origscip, &sequencesizes);
2698  }
2699  for( i = Csize - 1; i >= 0; --i )
2700  {
2701  assert(C != NULL );
2702  SCIPfreeBufferArrayNull(origscip, &(C[i]));
2703  }
2704  if( C != NULL )
2705  {
2706  assert( Csize > 0);
2707  SCIPfreeBufferArrayNull(origscip, &C);
2708  }
2709  }
2710  else
2711  {
2712  SCIPdebugMessage("root node\n");
2713  /* SCIP_CALL( InducedLexicographicSort( scip, F, Fsize, NULL, 0, NULL ) ); */
2714  SCIP_CALL( ChooseSeparateMethod( origscip, F, Fsize, &S, &Ssize, NULL, 0, NULL, blocknr, branchrule, result, checkedblocks,
2715  ncheckedblocks, checkedblockssortstrips, checkedblocksnsortstrips) );
2716  }
2717 
2718  /* create the |S|+1 child nodes in the branch-and-bound tree */
2719  if( S != NULL && Ssize > 0 )
2720  {
2721  SCIP_CALL( createChildNodesGeneric(origscip, branchrule, S, Ssize, blocknr, masterbranchcons, result) );
2722  }
2723 
2724  SCIPfreeBufferArrayNull(origscip, &S);
2725  SCIPdebugMessage("free F\n");
2726  SCIPfreeBufferArray(origscip, &F);
2727 
2728  return SCIP_OKAY;
2729 }
2730 
2731 /* from branch_master */
2732 static
2734  SCIP* scip /**< SCIP data structure */
2735  )
2736 {
2737  SCIP_CALL( SCIPincludeNodeselBfs(scip) );
2738  SCIP_CALL( SCIPincludeNodeselDfs(scip) );
2739  SCIP_CALL( SCIPincludeNodeselEstimate(scip) );
2740  SCIP_CALL( SCIPincludeNodeselHybridestim(scip) );
2741  SCIP_CALL( SCIPincludeNodeselRestartdfs(scip) );
2742  SCIP_CALL( SCIPincludeBranchruleAllfullstrong(scip) );
2743  SCIP_CALL( SCIPincludeBranchruleFullstrong(scip) );
2744  SCIP_CALL( SCIPincludeBranchruleInference(scip) );
2745  SCIP_CALL( SCIPincludeBranchruleMostinf(scip) );
2746  SCIP_CALL( SCIPincludeBranchruleLeastinf(scip) );
2747  SCIP_CALL( SCIPincludeBranchrulePscost(scip) );
2748  SCIP_CALL( SCIPincludeBranchruleRandom(scip) );
2749  SCIP_CALL( SCIPincludeBranchruleRelpscost(scip) );
2750  return SCIP_OKAY;
2751 }
2752 /** copy method for master branching rule */
2753 static
2754 SCIP_DECL_BRANCHCOPY(branchCopyGeneric)
2755 {
2756  assert(branchrule != NULL);
2757  assert(scip != NULL);
2758  SCIP_CALL( GCGincludeMasterCopyPlugins(scip) );
2759  return SCIP_OKAY;
2760 }
2761 
2762 /** callback activation method */
2763 static
2764 GCG_DECL_BRANCHACTIVEMASTER(branchActiveMasterGeneric)
2765 {
2766 
2767  SCIP_VAR** mastervars;
2768  int nmastervars;
2769  int i;
2770  int nvarsadded;
2771 
2772  assert(scip != NULL);
2773  assert(GCGisMaster(scip));
2774  assert(branchdata != NULL);
2775  assert(branchdata->mastercons != NULL);
2776 
2777  SCIPdebugMessage("branchActiveMasterGeneric: Block %d, Ssize %d\n", branchdata->consblocknr, branchdata->consSsize);
2778 
2779  if( branchdata->nvars >= SCIPgetNVars(scip) )
2780  return SCIP_OKAY;
2781 
2782  nmastervars = SCIPgetNVars(scip);
2783  mastervars = SCIPgetVars(scip);
2784  nvarsadded = 0;
2785 
2786  for( i = branchdata->nvars; i < nmastervars; ++i )
2787  {
2788  SCIP_Bool added = FALSE;
2789  assert(mastervars[i] != NULL);
2790  assert(GCGvarIsMaster(mastervars[i]));
2791 
2792  SCIP_CALL( addVarToMasterbranch(scip, mastervars[i], branchdata, &added) );
2793  if( added )
2794  ++nvarsadded;
2795 
2796  }
2797  SCIPdebugMessage("%d/%d vars added with lhs=%g\n", nvarsadded, nmastervars-branchdata->nvars, branchdata->lhs);
2798  branchdata->nvars = nmastervars;
2799 
2800  return SCIP_OKAY;
2801 }
2802 
2803 /** callback deactivation method */
2804 static
2805 GCG_DECL_BRANCHDEACTIVEMASTER(branchDeactiveMasterGeneric)
2806 {
2807  assert(scip != NULL);
2808  assert(GCGisMaster(scip));
2809  assert(branchdata != NULL);
2810  assert(branchdata->mastercons != NULL);
2811 
2812  SCIPdebugMessage("branchDeactiveMasterGeneric: Block %d, Ssize %d\n", branchdata->consblocknr, branchdata->consSsize);
2813 
2814  /* set number of variables since last call */
2815  branchdata->nvars = SCIPgetNVars(scip);
2816  return SCIP_OKAY;
2817 }
2818 
2819 
2820 
2821 /** callback propagation method */
2822 static
2823 GCG_DECL_BRANCHPROPMASTER(branchPropMasterGeneric)
2824 {
2825  assert(scip != NULL);
2826  assert(branchdata != NULL);
2827  assert(branchdata->mastercons != NULL);
2828  assert(branchdata->consS != NULL);
2829 
2830  /* SCIPdebugMessage("branchPropMasterGeneric: Block %d ,Ssize %d)\n", branchdata->consblocknr, branchdata->consSsize); */
2831  *result = SCIP_DIDNOTFIND;
2832  return SCIP_OKAY;
2833 }
2834 
2835 /** branching execution method for fractional LP solutions */
2836 static
2837 SCIP_DECL_BRANCHEXECLP(branchExeclpGeneric)
2838 { /*lint --e{715}*/
2839  SCIP* origscip;
2840  SCIP_Bool discretization;
2841 
2842  int* checkedblocks;
2843  int ncheckedblocks;
2844  GCG_STRIP*** checkedblockssortstrips;
2845  int* checkedblocksnsortstrips;
2846 
2847  assert(branchrule != NULL);
2848  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
2849  assert(scip != NULL);
2850  assert(result != NULL);
2851 
2852  origscip = GCGmasterGetOrigprob(scip);
2853  assert(origscip != NULL);
2854 
2855  SCIPdebugMessage("Execrel method of Vanderbecks generic branching\n");
2856 
2857  *result = SCIP_DIDNOTRUN;
2858 
2859  /* the branching scheme only works for the discretization approach */
2860  SCIP_CALL( SCIPgetBoolParam(origscip, "relaxing/gcg/discretization", &discretization) );
2861  if( !discretization )
2862  {
2863  SCIPdebugMessage("Generic branching only for discretization approach\n");
2864  return SCIP_OKAY;
2865  }
2866 
2867  if( GCGisMasterSetCovering(origscip) || GCGisMasterSetPartitioning(origscip) )
2868  {
2869  SCIPdebugMessage("Generic branching executed on a set covering or set partitioning problem\n");
2870  }
2871 
2872  if( GCGrelaxIsOrigSolFeasible(origscip) )
2873  {
2874  SCIPdebugMessage("node cut off, since origsol was feasible, solval = %f\n",
2875  SCIPgetSolOrigObj(origscip, GCGrelaxGetCurrentOrigSol(origscip)));
2876 
2877  *result = SCIP_DIDNOTFIND;
2878  return SCIP_OKAY;
2879  }
2880 
2881  *result = SCIP_BRANCHED;
2882 
2883  checkedblocks = NULL;
2884  ncheckedblocks = 0;
2885  checkedblockssortstrips = NULL;
2886  checkedblocksnsortstrips = NULL;
2887 
2888  SCIP_CALL( GCGbranchGenericInitbranch(scip, branchrule, result, &checkedblocks, &ncheckedblocks, &checkedblockssortstrips, &checkedblocksnsortstrips) );
2889 
2890  return SCIP_OKAY;
2891 }
2892 
2893 /** branching execution method for relaxation solutions */
2894 static
2895 SCIP_DECL_BRANCHEXECEXT(branchExecextGeneric)
2896 { /*lint --e{715}*/
2897  SCIPdebugMessage("Execext method of generic branching\n");
2898 
2899  *result = SCIP_DIDNOTRUN;
2900 
2901  return SCIP_OKAY;
2902 }
2903 
2904 /** branching execution method for not completely fixed pseudo solutions
2905  * @bug this needs to be implemented: #32
2906  */
2907 
2908 static
2909 SCIP_DECL_BRANCHEXECPS(branchExecpsGeneric)
2910 { /*lint --e{715}*/
2911  assert(branchrule != NULL);
2912  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
2913  assert(scip != NULL);
2914  assert(result != NULL);
2915 
2916  SCIPdebugMessage("Execps method of Vanderbecks generic branching\n");
2917 
2918  if( SCIPisStopped(scip) )
2919  {
2920  SCIPwarningMessage(scip, "No branching could be created, solving process cannot be restarted...\n" );
2921 
2922  *result = SCIP_DIDNOTRUN;
2923  return SCIP_OKAY;
2924  }
2925  else
2926  {
2927  SCIPerrorMessage("This method is not implemented, aborting since we cannot recover!\n");
2928  SCIPdialogMessage(scip, NULL, "Due to numerical issues, the problem could not be solved.\n");
2929  SCIPdialogMessage(scip, NULL, "You can try to disable discretization and aggregation and resolve the problem.\n");
2930 
2931  *result = SCIP_DIDNOTRUN;
2932  return SCIP_ERROR;
2933  }
2934 }
2935 
2936 /** initialization method of branching rule (called after problem was transformed) */
2937 static
2938 SCIP_DECL_BRANCHINIT(branchInitGeneric)
2939 {
2940  SCIP* origscip;
2941 
2942  origscip = GCGmasterGetOrigprob(scip);
2943  assert(branchrule != NULL);
2944  assert(origscip != NULL);
2945 
2946  SCIPdebugMessage("Init method of Vanderbecks generic branching\n");
2947 
2948  SCIP_CALL( GCGrelaxIncludeBranchrule(origscip, branchrule, branchActiveMasterGeneric,
2949  branchDeactiveMasterGeneric, branchPropMasterGeneric, NULL, branchDataDeleteGeneric) );
2950 
2951  return SCIP_OKAY;
2952 }
2953 
2954 /** creates the generic branching rule and includes it in SCIP */
2956  SCIP* scip /**< SCIP data structure */
2957  )
2958 {
2959  SCIP_BRANCHRULEDATA* branchruledata;
2960  SCIP_BRANCHRULE* branchrule;
2961 
2962  /* create branching rule data */
2963  branchruledata = NULL;
2964 
2965  SCIPdebugMessage("Include method of Vanderbecks generic branching\n");
2966 
2967  /* include branching rule */
2968  SCIP_CALL( SCIPincludeBranchrule(scip, BRANCHRULE_NAME, BRANCHRULE_DESC, BRANCHRULE_PRIORITY,
2969  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchCopyGeneric,
2971  branchExitsolGeneric, branchExeclpGeneric, branchExecextGeneric, branchExecpsGeneric,
2972  branchruledata) );
2973 
2974  /* include event handler for adding generated mastervars to the branching constraints */
2975  SCIP_CALL( SCIPincludeEventhdlr(scip, EVENTHDLR_NAME, EVENTHDLR_DESC,
2976  NULL, NULL, NULL, NULL, eventInitsolGenericbranchvaradd, eventExitsolGenericbranchvaradd,
2977  NULL, eventExecGenericbranchvaradd,
2978  NULL) );
2979 
2980  branchrule = SCIPfindBranchrule(scip, BRANCHRULE_NAME);
2981  assert(branchrule != NULL);
2982 
2983  SCIP_CALL( GCGconsIntegralorigAddBranchrule(scip, branchrule) );
2984 
2985  return SCIP_OKAY;
2986 }
2987 
2988 /** initializes branchdata */
2990  SCIP* scip, /**< SCIP data structure */
2991  GCG_BRANCHDATA** branchdata /**< branching data to initialize */
2992  )
2993 {
2994  assert(scip != NULL);
2995  assert(branchdata != NULL);
2996 
2997  SCIP_CALL( SCIPallocBlockMemory(scip, branchdata) );
2998  (*branchdata)->consS = NULL;
2999  (*branchdata)->consSsize = 0;
3000  (*branchdata)->maxconsS = 0;
3001  (*branchdata)->C = NULL;
3002  (*branchdata)->mastercons = NULL;
3003  (*branchdata)->consblocknr = -2;
3004 
3005  return SCIP_OKAY;
3006 }
3007 
3008 /** get component bound sequence */
3010  GCG_BRANCHDATA* branchdata /**< branching data */
3011  )
3012 {
3013  assert(branchdata != NULL);
3014  return branchdata->consS;
3015 }
3016 
3017 /** get size of component bound sequence */
3019  GCG_BRANCHDATA* branchdata /**< branching data */
3020  )
3021 {
3022  assert(branchdata != NULL);
3023  return branchdata->consSsize;
3024 }
3025 
3026 /** get id of pricing problem (or block) to which the constraint belongs */
3028  GCG_BRANCHDATA* branchdata /**< branching data */
3029  )
3030 {
3031  assert(branchdata != NULL);
3032  return branchdata->consblocknr;
3033 }
3034 
3035 /** get master constraint */
3037  GCG_BRANCHDATA* branchdata /**< branching data */
3038  )
3039 {
3040  assert(branchdata != NULL);
3041  return branchdata->mastercons;
3042 }
3043 
3044 /** returns true when the branch rule is the generic branchrule */
3046  SCIP_BRANCHRULE* branchrule /**< branchrule to check */
3047 )
3048 {
3049  return (branchrule != NULL) && (strcmp(BRANCHRULE_NAME, SCIPbranchruleGetName(branchrule)) == 0);
3050 }
type definitions for branching rules in GCG projects
int GCGgetBlockRepresentative(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4023
static SCIP_RETCODE Explore(SCIP *scip, GCG_COMPSEQUENCE **C, int Csize, int *sequencesizes, int p, SCIP_VAR **F, int Fsize, SCIP_VAR **IndexSet, int IndexSetSize, GCG_COMPSEQUENCE **S, int *Ssize, GCG_RECORD *record)
SCIP_CONS * GCGconsMasterbranchGetChildcons(SCIP_CONS *cons, int childnr)
static SCIP_RETCODE Separate(SCIP *scip, SCIP_VAR **F, int Fsize, SCIP_VAR **IndexSet, int IndexSetSize, GCG_COMPSEQUENCE *S, int Ssize, GCG_RECORD *record)
static SCIP_RETCODE createDirectBranchingCons(SCIP *scip, SCIP_NODE *node, GCG_BRANCHDATA *branchdata)
GCG_COMPSENSE
int GCGmasterVarGetNOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:886
GCG interface methods.
SCIP * scip
SCIP_Bool GCGvarIsMaster(SCIP_VAR *var)
Definition: gcgvar.c:150
SCIP_Bool GCGrelaxIsOrigSolFeasible(SCIP *scip)
Definition: relax_gcg.c:4202
static int ILOcomp(SCIP *scip, SCIP_VAR *mastervar1, SCIP_VAR *mastervar2, GCG_COMPSEQUENCE **C, int NBoundsequences, int *sequencesizes, int p)
int GCGoriginalVarGetNMastervars(SCIP_VAR *var)
Definition: gcgvar.c:569
int * sequencesizes
GCG_BRANCHDATA * GCGconsMasterbranchGetBranchdata(SCIP_CONS *cons)
SCIP_VAR ** GCGoriginalVarGetMastervars(SCIP_VAR *var)
Definition: gcgvar.c:587
static SCIP_RETCODE addToRecord(SCIP *scip, GCG_RECORD *record, GCG_COMPSEQUENCE *S, int Ssize)
GCG_COMPSEQUENCE ** record
int GCGbranchGenericBranchdataGetConsSsize(GCG_BRANCHDATA *branchdata)
SCIP_RETCODE GCGcreateConsMasterbranch(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_NODE *node, SCIP_CONS *parentcons, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata, SCIP_CONS **origbranchconss, int norigbranchconss, int maxorigbranchconss)
SCIP_RETCODE GCGbranchGenericInitbranch(SCIP *masterscip, SCIP_BRANCHRULE *branchrule, SCIP_RESULT *result, int **checkedblocks, int *ncheckedblocks, GCG_STRIP ****checkedblockssortstrips, int **checkedblocksnsortstrips)
#define EVENTHDLR_DESC
#define BRANCHRULE_MAXDEPTH
static SCIP_DECL_BRANCHCOPY(branchCopyGeneric)
SCIP_VAR ** GCGmasterVarGetOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:908
SCIP_Real * GCGmasterVarGetOrigvals(SCIP_VAR *var)
Definition: gcgvar.c:932
int GCGvarGetBlock(SCIP_VAR *var)
Definition: gcgvar.c:1033
static SCIP_DECL_EVENTEXITSOL(eventExitsolGenericbranchvaradd)
static SCIP_RETCODE GCGincludeMasterCopyPlugins(SCIP *scip)
#define BRANCHRULE_NAME
#define branchExitGeneric
SCIP_Bool GCGmasterVarIsLinking(SCIP_VAR *var)
Definition: gcgvar.c:828
int GCGconsMasterbranchGetNChildconss(SCIP_CONS *cons)
int GCGgetNPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3979
static SCIP_RETCODE initNodeBranchdata(SCIP *scip, GCG_BRANCHDATA **nodebranchdata, int blocknr)
GCG_COMPSEQUENCE * consS
GCG variable pricer.
int * capacities
SCIP_RETCODE GCGbranchGenericCreateBranchdata(SCIP *scip, GCG_BRANCHDATA **branchdata)
static SCIP_Bool pruneChildNodeByDominanceGeneric(SCIP *scip, SCIP_Real lhs, GCG_COMPSEQUENCE *childS, int childSsize, SCIP_CONS *masterbranchcons, int childBlocknr)
static SCIP_RETCODE addVarToMasterbranch(SCIP *scip, SCIP_VAR *mastervar, GCG_BRANCHDATA *branchdata, SCIP_Bool *added)
static SCIP_RETCODE createBranchingCons(SCIP *scip, SCIP_NODE *node, GCG_BRANCHDATA *branchdata)
SCIP * GCGgetMasterprob(SCIP *scip)
Definition: relax_gcg.c:3920
static SCIP_RETCODE partition(SCIP *scip, SCIP_VAR **J, int *Jsize, SCIP_Longint *priority, SCIP_VAR **F, int Fsize, SCIP_VAR **origvar, SCIP_Real *median)
constraint handler for the integrality constraint
static SCIP_RETCODE InducedLexicographicSort(SCIP *scip, GCG_STRIP **array, int arraysize, GCG_COMPSEQUENCE **C, int NBoundsequences, int *sequencesizes)
SCIP_EXPORT void GCGsortPtr(void **ptrarray, GCG_DECL_SORTPTRCOMP((*ptrcomp)), void *userdata, int len)
SCIP_BRANCHRULE * GCGconsMasterbranchGetBranchrule(SCIP_CONS *cons)
constraint handler for storing the branching decisions at each node of the tree
static SCIP_RETCODE createChildNodesGeneric(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_COMPSEQUENCE *S, int Ssize, int blocknr, SCIP_CONS *masterbranchcons, SCIP_RESULT *result)
static SCIP_DECL_BRANCHINIT(branchInitGeneric)
static SCIP_RETCODE LexicographicSort(SCIP *scip, GCG_STRIP **array, int arraysize)
static SCIP_DECL_BRANCHEXECPS(branchExecpsGeneric)
SCIP_Bool GCGisMaster(SCIP *scip)
Definition: misc.c:675
#define branchExitsolGeneric
#define BRANCHRULE_DESC
#define branchFreeGeneric
@ GCG_COMPSENSE_GE
branching rule based on vanderbeck's generic branching scheme
constraint handler for storing the branching decisions at each node of the tree
static SCIP_RETCODE InitIndexSet(SCIP *scip, SCIP_VAR **F, int Fsize, SCIP_VAR ***IndexSet, int *IndexSetSize)
#define EVENTHDLR_NAME
int GCGbranchGenericBranchdataGetConsblocknr(GCG_BRANCHDATA *branchdata)
int GCGgetNIdenticalBlocks(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4053
static SCIP_Real getGeneratorEntry(SCIP_VAR *mastervar, SCIP_VAR *origvar)
GCG_COMPSEQUENCE ** C
static GCG_DECL_BRANCHPROPMASTER(branchPropMasterGeneric)
SCIP_VAR * mastervar
SCIP_CONS * mastercons
static SCIP_DECL_BRANCHEXECEXT(branchExecextGeneric)
int * sequencesizes
static SCIP_DECL_EVENTEXEC(eventExecGenericbranchvaradd)
SCIP * GCGmasterGetOrigprob(SCIP *scip)
SCIP_RETCODE GCGpricerExistRays(SCIP *scip, SCIP_Bool *exist)
GCG_COMPSEQUENCE * GCGbranchGenericBranchdataGetConsS(GCG_BRANCHDATA *branchdata)
static int computeNewSequence(int Csize, int p, SCIP_VAR *origvar, int *sequencesizes, GCG_COMPSEQUENCE **C, GCG_COMPSEQUENCE **CopyC, int *newsequencesizes, GCG_COMPSENSE sense)
SCIP_SOL * GCGrelaxGetCurrentOrigSol(SCIP *scip)
Definition: relax_gcg.c:4183
SCIP_RETCODE SCIPincludeBranchruleGeneric(SCIP *scip)
static GCG_DECL_BRANCHDEACTIVEMASTER(branchDeactiveMasterGeneric)
SCIP_CONS * GCGconsMasterbranchGetParentcons(SCIP_CONS *cons)
static SCIP_DECL_EVENTINITSOL(eventInitsolGenericbranchvaradd)
static SCIP_DECL_SORTPTRCOMP(ptrilocomp)
static SCIP_DECL_BRANCHEXECLP(branchExeclpGeneric)
SCIP_CONS * GCGbranchGenericBranchdataGetMastercons(GCG_BRANCHDATA *branchdata)
#define BRANCHRULE_MAXBOUNDDIST
static SCIP_RETCODE ChoseS(SCIP *scip, GCG_RECORD **record, GCG_COMPSEQUENCE **S, int *Ssize)
SCIP_Bool GCGisBranchruleGeneric(SCIP_BRANCHRULE *branchrule)
GCG relaxator.
static SCIP_RETCODE ChooseSeparateMethod(SCIP *scip, SCIP_VAR **F, int Fsize, GCG_COMPSEQUENCE **S, int *Ssize, GCG_COMPSEQUENCE **C, int Csize, int *CompSizes, int blocknr, SCIP_BRANCHRULE *branchrule, SCIP_RESULT *result, int **checkedblocks, int *ncheckedblocks, GCG_STRIP ****checkedblockssortstrips, int **checkedblocksnsortstrips)
SCIP_CONS * GCGconsMasterbranchGetActiveCons(SCIP *scip)
static GCG_DECL_BRANCHDATADELETE(branchDataDeleteGeneric)
SCIP_Bool GCGmasterVarIsArtificial(SCIP_VAR *var)
Definition: gcgvar.c:869
int recordcapacity
#define branchInitsolGeneric
static SCIP_RETCODE branchDirectlyOnMastervar(SCIP *scip, SCIP_VAR *mastervar, SCIP_BRANCHRULE *branchrule)
#define BRANCHRULE_PRIORITY
static SCIP_Real GetMedian(SCIP *scip, SCIP_Real *array, int arraysize, SCIP_Real min)
sorting functions, adapted from SCIP's sorttpl to include userdata
SCIP_Bool GCGisMasterSetPartitioning(SCIP *scip)
Definition: relax_gcg.c:4240
static GCG_DECL_SORTPTRCOMP(ptrcomp)
SCIP_Bool GCGisMasterVarInBlock(SCIP_VAR *mastervar, int block)
Definition: gcgvar.c:1084
static GCG_DECL_BRANCHACTIVEMASTER(branchActiveMasterGeneric)
GCG_COMPSEQUENCE ** C
SCIP_Bool GCGisMasterSetCovering(SCIP *scip)
Definition: relax_gcg.c:4221
SCIP_RETCODE GCGrelaxIncludeBranchrule(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_DECL_BRANCHACTIVEMASTER((*branchactivemaster)), GCG_DECL_BRANCHDEACTIVEMASTER((*branchdeactivemaster)), GCG_DECL_BRANCHPROPMASTER((*branchpropmaster)), GCG_DECL_BRANCHMASTERSOLVED((*branchmastersolved)), GCG_DECL_BRANCHDATADELETE((*branchdatadelete)))
Definition: relax_gcg.c:3545
static SCIP_Bool checkchildconsS(SCIP *scip, SCIP_Real lhs, GCG_COMPSEQUENCE *childS, int childSsize, SCIP_CONS *parentcons, int childBlocknr)
static double computeAlpha(SCIP *scip, int Fsize, GCG_COMPSENSE isense, double ivalue, SCIP_VAR *origvar, SCIP_VAR **F)
@ GCG_COMPSENSE_LT
SCIP_RETCODE GCGconsIntegralorigAddBranchrule(SCIP *scip, SCIP_BRANCHRULE *branchrule)