Scippy

GCG

Branch-and-Price & Column Generation for Everyone

heur_greedycolsel.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_greedycolsel.c
29  * @brief greedy column selection primal heuristic
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 
37 #include "heur_greedycolsel.h"
38 #include "gcg.h"
39 #include "pricer_gcg.h"
40 
41 
42 #define HEUR_NAME "greedycolsel"
43 #define HEUR_DESC "greedy column selection heuristic"
44 #define HEUR_DISPCHAR 'e'
45 #define HEUR_PRIORITY 0
46 #define HEUR_FREQ 1
47 #define HEUR_FREQOFS 0
48 #define HEUR_MAXDEPTH -1
49 /** @todo should heuristic be called during the pricing loop or only after solving a node relaxation? */
50 #define HEUR_TIMING SCIP_HEURTIMING_DURINGLPLOOP | SCIP_HEURTIMING_DURINGPRICINGLOOP
51 #define HEUR_USESSUBSCIP FALSE
52 
53 #define DEFAULT_MINCOLUMNS 200 /**< minimum number of columns to regard in the master problem */
54 #define DEFAULT_USEOBJ FALSE /**< use objective coefficients as tie breakers */
55 
56 
57 
58 
59 /*
60  * Data structures
61  */
62 
63 /** primal heuristic data */
64 struct SCIP_HeurData
65 {
66  /* parameters */
67  int mincolumns; /**< minimum number of columns to regard in the master problem */
68  SCIP_Bool useobj; /**< use objective coefficients as tie breakers */
69 
70  /* data */
71  SCIP_VAR** zerovars; /**< array of master variables corresponding to zero solutions */
72  int maxzerovars; /**< capacity of zerovars */
73  int lastncols; /**< number of columns in the last call of the heuristic */
74 };
75 
76 
77 
78 
79 /*
80  * Local methods
81  */
82 
83 
84 /** how would the number of violated rows change if mastervar were increased? */
85 static
87  SCIP* scip,
88  SCIP_Real* activities,
89  SCIP_VAR* mastervar
90  )
91 {
92  SCIP_COL* col;
93  SCIP_ROW** colrows;
94  SCIP_Real* colvals;
95  int ncolrows;
96  int violchange;
97 
98  int r;
99 
100  /* get the rows in which the master variable appears (only these must be regarded) */
101  col = SCIPvarGetCol(mastervar);
102  colrows = SCIPcolGetRows(col);
103  colvals = SCIPcolGetVals(col);
104  ncolrows = SCIPcolGetNLPNonz(col);
105  assert(ncolrows == 0 || (colrows != NULL && colvals != NULL));
106 
107  violchange = 0;
108  for( r = 0; r < ncolrows; r++ )
109  {
110  SCIP_ROW* row;
111  int rowpos;
112 
113  row = colrows[r];
114  rowpos = SCIProwGetLPPos(row);
115  assert(-1 <= rowpos);
116 
117  if( rowpos >= 0 && !SCIProwIsLocal(row) )
118  {
119  SCIP_Real oldactivity;
120  SCIP_Real newactivity;
121 
122  oldactivity = activities[rowpos];
123  newactivity = oldactivity + colvals[r];
124 
125  if( SCIPisFeasLT(scip, oldactivity, SCIProwGetLhs(row)) || SCIPisFeasGT(scip, oldactivity, SCIProwGetRhs(row)) )
126  {
127  if( SCIPisFeasGE(scip, newactivity, SCIProwGetLhs(row)) && SCIPisFeasLE(scip, oldactivity, SCIProwGetRhs(row)) )
128  violchange--;
129  }
130  else
131  {
132  if( SCIPisFeasLT(scip, newactivity, SCIProwGetLhs(row)) || SCIPisFeasGT(scip, newactivity, SCIProwGetRhs(row)) )
133  violchange++;
134  }
135  }
136  }
137 
138  return violchange;
139 }
140 
141 /** get the index of the "best" master variable w.r.t. pseudo costs */
142 static
143 SCIP_RETCODE getBestMastervar(
144  SCIP* scip,
145  SCIP_SOL* mastersol,
146  SCIP_Real* activities,
147  int* blocknr,
148  SCIP_Bool* ignored,
149  SCIP_Bool useobj,
150  int* index,
151  int* violchange
152  )
153 {
154  SCIP* origprob;
155  SCIP_VAR** mastervars;
156  int nmastervars;
157 
158  int i;
159  int tmpviolchange;
160  SCIP_Real tmpobj;
161  SCIP_Real curobj;
162 
163  /* get original problem */
164  origprob = GCGmasterGetOrigprob(scip);
165  assert(origprob != NULL);
166 
167  /* get variable data of the master problem */
168  SCIP_CALL( SCIPgetVarsData(scip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
169  assert(nmastervars >= 0);
170 
171  *index = -1;
172  *violchange = INT_MAX;
173  curobj = SCIPinfinity(scip);
174 
175  for( i = nmastervars - 1; i >= 0; i-- )
176  {
177  SCIP_VAR* mastervar;
178  int block;
179 
180  mastervar = mastervars[i];
181  assert(GCGvarIsMaster(mastervar));
182  block = GCGvarGetBlock(mastervar);
183 
184  /** @todo handle copied original variables and linking variables */
185  if( block < 0 )
186  continue;
187 
188  /** @todo handle rays */
189  if( GCGmasterVarIsRay(mastervar) )
190  continue;
191 
192  /* ignore the master variable if the corresponding block is already full
193  * or which are fixed
194  */
195  if( blocknr[block] < GCGgetNIdenticalBlocks(origprob, block )
196  && !ignored[i]
197  && !SCIPisEQ(scip, SCIPvarGetLbLocal(mastervar), SCIPvarGetUbLocal(mastervar))
198  && SCIPisFeasGE(scip, SCIPgetSolVal(scip, mastersol, mastervar), SCIPvarGetUbLocal(mastervar)) )
199  {
200  tmpviolchange = getViolationChange(scip, activities, mastervar);
201  tmpobj = SCIPvarGetObj(mastervar);
202  if( tmpviolchange < *violchange ||
203  (tmpviolchange == *violchange && SCIPisLE(scip, tmpobj, curobj) && useobj) )
204  {
205  *index = i;
206  *violchange = tmpviolchange;
207  curobj = tmpobj;
208  }
209  }
210  }
211 
212  return SCIP_OKAY;
213 }
214 
215 /** update activities */
216 static
217 SCIP_RETCODE updateActivities(
218  SCIP* scip,
219  SCIP_Real* activities,
220  SCIP_VAR* mastervar
221  )
222 {
223  SCIP_COL* col;
224  SCIP_ROW** colrows;
225  SCIP_Real* colvals;
226  int ncolrows;
227 
228  int r;
229 
230  assert(activities != NULL);
231 
232  col = SCIPvarGetCol(mastervar);
233  colrows = SCIPcolGetRows(col);
234  colvals = SCIPcolGetVals(col);
235  ncolrows = SCIPcolGetNLPNonz(col);
236  assert(ncolrows == 0 || (colrows != NULL && colvals != NULL));
237 
238  for( r = 0; r < ncolrows; ++r )
239  {
240  SCIP_ROW* row = colrows[r];
241  int rowpos = SCIProwGetLPPos(row);
242 
243  assert(-1 <= rowpos);
244 
245  if( rowpos >= 0 && !SCIProwIsLocal(row) )
246  {
247  SCIP_Real oldactivity;
248  SCIP_Real newactivity;
249 
250  assert(SCIProwIsInLP(row));
251 
252  /* update row activity */
253  oldactivity = activities[rowpos];
254  newactivity = oldactivity + colvals[r];
255  if( SCIPisInfinity(scip, newactivity) )
256  newactivity = SCIPinfinity(scip);
257  else if( SCIPisInfinity(scip, -newactivity) )
258  newactivity = -SCIPinfinity(scip);
259  activities[rowpos] = newactivity;
260  }
261  }
262 
263  return SCIP_OKAY;
264 }
265 
266 /** for a given block, search if there is a master variable corresponding to the zero solution;
267  * @todo it would be more efficient to "mark" master variables as being trivial */
268 static
269 SCIP_RETCODE searchZeroMastervar(
270  SCIP* scip,
271  int block,
272  SCIP_VAR** zeromastervar
273  )
274 {
275  SCIP_VAR** mastervars;
276  int nmastervars;
277 
278  int i;
279  int j;
280 
281  /* get variable data of the master problem */
282  SCIP_CALL( SCIPgetVarsData(scip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
283 
284  *zeromastervar = NULL;
285 
286  /* go through all master variables */
287  for( i = 0; i < nmastervars && *zeromastervar == NULL; ++i )
288  {
289  SCIP_VAR* mastervar = mastervars[i];
290  int b = GCGvarGetBlock(mastervar);
291 
292  /* only regard master variables belonging to the block we are searching for */
293  if( b == block )
294  {
295  SCIP_Real* origvals = GCGmasterVarGetOrigvals(mastervar);
296  int norigvars = GCGmasterVarGetNOrigvars(mastervar);
297 
298  /* check if all original variables contained in the master variable have value zero */
299  for( j = 0; j < norigvars; ++j )
300  if( !SCIPisZero(scip, origvals[j]) )
301  break;
302 
303  /* if so, we have found the right master variable */
304  if( j == norigvars )
305  *zeromastervar = mastervar;
306  }
307  }
308 
309  return SCIP_OKAY;
310 }
311 
312 /** for a given block, return the master variable corresponding to the zero solution,
313  * or NULL is there is no such variable available */
314 static
315 SCIP_RETCODE getZeroMastervar(
316  SCIP* scip,
317  SCIP_HEURDATA* heurdata,
318  int block,
319  SCIP_VAR** zeromastervar
320  )
321 {
322  /* if no zero solution is known for the block, look if a master variable has been added
323  * and remember the variable for future use */
324  if( heurdata->zerovars[block] == NULL )
325  SCIP_CALL( searchZeroMastervar(scip, block, zeromastervar) );
326  else
327  *zeromastervar = heurdata->zerovars[block];
328 
329  return SCIP_OKAY;
330 }
331 
332 
333 
334 
335 /*
336  * Callback methods of primal heuristic
337  */
338 
339 
340 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
341 #define heurCopyGreedycolsel NULL
342 
343 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
344 static
345 SCIP_DECL_HEURFREE(heurFreeGreedycolsel)
346 { /*lint --e{715}*/
347  SCIP_HEURDATA* heurdata;
348 
349  assert(heur != NULL);
350  assert(scip != NULL);
351 
352  /* get heuristic data */
353  heurdata = SCIPheurGetData(heur);
354  assert(heurdata != NULL);
355 
356  /* free heuristic data */
357  SCIPfreeBlockMemory(scip, &heurdata);
358  SCIPheurSetData(heur, NULL);
359 
360  return SCIP_OKAY;
361 }
362 
363 
364 /** initialization method of primal heuristic (called after problem was transformed) */
365 static
366 SCIP_DECL_HEURINIT(heurInitGreedycolsel)
367 { /*lint --e{715}*/
368  SCIP* origprob;
369  SCIP_HEURDATA* heurdata;
370  int nblocks;
371 
372  int i;
373 
374  assert(heur != NULL);
375  assert(scip != NULL);
376 
377  /* get original problem */
378  origprob = GCGmasterGetOrigprob(scip);
379  assert(origprob != NULL);
380 
381  /* get heuristic's data */
382  heurdata = SCIPheurGetData(heur);
383  assert(heurdata != NULL);
384 
385  /* get number of blocks */
386  nblocks = GCGgetNPricingprobs(origprob);
387 
388  heurdata->lastncols = 0;
389 
390  /* allocate memory and initialize array with NULL pointers */
391  if( nblocks > 0 )
392  {
393  heurdata->maxzerovars = SCIPcalcMemGrowSize(scip, nblocks);
394  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->zerovars, heurdata->maxzerovars) );
395  }
396 
397  for( i = 0; i < nblocks; ++i )
398  heurdata->zerovars[i] = NULL;
399 
400  return SCIP_OKAY;
401 }
402 
403 
404 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
405 static
406 SCIP_DECL_HEUREXIT(heurExitGreedycolsel)
407 { /*lint --e{715}*/
408  SCIP_HEURDATA* heurdata;
409 
410  assert(heur != NULL);
411  assert(scip != NULL);
412 
413  /* get heuristic data */
414  heurdata = SCIPheurGetData(heur);
415  assert(heurdata != NULL);
416 
417  /* free memory */
418  SCIPfreeBlockMemoryArrayNull(scip, &heurdata->zerovars, heurdata->maxzerovars);
419 
420  return SCIP_OKAY;
421 }
422 
423 
424 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
425 #define heurInitsolGreedycolsel NULL
426 
427 
428 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
429 #define heurExitsolGreedycolsel NULL
430 
431 
432 /** execution method of primal heuristic */
433 static
434 SCIP_DECL_HEUREXEC(heurExecGreedycolsel)
435 { /*lint --e{715}*/
436  SCIP* origprob; /* SCIP structure of original problem */
437  SCIP_HEURDATA* heurdata; /* heuristic's data */
438  SCIP_ROW** lprows; /* LP rows of master problem */
439  SCIP_SOL* mastersol; /* working master solution */
440  SCIP_SOL* origsol; /* working original solution */
441  SCIP_VAR** mastervars;
442  SCIP_Real* activities; /* for each master LP row, activity of current master solution */
443  int* blocknr; /* for each pricing problem, block we are currently working in */
444  SCIP_Bool* ignored; /* for each master variable, store whether it has to be ignored */
445  SCIP_Bool allblocksfull; /* indicates if all blocks are full, i.e. all convexity constraints are satisfied */
446  SCIP_Bool masterfeas;
447  SCIP_Bool success;
448  int minnewcols; /* minimum number of new columns necessary for calling the heuristic */
449  int nlprows;
450  int nmastervars;
451  int nblocks;
452  int nviolrows;
453  int violchange;
454 
455  int i;
456  int j;
457  int k;
458  int index;
459 
460  assert(heur != NULL);
461  assert(scip != NULL);
462  assert(result != NULL);
463 
464  /* get original problem */
465  origprob = GCGmasterGetOrigprob(scip);
466  assert(origprob != NULL);
467 
468  /* get heuristic's data */
469  heurdata = SCIPheurGetData(heur);
470  assert(heurdata != NULL);
471 
472  *result = SCIP_DELAYED;
473 
474  /* get variable data of the master problem */
475  SCIP_CALL( SCIPgetVarsData(scip, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
476  assert(nmastervars >= 0);
477 
478  /* calculate minimum number of new columns necessary for calling the heuristic;
479  * this number is influenced by how successful the heuristic was in the past */
480  minnewcols = heurdata->mincolumns * (int) (1.0 * ((1.0 + SCIPheurGetNCalls(heur)) / (1.0 + SCIPheurGetNBestSolsFound(heur))));
481 
482  /* if there are not enough new columns since last call, abort heuristic */
483  if( nmastervars - heurdata->lastncols < minnewcols )
484  return SCIP_OKAY;
485 
486  *result = SCIP_DIDNOTFIND;
487 
488  SCIPdebugMessage("Executing Greedy Column Selection heuristic (nmastervars = %d) ...\n", nmastervars);
489 
490  /* get number of pricing problems */
491  nblocks = GCGgetNPricingprobs(origprob);
492  assert(nblocks >= 0);
493 
494  /* get master LP rows data */
495  SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );
496  assert(lprows != NULL);
497  assert(nlprows >= 0);
498 
499  /* allocate memory */
500  SCIP_CALL( SCIPallocBufferArray(scip, &blocknr, nblocks) );
501  SCIP_CALL( SCIPallocBufferArray(scip, &ignored, nmastervars) );
502  SCIP_CALL( SCIPallocBufferArray(scip, &activities, nlprows) );
503 
504  /* get memory for working solutions and row activities */
505  SCIP_CALL( SCIPcreateSol(scip, &mastersol, heur) );
506  SCIP_CALL( SCIPcreateSol(origprob, &origsol, heur) );
507 
508  /* initialize block and master variable information */
509  BMSclearMemoryArray(blocknr, nblocks);
510  BMSclearMemoryArray(ignored, nmastervars);
511  allblocksfull = FALSE;
512 
513  /* initialize activities with zero and get number of violated rows of zero master solution */
514  nviolrows = 0;
515  for( i = 0; i < nlprows; i++ )
516  {
517  SCIP_ROW* row;
518 
519  row = lprows[i];
520  assert(SCIProwGetLPPos(row) == i);
521 
522  if( !SCIProwIsLocal(row) )
523  {
524  activities[i] = 0;
525  if( SCIPisFeasLT(scip, 0.0, SCIProwGetLhs(row)) || SCIPisFeasGT(scip, 0.0, SCIProwGetRhs(row)) )
526  nviolrows++;
527  }
528  }
529 
530  SCIPdebugMessage(" -> %d master LP rows violated\n", nviolrows);
531 
532  masterfeas = FALSE;
533  success = FALSE;
534 
535  /* try to increase master variables until all blocks are full */
536  while( !allblocksfull && !success )
537  {
538  SCIP_VAR* mastervar;
539  SCIP_VAR** origvars;
540  SCIP_Real* origvals;
541  int norigvars;
542  int block;
543 
544  SCIP_CALL( getBestMastervar(scip, mastersol, activities, blocknr, ignored, heurdata->useobj, &index, &violchange) );
545  assert(index >= -1 && index < nmastervars);
546 
547  /* if no master variable could be selected, abort */
548  if( index == -1 )
549  {
550  assert(violchange == INT_MAX);
551  SCIPdebugMessage(" -> no master variable could be selected\n");
552  break;
553  }
554 
555  /* get master variable */
556  mastervar = mastervars[index];
557  assert(GCGvarIsMaster(mastervar));
558  assert(GCGvarGetBlock(mastervar) >= 0);
559  assert(!GCGmasterVarIsRay(mastervar));
560 
561  /* get blocknr and original variables */
562  block = GCGvarGetBlock(mastervar);
563  origvars = GCGmasterVarGetOrigvars(mastervar);
564  origvals = GCGmasterVarGetOrigvals(mastervar);
565  norigvars = GCGmasterVarGetNOrigvars(mastervar);
566 
567  SCIPdebugMessage(" -> (block %d) selected master variable %s; violchange=%d\n",
568  block, SCIPvarGetName(mastervar), violchange);
569 
570  /* increase master value by one and increase solution values in current original solution accordingly */
571  SCIP_CALL( SCIPincSolVal(scip, mastersol, mastervar, 1.0) );
572 
573  /* update original solution accordingly */
574  for( i = 0; i < norigvars; i++ )
575  {
576  assert(GCGvarIsOriginal(origvars[i]));
577 
578  /* linking variables are treated differently; if the variable already has been assigned a value,
579  * one must check whether the value for the current block is the same (otherwise, the resulting
580  * solution will be infeasible in any case) */
581  if( GCGoriginalVarIsLinking(origvars[i]) )
582  {
583  SCIP_VAR** linkingpricingvars;
584  SCIP_Bool hasvalue;
585 
586  /* check whether linking variable has already been assigned a value */
587  linkingpricingvars = GCGlinkingVarGetPricingVars(origvars[i]);
588  hasvalue = FALSE;
589  for( j = 0; j < nblocks; j++ )
590  if( linkingpricingvars[j] != NULL )
591  if( blocknr[j] > 0 )
592  {
593  hasvalue = TRUE;
594  break;
595  }
596 
597  /* if the linking variable has not been assigned a value yet, assign a value to
598  * the variable and the corresponding copy in the master problem */
599  if( !hasvalue )
600  {
601  SCIP_VAR* linkingmastervar;
602 
603  linkingmastervar = GCGoriginalVarGetMastervars(origvars[i])[0];
604  assert(linkingmastervar != NULL);
605  SCIP_CALL( SCIPincSolVal(origprob, origsol, origvars[i], origvals[i]) );
606  SCIP_CALL( SCIPincSolVal(scip, mastersol, linkingmastervar, origvals[i]) );
607  }
608  /* otherwise, exclude the current master variable, if the point has a different value for it */
609  else
610  {
611  SCIP_Real value;
612  value = SCIPgetSolVal(origprob, origsol, origvars[i]);
613  if( !SCIPisEQ(origprob, value, origvals[i]) )
614  {
615  SCIPdebugMessage(" -> cannot use mastervar: origvar %s already has value %g in block %d, different to %g\n",
616  SCIPvarGetName(origvars[i]), value, j, origvals[i]);
617  ignored[index] = TRUE;
618  break;
619  }
620  }
621  }
622  else
623  {
624  SCIP_VAR* pricingvar;
625  SCIP_VAR** origpricingvars;
626 #ifndef NDEBUG
627  int norigpricingvars;
628 #endif
629 
630  /* if the variable is zero, nothing happens */
631  if( SCIPisZero(scip, origvals[i]) )
632  continue;
633 
634  pricingvar = GCGoriginalVarGetPricingVar(origvars[i]);
635  assert(pricingvar != NULL);
636  assert(GCGvarIsPricing(pricingvar));
637 
638  origpricingvars = GCGpricingVarGetOrigvars(pricingvar);
639 
640 #ifndef NDEBUG
641  norigpricingvars = GCGpricingVarGetNOrigvars(pricingvar);
642  assert(blocknr[block] < norigpricingvars);
643 #endif
644 
645  /* increase the corresponding value */
646  SCIP_CALL( SCIPincSolVal(origprob, origsol, origpricingvars[blocknr[block]], origvals[i]) );
647  }
648  }
649 
650  /* if the current master variable was set to be ignored, reset solution values and choose a new one */
651  if( ignored[index] )
652  {
653  SCIP_CALL( SCIPincSolVal(scip, mastersol, mastervar, -1.0) );
654  for( k = 0; k < i; k++ )
655  {
656  if( GCGoriginalVarIsLinking(origvars[k]) )
657  {
658  SCIP_VAR** linkingpricingvars;
659  SCIP_Bool hasvalue;
660 
661  /* check whether linking variable has already been assigned a value */
662  linkingpricingvars = GCGlinkingVarGetPricingVars(origvars[k]);
663  hasvalue = FALSE;
664  for( j = 0; j < nblocks; j++ )
665  {
666  if( linkingpricingvars[j] != NULL )
667  {
668  if( blocknr[j] > 0 && j != block )
669  {
670  hasvalue = TRUE;
671  break;
672  }
673  }
674  }
675 
676  /* if the linking variable has not had a value before, set it back to zero */
677  if( !hasvalue )
678  {
679  SCIP_VAR* linkingmastervar;
680 
681  linkingmastervar = GCGoriginalVarGetMastervars(origvars[k])[0];
682  SCIP_CALL( SCIPincSolVal(origprob, origsol, origvars[k], -origvals[k]) );
683  SCIP_CALL( SCIPincSolVal(scip, mastersol, linkingmastervar, -origvals[k]) );
684  }
685  }
686  else
687  {
688  SCIP_VAR* pricingvar;
689  SCIP_VAR** origpricingvars;
690 #ifndef NDEBUG
691  int norigpricingvars;
692 #endif
693 
694  pricingvar = GCGoriginalVarGetPricingVar(origvars[k]);
695  assert(pricingvar != NULL);
696  assert(GCGvarIsPricing(pricingvar));
697 
698  origpricingvars = GCGpricingVarGetOrigvars(pricingvar);
699 
700 #ifndef NDEBUG
701  norigpricingvars = GCGpricingVarGetNOrigvars(pricingvar);
702  assert(blocknr[block] < norigpricingvars);
703 #endif
704 
705  /* decrease the corresponding value */
706  SCIP_CALL( SCIPincSolVal(origprob, origsol, origpricingvars[blocknr[block]], -origvals[k]) );
707  }
708  }
709  continue;
710  }
711 
712  blocknr[block]++;
713 
714  /* try to add the solution to (original) solution pool */
715  SCIP_CALL( SCIPtrySol(origprob, origsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
716 
717  /* check if all blocks are full */
718  allblocksfull = TRUE;
719  for( i = 0; i < nblocks && allblocksfull; i++ )
720  {
721  int nidentblocks;
722 
723  nidentblocks = GCGgetNIdenticalBlocks(origprob, i);
724 
725  /* in case the solution is feasible but the block is not full,
726  * we need a zero solution for this block in order to generate
727  * a corresponding master solution */
728  if( success && blocknr[i] < nidentblocks )
729  {
730  SCIP_VAR* zeromastervar;
731 
732  /* fill the block with the zero solution */
733  zeromastervar = NULL;
734  SCIP_CALL( getZeroMastervar(scip, heurdata, i, &zeromastervar) );
735  if( zeromastervar != NULL )
736  {
737  SCIPdebugMessage(" -> (block %d) selected zero master variable %s (%d times)\n",
738  i, SCIPvarGetName(zeromastervar), nidentblocks - blocknr[i]);
739 
740  SCIP_CALL( SCIPincSolVal(scip, mastersol, zeromastervar,
741  (SCIP_Real) nidentblocks - blocknr[i]) );
742  blocknr[i] = nidentblocks;
743  }
744  }
745 
746  /** @todo >= should not happen, replace it by == ? */
747  if( !(blocknr[i] >= nidentblocks) )
748  allblocksfull = FALSE;
749  }
750 
751  /* if we found a solution for the original instance,
752  * also add the corresponding master solution */
753  if( success && allblocksfull )
754  {
755 #ifdef SCIP_DEBUG
756  SCIP_CALL( SCIPtrySol(scip, mastersol, TRUE, TRUE, TRUE, TRUE, TRUE, &masterfeas) );
757 #else
758  SCIP_CALL( SCIPtrySol(scip, mastersol, FALSE, FALSE, TRUE, TRUE, TRUE, &masterfeas) );
759 #endif
760  if( !masterfeas )
761  {
762  SCIPdebugMessage("WARNING: original solution feasible, but no solution has been added to master problem.\n");
763  }
764  }
765 
766  /* update number of violated rows and activities array */
767  nviolrows += violchange;
768  SCIP_CALL( updateActivities(scip, activities, mastervars[index]) );
769  }
770 
771  if( success )
772  {
773  *result = SCIP_FOUNDSOL;
774  SCIPdebugMessage("heuristic successful - feasible solution found, obj=%g\n",
775  SCIPgetSolOrigObj(origprob, origsol));
776  }
777  else
778  {
779  SCIPdebugMessage("no feasible solution found or solution already known; %d constraints violated.\n", nviolrows);
780  }
781 
782  SCIP_CALL( SCIPfreeSol(origprob, &origsol) );
783  SCIP_CALL( SCIPfreeSol(scip, &mastersol) );
784  SCIPfreeBufferArray(scip, &activities);
785  SCIPfreeBufferArray(scip, &ignored);
786  SCIPfreeBufferArray(scip, &blocknr);
787 
788  heurdata->lastncols = nmastervars;
789 
790  return SCIP_OKAY;
791 }
792 
793 
794 
795 
796 /*
797  * primal heuristic specific interface methods
798  */
799 
800 /** creates the greedy column selection primal heuristic and includes it in SCIP */
802  SCIP* scip /**< SCIP data structure */
803  )
804 {
805  SCIP_HEURDATA* heurdata;
806 
807  /* create greedy column selection primal heuristic data */
808  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
809 
810  heurdata->zerovars = NULL;
811  heurdata->maxzerovars = 0;
812 
813  /* include primal heuristic */
814  SCIP_CALL( SCIPincludeHeur(scip, HEUR_NAME, HEUR_DESC, HEUR_DISPCHAR, HEUR_PRIORITY, HEUR_FREQ, HEUR_FREQOFS,
816  heurCopyGreedycolsel, heurFreeGreedycolsel, heurInitGreedycolsel, heurExitGreedycolsel,
817  heurInitsolGreedycolsel, heurExitsolGreedycolsel, heurExecGreedycolsel,
818  heurdata) );
819 
820  /* add greedy column selection primal heuristic parameters */
821  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/"HEUR_NAME"/mincolumns",
822  "minimum number of columns to regard in the master problem",
823  &heurdata->mincolumns, FALSE, DEFAULT_MINCOLUMNS, 1, INT_MAX, NULL, NULL) );
824  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/"HEUR_NAME"/useobj",
825  "use objective coefficients as tie breakers",
826  &heurdata->useobj, TRUE, DEFAULT_USEOBJ, NULL, NULL) );
827 
828  return SCIP_OKAY;
829 }
static SCIP_RETCODE getZeroMastervar(SCIP *scip, SCIP_HEURDATA *heurdata, int block, SCIP_VAR **zeromastervar)
SCIP_VAR ** zerovars
int GCGmasterVarGetNOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:886
GCG interface methods.
SCIP_Bool GCGvarIsMaster(SCIP_VAR *var)
Definition: gcgvar.c:150
static SCIP_DECL_HEUREXEC(heurExecGreedycolsel)
SCIP_VAR ** GCGoriginalVarGetMastervars(SCIP_VAR *var)
Definition: gcgvar.c:587
static int getViolationChange(SCIP *scip, SCIP_Real *activities, SCIP_VAR *mastervar)
static SCIP_DECL_HEURFREE(heurFreeGreedycolsel)
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
#define HEUR_DESC
#define HEUR_NAME
#define HEUR_FREQOFS
SCIP_Bool GCGvarIsPricing(SCIP_VAR *var)
Definition: gcgvar.c:134
#define HEUR_MAXDEPTH
SCIP_VAR * GCGoriginalVarGetPricingVar(SCIP_VAR *var)
Definition: gcgvar.c:216
int GCGgetNPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3979
SCIP_Bool GCGvarIsOriginal(SCIP_VAR *var)
Definition: gcgvar.c:166
GCG variable pricer.
greedy column selection primal heuristic
#define HEUR_TIMING
#define DEFAULT_USEOBJ
static SCIP_RETCODE updateActivities(SCIP *scip, SCIP_Real *activities, SCIP_VAR *mastervar)
int GCGpricingVarGetNOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:997
#define heurInitsolGreedycolsel
#define HEUR_DISPCHAR
int GCGgetNIdenticalBlocks(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4053
SCIP * GCGmasterGetOrigprob(SCIP *scip)
#define HEUR_USESSUBSCIP
#define HEUR_PRIORITY
SCIP_VAR ** GCGpricingVarGetOrigvars(SCIP_VAR *var)
Definition: gcgvar.c:1015
SCIP_RETCODE SCIPincludeHeurGreedycolsel(SCIP *scip)
static SCIP_DECL_HEURINIT(heurInitGreedycolsel)
SCIP_Bool GCGmasterVarIsRay(SCIP_VAR *var)
Definition: gcgvar.c:852
#define HEUR_FREQ
static SCIP_RETCODE searchZeroMastervar(SCIP *scip, int block, SCIP_VAR **zeromastervar)
SCIP_Bool GCGoriginalVarIsLinking(SCIP_VAR *var)
Definition: gcgvar.c:182
#define DEFAULT_MINCOLUMNS
static SCIP_DECL_HEUREXIT(heurExitGreedycolsel)
static SCIP_RETCODE getBestMastervar(SCIP *scip, SCIP_SOL *mastersol, SCIP_Real *activities, int *blocknr, SCIP_Bool *ignored, SCIP_Bool useobj, int *index, int *violchange)
SCIP_VAR ** GCGlinkingVarGetPricingVars(SCIP_VAR *var)
Definition: gcgvar.c:409
#define heurExitsolGreedycolsel
#define heurCopyGreedycolsel