Scippy

GCG

Branch-and-Price & Column Generation for Everyone

relax_gcg.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 relax_gcg.c
29  * @ingroup RELAXATORS
30  * @brief GCG relaxator
31  * @author Gerald Gamrath
32  * @author Martin Bergner
33  * @author Alexander Gross
34  * @author Michael Bastubbe
35  *
36  * \bug
37  * - The memory limit is not strictly enforced
38  * - Dealing with timelimits is a working hack only
39  * - CTRL-C handling is very flaky
40  */
41 
42 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
43 
44 //#define SCIP_DEBUG
45 
46 #include <string.h>
47 
48 #include "scip/scipdefplugins.h"
49 #include "scip/cons_linear.h"
50 #include "scip/cons_setppc.h"
51 #include "scip/scip.h"
52 #include "scip/misc.h"
53 #include "scip/clock.h"
54 
55 #include "relax_gcg.h"
56 
57 #include "struct_branchgcg.h"
58 
59 #include "cons_origbranch.h"
60 #include "cons_masterbranch.h"
61 #include "pricer_gcg.h"
62 #include "benders_gcg.h"
63 #include "masterplugins.h"
64 #include "bendersplugins.h"
65 #include "cons_decomp.h"
66 #include "scip_misc.h"
67 
68 #include "params_visu.h"
69 
70 #include "gcg.h"
71 
72 #ifdef WITH_BLISS
73 #include "pub_bliss.h"
74 #include "bliss_automorph.h"
75 #endif
76 
77 #define RELAX_NAME "gcg"
78 #define RELAX_DESC "relaxator for gcg project representing the master lp"
79 #define RELAX_PRIORITY -1
80 #define RELAX_FREQ 1
81 #define RELAX_INCLUDESLP TRUE
82 
83 #define DEFAULT_DISCRETIZATION TRUE
84 #define DEFAULT_MIPDISCRETIZATION TRUE
85 #define DEFAULT_AGGREGATION TRUE
86 #define DEFAULT_DISPINFOS FALSE
87 #define DEFAULT_MODE DEC_DECMODE_DANTZIGWOLFE /**< the decomposition mode that GCG will use. (0: Dantzig-Wolfe (default),
88  1: Benders' decomposition, 2: solve original problem) */
89 #define DEFAULT_BLISS TRUE
90 #define DEFAULT_BLISS_SEARCH_NODE_LIMIT 0
91 #define DEFAULT_BLISS_GENERATOR_LIMIT 0
92 #define DELVARS
93 
94 /*
95  * Data structures
96  */
97 
98 /** relaxator data */
99 
101 {
102  /* problems and convexity constraints */
103  SCIP* masterprob; /**< the master problem */
104  SCIP* altmasterprob; /**< the master problem for the alternate decomposition algorithm */
105  SCIP** pricingprobs; /**< the array of pricing problems */
106  int npricingprobs; /**< the number of pricing problems */
107  int nrelpricingprobs; /**< the number of relevant pricing problems */
108  int* blockrepresentative;/**< number of the pricing problem, that represents the i-th problem */
109  int* nblocksidentical; /**< number of pricing blocks represented by the i-th pricing problem */
110  SCIP_CONS** convconss; /**< array of convexity constraints, one for each block */
111  int ntransvars; /**< number of variables directly transferred to the master problem */
112  int nlinkingvars; /**< number of linking variables */
113  int nvarlinkconss; /**< number of constraints that ensure that copies of linking variables have the same value */
114  SCIP_Real pricingprobsmemused; /**< sum of memory used after problem creation stage of all pricing problems */
115 
116  /* hashmaps for transformation */
117  SCIP_HASHMAP* hashorig2origvar; /**< hashmap mapping original variables to themselves */
118 
119  /* constraint data */
120  SCIP_CONS** masterconss; /**< array of constraints in the master problem */
121  SCIP_CONS** origmasterconss; /**< array of constraints in the original problem that belong to the
122  * master problem */
123  SCIP_CONS** linearmasterconss; /**< array of linear constraints equivalent to the cons in
124  * the original problem that belong to the master problem */
125  SCIP_CONS** varlinkconss; /**< array of constraints ensuring linking vars equality */
126  int* varlinkconsblock; /**< array of constraints ensuring linking vars equality */
127  int maxmasterconss; /**< length of the array mastercons */
128  int nmasterconss; /**< number of constraints saved in mastercons */
129 
130  SCIP_SOL* currentorigsol; /**< current lp solution transformed into the original space */
131  SCIP_Bool origsolfeasible; /**< is the current lp solution primal feasible in the original space? */
132  SCIP_Longint lastmasterlpiters; /**< number of lp iterations when currentorigsol was updated the last time */
133  SCIP_SOL* lastmastersol; /**< last feasible master solution that was added to the original problem */
134  SCIP_CONS** markedmasterconss; /**< array of conss that are marked to be in the master */
135  int nmarkedmasterconss; /**< number of elements in array of conss that are marked to be in the master */
136  int maxmarkedmasterconss; /**< capacity of markedmasterconss */
137  SCIP_Longint lastsolvednodenr; /**< node number of the node that was solved at the last call of the relaxator */
138 
139  /* branchrule data */
140  GCG_BRANCHRULE** branchrules; /**< branching rules registered in the relaxator */
141  int nbranchrules; /**< number of branching rules registered in the relaxator */
142 
143  /* parameter data */
144  SCIP_Bool discretization; /**< TRUE: use discretization approach; FALSE: use convexification approach */
145  SCIP_Bool mipdiscretization; /**< TRUE: use discretization approach in MIPs; FALSE: use convexification approach in MIPs*/
146  SCIP_Bool aggregation; /**< should identical blocks be aggregated (only for discretization approach)? */
147  SCIP_Bool masterissetpart; /**< is the master a set partitioning problem? */
148  SCIP_Bool masterissetcover; /**< is the master a set covering problem? */
149  SCIP_Bool dispinfos; /**< should additional information be displayed? */
150  DEC_DECMODE mode; /**< the decomposition mode for GCG. 0: Dantzig-Wolfe (default), 1: Benders' decomposition, 2: automatic */
151  int origverblevel; /**< the verbosity level of the original problem */
152  SCIP_Bool usebliss; /**< should bliss be used to check for identical blocks? */
153  int searchnodelimit; /**< bliss search node limit (requires patched bliss version) */
154  int generatorlimit; /**< bliss generator limit (requires patched bliss version) */
155 
156  /* data for probing */
157  SCIP_Bool masterinprobing; /**< is the master problem in probing mode? */
158  SCIP_HEUR* probingheur; /**< heuristic that started probing in master problem, or NULL */
159  SCIP_SOL* storedorigsol; /**< original solution that was stored before the probing */
160  SCIP_Bool storedfeasibility; /**< is the stored original solution feasible? */
161 
162  /* structure information */
163  DEC_DECOMP* decomp; /**< structure information */
164  SCIP_Bool relaxisinitialized; /**< indicates whether the relaxator is initialized */
165 
166  /* statistical information */
167  SCIP_Longint simplexiters; /**< cumulative simplex iterations */
168  SCIP_CLOCK* rootnodetime; /**< time in root node */
169 
170  /* visualization parameter */
171  GCG_PARAMDATA* paramsvisu; /**< parameters for visualization */
172 };
173 
174 
175 /*
176  * Local methods
177  */
178 
179 /** sets the number of the block, the given original variable belongs to */
180 static
182  SCIP* scip, /**< SCIP data structure */
183  SCIP_RELAXDATA* relaxdata, /**< relaxator data data structure */
184  SCIP_VAR* var, /**< variable to set the block number for */
185  int newblock /**< number of the block, the variable belongs to */
186  )
187 {
188  int blocknr;
189 
190  assert(scip != NULL);
191  assert(var != NULL);
192  assert(newblock >= 0 || (GCGgetDecompositionMode(scip) == DEC_DECMODE_BENDERS && newblock == -2));
193 
194  assert(SCIPvarIsOriginal(var) || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
195  assert(relaxdata != NULL);
196 
197  blocknr = GCGvarGetBlock(var);
198  assert(GCGvarIsOriginal(var));
199 
200  assert(relaxdata->npricingprobs > 0);
201  assert(newblock < relaxdata->npricingprobs);
202  assert(blocknr >= -2 && blocknr < relaxdata->npricingprobs);
203 
204  /* var belongs to no block so far, just set the new block number */
205  if( blocknr == -1 )
206  {
207  assert(newblock >= 0);
208  GCGvarSetBlock(var, newblock);
209  }
210  /* if var already belongs to another block, it is a linking variable */
211  else if( blocknr != newblock )
212  {
213  SCIP_CALL( GCGoriginalVarAddBlock(scip, var, newblock, relaxdata->npricingprobs, relaxdata->mode) );
214  assert(newblock == -2 || GCGisLinkingVarInBlock(var, newblock));
215  assert(GCGoriginalVarIsLinking(var));
216  }
217  blocknr = GCGvarGetBlock(var);
218  assert(blocknr == -2 || blocknr == newblock);
219 
220  return SCIP_OKAY;
221 }
222 
223 /** marks the constraint to be transferred to the master problem */
224 static
225 SCIP_RETCODE markConsMaster(
226  SCIP* scip, /**< SCIP data structure */
227  SCIP_RELAXDATA* relaxdata, /**< relaxator data data structure */
228  SCIP_CONS* cons /**< constraint that is forced to be in the master */
229  )
230 {
231 #ifndef NDEBUG
232  int i;
233 #endif
234  assert(scip != NULL);
235  assert(cons != NULL);
236  assert(relaxdata != NULL);
237 
238  /* allocate array, if not yet done */
239  if( relaxdata->markedmasterconss == NULL )
240  {
241  relaxdata->maxmarkedmasterconss = SCIPcalcMemGrowSize(scip, SCIPgetNConss(scip));
242  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(relaxdata->markedmasterconss), relaxdata->maxmarkedmasterconss) );
243  relaxdata->nmarkedmasterconss = 0;
244  }
245  assert(relaxdata->nmarkedmasterconss <= SCIPgetNConss(scip));
246 
247 #ifndef NDEBUG
248  /* check that constraints are not marked more than one time */
249  for( i = 0; i < relaxdata->nmarkedmasterconss; i++ )
250  assert(relaxdata->markedmasterconss[i] != cons);
251 #endif
252 
253  /* save constraint */
254  relaxdata->markedmasterconss[relaxdata->nmarkedmasterconss] = cons;
255  relaxdata->nmarkedmasterconss++;
256 
257  return SCIP_OKAY;
258 }
259 
260 
261 /** converts the structure to the GCG format by setting the appropriate blocks and master constraints */
262 static
263 SCIP_RETCODE convertStructToGCG(
264  SCIP* scip, /**< SCIP data structure */
265  SCIP_RELAXDATA* relaxdata, /**< relaxator data structure */
266  DEC_DECOMP* decomp /**< decomp data structure */
267  )
268 {
269  int i;
270  int j;
271  int k;
272  int v;
273  int nblocks;
274  int nvars;
275  SCIP_VAR** origvars;
276  SCIP_HASHMAP* transvar2origvar;
277  SCIP_CONS** linkingconss;
278  int nlinkingconss;
279  SCIP_VAR** linkingvars;
280  int nlinkingvars;
281  SCIP_VAR*** subscipvars;
282  int* nsubscipvars;
283  SCIP_CONS*** subscipconss;
284  int* nsubscipconss;
285 
286  assert(decomp != NULL);
287  assert(relaxdata != NULL);
288  assert(scip != NULL);
289 
290  assert(DECdecompGetLinkingconss(decomp) != NULL || DECdecompGetNLinkingconss(decomp) == 0);
291  assert(DECdecompGetNSubscipvars(decomp) != NULL || DECdecompGetSubscipvars(decomp) == NULL);
292 
293 
294  SCIP_CALL( DECdecompAddRemainingConss(scip, decomp) );
295  SCIP_CALL( DECdecompCheckConsistency(scip, decomp) );
296 
297 
298 
299  origvars = SCIPgetOrigVars(scip);
300  nvars = SCIPgetNOrigVars(scip);
301  linkingconss = DECdecompGetLinkingconss(decomp);
302  nlinkingconss = DECdecompGetNLinkingconss(decomp);
303  linkingvars = DECdecompGetLinkingvars(decomp);
304  nlinkingvars = DECdecompGetNLinkingvars(decomp);
305  subscipvars = DECdecompGetSubscipvars(decomp);
306  nsubscipvars = DECdecompGetNSubscipvars(decomp);
307 
308  subscipconss = DECdecompGetSubscipconss(decomp);
309  nsubscipconss = DECdecompGetNSubscipconss(decomp);
310  nblocks = DECdecompGetNBlocks(decomp);
311 
312  SCIP_CALL( SCIPhashmapCreate(&transvar2origvar, SCIPblkmem(scip), nvars) );
313  relaxdata->npricingprobs = nblocks;
314  SCIP_CALL( GCGcreateOrigVarsData(scip) );
315 
316  SCIPdebugMessage("Copying structure with %d blocks, %d linking vars and %d linking constraints.\n", nblocks, nlinkingvars, nlinkingconss);
317 
318  /* set master constraints */
319  for( i = 0; i < nlinkingconss; ++i )
320  {
321  assert(linkingconss[i] != NULL);
322  /* SCIPdebugMessage("\tProcessing linking constraint %s.\n", SCIPconsGetName(linkingconss[i])); */
323  if( SCIPconsIsActive(linkingconss[i]) )
324  {
325  SCIP_CALL( markConsMaster(scip, relaxdata, linkingconss[i]) );
326  }
327  }
328 
329  /* prepare the map from transformed to original variables */
330  for( i = 0; i < nvars; ++i )
331  {
332  SCIP_VAR* transvar;
333 
334  SCIP_CALL( SCIPgetTransformedVar(scip, origvars[i], &transvar) );
335  assert(transvar != NULL);
336 
337  SCIP_CALL( SCIPhashmapInsert(transvar2origvar, transvar, origvars[i]) );
338  }
339 
340  for( i = 0; i < nblocks; ++i )
341  {
342  /* SCIPdebugMessage("\tProcessing block %d (%d conss, %d vars).\n", i, nsubscipconss[i], nsubscipvars[i]); */
343  assert((subscipvars[i] == NULL) == (nsubscipvars[i] == 0));
344  for( j = 0; j < nsubscipvars[i]; ++j )
345  {
346  SCIP_VAR* relevantvar;
347  assert(subscipvars[i][j] != NULL);
348  relevantvar = SCIPvarGetProbvar(subscipvars[i][j]);
349 
350  /* If there is a corresponding original (untransformed) variable, assign it to the block */
351  if( SCIPhashmapGetImage(transvar2origvar, subscipvars[i][j]) != NULL )
352  {
353  SCIP_VAR* origvar;
354 
355  origvar = (SCIP_VAR*) SCIPhashmapGetImage(transvar2origvar, subscipvars[i][j]);
356  assert(SCIPvarGetData(origvar) != NULL);
357 
358  SCIP_CALL( setOriginalVarBlockNr(scip, relaxdata, origvar, i) );
359  SCIPdebugMessage("\t\tOriginal var %s (%p) in block %d\n", SCIPvarGetName(subscipvars[i][j]), (void*) subscipvars[i][j], i);
360  }
361 
362  /* Assign the corresponding problem variable to the block */
363  if( SCIPvarGetData(relevantvar) == NULL )
364  SCIP_CALL( GCGorigVarCreateData(scip, relevantvar) );
365  SCIP_CALL( setOriginalVarBlockNr(scip, relaxdata, relevantvar, i) );
366 
367  SCIPdebugMessage("\t\tTransformed var %s (%p) in block %d\n", SCIPvarGetName(relevantvar), (void*) relevantvar, i);
368 
369  assert(SCIPvarGetData(subscipvars[i][j]) != NULL || SCIPvarGetData(relevantvar) != NULL);
370  }
371  }
372  SCIPdebugMessage("\tProcessing linking variables.\n");
373  for( i = 0; i < nlinkingvars; ++i )
374  {
375  int nfound = 0;
376 
377  if( GCGoriginalVarIsLinking(linkingvars[i]) )
378  continue;
379 
380  SCIPdebugMessage("\tDetecting constraint blocks of linking var %s\n", SCIPvarGetName(linkingvars[i]));
381  /* HACK; @todo find out constraint blocks more intelligently */
382  for( j = 0; j < nblocks; ++j )
383  {
384  int found = FALSE;
385  for( k = 0; k < nsubscipconss[j]; ++k )
386  {
387  SCIP_VAR** curvars;
388  int ncurvars;
389  if( SCIPconsIsDeleted(subscipconss[j][k]) )
390  continue;
391  ncurvars = GCGconsGetNVars(scip, subscipconss[j][k]);
392  curvars = NULL;
393  if( ncurvars > 0 )
394  {
395  SCIP_CALL( SCIPallocBufferArray(scip, &curvars, ncurvars) );
396  SCIP_CALL( GCGconsGetVars(scip, subscipconss[j][k], curvars, ncurvars) );
397 
398  for( v = 0; v < ncurvars; ++v )
399  {
400  if( SCIPvarGetProbvar(curvars[v]) == linkingvars[i] || curvars[v] == linkingvars[i] )
401  {
402  SCIPdebugMessage("\t\t%s is in %d\n", SCIPvarGetName(SCIPvarGetProbvar(curvars[v])), j);
403  assert(SCIPvarGetData(linkingvars[i]) != NULL);
404  SCIP_CALL( setOriginalVarBlockNr(scip, relaxdata, SCIPvarGetProbvar(linkingvars[i]), j) );
405  found = TRUE;
406  break;
407  }
408  }
409 
410  SCIPfreeBufferArray(scip, &curvars);
411  }
412 
413  if( found )
414  {
415  nfound++;
416  break;
417  }
418 
419  }
420  }
421 
422  /* if the linking variable is only in one block, then it would not have been flagged as a linking variable. In
423  * the Benders' decomposition case, then linking variable needs to be flagged as linking so that it is added to
424  * the master problem.
425  */
426  if( nfound == 1 && GCGgetDecompositionMode(scip) == DEC_DECMODE_BENDERS )
427  {
428  SCIP_CALL( setOriginalVarBlockNr(scip, relaxdata, SCIPvarGetProbvar(linkingvars[i]), -2) );
429  }
430  }
431 
432  SCIPhashmapFree(&transvar2origvar);
433  return SCIP_OKAY;
434 }
435 
436 /** ensures size of masterconss array */
437 static
439  SCIP* scip,
440  SCIP_RELAXDATA* relaxdata,
441  int size
442  )
443 {
444  assert(scip != NULL);
445  assert(relaxdata != NULL);
446  assert(relaxdata->masterconss != NULL);
447 
448  if( relaxdata->maxmasterconss < size )
449  {
450  int newsize = SCIPcalcMemGrowSize(scip, size);
451  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(relaxdata->masterconss), relaxdata->maxmasterconss, newsize) );
452  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(relaxdata->origmasterconss), relaxdata->maxmasterconss, newsize) );
453  relaxdata->maxmasterconss = newsize;
454 
455  }
456  assert(relaxdata->maxmasterconss >= size);
457 
458  return SCIP_OKAY;
459 }
460 
461 /** ensures size of branchrules array: enlarges the array by 1 */
462 static
464  SCIP* scip,
465  SCIP_RELAXDATA* relaxdata
466  )
467 {
468  assert(scip != NULL);
469  assert(relaxdata != NULL);
470  assert((relaxdata->branchrules == NULL) == (relaxdata->nbranchrules == 0));
471 
472  if( relaxdata->nbranchrules == 0 )
473  {
474  SCIP_CALL( SCIPallocMemoryArray(scip, &(relaxdata->branchrules), 1) ); /*lint !e506*/
475  }
476  else
477  {
478  SCIP_CALL( SCIPreallocMemoryArray(scip, &(relaxdata->branchrules), (size_t)relaxdata->nbranchrules+1) );
479  }
480 
481  return SCIP_OKAY;
482 }
483 
484 
485 /** check whether the master problem has a set partitioning or set covering structure */
486 static
487 SCIP_RETCODE checkSetppcStructure(
488  SCIP* scip, /**< SCIP data structure */
489  SCIP_RELAXDATA* relaxdata /**< relaxator data structure */
490  )
491 {
492  SCIP_CONS** masterconss;
493  int nmasterconss;
494 
495  int i;
496 
497  assert(relaxdata->decomp != NULL);
498 
499  masterconss = DECdecompGetLinkingconss(relaxdata->decomp);
500  nmasterconss = DECdecompGetNLinkingconss(relaxdata->decomp);
501  assert(nmasterconss >= 0);
502  assert(masterconss != NULL || nmasterconss == 0);
503 
504  if( nmasterconss == 0 || relaxdata->nvarlinkconss > 0 )
505  {
506  relaxdata->masterissetcover = FALSE;
507  relaxdata->masterissetpart = FALSE;
508  return SCIP_OKAY;
509  }
510 
511  relaxdata->masterissetcover = TRUE;
512  relaxdata->masterissetpart = TRUE;
513 
514  for( i = 0; i < nmasterconss; ++i )
515  {
516  assert(masterconss != NULL);
517 
518  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(masterconss[i])), "setppc") == 0 )
519  {
520  switch( SCIPgetTypeSetppc(scip, masterconss[i]) )
521  {
522  case SCIP_SETPPCTYPE_COVERING:
523  relaxdata->masterissetpart = FALSE;
524  break;
525  case SCIP_SETPPCTYPE_PARTITIONING:
526  relaxdata->masterissetcover = FALSE;
527  break;
528  case SCIP_SETPPCTYPE_PACKING:
529  relaxdata->masterissetcover = FALSE;
530  relaxdata->masterissetpart = FALSE;
531  break;
532  }
533  }
534  else if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(masterconss[i])), "logicor") == 0 )
535  {
536  relaxdata->masterissetpart = FALSE;
537  break;
538  }
539  else if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(masterconss[i])), "linear") == 0 )
540  {
541  SCIP_SETPPCTYPE type;
542 
543  if( GCGgetConsIsSetppc(scip, masterconss[i], &type) )
544  {
545  switch( type )
546  {
547  case SCIP_SETPPCTYPE_COVERING:
548  relaxdata->masterissetpart = FALSE;
549  break;
550  case SCIP_SETPPCTYPE_PARTITIONING:
551  relaxdata->masterissetcover = FALSE;
552  break;
553  case SCIP_SETPPCTYPE_PACKING:
554  relaxdata->masterissetcover = FALSE;
555  relaxdata->masterissetpart = FALSE;
556  break;
557  }
558  }
559  else
560  {
561  relaxdata->masterissetcover = FALSE;
562  relaxdata->masterissetpart = FALSE;
563  break;
564  }
565  }
566  else
567  {
568  relaxdata->masterissetcover = FALSE;
569  relaxdata->masterissetpart = FALSE;
570  break;
571  }
572  }
573 
574  if( relaxdata->masterissetcover )
575  {
576  assert(!relaxdata->masterissetpart);
577  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Master problem is a set covering problem.\n");
578  }
579  if( relaxdata->masterissetpart )
580  {
581  assert(!relaxdata->masterissetcover);
582  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Master problem is a set partitioning problem.\n");
583  }
584 
585  return SCIP_OKAY;
586 }
587 
588 /** checks whether two arrays of SCIP_Real's are identical */
589 static
591  SCIP* scip, /**< SCIP data structure */
592  SCIP_Real* array1, /**< first array */
593  int array1length, /**< length of first array */
594  SCIP_Real* array2, /**< second array */
595  int array2length /**< length of second array */
596  )
597 {
598  int i;
599 
600  if( array1length != array2length )
601  return FALSE;
602 
603  if( array1length == 0 )
604  return TRUE;
605 
606  assert(array1 != NULL);
607  assert(array2 != NULL);
608 
609  for( i = 0; i < array1length; i++ )
610  {
611  if( !SCIPisEQ(scip, array1[i], array2[i]) )
612  return FALSE;
613  }
614 
615  return TRUE;
616 }
617 
618 
619 /** checks whether two pricingproblems represent identical blocks */
620 static
621 SCIP_RETCODE checkIdentical(
622  SCIP* scip, /**< SCIP data structure */
623  SCIP_RELAXDATA* relaxdata, /**< the relaxator's data */
624  int probnr1, /**< number of the first pricingproblem */
625  int probnr2, /**< number of the second pricingproblem */
626  SCIP_HASHMAP* varmap, /**< hashmap mapping the variables of the second pricing problem
627  * to those of the first pricing problem */
628  SCIP_Bool* identical, /**< return value: are blocks identical */
629  SCIP* scip1, /**< first SCIP data structure to check */
630  SCIP* scip2 /**< second SCIP data structure to check */
631  )
632 {
633  SCIP_VAR** vars1;
634  SCIP_VAR** vars2;
635  int nvars1;
636  int nvars2;
637 
638  SCIP_CONS** conss1;
639  SCIP_CONS** conss2;
640  int nconss;
641 
642  int i;
643  int j;
644 
645  SCIPdebugMessage("check block %d and block %d for identity...\n", probnr1, probnr2);
646 
647  if( SCIPgetNVars(scip1) != SCIPgetNVars(scip2) )
648  {
649  SCIPdebugMessage("--> number of variables differs!\n");
650  return SCIP_OKAY;
651  }
652  if( SCIPgetNConss(scip1) != SCIPgetNConss(scip2) )
653  {
654  SCIPdebugMessage("--> number of constraints differs!\n");
655  return SCIP_OKAY;
656  }
657  /* get variables */
658  SCIP_CALL( SCIPgetVarsData(scip1, &vars1, &nvars1, NULL, NULL, NULL, NULL) );
659  SCIP_CALL( SCIPgetVarsData(scip2, &vars2, &nvars2, NULL, NULL, NULL, NULL) );
660 
661  for( i = 0; i < nvars1; i++ )
662  {
663  SCIP_Real* coefs1;
664  int ncoefs1;
665  SCIP_Real* coefs2;
666  int ncoefs2;
667  SCIP_VAR** origvars1;
668  SCIP_VAR** origvars2;
669 
670  if( !SCIPisEQ(relaxdata->masterprob, SCIPvarGetObj(vars1[i]), SCIPvarGetObj(vars2[i])) )
671  {
672  SCIPdebugMessage("--> obj differs for var %s and var %s!\n", SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
673  return SCIP_OKAY;
674  }
675  if( !SCIPisEQ(relaxdata->masterprob, SCIPvarGetLbOriginal(vars1[i]), SCIPvarGetLbOriginal(vars2[i])) )
676  {
677  SCIPdebugMessage("--> lb differs for var %s and var %s!\n", SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
678  return SCIP_OKAY;
679  }
680  if( !SCIPisEQ(relaxdata->masterprob, SCIPvarGetUbOriginal(vars1[i]), SCIPvarGetUbOriginal(vars2[i])) )
681  {
682  SCIPdebugMessage("--> ub differs for var %s and var %s!\n", SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
683  return SCIP_OKAY;
684  }
685  if( SCIPvarGetType(vars1[i]) != SCIPvarGetType(vars2[i]) )
686  {
687  SCIPdebugMessage("--> type differs for var %s and var %s!\n", SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
688  return SCIP_OKAY;
689  }
690 
691  assert(GCGvarIsPricing(vars1[i]));
692  assert(GCGvarIsPricing(vars2[i]));
693 
694  origvars1 = GCGpricingVarGetOrigvars(vars1[i]);
695  origvars2 = GCGpricingVarGetOrigvars(vars2[i]);
696 
697  if( !SCIPisEQ(relaxdata->masterprob, SCIPvarGetObj(origvars1[0]),SCIPvarGetObj(origvars2[0])) )
698  {
699  SCIPdebugMessage("--> orig obj differs for var %s and var %s!\n", SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
700  return SCIP_OKAY;
701  }
702 
703  assert(GCGvarIsOriginal(origvars1[0]));
704  assert(GCGvarIsOriginal(origvars2[0]));
705 
706  ncoefs1 = GCGoriginalVarGetNCoefs(origvars1[0]);
707  ncoefs2 = GCGoriginalVarGetNCoefs(origvars2[0]);
708 
709  /* nunber of coefficients differs */
710  if( ncoefs1 != ncoefs2 )
711  {
712  SCIPdebugMessage("--> number of coefficients differs for var %s and var %s!\n",
713  SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
714  return SCIP_OKAY;
715  }
716 
717  /* get master constraints and corresponding coefficients of both variables */
718  conss1 = GCGoriginalVarGetMasterconss(origvars1[0]);
719  conss2 = GCGoriginalVarGetMasterconss(origvars2[0]);
720  coefs1 = GCGoriginalVarGetCoefs(origvars1[0]);
721  coefs2 = GCGoriginalVarGetCoefs(origvars2[0]);
722 
723  /* check that the master constraints and the coefficients are the same */
724  for( j = 0; j < ncoefs1; ++j )
725  {
726  if( conss1[j] != conss2[j] )
727  {
728  SCIPdebugMessage("--> constraints differ for var %s and var %s!\n",
729  SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
730  return SCIP_OKAY;
731  }
732 
733  if( !SCIPisEQ(scip, coefs1[j], coefs2[j]) )
734  {
735  SCIPdebugMessage("--> coefficients differ for var %s and var %s!\n",
736  SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
737  return SCIP_OKAY;
738  }
739  }
740 
741  SCIP_CALL( SCIPhashmapInsert(varmap, (void*) vars1[i], (void*) vars2[i]) );
742  }
743 
744  /* check whether the conss are the same */
745  conss1 = SCIPgetConss(scip1);
746  conss2 = SCIPgetConss(scip2);
747  nconss = SCIPgetNConss(scip1);
748  assert(nconss == SCIPgetNConss(scip2));
749  for( i = 0; i < nconss; i++ )
750  {
751  if( SCIPgetNVarsLinear(scip1, conss1[i]) != SCIPgetNVarsLinear(scip2, conss2[i]) )
752  {
753  SCIPdebugMessage("--> nvars differs for cons %s and cons %s!\n", SCIPconsGetName(conss1[i]), SCIPconsGetName(conss2[i]));
754  return SCIP_OKAY;
755  }
756  if( !SCIPisEQ(relaxdata->masterprob, SCIPgetLhsLinear(scip1, conss1[i]), SCIPgetLhsLinear(scip2, conss2[i])) )
757  {
758  SCIPdebugMessage("--> lhs differs for cons %s and cons %s!\n", SCIPconsGetName(conss1[i]), SCIPconsGetName(conss2[i]));
759  return SCIP_OKAY;
760  }
761  if( !SCIPisEQ(relaxdata->masterprob, SCIPgetRhsLinear(scip1, conss1[i]), SCIPgetRhsLinear(scip2, conss2[i])) )
762  {
763  SCIPdebugMessage("--> rhs differs for cons %s and cons %s!\n", SCIPconsGetName(conss1[i]), SCIPconsGetName(conss2[i]));
764  return SCIP_OKAY;
765  }
766  if( !realArraysAreEqual(scip, SCIPgetValsLinear(scip1, conss1[i]), SCIPgetNVarsLinear(scip1, conss1[i]),
767  SCIPgetValsLinear(scip2, conss2[i]), SCIPgetNVarsLinear(scip2, conss2[i])) )
768  {
769  SCIPdebugMessage("--> coefs differ for cons %s and cons %s!\n", SCIPconsGetName(conss1[i]), SCIPconsGetName(conss2[i]));
770  return SCIP_OKAY;
771  }
772  vars1 = SCIPgetVarsLinear(scip1, conss1[i]);
773  vars2 = SCIPgetVarsLinear(scip2, conss2[i]);
774  for( j = 0; j < SCIPgetNVarsLinear(scip1, conss1[i]); j++ )
775  {
776  if( (SCIP_VAR*) SCIPhashmapGetImage(varmap, (void*) vars1[j]) != vars2[j] )
777  {
778  SCIPdebugMessage("--> vars differ for cons %s and cons %s!\n", SCIPconsGetName(conss1[i]), SCIPconsGetName(conss2[i]));
779  return SCIP_OKAY;
780  }
781  }
782 
783  }
784 
785  SCIPdebugMessage("--> blocks are identical!\n");
786 
787  *identical = TRUE;
788  return SCIP_OKAY;
789 }
790 
791 /* checks whether two pricingproblems represent identical blocks */
792 static
794  SCIP* scip, /**< SCIP data structure */
795  SCIP_RELAXDATA* relaxdata, /**< the relaxator's data */
796  SCIP_HASHMAP** hashorig2pricingvar,/**< mapping from orig to pricingvar */
797  int probnr1, /**< number of the first pricingproblem */
798  int probnr2, /**< number of the second pricingproblem */
799  SCIP_HASHMAP* varmap, /**< hashmap mapping the variables of the second pricing problem
800  * to those of the first pricing problem */
801  SCIP_Bool* identical /**< return value: are blocks identical */
802  )
803 {
804  SCIP* scip1;
805  SCIP* scip2;
806  int partialdecid;
807 
808 
809  assert(relaxdata != NULL);
810  assert(0 <= probnr1 && probnr1 < relaxdata->npricingprobs);
811  assert(0 <= probnr2 && probnr2 < relaxdata->npricingprobs);
812  assert(varmap != NULL);
813  assert(identical != NULL);
814 
815  scip1 = relaxdata->pricingprobs[probnr1];
816  scip2 = relaxdata->pricingprobs[probnr2];
817  assert(scip1 != NULL);
818  assert(scip2 != NULL);
819 
820  *identical = FALSE;
821 
822  /* 1) find partialdec number */
823 
824  partialdecid = DECdecompGetPartialdecID(relaxdata->decomp);
825 
826  /* 2) are pricingproblems identical for this partialdec? */
827  SCIP_CALL(GCGconshdlrDecompArePricingprobsIdenticalForPartialdecid(scip, partialdecid, probnr2, probnr1, identical) );
828 
829  /* 3) create varmap if pricing probs are identical */
830  if( *identical )
831  {
832  SCIP_CALL(GCGconshdlrDecompCreateVarmapForPartialdecId(scip, hashorig2pricingvar, partialdecid, probnr2, probnr1, scip2, scip1, varmap) );
833  }
834 
835  return SCIP_OKAY;
836 }
837 
838 static
840  SCIP* scip, /**< SCIP data structure */
841  SCIP_RELAXDATA* relaxdata, /**< the relaxator's data */
842  int probnr1, /**< number of the first pricingproblem */
843  int probnr2, /**< number of the second pricingproblem */
844  SCIP_HASHMAP* varmap, /**< hashmap mapping the variables of the second pricing problem
845  * to those of the first pricing problem */
846  SCIP_Bool* identical /**< return value: are blocks identical */
847  )
848 {
849  SCIP* scip1;
850  SCIP* scip2;
851 
852 #ifdef WITH_BLISS
853  SCIP_RESULT result;
854  SCIP_HASHMAP* consmap;
855 #endif
856 
857  assert(relaxdata != NULL);
858  assert(0 <= probnr1 && probnr1 < relaxdata->npricingprobs);
859  assert(0 <= probnr2 && probnr2 < relaxdata->npricingprobs);
860  assert(varmap != NULL);
861  assert(identical != NULL);
862 
863  scip1 = relaxdata->pricingprobs[probnr1];
864  scip2 = relaxdata->pricingprobs[probnr2];
865  assert(scip1 != NULL);
866  assert(scip2 != NULL);
867 
868  *identical = FALSE;
869 
870  checkIdentical(scip, relaxdata, probnr1, probnr2, varmap, identical, scip1, scip2);
871 
872 #ifdef WITH_BLISS
873  if( !*identical && relaxdata->usebliss )
874  {
875  unsigned int searchnodelimit;
876  unsigned int generatorlimit;
877 
878  searchnodelimit = relaxdata->searchnodelimit >= 0 ? relaxdata->searchnodelimit: 0u;
879  generatorlimit = relaxdata->generatorlimit >= 0 ? relaxdata->generatorlimit : 0u;
880 
881  SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), SCIPgetNConss(scip1) + 1) );
882  SCIP_CALL( cmpGraphPair(scip, scip2, scip1, probnr2, probnr1, &result, varmap, consmap,
883  searchnodelimit, generatorlimit) );
884 
885  *identical = (result == SCIP_SUCCESS);
886 
887  SCIPhashmapFree(&consmap);
888  }
889 #endif
890 
891  return SCIP_OKAY;
892 }
893 
894 /** checks whether there are identical pricing blocks */
895 static
896 SCIP_RETCODE checkIdenticalBlocks(
897  SCIP* scip, /**< SCIP data structure */
898  SCIP_RELAXDATA* relaxdata, /**< the relaxator data data structure*/
899  SCIP_HASHMAP** hashorig2pricingvar /**< mapping from orig to pricingvar for each block */
900  )
901 {
902  SCIP_HASHMAP* varmap;
903  SCIP_VAR** vars;
904  SCIP_VAR* origvar;
905  SCIP_VAR* pricingvar;
906  int nvars;
907  SCIP_Bool identical;
908 
909  int i;
910  int j;
911  int k;
912 
913  int nrelevant;
914 
915  SCIPdebugMessage("checking identical blocks \n");
916  assert(scip != NULL);
917  assert(relaxdata != NULL);
918 
919  for( i = 0; i < relaxdata->npricingprobs; i++ )
920  {
921  relaxdata->blockrepresentative[i] = i;
922  relaxdata->nblocksidentical[i] = 1;
923  }
924 
925  relaxdata->nrelpricingprobs = relaxdata->npricingprobs;
926  nrelevant = 0;
927 
928  if( ( !relaxdata->discretization || !relaxdata->aggregation ) )
929  {
930  SCIPdebugMessage("discretization is off, aggregation is off\n");
931  return SCIP_OKAY;
932  }
933 
934 
935  if( relaxdata->nlinkingvars != 0 )
936  {
937  SCIPdebugMessage("aggregation is off in presence of linking vars\n");
938  return SCIP_OKAY;
939  }
940 
941 
942  for( i = 0; i < relaxdata->npricingprobs; i++ )
943  {
944  for( j = 0; j < i && relaxdata->blockrepresentative[i] == i; j++ )
945  {
946  if( relaxdata->blockrepresentative[j] != j )
947  continue;
948 
949  SCIP_CALL( SCIPhashmapCreate(&varmap,
950  SCIPblkmem(scip),
951  5 * SCIPgetNVars(relaxdata->pricingprobs[i])+1) ); /* +1 to deal with empty subproblems */
952 
953  assert( SCIPgetNConss(scip) == GCGconshdlrDecompGetNFormerDetectionConssForID(scip, DECdecompGetPartialdecID(relaxdata->decomp)) );
954  SCIPdebugMessage( "nconss: %d; ndetectionconss: %d -> using partialdec information for identity test \n", SCIPgetNConss(scip), GCGconshdlrDecompGetNFormerDetectionConssForID(scip, DECdecompGetPartialdecID(relaxdata->decomp) ) );
955  SCIP_CALL( pricingprobsAreIdenticalFromDetectionInfo( scip, relaxdata, hashorig2pricingvar, i, j, varmap, &identical ) );
956 
957 /*
958  * new method of cons_decomp that uses partialdec information
959  * 1) check varmap
960  * 2) build varmap for partialdecs in partialdec datatstructures
961  * 3) translate varmap when transforming partialdec to decomp (store varmap in decomp or partialdec?)
962  * 4) write method in cons_decomp using partialdec agg info and varmap*/
963 
964  if( identical )
965  {
966  SCIPdebugMessage("Block %d is identical to block %d!\n", i, j);
967 
968  /* save variables in pricing problem variable */
969  vars = SCIPgetVars(relaxdata->pricingprobs[i]);
970  nvars = SCIPgetNVars(relaxdata->pricingprobs[i]);
971 
972  /*
973  * quick check whether some of the variables are linking in which case we cannot aggregate
974  * this is suboptimal but we use bliss anyway
975  */
976 
977  for( k = 0; k < nvars; k++ )
978  {
979  assert(GCGvarIsPricing(vars[k]));
980  origvar = GCGpricingVarGetOrigvars(vars[k])[0];
981  if( GCGoriginalVarIsLinking(origvar) )
982  {
983  SCIPdebugMessage("Var <%s> is linking and can not be aggregated.\n", SCIPvarGetName(origvar));
984  identical = FALSE;
985  break;
986  }
987  }
988 
989  if( !identical )
990  {
991  break;
992  }
993 
994 
995  /* block i will be represented by block j */
996  relaxdata->blockrepresentative[i] = j;
997  relaxdata->nblocksidentical[i] = 0;
998  relaxdata->nblocksidentical[j]++;
999 
1000  for( k = 0; k < nvars; k++ )
1001  {
1002  int blocknr;
1003  assert(GCGvarIsPricing(vars[k]));
1004  origvar = GCGpricingVarGetOrigvars(vars[k])[0];
1005 
1006  pricingvar = (SCIP_VAR*) SCIPhashmapGetImage(varmap, (void*) vars[k]);
1007  assert(pricingvar != NULL);
1008  blocknr = GCGvarGetBlock(pricingvar);
1009 
1010  assert(GCGvarIsPricing(pricingvar));
1011  assert(GCGvarIsOriginal(origvar));
1012  assert(GCGoriginalVarGetPricingVar(origvar) != NULL);
1013  GCGoriginalVarSetPricingVar(origvar, pricingvar);
1014  SCIP_CALL( GCGpricingVarAddOrigVar(relaxdata->pricingprobs[blocknr], pricingvar, origvar) );
1015  }
1016 
1017  }
1018  SCIPhashmapFree(&varmap);
1019 
1020  }
1021  if( relaxdata->blockrepresentative[i] == i )
1022  {
1023  SCIPdebugMessage("Block %d is relevant!\n", i);
1024  nrelevant++;
1025  }
1026  }
1027 
1028  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Matrix has %d blocks, using %d%s pricing problem%s.\n",
1029  relaxdata->npricingprobs, nrelevant, (relaxdata->npricingprobs == nrelevant ? "" : " aggregated"), (nrelevant == 1 ? "" : "s"));
1030 
1031  relaxdata->nrelpricingprobs = nrelevant;
1032 
1033  return SCIP_OKAY;
1034 }
1035 
1036 /** sets the pricing problem parameters */
1037 static
1039  SCIP* scip, /**< SCIP data structure of the pricing problem */
1040  int clocktype, /**< clocktype to use in the pricing problem */
1041  SCIP_Real infinity, /**< values larger than this are considered infinity in the pricing problem */
1042  SCIP_Real epsilon, /**< absolute values smaller than this are considered zero in the pricing problem */
1043  SCIP_Real sumepsilon, /**< absolute values of sums smaller than this are considered zero in the pricing problem */
1044  SCIP_Real feastol, /**< feasibility tolerance for constraints in the pricing problem */
1045  SCIP_Real lpfeastolfactor, /**< primal feasibility tolerance factor of LP solver in the pricing problem */
1046  SCIP_Real dualfeastol, /**< feasibility tolerance for reduced costs in LP solution in the pricing problem */
1047  SCIP_Bool enableppcuts /**< should ppcuts be stored for sepa_basis */
1048  )
1049 {
1050  assert(scip != NULL);
1051 
1052  /* disable conflict analysis */
1053  SCIP_CALL( SCIPsetBoolParam(scip, "conflict/useprop", FALSE) );
1054  SCIP_CALL( SCIPsetCharParam(scip, "conflict/useinflp", 'o') );
1055  SCIP_CALL( SCIPsetCharParam(scip, "conflict/useboundlp", 'o') );
1056  SCIP_CALL( SCIPsetBoolParam(scip, "conflict/usesb", FALSE) );
1057  SCIP_CALL( SCIPsetBoolParam(scip, "conflict/usepseudo", FALSE) );
1058 
1059  /* reduce the effort spent for hash tables */
1060  SCIP_CALL( SCIPsetBoolParam(scip, "misc/usevartable", FALSE) );
1061  SCIP_CALL( SCIPsetBoolParam(scip, "misc/useconstable", FALSE) );
1062  SCIP_CALL( SCIPsetBoolParam(scip, "misc/usesmalltables", TRUE) );
1063 
1064  /* disable expensive presolving */
1065  /* @todo test whether this really helps, perhaps set presolving emphasis to fast? */
1066  SCIP_CALL( SCIPsetBoolParam(scip, "constraints/linear/presolpairwise", FALSE) );
1067  SCIP_CALL( SCIPsetBoolParam(scip, "constraints/setppc/presolpairwise", FALSE) );
1068  SCIP_CALL( SCIPsetBoolParam(scip, "constraints/logicor/presolpairwise", FALSE) );
1069  SCIP_CALL( SCIPsetBoolParam(scip, "constraints/linear/presolusehashing", FALSE) );
1070  SCIP_CALL( SCIPsetBoolParam(scip, "constraints/setppc/presolusehashing", FALSE) );
1071  SCIP_CALL( SCIPsetBoolParam(scip, "constraints/logicor/presolusehashing", FALSE) );
1072 
1073  /* disable dual fixing presolver for the moment, because we want to avoid variables fixed to infinity */
1074  SCIP_CALL( SCIPsetIntParam(scip, "propagating/dualfix/freq", -1) );
1075  SCIP_CALL( SCIPsetIntParam(scip, "propagating/dualfix/maxprerounds", 0) );
1076  SCIP_CALL( SCIPfixParam(scip, "propagating/dualfix/freq") );
1077  SCIP_CALL( SCIPfixParam(scip, "propagating/dualfix/maxprerounds") );
1078 
1079 
1080  /* disable solution storage ! */
1081  SCIP_CALL( SCIPsetIntParam(scip, "limits/maxorigsol", 0) );
1082 
1083  /* disable multiaggregation because of infinite values */
1084  SCIP_CALL( SCIPsetBoolParam(scip, "presolving/donotmultaggr", TRUE) );
1085 
1086  /* @todo enable presolving and propagation of xor constraints if bug is fixed */
1087 
1088  /* disable presolving and propagation of xor constraints as work-around for a SCIP bug */
1089  SCIP_CALL( SCIPsetIntParam(scip, "constraints/xor/maxprerounds", 0) );
1090  SCIP_CALL( SCIPsetIntParam(scip, "constraints/xor/propfreq", -1) );
1091 
1092  /* disable output to console */
1093  SCIP_CALL( SCIPsetIntParam(scip, "display/verblevel", (int)SCIP_VERBLEVEL_NONE) );
1094 #if SCIP_VERSION > 210
1095  SCIP_CALL( SCIPsetBoolParam(scip, "misc/printreason", FALSE) );
1096 #endif
1097  SCIP_CALL( SCIPsetIntParam(scip, "limits/maxorigsol", 0) );
1098  SCIP_CALL( SCIPfixParam(scip, "limits/maxorigsol") );
1099 
1100  /* do not abort subproblem on CTRL-C */
1101  SCIP_CALL( SCIPsetBoolParam(scip, "misc/catchctrlc", FALSE) );
1102 
1103  /* set clock type */
1104  SCIP_CALL( SCIPsetIntParam(scip, "timing/clocktype", clocktype) );
1105 
1106  SCIP_CALL( SCIPsetBoolParam(scip, "misc/calcintegral", FALSE) );
1107  SCIP_CALL( SCIPsetBoolParam(scip, "misc/finitesolutionstore", TRUE) );
1108 
1109  SCIP_CALL( SCIPsetRealParam(scip, "numerics/infinity", infinity) );
1110  SCIP_CALL( SCIPsetRealParam(scip, "numerics/epsilon", epsilon) );
1111  SCIP_CALL( SCIPsetRealParam(scip, "numerics/sumepsilon", sumepsilon) );
1112  SCIP_CALL( SCIPsetRealParam(scip, "numerics/feastol", feastol) );
1113  SCIP_CALL( SCIPsetRealParam(scip, "numerics/lpfeastolfactor", lpfeastolfactor) );
1114  SCIP_CALL( SCIPsetRealParam(scip, "numerics/dualfeastol", dualfeastol) );
1115 
1116  /* jonas' stuff */
1117  if( enableppcuts )
1118  {
1119  int pscost;
1120  int prop;
1121 
1122  SCIP_CALL( SCIPgetIntParam(scip, "branching/pscost/priority", &pscost) );
1123  SCIP_CALL( SCIPgetIntParam(scip, "propagating/maxroundsroot", &prop) );
1124  SCIP_CALL( SCIPsetIntParam(scip, "branching/pscost/priority", 11000) );
1125  SCIP_CALL( SCIPsetIntParam(scip, "propagating/maxroundsroot", 0) );
1126  SCIP_CALL( SCIPsetPresolving(scip, SCIP_PARAMSETTING_OFF, TRUE) );
1127  }
1128  return SCIP_OKAY;
1129 }
1130 
1131 
1132 /** creates a variable in a pricing problem corresponding to the given original variable (belonging to exactly one block) */
1133 static
1134 SCIP_RETCODE createPricingVar(
1135  SCIP_RELAXDATA* relaxdata, /**< relaxator data data structure */
1136  SCIP_VAR* origvar /**< corresponding variable in the original program */
1137  )
1138 {
1139  SCIP_VAR* var;
1140  int pricingprobnr;
1141 
1142  assert(relaxdata != NULL);
1143  assert(origvar != NULL);
1144 
1145  pricingprobnr = GCGvarGetBlock(origvar);
1146  assert(pricingprobnr >= 0);
1147 
1148  SCIP_CALL( GCGoriginalVarCreatePricingVar(relaxdata->pricingprobs[pricingprobnr], origvar, &var) );
1149  assert(var != NULL);
1150 
1151  GCGoriginalVarSetPricingVar(origvar, var);
1152  SCIP_CALL( SCIPaddVar(relaxdata->pricingprobs[pricingprobnr], var) );
1153  assert(GCGvarIsPricing(var));
1154  /* because the variable was added to the problem,
1155  * it is captured by SCIP and we can safely release it right now
1156  */
1157  SCIP_CALL( SCIPreleaseVar(relaxdata->pricingprobs[pricingprobnr], &var) );
1158 
1159  return SCIP_OKAY;
1160 }
1161 
1162 /** creates a variable in each of the pricing problems linked by given original variable */
1163 static
1165  SCIP* scip, /**< SCIP data structure */
1166  SCIP_RELAXDATA* relaxdata, /**< relaxator data data structure */
1167  SCIP_VAR* origvar /**< corresponding linking variable in the original program */
1168  )
1169 {
1170  SCIP_VAR* var;
1171  SCIP_CONS* linkcons;
1172 #ifndef NDEBUG
1173  SCIP_CONS** linkconss;
1174  int nblocks;
1175 #endif
1176  SCIP_VAR** pricingvars;
1177  int i;
1178 
1179  assert(origvar != NULL);
1180  assert(relaxdata != NULL);
1181 
1182  /* get variable data of the original variable */
1183  assert(GCGvarIsOriginal(origvar));
1184  assert(GCGoriginalVarIsLinking(origvar));
1185  pricingvars = GCGlinkingVarGetPricingVars(origvar);
1186 
1187 #ifndef NDEBUG
1188  nblocks = GCGlinkingVarGetNBlocks(origvar);
1189  /* checks that GCGrelaxSetOriginalVarBlockNr() worked correctly */
1190  {
1191  int count;
1192 
1193  linkconss = GCGlinkingVarGetLinkingConss(origvar);
1194  /* the linking constraints could be NULL if the Benders' decomposition is used. */
1195  if( linkconss != NULL )
1196  {
1197  count = 0;
1198  for( i = 0; i < relaxdata->npricingprobs; i++ )
1199  {
1200  assert(linkconss[i] == NULL);
1201 
1202  if( pricingvars[i] != NULL )
1203  count++;
1204  }
1205  assert(nblocks == count);
1206  }
1207  }
1208 #endif
1209 
1210  for( i = 0; i < relaxdata->npricingprobs; ++i )
1211  {
1212  if( pricingvars[i] == NULL )
1213  continue;
1214 
1215  SCIP_CALL( GCGlinkingVarCreatePricingVar(relaxdata->pricingprobs[i], i, origvar, &var) );
1216 
1217  GCGlinkingVarSetPricingVar(origvar, i, var);
1218 
1219  assert(GCGvarIsPricing(var));
1220  SCIP_CALL( SCIPaddVar(relaxdata->pricingprobs[i], var) );
1221 
1222 
1223  if( relaxdata->mode != DEC_DECMODE_BENDERS )
1224  {
1225  SCIP_CALL( GCGlinkingVarCreateMasterCons(relaxdata->masterprob, i, origvar, &linkcons) );
1226  GCGlinkingVarSetLinkingCons(origvar, linkcons, i);
1227  SCIP_CALL( SCIPaddCons(relaxdata->masterprob, linkcons) );
1228 
1229  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->varlinkconss, relaxdata->nvarlinkconss, (size_t)relaxdata->nvarlinkconss+1) );
1230  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &relaxdata->varlinkconsblock, relaxdata->nvarlinkconss, (size_t)relaxdata->nvarlinkconss+1) );
1231 
1232  relaxdata->varlinkconss[relaxdata->nvarlinkconss] = linkcons;
1233  relaxdata->varlinkconsblock[relaxdata->nvarlinkconss] = i;
1234  relaxdata->nvarlinkconss++;
1235  }
1236 
1237  /* because the variable was added to the problem,
1238  * it is captured by SCIP and we can safely release it right now
1239  */
1240  SCIP_CALL( SCIPreleaseVar(relaxdata->pricingprobs[i], &var) );
1241  }
1242 
1243 #ifndef NDEBUG
1244  /* checks that createLinkingPricingVars() worked correctly */
1245  {
1246  int count;
1247 
1248  linkconss = GCGlinkingVarGetLinkingConss(origvar);
1249  /* the linking constraints could be NULL if the Benders' decomposition is used. */
1250  if( linkconss != NULL )
1251  {
1252  count = 0;
1253  for( i = 0; i < relaxdata->npricingprobs; i++ )
1254  {
1255  if( pricingvars[i] != NULL )
1256  {
1257  count++;
1258  assert(GCGvarIsPricing(pricingvars[i]));
1259  assert(relaxdata->mode == DEC_DECMODE_BENDERS || linkconss[i] != NULL);
1260  }
1261  else
1262  assert(linkconss[i] == NULL);
1263  }
1264  assert(nblocks == count);
1265  }
1266  }
1267 #endif
1268 
1269 
1270  return SCIP_OKAY;
1271 }
1272 
1273 /** create pricing problem variables */
1274 static
1276  SCIP* scip, /**< SCIP data structure */
1277  SCIP_RELAXDATA* relaxdata, /**< relaxator data data structure */
1278  SCIP_HASHMAP** hashorig2pricingvar /**< hashmap mapping original variables to pricing variables */
1279  )
1280 {
1281  SCIP_VAR** vars;
1282  int nvars;
1283  int v;
1284  int i;
1285  int npricingprobs;
1286 
1287  assert(scip != NULL);
1288  assert(relaxdata != NULL);
1289 
1290  /* create pricing variables and map them to the original variables */
1291  vars = SCIPgetVars(scip);
1292  nvars = SCIPgetNVars(scip);
1293  npricingprobs = relaxdata->npricingprobs;
1294 
1295  for( v = 0; v < nvars; v++ )
1296  {
1297  int blocknr;
1298  SCIP_VAR* probvar;
1299 
1300  assert(SCIPvarIsTransformed(vars[v]));
1301 
1302  probvar = SCIPvarGetProbvar(vars[v]);
1303  assert(SCIPvarIsTransformed(probvar));
1304  blocknr = GCGvarGetBlock(probvar);
1305  if( blocknr == -1 )
1306  {
1307  int tempblock;
1308  tempblock = (int) (size_t) SCIPhashmapGetImage(DECdecompGetVartoblock(relaxdata->decomp), probvar)-1; /*lint !e507*/
1309  if( tempblock >= DECdecompGetNBlocks(relaxdata->decomp) )
1310  {
1311  blocknr = -1;
1312  }
1313  else
1314  {
1315  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, " changed block number to %d \n", tempblock );
1316  blocknr = tempblock; /*lint !e806*/
1317  }
1318  }
1319 
1320  SCIPdebugMessage("Creating map for (%p, %p) var %s:", (void*)(vars[v]), (void*)(probvar), SCIPvarGetName(probvar));
1321  assert( !SCIPhashmapExists(relaxdata->hashorig2origvar, probvar) );
1322  SCIP_CALL( SCIPhashmapInsert(relaxdata->hashorig2origvar, (void*)(probvar), (void*)(probvar)) );
1323 
1324  /* variable belongs to exactly one block --> create corresponding pricing variable*/
1325  if( blocknr >= 0 )
1326  {
1327  SCIPdebugPrintf("block %d", blocknr);
1328 
1329  assert(GCGoriginalVarGetPricingVar(probvar) == NULL);
1330  SCIP_CALL( createPricingVar(relaxdata, probvar) );
1331  assert(GCGoriginalVarGetPricingVar(probvar) != NULL);
1332  assert(hashorig2pricingvar != NULL);
1333  assert(hashorig2pricingvar[blocknr] != NULL);
1334 
1335  SCIPdebugPrintf("-> %p\n", (void*) GCGoriginalVarGetPricingVar(probvar));
1336 
1337  assert(!SCIPhashmapExists(hashorig2pricingvar[blocknr], probvar));
1338  SCIP_CALL( SCIPhashmapInsert(hashorig2pricingvar[blocknr], (void*)(probvar),
1339  (void*)(GCGoriginalVarGetPricingVar(probvar)) ));
1340 
1341  assert(GCGvarIsPricing((SCIP_VAR*) SCIPhashmapGetImage(hashorig2pricingvar[blocknr], probvar)));
1342  }
1343  /* variable is a linking variable --> create corresponding pricing variable in all linked blocks
1344  * and create corresponding linking constraints */
1345  else if( GCGoriginalVarIsLinking(probvar) )
1346  {
1347  SCIP_VAR** pricingvars;
1348  SCIPdebugPrintf("linking.\n");
1349  relaxdata->nlinkingvars++;
1350  SCIP_CALL( createLinkingPricingVars(scip, relaxdata, probvar) );
1351  assert(GCGlinkingVarGetPricingVars(probvar) != NULL);
1352 
1353 
1354  pricingvars = GCGlinkingVarGetPricingVars(probvar);
1355 
1356  for( i = 0; i < npricingprobs; i++ )
1357  {
1358  if( pricingvars[i] != NULL )
1359  {
1360  assert(GCGvarIsPricing(pricingvars[i]));
1361  assert(hashorig2pricingvar != NULL);
1362  assert(hashorig2pricingvar[i] != NULL);
1363  assert(!SCIPhashmapExists(hashorig2pricingvar[i], probvar));
1364  SCIP_CALL( SCIPhashmapInsert(hashorig2pricingvar[i], (void*)(probvar),
1365  (void*)(pricingvars[i])) );
1366  assert(GCGvarIsPricing((SCIP_VAR*) SCIPhashmapGetImage(hashorig2pricingvar[i], probvar)));
1367  }
1368  }
1369  }
1370  else
1371  {
1372  assert(GCGvarGetBlock(probvar) == -1);
1373  assert(GCGoriginalVarGetPricingVar(probvar) == NULL);
1374  SCIPdebugPrintf("master!\n");
1375  relaxdata->ntransvars++;
1376  }
1377  assert(SCIPhashmapExists(relaxdata->hashorig2origvar, probvar));
1378  }
1379 
1380  return SCIP_OKAY;
1381 }
1382 
1383 
1384 /** displays statistics of the pricing problems */
1385 static
1387  SCIP* scip, /**< SCIP data structure */
1388  SCIP** pricingprobs, /**< array of pricing problems */
1389  int npricingprobs, /**< number of pricingproblems */
1390  int* blockrepresentative /**< array of representation information */
1391 )
1392 {
1393  char name[SCIP_MAXSTRLEN];
1394  int i;
1395 
1396  assert(scip != NULL);
1397  assert(pricingprobs != NULL);
1398  assert(blockrepresentative != NULL);
1399  assert(npricingprobs > 0);
1400  for( i = 0; i < npricingprobs; i++ )
1401  {
1402  int nbin;
1403  int nint;
1404  int nimpl;
1405  int ncont;
1406 
1407  if( blockrepresentative[i] != i )
1408  continue;
1409 
1410  SCIP_CALL( SCIPgetVarsData(pricingprobs[i], NULL, NULL, &nbin, &nint, &nimpl, &ncont) );
1411 
1412  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "pricing problem %d: %d conss, %d vars (%d bins, %d ints, %d impls and %d cont)\n", i,
1413  SCIPgetNConss(pricingprobs[i]), SCIPgetNVars(pricingprobs[i]), nbin, nint, nimpl, ncont);
1414 
1415  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "pricingprob_%d.lp", i);
1416  SCIP_CALL( SCIPwriteOrigProblem(pricingprobs[i], name, NULL, FALSE) );
1417  }
1418 
1419  return SCIP_OKAY;
1420 }
1421 
1422 
1423 /** allocates initial problem specific data */
1424 static
1426  SCIP* scip, /**< SCIP data structure */
1427  SCIP_RELAXDATA* relaxdata /**< relaxatordata data structure */
1428  )
1429 {
1430  assert(scip != NULL);
1431  assert(relaxdata != NULL);
1432 
1433  /* initialize relaxator data */
1434  relaxdata->maxmasterconss = 16;
1435  relaxdata->nmasterconss = 0;
1436 
1437  /* arrays of constraints belonging to the master problems */
1438  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(relaxdata->masterconss), relaxdata->maxmasterconss) );
1439  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(relaxdata->origmasterconss), relaxdata->maxmasterconss) );
1440 
1441  if( relaxdata->npricingprobs > 0 )
1442  {
1443  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(relaxdata->pricingprobs), relaxdata->npricingprobs) );
1444  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(relaxdata->blockrepresentative), relaxdata->npricingprobs) );
1445  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(relaxdata->nblocksidentical), relaxdata->npricingprobs) );
1446 
1447  /* array for saving convexity constraints belonging to one of the pricing problems */
1448  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(relaxdata->convconss), relaxdata->npricingprobs) );
1449  }
1450 
1451  SCIP_CALL( SCIPhashmapCreate(&(relaxdata->hashorig2origvar), SCIPblkmem(scip), 10*SCIPgetNVars(scip)+1) );
1452 
1453  return SCIP_OKAY;
1454 }
1455 
1456 
1457 /** creates the master problem with the specified name */
1458 static
1459 SCIP_RETCODE createMasterProblem(
1460  SCIP* masterscip, /**< SCIP data structure of master problem */
1461  const char* name, /**< name of the master problem */
1462  int clocktype, /**< clocktype to use in the master problem */
1463  SCIP_Real infinity, /**< values larger than this are considered infinity in the master problem */
1464  SCIP_Real epsilon, /**< absolute values smaller than this are considered zero in the master problem */
1465  SCIP_Real sumepsilon, /**< absolute values of sums smaller than this are considered zero in the master problem */
1466  SCIP_Real feastol, /**< feasibility tolerance for constraints in the master problem */
1467  SCIP_Real lpfeastolfactor, /**< primal feasibility tolerance factor of LP solver in the master problem */
1468  SCIP_Real dualfeastol, /**< feasibility tolerance for reduced costs in LP solution in the master problem */
1469  DEC_DECMODE mode /**< the decomposition mode */
1470  )
1471 {
1472  assert(masterscip != NULL);
1473  assert(name != NULL);
1474 
1475  SCIP_CALL( SCIPcreateProb(masterscip, name, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1476 
1477  /* set clocktype */
1478  SCIP_CALL( SCIPsetIntParam(masterscip, "timing/clocktype", clocktype) );
1479 
1480  /* set numerical tolerances */
1481  SCIP_CALL( SCIPsetRealParam(masterscip, "numerics/infinity", infinity) );
1482  SCIP_CALL( SCIPsetRealParam(masterscip, "numerics/epsilon", epsilon) );
1483  SCIP_CALL( SCIPsetRealParam(masterscip, "numerics/sumepsilon", sumepsilon) );
1484  SCIP_CALL( SCIPsetRealParam(masterscip, "numerics/feastol", feastol) );
1485  SCIP_CALL( SCIPsetRealParam(masterscip, "numerics/lpfeastolfactor", lpfeastolfactor) );
1486  SCIP_CALL( SCIPsetRealParam(masterscip, "numerics/dualfeastol", dualfeastol) );
1487 
1488  /* disable aggregation and multiaggregation of variables, as this might lead to issues with copied original variables */
1489  SCIP_CALL( SCIPsetBoolParam(masterscip, "presolving/donotaggr", TRUE) );
1490  SCIP_CALL( SCIPsetBoolParam(masterscip, "presolving/donotmultaggr", TRUE) );
1491 
1492  /* the following settings are for decomposition, so if the original problem is solved directly, then these settings
1493  * are not required
1494  */
1495  if( mode == DEC_DECMODE_ORIGINAL )
1496  {
1497  return SCIP_OKAY;
1498  }
1499 
1500  if( mode == DEC_DECMODE_DANTZIGWOLFE )
1501  SCIP_CALL( SCIPactivatePricer(masterscip, SCIPfindPricer(masterscip, "gcg")) );
1502 
1503  /* do not modify the time limit after solving the master problem */
1504  SCIP_CALL( SCIPsetBoolParam(masterscip, "reoptimization/commontimelimit", FALSE) );
1505 
1506  /* disable aggregation and multiaggregation of variables, as this might lead to issues with copied original variables */
1507  SCIP_CALL( SCIPsetBoolParam(masterscip, "presolving/donotaggr", TRUE) );
1508  SCIP_CALL( SCIPsetBoolParam(masterscip, "presolving/donotmultaggr", TRUE) );
1509 
1510  /* for Benders' decomposition, some additional parameter settings are required for the master problem. */
1511  if( mode == DEC_DECMODE_BENDERS )
1512  {
1513  SCIP_CALL( SCIPsetSeparating(masterscip, SCIP_PARAMSETTING_OFF, TRUE) );
1514  SCIP_CALL( SCIPsetPresolving(masterscip, SCIP_PARAMSETTING_OFF, TRUE) );
1515  SCIP_CALL( SCIPsetIntParam(masterscip, "presolving/maxrestarts", 0) );
1516  SCIP_CALL( SCIPsetIntParam(masterscip, "propagating/maxroundsroot", 0) );
1517  SCIP_CALL( SCIPsetIntParam(masterscip, "heuristics/trysol/freq", 1) );
1518  SCIP_CALL( SCIPsetBoolParam(masterscip, "constraints/benders/active", TRUE) );
1519  SCIP_CALL( SCIPsetBoolParam(masterscip, "constraints/benderslp/active", TRUE) );
1520  SCIP_CALL( SCIPsetBoolParam(masterscip, "benders/gcg/lnscheck", FALSE) );
1521  SCIP_CALL( SCIPsetIntParam(masterscip, "presolving/maxrounds", 1) );
1522  SCIP_CALL( SCIPsetIntParam(masterscip, "constraints/benders/maxprerounds", 1) );
1523 
1524  /* the trysol heuristic must have a high priority to ensure the solutions found by the relaxator are added to the
1525  * original problem
1526  */
1527  SCIP_CALL( SCIPsetIntParam(GCGgetOriginalprob(masterscip), "heuristics/trysol/freq", 1) );
1528  }
1529 
1530  return SCIP_OKAY;
1531 }
1532 
1533 
1534 /** creates the pricing problem with the specified name */
1535 static
1537  SCIP** pricingscip, /**< Pricing scip data structure */
1538  const char* name, /**< name of the pricing problem */
1539  int clocktype, /**< clocktype to use in the pricing problem */
1540  SCIP_Real infinity, /**< values larger than this are considered infinity in the pricing problem */
1541  SCIP_Real epsilon, /**< absolute values smaller than this are considered zero in the pricing problem */
1542  SCIP_Real sumepsilon, /**< absolute values of sums smaller than this are considered zero in the pricing problem */
1543  SCIP_Real feastol, /**< feasibility tolerance for constraints in the pricing problem */
1544  SCIP_Real lpfeastolfactor, /**< primal feasibility tolerance factor of LP solver in the pricing problem */
1545  SCIP_Real dualfeastol, /**< feasibility tolerance for reduced costs in LP solution in the pricing problem */
1546  SCIP_Bool enableppcuts /**< should ppcuts be stored for sepa_basis */
1547  )
1548 {
1549  assert(pricingscip != NULL);
1550  assert(name != NULL);
1551 
1552  SCIP_CALL( SCIPcreate(pricingscip) );
1553  SCIP_CALL( SCIPincludeDefaultPlugins(*pricingscip) );
1554  SCIP_CALL( setPricingProblemParameters(*pricingscip, clocktype, infinity, epsilon, sumepsilon, feastol, lpfeastolfactor, dualfeastol, enableppcuts) );
1555  SCIP_CALL( SCIPcreateProb(*pricingscip, name, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
1556 
1557  return SCIP_OKAY;
1558 }
1559 
1560 
1561 /** saves the coefficient of the masterconstraints in the original variable */
1562 static
1564  SCIP* scip, /**< SCIP data structure */
1565  SCIP_VAR** origvars, /**< original variables array */
1566  int norigvars, /**< size of original variables array*/
1567  int nmasterconss, /**< size of masterconns array */
1568  SCIP_CONS** origmasterconss, /**< orig master constraints array */
1569  SCIP_CONS** masterconss /**< master constraints */
1570  )
1571 {
1572  int v;
1573  int i;
1574 
1575  assert(scip != NULL);
1576  assert(origvars != NULL || norigvars == 0);
1577  assert(norigvars >= 0);
1578  assert(nmasterconss >= 0);
1579  assert(masterconss != NULL);
1580  assert(origmasterconss != NULL);
1581 
1582  /* for original variables, save the coefficients in the master problem */
1583  for( v = 0; v < norigvars; v++ )
1584  {
1585  SCIP_VAR* var;
1586  var = SCIPvarGetProbvar(origvars[v]); /*lint !e613*/
1587  assert(GCGvarIsOriginal(var));
1588  assert(GCGoriginalVarGetCoefs(var) == NULL);
1589  GCGoriginalVarSetNCoefs(var, 0);
1590  }
1591 
1592  /* save coefs */
1593  for( i = 0; i < nmasterconss; i++ )
1594  {
1595  SCIP_VAR** vars;
1596  SCIP_Real* vals;
1597  int nvars;
1598 
1599  nvars = GCGconsGetNVars(scip, origmasterconss[i]);
1600  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
1601  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
1602  GCGconsGetVars(scip, origmasterconss[i], vars, nvars);
1603  GCGconsGetVals(scip, origmasterconss[i], vals, nvars);
1604  for( v = 0; v < nvars; v++ )
1605  {
1606  SCIP_CALL( GCGoriginalVarAddCoef(scip, vars[v], vals[v], masterconss[i]) );
1607  }
1608  SCIPfreeBufferArray(scip, &vals);
1609  SCIPfreeBufferArray(scip, &vars);
1610  }
1611 
1612  return SCIP_OKAY;
1613 }
1614 
1615 /** creates the master problem constraints */
1616 static
1618  SCIP* scip, /**< SCIP data structure */
1619  SCIP_RELAXDATA* relaxdata /**< the relaxator data data structure */
1620  )
1621 {
1622  SCIP_CONS** masterconss;
1623  int nmasterconss;
1624  SCIP_CONS* mastercons;
1625  int c;
1626  char name[SCIP_MAXSTRLEN];
1627 
1628  masterconss = DECdecompGetLinkingconss(relaxdata->decomp);
1629  nmasterconss = DECdecompGetNLinkingconss(relaxdata->decomp);
1630 
1631  // assert(SCIPhashmapGetNElements(relaxdata->hashorig2origvar) == SCIPgetNVars(scip));
1632  for( c = 0; c < nmasterconss; ++c )
1633  {
1634  int nconsvars;
1635  int consvarssize;
1636  SCIP_VAR** consvars;
1637  SCIP_Real* consvals;
1638  SCIP_Bool* releasevars;
1639  int i;
1640 
1641  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(masterconss[c])), "origbranch") == 0 )
1642  continue;
1643 
1644  /* in the Benders' decomposition mode, all variables from the linking constraints need to be added to the master
1645  * problem. Additionally, if the original problem is solved directly, then we must ensure that all variables are
1646  * added to the master problem.
1647  */
1649  {
1650  nconsvars = GCGconsGetNVars(scip, masterconss[c]);
1651  consvarssize = nconsvars;
1652 
1653  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consvarssize) );
1654  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, consvarssize) );
1655  SCIP_CALL( SCIPallocClearBufferArray(scip, &releasevars, consvarssize) );
1656 
1657  SCIP_CALL( GCGconsGetVars(scip, masterconss[c], consvars, nconsvars) );
1658  SCIP_CALL( GCGconsGetVals(scip, masterconss[c], consvals, nconsvars) );
1659 
1660  for( i = 0; i < nconsvars; i++ )
1661  {
1662  SCIP_VAR* origvar;
1663 
1664  /* if the variable is a linking variable or is directly transferred to the master problem, then it is not
1665  * added to the constraint. This is because the linking variables and the transferred variables are added
1666  * later in GCGmasterCreateInitialMastervars().
1667  */
1668  while( i < nconsvars && (GCGoriginalVarIsLinking(consvars[i]) || GCGoriginalVarIsTransVar(consvars[i])) )
1669  {
1670  consvars[i] = consvars[nconsvars - 1];
1671  consvals[i] = consvals[nconsvars - 1];
1672  nconsvars--;
1673  }
1674 
1675  if( i >= nconsvars )
1676  break;
1677 
1678  /* assigning the origvar to the next variables that is not a linking variable */
1679  origvar = consvars[i];
1680 
1681  assert(GCGoriginalVarGetNMastervars(origvar) <= 1);
1682 
1683  /* if the original has already has a copy in the master problem, then this is used. Otherwise, the master
1684  * problem variable is created.
1685  */
1686  if( GCGoriginalVarGetNMastervars(origvar) > 0 )
1687  {
1688  consvars[i] = GCGoriginalVarGetMastervars(origvar)[0];
1689  releasevars[i] = FALSE;
1690  }
1691  else
1692  {
1693  SCIP_CALL( GCGcreateInitialMasterVar(relaxdata->masterprob, consvars[i], &consvars[i]) );
1694  SCIP_CALL( SCIPaddVar(relaxdata->masterprob, consvars[i]) );
1695 
1696  SCIP_CALL( GCGoriginalVarAddMasterVar(scip, origvar, consvars[i], 1.0) );
1697 
1698  releasevars[i] = TRUE;
1699  }
1700 
1701  assert(GCGoriginalVarGetNMastervars(origvar) <= 1);
1702  }
1703  }
1704  else
1705  {
1706  nconsvars = 0;
1707  consvars = NULL;
1708  consvals = NULL;
1709  releasevars = NULL;
1710  }
1711 
1712  /* create and add corresponding linear constraint in the master problem */
1713  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "m_%s", SCIPconsGetName(masterconss[c]));
1714  SCIP_CALL( SCIPcreateConsLinear(relaxdata->masterprob, &mastercons, name, nconsvars, consvars, consvals,
1715  GCGconsGetLhs(scip, masterconss[c]), GCGconsGetRhs(scip, masterconss[c]),
1716  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE) );
1717 
1718  SCIP_CALL( SCIPaddCons(relaxdata->masterprob, mastercons) );
1719  SCIPdebugMessage("Copying %s to masterproblem\n", SCIPconsGetName(masterconss[c]));
1720  /* store the constraints in the arrays origmasterconss and masterconss in the problem data */
1721  SCIP_CALL( ensureSizeMasterConss(scip, relaxdata, relaxdata->nmasterconss+1) );
1722  SCIP_CALL( SCIPcaptureCons(scip, masterconss[c]) );
1723  relaxdata->origmasterconss[relaxdata->nmasterconss] = masterconss[c];
1724  relaxdata->masterconss[relaxdata->nmasterconss] = mastercons;
1725  relaxdata->nmasterconss++;
1726 
1727  /* in the Benders' decomposition mode, the consvars and consvals arrays need to be freed */
1729  {
1730  assert(releasevars != NULL);
1731  assert(consvars != NULL);
1732  for( i = 0; i < nconsvars; i++ )
1733  {
1734  if( releasevars[i] )
1735  {
1736  SCIP_CALL( SCIPreleaseVar(relaxdata->masterprob, &consvars[i]) );
1737  }
1738  }
1739 
1740  SCIPfreeBufferArray(scip, &releasevars);
1741  SCIPfreeBufferArray(scip, &consvals);
1742  SCIPfreeBufferArray(scip, &consvars);
1743  }
1744  }
1745  assert(relaxdata->nmasterconss == nmasterconss);
1746  SCIP_CALL( saveOriginalVarMastercoeffs(scip, SCIPgetVars(scip), SCIPgetNVars(scip), relaxdata->nmasterconss, relaxdata->origmasterconss, relaxdata->masterconss) );
1747 
1748  return SCIP_OKAY;
1749 }
1750 
1751 /** creates the pricing problem constraints */
1752 static
1754  SCIP* scip, /**< SCIP data structure */
1755  SCIP_RELAXDATA* relaxdata, /**< the relaxator data data structure */
1756  SCIP_HASHMAP** hashorig2pricingvar /**< hashmap mapping original to corresponding pricing variables */
1757  )
1758 {
1759  SCIP_CONS*** subscipconss;
1760  int* nsubscipconss;
1761  SCIP_CONS* newcons;
1762  SCIP_HASHMAP* hashorig2pricingconstmp;
1763  int nblocks;
1764  int b;
1765  int c;
1766  char name[SCIP_MAXSTRLEN];
1767  SCIP_Bool success;
1768 
1769  assert(scip != NULL);
1770  assert(relaxdata != NULL);
1771 
1772  subscipconss = DECdecompGetSubscipconss(relaxdata->decomp);
1773  nsubscipconss = DECdecompGetNSubscipconss(relaxdata->decomp);
1774  nblocks = DECdecompGetNBlocks(relaxdata->decomp);
1775 
1776  SCIP_CALL( SCIPhashmapCreate(&hashorig2pricingconstmp, SCIPblkmem(scip), SCIPgetNConss(scip)) ); /*lint !e613*/
1777 
1778  for( b = 0; b < nblocks; ++b )
1779  {
1780  assert(hashorig2pricingvar != NULL);
1781  for( c = 0; c < nsubscipconss[b]; ++c )
1782  {
1783  SCIPdebugMessage("copying %s to pricing problem %d\n", SCIPconsGetName(subscipconss[b][c]), b);
1784  if( !SCIPconsIsActive(subscipconss[b][c]) )
1785  {
1786  SCIPdebugMessage("skipping, cons <%s> inactive\n", SCIPconsGetName(subscipconss[b][c]));
1787  continue;
1788  }
1789  SCIP_CALL( SCIPgetTransformedCons(scip, subscipconss[b][c], &subscipconss[b][c]) );
1790  assert(subscipconss[b][c] != NULL);
1791 
1792  /* copy the constraint */
1793  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "p%d_%s", b, SCIPconsGetName(subscipconss[b][c]));
1794  SCIP_CALL( SCIPgetConsCopy(scip, relaxdata->pricingprobs[b], subscipconss[b][c], &newcons, SCIPconsGetHdlr(subscipconss[b][c]),
1795  hashorig2pricingvar[b], hashorig2pricingconstmp, name,
1796  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, &success) );
1797 
1798  /* constraint was successfully copied */
1799  assert(success);
1800 
1801  SCIP_CALL( SCIPaddCons(relaxdata->pricingprobs[b], newcons) );
1802 
1803 
1804 #ifndef NDEBUG
1805  {
1806  SCIP_VAR** curvars;
1807  int ncurvars;
1808 
1809  ncurvars = GCGconsGetNVars(relaxdata->pricingprobs[b], newcons);
1810  curvars = NULL;
1811  if( ncurvars > 0 )
1812  {
1813  int i;
1814 
1815  SCIP_CALL( SCIPallocBufferArray(scip, &curvars, ncurvars) );
1816  SCIP_CALL( GCGconsGetVars(relaxdata->pricingprobs[b], newcons, curvars, ncurvars) );
1817 
1818  for( i = 0; i < ncurvars; ++i )
1819  {
1820  if( SCIPisFeasEQ( scip, SCIPvarGetLbGlobal(curvars[i]), SCIPvarGetUbGlobal(curvars[i]) ) && SCIPisFeasEQ( scip, SCIPvarGetUbGlobal(curvars[i]), 0. ) )
1821  continue;
1822 
1823  assert(GCGvarIsPricing(curvars[i]) || ( SCIPvarIsNegated(curvars[i]) && GCGvarIsPricing(SCIPvarGetNegatedVar(curvars[i]) ) ) );
1824  }
1825 
1826  SCIPfreeBufferArrayNull(scip, &curvars);
1827  }
1828  }
1829 #endif
1830  SCIP_CALL( SCIPreleaseCons(relaxdata->pricingprobs[b], &newcons) );
1831  }
1832  }
1833 
1834  SCIPhashmapFree(&hashorig2pricingconstmp);
1835 
1836  return SCIP_OKAY;
1837 }
1838 
1839 /** creates the master problem and the pricing problems and copies the constraints into them */
1840 static
1841 SCIP_RETCODE createMaster(
1842  SCIP* scip, /**< SCIP data structure */
1843  SCIP_RELAXDATA* relaxdata /**< the relaxator data data structure */
1844  )
1845 {
1846  int npricingprobs;
1847  SCIP_HASHMAP** hashorig2pricingvar;
1848  SCIP_Bool enableppcuts;
1849  char name[SCIP_MAXSTRLEN];
1850  int clocktype;
1851  SCIP_Real infinity;
1852  SCIP_Real epsilon;
1853  SCIP_Real sumepsilon;
1854  SCIP_Real feastol;
1855  SCIP_Real lpfeastolfactor;
1856  SCIP_Real dualfeastol;
1857  int i;
1858 
1859  assert(scip != NULL);
1860  assert(relaxdata != NULL);
1861 
1862  assert(relaxdata->decomp != NULL);
1863 
1864 
1865  SCIP_CALL( convertStructToGCG(scip, relaxdata, relaxdata->decomp) );
1866 
1867  /* if there are no pricing problems, then the original problem will be solved directly. */
1868  if( relaxdata->npricingprobs == 0 )
1869  {
1870  int origmode;
1871 
1872  /* setting the mode to ORIGINAL */
1873  SCIP_CALL( SCIPunfixParam(scip, "relaxing/gcg/mode") );
1874  SCIP_CALL( SCIPgetIntParam(scip, "relaxing/gcg/mode", &origmode) );
1875  SCIP_CALL( SCIPsetIntParam(scip, "relaxing/gcg/mode", (int) DEC_DECMODE_ORIGINAL) );
1876  SCIP_CALL( SCIPfixParam(scip, "relaxing/gcg/mode") );
1877 
1878  /* if the original problem is to be solved, then we need to free the currently master problem and create a new
1879  * SCIP instance
1880  */
1881 
1882  if( origmode == DEC_DECMODE_DANTZIGWOLFE )
1883  {
1884  SCIP* tmpscip;
1885 
1886  /* initialising the master problem */
1887  SCIP_CALL( SCIPsetIntParam(relaxdata->altmasterprob, "display/verblevel", (int)SCIP_VERBLEVEL_NONE) );
1888  SCIP_CALL( SCIPsetBoolParam(relaxdata->altmasterprob, "display/relevantstats", FALSE) );
1889 
1890  /* disabling unnecessary display columns */
1891  SCIP_CALL( SCIPsetIntParam(scip, "display/sumlpiterations/active", 0) );
1892  SCIP_CALL( SCIPsetIntParam(scip, "display/lpiterations/active", 0) );
1893  SCIP_CALL( SCIPsetIntParam(scip, "display/degeneracy/active", 0) );
1894 
1895  /* setting the total node limit to 1 for the original SCIP instance. This is because Benders' decomposition solves
1896  * the MIP within the relaxator of the root node. So no branching in the original problem is required.
1897  */
1898  SCIP_CALL( SCIPsetLongintParam(scip, "limits/totalnodes", 1) );
1899 
1900  /* swapping the master problem with the original master problem */
1901  tmpscip = relaxdata->altmasterprob;
1902  relaxdata->altmasterprob = relaxdata->masterprob;
1903  relaxdata->masterprob = tmpscip;
1904  }
1905 
1906  SCIP_CALL( SCIPsetIntParam(relaxdata->masterprob, "constraints/components/maxprerounds", 0) );
1907  SCIP_CALL( SCIPsetBoolParam(scip, "relaxing/gcg/discretization", FALSE) );
1908  }
1909 
1910 
1911  npricingprobs = relaxdata->npricingprobs;
1912  hashorig2pricingvar = NULL;
1913 
1914  if( npricingprobs > 0 )
1915  {
1916  /* create hashmaps for mapping from original to pricing variables */
1917  SCIP_CALL( SCIPallocBufferArray(scip, &(hashorig2pricingvar), npricingprobs) );
1918  }
1919 
1920  SCIPdebugMessage("Creating master problem...\n");
1921 
1922  SCIP_CALL( initRelaxProblemdata(scip, relaxdata) );
1923 
1924  /* get clocktype of the original SCIP instance in order to use the same clocktype in master and pricing problems */
1925  SCIP_CALL( SCIPgetIntParam(scip, "timing/clocktype", &clocktype) );
1926 
1927  /* get numerical tolerances of the original SCIP instance in order to use the same numerical tolerances in master and pricing problems */
1928  SCIP_CALL( SCIPgetRealParam(scip, "numerics/infinity", &infinity) );
1929  SCIP_CALL( SCIPgetRealParam(scip, "numerics/epsilon", &epsilon) );
1930  SCIP_CALL( SCIPgetRealParam(scip, "numerics/sumepsilon", &sumepsilon) );
1931  SCIP_CALL( SCIPgetRealParam(scip, "numerics/feastol", &feastol) );
1932  SCIP_CALL( SCIPgetRealParam(scip, "numerics/lpfeastolfactor", &lpfeastolfactor) );
1933  SCIP_CALL( SCIPgetRealParam(scip, "numerics/dualfeastol", &dualfeastol) );
1934 
1935  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "master_%s", SCIPgetProbName(scip));
1936  SCIP_CALL( createMasterProblem(relaxdata->masterprob, name, clocktype, infinity, epsilon, sumepsilon, feastol,
1937  lpfeastolfactor, dualfeastol, relaxdata->mode) );
1938 
1939  enableppcuts = FALSE;
1940  SCIP_CALL( SCIPgetBoolParam(scip, "sepa/basis/enableppcuts", &enableppcuts) );
1941 
1942  /* create the pricing problems */
1943  for( i = 0; i < npricingprobs; i++ )
1944  {
1945  relaxdata->convconss[i] = NULL;
1946  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "pricing_block_%d", i);
1947  SCIP_CALL( createPricingProblem(&(relaxdata->pricingprobs[i]), name, clocktype, infinity, epsilon, sumepsilon,
1948  feastol, lpfeastolfactor, dualfeastol, enableppcuts) );
1949  SCIP_CALL( SCIPhashmapCreate(&(hashorig2pricingvar[i]), SCIPblkmem(scip), SCIPgetNVars(scip)) ); /*lint !e613*/
1950 
1951  /* disabling restarts from the tree size estimation */
1952  SCIP_CALL( SCIPsetCharParam(relaxdata->pricingprobs[i], "estimation/restarts/restartpolicy", 'n') );
1953  }
1954 
1955  SCIP_CALL( createPricingVariables(scip, relaxdata, hashorig2pricingvar) );
1956 
1957  /* create master and pricing problem constraints
1958  * If the master problem is solved directly, then we can still call methods creating the pricing problems. These
1959  * methods check the number of pricing problems and number of blocks. As such, if the original problem is solved
1960  * directly, then nothing will happen in these methods
1961  */
1962  SCIP_CALL( createMasterprobConss(scip, relaxdata) );
1963  SCIP_CALL( createPricingprobConss(scip, relaxdata, hashorig2pricingvar) );
1964  SCIP_CALL( GCGmasterCreateInitialMastervars(relaxdata->masterprob) );
1965 
1966  /* check if the master problem is a set partitioning or set covering problem */
1967  SCIP_CALL( checkSetppcStructure(scip, relaxdata) );
1968 
1969  /* check for identity of blocks */
1970  SCIP_CALL( checkIdenticalBlocks(scip, relaxdata, hashorig2pricingvar) );
1971 
1972  /* the convexity constraints are only added in the Dantzig-Wolfe mode */
1973  if( relaxdata->mode == DEC_DECMODE_DANTZIGWOLFE )
1974  {
1975  for( i = 0; i < relaxdata->npricingprobs; i++ )
1976  {
1977  if( relaxdata->blockrepresentative[i] != i )
1978  continue;
1979 
1980  /* create the corresponding convexity constraint */
1981  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "conv_block_%d", i);
1982  SCIP_CALL( SCIPcreateConsLinear(relaxdata->masterprob, &(relaxdata->convconss[i]), name, 0, NULL, NULL,
1983  relaxdata->nblocksidentical[i]*1.0, relaxdata->nblocksidentical[i]*1.0,
1984  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE) );
1985  SCIP_CALL( SCIPaddCons(relaxdata->masterprob, relaxdata->convconss[i]) );
1986  }
1987  }
1988 
1989  /* display statistics */
1990  if( relaxdata->dispinfos )
1991  {
1992  SCIP_CALL( displayPricingStatistics(scip, relaxdata->pricingprobs, relaxdata->npricingprobs, relaxdata->blockrepresentative) );
1993  SCIP_CALL( SCIPwriteOrigProblem(relaxdata->masterprob, "masterprob.lp", "lp", FALSE) );
1994  }
1995 
1996  if( hashorig2pricingvar != NULL )
1997  {
1998  for( i = 0; i < npricingprobs; i++ )
1999  SCIPhashmapFree(&(hashorig2pricingvar[i]));
2000 
2001  SCIPfreeBufferArray(scip, &(hashorig2pricingvar));
2002  }
2003 
2004  /* get used memory and save it for reference */
2005  for( i = 0; i < npricingprobs; ++i )
2006  {
2007  relaxdata->pricingprobsmemused += SCIPgetMemUsed(relaxdata->pricingprobs[i])/1048576.0;
2008  }
2009 
2010  return SCIP_OKAY;
2011 }
2012 
2013 /** combines the solutions from all (disjoint) problems to one solution */
2014 static
2015 SCIP_RETCODE combineSolutions(
2016  SCIP* scip, /**< SCIP data structure */
2017  SCIP_SOL** newsol, /**< pointer to store new solution */
2018  SCIP** probs, /**< array of (solved) subproblems */
2019  int nprobs /**< number of subproblems */
2020  )
2021 {
2022 #ifdef SCIP_DEBUG
2023  int i;
2024 #endif
2025 
2026  int v;
2027  int nvars;
2028 
2029  SCIP_VAR** vars;
2030  assert(scip != NULL);
2031  assert(newsol != NULL);
2032  assert(probs != NULL);
2033  assert(nprobs > 0);
2034 
2035  SCIP_CALL( SCIPcreateSol(scip, newsol, NULL) );
2036  nvars = SCIPgetNVars(scip);
2037  vars = SCIPgetVars(scip);
2038 
2039 #ifdef SCIP_DEBUG
2040  for( i = 0; i < nprobs; ++i )
2041  {
2042  if( probs[i] == NULL )
2043  continue;
2044 
2045  SCIPprintOrigProblem(probs[i], NULL, "lp", FALSE);
2046  SCIPprintSol(probs[i], SCIPgetBestSol(probs[i]), NULL, FALSE );
2047  }
2048 #endif
2049 
2050  for( v = 0; v < nvars; ++v )
2051  {
2052  SCIP_VAR* pricingvar;
2053  int block;
2054 
2055  pricingvar = GCGoriginalVarGetPricingVar(vars[v]);
2056  block = GCGvarGetBlock(pricingvar);
2057  assert(block >= 0);
2058  assert(block < nprobs);
2059  assert(probs[block] != NULL);
2060 
2061  /* @todo solval should be 0 before, anyway, check it with an assert */
2062  SCIP_CALL( SCIPincSolVal(scip, *newsol, vars[v], SCIPgetSolVal(probs[block], SCIPgetBestSol(probs[block]), pricingvar)) );
2063  }
2064  return SCIP_OKAY;
2065 }
2066 
2067 /** sets the pricing objective function to what is necessary */
2068 static
2070  SCIP* scip, /**< SCIP data structure */
2071  SCIP** probs, /**< array of subproblems */
2072  int nprobs /**< number of subproblems */
2073  )
2074 {
2075  int v;
2076  int nvars;
2077  SCIP_VAR** vars;
2078  int i;
2079 
2080  assert(scip != NULL);
2081  assert(probs != NULL);
2082  assert(nprobs > 0);
2083 
2084  nvars = SCIPgetNVars(scip);
2085  vars = SCIPgetVars(scip);
2086 
2087  /* if the Benders' decomposition is used, then the transformed problem of the subproblems must be freed.
2088  * This is because the within the create subproblem stage, if the subproblem is an LP, then the SCIP instance is put
2089  * into probing mode.
2090  */
2092  {
2093  for( i = 0; i < nprobs; i++ )
2094  {
2095  /* if the problem is not in SCIP_STAGE_PROBLEM, then the transformed problem must be freed. The subproblem
2096  * should also be in probing mode.
2097  */
2098  if( SCIPgetStage(probs[i]) != SCIP_STAGE_PROBLEM )
2099  {
2100  if( SCIPinProbing(probs[i]) )
2101  {
2102  SCIP_CALL( SCIPendProbing(probs[i]) );
2103  }
2104 
2105  SCIP_CALL( SCIPfreeTransform(probs[i]) );
2106  }
2107  }
2108  }
2109 
2110  for( v = 0; v < nvars; ++v )
2111  {
2112  SCIP_VAR* pricingvar;
2113  SCIP_VAR* origvar;
2114  SCIP_Real objvalue;
2115 
2116  assert(GCGvarIsOriginal(vars[v]));
2117  origvar = SCIPvarGetProbvar(vars[v]);
2118 
2119  if( !GCGisPricingprobRelevant(scip, GCGvarGetBlock(origvar)) )
2120  continue;
2121 
2122  pricingvar = GCGoriginalVarGetPricingVar(origvar);
2123  assert(pricingvar != NULL);
2124 
2125  objvalue = SCIPvarGetObj(origvar);
2126  /* SCIPinfoMessage(scip, NULL, "%s: %f block %d\n", SCIPvarGetName(origvar), SCIPvarGetObj(origvar),
2127  GCGvarGetBlock(origvar)); */
2128  SCIP_CALL( SCIPchgVarObj(probs[GCGvarGetBlock(pricingvar)], pricingvar, objvalue) );
2129  }
2130  return SCIP_OKAY;
2131 }
2132 
2133 /** solve a block problem when the decomposition is diagonal */
2134 static
2135 SCIP_RETCODE solveBlockProblem(
2136  SCIP* scip, /**< SCIP data structure */
2137  SCIP* blockprob, /**< the block problem that will be solved */
2138  SCIP_RELAXDATA* relaxdata, /**< relaxator data structure */
2139  SCIP_Real timelimit, /**< the original problem timelimit */
2140  int blocknum, /**< the number of the block, -1 for the original problem */
2141  SCIP_RESULT* result, /**< result pointer to indicate success or failure */
2142  SCIP_Real* objvalue /**< the objective function value */
2143  )
2144 {
2145  SCIP_Real blocktimelimit;
2146 
2147  assert(scip != NULL);
2148  assert(result != NULL);
2149  assert(objvalue != NULL);
2150 
2151  (*result) = SCIP_DIDNOTRUN;
2152 
2153 #ifdef SCIP_DEBUG
2154  char name[SCIP_MAXSTRLEN];
2155 #endif
2156 
2157  if( blockprob == NULL )
2158  {
2159  (*result) = SCIP_SUCCESS;
2160  return SCIP_OKAY;
2161  }
2162 
2164  {
2165  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Solving block %i.\n", blocknum+1);
2166  }
2167 
2168  SCIP_CALL( SCIPsetIntParam(blockprob, "display/verblevel", relaxdata->origverblevel) );
2169 
2170  /* give the pricing problem 2% more time then the original scip has left */
2171  if( SCIPgetStage(blockprob) > SCIP_STAGE_PROBLEM )
2172  {
2173  if( SCIPisInfinity(scip, timelimit) )
2174  {
2175  blocktimelimit = SCIPinfinity(blockprob);
2176  }
2177  else
2178  {
2179  blocktimelimit = (timelimit - SCIPgetSolvingTime(scip)) * 1.02 + SCIPgetSolvingTime(blockprob);
2180  blocktimelimit = MIN(SCIPinfinity(blockprob), blocktimelimit); /*lint !e666*/
2181  }
2182  }
2183  else
2184  {
2185  if( SCIPisInfinity(scip, timelimit) )
2186  {
2187  blocktimelimit = SCIPinfinity(blockprob);
2188  }
2189  else
2190  {
2191  blocktimelimit = (timelimit - SCIPgetSolvingTime(scip)) * 1.02;
2192  blocktimelimit = MIN(SCIPinfinity(blockprob), blocktimelimit); /*lint !e666*/
2193  }
2194  }
2195 
2196  if( blocktimelimit < 0 )
2197  {
2198  (*result) = SCIP_DIDNOTRUN;
2199  return SCIP_OKAY;
2200  }
2201 
2202  SCIP_CALL( SCIPsetRealParam(blockprob, "limits/time", blocktimelimit) );
2203 
2204 #ifdef SCIP_DEBUG
2205  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "block_%i.lp", blocknum);
2206  SCIP_CALL( SCIPwriteOrigProblem(blockprob, name, "lp", FALSE) );
2207 #endif
2208 
2210  {
2211  SCIP_CALL( SCIPsolve(blockprob) );
2212  }
2213  else
2214  {
2215  SCIP_BENDERS* benders;
2216  SCIP_Bool infeasible;
2217 
2219 
2220  /* retrieving the Benders' decomposition */
2221  benders = SCIPfindBenders(relaxdata->masterprob, "gcg");
2222 
2223  /* since the diagonal blocks are being solved, this indicates that the subproblems are independent. As such, we
2224  * can declare this in the Benders' decomposition framework. This allows us to call
2225  * SCIPsolveBendersSubproblem() without setting up the problem
2226  */
2227  SCIPbendersSetSubproblemIsIndependent(benders, blocknum, TRUE);
2228 
2229  /* solving the Benders' decomposition subproblem */
2230  SCIP_CALL( SCIPsolveBendersSubproblem(relaxdata->masterprob, benders, NULL, blocknum, &infeasible,
2231  TRUE, NULL) );
2232  }
2233 
2234 
2235  switch( SCIPgetStatus(blockprob) )
2236  {
2237  case SCIP_STATUS_UNBOUNDED:
2238  case SCIP_STATUS_INFORUNBD:
2239  case SCIP_STATUS_INFEASIBLE:
2240  /* no other blocks should be solved. */
2241  *result = SCIP_CUTOFF;
2242  break;
2243  case SCIP_STATUS_BESTSOLLIMIT:
2244  case SCIP_STATUS_MEMLIMIT:
2245  case SCIP_STATUS_STALLNODELIMIT:
2246  case SCIP_STATUS_NODELIMIT:
2247  case SCIP_STATUS_SOLLIMIT:
2248  case SCIP_STATUS_TIMELIMIT:
2249  /* no other blocks should be solved. */
2250  *result = SCIP_DIDNOTRUN;
2251  break;
2252  case SCIP_STATUS_GAPLIMIT:
2253  case SCIP_STATUS_OPTIMAL:
2254  (*result) = SCIP_SUCCESS;
2255  (*objvalue) += SCIPgetDualbound(blockprob);
2256  break;
2257  default:
2258  break;
2259  } /*lint !e788*/
2260 
2261  return SCIP_OKAY;
2262 }
2263 
2264 /** frees the block problem */
2265 static
2266 SCIP_RETCODE freeBlockProblem(
2267  SCIP* scip, /**< SCIP data structure */
2268  SCIP* blockprob, /**< the block problem that will be solved */
2269  SCIP_RELAXDATA* relaxdata, /**< relaxator data structure */
2270  int blocknum /**< the number of the block, -1 for the original problem */
2271  )
2272 {
2273  assert(scip != NULL);
2274 
2275  if( blockprob == NULL )
2276  return SCIP_OKAY;
2277 
2279  {
2280  SCIP_CALL( SCIPfreeTransform(blockprob) );
2281  }
2282  else
2283  {
2284  SCIP_BENDERS* benders;
2285 
2287 
2288  /* retrieving the Benders' decomposition */
2289  benders = SCIPfindBenders(relaxdata->masterprob, "gcg");
2290 
2291  /* freeing the Benders' decomposition subproblems */
2292  SCIP_CALL( SCIPfreeBendersSubproblem(relaxdata->masterprob, benders, blocknum) );
2293  }
2294 
2295  return SCIP_OKAY;
2296 }
2297 
2298 /** solves the blocks diagonal and individually */
2299 static
2300 SCIP_RETCODE solveDiagonalBlocks(
2301  SCIP* scip, /**< SCIP data structure */
2302  SCIP_RELAXDATA* relaxdata, /**< relaxator data structure */
2303  SCIP_RESULT* result, /**< result pointer to indicate success or failure */
2304  SCIP_Real* lowerbound /**< lower bound pointer to return the lower bound */
2305  )
2306 {
2307  int i;
2308  SCIP_Real timelimit;
2309  SCIP_Real objvalue;
2310  SCIP_SOL *newsol;
2311  SCIP_Bool isfeasible;
2312  SCIP_RESULT solveresult;
2313 
2314  /* set objective of pricing problems to original objective */
2316  {
2317  SCIP_CALL( setPricingObjsOriginal(scip, relaxdata->pricingprobs, relaxdata->npricingprobs) );
2318  }
2319 
2320  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
2321 
2322  objvalue = 0.0;
2323 
2325  {
2326  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Block diagonal structure detected, solving blocks individually.\n");
2327  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "There is an objective function offet of %f.\n", SCIPgetTransObjoffset(scip));
2328  }
2329 
2330  /* if the original problem is solved directly, then we call solveBlockProblem with the master problem */
2332  {
2333  SCIP_CALL( solveBlockProblem(scip, relaxdata->masterprob, relaxdata, timelimit, -1, &solveresult, &objvalue) );
2334 
2335  if( solveresult == SCIP_CUTOFF || solveresult == SCIP_DIDNOTRUN )
2336  {
2337  (*result) = solveresult;
2338  return SCIP_OKAY;
2339  }
2340  }
2341  else
2342  {
2343  /* solve pricing problems one after the other */
2344  for( i = 0; i < relaxdata->npricingprobs; ++i )
2345  {
2346  SCIP_CALL( solveBlockProblem(scip, relaxdata->pricingprobs[i], relaxdata, timelimit, i, &solveresult, &objvalue) );
2347 
2348  if( solveresult == SCIP_CUTOFF || solveresult == SCIP_DIDNOTRUN )
2349  {
2350  (*result) = solveresult;
2351  return SCIP_OKAY;
2352  }
2353  }
2354  }
2355 
2356  /* get solution and glue it together */
2357 
2359  {
2360  SCIP_CALL( GCGtransformMastersolToOrigsol(scip, SCIPgetBestSol(relaxdata->masterprob), &newsol) );
2361  }
2362  else
2363  {
2364  SCIP_CALL( combineSolutions(scip, &newsol, relaxdata->pricingprobs, relaxdata->npricingprobs) );
2365  }
2366 
2367  /* update lower bound pointer and add solution such that this node will be cut off automatically */
2368  if( SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE )
2369  *lowerbound = -objvalue;
2370  else
2371  *lowerbound = objvalue;
2372 
2373  SCIP_CALL( SCIPcheckSol(scip, newsol, TRUE, TRUE, TRUE, TRUE, TRUE, &isfeasible) );
2374  assert(isfeasible);
2375 
2376  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &isfeasible) );
2377 
2378  /** @todo maybe add a constraint here to indicate that it has been decomposed */
2379 
2380  /* if the original problem is solved directly, then we call freeBlockProblem with the master problem */
2382  {
2383  /* solve pricing problems one after the other */
2384  for( i = 0; i < relaxdata->npricingprobs; ++i )
2385  {
2386  SCIP_CALL( freeBlockProblem(scip, relaxdata->pricingprobs[i], relaxdata, i) );
2387  }
2388  }
2389 
2390  *result = SCIP_SUCCESS;
2391 
2392  return SCIP_OKAY;
2393 
2394 }
2395 
2396 
2398  SCIP* scip
2399  )
2400 {
2401  SCIP_RELAX* relax;
2402  SCIP_RELAXDATA* relaxdata;
2403 
2404  assert(scip != NULL);
2405 
2406  relax = SCIPfindRelax(scip, RELAX_NAME);
2407  assert(relax != NULL);
2408 
2409  relaxdata = SCIPrelaxGetData(relax);
2410  assert(relaxdata != NULL);
2411 
2412  return relaxdata->decomp;
2413 }
2414 
2415 
2416 /** sets the structure information */
2417 static
2418 SCIP_RETCODE GCGsetStructDecomp(
2419  SCIP* scip, /**< SCIP data structure */
2420  DEC_DECOMP* decomp /**< decomposition data structure */
2421  )
2422 {
2423  SCIP_RELAX* relax;
2424  SCIP_RELAXDATA* relaxdata;
2425 
2426  assert(scip != NULL);
2427  assert(decomp != NULL);
2428 
2429  relax = SCIPfindRelax(scip, RELAX_NAME);
2430  assert(relax != NULL);
2431 
2432  relaxdata = SCIPrelaxGetData(relax);
2433  assert(relaxdata != NULL);
2434 
2435  if( relaxdata->decomp != NULL )
2436  SCIP_CALL( DECdecompFree(scip, &relaxdata->decomp ) );
2437 
2438  relaxdata->decomp = decomp;
2439 
2440  return SCIP_OKAY;
2441 }
2442 
2443 
2444 /** transforms the master problem **/
2445 static
2446 SCIP_RETCODE transformMaster(
2447  SCIP* scip, /**< SCIP data structure */
2448  SCIP_RELAX* relax /**< relaxator data structure */
2449  )
2450 {
2451  SCIP* masterprob;
2452  SCIP_VAR** vars;
2453  SCIP_CONS** oldconss;
2454  SCIP_RELAXDATA* relaxdata;
2455  int i;
2456  int nvars;
2457  int permutationseed;
2458  int oxfordcomma;
2459 
2460  assert(scip != NULL);
2461  assert(relax != NULL);
2462 
2463  relaxdata = SCIPrelaxGetData(relax);
2464  assert(relaxdata != NULL);
2465 
2466  masterprob = relaxdata->masterprob;
2467  assert(masterprob != NULL);
2468  SCIP_CALL( SCIPtransformProb(masterprob) );
2469  SCIP_CALL( SCIPduplicateBufferArray(scip, &oldconss, relaxdata->masterconss, relaxdata->nmasterconss) );
2470 
2471  /* transform the master constraints */
2472  SCIP_CALL( SCIPtransformConss(masterprob, relaxdata->nmasterconss,
2473  relaxdata->masterconss, relaxdata->masterconss) );
2474  for( i = 0; i < relaxdata->nmasterconss; ++i )
2475  {
2476  SCIP_CALL( SCIPreleaseCons(masterprob, &(oldconss[i])) );
2477  }
2478  SCIPfreeBufferArray(scip, &oldconss);
2479 
2480  /* transform the convexity constraints */
2481  for( i = 0; i < relaxdata->npricingprobs; i++ )
2482  {
2483  if( relaxdata->convconss[i] != NULL )
2484  {
2485  SCIP_CONS* oldcons = relaxdata->convconss[i];
2486  SCIP_CALL( SCIPreleaseCons(masterprob, &oldcons) );
2487  SCIP_CALL( SCIPtransformCons(masterprob, relaxdata->convconss[i], &(relaxdata->convconss[i])) );
2488  }
2489  }
2490 
2491  nvars = SCIPgetNVars(scip);
2492  vars = SCIPgetVars(scip);
2493 
2494  /* transform the linking variable constraints */
2495  for( i = 0; i < nvars; ++i )
2496  {
2497  assert(GCGvarIsOriginal(vars[i]));
2498 
2499  if( GCGoriginalVarIsLinking(vars[i]) )
2500  {
2501  int j;
2502  SCIP_CONS** linkconss;
2503  linkconss = GCGlinkingVarGetLinkingConss(vars[i]);
2504  /* the linking constraints could be NULL if the Benders' decomposition is used. */
2505  if( linkconss != NULL )
2506  {
2507  for( j = 0; j < relaxdata->npricingprobs; ++j )
2508  {
2509  if( linkconss[j] != NULL )
2510  {
2511  SCIP_CONS* tempcons;
2512  SCIP_CALL( SCIPtransformCons(masterprob, linkconss[j], &(tempcons)) );
2513  GCGlinkingVarSetLinkingCons(vars[i], tempcons, j);
2514  }
2515  }
2516  }
2517  }
2518  }
2519  for( i = 0; i < relaxdata->nvarlinkconss; ++i )
2520  {
2521  SCIP_CONS* transcons;
2522 
2523  SCIP_CALL( SCIPgetTransformedCons(masterprob, relaxdata->varlinkconss[i], &transcons) );
2524  assert(transcons != NULL);
2525 
2526  SCIP_CALL( SCIPreleaseCons(masterprob, &relaxdata->varlinkconss[i]) );
2527  relaxdata->varlinkconss[i] = transcons;
2528  }
2529  return SCIP_OKAY;
2530 }
2531 
2532 
2533 /** initializes and transforms relaxator data */
2534 static
2535 SCIP_RETCODE initRelaxator(
2536  SCIP* scip, /**< SCIP data structure */
2537  SCIP_RELAX* relax /**< relaxator data structure */
2538  )
2539 {
2540  SCIP_VAR** vars;
2541  SCIP_CONS** oldconss;
2542  SCIP_RELAXDATA* relaxdata;
2543  int i;
2544  int nvars;
2545  int permutationseed;
2546  int oxfordcomma;
2547 
2548  assert(scip != NULL);
2549  assert(relax != NULL);
2550 
2551  relaxdata = SCIPrelaxGetData(relax);
2552  assert(relaxdata != NULL);
2553 
2554  /* when the original problem should be solved directly, then a decomposition must be made with zero blocks */
2556  {
2557  DEC_DECOMP* decomp;
2558  SCIP_RETCODE retcode;
2559 
2560  assert(relaxdata->decomp == NULL);
2561 
2562  retcode = DECcreateBasicDecomp(scip, &decomp, TRUE);
2563  assert(retcode == SCIP_OKAY);
2564  if( retcode != SCIP_OKAY )
2565  {
2566  SCIPerrorMessage("Could not add decomp to cons_decomp!\n");
2567  return SCIP_ERROR;
2568  }
2569 
2570  assert(decomp != NULL );
2571 
2572  GCGsetStructDecomp(scip, decomp);
2573  }
2574 
2575  if( relaxdata->decomp == NULL )
2576  {
2577  relaxdata->decomp = DECgetBestDecomp(scip, TRUE);
2578  if( relaxdata->decomp == NULL )
2579  {
2580  int partialdecid;
2581  SCIPwarningMessage(scip, "No complete decomposition available. Creating basic decomposition.\n");
2582  partialdecid = GCGconshdlrDecompAddBasicPartialdec(scip, TRUE);
2583  SCIP_CALL( GCGconshdlrDecompSelectPartialdec(scip, partialdecid, TRUE) );
2584 
2585  relaxdata->decomp = DECgetBestDecomp(scip, FALSE);
2586  assert( relaxdata->decomp != NULL );
2587  }
2588  }
2589 
2590  oxfordcomma = 0;
2591  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "Chosen structure has %d blocks", DECdecompGetNBlocks(relaxdata->decomp));
2592  /* every master-only variable internally also counts as linking, but should not be reported as linking variable */
2593  if ( DECdecompGetNLinkingvars(relaxdata->decomp) - DECdecompGetNMastervars(relaxdata->decomp) > 0)
2594  {
2595  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, ", %d linking variables", DECdecompGetNLinkingvars(relaxdata->decomp) - DECdecompGetNMastervars(relaxdata->decomp));
2596  ++oxfordcomma;
2597  }
2598  if ( DECdecompGetNMastervars(relaxdata->decomp) > 0 )
2599  {
2600  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, ", %d master-only (static) variables", DECdecompGetNMastervars(relaxdata->decomp));
2601  ++oxfordcomma;
2602  }
2603  if ( oxfordcomma > 0 )
2604  {
2605  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, ",");
2606  }
2607  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, " and %d linking constraints.\n", DECdecompGetNLinkingconss(relaxdata->decomp));
2608  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "This decomposition has a maxwhite score of %f.\n", DECdecompGetMaxwhiteScore(relaxdata->decomp));
2609 
2610  /* permute the decomposition if the permutation seed is set */
2611  SCIP_CALL( SCIPgetIntParam(scip, "randomization/permutationseed", &permutationseed) );
2612 
2613  if( permutationseed > 0 )
2614  {
2615  SCIP_RANDNUMGEN* randnumgen;
2616 
2617  SCIP_CALL( SCIPcreateRandom(scip, &randnumgen, (unsigned int) permutationseed, TRUE) );
2618  SCIP_CALL( DECpermuteDecomp(scip, relaxdata->decomp, randnumgen) );
2619  SCIPfreeRandom(scip, &randnumgen);
2620  }
2621 
2622  if( relaxdata->discretization && (SCIPgetNContVars(scip) > 0) )
2623  {
2624  if( relaxdata->mipdiscretization )
2625  {
2626  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Warning: Discretization with continuous variables is only an experimental feature.\n");
2627  }
2628  else
2629  {
2630  SCIP_CALL( SCIPsetBoolParam(scip, "relaxing/gcg/discretization", FALSE) );
2631  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Warning: Discretization with continuous variables is disabled by parameter relaxing/gcg/mipdiscretization.\n");
2632  }
2633  }
2634 
2635  SCIP_CALL( createMaster(scip, relaxdata) );
2636 
2637  /* for Benders' decomposition, the Benders' plugin must be activated */
2638  if( relaxdata->mode == DEC_DECMODE_BENDERS )
2639  {
2640  SCIP_CALL( SCIPactivateBenders(relaxdata->masterprob, SCIPfindBenders(relaxdata->masterprob, "gcg"),
2641  relaxdata->npricingprobs) );
2642  }
2643 
2644  relaxdata->lastsolvednodenr = -1;
2645 
2646  /* set objective limit in master problem if objective limit in original problem is finite */
2647  if( !SCIPisInfinity(scip, (int) SCIPgetObjsense(scip) * SCIPgetObjlimit(scip)) )
2648  {
2649  SCIP_CALL( SCIPsetObjlimit(relaxdata->masterprob, (int) SCIPgetObjsense(scip) * SCIPgetObjlimit(scip)) );
2650  }
2651 
2652  return SCIP_OKAY;
2653 }
2654 
2655 /** initializes relaxator data */
2656 static
2658  SCIP_RELAXDATA* relaxdata /**< relaxdata data structure */
2659  )
2660 {
2661  assert(relaxdata != NULL);
2662 
2663  relaxdata->decomp = NULL;
2664 
2665  relaxdata->blockrepresentative = NULL;
2666  relaxdata->convconss = NULL;
2667  relaxdata->hashorig2origvar = NULL;
2668  relaxdata->lastsolvednodenr = 0;
2669 
2670  relaxdata->origmasterconss = NULL;
2671  relaxdata->masterconss = NULL;
2672  relaxdata->nmasterconss = 0;
2673 
2674  relaxdata->npricingprobs = -1;
2675  relaxdata->pricingprobs = NULL;
2676  relaxdata->nrelpricingprobs = 0;
2677  relaxdata->currentorigsol = NULL;
2678  relaxdata->storedorigsol = NULL;
2679  relaxdata->origsolfeasible = FALSE;
2680  relaxdata->storedfeasibility = FALSE;
2681  relaxdata->nblocksidentical = NULL;
2682 
2683  relaxdata->lastmastersol = NULL;
2684  relaxdata->lastmasterlpiters = 0;
2685  relaxdata->markedmasterconss = NULL;
2686  relaxdata->maxmarkedmasterconss = 0;
2687  relaxdata->masterinprobing = FALSE;
2688  relaxdata->probingheur = NULL;
2689 
2690  relaxdata->ntransvars = 0;
2691  relaxdata->nlinkingvars = 0;
2692  relaxdata->nvarlinkconss = 0;
2693  relaxdata->varlinkconss = NULL;
2694  relaxdata->varlinkconsblock = NULL;
2695  relaxdata->pricingprobsmemused = 0.0;
2696 
2697  relaxdata->relaxisinitialized = FALSE;
2698  relaxdata->simplexiters = 0;
2699  relaxdata->rootnodetime = NULL;
2700 }
2701 
2702 /*
2703  * Callback methods of relaxator
2704  */
2705 
2706 /** destructor of relaxator to free user data (called when SCIP is exiting) */
2707 static
2708 SCIP_DECL_RELAXFREE(relaxFreeGcg)
2709 {
2710  SCIP_RELAXDATA* relaxdata;
2711 
2712  relaxdata = SCIPrelaxGetData(relax);
2713  assert(relaxdata != NULL);
2714 
2715  /* free visualization parameters */
2716  if( relaxdata->paramsvisu != NULL )
2717  {
2718  GCGVisuFreeParams(scip, relaxdata->paramsvisu);
2719  }
2720 
2721  /* free master problem */
2722  if( relaxdata->masterprob != NULL )
2723  {
2724  SCIP_CALL( SCIPfree(&(relaxdata->masterprob)) );
2725  }
2726 
2727  /* free the alternate master problem */
2728  if( relaxdata->altmasterprob != NULL )
2729  {
2730  SCIP_CALL( SCIPfree(&(relaxdata->altmasterprob)) );
2731  }
2732 
2733  /* free used decomposition */
2734  if( relaxdata->decomp != NULL )
2735  {
2736  SCIP_CALL( DECdecompFree(scip, &relaxdata->decomp) );
2737  }
2738 
2739  SCIPfreeMemory(scip, &relaxdata);
2740  return SCIP_OKAY;
2741 }
2742 
2743 /** deinitialization method of relaxator (called before transformed problem is freed) */
2744 
2745 static
2746 SCIP_DECL_RELAXEXIT(relaxExitGcg)
2747 {
2748  SCIP_RELAXDATA* relaxdata;
2749 
2750  assert(scip != NULL);
2751  assert(relax != NULL);
2752 
2753  relaxdata = SCIPrelaxGetData(relax);
2754  assert(relaxdata != NULL);
2755 
2756  if( relaxdata->decomp != NULL )
2757  {
2758  SCIP_CALL( DECdecompFree(scip, &relaxdata->decomp) );
2759  relaxdata->decomp = NULL;
2760  }
2761 
2762  /* free array for branchrules*/
2763  if( relaxdata->nbranchrules > 0 )
2764  {
2765  int i;
2766 
2767  for( i = 0; i < relaxdata->nbranchrules; i++ )
2768  {
2769  SCIPfreeMemory(scip, &(relaxdata->branchrules[i]));
2770  }
2771  SCIPfreeMemoryArray(scip, &(relaxdata->branchrules));
2772  }
2773 
2774 
2775  relaxdata->nbranchrules = 0;
2776  relaxdata->relaxisinitialized = FALSE;
2777 
2778  return SCIP_OKAY;
2779 }
2780 
2781 
2782 /** initialize the relaxator and master problem for solving the original problem by Dantzig-Wolfe reformulation and
2783  * Benders' decomposition
2784  */
2785 static
2787  SCIP* scip, /**< the SCIP data structure */
2788  SCIP_RELAX* relax /**< the relaxator */
2789 )
2790 {
2791  SCIP_RELAXDATA* relaxdata;
2792  SCIP_Bool cutoff;
2793 
2794  assert(scip != NULL);
2795  assert(relax != NULL);
2796 
2797  relaxdata = SCIPrelaxGetData(relax);
2798  assert(relaxdata != NULL);
2799 
2800  /* the relaxator is initialised if it has not been previously initialised */
2801  if( !relaxdata->relaxisinitialized )
2802  {
2803  /* set integral objective status in the extended problem, if possible */
2804  if( SCIPisObjIntegral(scip) && relaxdata->discretization && SCIPgetNContVars(scip) == 0
2805  && relaxdata->mode == DEC_DECMODE_DANTZIGWOLFE )
2806  {
2807  SCIP_CALL( SCIPsetObjIntegral(relaxdata->masterprob) );
2808  }
2809  SCIP_CALL( transformMaster(scip, relax) );
2810  /* transform the decomposition */
2811  // SCIP_CALL( DECdecompTransform(scip, relaxdata->decomp) );
2812  SCIP_CALL( GCGconsOrigbranchAddRootCons(scip) );
2813  relaxdata->relaxisinitialized = TRUE;
2814  assert(relaxdata->decomp != NULL);
2815  }
2816 
2817  if( !SCIPisLPConstructed(scip) ) {
2818  /* construct the LP in the original problem */
2819  SCIP_CALL(SCIPconstructLP(scip, &cutoff));
2820  assert(!cutoff);
2821  SCIP_CALL(SCIPflushLP(scip));
2822  }
2823 
2824  return SCIP_OKAY;
2825 }
2826 
2827 
2828 /** solving process initialization method of relaxator (called when branch and bound process is about to begin) */
2829 static
2830 SCIP_DECL_RELAXINITSOL(relaxInitsolGcg)
2831 {
2832  SCIP_RELAXDATA* relaxdata;
2833 
2834  assert(scip != NULL);
2835  assert(relax != NULL);
2836 
2837  relaxdata = SCIPrelaxGetData(relax);
2838  assert(relaxdata != NULL);
2839  assert(relaxdata->masterprob != NULL);
2840 
2841  initRelaxdata(relaxdata);
2842  SCIP_CALL( SCIPcreateClock(scip, &(relaxdata->rootnodetime)) );
2843 
2844  /* if the master problem decomposition mode is the same as the original SCIP instance mode, then the master problem
2845  * must be swapped with the alternate master problem.
2846  */
2847  if( GCGgetMasterDecompMode(relaxdata->masterprob) != DEC_DECMODE_ORIGINAL &&
2848  GCGgetMasterDecompMode(relaxdata->masterprob) != GCGgetDecompositionMode(scip) )
2849  {
2850  SCIP* tmpscip;
2851 
2852  tmpscip = relaxdata->masterprob;
2853  relaxdata->masterprob = relaxdata->altmasterprob;
2854  relaxdata->altmasterprob = tmpscip;
2855  }
2856 
2857  /* alternative verbosity levels are used for the Benders' decomposition and original mode compared to the Dantzig-Wolfe
2858  * decomposition mode.
2859  */
2861  {
2862  /* first getting the verbosity level for the original problem before setting it to none. While the verbosity level
2863  * was collected previously, the user may have changed this in the mean time.
2864  */
2865  SCIP_CALL( SCIPgetIntParam(scip, "display/verblevel", &relaxdata->origverblevel) );
2866 
2867  /* deactivating display columns */
2868  SCIP_CALL( SCIPsetIntParam(scip, "display/sumlpiterations/active", 0) );
2869  SCIP_CALL( SCIPsetIntParam(scip, "display/lpiterations/active", 0) );
2870  SCIP_CALL( SCIPsetIntParam(scip, "display/degeneracy/active", 0) );
2871 
2872  /* setting the total node limit to 1 for the original SCIP instance. This is because Benders' decomposition solves
2873  * the MIP within the relaxator of the root node. So no branching in the original problem is required.
2874  */
2875  SCIP_CALL( SCIPsetLongintParam(scip, "limits/totalnodes", 1LL) );
2876  }
2877 
2878  /* fixing the GCG mode parameter. This ensure that the user does not change this during the solution process. If the
2879  * mode parameter were to change, the behaviour is unknown.
2880  */
2881  SCIP_CALL( SCIPfixParam(scip, "relaxing/gcg/mode") );
2882 
2883  /* Informing the user of the decomposition technique that is being used to solve the original problem */
2884  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "\n");
2885  if( relaxdata->mode == DEC_DECMODE_DANTZIGWOLFE )
2886  {
2887  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "A Dantzig-Wolfe reformulation is applied to solve the original problem.\n");
2888  }
2889  else if( relaxdata->mode == DEC_DECMODE_BENDERS )
2890  {
2891  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "A Benders' decomposition is applied to solve the original problem.\n");
2892  }
2893  else if( relaxdata->mode == DEC_DECMODE_ORIGINAL )
2894  {
2895  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "No reformulation will be performed. Solving the original model.\n");
2896  }
2897 
2898  if( !SCIPisStopped(scip) )
2899  SCIP_CALL( initRelaxator(scip, relax) );
2900 
2901  return SCIP_OKAY;
2902 }
2903 
2904 
2905 /** solving process deinitialization method of relaxator (called before branch and bound process data is freed) */
2906 static
2907 SCIP_DECL_RELAXEXITSOL(relaxExitsolGcg)
2908 {
2909  SCIP_RELAXDATA* relaxdata;
2910  int i;
2911 
2912  assert(scip != NULL);
2913  assert(relax != NULL);
2914 
2915  relaxdata = SCIPrelaxGetData(relax);
2916  assert(relaxdata != NULL);
2917 
2918  if( relaxdata->hashorig2origvar != NULL )
2919  {
2920  SCIPhashmapFree(&(relaxdata->hashorig2origvar));
2921  relaxdata->hashorig2origvar = NULL;
2922  }
2923 
2924  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->markedmasterconss), relaxdata->maxmarkedmasterconss);
2925  relaxdata->markedmasterconss = NULL;
2926  relaxdata->maxmarkedmasterconss = 0;
2927 
2928  /* free arrays for constraints */
2929  for( i = 0; i < relaxdata->nmasterconss; i++ )
2930  {
2931  SCIP_CALL( SCIPreleaseCons(scip, &relaxdata->origmasterconss[i]) );
2932  SCIP_CALL( SCIPreleaseCons(relaxdata->masterprob, &relaxdata->masterconss[i]) );
2933  }
2934  for( i = 0; i < relaxdata->npricingprobs; i++ )
2935  {
2936  if( relaxdata->convconss[i] != NULL )
2937  SCIP_CALL( SCIPreleaseCons(relaxdata->masterprob, &relaxdata->convconss[i]) );
2938  }
2939  for( i = 0; i < relaxdata->nvarlinkconss; i++ )
2940  {
2941  SCIP_CALL( SCIPreleaseCons(relaxdata->masterprob, &relaxdata->varlinkconss[i]) );
2942  }
2943  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->varlinkconss), relaxdata->nvarlinkconss);
2944  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->varlinkconsblock), relaxdata->nvarlinkconss);
2945  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->origmasterconss), relaxdata->maxmasterconss);
2946  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->masterconss), relaxdata->maxmasterconss);
2947  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->convconss), relaxdata->npricingprobs);
2948 
2949  /* free master problem */
2950  if( relaxdata->masterprob != NULL )
2951  {
2952  SCIP_CALL( SCIPfreeProb(relaxdata->masterprob) );
2953  }
2954 
2955  /* free pricing problems */
2956  for( i = relaxdata->npricingprobs - 1; i >= 0 ; i-- )
2957  {
2958  SCIP_CALL( SCIPfree(&(relaxdata->pricingprobs[i])) );
2959  }
2960  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->pricingprobs), relaxdata->npricingprobs);
2961  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->blockrepresentative), relaxdata->npricingprobs);
2962  SCIPfreeBlockMemoryArrayNull(scip, &(relaxdata->nblocksidentical), relaxdata->npricingprobs);
2963 
2964  /* free solutions */
2965  if( relaxdata->currentorigsol != NULL )
2966  {
2967  SCIP_CALL( SCIPfreeSol(scip, &relaxdata->currentorigsol) );
2968  }
2969  if( relaxdata->storedorigsol != NULL )
2970  {
2971  SCIP_CALL( SCIPfreeSol(scip, &relaxdata->storedorigsol) );
2972  }
2973 
2974  if( relaxdata->decomp != NULL )
2975  {
2976  SCIP_CALL( DECdecompFree(scip, &relaxdata->decomp) );
2977  relaxdata->decomp = NULL;
2978  }
2979 
2980  SCIP_CALL( GCGfreeOrigVarsData(scip) );
2981 
2982  /* free root node clock */
2983  if( relaxdata->rootnodetime != NULL )
2984  {
2985  SCIP_CALL( SCIPfreeClock(scip, &(relaxdata->rootnodetime)) );
2986  }
2987 
2988  relaxdata->relaxisinitialized = FALSE;
2989 
2990  return SCIP_OKAY;
2991 }
2992 
2993 
2994 /** method to solve the master problem that is used by Dantzig-Wolfe and Benders' decomposition */
2995 static
2996 SCIP_RETCODE solveMasterProblem(
2997  SCIP* scip, /**< the SCIP data structure */
2998  SCIP* masterprob, /**< the master problem SCIP instance */
2999  SCIP_RELAXDATA* relaxdata, /**< the relaxator data */
3000  SCIP_Longint nodelimit, /**< the number of nodes the will be solved in this master problem */
3001  SCIP_Real* lowerbound, /**< the lowerbound computed by the relaxator for the current node */
3002  SCIP_RESULT* result /**< the result of the relaxation call */
3003  )
3004 {
3005  SCIP_Real timelimit;
3006  SCIP_Real memorylimit;
3007 
3008  assert(scip != NULL);
3009  assert(masterprob != NULL);
3010  assert(relaxdata != NULL);
3011 
3012  /* update the number of the last solved node */
3013  relaxdata->lastsolvednodenr = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
3014 
3015  /* increase the node limit for the master problem by 1 */
3016  SCIP_CALL( SCIPsetLongintParam(masterprob, "limits/nodes", nodelimit) );
3017 
3018 
3019  /* loop to solve the master problem, this is a workaround and does not fix any problem */
3020  while( !SCIPisStopped(scip) )
3021  {
3022  SCIP_Real mastertimelimit = SCIPinfinity(scip);
3023 
3024  /* set memorylimit for master */
3025  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
3026  if( !SCIPisInfinity(scip, memorylimit) )
3027  memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
3028 
3029  SCIP_CALL( SCIPsetRealParam(masterprob, "limits/memory", memorylimit) );
3030 
3031  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
3032  if( !SCIPisInfinity(scip, timelimit) )
3033  {
3034 
3035  /* give the master 2% more time then the original scip has left */
3036  mastertimelimit = (timelimit - SCIPgetSolvingTime(scip)) * 1.02 + SCIPgetSolvingTime(masterprob);
3037  SCIP_CALL( SCIPsetRealParam(masterprob, "limits/time", mastertimelimit) );
3038 
3039  SCIPdebugMessage(" time limit for master: %f, left: %f, left for original problem: %f\n",
3040  mastertimelimit,
3041  mastertimelimit - SCIPgetSolvingTime(masterprob),
3042  timelimit - SCIPgetSolvingTime(scip));
3043  }
3044 
3045  /* if we have a blockdetection, see whether the node is block diagonal. Additionally, the solveDiagonalBlocks can
3046  * be called when the original problem is solved directly.
3047  */
3049  {
3050  SCIP_CALL( solveDiagonalBlocks(scip, relaxdata, result, lowerbound) );
3051  if( *result == SCIP_SUCCESS || *result == SCIP_CUTOFF )
3052  {
3053  *result = SCIP_CUTOFF;
3054  return SCIP_OKAY;
3055  }
3056  }
3057  /* We are solving the masterproblem regularly */
3058  else
3059  {
3060  SCIP_CALL( SCIPsolve(masterprob) );
3061  }
3062 
3063 
3064  if( SCIPgetStatus(masterprob) != SCIP_STATUS_TIMELIMIT )
3065  {
3066  break;
3067  }
3068 
3069  if( !SCIPisInfinity(scip, timelimit) && !SCIPisStopped(scip) )
3070  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "time for master problem was too short, extending time by %f.\n", mastertimelimit - SCIPgetSolvingTime(masterprob));
3071  }
3072  if( SCIPgetStatus(masterprob) == SCIP_STATUS_TIMELIMIT && SCIPisStopped(scip) )
3073  {
3074  *result = SCIP_DIDNOTRUN;
3075  return SCIP_OKAY;
3076  }
3077 
3078  /* set the lower bound pointer */
3079  if( SCIPgetStage(masterprob) == SCIP_STAGE_SOLVING && GCGmasterIsCurrentSolValid(masterprob) )
3080  {
3081  *lowerbound = SCIPgetLocalDualbound(masterprob);
3082  }
3083  else
3084  {
3085  SCIPdebugMessage(" stage: %d\n", SCIPgetStage(masterprob));
3086  assert(SCIPgetStatus(masterprob) == SCIP_STATUS_TIMELIMIT || SCIPgetBestSol(masterprob) != NULL || SCIPgetStatus(masterprob) == SCIP_STATUS_INFEASIBLE || SCIPgetStatus(masterprob) == SCIP_STATUS_UNKNOWN);
3087  if( SCIPgetStatus(masterprob) == SCIP_STATUS_OPTIMAL && GCGmasterIsCurrentSolValid(masterprob) )
3088  *lowerbound = SCIPgetSolOrigObj(masterprob, SCIPgetBestSol(masterprob));
3089  else if( SCIPgetStatus(masterprob) == SCIP_STATUS_INFEASIBLE || SCIPgetStatus(masterprob) == SCIP_STATUS_TIMELIMIT || !GCGmasterIsCurrentSolValid(masterprob) )
3090  {
3091  SCIP_Real tilim;
3092  SCIP_CALL( SCIPgetRealParam(masterprob, "limits/time", &tilim) );
3093  if( tilim-SCIPgetSolvingTime(masterprob) < 0 )
3094  {
3095  *result = SCIP_DIDNOTRUN;
3096  return SCIP_OKAY;
3097  }
3098  *lowerbound = SCIPinfinity(scip);
3099  }
3100  else if( SCIPgetStatus(masterprob) == SCIP_STATUS_UNKNOWN )
3101  {
3102  *result = SCIP_DIDNOTRUN;
3103  return SCIP_OKAY;
3104  }
3105  else
3106  {
3107  SCIPwarningMessage(scip, "Stage <%d> is not handled!\n", SCIPgetStage(masterprob));
3108  *result = SCIP_DIDNOTRUN;
3109  return SCIP_OKAY;
3110  }
3111  }
3112 
3113  SCIPdebugMessage(" update lower bound (value = %g).\n", *lowerbound);
3114 
3115  /* NOTE: All other points when result is set, the function is exited immediately. Ensure that this is checked for
3116  * future changes to this function
3117  */
3118  *result = SCIP_SUCCESS;
3119 
3120  return SCIP_OKAY;
3121 }
3122 
3123 
3124 /** execution method of the relaxator for Dantzig-Wolfe reformulation */
3125 static
3127  SCIP* scip, /**< the SCIP data structure */
3128  SCIP_RELAX* relax, /**< the relaxator */
3129  SCIP_Real* lowerbound, /**< the lowerbound computed by the relaxator for the current node */
3130  SCIP_RESULT* result /**< the result of the relaxation call */
3131  )
3132 {
3133  SCIP* masterprob;
3134  SCIP_RELAXDATA* relaxdata;
3135  SCIP_Longint oldnnodes;
3136  SCIP_Longint nodelimit;
3137  SCIP_Bool stored;
3138 
3139  assert(scip != NULL);
3140  assert(relax != NULL);
3141  assert(result != NULL);
3143 
3144  relaxdata = SCIPrelaxGetData(relax);
3145  assert(relaxdata != NULL);
3146  *result = SCIP_DIDNOTRUN;
3147 
3148  masterprob = relaxdata->masterprob;
3149  assert(masterprob != NULL);
3150 
3151  /* solve the next node in the master problem */
3152  SCIPdebugMessage("Solving node %"SCIP_LONGINT_FORMAT"'s relaxation.\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
3153 
3154  /* only solve the relaxation if it was not yet solved at the current node */
3155  if( SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) != relaxdata->lastsolvednodenr )
3156  {
3157  /* start root node time clock */
3158  if( SCIPgetRootNode(scip) == SCIPgetCurrentNode(scip) )
3159  {
3160  SCIP_CALL( SCIPstartClock(scip, relaxdata->rootnodetime) );
3161  SCIPdebugMessage(" root node time clock started.\n");
3162  }
3163 
3164  /* increase the node limit for the master problem by 1 */
3165  SCIP_CALL( SCIPgetLongintParam(masterprob, "limits/nodes", &oldnnodes) );
3166 
3167  nodelimit = (SCIPgetRootNode(scip) == SCIPgetCurrentNode(scip) ? 1 : oldnnodes + 1);
3168  /* solving the master problem */
3169  SCIP_CALL( solveMasterProblem(scip, masterprob, relaxdata, nodelimit, lowerbound, result) );
3170 
3171  if( relaxdata->currentorigsol != NULL )
3172  {
3173  SCIP_CALL( SCIPtrySol(scip, relaxdata->currentorigsol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
3174  }
3175 
3176  /* if a new primal solution was found in the master problem, transfer it to the original problem */
3177  if( SCIPgetBestSol(relaxdata->masterprob) != NULL && relaxdata->lastmastersol != SCIPgetBestSol(relaxdata->masterprob) && GCGmasterIsCurrentSolValid(masterprob) )
3178  {
3179  SCIP_SOL* newsol;
3180 
3181  relaxdata->lastmastersol = SCIPgetBestSol(relaxdata->masterprob);
3182 
3183  SCIP_CALL( GCGtransformMastersolToOrigsol(scip, relaxdata->lastmastersol, &newsol) );
3184  #ifdef SCIP_DEBUG
3185  SCIP_CALL( SCIPtrySol(scip, newsol, TRUE, TRUE, TRUE, TRUE, TRUE, &stored) );
3186  #else
3187  SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
3188  #endif
3189  /* only check failed solution if best master solution is valid */
3190  if( !stored && GCGmasterIsBestsolValid(relaxdata->masterprob) )
3191  {
3192  SCIP_CALL( SCIPcheckSolOrig(scip, newsol, &stored, TRUE, TRUE) );
3193  }
3194  /** @bug The solution doesn't have to be accepted, numerics might bite us, so the transformation might fail.
3195  * A remedy could be: Round the values or propagate changes or call a heuristic to fix it.
3196  */
3197  SCIP_CALL( SCIPfreeSol(scip, &newsol) );
3198 
3199  if( stored )
3200  SCIPdebugMessage(" updated current best primal feasible solution.\n");
3201  }
3202 
3204  {
3207  }
3208 
3209  /* stop root node clock */
3210  if( SCIPgetRootNode(scip) == SCIPgetCurrentNode(scip))
3211  {
3212  SCIP_CALL( SCIPstopClock(scip, relaxdata->rootnodetime) );
3213  SCIPdebugMessage(" root node time clock stopped at %6.2fs.\n", SCIPgetClockTime(scip, relaxdata->rootnodetime));
3214  }
3215  }
3216  else
3217  {
3218  SCIPdebugMessage("Problem has been already solved at this node\n");
3219  }
3220 
3221  return SCIP_OKAY;
3222 }
3223 
3224 
3225 /** method to solve the master problem for Benders' decomposition and when solving the original problem directly. */
3226 static
3228  SCIP* scip, /**< the SCIP data structure */
3229  SCIP_RELAX* relax, /**< the relaxator */
3230  SCIP_Real* lowerbound, /**< the lowerbound computed by the relaxator for the current node */
3231  SCIP_RESULT* result /**< the result of the relaxation call */
3232  )
3233 {
3234  SCIP* masterprob;
3235  SCIP_RELAXDATA* relaxdata;
3236  SCIP_Longint nodelimit;
3237 
3238  assert(scip != NULL);
3239  assert(relax != NULL);
3240  assert(result != NULL);
3241 
3242  relaxdata = SCIPrelaxGetData(relax);
3243  assert(relaxdata != NULL);
3244  *result = SCIP_DIDNOTRUN;
3245 
3246  masterprob = relaxdata->masterprob;
3247  assert(masterprob != NULL);
3248 
3249  /* solve the next node in the master problem */
3250  SCIPdebugMessage("Solving node %"SCIP_LONGINT_FORMAT"'s relaxation.\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
3251 
3252  /* prior to performing the decomposition the original problem verbosity is changed to NONE. This avoids output from
3253  * the original problem before the decomposition output. Once the decomposition has been performed, then the
3254  * verbosity level of the original problem is returned to the original verbosity level.
3255  */
3256  SCIP_CALL( SCIPsetIntParam(scip, "display/verblevel", relaxdata->origverblevel) );
3257  SCIP_CALL( SCIPsetIntParam(masterprob, "display/verblevel", relaxdata->origverblevel) );
3258 
3259  /* getting the node limit from the original problem. This is because the master problem is solved to optimality in
3260  * the execution of the relaxator.
3261  */
3262  SCIP_CALL( SCIPgetLongintParam(scip, "limits/nodes", &nodelimit) );
3263 
3264  /* solving the master problem */
3265  SCIP_CALL( solveMasterProblem(scip, masterprob, relaxdata, nodelimit, lowerbound, result) );
3266 
3267  /* if the master problem has been detected as infeasible, then the result must be set to SCIP_CUTOFF. */
3268  if( SCIPgetStatus(masterprob) == SCIP_STATUS_INFEASIBLE )
3269  (*result) = SCIP_CUTOFF;
3270 
3271  /* if the master problem has been solved to optimality, the we cutoff the root node. This informs that original
3272  * problem that no further processing is required.
3273  */
3274  if( SCIPgetStatus(masterprob) == SCIP_STATUS_OPTIMAL )
3275  {
3276  (*result) = SCIP_CUTOFF;
3277  }
3278 
3279  /* if there is no primal solution for the original problem, then the master solution is transferred */
3280  if( SCIPgetBestSol(relaxdata->masterprob) != NULL && relaxdata->lastmastersol != SCIPgetBestSol(relaxdata->masterprob) )
3281  {
3282  SCIP_SOL* newsol;
3283  SCIP_Bool stored;
3284 
3285  relaxdata->lastmastersol = SCIPgetBestSol(relaxdata->masterprob);
3286 
3287  SCIP_CALL( GCGtransformMastersolToOrigsol(scip, SCIPgetBestSol(relaxdata->masterprob), &newsol) );
3288 #ifdef SCIP_DEBUG
3289  SCIP_CALL( SCIPtrySol(scip, newsol, TRUE, TRUE, TRUE, TRUE, TRUE, &stored) );
3290 #else
3291  SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
3292 #endif
3293  /* only check failed solution if best master solution is valid */
3294  if( !stored && GCGmasterIsBestsolValid(relaxdata->masterprob) )
3295  {
3296  SCIP_CALL( SCIPcheckSolOrig(scip, newsol, &stored, TRUE, TRUE) );
3297  }
3298  /** @bug The solution doesn't have to be accepted, numerics might bite us, so the transformation might fail.
3299  * A remedy could be: Round the values or propagate changes or call a heuristic to fix it.
3300  */
3301  SCIP_CALL( SCIPfreeSol(scip, &newsol) );
3302 
3303  if( stored )
3304  SCIPdebugMessage(" updated current best primal feasible solution.\n");
3305  }
3306 
3307  /* set the lower bound pointer */
3308  if( GCGmasterIsCurrentSolValid(masterprob)
3309  && (SCIPgetStage(masterprob) == SCIP_STAGE_SOLVED || SCIPgetStage(masterprob) == SCIP_STAGE_SOLVING) )
3310  {
3311  *lowerbound = SCIPgetDualbound(masterprob);
3312  }
3313 
3314  /* if the time, memory or node limit is hit in the Original or Benders mode, then we need to interrupt the solve.
3315  * This is required because the original problem is not solved in either of these modes, so it is not certain that
3316  * the original SCIP will also exceed the limit (definitely not for the node limit).
3317  */
3318  if( SCIPgetStatus(masterprob) == SCIP_STATUS_TIMELIMIT || SCIPgetStatus(masterprob) == SCIP_STATUS_NODELIMIT
3319  || SCIPgetStatus(masterprob) == SCIP_STATUS_MEMLIMIT )
3320  {
3321  SCIP_CALL( SCIPinterruptSolve(scip) );
3322  }
3323 
3324  /* if the result pointer is DIDNOTRUN, this implies that the master problem was interrupted during solving. Since
3325  * Benders' decomposition uses a one-tree approach, then the user limits must be adhered to. This means, the if a
3326  * limit is exceeded, this is still a success for the solving.
3327  */
3328  if( (*result) == SCIP_DIDNOTRUN )
3329  (*result) = SCIP_SUCCESS;
3330 
3331  return SCIP_OKAY;
3332 }
3333 
3334 /** execution method of the relaxator for Benders' decomposition */
3335 static
3337  SCIP* scip, /**< the SCIP data structure */
3338  SCIP_RELAX* relax, /**< the relaxator */
3339  SCIP_Real* lowerbound, /**< the lowerbound computed by the relaxator for the current node */
3340  SCIP_RESULT* result /**< the result of the relaxation call */
3341  )
3342 {
3343  assert(scip != NULL);
3344  assert(relax != NULL);
3345  assert(result != NULL);
3346 
3347  SCIP_CALL( solveMasterProblemAndEvaluate(scip, relax, lowerbound, result) );
3348 
3349  return SCIP_OKAY;
3350 }
3351 
3352 /** execution method of the relaxator when the original problem is solved directly */
3353 static
3355  SCIP* scip, /**< the SCIP data structure */
3356  SCIP_RELAX* relax, /**< the relaxator */
3357  SCIP_Real* lowerbound, /**< the lowerbound computed by the relaxator for the current node */
3358  SCIP_RESULT* result /**< the result of the relaxation call */
3359  )
3360 {
3361  assert(scip != NULL);
3362  assert(relax != NULL);
3363  assert(result != NULL);
3364 
3365  SCIP_CALL( solveMasterProblemAndEvaluate(scip, relax, lowerbound, result) );
3366 
3367  return SCIP_OKAY;
3368 }
3369 
3370 
3371 /** execution method of relaxator */
3372 static
3373 SCIP_DECL_RELAXEXEC(relaxExecGcg)
3374 {
3375  SCIP_RELAXDATA* relaxdata;
3376 
3377  assert(scip != NULL);
3378  assert(relax != NULL);
3379  assert(result != NULL);
3380 
3381  relaxdata = SCIPrelaxGetData(relax);
3382  assert(relaxdata != NULL);
3383 
3384  /* checking whether the relaxator needs to be initialised. If so, then the master problem and pricing problems will
3385  * be created.
3386  */
3387  SCIP_CALL( initializeMasterProblemSolve(scip, relax) );
3388 
3389  /* selecting the solving algorithm based upon the decomposition mode selected by the user, or whether the original
3390  * problem should be solved directly
3391  */
3393  {
3394  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "There are no pricing problems in the decomposition. The original problem will be solved directly.\n");
3395  SCIP_CALL( relaxExecGcgOriginalProblem(scip, relax, lowerbound, result) );
3396  }
3397  else if( relaxdata->mode == DEC_DECMODE_DANTZIGWOLFE )
3398  {
3399  SCIP_CALL( relaxExecGcgDantzigWolfe(scip, relax, lowerbound, result) );
3400  }
3401  else if( relaxdata->mode == DEC_DECMODE_BENDERS )
3402  {
3403  SCIP_CALL( relaxExecGcgBendersDecomposition(scip, relax, lowerbound, result) );
3404  }
3405  else
3406  {
3407  SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "Sorry, the automatic selection is not currently available\n");
3408  }
3409 
3410  return SCIP_OKAY;
3411 }
3412 
3413 #define relaxCopyGcg NULL
3414 #define relaxInitGcg NULL
3415 
3416 
3417 /*
3418  * relaxator specific interface methods
3419  */
3420 
3421 /** creates the GCG relaxator and includes it in SCIP */
3422 SCIP_RETCODE SCIPincludeRelaxGcg(
3423  SCIP* scip /**< SCIP data structure */
3424  )
3425 {
3426  SCIP_RELAXDATA* relaxdata;
3427 
3428 #ifdef WITH_BLISS
3429  {
3430  char name[SCIP_MAXSTRLEN];
3431  GCGgetBlissName(name, SCIP_MAXSTRLEN);
3432  SCIP_CALL( SCIPincludeExternalCodeInformation(scip, name, "A Tool for Computing Automorphism Groups of Graphs by T. Junttila and P. Kaski (http://www.tcs.hut.fi/Software/bliss/)") );
3433  }
3434 #endif
3435 
3436 #ifdef WITH_CLIQUER
3437  SCIP_CALL( SCIPincludeExternalCodeInformation(scip, "Cliquer", "A set of C routines for finding cliques in an arbitrary weighted graph by S. Niskanen and P. Ostergard (https://users.aalto.fi/~pat/cliquer.html)") );
3438 #endif
3439 
3440  /* create GCG relaxator data */
3441  SCIP_CALL( SCIPallocMemory(scip, &relaxdata) );
3442 
3443  relaxdata->decomp = NULL;
3444  relaxdata->nbranchrules = 0;
3445  relaxdata->branchrules = NULL;
3446  relaxdata->masterprob = NULL;
3447  relaxdata->altmasterprob = NULL;
3448  relaxdata->paramsvisu = NULL;
3449  SCIPcreateParamsVisu(scip, &(relaxdata->paramsvisu));
3450  assert(relaxdata->paramsvisu != NULL);
3451 
3452  initRelaxdata(relaxdata);
3453 
3454  /* include relaxator */
3455  SCIP_CALL( SCIPincludeRelax(scip, RELAX_NAME, RELAX_DESC, RELAX_PRIORITY, RELAX_FREQ, relaxCopyGcg, relaxFreeGcg, relaxInitGcg,
3456  relaxExitGcg, relaxInitsolGcg, relaxExitsolGcg, relaxExecGcg, relaxdata) );
3457 
3458  /* inform the main scip, that no LPs should be solved */
3459  SCIP_CALL( SCIPsetIntParam(scip, "lp/solvefreq", 0) );
3460 
3461  /* Disable restarts */
3462  SCIP_CALL( SCIPsetIntParam(scip, "presolving/maxrestarts", 0) );
3463  SCIP_CALL( SCIPsetBoolParam(scip, "misc/calcintegral", FALSE) );
3464 
3465  /* initialize the scip data structure for the master problem. The master problem is initialized as the Dantzig-Wolfe
3466  * master problem. The alternate master problem is initialized as the Benders' decomposition master problem.
3467  */
3468  SCIP_CALL( SCIPcreate(&(relaxdata->masterprob)) );
3469  SCIP_CALL( SCIPincludePricerGcg(relaxdata->masterprob, scip) );
3470  SCIP_CALL( GCGincludeMasterPlugins(relaxdata->masterprob) );
3471  SCIP_CALL( SCIPsetMessagehdlr(relaxdata->masterprob, SCIPgetMessagehdlr(scip)) );
3472 
3473  /* getting the verbosity level of the original problem */
3474  SCIP_CALL( SCIPgetIntParam(scip, "display/verblevel", &relaxdata->origverblevel) );
3475 
3476  /* disable display output in the master problem */
3477  SCIP_CALL( SCIPsetIntParam(relaxdata->masterprob, "display/verblevel", (int)SCIP_VERBLEVEL_NONE) );
3478 
3479  /* set parameters in master problem */
3480  SCIP_CALL( SCIPsetIntParam(relaxdata->masterprob, "pricing/maxvars", INT_MAX) );
3481  SCIP_CALL( SCIPsetIntParam(relaxdata->masterprob, "pricing/maxvarsroot", INT_MAX) );
3482  SCIP_CALL( SCIPsetRealParam(relaxdata->masterprob, "pricing/abortfac", 1.0) );
3483  SCIP_CALL( SCIPsetIntParam(relaxdata->masterprob, "lp/disablecutoff", 1) );
3484 #ifdef DELVARS
3485  /* set paramteters to allow deletion of variables */
3486  SCIP_CALL( SCIPsetBoolParam(relaxdata->masterprob, "pricing/delvars", TRUE) );
3487  SCIP_CALL( SCIPsetBoolParam(relaxdata->masterprob, "pricing/delvarsroot", TRUE) );
3488  SCIP_CALL( SCIPsetBoolParam(relaxdata->masterprob, "lp/cleanupcols", TRUE) );
3489  SCIP_CALL( SCIPsetBoolParam(relaxdata->masterprob, "lp/cleanupcolsroot", TRUE) );
3490 #endif
3491 
3492  /* initializing the alternate master problem. The alternate master problem is initially the Benders' decomposition
3493  * master problem
3494  */
3495  SCIP_CALL( SCIPcreate(&(relaxdata->altmasterprob)) );
3496  SCIP_CALL( SCIPincludeBendersGcg(relaxdata->altmasterprob, scip) );
3497  SCIP_CALL( GCGincludeBendersPlugins(relaxdata->altmasterprob) );
3498  SCIP_CALL( SCIPsetMessagehdlr(relaxdata->altmasterprob, SCIPgetMessagehdlr(scip)) );
3499 
3500  SCIP_CALL( SCIPsetIntParam(relaxdata->altmasterprob, "display/verblevel", (int)SCIP_VERBLEVEL_NONE) );
3501  SCIP_CALL( SCIPsetBoolParam(relaxdata->altmasterprob, "display/relevantstats", FALSE) );
3502 
3503  /* add GCG relaxator parameters */
3504  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/gcg/discretization",
3505  "should discretization (TRUE) or convexification (FALSE) approach be used?",
3506  &(relaxdata->discretization), FALSE, DEFAULT_DISCRETIZATION, NULL, NULL) );
3507  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/gcg/mipdiscretization",
3508  "should discretization (TRUE) or convexification (FALSE) approach be used in mixed-integer programs?",
3509  &(relaxdata->mipdiscretization), FALSE, DEFAULT_MIPDISCRETIZATION, NULL, NULL) );
3510  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/gcg/aggregation",
3511  "should identical blocks be aggregated (only for discretization approach)?",
3512  &(relaxdata->aggregation), FALSE, DEFAULT_AGGREGATION, NULL, NULL) );
3513  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/gcg/dispinfos",
3514  "should additional information about the blocks be displayed?",
3515  &(relaxdata->dispinfos), FALSE, DEFAULT_DISPINFOS, NULL, NULL) );
3516  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/gcg/mode",
3517  "the decomposition mode that GCG will use. (0: Dantzig-Wolfe (default), 1: Benders' decomposition, "
3518  "2: no decomposition will be performed)",
3519  (int*)&(relaxdata->mode), FALSE, (int)DEFAULT_MODE, 0, 2, NULL, NULL) );
3520 #ifdef WITH_BLISS
3521  SCIP_CALL( SCIPaddBoolParam(scip, "relaxing/gcg/bliss/enabled",
3522  "should bliss be used to check for identical blocks?",
3523  &(relaxdata->usebliss), FALSE, DEFAULT_BLISS, NULL, NULL) );
3524  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/gcg/bliss/searchnodelimit",
3525  "bliss search node limit (0: unlimited), requires patched bliss version",
3526  &(relaxdata->searchnodelimit), TRUE, (int)DEFAULT_BLISS_SEARCH_NODE_LIMIT, 0, INT_MAX, NULL, NULL) );
3527  SCIP_CALL( SCIPaddIntParam(scip, "relaxing/gcg/bliss/generatorlimit",
3528  "bliss generator limit (0: unlimited), requires patched bliss version",
3529  &(relaxdata->generatorlimit), TRUE, (int)DEFAULT_BLISS_GENERATOR_LIMIT, 0, INT_MAX, NULL, NULL) );
3530 #else
3531  relaxdata->usebliss = FALSE;
3532  relaxdata->searchnodelimit = 0;
3533  relaxdata->generatorlimit = 0;
3534 #endif
3535 
3536  return SCIP_OKAY;
3537 }
3538 
3539 
3540 /*
3541  * relaxator specific interface methods for coordination of branching rules
3542  */
3543 
3544 /** includes a branching rule into the relaxator data */
3546  SCIP* scip, /**< SCIP data structure */
3547  SCIP_BRANCHRULE* branchrule, /**< branching rule for which callback methods are saved */
3548  GCG_DECL_BRANCHACTIVEMASTER((*branchactivemaster)),/**< activation method for branchrule */
3549  GCG_DECL_BRANCHDEACTIVEMASTER((*branchdeactivemaster)),/**< deactivation method for branchrule */
3550  GCG_DECL_BRANCHPROPMASTER((*branchpropmaster)),/**< propagation method for branchrule */
3551  GCG_DECL_BRANCHMASTERSOLVED((*branchmastersolved)),/**< master solved method for branchrule */
3552  GCG_DECL_BRANCHDATADELETE((*branchdatadelete))/**< branchdata deletion method for branchrule */
3553  )
3554 {
3555  SCIP_RELAX* relax;
3556  SCIP_RELAXDATA* relaxdata;
3557  int pos;
3558 
3559  assert(scip != NULL);
3560  assert(branchrule != NULL);
3561 
3562  relax = SCIPfindRelax(scip, RELAX_NAME);
3563  assert(relax != NULL);
3564 
3565  relaxdata = SCIPrelaxGetData(relax);
3566  assert(relaxdata != NULL);
3567 
3568  SCIP_CALL( ensureSizeBranchrules(scip, relaxdata) );
3569 
3570  pos = relaxdata->nbranchrules;
3571 
3572  /* store callback functions */
3573  SCIP_CALL( SCIPallocMemory(scip, &(relaxdata->branchrules[pos])) ); /*lint !e866*/
3574  relaxdata->branchrules[pos]->branchrule = branchrule;
3575  relaxdata->branchrules[pos]->branchactivemaster = branchactivemaster;
3576  relaxdata->branchrules[pos]->branchdeactivemaster = branchdeactivemaster;
3577  relaxdata->branchrules[pos]->branchpropmaster = branchpropmaster;
3578  relaxdata->branchrules[pos]->branchmastersolved = branchmastersolved;
3579  relaxdata->branchrules[pos]->branchdatadelete = branchdatadelete;
3580  relaxdata->nbranchrules++;
3581 
3582  return SCIP_OKAY;
3583 }
3584 
3585 /** perform activation method of the given branchrule for the given branchdata */
3587  SCIP* scip, /**< SCIP data structure */
3588  SCIP_BRANCHRULE* branchrule, /**< branching rule that did the branching */
3589  GCG_BRANCHDATA* branchdata /**< data representing the branching decision */
3590  )
3591 {
3592  SCIP_RELAX* relax;
3593  SCIP_RELAXDATA* relaxdata;
3594  int i;
3595 
3596  assert(scip != NULL);
3597  assert(branchrule != NULL);
3598 
3599  relax = SCIPfindRelax(scip, RELAX_NAME);
3600  assert(relax != NULL);
3601 
3602  relaxdata = SCIPrelaxGetData(relax);
3603  assert(relaxdata != NULL);
3604 
3605  /* search for the branching rule in the branchrules array */
3606  for( i = 0; i < relaxdata->nbranchrules; i++ )
3607  {
3608  if( branchrule == relaxdata->branchrules[i]->branchrule )
3609  {
3610  /* call activation method of branching rule */
3611  if( relaxdata->branchrules[i]->branchactivemaster != NULL )
3612  SCIP_CALL( relaxdata->branchrules[i]->branchactivemaster(relaxdata->masterprob, branchdata) );
3613 
3614  break;
3615  }
3616  }
3617 
3618  assert(i < relaxdata->nbranchrules);
3619 
3620  return SCIP_OKAY;
3621 }
3622 
3623 /** perform deactivation method of the given branchrule for the given branchdata */
3625  SCIP* scip, /**< SCIP data structure */
3626  SCIP_BRANCHRULE* branchrule, /**< branching rule that did the branching */
3627  GCG_BRANCHDATA* branchdata /**< data representing the branching decision */
3628  )
3629 {
3630  SCIP_RELAX* relax;
3631  SCIP_RELAXDATA* relaxdata;
3632  int i;
3633 
3634  assert(scip != NULL);
3635  assert(branchrule != NULL);
3636 
3637  relax = SCIPfindRelax(scip, RELAX_NAME);
3638  assert(relax != NULL);
3639 
3640  relaxdata = SCIPrelaxGetData(relax);
3641  assert(relaxdata != NULL);
3642 
3643  /* search for the branching rule in the branchrules array */
3644  for( i = 0; i < relaxdata->nbranchrules; i++ )
3645  {
3646  if( branchrule == relaxdata->branchrules[i]->branchrule )
3647  {
3648  /* call deactivation method of branching rule */
3649  if( relaxdata->branchrules[i]->branchdeactivemaster != NULL )
3650  SCIP_CALL( relaxdata->branchrules[i]->branchdeactivemaster(relaxdata->masterprob, branchdata) );
3651 
3652  break;
3653  }
3654  }
3655 
3656  assert(i < relaxdata->nbranchrules);
3657 
3658  return SCIP_OKAY;
3659 }
3660 
3661 /** perform propagation method of the given branchrule for the given branchdata */
3663  SCIP* scip, /**< SCIP data structure */
3664  SCIP_BRANCHRULE* branchrule, /**< branching rule that did the branching */
3665  GCG_BRANCHDATA* branchdata, /**< data representing the branching decision */
3666  SCIP_RESULT* result /**< pointer to store the result of the propagation call */
3667  )
3668 {
3669  SCIP_RELAX* relax;
3670  SCIP_RELAXDATA* relaxdata;
3671  int i;
3672 
3673  assert(scip != NULL);
3674  assert(branchrule != NULL);
3675  assert(result != NULL);
3676 
3677  relax = SCIPfindRelax(scip, RELAX_NAME);
3678  assert(relax != NULL);
3679 
3680  relaxdata = SCIPrelaxGetData(relax);
3681  assert(relaxdata != NULL);
3682 
3683  *result = SCIP_DIDNOTRUN;
3684 
3685  /* search for the branching rule in the branchrules array */
3686  for( i = 0; i < relaxdata->nbranchrules; i++ )
3687  {
3688  if( branchrule == relaxdata->branchrules[i]->branchrule )
3689  {
3690  /* call propagation method of branching rule*/
3691  if( relaxdata->branchrules[i]->branchpropmaster != NULL )
3692  SCIP_CALL( relaxdata->branchrules[i]->branchpropmaster(relaxdata->masterprob, branchdata, result) );
3693 
3694  break;
3695  }
3696  }
3697 
3698  assert(i < relaxdata->nbranchrules);
3699 
3700  return SCIP_OKAY;
3701 }
3702 
3703 /** frees branching data created by the given branchrule */
3705  SCIP* scip, /**< SCIP data structure */
3706  SCIP_BRANCHRULE* branchrule, /**< branching rule that did the branching */
3707  GCG_BRANCHDATA** branchdata /**< data representing the branching decision */
3708  )
3709 {
3710  SCIP_RELAX* relax;
3711  SCIP_RELAXDATA* relaxdata;
3712  int i;
3713 
3714  assert(scip != NULL);
3715  assert(branchrule != NULL);
3716  assert(branchdata != NULL);
3717 
3718  relax = SCIPfindRelax(scip, RELAX_NAME);
3719  assert(relax != NULL);
3720 
3721  relaxdata = SCIPrelaxGetData(relax);
3722  assert(relaxdata != NULL);
3723 
3724  /* search for the branching rule in the branchrules array */
3725  for( i = 0; i < relaxdata->nbranchrules; i++ )
3726  {
3727  if( branchrule == relaxdata->branchrules[i]->branchrule )
3728  {
3729  /* call branchrule data deletion method of the branching rule */
3730  if( relaxdata->branchrules[i]->branchdatadelete != NULL )
3731  SCIP_CALL( relaxdata->branchrules[i]->branchdatadelete(scip, branchdata) );
3732  else
3733  {
3734  if( *branchdata != NULL )
3735  {
3736  SCIPfreeMemory(GCGgetMasterprob(scip), branchdata);
3737  }
3738  }
3739  break;
3740  }
3741  }
3742 
3743  assert(i < relaxdata->nbranchrules);
3744 
3745  return SCIP_OKAY;
3746 }
3747 
3748 /** perform method of the given branchrule that is called after the master LP is solved */
3750  SCIP* scip, /**< SCIP data structure */
3751  SCIP_BRANCHRULE* branchrule, /**< branching rule that did the branching */
3752  GCG_BRANCHDATA* branchdata, /**< data representing the branching decision */
3753  SCIP_Real newlowerbound /**< the new local lowerbound */
3754  )
3755 {
3756  SCIP_RELAX* relax;
3757  SCIP_RELAXDATA* relaxdata;
3758  int i;
3759 
3760  assert(scip != NULL);
3761  assert(branchrule != NULL);
3762 
3763  relax = SCIPfindRelax(scip, RELAX_NAME);
3764  assert(relax != NULL);
3765 
3766  relaxdata = SCIPrelaxGetData(relax);
3767  assert(relaxdata != NULL);
3768 
3769  /* search for the branching rule in the branchrules array */
3770  for( i = 0; i < relaxdata->nbranchrules; i++ )
3771  {
3772  if( branchrule == relaxdata->branchrules[i]->branchrule )
3773  {
3774  /* call master problem solved method of the branching rule */
3775  if( relaxdata->branchrules[i]->branchmastersolved != NULL )
3776  SCIP_CALL( relaxdata->branchrules[i]->branchmastersolved(scip, branchdata, newlowerbound) );
3777 
3778  break;
3779  }
3780  }
3781 
3782  assert(i < relaxdata->nbranchrules);
3783 
3784  return SCIP_OKAY;
3785 }
3786 
3787 /** transforms a constraint of the original problem into the master variable space
3788  * and stores information about the constraints in the variable */
3790  SCIP* scip, /**< SCIP data structure */
3791  SCIP_CONS* cons, /**< the constraint that should be transformed */
3792  SCIP_CONS** transcons /**< pointer to store the transformed constraint */
3793  )
3794 {
3795 
3796  SCIP_RELAX* relax;
3797  SCIP_RELAXDATA* relaxdata;
3798  SCIP_CONS* mastercons;
3799  char name[SCIP_MAXSTRLEN];
3800 
3801  SCIP_VAR** mastervars;
3802  int nmastervars;
3803  SCIP_VAR** consvars;
3804  SCIP_Real* consvals;
3805  int nconsvars;
3806  int v;
3807  int i;
3808  int j;
3809 
3810  SCIP_Bool success;
3811 
3812  assert(scip != NULL);
3813  assert(cons != NULL);
3814 
3815  relax = SCIPfindRelax(scip, RELAX_NAME);
3816  assert(relax != NULL);
3817 
3818  relaxdata = SCIPrelaxGetData(relax);
3819  assert(relaxdata != NULL);
3820 
3821  /* create and add corresponding linear constraint in the master problem */
3822  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "m_%s", SCIPconsGetName(cons));
3823  SCIP_CALL( SCIPcreateConsLinear(relaxdata->masterprob, &mastercons, name, 0, NULL, NULL,
3824  GCGconsGetLhs(scip, cons), GCGconsGetRhs(scip, cons),
3825  TRUE, TRUE, TRUE, TRUE, TRUE, SCIPconsIsLocal(cons), TRUE, FALSE, FALSE,
3826  SCIPconsIsStickingAtNode(cons)) );
3827 
3828  /* now compute coefficients of the master variables in the master constraint */
3829  mastervars = SCIPgetVars(relaxdata->masterprob);
3830  nmastervars = SCIPgetNVars(relaxdata->masterprob);
3831 
3832  consvars = SCIPgetVarsLinear(scip, cons);
3833  nconsvars = SCIPgetNVarsLinear(scip, cons);
3834  consvals = SCIPgetValsLinear(scip, cons);
3835 
3836 
3837  /* add coefs of the original variables in the constraint to their variable data */
3838  for( v = 0; v < nconsvars; v++ )
3839  {
3840  SCIP_CALL( GCGoriginalVarAddCoef(scip, consvars[v], consvals[v], mastercons) );
3841  }
3842 
3843  /* add master variables to the corresponding master constraint */
3844  for( v = 0; v < nmastervars; v++ )
3845  {
3846  SCIP_VAR** origvars;
3847  SCIP_Real* origvals;
3848  int norigvars;
3849  SCIP_Real coef = 0.0;
3850 
3851  origvars = GCGmasterVarGetOrigvars(mastervars[v]);
3852  norigvars = GCGmasterVarGetNOrigvars(mastervars[v]);
3853  origvals = GCGmasterVarGetOrigvals(mastervars[v]);
3854 
3855  for( i = 0; i < norigvars; i++ )
3856  for( j = 0; j < nconsvars; j++ )
3857  if( consvars[j] == origvars[i] )
3858  coef += consvals[j] * origvals[i];
3859 
3860  if( !SCIPisFeasZero(scip, coef) )
3861  {
3862  SCIP_CALL( SCIPaddCoefLinear(relaxdata->masterprob, mastercons, mastervars[v], coef) );
3863  }
3864  }
3865 
3866  /* store the constraints in the arrays origmasterconss and masterconss in the problem data */
3867  SCIP_CALL( ensureSizeMasterConss(scip, relaxdata, relaxdata->nmasterconss+1) );
3868  SCIP_CALL( SCIPcaptureCons(scip, cons) );
3869  relaxdata->origmasterconss[relaxdata->nmasterconss] = cons;
3870  relaxdata->masterconss[relaxdata->nmasterconss] = mastercons;
3871 
3872  SCIP_CALL( GCGmasterAddMasterconsToHashmap(relaxdata->masterprob, relaxdata->masterconss[relaxdata->nmasterconss],
3873  relaxdata->nmasterconss) );
3874 
3875  relaxdata->nmasterconss++;
3876 
3877  *transcons = mastercons;
3878 
3879  return SCIP_OKAY;
3880 }
3881 
3882 /** returns the original problem for the given master problem */
3884  SCIP* masterprob /**< the SCIP data structure for the master problem */
3885  )
3886 {
3887  SCIP* origprob;
3888  SCIP_BENDERS* benders;
3889  SCIP_PRICER* pricer;
3890 
3891  assert(masterprob != NULL);
3892 
3893  /* retrieving the Benders' decomposition and the pricer plugins. There should only be one or the other for a given
3894  * master problem. If there are both, then an error is returned */
3895  benders = SCIPfindBenders(masterprob, "gcg");
3896  pricer = SCIPfindPricer(masterprob, "gcg");
3897  assert((benders != NULL && pricer == NULL) || (pricer != NULL && benders == NULL));
3898 
3899  origprob = NULL;
3900  if( benders != NULL && pricer == NULL )
3901  {
3902  origprob = GCGbendersGetOrigprob(masterprob);
3903  assert(GCGgetDecompositionMode(origprob) == DEC_DECMODE_BENDERS
3905  }
3906  else if( pricer != NULL && benders == NULL )
3907  {
3908  origprob = GCGmasterGetOrigprob(masterprob);
3910  }
3911  else
3912  {
3913  SCIPerrorMessage("There must exist either a pricer or a benders or neither, not both.\n");
3914  }
3915 
3916  return origprob;
3917 }
3918 
3919 /** returns the master problem */
3921  SCIP* scip /**< SCIP data structure */
3922  )
3923 {
3924  SCIP_RELAX* relax;
3925  SCIP_RELAXDATA* relaxdata;
3926 
3927  assert(scip != NULL);
3928 
3929  relax = SCIPfindRelax(scip, RELAX_NAME);
3930  assert(relax != NULL);
3931 
3932  relaxdata = SCIPrelaxGetData(relax);
3933  assert(relaxdata != NULL);
3934 
3935  return relaxdata->masterprob;
3936 }
3937 
3938 /** returns the pricing problem of the given number */
3940  SCIP* scip, /**< SCIP data structure */
3941  int pricingprobnr /**< number of the pricing problem */
3942  )
3943 {
3944  SCIP_RELAX* relax;
3945  SCIP_RELAXDATA* relaxdata;
3946 
3947  assert(scip != NULL);
3948 
3949  relax = SCIPfindRelax(scip, RELAX_NAME);
3950  assert(relax != NULL);
3951 
3952  relaxdata = SCIPrelaxGetData(relax);
3953  assert(relaxdata != NULL);
3954 
3955  return relaxdata->pricingprobs[pricingprobnr];
3956 }
3957 
3958 /** returns the number of relevant pricing problems */
3960  SCIP* scip /**< SCIP data structure */
3961  )
3962 {
3963  SCIP_RELAX* relax;
3964  SCIP_RELAXDATA* relaxdata;
3965 
3966  assert(scip != NULL);
3967 
3968  relax = SCIPfindRelax(scip, RELAX_NAME);
3969  assert(relax != NULL);
3970 
3971  relaxdata = SCIPrelaxGetData(relax);
3972  assert(relaxdata != NULL);
3973 
3974  assert(relaxdata->nrelpricingprobs >= -1);
3975  return relaxdata->nrelpricingprobs;
3976 }
3977 
3978 /** returns the number of pricing problems */
3980  SCIP* scip /**< SCIP data structure */
3981  )
3982 {
3983  SCIP_RELAX* relax;
3984  SCIP_RELAXDATA* relaxdata;
3985 
3986  assert(scip != NULL);
3987 
3988  relax = SCIPfindRelax(scip, RELAX_NAME);
3989  assert(relax != NULL);
3990 
3991  relaxdata = SCIPrelaxGetData(relax);
3992  assert(relaxdata != NULL);
3993 
3994  assert(relaxdata->npricingprobs >= -1);
3995  return relaxdata->npricingprobs;
3996 }
3997 
3998 /** returns TRUE iff the pricing problem of the given number is relevant, that means is not identical to
3999  * another and represented by it */
4001  SCIP* scip, /**< SCIP data structure */
4002  int pricingprobnr /**< number of the pricing problem */
4003  )
4004 {
4005  SCIP_RELAX* relax;
4006  SCIP_RELAXDATA* relaxdata;
4007 
4008  assert(scip != NULL);
4009 
4010  relax = SCIPfindRelax(scip, RELAX_NAME);
4011  assert(relax != NULL);
4012 
4013  relaxdata = SCIPrelaxGetData(relax);
4014  assert(relaxdata != NULL);
4015 
4016  return (relaxdata->blockrepresentative[pricingprobnr] == pricingprobnr);
4017 
4018 }
4019 
4020 /**
4021  * for a given block, return the block by which it is represented
4022  */
4024  SCIP* scip, /**< SCIP data structure */
4025  int pricingprobnr /**< number of the pricing problem */
4026  )
4027 {
4028  SCIP_RELAX* relax;
4029  SCIP_RELAXDATA* relaxdata;
4030 
4031  if( pricingprobnr == -1 )
4032  return -1;
4033 
4034  assert(scip != NULL);
4035 
4036  relax = SCIPfindRelax(scip, RELAX_NAME);
4037  assert(relax != NULL);
4038 
4039  relaxdata = SCIPrelaxGetData(relax);
4040  assert(relaxdata != NULL);
4041 
4042  assert(pricingprobnr >= 0);
4043  assert(pricingprobnr < relaxdata->npricingprobs);
4044  assert(relaxdata->nblocksidentical[pricingprobnr] >= 0);
4045  assert((relaxdata->blockrepresentative[pricingprobnr] == pricingprobnr)
4046  == (relaxdata->nblocksidentical[pricingprobnr] > 0));
4047 
4048  return relaxdata->blockrepresentative[pricingprobnr];
4049 }
4050 
4051 /** returns the number of blocks in the original formulation, that are represented by
4052  * the pricingprob with the given number */
4054  SCIP* scip, /**< SCIP data structure */
4055  int pricingprobnr /**< number of the pricing problem */
4056  )
4057 {
4058  SCIP_RELAX* relax;
4059  SCIP_RELAXDATA* relaxdata;
4060 
4061  assert(scip != NULL);
4062 
4063  relax = SCIPfindRelax(scip, RELAX_NAME);
4064  assert(relax != NULL);
4065  assert(pricingprobnr >= 0);
4066 
4067  relaxdata = SCIPrelaxGetData(relax);
4068  assert(relaxdata != NULL);
4069  assert(pricingprobnr <= relaxdata->npricingprobs);
4070  assert(relaxdata->nblocksidentical[pricingprobnr] >= 0);
4071  assert((relaxdata->blockrepresentative[pricingprobnr] == pricingprobnr)
4072  == (relaxdata->nblocksidentical[pricingprobnr] > 0));
4073 
4074  return relaxdata->nblocksidentical[pricingprobnr];
4075 
4076 }
4077 
4078 /** returns the number of constraints in the master problem */
4080  SCIP* scip /**< SCIP data structure */
4081  )
4082 {
4083  SCIP_RELAX* relax;
4084  SCIP_RELAXDATA* relaxdata;
4085 
4086  assert(scip != NULL);
4087 
4088  relax = SCIPfindRelax(scip, RELAX_NAME);
4089  assert(relax != NULL);
4090 
4091  relaxdata = SCIPrelaxGetData(relax);
4092  assert(relaxdata != NULL);
4093 
4094  return relaxdata->nmasterconss;
4095 }
4096 
4097 /** returns the contraints in the master problem */
4098 SCIP_CONS** GCGgetMasterConss(
4099  SCIP* scip /**< SCIP data structure */
4100  )
4101 {
4102  SCIP_RELAX* relax;
4103  SCIP_RELAXDATA* relaxdata;
4104 
4105  assert(scip != NULL);
4106 
4107  relax = SCIPfindRelax(scip, RELAX_NAME);
4108  assert(relax != NULL);
4109 
4110  relaxdata = SCIPrelaxGetData(relax);
4111  assert(relaxdata != NULL);
4112 
4113  return relaxdata->masterconss;
4114 }
4115 
4116 /** returns the linking constraints in the original problem that correspond to the constraints in the master problem */
4118  SCIP* scip /**< SCIP data structure */
4119  )
4120 {
4121  SCIP_RELAX* relax;
4122  SCIP_RELAXDATA* relaxdata;
4123 
4124  assert(scip != NULL);
4125 
4126  relax = SCIPfindRelax(scip, RELAX_NAME);
4127  assert(relax != NULL);
4128 
4129  relaxdata = SCIPrelaxGetData(relax);
4130  assert(relaxdata != NULL);
4131 
4132  return relaxdata->origmasterconss;
4133 }
4134 
4135 /** returns the convexity constraint for the given block */
4136 SCIP_CONS* GCGgetConvCons(
4137  SCIP* scip, /**< SCIP data structure */
4138  int blocknr /**< the number of the block for which we
4139  * need the convexity constraint */
4140  )
4141 {
4142  SCIP_RELAX* relax;
4143  SCIP_RELAXDATA* relaxdata;
4144 
4145  assert(scip != NULL);
4146  assert(blocknr >= 0);
4147 
4148  relax = SCIPfindRelax(scip, RELAX_NAME);
4149  assert(relax != NULL);
4150 
4151  relaxdata = SCIPrelaxGetData(relax);
4152  assert(relaxdata != NULL);
4153  assert(blocknr < relaxdata->npricingprobs);
4154 
4155  return relaxdata->convconss[blocknr];
4156 }
4157 
4158 /** returns the visualization parameters */
4160  SCIP* scip /**< SCIP data structure */
4161  )
4162 {
4163  SCIP_RELAX* relax;
4164  SCIP_RELAXDATA* relaxdata;
4165  GCG_PARAMDATA* paramdata;
4166 
4167  assert(scip != NULL);
4168 
4169  relax = SCIPfindRelax(scip, RELAX_NAME);
4170  assert(relax != NULL);
4171 
4172  relaxdata = SCIPrelaxGetData(relax);
4173  assert(relaxdata != NULL);
4174  assert(relaxdata->paramsvisu != NULL);
4175 
4176  paramdata = relaxdata->paramsvisu;
4177  assert(paramdata != NULL);
4178 
4179  return paramdata;
4180 }
4181 
4182 /** returns the current solution for the original problem */
4184  SCIP* scip /**< SCIP data structure */
4185  )
4186 {
4187  SCIP_RELAX* relax;
4188  SCIP_RELAXDATA* relaxdata;
4189 
4190  assert(scip != NULL);
4191 
4192  relax = SCIPfindRelax(scip, RELAX_NAME);
4193  assert(relax != NULL);
4194 
4195  relaxdata = SCIPrelaxGetData(relax);
4196  assert(relaxdata != NULL);
4197 
4198  return relaxdata->currentorigsol;
4199 }
4200 
4201 /** returns whether the current solution is primal feasible in the original problem */
4203  SCIP* scip /**< SCIP data structure */
4204  )
4205 {
4206  SCIP_RELAX* relax;
4207  SCIP_RELAXDATA* relaxdata;
4208 
4209  assert(scip != NULL);
4210 
4211  relax = SCIPfindRelax(scip, RELAX_NAME);
4212  assert(relax != NULL);
4213 
4214  relaxdata = SCIPrelaxGetData(relax);
4215  assert(relaxdata != NULL);
4216 
4217  return relaxdata->origsolfeasible;
4218 }
4219 
4220 /** returns whether the master problem is a set covering problem */
4222  SCIP* scip /**< SCIP data structure */
4223  )
4224 {
4225  SCIP_RELAX* relax;
4226  SCIP_RELAXDATA* relaxdata;
4227 
4228  assert(scip != NULL);
4229 
4230  relax = SCIPfindRelax(scip, RELAX_NAME);
4231  assert(relax != NULL);
4232 
4233  relaxdata = SCIPrelaxGetData(relax);
4234  assert(relaxdata != NULL);
4235 
4236  return relaxdata->masterissetcover;
4237 }
4238 
4239 /** returns whether the master problem is a set partitioning problem */
4241  SCIP* scip /**< SCIP data structure */
4242  )
4243 {
4244  SCIP_RELAX* relax;
4245  SCIP_RELAXDATA* relaxdata;
4246 
4247  assert(scip != NULL);
4248 
4249  relax = SCIPfindRelax(scip, RELAX_NAME);
4250  assert(relax != NULL);
4251 
4252  relaxdata = SCIPrelaxGetData(relax);
4253  assert(relaxdata != NULL);
4254 
4255  return relaxdata->masterissetpart;
4256 }
4257 
4258 /** start probing mode on both the original and master problems
4259  *
4260  * @note This mode is intended for working on the original variables but using the master LP;
4261  * it currently only supports bound changes on the original variables,
4262  * but no additional rows
4263  */
4265  SCIP* scip, /**< SCIP data structure */
4266  SCIP_HEUR* probingheur /**< heuristic that started probing mode, or NULL */
4267  )
4268 {
4269  SCIP_RELAX* relax;
4270  SCIP_RELAXDATA* relaxdata;
4271  SCIP* masterprob;
4272 
4273  assert(scip != NULL);
4274 
4275  relax = SCIPfindRelax(scip, RELAX_NAME);
4276  assert(relax != NULL);
4277 
4278  relaxdata = SCIPrelaxGetData(relax);
4279  assert(relaxdata != NULL);
4280 
4281  if( relaxdata->masterinprobing )
4282  {
4283  SCIPerrorMessage("already in GCG probing mode\n");
4284  return SCIP_INVALIDCALL;
4285  }
4286 
4287  masterprob = relaxdata->masterprob;
4288  assert(masterprob != NULL);
4289 
4290  /* start probing in both the original and the master problem */
4291  SCIP_CALL( SCIPstartProbing(scip) );
4292  SCIP_CALL( SCIPstartProbing(masterprob) );
4293 
4294  relaxdata->masterinprobing = TRUE;
4295  relaxdata->probingheur = probingheur;
4296 
4297  /* remember the current original solution */
4298  assert(relaxdata->storedorigsol == NULL);
4299  if( relaxdata->currentorigsol != NULL )
4300  {
4301  SCIP_CALL( SCIPcreateSolCopy(scip, &relaxdata->storedorigsol, relaxdata->currentorigsol) );
4302  relaxdata->storedfeasibility = relaxdata->origsolfeasible;
4303  }
4304 
4305  return SCIP_OKAY;
4306 }
4307 
4308 /** returns the heuristic that started probing in the master problem, or NULL */
4310  SCIP* scip /**< SCIP data structure */
4311  )
4312 {
4313  SCIP_RELAX* relax;
4314  SCIP_RELAXDATA* relaxdata;
4315 
4316  assert(scip != NULL);
4317 
4318  relax = SCIPfindRelax(scip, RELAX_NAME);
4319  assert(relax != NULL);
4320 
4321  relaxdata = SCIPrelaxGetData(relax);
4322  assert(relaxdata != NULL);
4323 
4324  return relaxdata->probingheur;
4325 }
4326 
4327 /** add a new probing node the original problem together with an original branching constraint
4328  *
4329  * @note A corresponding probing node must be added to the master problem right before solving the probing LP
4330  */
4332  SCIP* scip /**< SCIP data structure */
4333  )
4334 {
4335  SCIP_RELAX* relax;
4336  SCIP_RELAXDATA* relaxdata;
4337  SCIP_CONS* probingcons;
4338  SCIP_NODE* probingnode;
4339 
4340  assert(scip != NULL);
4341 
4342  relax = SCIPfindRelax(scip, RELAX_NAME);
4343  assert(relax != NULL);
4344 
4345  relaxdata = SCIPrelaxGetData(relax);
4346  assert(relaxdata != NULL);
4347 
4348  if( !relaxdata->masterinprobing )
4349  {
4350  SCIPerrorMessage("not in GCG probing mode\n");
4351  return SCIP_INVALIDCALL;
4352  }
4353 
4354  if( SCIPgetProbingDepth(scip) != SCIPgetProbingDepth(GCGgetMasterprob(scip)) )
4355  {
4356  SCIPerrorMessage("original and master problem not at same probing depth\n");
4357  return SCIP_INVALIDCALL;
4358  }
4359 
4360  /* add a probing node in the original problem together with an original branching constraint */
4361  SCIP_CALL( SCIPnewProbingNode(scip) );
4362  probingnode = SCIPgetCurrentNode(scip);
4363  SCIP_CALL( GCGcreateConsOrigbranch(scip, &probingcons, "probingcons", probingnode,
4364  GCGconsOrigbranchGetActiveCons(scip), NULL, NULL) );
4365  SCIP_CALL( SCIPaddConsNode(scip, probingnode, probingcons, NULL) );
4366  SCIP_CALL( SCIPreleaseCons(scip, &probingcons) );
4367 
4368 
4369  return SCIP_OKAY;
4370 }
4371 
4372 /** add a new probing node the master problem together with a master branching constraint
4373  * which ensures that bound changes are transferred to master and pricing problems
4374  *
4375  * @note A corresponding probing node must have been added to the original problem beforehand;
4376  * furthermore, this method must be called after bound changes to the original problem have been made
4377  */
4379  SCIP* scip /**< SCIP data structure */
4380  )
4381 {
4382  SCIP_RELAX* relax;
4383  SCIP_RELAXDATA* relaxdata;
4384  SCIP* masterprob;
4385  SCIP_CONS* probingcons;
4386  SCIP_NODE* probingnode;
4387 
4388  assert(scip != NULL);
4389 
4390  relax = SCIPfindRelax(scip, RELAX_NAME);
4391  assert(relax != NULL);
4392 
4393  relaxdata = SCIPrelaxGetData(relax);
4394  assert(relaxdata != NULL);
4395 
4396  if( !relaxdata->masterinprobing )
4397  {
4398  SCIPerrorMessage("not in GCG probing mode\n");
4399  return SCIP_INVALIDCALL;
4400  }
4401 
4402  masterprob = relaxdata->masterprob;
4403  assert(masterprob != NULL);
4404 
4405  if( SCIPgetProbingDepth(scip) != SCIPgetProbingDepth(masterprob) + 1 )
4406  {
4407  SCIPerrorMessage("master probing node must be created after original probing node\n");
4408  return SCIP_INVALIDCALL;
4409  }
4410 
4411  /* add a probing node in the master problem together with a master branching constraint */
4412  SCIP_CALL( SCIPnewProbingNode(masterprob) );
4413  probingnode = SCIPgetCurrentNode(masterprob);
4414  assert(GCGconsMasterbranchGetActiveCons(masterprob) != NULL);
4415  SCIP_CALL( GCGcreateConsMasterbranch(masterprob, &probingcons, "mprobingcons", probingnode,
4416  GCGconsMasterbranchGetActiveCons(masterprob), NULL, NULL, NULL, 0, 0) );
4417  SCIP_CALL( SCIPaddConsNode(masterprob, probingnode, probingcons, NULL) );
4418  SCIP_CALL( SCIPreleaseCons(masterprob, &probingcons) );
4419 
4420  return SCIP_OKAY;
4421 }
4422 
4423 /** add a new probing node the master problem together with a master branching constraint
4424  * which ensures that bound changes are transferred to master and pricing problems as well as additional
4425  * constraints
4426  *
4427  * @note A corresponding probing node must have been added to the original problem beforehand;
4428  * furthermore, this method must be called after bound changes to the original problem have been made
4429  */
4431  SCIP* scip, /**< SCIP data structure */
4432  SCIP_BRANCHRULE* branchrule, /**< pointer to the branching rule */
4433  GCG_BRANCHDATA* branchdata, /**< branching data */
4434  SCIP_CONS** origbranchconss, /**< original constraints enforcing the branching decision */
4435  int norigbranchconss, /**< number of original constraints */
4436  int maxorigbranchconss /**< capacity of origbranchconss */
4437  )
4438 {
4439  SCIP_RELAX* relax;
4440  SCIP_RELAXDATA* relaxdata;
4441  SCIP* masterprob;
4442  SCIP_CONS* probingcons;
4443  SCIP_NODE* probingnode;
4444 
4445  assert(scip != NULL);
4446 
4447  relax = SCIPfindRelax(scip, RELAX_NAME);
4448  assert(relax != NULL);
4449 
4450  relaxdata = SCIPrelaxGetData(relax);
4451  assert(relaxdata != NULL);
4452 
4453  if( !relaxdata->masterinprobing )
4454  {
4455  SCIPerrorMessage("not in GCG probing mode\n");
4456  return SCIP_INVALIDCALL;
4457  }
4458 
4459  masterprob = relaxdata->masterprob;
4460  assert(masterprob != NULL);
4461 
4462  if( SCIPgetProbingDepth(scip) != SCIPgetProbingDepth(masterprob) + 1 )
4463  {
4464  SCIPerrorMessage("master probing node must be created after original probing node\n");
4465  return SCIP_INVALIDCALL;
4466  }
4467 
4468  /* add a probing node in the master problem together with a master branching constraint */
4469  SCIP_CALL( SCIPnewProbingNode(masterprob) );
4470  probingnode = SCIPgetCurrentNode(masterprob);
4471  assert(GCGconsMasterbranchGetActiveCons(masterprob) != NULL);
4472  SCIP_CALL( GCGcreateConsMasterbranch(masterprob, &probingcons, "mprobingcons", probingnode,
4473  GCGconsMasterbranchGetActiveCons(masterprob), branchrule, branchdata, origbranchconss, norigbranchconss, maxorigbranchconss) );
4474  SCIP_CALL( SCIPaddConsNode(masterprob, probingnode, probingcons, NULL) );
4475  SCIP_CALL( SCIPreleaseCons(masterprob, &probingcons) );
4476 
4477  return SCIP_OKAY;
4478 }
4479 
4480 /** add probing nodes to both the original and master problem;
4481  * furthermore, add origbranch and masterbranch constraints to transfer branching decisions
4482  * from the original to the master problem
4483  */
4485  SCIP* scip, /**< SCIP data structure */
4486  int probingdepth /**< probing depth of the node in the probing path that should be reactivated */
4487  )
4488 {
4489  SCIP_RELAX* relax;
4490  SCIP_RELAXDATA* relaxdata;
4491  SCIP* masterprob;
4492 
4493  assert(scip != NULL);
4494 
4495  relax = SCIPfindRelax(scip, RELAX_NAME);
4496  assert(relax != NULL);
4497 
4498  relaxdata = SCIPrelaxGetData(relax);
4499  assert(relaxdata != NULL);
4500 
4501  if( !relaxdata->masterinprobing )
4502  {
4503  SCIPerrorMessage("not in GCG probing mode\n");
4504  return SCIP_INVALIDCALL;
4505  }
4506 
4507  masterprob = relaxdata->masterprob;
4508  assert(masterprob != NULL);
4509 
4510  SCIP_CALL( SCIPbacktrackProbing(scip, probingdepth) );
4511  SCIP_CALL( SCIPbacktrackProbing(masterprob, probingdepth) );
4512 
4513  return SCIP_OKAY;
4514 }
4515 
4516 /** solve the master probing LP with or without pricing */
4517 static
4518 SCIP_RETCODE performProbing(
4519  SCIP* scip, /**< SCIP data structure */
4520  int maxlpiterations, /**< maximum number of lp iterations allowed */
4521  int maxpricerounds, /**< maximum number of pricing rounds allowed */
4522  SCIP_Bool usepricing, /**< should the LP be solved with or without pricing? */
4523  SCIP_Longint* nlpiterations, /**< pointer to store the number of performed LP iterations (or NULL) */
4524  int* npricerounds, /**< pointer to store the number of performed pricing rounds (or NULL) */
4525  SCIP_Real* lpobjvalue, /**< pointer to store the lp obj value if lp was solved */
4526  SCIP_Bool* lpsolved, /**< pointer to store whether the lp was solved */
4527  SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occured or the
4528  * solving process should be stopped (e.g., due to a time limit) */
4529  SCIP_Bool* cutoff /**< pointer to store whether the probing direction is infeasible */
4530  )
4531 {
4532  SCIP_RELAX* relax;
4533  SCIP_RELAXDATA* relaxdata;
4534  SCIP* masterprob;
4535  SCIP_LPSOLSTAT lpsolstat;
4536  SCIP_Longint oldnlpiters;
4537  int oldpricerounds;
4538  SCIP_Longint nodelimit;
4539 
4540  assert(scip != NULL);
4541 
4542  /* get the relaxator */
4543  relax = SCIPfindRelax(scip, RELAX_NAME);
4544  assert(relax != NULL);
4545 
4546  /* get the relaxator data */
4547  relaxdata = SCIPrelaxGetData(relax);
4548  assert(relaxdata != NULL);
4549 
4550  if( !relaxdata->masterinprobing )
4551  {
4552  SCIPerrorMessage("not in GCG probing mode\n");
4553  return SCIP_INVALIDCALL;
4554  }
4555 
4556  /* get master problem */
4557  masterprob = relaxdata->masterprob;
4558  assert(masterprob != NULL);
4559 
4560  /* increase node limit for the master problem by 1 */
4561  SCIP_CALL( SCIPgetLongintParam(masterprob, "limits/nodes", &nodelimit) );
4562  SCIP_CALL( SCIPsetLongintParam(masterprob, "limits/nodes", nodelimit + 1) );
4563 
4564  /* propagate probing bound changes to the master problem */
4565  SCIP_CALL( SCIPpropagateProbing(masterprob, -1, cutoff, NULL) );
4566  assert(!(*cutoff));
4567 
4568  /* remember LP iterations and pricing rounds before LP solving */
4569  oldnlpiters = SCIPgetNLPIterations(masterprob);
4570  oldpricerounds = SCIPgetNPriceRounds(masterprob);
4571 
4572  *lpobjvalue = 0.0;
4573  *lpsolved = FALSE;
4574 
4575  /* solve the probing LP */
4576  if( usepricing )
4577  {
4578  /* LP iterations are unlimited when probing LP is solved with pricing */
4579  assert(maxlpiterations == -1);
4580  SCIP_CALL( SCIPsolveProbingLPWithPricing(masterprob, FALSE, TRUE, maxpricerounds, lperror, NULL) );
4581  }
4582  else
4583  {
4584  assert(maxpricerounds == 0);
4585  SCIP_CALL( SCIPsolveProbingLP(masterprob, maxlpiterations, lperror, NULL) );
4586  }
4587  lpsolstat = SCIPgetLPSolstat(masterprob);
4588 
4589  /* reset the node limit */
4590  SCIP_CALL( SCIPsetLongintParam(masterprob, "limits/nodes", nodelimit) );
4591 
4592  /* calculate number of LP iterations and pricing rounds performed */
4593  if( nlpiterations != NULL )
4594  *nlpiterations = SCIPgetNLPIterations(masterprob) - oldnlpiters;
4595  if( npricerounds != NULL )
4596  *npricerounds = SCIPgetNPriceRounds(masterprob) - oldpricerounds;
4597 
4598  if( !(*lperror) )
4599  {
4600  /* get LP solution status, objective value */
4601  *cutoff = *cutoff || (lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT || lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE);
4602  if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
4603  {
4604  SCIPdebugMessage("lpobjval = %g\n", SCIPgetLPObjval(masterprob));
4605  *lpobjvalue = SCIPgetLPObjval(masterprob);
4606  *lpsolved = TRUE;
4607  SCIP_CALL( GCGrelaxUpdateCurrentSol(scip) );
4608  }
4609  }
4610  else
4611  {
4612  SCIPdebugMessage("something went wrong, an lp error occurred\n");
4613  }
4614 
4615  return SCIP_OKAY;
4616 }
4617 
4618 
4619 /** solve the master probing LP without pricing */
4621  SCIP* scip, /**< SCIP data structure */
4622  int maxlpiterations, /**< maximum number of lp iterations allowed */
4623  SCIP_Longint* nlpiterations, /**< pointer to store the number of performed LP iterations (or NULL) */
4624  SCIP_Real* lpobjvalue, /**< pointer to store the lp obj value if lp was solved */
4625  SCIP_Bool* lpsolved, /**< pointer to store whether the lp was solved */
4626  SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occured or the
4627  * solving process should be stopped (e.g., due to a time limit) */
4628  SCIP_Bool* cutoff /**< pointer to store whether the probing direction is infeasible */
4629  )
4630 {
4631  SCIP_CALL( performProbing(scip, maxlpiterations, 0, FALSE, nlpiterations,
4632  NULL, lpobjvalue, lpsolved, lperror, cutoff) );
4633 
4634  return SCIP_OKAY;
4635 }
4636 
4637 
4638 /** solve the master probing LP with pricing */
4640  SCIP* scip, /**< SCIP data structure */
4641  int maxpricerounds, /**< maximum number of pricing rounds allowed */
4642  SCIP_Longint* nlpiterations, /**< pointer to store the number of performed LP iterations (or NULL) */
4643  int* npricerounds, /**< pointer to store the number of performed pricing rounds (or NULL) */
4644  SCIP_Real* lpobjvalue, /**< pointer to store the lp obj value if lp was solved */
4645  SCIP_Bool* lpsolved, /**< pointer to store whether the lp was solved */
4646  SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occured or the
4647  * solving process should be stopped (e.g., due to a time limit) */
4648  SCIP_Bool* cutoff /**< pointer to store whether the probing direction is infeasible */
4649  )
4650 {
4651  SCIP_CALL( performProbing(scip, -1, maxpricerounds, TRUE, nlpiterations,
4652  npricerounds, lpobjvalue, lpsolved, lperror, cutoff) );
4653 
4654  return SCIP_OKAY;
4655 }
4656 
4657 /** end probing mode in both the original and master problems */
4658 SCIP_RETCODE GCGrelaxEndProbing(
4659  SCIP* scip /**< SCIP data structure */
4660  )
4661 {
4662  SCIP_RELAX* relax;
4663  SCIP_RELAXDATA* relaxdata;
4664  SCIP* masterprob;
4665 
4666  SCIP_VAR** vars;
4667  int nvars;
4668 
4669  assert(scip != NULL);
4670 
4671  relax = SCIPfindRelax(scip, RELAX_NAME);
4672  assert(relax != NULL);
4673 
4674  relaxdata = SCIPrelaxGetData(relax);
4675  assert(relaxdata != NULL);
4676 
4677  if( !relaxdata->masterinprobing )
4678  {
4679  SCIPerrorMessage("not in GCG probing mode\n");
4680  return SCIP_INVALIDCALL;
4681  }
4682 
4683  masterprob = relaxdata->masterprob;
4684  assert(masterprob != NULL);
4685 
4686  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
4687  assert(vars != NULL);
4688  assert(nvars >= 0);
4689 
4690  SCIP_CALL( SCIPendProbing(masterprob) );
4691  SCIP_CALL( SCIPendProbing(scip) );
4692 
4693  relaxdata->masterinprobing = FALSE;
4694  relaxdata->probingheur = NULL;
4695 
4696  /* if a new primal solution was found in the master problem, transfer it to the original problem
4697  * @todo: this is probably not necessary anymore since it is done by an event handler
4698  */
4699  if( SCIPgetBestSol(masterprob) != NULL && relaxdata->lastmastersol != SCIPgetBestSol(masterprob) )
4700  {
4701  SCIP_SOL* newsol;
4702  SCIP_Bool stored;
4703 
4704  relaxdata->lastmastersol = SCIPgetBestSol(masterprob);
4705 
4706  SCIP_CALL( GCGtransformMastersolToOrigsol(scip, relaxdata->lastmastersol, &newsol) );
4707 
4708  SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
4709  if( !stored )
4710  {
4711  SCIP_CALL( SCIPcheckSolOrig(scip, newsol, &stored, TRUE, TRUE) );
4712  }
4713  assert(stored);
4714  SCIP_CALL( SCIPfreeSol(scip, &newsol) );
4715 
4716  SCIPdebugMessage("probing finished in master problem\n");
4717  }
4718 
4719  /* restore old relaxation solution and branching candidates */
4720  if( relaxdata->currentorigsol != NULL )
4721  {
4722  SCIPdebugMessage("Freeing previous solution origsol\n");
4723  SCIP_CALL( SCIPfreeSol(scip, &(relaxdata->currentorigsol)) );
4724  }
4725  SCIPclearExternBranchCands(scip);
4726 
4727  if( relaxdata->storedorigsol != NULL )
4728  {
4729  int i;
4730 
4731  SCIP_CALL( SCIPcreateSol(scip, &relaxdata->currentorigsol, NULL) );
4732  SCIP_CALL( SCIPsetRelaxSolValsSol(scip, relax, relaxdata->storedorigsol, RELAX_INCLUDESLP) );
4733 
4734  for( i = 0; i < nvars; i++ )
4735  {
4736  SCIP_VAR* var;
4737  SCIP_Real solval;
4738 
4739  var = vars[i];
4740  solval = SCIPgetSolVal(scip, relaxdata->storedorigsol, var);
4741 
4742  SCIP_CALL( SCIPsetSolVal(scip, relaxdata->currentorigsol, var, solval) );
4743 
4744  if( SCIPvarGetType(var) <= SCIP_VARTYPE_INTEGER && !SCIPisFeasIntegral(scip, solval) )
4745  {
4746  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
4747  SCIP_CALL( SCIPaddExternBranchCand(scip, var, solval - SCIPfloor(scip, solval), solval) );
4748  }
4749  }
4750  assert(SCIPisFeasEQ(scip, SCIPgetRelaxSolObj(scip), SCIPgetSolTransObj(scip, relaxdata->currentorigsol)));
4751 
4752  SCIP_CALL( SCIPfreeSol(scip, &relaxdata->storedorigsol) );
4753 
4754  relaxdata->origsolfeasible = relaxdata->storedfeasibility;
4755  }
4756 
4757  /** @todo solve master problem again */
4758 
4759  return SCIP_OKAY;
4760 }
4761 
4762 
4763 /** checks whether a variable shoudl be added as an external branching candidate, if so it is added */
4764 static
4766  SCIP* scip, /**< the SCIP data structure */
4767  SCIP_VAR* var /**< the variable to check whether to add as a branching candidate */
4768  )
4769 {
4770  assert(scip != NULL);
4771  assert(var != NULL);
4772 
4773  if( SCIPvarGetType(var) <= SCIP_VARTYPE_INTEGER && !SCIPisFeasIntegral(scip, SCIPgetRelaxSolVal(scip, var)) )
4774  {
4775  if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) )
4776  {
4777  SCIPdebugMessage("lblocal = %g, ublocal = %g\n", SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var));
4778  SCIPdebugMessage("var = %s, vartype = %d, val = %g\n", SCIPvarGetName(var), SCIPvarGetType(var),
4779  SCIPgetRelaxSolVal(scip, var));
4780  }
4781 
4782  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)));
4783 
4784  SCIP_CALL( SCIPaddExternBranchCand(scip, var, SCIPgetRelaxSolVal(scip, var) -
4785  SCIPfloor(scip, SCIPgetRelaxSolVal(scip, var)), SCIPgetRelaxSolVal(scip, var)) );
4786  }
4787 
4788  return SCIP_OKAY;
4789 }
4790 
4791 
4792 
4793 /** transforms the current solution of the master problem into the original problem's space
4794  * and saves this solution as currentsol in the relaxator's data
4795  */
4797  SCIP* scip /**< SCIP data structure */
4798  )
4799 {
4800  SCIP_RELAX* relax;
4801  SCIP_RELAXDATA* relaxdata;
4802  SCIP_VAR** origvars;
4803  int norigvars;
4804  SCIP_Bool stored;
4805 
4806  assert(scip != NULL);
4807 
4808  relax = SCIPfindRelax(scip, RELAX_NAME);
4809  assert(relax != NULL);
4810 
4811  relaxdata = SCIPrelaxGetData(relax);
4812  assert(relaxdata != NULL);
4813 
4814  origvars = SCIPgetVars(scip);
4815  norigvars = SCIPgetNVars(scip);
4816  assert(origvars != NULL);
4817 
4818  relaxdata->origsolfeasible = FALSE;
4819 
4820  /* if the master problem has not been solved, don't try to update the solution */
4821  if( SCIPgetStage(relaxdata->masterprob) == SCIP_STAGE_TRANSFORMED )
4822  return SCIP_OKAY;
4823 
4824  /* free previous solution and clear branching candidates */
4825  if( relaxdata->currentorigsol != NULL )
4826  {
4827  SCIPdebugMessage("Freeing previous solution origsol\n");
4828  SCIP_CALL( SCIPfreeSol(scip, &(relaxdata->currentorigsol)) );
4829  }
4830  SCIPclearExternBranchCands(scip);
4831 
4832  if( SCIPgetStage(relaxdata->masterprob) == SCIP_STAGE_SOLVED || SCIPgetLPSolstat(relaxdata->masterprob) == SCIP_LPSOLSTAT_OPTIMAL )
4833  {
4834  SCIP_SOL* mastersol;
4835 
4836  relaxdata->lastmasterlpiters = SCIPgetNLPIterations(relaxdata->masterprob);
4837 
4838  /* create new solution */
4839  if( SCIPgetStage(relaxdata->masterprob) == SCIP_STAGE_SOLVING )
4840  {
4841  SCIPdebugMessage("Masterproblem still solving, mastersol = NULL\n");
4842  mastersol = NULL;
4843  }
4844  else if( SCIPgetStage(relaxdata->masterprob) == SCIP_STAGE_SOLVED )
4845  {
4846  mastersol = SCIPgetBestSol(relaxdata->masterprob);
4847  if( mastersol == NULL )
4848  {
4849  SCIPdebugMessage("Masterproblem solved, no master sol present\n");
4850  return SCIP_OKAY;
4851  }
4852  SCIPdebugMessage("Masterproblem solved, mastersol = %p\n", (void*) mastersol);
4853  }
4854  else
4855  {
4856  SCIPdebugMessage("stage in master not solving and not solved!\n");
4857  return SCIP_OKAY;
4858  }
4859 
4860  if( !SCIPisInfinity(scip, SCIPgetSolOrigObj(relaxdata->masterprob, mastersol)) && GCGmasterIsSolValid(relaxdata->masterprob, mastersol) )
4861  {
4862  int i;
4863  int j;
4864 
4865  /* transform the master solution to the original variable space */
4866  SCIP_CALL( GCGtransformMastersolToOrigsol(scip, mastersol, &(relaxdata->currentorigsol)) );
4867 
4868  /* store the solution as relaxation solution */
4869  SCIP_CALL( SCIPsetRelaxSolValsSol(scip, relax, relaxdata->currentorigsol, RELAX_INCLUDESLP) );
4870  assert(SCIPisEQ(scip, SCIPgetRelaxSolObj(scip), SCIPgetSolTransObj(scip, relaxdata->currentorigsol)));
4871 
4873  SCIP_CALL( SCIPtrySol(scip, relaxdata->currentorigsol, FALSE, FALSE, TRUE, TRUE, TRUE, &stored) );
4874  else
4875  SCIP_CALL( SCIPcheckSolOrig(scip, relaxdata->currentorigsol, &stored, FALSE, TRUE) );
4876 
4877  SCIPdebugMessage("updated current original LP solution, %s feasible in the original problem!\n",
4878  (stored ? "" : "not"));
4879 
4880  if( stored )
4881  relaxdata->origsolfeasible = TRUE;
4882 
4883  /* in the case of Benders decomposition, only the master variables can be added as branching candidates */
4885  {
4886  SCIP* masterprob;
4887  SCIP_VAR** mastervars;
4888  SCIP_VAR** masterorigvars;
4889  int nmastervars;
4890  int nmasterorigvars;
4891 
4892  /* retrieving the master problem */
4893  masterprob = GCGgetMasterprob(scip);
4894 
4895  /* get variables of the master problem and their solution values */
4896  SCIP_CALL( SCIPgetVarsData(masterprob, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
4897 
4898  /* looping over all master variables to get the original variable for branching candidates */
4899  for( i = 0; i < nmastervars; i++ )
4900  {
4901  masterorigvars = GCGmasterVarGetOrigvars(mastervars[i]);
4902  nmasterorigvars = GCGmasterVarGetNOrigvars(mastervars[i]);
4903 
4904  for( j = 0; j < nmasterorigvars; j++ )
4905  SCIP_CALL( checkAndAddExternalBranchingCandidate(scip, masterorigvars[j]) );
4906  }
4907  }
4908  else
4909  {
4911  /* store branching candidates */
4912  for( i = 0; i < norigvars; i++ )
4913  SCIP_CALL( checkAndAddExternalBranchingCandidate(scip, origvars[i]) );
4914  }
4915 
4916  SCIPdebugMessage("updated relaxation branching candidates\n");
4917  }
4918  }
4919 
4920  return SCIP_OKAY;
4921 }
4922 
4923 
4924 /** gets the total memory used after problem creation stage for all pricingproblems */
4926  SCIP* scip /**< SCIP data structure */
4927  )
4928 {
4929  SCIP_RELAX* relax;
4930  SCIP_RELAXDATA* relaxdata;
4931 
4932  int p;
4933  SCIP_Real memused;
4934 
4935  assert(scip != NULL);
4936 
4937  relax = SCIPfindRelax(scip, RELAX_NAME);
4938  assert(relax != NULL);
4939 
4940  relaxdata = SCIPrelaxGetData(relax);
4941  assert(relaxdata != NULL);
4942 
4943  memused = 0.0;
4944 
4945  /* @todo replace the computation by relaxdata->pricingprobsmemused if we can assure that the memory
4946  * used by the pricing problems is constant */
4947 
4948  /* compute memory that is used by all pricing problems */
4949  for( p = 0; p < relaxdata->npricingprobs; ++p )
4950  {
4951  memused += SCIPgetMemUsed(relaxdata->pricingprobs[p])/1048576.0;
4952  }
4953 
4954  return memused;
4955 }
4956 
4957 /** returns whether the relaxator has been initialized */
4959  SCIP* scip /**< SCIP data structure */
4960  )
4961 {
4962 
4963  SCIP_RELAX* relax;
4964  SCIP_RELAXDATA* relaxdata;
4965 
4966  assert(scip != NULL);
4967 
4968  relax = SCIPfindRelax(scip, RELAX_NAME);
4969  assert(relax != NULL);
4970 
4971  relaxdata = SCIPrelaxGetData(relax);
4972  assert(relaxdata != NULL);
4973 
4974  return relaxdata->relaxisinitialized;
4975 }
4976 
4977 /** returns the average degeneracy */
4979  SCIP* scip /**< SCIP data structure */
4980  )
4981 {
4982 
4983  SCIP_Real degeneracy;
4984  SCIP_RELAX* relax;
4985  SCIP_RELAXDATA* relaxdata;
4986 
4987  assert(scip != NULL);
4988 
4989  relax = SCIPfindRelax(scip, RELAX_NAME);
4990  assert(relax != NULL);
4991 
4992  relaxdata = SCIPrelaxGetData(relax);
4993  assert(relaxdata != NULL);
4994  degeneracy = 0.0;
4995  if( relaxdata->masterprob != NULL )
4996  {
4997  degeneracy = GCGmasterGetDegeneracy(relaxdata->masterprob);
4998  if( SCIPisInfinity(relaxdata->masterprob, degeneracy) )
4999  degeneracy = SCIPinfinity(scip);
5000  }
5001  return degeneracy;
5002 }
5003 
5004 /** return linking constraints for variables */
5006  SCIP* scip /**< SCIP data structure */
5007  )
5008 {
5009  SCIP_RELAX* relax;
5010  SCIP_RELAXDATA* relaxdata;
5011 
5012  assert(scip != NULL);
5013 
5014  relax = SCIPfindRelax(scip, RELAX_NAME);
5015  assert(relax != NULL);
5016 
5017  relaxdata = SCIPrelaxGetData(relax);
5018  assert(relaxdata != NULL);
5019 
5020  return relaxdata->varlinkconss;
5021 }
5022 
5023 /** return blocks of linking constraints for variables */
5025  SCIP* scip /**< SCIP data structure */
5026  )
5027 {
5028  SCIP_RELAX* relax;
5029  SCIP_RELAXDATA* relaxdata;
5030 
5031  assert(scip != NULL);
5032 
5033  relax = SCIPfindRelax(scip, RELAX_NAME);
5034  assert(relax != NULL);
5035 
5036  relaxdata = SCIPrelaxGetData(relax);
5037  assert(relaxdata != NULL);
5038 
5039  return relaxdata->varlinkconsblock;
5040 }
5041 
5042 /** return number of linking constraints for variables */
5044  SCIP* scip /**< SCIP data structure */
5045  )
5046 {
5047  SCIP_RELAX* relax;
5048  SCIP_RELAXDATA* relaxdata;
5049 
5050  assert(scip != NULL);
5051 
5052  relax = SCIPfindRelax(scip, RELAX_NAME);
5053  assert(relax != NULL);
5054 
5055  relaxdata = SCIPrelaxGetData(relax);
5056  assert(relaxdata != NULL);
5057 
5058  return relaxdata->nvarlinkconss;
5059 }
5060 
5061 /** return number of linking variables */
5063  SCIP* scip /**< SCIP data structure */
5064  )
5065 {
5066  SCIP_RELAX* relax;
5067  SCIP_RELAXDATA* relaxdata;
5068 
5069  assert(scip != NULL);
5070 
5071  relax = SCIPfindRelax(scip, RELAX_NAME);
5072  assert(relax != NULL);
5073 
5074  relaxdata = SCIPrelaxGetData(relax);
5075  assert(relaxdata != NULL);
5076 
5077  return relaxdata->nlinkingvars;
5078 }
5079 
5080 /** return number of variables directly transferred to the master problem */
5082  SCIP* scip /**< SCIP data structure */
5083  )
5084 {
5085  SCIP_RELAX* relax;
5086  SCIP_RELAXDATA* relaxdata;
5087 
5088  assert(scip != NULL);
5089 
5090  relax = SCIPfindRelax(scip, RELAX_NAME);
5091  assert(relax != NULL);
5092 
5093  relaxdata = SCIPrelaxGetData(relax);
5094  assert(relaxdata != NULL);
5095 
5096  return relaxdata->ntransvars;
5097 }
5098 
5099 /** returns the relaxation solution from the Benders' decomposition */
5101  SCIP* scip /**< SCIP data structure */
5102  )
5103 {
5104  SCIP_RELAX* relax;
5105  SCIP_RELAXDATA* relaxdata;
5106  SCIP_BENDERS* benders;
5107 
5108  assert(scip != NULL);
5109 
5110  relax = SCIPfindRelax(scip, RELAX_NAME);
5111  assert(relax != NULL);
5112 
5113  relaxdata = SCIPrelaxGetData(relax);
5114  assert(relaxdata != NULL);
5115 
5116  benders = SCIPfindBenders(relaxdata->masterprob, "gcg");
5117  assert(benders != NULL);
5118 
5119  return SCIPbendersGetRelaxSol(benders);
5120 }
5121 
5122 /** returns the decomposition mode */
5124  SCIP* scip /**< SCIP data structure */
5125  )
5126 {
5127  SCIP_RELAX* relax;
5128  SCIP_RELAXDATA* relaxdata;
5129 
5130  assert(scip != NULL);
5131 
5132  relax = SCIPfindRelax(scip, RELAX_NAME);
5133  assert(relax != NULL);
5134 
5135  relaxdata = SCIPrelaxGetData(relax);
5136  assert(relaxdata != NULL);
5137 
5138  return (DEC_DECMODE)relaxdata->mode;
5139 }
5140 
5141 /** returns the decomposition mode of the master problem. The mode is given by the existence of either the GCG pricer or
5142  * the GCG Benders' decomposition plugins.
5143  */
5145  SCIP* masterprob /**< the master problem SCIP instance */
5146  )
5147 {
5148  SCIP_BENDERS* benders;
5149  SCIP_PRICER* pricer;
5150  DEC_DECMODE mode;
5151 
5152  assert(masterprob != NULL);
5153 
5154  /* retrieving the Benders' decomposition and the pricer plugins. There should only be one or the other for a given
5155  * master problem. If there are both, then an error is returned */
5156  benders = SCIPfindBenders(masterprob, "gcg");
5157  pricer = SCIPfindPricer(masterprob, "gcg");
5158  assert((benders != NULL && pricer == NULL) || (pricer != NULL && benders == NULL));
5159 
5160  if( benders != NULL )
5161  {
5162  /* both the Benders' master and the original master have the Benders' decomposition included. */
5163  if( SCIPgetNActiveBenders(masterprob) > 0 )
5164  mode = DEC_DECMODE_BENDERS;
5165  else
5166  mode = DEC_DECMODE_ORIGINAL;
5167  }
5168  else if( pricer != NULL )
5169  mode = DEC_DECMODE_DANTZIGWOLFE;
5170  else
5171  {
5172  mode = DEC_DECMODE_UNKNOWN;
5173  SCIPerrorMessage("Sorry, the decomposition mode of the master problem is invalid. This should not happen.");
5174  SCIPABORT();
5175  }
5176 
5177  return mode;
5178 }
5179 
5180 /** return root node time clock */
5182  SCIP* scip /**< SCIP data structure */
5183  )
5184 {
5185  SCIP_RELAX* relax;
5186  SCIP_RELAXDATA* relaxdata;
5187 
5188  assert(scip != NULL);
5189 
5190  relax = SCIPfindRelax(scip, RELAX_NAME);
5191  assert(relax != NULL);
5192 
5193  relaxdata = SCIPrelaxGetData(relax);
5194  assert(relaxdata != NULL);
5195 
5196  return relaxdata->rootnodetime;
5197 }
5198 
5199 SCIP_RETCODE GCGtransformProb(
5200  SCIP* scip /**< SCIP data structure */
5201  )
5202 {
5203  switch( SCIPgetStage(scip) )
5204  {
5205  case SCIP_STAGE_INIT:
5206  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "no problem exists\n");
5207  break;
5208 
5209  case SCIP_STAGE_PROBLEM:
5210  SCIP_CALL( SCIPconshdlrDecompRepairConsNames(scip) );
5211  SCIP_CALL( SCIPtransformProb(scip) );
5212  break;
5213 
5214  case SCIP_STAGE_TRANSFORMED:
5215  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "problem is already transformed\n");
5216  break;
5217 
5218  case SCIP_STAGE_TRANSFORMING:
5219  case SCIP_STAGE_INITPRESOLVE:
5220  case SCIP_STAGE_PRESOLVING:
5221  case SCIP_STAGE_PRESOLVED:
5222  case SCIP_STAGE_EXITPRESOLVE:
5223  case SCIP_STAGE_INITSOLVE:
5224  case SCIP_STAGE_SOLVING:
5225  case SCIP_STAGE_SOLVED:
5226  case SCIP_STAGE_EXITSOLVE:
5227  case SCIP_STAGE_FREETRANS:
5228  case SCIP_STAGE_FREE:
5229  default:
5230  SCIPerrorMessage("invalid SCIP stage\n");
5231  return SCIP_INVALIDCALL;
5232  }
5233 
5234  return SCIP_OKAY;
5235 }
5236 
5237 SCIP_RETCODE GCGpresolve(
5238  SCIP* scip /**< SCIP data structure */
5239  )
5240 {
5241  switch( SCIPgetStage(scip) )
5242  {
5243  case SCIP_STAGE_INIT:
5244  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "no problem exists\n");
5245  break;
5246 
5247  case SCIP_STAGE_PROBLEM:
5248  SCIP_CALL( GCGtransformProb(scip) );
5249  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMED);
5250 
5251  /*lint -fallthrough*/
5252 
5253  case SCIP_STAGE_TRANSFORMED:
5254  case SCIP_STAGE_PRESOLVING:
5255  SCIP_CALL( SCIPpresolve(scip) );
5256  SCIP_CALL( GCGconshdlrDecompTranslateOrigPartialdecs(scip) );
5257  break;
5258 
5259  case SCIP_STAGE_PRESOLVED:
5260  case SCIP_STAGE_SOLVING:
5261  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "problem is already presolved\n");
5262  break;
5263 
5264  case SCIP_STAGE_SOLVED:
5265  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "problem is already solved\n");
5266  break;
5267 
5268  case SCIP_STAGE_TRANSFORMING:
5269  case SCIP_STAGE_INITPRESOLVE:
5270  case SCIP_STAGE_EXITPRESOLVE:
5271  case SCIP_STAGE_INITSOLVE:
5272  case SCIP_STAGE_EXITSOLVE:
5273  case SCIP_STAGE_FREETRANS:
5274  case SCIP_STAGE_FREE:
5275  default:
5276  SCIPerrorMessage("invalid SCIP stage\n");
5277  return SCIP_INVALIDCALL;
5278  }
5279 
5280  return SCIP_OKAY;
5281 }
5282 
5283 SCIP_RETCODE GCGdetect(
5284  SCIP* scip /**< SCIP data structure */
5285  )
5286 {
5287  SCIP_RESULT result;
5288 
5289  switch( SCIPgetStage(scip) )
5290  {
5291  case SCIP_STAGE_INIT:
5292  SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "no problem exists\n");
5293  break;
5294 
5295  case SCIP_STAGE_PROBLEM:
5296  SCIP_CALL( GCGtransformProb(scip) );
5297  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMED);
5298 
5299  /*lint -fallthrough*/
5300 
5301  case SCIP_STAGE_TRANSFORMED:
5302  if( GCGdetectionTookPlace(scip, TRUE) )
5303  {
5304  SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "The detection for the original problem took place already.\n");
5305  }
5306  else
5307  {
5308  SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "starting detection\n");
5309  SCIP_CALL( DECdetectStructure(scip, &result) );
5310  }
5311  break;
5312  case SCIP_STAGE_PRESOLVING:
5313  case SCIP_STAGE_PRESOLVED:
5314  if( GCGdetectionTookPlace(scip, FALSE) )
5315  {
5316  SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "The detection for the presolved problem took place already.\n");
5317  }
5318  else
5319  {
5320  SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "starting detection\n");
5321  SCIP_CALL( DECdetectStructure(scip, &result) );
5322  }
5323  break;
5324  case SCIP_STAGE_SOLVING:
5325  case SCIP_STAGE_SOLVED:
5326  case SCIP_STAGE_TRANSFORMING:
5327  case SCIP_STAGE_INITPRESOLVE:
5328  case SCIP_STAGE_EXITPRESOLVE:
5329  case SCIP_STAGE_INITSOLVE:
5330  case SCIP_STAGE_EXITSOLVE:
5331  case SCIP_STAGE_FREETRANS:
5332  case SCIP_STAGE_FREE:
5333  default:
5334  SCIPerrorMessage("invalid SCIP stage\n");
5335  return SCIP_INVALIDCALL;
5336  }
5337 
5338  return SCIP_OKAY;
5339 }
5340 
5341 SCIP_RETCODE GCGsolve(
5342  SCIP* scip /**< SCIP data structure */
5343  )
5344 {
5345  SCIP_RESULT result;
5346  int presolrounds;
5347  SCIP_Bool exit = FALSE;
5348 
5349  presolrounds = -1;
5350 
5351  assert(GCGconshdlrDecompCheckConsistency(scip) );
5352 
5353  while( !exit )
5354  {
5355  switch( SCIPgetStage(scip) )
5356  {
5357  case SCIP_STAGE_INIT:
5358  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "No problem exists\n");
5359  exit = TRUE;
5360  break;
5361 
5362  case SCIP_STAGE_PROBLEM:
5363  SCIP_CALL( GCGtransformProb(scip) );
5364  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMED);
5365 
5366  /*lint -fallthrough*/
5367 
5368  case SCIP_STAGE_TRANSFORMED:
5369  case SCIP_STAGE_PRESOLVING:
5371  {
5372  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "there is an original decomposition and problem is not presolved yet -> disable presolving and start optimizing (rerun with presolve command before detect command for detecting in presolved problem) \n");
5373  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &presolrounds) );
5374  SCIP_CALL( SCIPsetIntParam(scip, "presolving/maxrounds", 0) );
5375  }
5376  SCIP_CALL( GCGpresolve(scip) );
5377  assert(SCIPgetStage(scip) > SCIP_STAGE_PRESOLVING);
5378 
5379  break;
5380 
5381  case SCIP_STAGE_PRESOLVED:
5382  assert(GCGconshdlrDecompCheckConsistency(scip) );
5383 
5385  {
5386  SCIP_CALL( DECdetectStructure(scip, &result) );
5387  if( result == SCIP_DIDNOTFIND )
5388  {
5389  DEC_DECOMP* bestdecomp;
5390  bestdecomp = DECgetBestDecomp(scip, TRUE);
5391  assert(bestdecomp == NULL && (GCGdetectionTookPlace(scip, TRUE) || GCGdetectionTookPlace(scip, FALSE)));
5392  DECdecompFree(scip, &bestdecomp);
5393  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "No decomposition exists or could be detected. Solution process started with original problem...\n");
5394  }
5395  }
5396  else if( !GCGdetectionTookPlace(scip, TRUE) && !GCGdetectionTookPlace(scip, FALSE) && GCGconshdlrDecompGetNFinishedPartialdecsTransformed(scip) > 0 )
5397  {
5398  #ifndef NDEBUG
5399  DEC_DECOMP* bestdecomp;
5400  bestdecomp = DECgetBestDecomp(scip, TRUE);
5401  assert(bestdecomp != NULL);
5402  DECdecompFree(scip, &bestdecomp);
5403  #endif
5404  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "Preexisting decomposition found. Solution process started...\n");
5405  }
5407  {
5408  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "No decomposition exists or could be detected. Solution process started with original problem...\n");
5409  }
5410  assert(GCGconshdlrDecompCheckConsistency(scip));
5411  assert(SCIPgetNConss(scip) == SCIPgetNActiveConss(scip));
5412 
5413  /*lint -fallthrough*/
5414  case SCIP_STAGE_SOLVING:
5415  SCIP_CALL( SCIPsolve(scip) );
5416  exit = TRUE;
5417  break;
5418 
5419  case SCIP_STAGE_SOLVED:
5420  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "Problem is already solved\n");
5421  exit = TRUE;
5422  break;
5423 
5424  case SCIP_STAGE_TRANSFORMING:
5425  case SCIP_STAGE_INITPRESOLVE:
5426  case SCIP_STAGE_EXITPRESOLVE:
5427  case SCIP_STAGE_INITSOLVE:
5428  case SCIP_STAGE_EXITSOLVE:
5429  case SCIP_STAGE_FREETRANS:
5430  case SCIP_STAGE_FREE:
5431  default:
5432  SCIPerrorMessage("invalid SCIP stage <%d>\n", SCIPgetStage(scip));
5433  return SCIP_INVALIDCALL;
5434  }
5435  }
5436 
5437  if( presolrounds != -1 )
5438  {
5439  SCIP_CALL( SCIPsetIntParam(scip, "presolving/maxrounds", presolrounds) );
5440  }
5441 
5442  return SCIP_OKAY;
5443 }
5444 
5446  SCIP* scip /**< SCIP data structure */
5447  )
5448 {
5449  SCIP* masterprob;
5450  SCIP_Real dualbound;
5451 
5452  assert(scip != NULL);
5453 
5454  /* get master problem */
5455  masterprob = GCGgetMasterprob(scip);
5456  assert(masterprob != NULL);
5457 
5458  dualbound = SCIPgetDualbound(scip);
5459 
5460  /* @todo find a better way to do this */
5461  if( SCIPgetStage(masterprob) >= SCIP_STAGE_SOLVING )
5462  {
5463  SCIP_Real masterdualbound;
5464 
5465  masterdualbound = SCIPgetDualbound(masterprob);
5466  masterdualbound = SCIPretransformObj(scip, masterdualbound);
5467  dualbound = MAX(dualbound, masterdualbound);
5468  }
5469 
5470  return dualbound;
5471 }
5472 
5474  SCIP* scip /**< SCIP data structure */
5475  )
5476 {
5477  SCIP* masterprob;
5478  SCIP_Real primalbound;
5479 
5480  assert(scip != NULL);
5481 
5482  /* get master problem */
5483  masterprob = GCGgetMasterprob(scip);
5484  assert(masterprob != NULL);
5485 
5486  primalbound = SCIPgetPrimalbound(scip);
5487 
5488  /* @todo find a better way to do this */
5489  if( SCIPgetStage(masterprob) >= SCIP_STAGE_SOLVING && GCGmasterIsBestsolValid(masterprob) )
5490  {
5491  SCIP_Real masterprimalbound;
5492  masterprimalbound = SCIPgetPrimalbound(masterprob);
5493  masterprimalbound = SCIPretransformObj(scip, masterprimalbound);
5494 
5495  primalbound = MIN(primalbound, masterprimalbound);
5496  }
5497 
5498  return primalbound;
5499 }
5500 
5501 SCIP_Real GCGgetGap(
5502  SCIP* scip /**< SCIP data structure */
5503  )
5504 {
5505  SCIP_Real dualbound;
5506  SCIP_Real primalbound;
5507  SCIP_Real gap;
5508 
5509  assert(scip != NULL);
5510 
5511  primalbound = GCGgetPrimalbound(scip);
5512  dualbound = GCGgetDualbound(scip);
5513 
5514  /* this is the gap calculation from SCIPgetGap() */
5515  if( SCIPisEQ(scip, primalbound, dualbound) )
5516  gap = 0.0;
5517  else if( SCIPisZero(scip, dualbound )
5518  || SCIPisZero(scip, primalbound)
5519  || SCIPisInfinity(scip, REALABS(primalbound))
5520  || SCIPisInfinity(scip, REALABS(dualbound))
5521  || primalbound * dualbound < 0.0 )
5522  gap = SCIPinfinity(scip);
5523  else
5524  {
5525  SCIP_Real absdual = REALABS(dualbound);
5526  SCIP_Real absprimal = REALABS(primalbound);
5527 
5528  gap = REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
5529  }
5530 
5531  return gap;
5532 }
int GCGgetNTransvars(SCIP *scip)
Definition: relax_gcg.c:5081
int * varlinkconsblock
Definition: relax_gcg.c:126
SCIP_Bool GCGconshdlrDecompOrigPartialdecExists(SCIP *scip)
returns whether or not an original decompositions exists in the data structures
#define DEFAULT_DISCRETIZATION
Definition: relax_gcg.c:83
@ DEC_DECMODE_BENDERS
Definition: type_decomp.h:62
SCIP_Real pricingprobsmemused
Definition: relax_gcg.c:114
SCIP_Real GCGconsGetRhs(SCIP *scip, SCIP_CONS *cons)
Definition: scip_misc.c:108
int GCGmasterVarGetNOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:886
SCIP_RETCODE GCGoriginalVarAddBlock(SCIP *scip, SCIP_VAR *var, int newblock, int nblocks, DEC_DECMODE mode)
Definition: gcgvar.c:726
SCIP * GCGgetMasterprob(SCIP *scip)
Definition: relax_gcg.c:3920
DEC_DECTYPE DECdecompGetType(DEC_DECOMP *decomp)
Definition: decomp.c:691
GCG interface methods.
static SCIP_RETCODE freeBlockProblem(SCIP *scip, SCIP *blockprob, SCIP_RELAXDATA *relaxdata, int blocknum)
Definition: relax_gcg.c:2266
SCIP_RETCODE GCGrelaxNewProbingnodeMasterCons(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata, SCIP_CONS **origbranchconss, int norigbranchconss, int maxorigbranchconss)
Definition: relax_gcg.c:4430
GCG_BRANCHDATA * GCGconsOrigbranchGetBranchdata(SCIP_CONS *cons)
#define GCG_DECL_BRANCHPROPMASTER(x)
SCIP_RETCODE GCGrelaxPerformProbing(SCIP *scip, int maxlpiterations, SCIP_Longint *nlpiterations, SCIP_Real *lpobjvalue, SCIP_Bool *lpsolved, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: relax_gcg.c:4620
void GCGlinkingVarSetLinkingCons(SCIP_VAR *var, SCIP_CONS *cons, int index)
Definition: gcgvar.c:806
int GCGconshdlrDecompGetNFormerDetectionConssForID(SCIP *scip, int id)
gets number of active constraints during the detection of the decomp with given id
SCIP_Bool GCGrelaxIsOrigSolFeasible(SCIP *scip)
Definition: relax_gcg.c:4202
int GCGoriginalVarGetNCoefs(SCIP_VAR *var)
Definition: gcgvar.c:641
SCIP_Bool masterinprobing
Definition: relax_gcg.c:157
static SCIP_RETCODE solveMasterProblem(SCIP *scip, SCIP *masterprob, SCIP_RELAXDATA *relaxdata, SCIP_Longint nodelimit, SCIP_Real *lowerbound, SCIP_RESULT *result)
Definition: relax_gcg.c:2996
SCIP_Longint simplexiters
Definition: relax_gcg.c:167
static SCIP_RETCODE checkIdentical(SCIP *scip, SCIP_RELAXDATA *relaxdata, int probnr1, int probnr2, SCIP_HASHMAP *varmap, SCIP_Bool *identical, SCIP *scip1, SCIP *scip2)
Definition: relax_gcg.c:621
static SCIP_RETCODE combineSolutions(SCIP *scip, SCIP_SOL **newsol, SCIP **probs, int nprobs)
Definition: relax_gcg.c:2015
SCIP_RETCODE GCGrelaxBranchMasterSolved(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata, SCIP_Real newlowerbound)
Definition: relax_gcg.c:3749
SCIP_RETCODE GCGrelaxNewProbingnodeMaster(SCIP *scip)
Definition: relax_gcg.c:4378
void GCGvarSetBlock(SCIP_VAR *var, int block)
Definition: gcgvar.c:1048
SCIP_Bool usebliss
Definition: relax_gcg.c:152
static SCIP_RETCODE createPricingProblem(SCIP **pricingscip, const char *name, int clocktype, SCIP_Real infinity, SCIP_Real epsilon, SCIP_Real sumepsilon, SCIP_Real feastol, SCIP_Real lpfeastolfactor, SCIP_Real dualfeastol, SCIP_Bool enableppcuts)
Definition: relax_gcg.c:1536
int nmarkedmasterconss
Definition: relax_gcg.c:135
SCIP_Real GCGconsGetLhs(SCIP *scip, SCIP_CONS *cons)
Definition: scip_misc.c:206
SCIP_CONS ** linearmasterconss
Definition: relax_gcg.c:123
SCIP_CLOCK * GCGgetRootNodeTime(SCIP *scip)
Definition: relax_gcg.c:5181
int GCGoriginalVarGetNMastervars(SCIP_VAR *var)
Definition: gcgvar.c:569
data structures for branching rules
SCIP_RETCODE GCGrelaxBranchDataDelete(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA **branchdata)
Definition: relax_gcg.c:3704
SCIP_VAR *** DECdecompGetSubscipvars(DEC_DECOMP *decomp)
Definition: decomp.c:823
SCIP_VAR ** GCGoriginalVarGetMastervars(SCIP_VAR *var)
Definition: gcgvar.c:587
SCIP_Bool GCGmasterIsSolValid(SCIP *scip, SCIP_SOL *mastersol)
static SCIP_RETCODE solveBlockProblem(SCIP *scip, SCIP *blockprob, SCIP_RELAXDATA *relaxdata, SCIP_Real timelimit, int blocknum, SCIP_RESULT *result, SCIP_Real *objvalue)
Definition: relax_gcg.c:2135
int DECdecompGetNLinkingconss(DEC_DECOMP *decomp)
Definition: decomp.c:977
unsigned int GCGconshdlrDecompGetNFinishedPartialdecsTransformed(SCIP *scip)
Gets the number of finished partialdecs available for the transformed problem.
SCIP_RETCODE GCGoriginalVarAddCoef(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_CONS *cons)
Definition: gcgvar.c:679
#define RELAX_DESC
Definition: relax_gcg.c:78
SCIP_Bool GCGisLinkingVarInBlock(SCIP_VAR *var, int block)
Definition: gcgvar.c:1064
SCIP_RETCODE DECpermuteDecomp(SCIP *scip, DEC_DECOMP *decomp, SCIP_RANDNUMGEN *randnumgen)
Definition: decomp.c:4323
SCIP_Bool GCGisMasterSetCovering(SCIP *scip)
Definition: relax_gcg.c:4221
static SCIP_DECL_RELAXEXIT(relaxExitGcg)
Definition: relax_gcg.c:2746
SCIP_RETCODE GCGconshdlrDecompSelectPartialdec(SCIP *scip, int partialdecid, SCIP_Bool select)
selects/unselects a partialdecomp
SCIP_RETCODE GCGoriginalVarCreatePricingVar(SCIP *scip, SCIP_VAR *origvar, SCIP_VAR **var)
Definition: gcgvar.c:1213
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 plugins for generic column generation.
SCIP_RETCODE GCGconshdlrDecompCreateVarmapForPartialdecId(SCIP *scip, SCIP_HASHMAP **hashorig2pricingvar, int partialdecid, int probnr1, int probnr2, SCIP *scip1, SCIP *scip2, SCIP_HASHMAP *varmap)
for two identical pricing problems a corresponding varmap is created
constraint handler for structure detection
SCIP_Bool storedfeasibility
Definition: relax_gcg.c:160
int maxmarkedmasterconss
Definition: relax_gcg.c:136
#define RELAX_FREQ
Definition: relax_gcg.c:80
int * DECdecompGetNSubscipconss(DEC_DECOMP *decomp)
Definition: decomp.c:917
SCIP_RETCODE GCGsolve(SCIP *scip)
Definition: relax_gcg.c:5341
static SCIP_RETCODE setOriginalVarBlockNr(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_VAR *var, int newblock)
Definition: relax_gcg.c:181
SCIP_HEUR * GCGrelaxGetProbingheur(SCIP *scip)
Definition: relax_gcg.c:4309
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
int GCGlinkingVarGetNBlocks(SCIP_VAR *var)
Definition: gcgvar.c:493
SCIP_RETCODE GCGconsGetVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars)
Definition: scip_misc.c:490
SCIP_RETCODE GCGrelaxBranchActiveMaster(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata)
Definition: relax_gcg.c:3586
#define DEFAULT_BLISS
Definition: relax_gcg.c:89
GCG_PARAMDATA * paramsvisu
Definition: relax_gcg.c:171
SCIP_Bool GCGvarIsPricing(SCIP_VAR *var)
Definition: gcgvar.c:134
SCIP_Bool masterissetcover
Definition: relax_gcg.c:148
static SCIP_DECL_RELAXINITSOL(relaxInitsolGcg)
Definition: relax_gcg.c:2830
SCIP_RETCODE GCGrelaxTransOrigToMasterCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **transcons)
Definition: relax_gcg.c:3789
SCIP_Real GCGmasterGetDegeneracy(SCIP *scip)
SCIP_Real GCGgetGap(SCIP *scip)
Definition: relax_gcg.c:5501
@ DEC_DECMODE_ORIGINAL
Definition: type_decomp.h:63
static SCIP_RETCODE createMaster(SCIP *scip, SCIP_RELAXDATA *relaxdata)
Definition: relax_gcg.c:1841
#define relaxCopyGcg
Definition: relax_gcg.c:3413
SCIP * GCGgetOriginalprob(SCIP *masterprob)
Definition: relax_gcg.c:3883
#define GCG_DECL_BRANCHDATADELETE(x)
static SCIP_RETCODE createLinkingPricingVars(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_VAR *origvar)
Definition: relax_gcg.c:1164
SCIP_VAR ** DECdecompGetLinkingvars(DEC_DECOMP *decomp)
Definition: decomp.c:1036
void GCGoriginalVarSetNCoefs(SCIP_VAR *var, int ncoefs)
Definition: gcgvar.c:658
SCIP_CONS ** DECdecompGetLinkingconss(DEC_DECOMP *decomp)
Definition: decomp.c:967
static SCIP_RETCODE createMasterprobConss(SCIP *scip, SCIP_RELAXDATA *relaxdata)
Definition: relax_gcg.c:1617
SCIP_VAR * GCGoriginalVarGetPricingVar(SCIP_VAR *var)
Definition: gcgvar.c:216
GCG Benders' decomposition.
#define RELAX_PRIORITY
Definition: relax_gcg.c:79
void GCGgetBlissName(char *buffer, int len)
SCIP_Real GCGgetDegeneracy(SCIP *scip)
Definition: relax_gcg.c:4978
SCIP_Bool GCGvarIsOriginal(SCIP_VAR *var)
Definition: gcgvar.c:166
GCG variable pricer.
SCIP_RETCODE GCGconshdlrDecompArePricingprobsIdenticalForPartialdecid(SCIP *scip, int partialdecid, int probnr1, int probnr2, SCIP_Bool *identical)
checks if two pricing problems are identical based on information from detection
#define RELAX_INCLUDESLP
Definition: relax_gcg.c:81
static SCIP_RETCODE transformMaster(SCIP *scip, SCIP_RELAX *relax)
Definition: relax_gcg.c:2446
SCIP_RETCODE GCGrelaxBranchDeactiveMaster(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata)
Definition: relax_gcg.c:3624
static SCIP_RETCODE ensureSizeBranchrules(SCIP *scip, SCIP_RELAXDATA *relaxdata)
Definition: relax_gcg.c:463
DEC_DECOMP * decomp
Definition: relax_gcg.c:163
SCIP_RETCODE GCGconshdlrDecompTranslateOrigPartialdecs(SCIP *scip)
translates unpresolved partialdec to a complete presolved one
SCIP_RETCODE GCGincludeBendersPlugins(SCIP *scip)
various SCIP helper methods
#define GCG_DECL_BRANCHDEACTIVEMASTER(x)
SCIP_RETCODE GCGrelaxUpdateCurrentSol(SCIP *scip)
Definition: relax_gcg.c:4796
SCIP_Bool masterissetpart
Definition: relax_gcg.c:147
static SCIP_RETCODE markConsMaster(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_CONS *cons)
Definition: relax_gcg.c:225
SCIP plugins for the master problem running in Benders' decomposition mode.
static SCIP_RETCODE checkSetppcStructure(SCIP *scip, SCIP_RELAXDATA *relaxdata)
Definition: relax_gcg.c:487
SCIP_CONS * GCGconsOrigbranchGetActiveCons(SCIP *scip)
SCIP_RETCODE GCGrelaxEndProbing(SCIP *scip)
Definition: relax_gcg.c:4658
SCIP_SOL * storedorigsol
Definition: relax_gcg.c:159
SCIP_RETCODE GCGtransformProb(SCIP *scip)
Definition: relax_gcg.c:5199
SCIP_CONS ** GCGgetMasterConss(SCIP *scip)
Definition: relax_gcg.c:4098
SCIP_CONS ** GCGlinkingVarGetLinkingConss(SCIP_VAR *var)
Definition: gcgvar.c:787
SCIP_Longint lastmasterlpiters
Definition: relax_gcg.c:132
static SCIP_RETCODE checkAndAddExternalBranchingCandidate(SCIP *scip, SCIP_VAR *var)
Definition: relax_gcg.c:4765
#define DEFAULT_DISPINFOS
Definition: relax_gcg.c:86
SCIP_RETCODE GCGconsOrigbranchAddRootCons(SCIP *scip)
SCIP_Bool GCGisPricingprobRelevant(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4000
static SCIP_RETCODE createMasterProblem(SCIP *masterscip, const char *name, int clocktype, SCIP_Real infinity, SCIP_Real epsilon, SCIP_Real sumepsilon, SCIP_Real feastol, SCIP_Real lpfeastolfactor, SCIP_Real dualfeastol, DEC_DECMODE mode)
Definition: relax_gcg.c:1459
SCIP_HASHMAP * DECdecompGetVartoblock(DEC_DECOMP *decomp)
Definition: decomp.c:1199
#define DEFAULT_MIPDISCRETIZATION
Definition: relax_gcg.c:84
SCIP_SOL * SCIPbendersGetRelaxSol(SCIP_BENDERS *benders)
Definition: benders_gcg.c:753
SCIP_BRANCHRULE * GCGconsOrigbranchGetBranchrule(SCIP_CONS *cons)
SCIP_Bool GCGoriginalVarIsTransVar(SCIP_VAR *var)
Definition: gcgvar.c:199
SCIP_SOL * lastmastersol
Definition: relax_gcg.c:133
static SCIP_RETCODE relaxExecGcgOriginalProblem(SCIP *scip, SCIP_RELAX *relax, SCIP_Real *lowerbound, SCIP_RESULT *result)
Definition: relax_gcg.c:3354
SCIP_Bool GCGisMasterSetPartitioning(SCIP *scip)
Definition: relax_gcg.c:4240
constraint handler for storing the branching decisions at each node of the tree
int DECdecompGetNMastervars(DEC_DECOMP *decomp)
Definition: decomp.c:1069
int generatorlimit
Definition: relax_gcg.c:154
#define DEFAULT_MODE
Definition: relax_gcg.c:87
void GCGoriginalVarSetPricingVar(SCIP_VAR *var, SCIP_VAR *pricingvar)
Definition: gcgvar.c:235
static SCIP_RETCODE pricingprobsAreIdenticalFromDetectionInfo(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_HASHMAP **hashorig2pricingvar, int probnr1, int probnr2, SCIP_HASHMAP *varmap, SCIP_Bool *identical)
Definition: relax_gcg.c:793
SCIP_Bool mipdiscretization
Definition: relax_gcg.c:145
SCIP_RETCODE SCIPconshdlrDecompRepairConsNames(SCIP *scip)
static SCIP_DECL_RELAXEXITSOL(relaxExitsolGcg)
Definition: relax_gcg.c:2907
SCIP_Real GCGgetDualbound(SCIP *scip)
Definition: relax_gcg.c:5445
SCIP_RETCODE GCGtransformMastersolToOrigsol(SCIP *scip, SCIP_SOL *mastersol, SCIP_SOL **origsol)
Definition: misc.c:120
SCIP_RETCODE GCGoriginalVarAddMasterVar(SCIP *scip, SCIP_VAR *origvar, SCIP_VAR *var, SCIP_Real val)
Definition: gcgvar.c:1121
SCIP_Bool dispinfos
Definition: relax_gcg.c:149
int maxmasterconss
Definition: relax_gcg.c:127
SCIP_RETCODE GCGmasterAddMasterconsToHashmap(SCIP *scip, SCIP_CONS *cons, int pos)
SCIP_RETCODE DECcreateBasicDecomp(SCIP *scip, DEC_DECOMP **decomp, SCIP_Bool solveorigprob)
Definition: decomp.c:2388
constraint handler for storing the branching decisions at each node of the tree
SCIP_Bool origsolfeasible
Definition: relax_gcg.c:131
int * GCGgetVarLinkingconssBlock(SCIP *scip)
Definition: relax_gcg.c:5024
SCIP_RETCODE GCGrelaxBacktrackProbing(SCIP *scip, int probingdepth)
Definition: relax_gcg.c:4484
SCIP_RETCODE GCGlinkingVarCreatePricingVar(SCIP *pricingscip, int pricingprobnr, SCIP_VAR *origvar, SCIP_VAR **var)
Definition: gcgvar.c:1250
GCG_BRANCHRULE ** branchrules
Definition: relax_gcg.c:140
static void initRelaxdata(SCIP_RELAXDATA *relaxdata)
Definition: relax_gcg.c:2657
static SCIP_RETCODE createPricingVar(SCIP_RELAXDATA *relaxdata, SCIP_VAR *origvar)
Definition: relax_gcg.c:1134
#define DEFAULT_BLISS_SEARCH_NODE_LIMIT
Definition: relax_gcg.c:90
SCIP_Real * GCGoriginalVarGetCoefs(SCIP_VAR *var)
Definition: gcgvar.c:623
SCIP_RETCODE GCGcreateInitialMasterVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **newvar)
Definition: gcgvar.c:1472
DEC_DECMODE GCGgetMasterDecompMode(SCIP *masterprob)
Definition: relax_gcg.c:5144
SCIP_Real GCGgetPrimalbound(SCIP *scip)
Definition: relax_gcg.c:5473
SCIP_RETCODE GCGrelaxBranchPropMaster(SCIP *scip, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata, SCIP_RESULT *result)
Definition: relax_gcg.c:3662
DEC_DECMODE GCGgetDecompositionMode(SCIP *scip)
Definition: relax_gcg.c:5123
static SCIP_DECL_RELAXFREE(relaxFreeGcg)
Definition: relax_gcg.c:2708
int * DECdecompGetNSubscipvars(DEC_DECOMP *decomp)
Definition: decomp.c:833
@ DEC_DECMODE_DANTZIGWOLFE
Definition: type_decomp.h:61
SCIP_RETCODE DECdetectStructure(SCIP *scip, SCIP_RESULT *result)
interface method to detect the structure including presolving
static SCIP_RETCODE convertStructToGCG(SCIP *scip, SCIP_RELAXDATA *relaxdata, DEC_DECOMP *decomp)
Definition: relax_gcg.c:263
SCIP_SOL * GCGgetBendersRelaxationSol(SCIP *scip)
Definition: relax_gcg.c:5100
SCIP_CONS ** GCGoriginalVarGetMasterconss(SCIP_VAR *var)
Definition: gcgvar.c:710
int GCGgetNRelPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3959
SCIP_RETCODE GCGrelaxStartProbing(SCIP *scip, SCIP_HEUR *probingheur)
Definition: relax_gcg.c:4264
SCIP_Bool GCGmasterIsBestsolValid(SCIP *scip)
SCIP_RETCODE DECdecompFree(SCIP *scip, DEC_DECOMP **decdecomp)
Definition: decomp.c:530
#define GCG_DECL_BRANCHMASTERSOLVED(x)
SCIP * masterprob
Definition: relax_gcg.c:103
enum Decmode DEC_DECMODE
Definition: type_decomp.h:68
SCIP_Bool discretization
Definition: relax_gcg.c:144
SCIP * GCGbendersGetOrigprob(SCIP *masterprob)
Definition: benders_gcg.c:768
SCIP_CONS * GCGgetConvCons(SCIP *scip, int blocknr)
Definition: relax_gcg.c:4136
static SCIP_RETCODE initRelaxProblemdata(SCIP *scip, SCIP_RELAXDATA *relaxdata)
Definition: relax_gcg.c:1425
static SCIP_RETCODE createPricingprobConss(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_HASHMAP **hashorig2pricingvar)
Definition: relax_gcg.c:1753
SCIP_RETCODE GCGrelaxNewProbingnodeOrig(SCIP *scip)
Definition: relax_gcg.c:4331
SCIP * GCGmasterGetOrigprob(SCIP *scip)
int DECdecompGetNLinkingvars(DEC_DECOMP *decomp)
Definition: decomp.c:1046
SCIP_HEUR * probingheur
Definition: relax_gcg.c:158
SCIP_SOL * GCGrelaxGetCurrentOrigSol(SCIP *scip)
Definition: relax_gcg.c:4183
SCIP_RETCODE SCIPincludeRelaxGcg(SCIP *scip)
Definition: relax_gcg.c:3422
SCIP_Real DECdecompGetMaxwhiteScore(DEC_DECOMP *decomp)
Definition: decomp.c:701
SCIP_RETCODE GCGconsGetVals(SCIP *scip, SCIP_CONS *cons, SCIP_Real *vals, int nvals)
Definition: scip_misc.c:621
#define DEFAULT_AGGREGATION
Definition: relax_gcg.c:85
int GCGgetNPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3979
int * nblocksidentical
Definition: relax_gcg.c:109
SCIP * altmasterprob
Definition: relax_gcg.c:104
int searchnodelimit
Definition: relax_gcg.c:153
SCIP_CONS *** DECdecompGetSubscipconss(DEC_DECOMP *decomp)
Definition: decomp.c:908
static SCIP_RETCODE setPricingObjsOriginal(SCIP *scip, SCIP **probs, int nprobs)
Definition: relax_gcg.c:2069
int GCGgetBlockRepresentative(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4023
static SCIP_RETCODE createPricingVariables(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_HASHMAP **hashorig2pricingvar)
Definition: relax_gcg.c:1275
SCIP_CONS ** markedmasterconss
Definition: relax_gcg.c:134
static SCIP_RETCODE setPricingProblemParameters(SCIP *scip, int clocktype, SCIP_Real infinity, SCIP_Real epsilon, SCIP_Real sumepsilon, SCIP_Real feastol, SCIP_Real lpfeastolfactor, SCIP_Real dualfeastol, SCIP_Bool enableppcuts)
Definition: relax_gcg.c:1038
static SCIP_RETCODE displayPricingStatistics(SCIP *scip, SCIP **pricingprobs, int npricingprobs, int *blockrepresentative)
Definition: relax_gcg.c:1386
int GCGconsGetNVars(SCIP *scip, SCIP_CONS *cons)
Definition: scip_misc.c:434
automorphism recognition of SCIPs
static SCIP_RETCODE relaxExecGcgDantzigWolfe(SCIP *scip, SCIP_RELAX *relax, SCIP_Real *lowerbound, SCIP_RESULT *result)
Definition: relax_gcg.c:3126
SCIP_RETCODE GCGcreateConsOrigbranch(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_NODE *node, SCIP_CONS *parentcons, SCIP_BRANCHRULE *branchrule, GCG_BRANCHDATA *branchdata)
SCIP_Real GCGgetPricingprobsMemUsed(SCIP *scip)
Definition: relax_gcg.c:4925
GCG relaxator.
void GCGVisuFreeParams(SCIP *scip, GCG_PARAMDATA *paramdata)
Definition: params_visu.c:695
static SCIP_RETCODE initRelaxator(SCIP *scip, SCIP_RELAX *relax)
Definition: relax_gcg.c:2535
SCIP_RETCODE DECdecompAddRemainingConss(SCIP *scip, DEC_DECOMP *decdecomp)
Definition: decomp.c:2179
SCIP_CONS * GCGconsMasterbranchGetActiveCons(SCIP *scip)
SCIP_RETCODE GCGorigVarCreateData(SCIP *scip, SCIP_VAR *var)
Definition: gcgvar.c:313
SCIP_VAR ** GCGpricingVarGetOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:1015
int GCGconshdlrDecompAddBasicPartialdec(SCIP *scip, SCIP_Bool presolved)
creates and adds a basic partialdecomp (all cons/vars are assigned to master)
SCIP_RETCODE SCIPincludeBendersGcg(SCIP *scip, SCIP *origprob)
Definition: benders_gcg.c:719
SCIP_HASHMAP * hashorig2origvar
Definition: relax_gcg.c:117
SCIP_Bool GCGgetConsIsSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_SETPPCTYPE *setppctype)
Definition: scip_misc.c:763
SCIP_RETCODE GCGpricingVarAddOrigVar(SCIP *scip, SCIP_VAR *pricingvar, SCIP_VAR *origvar)
Definition: gcgvar.c:531
SCIP_RETCODE GCGdetect(SCIP *scip)
Definition: relax_gcg.c:5283
int GCGgetNVarLinkingconss(SCIP *scip)
Definition: relax_gcg.c:5043
SCIP_Longint lastsolvednodenr
Definition: relax_gcg.c:137
SCIP_SOL * currentorigsol
Definition: relax_gcg.c:130
static SCIP_DECL_RELAXEXEC(relaxExecGcg)
Definition: relax_gcg.c:3373
SCIP_Bool GCGmasterIsCurrentSolValid(SCIP *scip)
@ DEC_DECTYPE_DIAGONAL
Definition: type_decomp.h:52
static SCIP_RETCODE GCGsetStructDecomp(SCIP *scip, DEC_DECOMP *decomp)
Definition: relax_gcg.c:2418
helper functions for automorphism detection
SCIP_RETCODE GCGlinkingVarCreateMasterCons(SCIP *masterscip, int pricingprobnr, SCIP_VAR *origvar, SCIP_CONS **linkcons)
Definition: gcgvar.c:1285
SCIP_RETCODE GCGmasterCreateInitialMastervars(SCIP *scip)
int GCGgetNMasterConss(SCIP *scip)
Definition: relax_gcg.c:4079
static SCIP_RETCODE pricingprobsAreIdentical(SCIP *scip, SCIP_RELAXDATA *relaxdata, int probnr1, int probnr2, SCIP_HASHMAP *varmap, SCIP_Bool *identical)
Definition: relax_gcg.c:839
SCIP_RETCODE GCGrelaxPerformProbingWithPricing(SCIP *scip, int maxpricerounds, SCIP_Longint *nlpiterations, int *npricerounds, SCIP_Real *lpobjvalue, SCIP_Bool *lpsolved, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: relax_gcg.c:4639
DEC_DECOMP * GCGgetStructDecomp(SCIP *scip)
Definition: relax_gcg.c:2397
SCIP_RETCODE GCGfreeOrigVarsData(SCIP *scip)
Definition: gcgvar.c:279
static SCIP_RETCODE solveDiagonalBlocks(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_RESULT *result, SCIP_Real *lowerbound)
Definition: relax_gcg.c:2300
int DECdecompGetNBlocks(DEC_DECOMP *decomp)
Definition: decomp.c:745
static SCIP_RETCODE checkIdenticalBlocks(SCIP *scip, SCIP_RELAXDATA *relaxdata, SCIP_HASHMAP **hashorig2pricingvar)
Definition: relax_gcg.c:896
SCIP_Bool GCGoriginalVarIsLinking(SCIP_VAR *var)
Definition: gcgvar.c:182
static SCIP_RETCODE initializeMasterProblemSolve(SCIP *scip, SCIP_RELAX *relax)
Definition: relax_gcg.c:2786
static SCIP_RETCODE ensureSizeMasterConss(SCIP *scip, SCIP_RELAXDATA *relaxdata, int size)
Definition: relax_gcg.c:438
@ DEC_DECMODE_UNKNOWN
Definition: type_decomp.h:65
int GCGgetNIdenticalBlocks(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4053
SCIP * GCGgetPricingprob(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:3939
SCIP ** pricingprobs
Definition: relax_gcg.c:105
SCIP_CONS ** varlinkconss
Definition: relax_gcg.c:125
#define RELAX_NAME
Definition: relax_gcg.c:77
GCG_PARAMDATA * GCGgetParamsVisu(SCIP *scip)
Definition: relax_gcg.c:4159
SCIP_RETCODE SCIPcreateParamsVisu(SCIP *scip, GCG_PARAMDATA **paramdata)
Definition: params_visu.c:716
SCIP_RETCODE cmpGraphPair(SCIP *origscip, SCIP *scip1, SCIP *scip2, int prob1, int prob2, SCIP_RESULT *result, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, unsigned int searchnodelimit, unsigned int generatorlimit)
SCIP_RETCODE DECdecompCheckConsistency(SCIP *scip, DEC_DECOMP *decdecomp)
Definition: decomp.c:2267
SCIP_CONS ** masterconss
Definition: relax_gcg.c:120
static SCIP_RETCODE relaxExecGcgBendersDecomposition(SCIP *scip, SCIP_RELAX *relax, SCIP_Real *lowerbound, SCIP_RESULT *result)
Definition: relax_gcg.c:3336
void GCGlinkingVarSetPricingVar(SCIP_VAR *origvar, int pricingprobnr, SCIP_VAR *var)
Definition: gcgvar.c:427
SCIP_VAR ** GCGlinkingVarGetPricingVars(SCIP_VAR *var)
Definition: gcgvar.c:409
SCIP_Bool relaxisinitialized
Definition: relax_gcg.c:164
SCIP_CLOCK * rootnodetime
Definition: relax_gcg.c:168
SCIP_CONS ** GCGgetOrigMasterConss(SCIP *scip)
Definition: relax_gcg.c:4117
SCIP_CONS ** origmasterconss
Definition: relax_gcg.c:121
SCIP_CONS ** convconss
Definition: relax_gcg.c:110
#define relaxInitGcg
Definition: relax_gcg.c:3414
SCIP_RETCODE GCGincludeMasterPlugins(SCIP *scip)
static SCIP_Bool realArraysAreEqual(SCIP *scip, SCIP_Real *array1, int array1length, SCIP_Real *array2, int array2length)
Definition: relax_gcg.c:590
int DECdecompGetPartialdecID(DEC_DECOMP *decomp)
Definition: decomp.c:1660
static SCIP_RETCODE saveOriginalVarMastercoeffs(SCIP *scip, SCIP_VAR **origvars, int norigvars, int nmasterconss, SCIP_CONS **origmasterconss, SCIP_CONS **masterconss)
Definition: relax_gcg.c:1563
SCIP_Bool GCGrelaxIsInitialized(SCIP *scip)
Definition: relax_gcg.c:4958
static SCIP_RETCODE performProbing(SCIP *scip, int maxlpiterations, int maxpricerounds, SCIP_Bool usepricing, SCIP_Longint *nlpiterations, int *npricerounds, SCIP_Real *lpobjvalue, SCIP_Bool *lpsolved, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: relax_gcg.c:4518
#define GCG_DECL_BRANCHACTIVEMASTER(x)
SCIP_Bool GCGdetectionTookPlace(SCIP *scip, SCIP_Bool original)
#define DEFAULT_BLISS_GENERATOR_LIMIT
Definition: relax_gcg.c:91
SCIP_RETCODE GCGpresolve(SCIP *scip)
Definition: relax_gcg.c:5237
SCIP_RETCODE SCIPincludePricerGcg(SCIP *scip, SCIP *origprob)
SCIP_Bool aggregation
Definition: relax_gcg.c:146
int * blockrepresentative
Definition: relax_gcg.c:108
static SCIP_RETCODE solveMasterProblemAndEvaluate(SCIP *scip, SCIP_RELAX *relax, SCIP_Real *lowerbound, SCIP_RESULT *result)
Definition: relax_gcg.c:3227
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
SCIP_CONS ** GCGgetVarLinkingconss(SCIP *scip)
Definition: relax_gcg.c:5005
int GCGgetNLinkingvars(SCIP *scip)
Definition: relax_gcg.c:5062
int nrelpricingprobs
Definition: relax_gcg.c:107
SCIP_Bool GCGconshdlrDecompCheckConsistency(SCIP *scip)
check whether partialdecs are consistent
DEC_DECOMP * DECgetBestDecomp(SCIP *scip, SCIP_Bool printwarnings)
Gets the best known decomposition.
DEC_DECMODE mode
Definition: relax_gcg.c:150
SCIP_RETCODE GCGcreateOrigVarsData(SCIP *scip)
Definition: gcgvar.c:255