Scippy

GCG

Branch-and-Price & Column Generation for Everyone

heur_xprins.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 heur_xprins.c
29  * @brief Extreme Point RINS
30  * @author Christian Puchert
31  */
32 
33 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34 
35 #include <assert.h>
36 #include <string.h>
37 #include <stdio.h>
38 
39 #include "heur_xprins.h"
40 #include "gcg.h"
41 
42 #include "scip/scip.h"
43 #include "scip/misc.h"
44 #include "scip/scipdefplugins.h"
45 
46 
47 #define HEUR_NAME "xprins"
48 #define HEUR_DESC "Extreme Point RINS"
49 #define HEUR_DISPCHAR 'Y'
50 #define HEUR_PRIORITY -1100600
51 #define HEUR_FREQ 0
52 #define HEUR_FREQOFS 0
53 #define HEUR_MAXDEPTH -1
54 #define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
55 #define HEUR_USESSUBSCIP TRUE
56 
57 #define DEFAULT_EQUALITYRATE 0.5 /**< minimum percentage of coincidence of relaxation and extreme pts */
58 #define DEFAULT_MAXNODES 1000LL /**< maximum number of nodes to regard in the subproblem */
59 #define DEFAULT_MINIMPROVE 0.01 /**< factor by which xprins should at least improve the incumbent */
60 #define DEFAULT_MINNODES 200LL /**< minimum number of nodes to regard in the subproblem */
61 #define DEFAULT_MINFIXINGRATE 0.4 /**< minimum percentage of integer variables that have to be fixed */
62 #define DEFAULT_NODESOFS 200LL /**< number of nodes added to the contingent of the total nodes */
63 #define DEFAULT_NODESQUOT 0.1 /**< subproblem nodes in relation to nodes of the original problem */
64 #define DEFAULT_NUSEDPTS -1 /**< number of extreme pts per block that will be taken into account
65  * (-1: all; 0: all which contribute to current relaxation solution)
66  */
67 #define DEFAULT_RANDOMIZATION FALSE /**< should the choice which sols to take be randomized? */
68 #define DEFAULT_COPYCUTS TRUE /**< if DEFAULT_USELPROWS is FALSE, then should all active cuts from the cutpool
69  * of the original scip be copied to constraints of the subscip
70  */
71 #define DEFAULT_RANDSEED 7 /**< initial random seed */
72 
73 
74 
75 /*
76  * Data structures
77  */
78 
79 /** primal heuristic data */
80 struct SCIP_HeurData
81 {
82  SCIP_Real equalityrate; /**< minimum percentage of coincidence of relaxation and extreme pts */
83  SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
84  SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
85  SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
86  SCIP_Longint usednodes; /**< nodes already used by xprins in earlier calls */
87  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
88  int nusedpts; /**< number of extreme pts per block that will be taken into account
89  * (-1: all; 0: all which contribute to current relaxation solution)
90  */
91  unsigned int nfailures; /**< number of failures since last successful call */
92  SCIP_Longint nextnodenumber; /**< number of BnB nodes at which crossover should be called next */
93  SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
94  SCIP_Real minimprove; /**< factor by which xprins should at least improve the incumbent */
95  SCIP_Bool randomization; /**< should the choice which sols to take be randomized? */
96  SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
97  * to constraints in subproblem?
98  */
99  SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
100 
101 #ifdef SCIP_STATISTIC
102  SCIP_Longint nfixfails; /**< number of abortions due to a bad fixing rate */
103  SCIP_Real avgfixrate; /**< average rate of variables that are fixed */
104  SCIP_Real avgzerorate; /**< average rate of fixed variables that are zero */
105  SCIP_Longint totalsols; /**< total number of subSCIP solutions (including those which have not
106  * been added)
107  */
108  SCIP_Real subsciptime; /**< total subSCIP solving time in seconds */
109  SCIP_Real bestprimalbd; /**< objective value of best solution found by this heuristic */
110 #endif
111 };
112 
113 
114 
115 
116 /*
117  * Local methods
118  */
119 
120 
121 /** for each block, select extreme points (represented by mastervars) to be compared to the relaxation solution */
122 static
123 SCIP_RETCODE selectExtremePoints(
124  SCIP* scip, /**< original SCIP data structure */
125  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
126  int* selection, /**< indices of selected extreme points */
127  int* nactualpts, /**< number of points per block that have actually been selected */
128  SCIP_Bool* success /**< pointer to store whether the process was successful */
129  )
130 {
131  SCIP* masterprob;
132  int nblocks;
133 
134  SCIP_VAR** mastervars;
135  SCIP_Real* mastervals;
136  int nmastervars;
137 
138  int nusedpts;
139  int block;
140 #ifndef NDEBUG
141  int nidentblocks;
142 #endif
143  int* blocknrs;
144  int* identblock;
145  SCIP_Real* blockvalue;
146  SCIP_Real value;
147  SCIP_Real* selvalue;
148 
149  int i;
150  int j;
151 
152  /* check preconditions */
153  assert(scip != NULL);
154  assert(heurdata != NULL);
155  assert(selection != NULL);
156  assert(success != NULL);
157 
158  assert(heurdata->nusedpts >= 0);
159 
160  /* get master problem */
161  masterprob = GCGgetMasterprob(scip);
162  assert(masterprob != NULL);
163 
164  /* get number of blocks */
165  nblocks = GCGgetNPricingprobs(scip);
166 
167  /* get variables of the master problem */
168  SCIP_CALL( SCIPgetVarsData(masterprob, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
169  assert(mastervars != NULL);
170  assert(nmastervars >= 0);
171 
172  /* get master LP solution values */
173  SCIP_CALL( SCIPallocBufferArray(scip, &mastervals, nmastervars) );
174  SCIP_CALL( SCIPgetSolVals(masterprob, NULL, nmastervars, mastervars, mastervals) );
175 
176  /* get number of extreme points per block */
177  nusedpts = heurdata->nusedpts;
178 
179  /* allocate memory */
180  SCIP_CALL( SCIPallocBufferArray(scip, &selvalue, nblocks * nusedpts) );
181  SCIP_CALL( SCIPallocBufferArray(scip, &blocknrs, nblocks) );
182  SCIP_CALL( SCIPallocBufferArray(scip, &blockvalue, nblocks) );
183  SCIP_CALL( SCIPallocBufferArray(scip, &identblock, nblocks) );
184 
185  /* initialize the block values for the pricing problems */
186  for( i = 0; i < nblocks; i++ )
187  {
188  blockvalue[i] = 0.0;
189  blocknrs[i] = 0;
190  identblock[i] = i;
191  nactualpts[i] = 0;
192  }
193 
194  *success = FALSE;
195 
196  /* loop over all given master variables;
197  * this loop treats master variables that have value one or greater
198  * (in particular important if blocks are represented by others)
199  */
200  for( i = 0; i < nmastervars; i++ )
201  {
202  SCIP_VAR* mastervar;
203 
204  mastervar = mastervars[i];
205  assert(GCGvarIsMaster(mastervar));
206 
207  /* get block information and solution value */
208  block = GCGvarGetBlock(mastervar);
209  value = SCIPgetSolVal(masterprob, NULL, mastervar);
210 
211  /** @todo handle infinite master solution values */
212  assert(!SCIPisInfinity(scip, value));
213 
214  /* ignore irrelevant extreme points */
215  if( SCIPisFeasZero(scip, value) )
216  continue;
217 
218  /* ignore rays
219  * @todo do it smarter */
220  if( GCGmasterVarIsRay(mastervar) )
221  continue;
222 
223  /* variables belonging to no block are not treated here */
224  if( block == -1 )
225  continue;
226 
227  /* get number of blocks that are identical to this block */
228  assert(block >= 0);
229 #ifndef NDEBUG
230  nidentblocks = GCGgetNIdenticalBlocks(scip, block);
231 #endif
232 
233  while( SCIPisFeasGE(scip, mastervals[i], 1.0) )
234  {
235  /* insert the extreme point in the selection (should be the only point for this block) */
236  j = identblock[block] * nusedpts;
237  assert(selection[j] == -1);
238  assert(nactualpts[identblock[block]] == 0);
239 
240  nactualpts[identblock[block]] = 1;
241  selection[j] = i;
242  selvalue[j] = 1.0;
243 
244  mastervals[i] = mastervals[i] - 1.0;
245  blocknrs[block]++;
246 
247  /* search the next block to be considered */
248  for( j = identblock[block] + 1; j < nblocks; ++j )
249  if( GCGgetBlockRepresentative(scip, j) == block )
250  {
251  identblock[block] = j;
252  break;
253  }
254 
255 #ifndef NDEBUG
256  assert(blocknrs[block] >= nidentblocks || j < nblocks);
257 #endif
258  }
259  }
260 
261  /* loop over all given master variables */
262  for( i = 0; i < nmastervars; i++ )
263  {
264  SCIP_VAR* mastervar;
265 
266  mastervar = mastervars[i];
267  assert(GCGvarIsMaster(mastervar));
268 
269  /* get block information and solution value */
270  block = GCGvarGetBlock(mastervar);
271  value = SCIPgetSolVal(masterprob, NULL, mastervar);
272 
273  /** @todo handle infinite master solution values */
274  assert(!SCIPisInfinity(scip, value));
275 
276  /* ignore irrelevant extreme points */
277  if( SCIPisFeasZero(scip, value) )
278  continue;
279 
280  /* ignore rays */
281  if( GCGmasterVarIsRay(mastervar) )
282  continue;
283 
284  /* variables belonging to no block are not treated here */
285  if( block == -1 )
286  continue;
287 
288  /* get number of blocks that are identical to this block */
289  assert(block >= 0);
290 #ifndef NDEBUG
291  nidentblocks = GCGgetNIdenticalBlocks(scip, block);
292 #endif
293 
294  assert(SCIPisFeasGE(scip, mastervals[i], 0.0) && SCIPisFeasLT(scip, mastervals[i], 1.0));
295 
296  while( SCIPisFeasPositive(scip, mastervals[i]) )
297  {
298  value = MIN(mastervals[i], 1.0 - blockvalue[block]);
299 
300  /* check if the extreme point is good enough to be inserted in the selection
301  * by looking for a position where it may be inserted
302  */
303  for( j = (identblock[block] * nusedpts) + nactualpts[identblock[block]];
304  j > identblock[block] * nusedpts && SCIPisGT(scip, value, selvalue[j]); --j )
305  {
306  if( j < (identblock[block] + 1) * nusedpts )
307  {
308  selection[j] = selection[j-1];
309  selvalue[j] = selvalue[j-1];
310  }
311  }
312  if( j < (identblock[block] * nusedpts) + nusedpts )
313  {
314  selection[j] = i;
315  selvalue[j] = value;
316 
317  if( nactualpts[identblock[block]] < nusedpts )
318  ++nactualpts[identblock[block]];
319  }
320 
321  mastervals[i] = mastervals[i] - value;
322  if( SCIPisFeasZero(scip, mastervals[i]) )
323  mastervals[i] = 0.0;
324  blockvalue[block] += value;
325 
326  /* if the value assigned to the block is equal to 1, this block is full and we consider the next block */
327  if( SCIPisFeasGE(scip, blockvalue[block], 1.0) )
328  {
329  blockvalue[block] = 0.0;
330  blocknrs[block]++;
331 
332  /* search the next identical block to be considered */
333  for( j = identblock[block] + 1; j < nblocks; ++j )
334  if( GCGgetBlockRepresentative(scip, j) == block )
335  {
336  identblock[block] = j;
337  break;
338  }
339 
340 #ifndef NDEBUG
341  assert(blocknrs[block] >= nidentblocks || j < nblocks);
342 #endif
343  }
344  }
345  }
346 
347  *success = TRUE;
348 
349  /* free memory */
350  SCIPfreeBufferArray(scip, &identblock);
351  SCIPfreeBufferArray(scip, &blockvalue);
352  SCIPfreeBufferArray(scip, &blocknrs);
353  SCIPfreeBufferArray(scip, &selvalue);
354  SCIPfreeBufferArray(scip, &mastervals);
355 
356  return SCIP_OKAY;
357 }
358 
359 
360 /** select extreme points (represented by mastervars) randomly */
361 static
363  SCIP* scip, /**< original SCIP data structure */
364  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
365  int* selection, /**< indices of selected extreme points */
366  int* nactualpts, /**< number of points per block that have actually been selected */
367  SCIP_Bool* success /**< pointer to store whether the process was successful */
368  )
369 {
370  SCIP* masterprob;
371  int nblocks;
372 
373  SCIP_VAR** mastervars;
374  int nmastervars;
375 
376  int nusedpts; /* number of extreme points per block to be chosen */
377  int* npts; /* for each block, the number of available extreme points */
378  int* blockpts; /* all points of a block which to be considered */
379  SCIP_Real* ptvals; /* solution values of extreme points in master problem */
380 
381  int i;
382  int j;
383 
384  /* check preconditions */
385  assert(scip != NULL);
386  assert(heurdata != NULL);
387  assert(selection != NULL);
388  assert(success != NULL);
389 
390  /* get master problem */
391  masterprob = GCGgetMasterprob(scip);
392  assert(masterprob != NULL);
393 
394  /* get number of blocks */
395  nblocks = GCGgetNPricingprobs(scip);
396 
397  /* get variables of the master problem */
398  SCIP_CALL( SCIPgetVarsData(masterprob, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
399  assert(mastervars != NULL);
400  assert(nmastervars >= 0);
401 
402  /* get number of extreme points per block */
403  nusedpts = heurdata->nusedpts;
404 
405  /* allocate memory */
406  SCIP_CALL( SCIPallocBufferArray(scip, &npts, nblocks) );
407 
408  *success = TRUE;
409 
410  /* check whether we have enough points per block to perform a randomization */
411  for( i = 0; i < nblocks; ++i )
412  npts[i] = 0;
413  for( i = 0; i < nmastervars; ++i )
414  {
415  SCIP_VAR* mastervar;
416  SCIP_Real solval;
417  int block;
418 
419  mastervar = mastervars[i];
420  solval = SCIPgetSolVal(masterprob, NULL, mastervar);
421  block = GCGvarGetBlock(mastervar);
422 
423  if( block >= 0 && !SCIPisFeasZero(scip, solval) )
424  ++npts[block];
425  }
426  for( i = 0; i < nblocks; ++i )
427  if( GCGisPricingprobRelevant(scip, i) && npts[i] <= nusedpts )
428  *success = FALSE;
429 
430  /* do not randomize if there are not enough points available */
431  if( !*success )
432  {
433  SCIPdebugMessage(" -> not enough extreme points available for randomization.\n");
434 
435  /* free memory */
436  SCIPfreeBufferArray(scip, &npts);
437 
438  return SCIP_OKAY;
439  }
440 
441  *success = FALSE;
442 
443  /* perform randomization: for each block, select a set of extreme points to be considered */
444  for( i = 0; i < nblocks; ++i )
445  {
446  int blockrep;
447  int lastpt; /* the worst extreme point possible to choose */
448 
449  int k;
450 
451 
452  SCIP_CALL( SCIPallocBufferArray(scip, &blockpts, npts[i]) );
453  SCIP_CALL( SCIPallocBufferArray(scip, &ptvals, npts[i]) );
454 
455  /* get representative of this block */
456  blockrep = GCGgetBlockRepresentative(scip, i);
457  assert(blockrep >= 0 && blockrep <= i);
458 
459  /* get all relevant extreme points for this block */
460  k = 0;
461  for( j = 0; j < nmastervars; ++j )
462  {
463  SCIP_VAR* mastervar;
464  SCIP_Real solval;
465  int block;
466 
467  mastervar = mastervars[j];
468  solval = SCIPgetSolVal(masterprob, NULL, mastervar);
469  block = GCGvarGetBlock(mastervar);
470 
471  if( block == blockrep && !SCIPisFeasZero(scip, solval) )
472  {
473  assert(k < npts[blockrep]);
474  blockpts[k] = j;
475  ++k;
476  }
477  }
478  assert(k == npts[blockrep]);
479 
480  /* sort the extreme points */
481  SCIPsortRealInt(ptvals, blockpts, npts[blockrep]);
482  lastpt = npts[blockrep];
483 
484  /* perform a random selection for this block */
485  for( k = 0; k < nusedpts; ++k )
486  {
487  int idx;
488  int selidx;
489 
490  idx = SCIPrandomGetInt(heurdata->randnumgen, nusedpts-k-1, lastpt-1);
491  selidx = i * nusedpts + k;
492  selection[selidx] = blockpts[idx];
493  lastpt = idx;
494  }
495 
496  nactualpts[i] = nusedpts;
497 
498  SCIPfreeBufferArray(scip, &ptvals);
499  SCIPfreeBufferArray(scip, &blockpts);
500  }
501 
502  *success = TRUE;
503 
504  /* free memory */
505  SCIPfreeBufferArray(scip, &npts);
506 
507  return SCIP_OKAY;
508 }
509 
510 /*
511  * count extreme points per block to be considered;
512  * this is only done when no selection of extreme points has been made!
513  */
514 static
515 SCIP_RETCODE countExtremePoints(
516  SCIP* scip, /**< original SCIP data structure */
517  int* selection, /**< selected extreme points the heuristic will use, or NULL */
518  int nusedpts, /**< number of extreme points per block to be considered, or 0, or -1 */
519  int* nactualpts /**< number of points per block that have actually been selected */
520  )
521 {
522  SCIP* masterprob; /* master problem */
523  SCIP_VAR** mastervars; /* master variables */
524  int nmastervars; /* number of master variables */
525  int nblocks;
526 
527  int i;
528 
529  assert(nusedpts == 0 || nusedpts == -1);
530  assert(selection == NULL);
531 
532  /* get master problem and its variables */
533  masterprob = GCGgetMasterprob(scip);
534  assert(masterprob != NULL);
535  SCIP_CALL( SCIPgetVarsData(masterprob, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
536  assert(mastervars != NULL);
537  assert(nmastervars >= 0);
538 
539  nblocks = GCGgetNPricingprobs(scip);
540 
541  for( i = 0; i < nblocks; ++i )
542  nactualpts[i] = 0;
543  for( i = 0; i < nmastervars; ++i )
544  {
545  SCIP_VAR* mastervar;
546  int block;
547 
548  mastervar = mastervars[i];
549  assert(mastervar != NULL);
550  block = GCGvarGetBlock(mastervar);
551  if( block >= 0 && (nusedpts == -1 || !SCIPisZero(scip, SCIPgetSolVal(masterprob, NULL, mastervar))) )
552  ++nactualpts[block];
553  }
554  /* We have only counted for the relevant blocks so far,
555  * so it is still necessary to set the numbers of extreme points for the other blocks
556  */
557  for( i = 0; i < nblocks; ++i )
558  {
559  int blockrep = GCGgetBlockRepresentative(scip, i);
560  assert(blockrep >= 0 && blockrep <= i);
561 
562  nactualpts[i] = nactualpts[blockrep];
563  }
564 
565  return SCIP_OKAY;
566 }
567 
568 
569 
570 /** initialize the subSCIP instance: copy SCIP to subSCIP, set the parameters */
571 static
572 SCIP_RETCODE setupSubproblem(
573  SCIP* scip, /**< original SCIP data structure */
574  SCIP* subscip, /**< SCIP data structure for the subproblem */
575  SCIP_VAR** subvars, /**< the variables of the subproblem */
576  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
577  SCIP_Longint nstallnodes, /**< node limit for subproblem */
578  SCIP_Real timelimit, /**< time limit for subproblem */
579  SCIP_Real memorylimit /**< memory limit for subproblem */
580  )
581 {
582  SCIP_VAR** vars;
583  int nvars;
584 
585  int i;
586 
587  char probname[SCIP_MAXSTRLEN];
588  SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to subSCIP variables */
589  SCIP_Bool valid;
590 
591  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
592  SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
593 
594  /* copy the SCIP instance to the subSCIP */
595 
596  /* copy all plugins */
597  SCIP_CALL( SCIPincludeDefaultPlugins(subscip) );
598 
599  /* get name of the original problem and add the string "_extremeptsub" */
600  (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_extremeptsub", SCIPgetProbName(scip));
601 
602  /* create the subproblem */
603  SCIP_CALL( SCIPcreateProb(subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
604 
605  /* copy all variables */
606  SCIP_CALL( SCIPcopyVars(scip, subscip, varmapfw, NULL, NULL, NULL, 0, TRUE) );
607 
608  /* copy all constraints */
609  valid = FALSE;
610  SCIP_CALL( SCIPcopyConss(scip, subscip, varmapfw, NULL, TRUE, FALSE, &valid) );
611  if( heurdata->copycuts )
612  {
613  /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
614  SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, TRUE, NULL) );
615  }
616  SCIPdebugMessage("Copying the SCIP constraints was %s complete.\n", valid ? "" : "not ");
617 
618  /* get the subproblem variables */
619  for( i = 0; i < nvars; i++ )
620  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
621 
622  /* free hash map */
623  SCIPhashmapFree(&varmapfw);
624 
625  /* setup parameters of subSCIP */
626  /* do not abort subproblem on CTRL-C */
627  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
628 
629 #ifdef SCIP_DEBUG
630  /* for debugging RENS, enable MIP output */
631  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
632  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
633 #else
634  /* disable output to console */
635  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
636 #endif
637 
638  /* set limits for the subproblem */
639  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nstallnodes) );
640  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", MAX(10, nstallnodes/10)) );
641  SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
642  SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
643 
644  /* forbid recursive call of heuristics and separators solving subMIPs */
645  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
646 
647  /* disable cutting plane separation */
648  SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) );
649 
650  /* disable expensive presolving */
651  SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) );
652 
653  /* use best estimate node selection */
654  if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
655  {
656  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
657  }
658 
659  /* use inference branching */
660  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
661  {
662  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
663  }
664 
665  /* disable conflict analysis */
666  if( !SCIPisParamFixed(subscip, "conflict/enable") )
667  {
668  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", FALSE) );
669  }
670 
671  /* if there is already a solution, add an objective cutoff */
672  if( SCIPgetNSols(scip) > 0 )
673  {
674  SCIP_Real cutoff; /* objective cutoff for the subproblem */
675  SCIP_Real upperbound;
676 
677  assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) );
678 
679  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
680  if( !SCIPisInfinity(scip,-1.0*SCIPgetLowerbound(scip)) )
681  {
682  cutoff = (1-heurdata->minimprove)*SCIPgetUpperbound(scip) + heurdata->minimprove*SCIPgetLowerbound(scip);
683  }
684  else
685  {
686  if( SCIPgetUpperbound ( scip ) >= 0 )
687  cutoff = ( 1 - heurdata->minimprove ) * SCIPgetUpperbound ( scip );
688  else
689  cutoff = ( 1 + heurdata->minimprove ) * SCIPgetUpperbound ( scip );
690  }
691  cutoff = MIN(upperbound, cutoff );
692  SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
693  }
694 
695  return SCIP_OKAY;
696 }
697 
698 
699 /**
700  * compare an extreme point (represented by a master variable) to the relaxation solution
701  */
702 static
704  SCIP* scip, /**< original SCIP data structure */
705  SCIP_VAR* mastervar, /**< master variable representing the extreme point */
706  int solblock, /**< block in which the relaxation solution should be compared, or -1 if all blocks of the extreme point should be considered */
707  int* neqpts, /**< for each original variable, count how many extreme points share its relaxation solution value */
708  SCIP_Bool* zeroblocks /**< for each block, the information whether it would be fixed entirely to zero */
709  )
710 {
711  int block; /* representative block the master variable belongs to */
712  int nblocks;
713  SCIP_VAR** origvars; /* original variables of the extreme point */
714  SCIP_Real* origvals; /* values of the original variables in the extreme point */
715  int norigvars; /* number of original variables of the extreme point */
716 
717  int i;
718  int j;
719  int k;
720 
721  assert(GCGvarIsMaster(mastervar));
722 
723  block = GCGvarGetBlock(mastervar);
724  assert(block >= 0);
725 
726  nblocks = GCGgetNPricingprobs(scip);
727 
728  /* get the actual extreme point */
729  origvars = GCGmasterVarGetOrigvars(mastervar);
730  origvals = GCGmasterVarGetOrigvals(mastervar);
731  norigvars = GCGmasterVarGetNOrigvars(mastervar);
732 
733  /* compare each extreme point value to the corresponding relaxation solution value */
734  for( i = 0; i < norigvars; ++i )
735  {
736  SCIP_VAR* pricingvar;
737  SCIP_VAR** pricingorigvars;
738  int npricingorigvars;
739 
740  if( SCIPvarGetType(origvars[i]) > SCIP_VARTYPE_INTEGER )
741  continue;
742 
743  /* get the corresponding pricing variable;
744  * needed to obtain original variables corresponding to the current one from other blocks
745  * (see below)
746  */
747  if( GCGoriginalVarIsLinking(origvars[i]) )
748  {
749  SCIP_VAR** linkingpricingvars = GCGlinkingVarGetPricingVars(origvars[i]);
750  pricingvar = linkingpricingvars[block];
751  }
752  else
753  pricingvar = GCGoriginalVarGetPricingVar(origvars[i]);
754 
755  assert(pricingvar != NULL);
756  assert(GCGvarIsPricing(pricingvar));
757 
758  /* get all original variables corresponding to the current one;
759  * this is necessary since in case of identical, aggregated blocks,
760  * the extreme point may belong to multiple blocks
761  */
762  pricingorigvars = GCGpricingVarGetOrigvars(pricingvar);
763  npricingorigvars = GCGpricingVarGetNOrigvars(pricingvar);
764  assert(pricingorigvars != NULL);
765  assert(npricingorigvars >= 0);
766 
767  for( j = 0; j < npricingorigvars; ++j )
768  {
769  int origblock;
770  int idx;
771  SCIP_Real solval;
772 
773  origblock = GCGvarGetBlock(pricingorigvars[j]);
774  assert(origblock != -1);
775 
776  if( solblock != -1 &&
777  ((origblock != -2 && origblock != solblock) || (origblock == -2 && !GCGisLinkingVarInBlock(pricingorigvars[j], solblock))) )
778  continue;
779 
780  idx = SCIPvarGetProbindex(pricingorigvars[j]);
781  assert(SCIPvarGetType(pricingorigvars[j]) <= SCIP_VARTYPE_INTEGER);
782  solval = SCIPgetRelaxSolVal(scip, pricingorigvars[j]);
783 
784  /* If a relaxation solution value is zero, we assumed that it is zero in all extreme points,
785  * so we need to decrease the counter if this is not the case
786  */
787  if( SCIPisZero(scip, solval) )
788  {
789  if( !SCIPisZero(scip, origvals[i]) )
790  --neqpts[idx];
791  }
792  else
793  {
794  if( SCIPisEQ(scip, solval, origvals[i]) )
795  ++neqpts[idx];
796 
797  /* The block will not be entirely fixed to zero, since the variable has nonzero relaxation solution value */
798  if( origblock != -2 )
799  zeroblocks[origblock] = FALSE;
800  else
801  {
802  /* For a linking variable, get all blocks it appears in */
803  SCIP_VAR** linkingpricingvars = GCGlinkingVarGetPricingVars(pricingorigvars[j]);
804  for( k = 0; k < nblocks; ++k )
805  if( linkingpricingvars[k] != NULL )
806  zeroblocks[k] = FALSE;
807  }
808  }
809  }
810  }
811 }
812 
813 /**
814  * compare all selected extreme points to the relaxation solution
815  */
816 static
818  SCIP* scip, /**< original SCIP data structure */
819  int* selection, /**< selected extreme points the heuristic will use, or NULL */
820  int nusedpts, /**< number of extreme points per block to be considered, or 0, or -1 */
821  int* neqpts, /**< for each original variable, count how many extreme points share its relaxation solution value */
822  SCIP_Bool* zeroblocks /**< for each block, the information whether it would be fixed entirely to zero */
823  )
824 {
825  SCIP* masterprob; /* master problem */
826  SCIP_VAR** mastervars; /* master variables */
827  int nmastervars; /* number of master variables */
828  int nblocks;
829 
830  int i;
831  int j;
832 
833  /* get master problem and its variables */
834  masterprob = GCGgetMasterprob(scip);
835  assert(masterprob != NULL);
836  SCIP_CALL( SCIPgetVarsData(masterprob, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
837  assert(mastervars != NULL);
838  assert(nmastervars >= 0);
839 
840  nblocks = GCGgetNPricingprobs(scip);
841 
842  if( nusedpts <= 0 )
843  {
844  assert(nusedpts == 0 || nusedpts == -1);
845 
846  for( i = 0; i < nmastervars; ++i )
847  {
848  SCIP_VAR* mastervar;
849 
850  /* get master variable */
851  mastervar = mastervars[i];
852 
853  /* ignore master variables which are just copies from original variables and no extreme points */
854  if( GCGvarGetBlock(mastervar) == -1 )
855  continue;
856 
857  /* ignore master variable if it is zero and only the nonzeroes should be considered */
858  if( nusedpts == 0 && SCIPisZero(scip, SCIPgetSolVal(masterprob, NULL, mastervar)) )
859  continue;
860 
861  compareOneExtremePoint(scip, mastervar, -1, neqpts, zeroblocks);
862  }
863  }
864  else
865  {
866  assert(selection != NULL);
867 
868  for( i = 0; i < nblocks; ++i )
869  {
870  /* compare the relaxation solution to the selected extreme points */
871  for( j = 0; j < nusedpts; ++j )
872  {
873  int selidx = i * nusedpts + j;
874  if( selection[selidx] != -1 )
875  {
876  SCIP_VAR* mastervar;
877 
878  /* get master variable */
879  mastervar = mastervars[selection[selidx]];
880  assert(mastervar != NULL);
881  assert(GCGvarGetBlock(mastervar) == GCGgetBlockRepresentative(scip, i));
882 
883  compareOneExtremePoint(scip, mastervar, i, neqpts, zeroblocks);
884  }
885  }
886  }
887  }
888 
889  return SCIP_OKAY;
890 }
891 
892 /** fix variables; for each variable, we evaluate the percentage of extreme points in which it has the same value
893  * as in the relaxation solution and fix it if the percentage exceeds a certain value
894  */
895 static
896 SCIP_RETCODE fixVariables(
897  SCIP* scip, /**< original SCIP data structure */
898  SCIP* subscip, /**< SCIP data structure for the subproblem */
899  SCIP_VAR** subvars, /**< the variables of the subproblem */
900  int* selection, /**< selected extreme points the heuristic will use, or NULL */
901  int* nactualpts, /**< number of points per block that have actually been selected */
902  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
903  SCIP_Real* intfixingrate, /**< percentage of integers that get actually fixed */
904  SCIP_Real* zerofixingrate, /**< percentage of variables fixed to zero */
905  SCIP_Bool* success /**< pointer to store whether the problem was created successfully */
906  )
907 {
908  SCIP_VAR** vars; /* original scip variables */
909 
910  int nblocks; /* number of blocks */
911  int nbinvars; /* number of binary variables in the original problem */
912  int nintvars; /* number of general integer variables */
913 
914  int* neqpts; /* for each original variable, count the number of
915  points where it has the same value as the relaxation solution */
916  SCIP_Bool* zeroblocks; /* blocks that would be entirely fixed to zero */
917  int fixingcounter; /* count how many original variables are fixed */
918  int zerocounter; /* count how many variables are fixed to zero */
919 
920  int i;
921  int j;
922 
923  /* check preconditions */
924  assert(scip != NULL);
925  assert(subscip != NULL);
926  assert(subvars != NULL);
927  assert(heurdata != NULL);
928  assert(selection != NULL || heurdata->nusedpts < 0);
929  assert(nactualpts != NULL);
930  assert(intfixingrate != NULL);
931  assert(zerofixingrate != NULL);
932  assert(success != NULL);
933 
934  /* get required data of the original problem */
935  SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
936 
937  nblocks = GCGgetNPricingprobs(scip);
938  fixingcounter = 0;
939  zerocounter = 0;
940 
941  *success = FALSE;
942 
943  /* allocate memory */
944  SCIP_CALL( SCIPallocBufferArray(scip, &neqpts, nbinvars + nintvars) );
945  SCIP_CALL( SCIPallocBufferArray(scip, &zeroblocks, nblocks) );
946 
947  for( i = 0; i < nblocks; ++i )
948  zeroblocks[i] = TRUE;
949 
950  /* initialize counters for identical solution values
951  *
952  * @note: Zero values of extreme points are not stored explicitly in the master
953  * variable data; therefore, we assume for each variable with solution value zero
954  * that each extreme point also has value zero, and we will later on decrease the
955  * counter for each point where this is not the case
956  */
957  for( i = 0; i < nbinvars + nintvars; ++i )
958  {
959  SCIP_VAR* var;
960  int block;
961  SCIP_Real solval;
962 
963  /* get variable, block and relaxation value */
964  var = vars[i];
965  assert(var != NULL);
966  block = GCGvarGetBlock(var);
967  solval = SCIPgetRelaxSolVal(scip, var);
968 
969  if( !SCIPisZero(scip, solval) || block == -1 )
970  neqpts[i] = 0;
971  else if( block == -2 )
972  {
973  SCIP_VAR** linkingpricingvars = GCGlinkingVarGetPricingVars(var);
974  neqpts[i] = 0;
975  for( j = 0; j < nblocks; ++j )
976  if( linkingpricingvars[j] != NULL )
977  neqpts[i] += nactualpts[j];
978  }
979  else
980  {
981  assert(block >= 0);
982  neqpts[i] = nactualpts[block];
983  }
984  }
985 
986  SCIP_CALL( compareExtremePointsToRelaxSol(scip, selection, heurdata->nusedpts, neqpts, zeroblocks) );
987 
988  /* try to fix the binary and general integer variables */
989  for( i = 0; i < nbinvars + nintvars; ++i )
990  {
991  SCIP_VAR* var;
992  int block; /* current block we are working in */
993  SCIP_Real solval;
994 
995  var = vars[i];
996  assert(GCGvarIsOriginal(var));
997  block = GCGvarGetBlock(var);
998  solval = SCIPgetRelaxSolVal(scip, var);
999 
1000  /* Variables which were directly copied from the original problem do not appear in any extreme point;
1001  * they are fixed like in the RENS heuristic
1002  */
1003  if( block == -1 )
1004  {
1005  if( SCIPisFeasIntegral(scip, solval) )
1006  {
1007  /* fix variable to current relaxation solution if it is integral;
1008  * use exact integral value, if the variable is only integral within numerical tolerances
1009  */
1010  solval = SCIPfloor(scip, solval + 0.5);
1011  SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[i], solval) );
1012  SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[i], solval) );
1013 
1014  fixingcounter++;
1015  if( SCIPisZero(scip, solval) )
1016  zerocounter++;
1017  }
1018  }
1019  /* For variables belonging to one or more blocks, we evaluate in how many percent of the
1020  * extreme points they have the same value as in the relaxation solution
1021  */
1022  else
1023  {
1024  int ntotalpts;
1025  SCIP_Real quoteqpts;
1026 
1027  assert(block == -2 || block >= 0);
1028 
1029  /* Calculate in how many extreme points the variable appears;
1030  * in case of linking variables, we need to consider points from all their blocks
1031  */
1032  if( block >= 0 )
1033  ntotalpts = nactualpts[block];
1034  else
1035  {
1036  SCIP_VAR** linkingpricingvars;
1037 
1038  assert(GCGoriginalVarIsLinking(var));
1039  linkingpricingvars = GCGlinkingVarGetPricingVars(var);
1040 
1041  ntotalpts = 0;
1042  for( j = 0; j < nblocks; ++j )
1043  if( linkingpricingvars[j] != NULL )
1044  ntotalpts += nactualpts[j];
1045  }
1046 
1047  assert(neqpts[i] <= ntotalpts);
1048  quoteqpts = (SCIP_Real) neqpts[i] / (SCIP_Real) MAX(ntotalpts,1);
1049 
1050  SCIPdebugMessage("Variable %s: %d/%d (%.2f percent) extreme points identical to relaxation solution (value=%g).\n",
1051  SCIPvarGetName(var), neqpts[i], ntotalpts, quoteqpts * 100, solval);
1052 
1053  /* The variable can be fixed if the relaxation value is shared by enough extreme points;
1054  * besides, we avoid fixing entire blocks to zero
1055  */
1056  if( quoteqpts >= heurdata->equalityrate && (block < 0 || !zeroblocks[block]) )
1057  {
1058  SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[i], solval) );
1059  SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[i], solval) );
1060 
1061  fixingcounter++;
1062  if( SCIPisZero(scip, solval) )
1063  zerocounter++;
1064  }
1065  }
1066  }
1067 
1068  *intfixingrate = (SCIP_Real) fixingcounter / (SCIP_Real) (MAX(nbinvars + nintvars, 1));
1069  *zerofixingrate = (SCIP_Real)zerocounter / MAX((SCIP_Real)fixingcounter, 1.0);
1070 
1071  /* If not enough variables were fixed, try to fix blocks which relaxation solution value zero,
1072  * until the minimum fixing rate is reached
1073  */
1074  while( *intfixingrate < heurdata->minfixingrate )
1075  {
1076  SCIPdebugMessage(" fixing rate only %5.2f --> trying to fix a zero block\n", *intfixingrate);
1077 
1078  /* get the next zero block */
1079  for( i = 0; i < nblocks; ++i )
1080  if( zeroblocks[i] )
1081  {
1082  /* fix variables */
1083  for( j = 0; j < nbinvars + nintvars; ++j )
1084  if( GCGvarGetBlock(vars[j]) == i )
1085  {
1086  SCIP_Real quoteqpts;
1087 
1088  /* evaluate percentage of extreme points having the same variable value as the relaxation solution */
1089  assert(SCIPisZero(scip, SCIPgetRelaxSolVal(scip, vars[j])));
1090  assert(neqpts[j] <= nactualpts[i]);
1091  quoteqpts = (SCIP_Real) neqpts[j] / (SCIP_Real) MAX(nactualpts[i],1);
1092 
1093  if( quoteqpts >= heurdata->equalityrate )
1094  {
1095  SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[j], 0.0) );
1096  SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[j], 0.0) );
1097 
1098  fixingcounter++;
1099  zerocounter++;
1100  }
1101  }
1102 
1103  zeroblocks[i] = FALSE;
1104  break;
1105  }
1106 
1107  *intfixingrate = (SCIP_Real)fixingcounter / (SCIP_Real)(MAX(nbinvars + nintvars, 1));
1108  *zerofixingrate = (SCIP_Real)zerocounter / MAX((SCIP_Real)fixingcounter, 1.0);
1109 
1110  if( i == nblocks )
1111  break;
1112  }
1113 
1114  /* if all variables were fixed or amount of fixed variables is insufficient, abort immediately */
1115  if( *intfixingrate < heurdata->minfixingrate )
1116  {
1117  SCIPstatisticPrintf("xprins statistic: fixed only %5.2f ( %5.2f zero) integer variables --> abort \n", *intfixingrate, *zerofixingrate);
1118  }
1119  if( fixingcounter == nbinvars + nintvars )
1120  {
1121  SCIPstatisticPrintf("xprins statistic: fixed all ( %5.2f zero) integer variables --> abort \n", *zerofixingrate);
1122  }
1123 
1124  *success = TRUE;
1125 
1126  /* free memory */
1127  SCIPfreeBufferArray(scip, &zeroblocks);
1128  SCIPfreeBufferArray(scip, &neqpts);
1129 
1130  return SCIP_OKAY;
1131 }
1132 
1133 
1134 /** creates a new solution for the original problem by copying the solution of the subproblem */
1135 static
1136 SCIP_RETCODE createNewSol(
1137  SCIP* scip, /**< original SCIP data structure */
1138  SCIP* subscip, /**< SCIP structure of the subproblem */
1139  SCIP_VAR** subvars, /**< the variables of the subproblem */
1140  SCIP_HEUR* heur, /**< primal heuristic structure */
1141  SCIP_SOL* subsol, /**< solution of the subproblem */
1142  SCIP_Bool* success /**< used to store whether new solution was found or not */
1143  )
1144 {
1145 #ifdef SCIP_STATISTIC
1146  SCIP_HEURDATA* heurdata;
1147 #endif
1148  SCIP_VAR** vars; /* the original problem's variables */
1149  int nvars;
1150  SCIP_SOL* newsol; /* solution to be created for the original problem */
1151  SCIP_Real* subsolvals; /* solution values of the subproblem */
1152 
1153  assert(scip != NULL);
1154  assert(subscip != NULL);
1155  assert(subvars != NULL);
1156  assert(subsol != NULL);
1157 
1158 #ifdef SCIP_STATISTIC
1159  /* get heuristic data */
1160  heurdata = SCIPheurGetData(heur);
1161  assert( heurdata != NULL );
1162 #endif
1163 
1164  /* get variables' data */
1165  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
1166  assert(nvars <= SCIPgetNOrigVars(subscip));
1167 
1168  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
1169 
1170  /* copy the solution */
1171  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
1172 
1173  /* create new solution for the original problem */
1174  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
1175  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
1176 
1177  SCIPstatisticPrintf("xprins statistic: Solution %13.6e found at node %"SCIP_LONGINT_FORMAT"\n",
1178  SCIPgetSolTransObj(scip, newsol), SCIPsolGetNodenum(subsol));
1179 
1180  /* try to add new solution to scip */
1181 #ifdef SCIP_STATISTIC
1182  if( !*success )
1183 #endif
1184  SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
1185 
1186 #ifdef SCIP_STATISTIC
1187  if( SCIPgetSolTransObj(scip, newsol) < heurdata->bestprimalbd )
1188  heurdata->bestprimalbd = SCIPgetSolTransObj(scip, newsol);
1189 
1190  SCIPstatisticPrintf("xprins statistic: Solution %13.6e found at node %"SCIP_LONGINT_FORMAT"\n",
1191  SCIPgetSolTransObj(scip, newsol), SCIPsolGetNodenum(subsol));
1192 #endif
1193 
1194  SCIP_CALL( SCIPfreeSol(scip, &newsol) );
1195 
1196  SCIPfreeBufferArray(scip, &subsolvals);
1197 
1198  return SCIP_OKAY;
1199 }
1200 
1201 /** updates heurdata after a run of crossover */
1202 static
1204  SCIP* scip, /**< original SCIP data structure */
1205  SCIP_HEURDATA* heurdata /**< primal heuristic data */
1206  )
1207 {
1208  /* increase number of failures, calculate next node at which crossover should be called and update actual solutions */
1209  heurdata->nfailures++;
1210  heurdata->nextnodenumber = (heurdata->nfailures <= 25
1211  ? SCIPgetNNodes(scip) + 100*(2LL << heurdata->nfailures) /*lint !e703*/
1212  : SCIP_LONGINT_MAX);
1213 }
1214 
1215 
1216 
1217 /*
1218  * Callback methods of primal heuristic
1219  */
1220 
1221 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
1222 static
1223 SCIP_DECL_HEURFREE(heurFreeXprins)
1224 { /*lint --e{715}*/
1225  SCIP_HEURDATA* heurdata;
1226 
1227  assert(heur != NULL);
1228  assert(scip != NULL);
1229 
1230  /* get heuristic data */
1231  heurdata = SCIPheurGetData(heur);
1232  assert(heurdata != NULL);
1233 
1234  /* free heuristic data */
1235  SCIPfreeMemory(scip, &heurdata);
1236  SCIPheurSetData(heur, NULL);
1237 
1238  return SCIP_OKAY;
1239 }
1240 
1241 /** initialization method of primal heuristic (called after problem was transformed) */
1242 static
1243 SCIP_DECL_HEURINIT(heurInitXprins)
1244 { /*lint --e{715}*/
1245  SCIP_HEURDATA* heurdata;
1246 
1247  assert(heur != NULL);
1248  assert(scip != NULL);
1249 
1250  /* get heuristic data */
1251  heurdata = SCIPheurGetData(heur);
1252  assert(heurdata != NULL);
1253 
1254  /* initialize data */
1255  heurdata->usednodes = 0;
1256  heurdata->nfailures = 0;
1257  heurdata->nextnodenumber = 0;
1258 
1259  /* create random number generator */
1260  SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen,
1261  SCIPinitializeRandomSeed(scip, DEFAULT_RANDSEED), TRUE) );
1262 
1263  return SCIP_OKAY;
1264 }
1265 
1266 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
1267 static
1268 SCIP_DECL_HEUREXIT(heurExitXprins)
1269 { /*lint --e{715}*/
1270  SCIP_HEURDATA* heurdata;
1271 
1272  assert(heur != NULL);
1273  assert(scip != NULL);
1274 
1275  /* get heuristic data */
1276  heurdata = SCIPheurGetData(heur);
1277  assert(heurdata != NULL);
1278 
1279  /* free random number generator */
1280  SCIPfreeRandom(scip, &heurdata->randnumgen);
1281 
1282  return SCIP_OKAY;
1283 }
1284 
1285 #ifdef SCIP_STATISTIC
1286 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
1287 static
1288 SCIP_DECL_HEURINITSOL(heurInitsolXprins)
1289 { /*lint --e{715}*/
1290  SCIP_HEURDATA* heurdata;
1291 
1292  assert(heur != NULL);
1293  assert(scip != NULL);
1294 
1295  /* get heuristic data */
1296  heurdata = SCIPheurGetData(heur);
1297  assert(heurdata != NULL);
1298 
1299  /* initialize statistical data */
1300  heurdata->avgfixrate = 0.0;
1301  heurdata->avgzerorate = 0.0;
1302  heurdata->totalsols = 0;
1303  heurdata->subsciptime = 0.0;
1304  heurdata->bestprimalbd = SCIPinfinity(scip);
1305 
1306  return SCIP_OKAY;
1307 }
1308 
1309 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
1310 static
1311 SCIP_DECL_HEUREXITSOL(heurExitsolXprins)
1312 { /*lint --e{715}*/
1313  SCIP_HEURDATA* heurdata;
1314  SCIP_Longint ncalls;
1315 
1316  assert(heur != NULL);
1317  assert(scip != NULL);
1318 
1319  /* get heuristic data */
1320  heurdata = SCIPheurGetData(heur);
1321  assert(heurdata != NULL);
1322 
1323  ncalls = SCIPheurGetNCalls(heur);
1324  heurdata->avgfixrate /= MAX((SCIP_Real)ncalls, 1.0);
1325  heurdata->avgzerorate /= MAX((SCIP_Real)ncalls, 1.0);
1326 
1327  /* print detailed statistics */
1328  SCIPstatisticPrintf("LNS Statistics -- %s:\n", SCIPheurGetName(heur));
1329  SCIPstatisticPrintf("Calls : %13"SCIP_LONGINT_FORMAT"\n", ncalls);
1330  SCIPstatisticPrintf("Failed Fixings : %13"SCIP_LONGINT_FORMAT"\n", heurdata->nfixfails);
1331  SCIPstatisticPrintf("Sols : %13"SCIP_LONGINT_FORMAT"\n", SCIPheurGetNSolsFound(heur));
1332  SCIPstatisticPrintf("Improving Sols : %13"SCIP_LONGINT_FORMAT"\n", SCIPheurGetNBestSolsFound(heur));
1333  SCIPstatisticPrintf("Total Sols : %13"SCIP_LONGINT_FORMAT"\n", heurdata->totalsols);
1334  SCIPstatisticPrintf("subSCIP time : %13.2f\n", heurdata->subsciptime);
1335  SCIPstatisticPrintf("subSCIP nodes : %13"SCIP_LONGINT_FORMAT"\n", heurdata->usednodes);
1336  SCIPstatisticPrintf("Avg. fixing rate : %13.2f\n", 100.0 * heurdata->avgfixrate);
1337  SCIPstatisticPrintf("Avg. zero rate : %13.2f\n", 100.0 * heurdata->avgzerorate);
1338  SCIPstatisticPrintf("Best primal bd. :");
1339  if( SCIPisInfinity(scip, heurdata->bestprimalbd) )
1340  SCIPstatisticPrintf(" infinity\n");
1341  else
1342  SCIPstatisticPrintf(" %13.6e\n", heurdata->bestprimalbd);
1343  SCIPstatisticPrintf("\n");
1344 
1345  return SCIP_OKAY;
1346 }
1347 #endif
1348 
1349 
1350 /** execution method of primal heuristic */
1351 static
1352 SCIP_DECL_HEUREXEC(heurExecXprins)
1353 { /*lint --e{715}*/
1354 
1355  SCIP* masterprob;
1356  SCIP_HEURDATA* heurdata;
1357 
1358  SCIP* subscip;
1359  SCIP_VAR** subvars;
1360 
1361  SCIP_Real memorylimit; /* memory limit for the subproblem */
1362  SCIP_Real timelimit; /* time limit for the subproblem */
1363  SCIP_Longint nstallnodes; /* node limit for the subproblem */
1364  SCIP_Real allfixingrate; /* percentage of all variables fixed */
1365  SCIP_Real intfixingrate; /* percentage of integer variables fixed */
1366  SCIP_Real zerofixingrate; /* percentage of variables fixed to zero */
1367 
1368  int* selection; /* selected extreme points the heuristic will use, or NULL */
1369  int* nactualpts; /* number of points per block that have actually been selected -- may be less than 'nusedpts' */
1370  int nblocks;
1371 
1372  SCIP_Bool success;
1373  SCIP_RETCODE retcode;
1374 
1375  int i;
1376 
1377  assert(heur != NULL);
1378  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1379  assert(scip != NULL);
1380  assert(result != NULL);
1381 
1382  /* get master problem */
1383  masterprob = GCGgetMasterprob(scip);
1384  assert(masterprob != NULL);
1385 
1386  nblocks = GCGgetNPricingprobs(scip);
1387 
1388  /* get heuristic data */
1389  heurdata = SCIPheurGetData(heur);
1390  assert(heurdata != NULL);
1391 
1392  *result = SCIP_DELAYED;
1393 
1394  /* do not execute the heuristic on invalid relaxation solutions
1395  * (which is the case if the node has been cut off)
1396  */
1397  if( !SCIPisRelaxSolValid(scip) )
1398  {
1399  SCIPdebugMessage("skipping Extreme Point RINS: invalid relaxation solution\n");
1400  return SCIP_OKAY;
1401  }
1402 
1403  /* only call heuristic, if an optimal LP solution is at hand */
1404  if( SCIPgetStage(masterprob) > SCIP_STAGE_SOLVING || SCIPgetLPSolstat(masterprob) != SCIP_LPSOLSTAT_OPTIMAL )
1405  {
1406  SCIPdebugMessage("skipping Extreme Point RINS: master LP not solved to optimality.\n");
1407  return SCIP_OKAY;
1408  }
1409 
1410  assert(SCIPhasCurrentNodeLP(masterprob));
1411 
1412  /* if heuristic should be delayed, wait until certain number of nodes is reached */
1413  if( SCIPgetNNodes(scip) < heurdata->nextnodenumber )
1414  return SCIP_OKAY;
1415 
1416  *result = SCIP_DIDNOTRUN;
1417 
1418  /* only continue with some fractional variables */
1419  if( SCIPgetNExternBranchCands(scip) == 0 )
1420  return SCIP_OKAY;
1421 
1422  /* check whether there is enough time and memory left */
1423  timelimit = 0.0;
1424  memorylimit = 0.0;
1425  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
1426  if( !SCIPisInfinity(scip, timelimit) )
1427  timelimit -= SCIPgetSolvingTime(scip);
1428  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
1429 
1430  /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
1431  if( !SCIPisInfinity(scip, memorylimit) )
1432  {
1433  memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
1434  memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
1435  }
1436 
1437  /* abort if no time is left or not enough memory to create a copy of SCIP, including external memory usage */
1438  if( timelimit <= 0.0 || memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
1439  return SCIP_OKAY;
1440 
1441  /* calculate the maximal number of branching nodes until heuristic is aborted */
1442  nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
1443 
1444  /* reward Crossover if it succeeded often */
1445  nstallnodes = (SCIP_Longint)
1446  (nstallnodes * (1.0 + 2.0*(SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur)+1.0)));
1447 
1448  /* count the setup costs for the sub-MIP as 100 nodes */
1449  nstallnodes -= 100 * SCIPheurGetNCalls(heur);
1450  nstallnodes += heurdata->nodesofs;
1451 
1452  /* determine the node limit for the current process */
1453  nstallnodes -= heurdata->usednodes;
1454  nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
1455 
1456  /* check whether we have enough nodes left to call subproblem solving */
1457  if( nstallnodes < heurdata->minnodes )
1458  {
1459  SCIPdebugMessage("skipping Extreme Point RINS: nstallnodes=%"SCIP_LONGINT_FORMAT", minnodes=%"SCIP_LONGINT_FORMAT"\n", nstallnodes, heurdata->minnodes);
1460  return SCIP_OKAY;
1461  }
1462 
1463  if( SCIPisStopped(scip) )
1464  return SCIP_OKAY;
1465 
1466  SCIPdebugMessage("Executing Extreme Point RINS heuristic ...\n");
1467 
1468  /* allocate memory */
1469  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, SCIPgetNVars(scip)) );
1470  SCIP_CALL( SCIPallocBufferArray(scip, &nactualpts, nblocks) );
1471  selection = NULL;
1472 
1473  if( heurdata->nusedpts > 0 )
1474  {
1475  /* allocate memory */
1476  SCIP_CALL( SCIPallocBufferArray(scip, &selection, nblocks * heurdata->nusedpts) );
1477 
1478  /* initialize empty selection */
1479  for( i = 0; i < nblocks * heurdata->nusedpts; ++i )
1480  selection[i] = -1;
1481 
1482  /* for each block, select extreme points (represented by master variables) to perform RINS */
1483  success = FALSE;
1484  if( heurdata->randomization )
1485  {
1486  SCIPdebugMessage("selecting extreme points randomly...\n");
1487  SCIP_CALL( selectExtremePointsRandomized(scip, heurdata, selection, nactualpts, &success) );
1488  if( !success )
1489  {
1490  SCIPdebugMessage(" --> unsuccessful!\n");
1491  }
1492  }
1493  if( !heurdata->randomization || !success )
1494  {
1495  SCIPdebugMessage("selecting extreme points deterministically...\n");
1496  SCIP_CALL( selectExtremePoints(scip, heurdata, selection, nactualpts, &success) );
1497  }
1498 
1499  /* do not execute heuristic if no new selection of extreme points was found */
1500  if( !success )
1501  {
1502  SCIPdebugMessage("no proper selection could be created - aborting heuristic.\n");
1503 
1504  updateFailureStatistic(scip, heurdata);
1505 
1506  /* free memory */
1507  SCIPfreeBufferArray(scip, &selection);
1508  SCIPfreeBufferArray(scip, &nactualpts);
1509  SCIPfreeBufferArray(scip, &subvars);
1510 
1511  return SCIP_OKAY;
1512  }
1513  }
1514  else
1515  {
1516  if( heurdata->randomization )
1517  {
1518  SCIPwarningMessage(scip, "Randomization not supported when number of selected extreme points is not constant -- ignoring parameter\n");
1519  }
1520 
1521  SCIP_CALL( countExtremePoints(scip, selection, heurdata->nusedpts, nactualpts) );
1522  }
1523 
1524  /* initialize the subproblem */
1525  SCIP_CALL( SCIPcreate(&subscip) );
1526  SCIP_CALL( setupSubproblem(scip, subscip, subvars, heurdata, nstallnodes, timelimit, memorylimit) );
1527  SCIPdebugMessage("XP RINS subproblem: %d vars, %d conss\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip));
1528 
1529  SCIPstatisticPrintf("xprins statistic: called at node %"SCIP_LONGINT_FORMAT"\n", SCIPgetNNodes(scip));
1530 
1531  /* fix variables the variables of the subproblem */
1532  SCIP_CALL( fixVariables(scip, subscip, subvars, selection, nactualpts, heurdata, &intfixingrate, &zerofixingrate, &success) );
1533 
1534 #ifdef SCIP_STATISTIC
1535  /* for final statistics */
1536  heurdata->avgfixrate += intfixingrate;
1537  heurdata->avgzerorate += zerofixingrate;
1538 #endif
1539 
1540  /* if creation of subscip was aborted (e.g. due to number of fixings), free subscip and abort */
1541  if( !success )
1542  {
1543  /* this run will be counted as a failure since the neighborhood of the
1544  * solution was not fruitful in the sense that it was too big
1545  */
1546  updateFailureStatistic(scip, heurdata);
1547 #ifdef SCIP_STATISTIC
1548  ++heurdata->nfixfails;
1549 #endif
1550  goto TERMINATE;
1551  }
1552 
1553  *result = SCIP_DIDNOTFIND;
1554 
1555  /* presolve the subproblem */
1556  retcode = SCIPpresolve(subscip);
1557 
1558  /* errors in solving the subproblem should not kill the overall solving process;
1559  * hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
1560  */
1561  if( retcode != SCIP_OKAY )
1562  {
1563 #ifndef NDEBUG
1564  SCIP_CALL( retcode );
1565 #endif
1566  SCIPwarningMessage(scip, "Error while presolving subproblem in XP RINS heuristic; sub-SCIP terminated with code <%d>\n",retcode);
1567  goto TERMINATE;
1568  }
1569 
1570  SCIPdebugMessage("XP RINS presolved subproblem: %d vars, %d conss, success=%u\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip), success);
1571 
1572  allfixingrate = (SCIPgetNOrigVars(subscip) - SCIPgetNVars(subscip)) / (SCIP_Real)SCIPgetNOrigVars(subscip);
1573 
1574  /* additional variables added in presolving may lead to the subSCIP having more variables than the original */
1575  allfixingrate = MAX(allfixingrate, 0.0);
1576 
1577  /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous)
1578  * to ensure that not only the MIP but also the LP relaxation is easy enough
1579  */
1580  if( allfixingrate >= heurdata->minfixingrate / 2.0 )
1581  {
1582  SCIP_SOL** subsols;
1583  int nsubsols;
1584 
1585  /* solve the subproblem */
1586  SCIPdebugMessage("subSCIP: Solving... (node limit = %lld, time limit = %.2g)\n", nstallnodes, timelimit);
1587 
1588  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
1589  * Hence in optimized mode, the return code is catched and a warning is printed, only in debug mode, SCIP will stop.
1590  */
1591 #ifdef NDEBUG
1592  retcode = SCIPsolve(subscip);
1593  if( retcode != SCIP_OKAY )
1594  {
1595  SCIPwarningMessage(scip, "Error while solving subproblem in XP RINS heuristic; sub-SCIP terminated with code <%d>\n",
1596  retcode);
1597  }
1598 #else
1599  SCIP_CALL( SCIPsolve(subscip) );
1600 #endif
1601 
1602 #ifdef SCIP_STATISTIC
1603  heurdata->usednodes += SCIPgetNNodes(subscip);
1604  heurdata->subsciptime += SCIPgetTotalTime(subscip);
1605 #endif
1606 
1607  /* check, whether a solution was found;
1608  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
1609  */
1610  nsubsols = SCIPgetNSols(subscip);
1611  subsols = SCIPgetSols(subscip);
1612  success = FALSE;
1613 #ifdef SCIP_STATISTIC
1614  heurdata->totalsols += nsubsols;
1615  for( i = 0; i < nsubsols; ++i )
1616 #else
1617  for( i = 0; i < nsubsols && !success; ++i )
1618 #endif
1619  {
1620  SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) );
1621  if( success )
1622  *result = SCIP_FOUNDSOL;
1623  }
1624 
1625  SCIPstatisticPrintf("xprins statistic: fixed %6.3f integer variables ( %6.3f zero), %6.3f all variables, needed %6.1f sec (SCIP time: %6.1f sec), %"SCIP_LONGINT_FORMAT" nodes, found %d solutions, solution %10.4f found at node %"SCIP_LONGINT_FORMAT"\n",
1626  intfixingrate, zerofixingrate, allfixingrate, SCIPgetSolvingTime(subscip), SCIPgetSolvingTime(scip), SCIPgetNNodes(subscip), nsubsols,
1627  success ? SCIPgetPrimalbound(scip) : SCIPinfinity(scip), nsubsols > 0 ? SCIPsolGetNodenum(SCIPgetBestSol(subscip)) : -1 );
1628 
1629  if( !success )
1630  {
1631  /* if no new solution was found, run was a failure */
1632  updateFailureStatistic(scip, heurdata);
1633  SCIPdebugMessage(" -> no subMIP solution found - subSCIP status is %d\n", SCIPgetStatus(subscip));
1634  }
1635  }
1636  else
1637  {
1638  SCIPstatisticPrintf("xprins statistic: fixed only %6.3f integer variables ( %6.3f zero), %6.3f all variables --> abort \n", intfixingrate, zerofixingrate, allfixingrate);
1639  }
1640 
1641 TERMINATE:
1642  /* free memory */
1643  SCIP_CALL( SCIPfree(&subscip) );
1644  SCIPfreeBufferArrayNull(scip, &selection);
1645  SCIPfreeBufferArray(scip, &nactualpts);
1646  SCIPfreeBufferArray(scip, &subvars);
1647 
1648  return SCIP_OKAY;
1649 }
1650 
1651 
1652 
1653 /*
1654  * primal heuristic specific interface methods
1655  */
1656 
1657 /** creates the Extreme Point RINS primal heuristic and includes it in SCIP */
1659  SCIP* scip /**< SCIP data structure */
1660  )
1661 {
1662  SCIP_HEURDATA* heurdata;
1663  SCIP_HEUR* heur;
1664 
1665  /* create Extreme Point RINS primal heuristic data */
1666  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
1667 
1668  /* include primal heuristic */
1669  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1671  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecXprins, heurdata) );
1672 
1673  assert(heur != NULL);
1674 
1675  /* set non-NULL pointers to callback methods */
1676  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeXprins) );
1677  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitXprins) );
1678  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitXprins) );
1679 #ifdef SCIP_STATISTIC
1680  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolXprins) );
1681  SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolXprins) );
1682 #endif
1683 
1684  /* add Extreme Point RINS primal heuristic parameters */
1685 
1686  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/"HEUR_NAME"/equalityrate",
1687  "minimum percentage of coincidence of relaxation and extreme pts",
1688  &heurdata->equalityrate, FALSE, DEFAULT_EQUALITYRATE, 0.0, 1.0, NULL, NULL) );
1689 
1690  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/"HEUR_NAME"/nodesofs",
1691  "number of nodes added to the contingent of the total nodes",
1692  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1693 
1694  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/"HEUR_NAME"/maxnodes",
1695  "maximum number of nodes to regard in the subproblem",
1696  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1697 
1698  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/"HEUR_NAME"/minnodes",
1699  "minimum number of nodes required to start the subproblem",
1700  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1701 
1702  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/"HEUR_NAME"/nusedpts",
1703  "number of extreme pts per block that will be taken into account (-1: all; 0: all which contribute to current relaxation solution)",
1704  &heurdata->nusedpts, FALSE, DEFAULT_NUSEDPTS, -1, INT_MAX, NULL, NULL) );
1705 
1706  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/"HEUR_NAME"/nodesquot",
1707  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1708  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1709 
1710  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/"HEUR_NAME"/minfixingrate",
1711  "minimum percentage of integer variables that have to be fixed",
1712  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
1713 
1714  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/"HEUR_NAME"/minimprove",
1715  "factor by which crossover should at least improve the incumbent",
1716  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1717 
1718  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/"HEUR_NAME"/randomization",
1719  "should the choice which sols to take be randomized?",
1720  &heurdata->randomization, TRUE, DEFAULT_RANDOMIZATION, NULL, NULL) );
1721 
1722  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/"HEUR_NAME"/copycuts",
1723  "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
1724  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
1725 
1726  return SCIP_OKAY;
1727 }
int GCGgetBlockRepresentative(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4023
#define HEUR_FREQ
Definition: heur_xprins.c:51
static SCIP_DECL_HEURINITSOL(heurInitsolGcgdins)
Definition: heur_gcgdins.c:485
int GCGmasterVarGetNOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:886
GCG interface methods.
SCIP_Bool GCGvarIsMaster(SCIP_VAR *var)
Definition: gcgvar.c:150
SCIP_Real minimprove
Definition: heur_gcgdins.c:80
#define DEFAULT_NODESOFS
Definition: heur_xprins.c:62
#define DEFAULT_MINFIXINGRATE
Definition: heur_xprins.c:61
static SCIP_RETCODE setupSubproblem(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEURDATA *heurdata, SCIP_Longint nstallnodes, SCIP_Real timelimit, SCIP_Real memorylimit)
Definition: heur_xprins.c:572
#define HEUR_DESC
Definition: heur_xprins.c:48
SCIP_Bool GCGisLinkingVarInBlock(SCIP_VAR *var, int block)
Definition: gcgvar.c:1064
static SCIP_DECL_HEURINIT(heurInitXprins)
Definition: heur_xprins.c:1243
SCIP_VAR ** GCGmasterVarGetOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:908
SCIP_Real * GCGmasterVarGetOrigvals(SCIP_VAR *var)
Definition: gcgvar.c:932
int GCGvarGetBlock(SCIP_VAR *var)
Definition: gcgvar.c:1033
static void updateFailureStatistic(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_xprins.c:1203
#define DEFAULT_COPYCUTS
Definition: heur_xprins.c:68
SCIP_Bool GCGvarIsPricing(SCIP_VAR *var)
Definition: gcgvar.c:134
SCIP_Bool copycuts
Definition: heur_gcgdins.c:89
SCIP_Longint nodesofs
Definition: heur_gcgdins.c:76
static SCIP_RETCODE compareExtremePointsToRelaxSol(SCIP *scip, int *selection, int nusedpts, int *neqpts, SCIP_Bool *zeroblocks)
Definition: heur_xprins.c:817
SCIP_Real equalityrate
Definition: heur_xprins.c:82
static SCIP_DECL_HEUREXEC(heurExecXprins)
Definition: heur_xprins.c:1352
SCIP_VAR * GCGoriginalVarGetPricingVar(SCIP_VAR *var)
Definition: gcgvar.c:216
static SCIP_DECL_HEUREXIT(heurExitXprins)
Definition: heur_xprins.c:1268
int GCGgetNPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3979
SCIP_RANDNUMGEN * randnumgen
SCIP_Bool GCGvarIsOriginal(SCIP_VAR *var)
Definition: gcgvar.c:166
SCIP_Longint nextnodenumber
#define DEFAULT_MINIMPROVE
Definition: heur_xprins.c:59
#define HEUR_DISPCHAR
Definition: heur_xprins.c:49
SCIP * GCGgetMasterprob(SCIP *scip)
Definition: relax_gcg.c:3920
static SCIP_RETCODE countExtremePoints(SCIP *scip, int *selection, int nusedpts, int *nactualpts)
Definition: heur_xprins.c:515
#define DEFAULT_RANDSEED
Definition: heur_xprins.c:71
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEUR *heur, SCIP_SOL *subsol, SCIP_Bool *success)
Definition: heur_xprins.c:1136
Extreme Point RINS.
#define DEFAULT_NUSEDPTS
Definition: heur_xprins.c:64
int GCGpricingVarGetNOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:997
SCIP_Longint maxnodes
Definition: heur_gcgdins.c:77
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, int *selection, int *nactualpts, SCIP_HEURDATA *heurdata, SCIP_Real *intfixingrate, SCIP_Real *zerofixingrate, SCIP_Bool *success)
Definition: heur_xprins.c:896
#define DEFAULT_NODESQUOT
Definition: heur_xprins.c:63
#define HEUR_TIMING
Definition: heur_xprins.c:54
int GCGgetNIdenticalBlocks(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4053
SCIP_RETCODE SCIPincludeHeurXprins(SCIP *scip)
Definition: heur_xprins.c:1658
static SCIP_RETCODE selectExtremePoints(SCIP *scip, SCIP_HEURDATA *heurdata, int *selection, int *nactualpts, SCIP_Bool *success)
Definition: heur_xprins.c:123
static SCIP_DECL_HEURFREE(heurFreeXprins)
Definition: heur_xprins.c:1223
unsigned int nfailures
#define DEFAULT_MAXNODES
Definition: heur_xprins.c:58
#define HEUR_PRIORITY
Definition: heur_xprins.c:50
#define HEUR_FREQOFS
Definition: heur_xprins.c:52
SCIP_VAR ** GCGpricingVarGetOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:1015
static SCIP_DECL_HEUREXITSOL(heurExitsolGcgdins)
Definition: heur_gcgdins.c:529
static SCIP_RETCODE selectExtremePointsRandomized(SCIP *scip, SCIP_HEURDATA *heurdata, int *selection, int *nactualpts, SCIP_Bool *success)
Definition: heur_xprins.c:362
SCIP_Bool GCGmasterVarIsRay(SCIP_VAR *var)
Definition: gcgvar.c:852
#define HEUR_NAME
Definition: heur_xprins.c:47
SCIP_Bool GCGoriginalVarIsLinking(SCIP_VAR *var)
Definition: gcgvar.c:182
SCIP_Bool GCGisPricingprobRelevant(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4000
static void compareOneExtremePoint(SCIP *scip, SCIP_VAR *mastervar, int solblock, int *neqpts, SCIP_Bool *zeroblocks)
Definition: heur_xprins.c:703
#define DEFAULT_MINNODES
Definition: heur_xprins.c:60
SCIP_Longint usednodes
Definition: heur_gcgdins.c:81
SCIP_VAR ** GCGlinkingVarGetPricingVars(SCIP_VAR *var)
Definition: gcgvar.c:409
SCIP_Longint minnodes
Definition: heur_gcgdins.c:78
#define DEFAULT_EQUALITYRATE
Definition: heur_xprins.c:57
SCIP_Bool randomization
#define HEUR_USESSUBSCIP
Definition: heur_xprins.c:55
SCIP_Real minfixingrate
Definition: heur_gcgrens.c:84
#define HEUR_MAXDEPTH
Definition: heur_xprins.c:53
SCIP_Real nodesquot
Definition: heur_gcgdins.c:82
#define DEFAULT_RANDOMIZATION
Definition: heur_xprins.c:67