Scippy

GCG

Branch-and-Price & Column Generation for Everyone

class_pricingcontroller.cpp
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 class_pricingcontroller.cpp
29  * @brief pricing controller managing the pricing strategy
30  * @author Christian Puchert
31  */
32 
33 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34 
36 #include "pricer_gcg.h"
37 #include "class_pricingtype.h"
38 #include "gcg.h"
39 #include "scip_misc.h"
40 #include "branch_generic.h"
41 #include "cons_masterbranch.h"
42 #include "pub_gcgpqueue.h"
43 #include "pub_pricingjob.h"
44 #include "pub_pricingprob.h"
45 #include "pub_solver.h"
46 #include "pricingjob.h"
47 #include "pricingprob.h"
48 
49 #include "scip/scip.h"
50 #include "objscip/objscip.h"
51 
52 #include <exception>
53 
54 #define DEFAULT_HEURPRICINGITERS 1 /**< maximum number of heuristic pricing iterations per pricing call and problem */
55 #define DEFAULT_MAXHEURDEPTH -1 /**< maximum depth at which heuristic pricing should be performed (-1 for infinity) */
56 #define DEFAULT_SORTING 'r' /**< order by which the pricing problems should be sorted:
57  * 'i'ndices
58  * 'd'ual solutions of convexity constraints
59  * 'r'eliability from all previous rounds
60  * reliability from the 'l'ast nroundscol rounds
61  */
62 #define DEFAULT_NROUNDSCOL 15
63 #define DEFAULT_CHUNKSIZE INT_MAX /**< maximal number of pricing problems to be solved during one pricing loop */
64 #define DEFAULT_EAGERFREQ 10 /**< frequency at which all pricingproblems should be solved (0 to disable) */
65 
66 #define SCIP_CALL_EXC(x) do \
67  { \
68  SCIP_RETCODE _retcode_; \
69  if( (_retcode_ = (x)) != SCIP_OKAY ) \
70  { \
71  SCIPerrorMessage("Error <%d> in function call\n", _retcode_); \
72  throw std::exception(); \
73  } \
74  } \
75  while( FALSE )
76 
77 
78 namespace gcg {
79 
81  SCIP* scip
82  )
83 {
84  scip_ = scip;
85  pricingprobs = NULL;
86  npricingprobs = 0;
87  pricingjobs = NULL;
88  npricingjobs = 0;
89 
90  sorting = DEFAULT_SORTING;
91  nroundscol = DEFAULT_NROUNDSCOL;
92  chunksize = DEFAULT_CHUNKSIZE;
93  eagerfreq = DEFAULT_EAGERFREQ;
94 
95  pqueue = NULL;
96  maxniters = INT_MAX;
97  nchunks = 1;
98  curchunk = 0;
99 
100  pricingtype_ = NULL;
101 
102  eagerage = 0;
103  nsolvedprobs = 0;
104 }
105 
107 {
108 }
109 
111 {
112  SCIP* origprob = GCGmasterGetOrigprob(scip_);
113 
114  SCIP_CALL( SCIPaddIntParam(origprob, "pricing/masterpricer/heurpricingiters",
115  "maximum number of heuristic pricing iterations per pricing call and problem",
116  &heurpricingiters, FALSE, DEFAULT_HEURPRICINGITERS, 0, INT_MAX, NULL, NULL) );
117 
118  SCIP_CALL( SCIPaddIntParam(origprob, "pricing/masterpricer/maxheurdepth",
119  "maximum depth at which heuristic pricing should be performed (-1 for infinity)",
120  &maxheurdepth, FALSE, DEFAULT_MAXHEURDEPTH, -1, INT_MAX, NULL, NULL) );
121 
122  SCIP_CALL( SCIPaddCharParam(origprob, "pricing/masterpricer/sorting",
123  "order by which the pricing problems should be sorted ('i'ndices, 'd'ual solutions of convexity constraints, 'r'eliability from previous rounds, reliability from the 'l'ast nroundscol rounds)",
124  &sorting, FALSE, DEFAULT_SORTING, "dilr", NULL, NULL) );
125 
126  SCIP_CALL( SCIPaddIntParam(origprob, "pricing/masterpricer/nroundscol",
127  "number of previous pricing rounds for which the number of improving columns should be counted",
128  &nroundscol, TRUE, DEFAULT_NROUNDSCOL, 1, INT_MAX, NULL, NULL) );
129 
130  SCIP_CALL( SCIPaddIntParam(origprob, "pricing/masterpricer/chunksize",
131  "maximal number of pricing problems to be solved during one pricing loop",
132  &chunksize, TRUE, DEFAULT_CHUNKSIZE, 1, INT_MAX, NULL, NULL) );
133 
134  SCIP_CALL( SCIPaddIntParam(origprob, "pricing/masterpricer/eagerfreq",
135  "frequency at which all pricingproblems should be solved (0 to disable)",
136  &eagerfreq, FALSE, DEFAULT_EAGERFREQ, 0, INT_MAX, NULL, NULL) );
137 
138  return SCIP_OKAY;
139 }
140 
141 /** comparison operator for pricing jobs w.r.t. their solution priority */
142 SCIP_DECL_SORTPTRCOMP(Pricingcontroller::comparePricingjobs)
143 {
144  GCG_PRICINGJOB* pricingjob1;
145  GCG_PRICINGJOB* pricingjob2;
146  GCG_PRICINGPROB* pricingprob1;
147  GCG_PRICINGPROB* pricingprob2;
148  GCG_SOLVER* solver1;
149  GCG_SOLVER* solver2;
150 
151  pricingjob1 = (GCG_PRICINGJOB*) elem1;
152  pricingjob2 = (GCG_PRICINGJOB*) elem2;
153 
154  pricingprob1 = GCGpricingjobGetPricingprob(pricingjob1);
155  pricingprob2 = GCGpricingjobGetPricingprob(pricingjob2);
156 
157  solver1 = GCGpricingjobGetSolver(pricingjob1);
158  solver2 = GCGpricingjobGetSolver(pricingjob2);
159 
160  /* preliminary order of sorting:
161  * * priority of pricing solvers
162  * * heuristic before exact
163  * * score
164  */
165 
166  if( GCGsolverGetPriority(solver1) > GCGsolverGetPriority(solver2) )
167  return -1;
168  else if( GCGsolverGetPriority(solver1) < GCGsolverGetPriority(solver2) )
169  return 1;
170 
171  if( GCGpricingjobIsHeuristic(pricingjob1) && GCGpricingjobIsHeuristic(pricingjob2) )
172  {
173  if( GCGpricingjobGetNHeurIters(pricingjob1) < GCGpricingjobGetNHeurIters(pricingjob2) )
174  return -1;
175  else if( GCGpricingjobGetNHeurIters(pricingjob1) > GCGpricingjobGetNHeurIters(pricingjob2) )
176  return 1;
177  }
178 
179  if( GCGpricingjobIsHeuristic(pricingjob1) != GCGpricingjobIsHeuristic(pricingjob2) )
180  {
181  if( GCGpricingjobIsHeuristic(pricingjob1) )
182  return -1;
183  else if( GCGpricingjobIsHeuristic(pricingjob2) )
184  return 1;
185  }
186 
187  if( GCGpricingjobGetScore(pricingjob1) > GCGpricingjobGetScore(pricingjob2) )
188  return -1;
189  else if( GCGpricingjobGetScore(pricingjob1) < GCGpricingjobGetScore(pricingjob2) )
190  return 1;
191 
192  // @todo: preliminary tie breaking by pricing problem index
193  if( GCGpricingprobGetProbnr(pricingprob1) < GCGpricingprobGetProbnr(pricingprob2) )
194  return -1;
195  else
196  return 1;
197 
198  return 0;
199 }
200 
201 /** for each pricing problem, get its corresponding generic branching constraints */
202 SCIP_RETCODE Pricingcontroller::getGenericBranchconss()
203 {
204  /* get current branching rule */
205  SCIP_CONS* branchcons = GCGconsMasterbranchGetActiveCons(scip_);
206  SCIP_BRANCHRULE* branchrule = GCGconsMasterbranchGetBranchrule(branchcons);
207 
208  assert(branchcons != NULL);
209  assert(SCIPnodeGetDepth(GCGconsMasterbranchGetNode(branchcons)) == 0 || branchrule != NULL || SCIPinProbing(scip_));
210 
211  while( GCGisBranchruleGeneric(branchrule) )
212  {
213  GCG_BRANCHDATA* branchdata;
214  SCIP_CONS* mastercons;
215  int consblocknr;
216 
217  int i;
218 
219  branchdata = GCGconsMasterbranchGetBranchdata(branchcons);
220  assert(branchdata != NULL);
221 
222  mastercons = GCGbranchGenericBranchdataGetMastercons(branchdata);
223  consblocknr = GCGbranchGenericBranchdataGetConsblocknr(branchdata);
224  assert(mastercons != NULL);
225  assert(consblocknr >= 0 || consblocknr == -3);
226 
227  if( consblocknr >= 0 )
228  {
229  for( i = 0; i < npricingprobs; ++i )
230  {
231  /* search for the pricing problem to which the generic branching decision belongs */
232  if( consblocknr == GCGpricingprobGetProbnr(pricingprobs[i]) )
233  {
234  SCIP_CALL( GCGpricingprobAddGenericBranchData(scip_, pricingprobs[i], branchcons,
235  pricingtype_->consGetDual(scip_, mastercons)) );
236  break;
237  }
238  }
239  assert(i < npricingprobs);
240  }
241 
242  branchcons = GCGconsMasterbranchGetParentcons(branchcons);
243  branchrule = GCGconsMasterbranchGetBranchrule(branchcons);
244  }
245 
246  return SCIP_OKAY;
247 }
248 
249 /** check if a pricing problem is done */
250 SCIP_Bool Pricingcontroller::pricingprobIsDone(
251  GCG_PRICINGPROB* pricingprob /**< pricing problem structure */
252  ) const
253 {
254  return GCGpricingprobGetNImpCols(pricingprob) > 0
258  || SCIPisStopped(scip_);
259 }
260 
261 /** check whether the next generic branching constraint of a pricing problem must be considered */
262 SCIP_Bool Pricingcontroller::pricingprobNeedsNextBranchingcons(
263  GCG_PRICINGPROB* pricingprob /**< pricing problem structure */
264  ) const
265 {
266  return GCGpricingprobGetNImpCols(pricingprob) == 0
268  && GCGpricingprobGetBranchconsIdx(pricingprob) > 0;
269 }
270 
272 {
273  SCIP* origprob = GCGmasterGetOrigprob(scip_);
274  int nblocks = GCGgetNPricingprobs(origprob);
275  GCG_SOLVER** solvers = GCGpricerGetSolvers(scip_);
276  int nsolvers = GCGpricerGetNSolvers(scip_);
277  int actchunksize = MIN(chunksize, GCGgetNRelPricingprobs(origprob));
278 
279  npricingprobs = 0;
280  npricingjobs = 0;
281  nchunks = (int) SCIPceil(scip_, (SCIP_Real) GCGgetNRelPricingprobs(origprob) / actchunksize);
282  curchunk = nchunks - 1;
283  eagerage = 0;
284 
285  /* create pricing problem and pricing job data structures */
286  maxpricingprobs = SCIPcalcMemGrowSize(scip_, GCGgetNRelPricingprobs(origprob));
287  maxpricingjobs = SCIPcalcMemGrowSize(scip_, GCGgetNRelPricingprobs(origprob) * nsolvers);
288  SCIP_CALL_EXC( SCIPallocBlockMemoryArray(scip_, &pricingprobs, maxpricingprobs) );
289  SCIP_CALL_EXC( SCIPallocBlockMemoryArray(scip_, &pricingjobs, maxpricingjobs) );
290  for( int i = 0; i < nblocks; ++i )
291  {
292  if( GCGisPricingprobRelevant(origprob, i) )
293  {
294  SCIP_CALL_EXC( GCGpricingprobCreate(scip_, &pricingprobs[npricingprobs], GCGgetPricingprob(origprob, i), i, nroundscol) );
295 
296  for( int j = 0; j < nsolvers; ++j )
297  {
298  if( GCGsolverIsHeurEnabled(solvers[j]) || GCGsolverIsExactEnabled(solvers[j]) )
299  {
300  SCIP_CALL_EXC( GCGpricingjobCreate(scip_, &pricingjobs[npricingjobs], pricingprobs[npricingprobs], solvers[j], npricingprobs / actchunksize) );
301  ++npricingjobs;
302  break;
303  }
304  }
305  ++npricingprobs;
306  }
307  }
308 
309  SCIP_CALL_EXC( GCGpqueueCreate(scip_, &pqueue, npricingjobs, comparePricingjobs) );
310 
311  return SCIP_OKAY;
312 }
313 
315 {
316  GCGpqueueFree(&pqueue);
317 
318  for( int i = 0; i < npricingprobs; ++i )
319  {
320  GCGpricingprobFree(scip_, &pricingprobs[i]);
321  }
322  for( int i = 0; i < npricingjobs; ++i )
323  {
324  GCGpricingjobFree(scip_, &pricingjobs[i]);
325  }
326  SCIPfreeBlockMemoryArray(scip_, &pricingprobs, maxpricingprobs);
327  SCIPfreeBlockMemoryArray(scip_, &pricingjobs, maxpricingjobs);
328 
329  return SCIP_OKAY;
330 }
331 
332 /** pricing initialization, called right at the beginning of pricing */
334  PricingType* pricingtype /**< type of pricing */
335  )
336 {
337  SCIP_Longint tmpmaxniters;
338 
339  pricingtype_ = pricingtype;
340 
341  /* move chunk index forward */
342  curchunk = (curchunk + 1) % nchunks;
343  startchunk = curchunk;
344 
345  for( int i = 0; i < npricingprobs; ++i )
346  GCGpricingprobInitPricing(pricingprobs[i]);
347 
348  SCIP_CALL( getGenericBranchconss() );
349 
350  /* calculate maximal possible number of pricing iterations per mis-pricing iteration */
351  tmpmaxniters = 0;
352  for( int i = 0; i < npricingprobs; ++i )
353  tmpmaxniters += GCGpricerGetNSolvers(scip_) * ((SCIP_Longint) heurpricingiters + 1) * (GCGpricingprobGetNGenericBranchconss(pricingprobs[i]) + 1);
354  maxniters = (int) MIN(tmpmaxniters, 16383);
355 
356  SCIPdebugMessage("initialize pricing, chunk = %d/%d\n", curchunk+1, nchunks);
357 
358  return SCIP_OKAY;
359 }
360 
361 /** pricing deinitialization, called when pricing is finished */
363 {
364  for( int i = npricingprobs-1; i >= 0; --i )
365  GCGpricingprobExitPricing(pricingprobs[i], nroundscol);
366 
367  pricingtype_ = NULL;
368 }
369 
370 /** setup the priority queue (done once per stabilization round): add all pricing jobs to be performed */
372  SCIP_Real* dualsolconv /**< dual solution values / Farkas coefficients of convexity constraints */
373  )
374 {
375  SCIPdebugMessage("Setup pricing queue, chunk = %d/%d\n", curchunk+1, nchunks);
376 
377  GCGpqueueClear(pqueue);
378 
379  /* reset pricing problems */
380  for( int i = 0; i < npricingprobs; ++i )
381  GCGpricingprobReset(scip_, pricingprobs[i]);
382 
383  for( int i = 0; i < npricingjobs; ++i )
384  {
385  int probnr = GCGpricingprobGetProbnr(GCGpricingjobGetPricingprob(pricingjobs[i]));
386 
387  SCIP_CALL_EXC( GCGpricingjobSetup(scip_, pricingjobs[i],
388  (heurpricingiters > 0
389  && (maxheurdepth == -1 || SCIPnodeGetDepth(SCIPgetCurrentNode(scip_)) <= maxheurdepth)
390  && GCGsolverIsHeurEnabled(GCGpricingjobGetSolver(pricingjobs[i]))),
391  sorting, nroundscol, dualsolconv[probnr], GCGpricerGetNPointsProb(scip_, probnr), GCGpricerGetNRaysProb(scip_, probnr)) );
392 
393  if( GCGpricingjobGetChunk(pricingjobs[i]) == curchunk )
394  {
395  SCIP_CALL_EXC( GCGpqueueInsert(pqueue, (void*) pricingjobs[i]) );
396  }
397  }
398 
399  nsolvedprobs = 0;
400 
401  return SCIP_OKAY;
402 }
403 
404 /** get the next pricing job to be performed */
406 {
407  GCG_PRICINGJOB* pricingjob = NULL;
408 
409  do
410  {
411  pricingjob = (GCG_PRICINGJOB*) GCGpqueueRemove(pqueue);
412  }
413  while( pricingjob != NULL && pricingprobIsDone(GCGpricingjobGetPricingprob(pricingjob)) );
414 
415  return pricingjob;
416 }
417 
418 /** add the information that the next branching constraint must be added,
419  * and for the pricing job, reset heuristic pricing counter and flag
420  */
422  GCG_PRICINGPROB* pricingprob /**< pricing problem structure */
423  )
424 {
425  int i;
426 
427  GCGpricingprobNextBranchcons(pricingprob);
428 
429  /* reset heuristic pricing counter and flag for every corresponding pricing job */
430  if( heurpricingiters > 0 )
431  for( i = 0; i < npricingjobs; ++i )
432  if( GCGpricingjobGetPricingprob(pricingjobs[i]) == pricingprob )
433  GCGpricingjobResetHeuristic(pricingjobs[i]);
434 
435  /* re-sort the priority queue */
436  SCIP_CALL( GCGpqueueResort(pqueue) );
437 
438  return SCIP_OKAY;
439 }
440 
441 /** set an individual time limit for a pricing job */
443  GCG_PRICINGJOB* pricingjob /**< pricing job */
444  )
445 {
446  SCIP* pricingscip = GCGpricingprobGetPricingscip(GCGpricingjobGetPricingprob(pricingjob));
447  SCIP_Real mastertimelimit;
448  SCIP_Real timelimit;
449 
450  SCIP_CALL( SCIPgetRealParam(scip_, "limits/time", &mastertimelimit) );
451 
452  /* do not give pricing job more time than is left for solving the master problem */
453  timelimit = MAX(0, mastertimelimit - SCIPgetSolvingTime(scip_));
454 
455  SCIP_CALL( SCIPsetRealParam(pricingscip, "limits/time", timelimit) );
456 
457  return SCIP_OKAY;
458 }
459 
460 /** update solution information of a pricing problem */
462  GCG_PRICINGPROB* pricingprob, /**< pricing problem structure */
463  GCG_PRICINGSTATUS status, /**< new pricing status */
464  SCIP_Real lowerbound, /**< new lower bound */
465  int nimpcols /**< number of new improving columns */
466  )
467 {
468  GCGpricingprobUpdate(scip_, pricingprob, status, lowerbound, nimpcols);
469 }
470 
471 /** decide whether a pricing job must be treated again */
473  GCG_PRICINGJOB* pricingjob, /**< pricing job */
474  GCG_PRICINGSTATUS status /**< status of pricing job */
475  )
476 {
477  GCG_PRICINGPROB* pricingprob = GCGpricingjobGetPricingprob(pricingjob);
478  SCIP_Bool heuristic = GCGpricingjobIsHeuristic(pricingjob);
479 
480  /* Go to the next heuristic pricing iteration */
481  if( heuristic )
483 
484  /* If the pricing job has not yielded any improving column, possibly solve it again;
485  * increase at least one of its limits, or solve it exactly if it was solved heuristically before
486  */
487  // @todo: update score of pricing job
488  if( !pricingprobIsDone(pricingprob) )
489  {
490  SCIPdebugMessage("Solving problem %d with <%s> has not yielded improving columns.\n",
492 
493  if( heuristic && status != GCG_PRICINGSTATUS_OPTIMAL && status != GCG_PRICINGSTATUS_NOTAPPLICABLE )
494  {
495  assert(status == GCG_PRICINGSTATUS_UNKNOWN || status == GCG_PRICINGSTATUS_SOLVERLIMIT);
496 
497  if( status != GCG_PRICINGSTATUS_SOLVERLIMIT || GCGpricingjobGetNHeurIters(pricingjob) >= heurpricingiters )
498  {
499  GCGpricingjobSetExact(pricingjob);
500  SCIPdebugMessage(" -> set exact\n");
501  }
502  else
503  {
504  SCIPdebugMessage(" -> increase a limit\n");
505  }
506  SCIP_CALL_EXC( GCGpqueueInsert(pqueue, (void*) pricingjob) );
507 
508  return;
509  }
510 
511  if( pricingprobNeedsNextBranchingcons(pricingprob) )
512  {
513 
514  SCIPdebugMessage(" -> consider next generic branching constraint.\n");
515 
517 
518  SCIP_CALL_EXC( GCGpqueueInsert(pqueue, (void*) pricingjob) );
519 
520  return;
521  }
522 
523  GCGpricingjobNextSolver(scip_, pricingjob);
524  if( heurpricingiters > 0 )
525  GCGpricingjobResetHeuristic(pricingjob);
526  if( GCGpricingjobGetSolver(pricingjob) != NULL )
527  {
528  SCIPdebugMessage(" -> use another solver\n");
529  SCIP_CALL_EXC( GCGpqueueInsert(pqueue, (void*) pricingjob) );
530  }
531  }
532  else
533  ++nsolvedprobs;
534 }
535 
536 /** collect solution results from all pricing problems */
538  GCG_COL** bestcols, /**< best found columns per pricing problem */
539  SCIP_Bool* infeasible, /**< pointer to store whether pricing is infeasible */
540  SCIP_Bool* optimal, /**< pointer to store whether all pricing problems were solved to optimality */
541  SCIP_Real* bestobjvals, /**< array to store best lower bounds */
542  SCIP_Real* beststabobj, /**< pointer to store total lower bound */
543  SCIP_Real* bestredcost, /**< pointer to store best total reduced cost */
544  SCIP_Bool* bestredcostvalid /**< pointer to store whether best reduced cost is valid */
545  )
546 {
547  SCIP* origprob = GCGmasterGetOrigprob(scip_);
548  int nblocks = GCGgetNPricingprobs(origprob);
549  SCIP_Bool foundcols = FALSE;
550 
551  /* initializations */
552  *infeasible = FALSE;
553  *optimal = TRUE;
554  *beststabobj = 0.0;
555  *bestredcost = 0.0;
556  for( int i = 0; i < nblocks; ++i )
557  bestobjvals[i] = -SCIPinfinity(scip_);
558 
559  for( int i = 0; i < npricingprobs; ++i )
560  {
561  int probnr = GCGpricingprobGetProbnr(pricingprobs[i]);
562  int nidentblocks = GCGgetNIdenticalBlocks(origprob, probnr);
563  SCIP_Real lowerbound = GCGpricingprobGetLowerbound(pricingprobs[i]);
564 
565  /* check infeasibility */
566  *infeasible |= GCGpricingprobGetStatus(pricingprobs[i]) == GCG_PRICINGSTATUS_INFEASIBLE;
567 
568  /* check optimality */
569  *optimal &= GCGpricingprobGetStatus(pricingprobs[i]) == GCG_PRICINGSTATUS_OPTIMAL;
570 
571  if( GCGpricingprobGetNImpCols(pricingprobs[i]) > 0 )
572  foundcols = TRUE;
573 
574  /* update lower bound information */
575  bestobjvals[probnr] = SCIPisInfinity(scip_, ABS(lowerbound)) ? lowerbound : nidentblocks * lowerbound;
576  if( SCIPisInfinity(scip_, -lowerbound) )
577  *beststabobj = -SCIPinfinity(scip_);
578  else if( !SCIPisInfinity(scip_, -(*beststabobj)) )
579  *beststabobj += bestobjvals[probnr];
580 
581  if( bestcols[probnr] != NULL )
582  *bestredcost += GCGcolGetRedcost(bestcols[probnr]) * nidentblocks;
583  }
584 
585  *infeasible |= (pricingtype_->getType() == GCG_PRICETYPE_FARKAS && *optimal && !foundcols);
586  *bestredcostvalid &= foundcols || *optimal;
587 }
588 
589 /** check if the next chunk of pricing problems is to be used */
591 {
592  int nextchunk = (curchunk + 1) % nchunks;
593 
594  if( nextchunk == startchunk )
595  {
596  SCIPdebugMessage("not considering next chunk.\n");
597  return FALSE;
598  }
599  else
600  {
601  SCIPdebugMessage("need considering next chunk = %d/%d\n", nextchunk+1, nchunks);
602  curchunk = nextchunk;
603  return TRUE;
604  }
605 }
606 
607 /** decide whether the pricing loop can be aborted */
609  PricingType* pricingtype, /**< type of pricing (reduced cost or Farkas) */
610  int nfoundcols, /**< number of negative reduced cost columns found so far */
611  int nsuccessfulprobs /**< number of pricing problems solved successfully so far */
612  ) const
613 {
614  int nrelpricingprobs = GCGgetNRelPricingprobs(GCGmasterGetOrigprob(scip_));
615 
616  if( eagerage == eagerfreq )
617  return FALSE;
618 
619  if( SCIPisStopped(scip_) )
620  return TRUE;
621 
622  return !((nfoundcols < pricingtype->getMaxcolsround())
623  && nsuccessfulprobs < pricingtype->getMaxsuccessfulprobs()
624  && nsuccessfulprobs < pricingtype->getRelmaxsuccessfulprobs() * nrelpricingprobs
625  && (nfoundcols == 0 || nsolvedprobs < pricingtype->getRelmaxprobs() * nrelpricingprobs));
626 }
627 
629 {
630  eagerage = 0;
631 }
632 
634 {
635  if( eagerfreq > 0 )
636  eagerage++;
637 }
638 
639 /** for a given problem index, get the corresponding pricing problem (or NULL, if it does not exist) */
641  int probnr /**< index of the pricing problem */
642  )
643 {
644  for( int i = 0; i < npricingprobs; ++i )
645  if( GCGpricingprobGetProbnr(pricingprobs[i]) == probnr )
646  return pricingprobs[i];
647 
648  return NULL;
649 }
650 
651 /** get maximal possible number of pricing iterations */
653 {
654  return maxniters;
655 }
656 
657 } /* namespace gcg */
void collectResults(GCG_COL **bestcols, SCIP_Bool *infeasible, SCIP_Bool *optimal, SCIP_Real *bestobjvals, SCIP_Real *beststabobj, SCIP_Real *bestredcost, SCIP_Bool *bestredcostvalid)
SCIP_RETCODE initPricing(PricingType *pricingtype)
#define DEFAULT_CHUNKSIZE
public methods for working with pricing problems
void evaluatePricingjob(GCG_PRICINGJOB *pricingjob, GCG_PRICINGSTATUS status)
SCIP_RETCODE GCGpricingprobAddGenericBranchData(SCIP *scip, GCG_PRICINGPROB *pricingprob, SCIP_CONS *branchcons, SCIP_Real branchdual)
Definition: pricingprob.c:122
GCG interface methods.
GCG_PRICINGPROB * getPricingprob(int probnr)
int GCGpricingprobGetBranchconsIdx(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:236
GCG_BRANCHDATA * GCGconsMasterbranchGetBranchdata(SCIP_CONS *cons)
void GCGpricingprobUpdate(SCIP *scip, GCG_PRICINGPROB *pricingprob, GCG_PRICINGSTATUS status, SCIP_Real lowerbound, int nimpcols)
Definition: pricingprob.c:174
virtual int getMaxcolsround() const =0
void GCGpricingprobInitPricing(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:95
SCIP_Real GCGpricingprobGetLowerbound(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:279
public methods for working with pricing jobs
SCIP_Real GCGcolGetRedcost(GCG_COL *gcgcol)
Definition: gcgcol.c:359
void GCGpricingprobReset(SCIP *scip, GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:160
GCG_SOLVER * GCGpricingjobGetSolver(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:133
SCIP_RETCODE setupPriorityQueue(SCIP_Real *dualsolconv)
@ GCG_PRICINGSTATUS_UNBOUNDED
int GCGpricerGetNPointsProb(SCIP *scip, int probnr)
SCIP_RETCODE GCGpqueueCreate(SCIP *scip, GCG_PQUEUE **pqueue, int initsize, SCIP_DECL_SORTPTRCOMP((*ptrcomp)))
Definition: gcgpqueue.c:118
void GCGpricingprobNextBranchcons(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:260
#define DEFAULT_SORTING
SCIP_RETCODE pricingprobNextBranchcons(GCG_PRICINGPROB *pricingprob)
SCIP * GCGgetPricingprob(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:3939
GCG_SOLVER ** GCGpricerGetSolvers(SCIP *scip)
SCIP_Real getRelmaxsuccessfulprobs() const
SCIP_RETCODE GCGpricingjobSetup(SCIP *scip, GCG_PRICINGJOB *pricingjob, SCIP_Bool heuristic, int scoring, int nroundscol, SCIP_Real dualsolconv, int npointsprob, int nraysprob)
Definition: pricingjob.c:82
void GCGpricingjobResetHeuristic(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:238
void GCGpricingprobFree(SCIP *scip, GCG_PRICINGPROB **pricingprob)
Definition: pricingprob.c:82
int GCGgetNPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3979
SCIP_RETCODE GCGpqueueResort(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:234
GCG variable pricer.
enum GCG_PricingStatus GCG_PRICINGSTATUS
SCIP_NODE * GCGconsMasterbranchGetNode(SCIP_CONS *cons)
various SCIP helper methods
SCIP_EXPORT int GCGsolverGetPriority(GCG_SOLVER *solver)
Definition: solver.c:418
GCG_PRICINGPROB * GCGpricingjobGetPricingprob(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:126
void GCGpqueueClear(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:153
private methods for working with pricing jobs, to be used by the pricing controller only
@ GCG_PRICINGSTATUS_SOLVERLIMIT
#define DEFAULT_MAXHEURDEPTH
@ GCG_PRICINGSTATUS_NOTAPPLICABLE
@ GCG_PRICINGSTATUS_INFEASIBLE
SCIP_BRANCHRULE * GCGconsMasterbranchGetBranchrule(SCIP_CONS *cons)
@ GCG_PRICINGSTATUS_OPTIMAL
constraint handler for storing the branching decisions at each node of the tree
int GCGpricerGetNRaysProb(SCIP *scip, int probnr)
#define SCIP_CALL_EXC(x)
int GCGpricingjobGetNHeurIters(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:259
void GCGpricingjobFree(SCIP *scip, GCG_PRICINGJOB **pricingjob)
Definition: pricingjob.c:72
void GCGpqueueFree(GCG_PQUEUE **pqueue)
Definition: gcgpqueue.c:142
branching rule based on vanderbeck's generic branching scheme
void updatePricingprob(GCG_PRICINGPROB *pricingprob, GCG_PRICINGSTATUS status, SCIP_Real lowerbound, int nimpcols)
void GCGpricingjobIncreaseNHeurIters(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:250
int GCGbranchGenericBranchdataGetConsblocknr(GCG_BRANCHDATA *branchdata)
pricing controller managing the pricing strategy
int GCGgetNIdenticalBlocks(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4053
GCG_PRICETYPE getType() const
SCIP_EXPORT SCIP_Bool GCGsolverIsExactEnabled(GCG_SOLVER *solver)
Definition: solver.c:438
GCG_PRICINGSTATUS GCGpricingprobGetStatus(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:271
int GCGgetNRelPricingprobs(SCIP *scip)
Definition: relax_gcg.c:3959
@ GCG_PRICETYPE_FARKAS
Definition: pricer_gcg.h:56
SCIP * GCGpricingprobGetPricingscip(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:196
GCG_PRICINGJOB * getNextPricingjob()
SCIP * GCGmasterGetOrigprob(SCIP *scip)
void * GCGpqueueRemove(GCG_PQUEUE *pqueue)
Definition: gcgpqueue.c:193
SCIP_CONS * GCGconsMasterbranchGetParentcons(SCIP_CONS *cons)
SCIP_RETCODE GCGpqueueInsert(GCG_PQUEUE *pqueue, void *elem)
Definition: gcgpqueue.c:163
int GCGpricingprobGetNGenericBranchconss(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:228
SCIP_CONS * GCGbranchGenericBranchdataGetMastercons(GCG_BRANCHDATA *branchdata)
void GCGpricingprobExitPricing(GCG_PRICINGPROB *pricingprob, int nroundscol)
Definition: pricingprob.c:107
SCIP_Bool GCGisBranchruleGeneric(SCIP_BRANCHRULE *branchrule)
void GCGpricingjobNextSolver(SCIP *scip, GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:171
#define DEFAULT_EAGERFREQ
private methods for working with pricing problems, to be used by the pricing controller only
SCIP_CONS * GCGconsMasterbranchGetActiveCons(SCIP *scip)
virtual SCIP_Real consGetDual(SCIP *scip, SCIP_CONS *cons) const =0
const SCIP_EXPORT char * GCGsolverGetName(GCG_SOLVER *solver)
Definition: solver.c:398
SCIP_Bool GCGpricingjobIsHeuristic(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:222
SCIP_Bool canPricingloopBeAborted(PricingType *pricingtype, int nfoundcols, int nsuccessfulprobs) const
@ GCG_PRICINGSTATUS_UNKNOWN
SCIP_RETCODE setPricingjobTimelimit(GCG_PRICINGJOB *pricingjob)
virtual SCIP_Real getRelmaxprobs() const =0
abstraction for SCIP pricing types
void GCGpricingjobSetExact(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:230
SCIP_RETCODE GCGpricingjobCreate(SCIP *scip, GCG_PRICINGJOB **pricingjob, GCG_PRICINGPROB *pricingprob, GCG_SOLVER *solver, int chunk)
Definition: pricingjob.c:51
SCIP_Bool GCGisPricingprobRelevant(SCIP *scip, int pricingprobnr)
Definition: relax_gcg.c:4000
SCIP_Real GCGpricingjobGetChunk(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:206
int GCGpricerGetNSolvers(SCIP *scip)
#define DEFAULT_NROUNDSCOL
#define DEFAULT_HEURPRICINGITERS
SCIP_EXPORT SCIP_Bool GCGsolverIsHeurEnabled(GCG_SOLVER *solver)
Definition: solver.c:428
int GCGpricingprobGetProbnr(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:204
SCIP_DECL_SORTPTRCOMP(Pricingcontroller::comparePricingjobs)
int GCGpricingprobGetNImpCols(GCG_PRICINGPROB *pricingprob)
Definition: pricingprob.c:287
SCIP_Real GCGpricingjobGetScore(GCG_PRICINGJOB *pricingjob)
Definition: pricingjob.c:214
SCIP_RETCODE GCGpricingprobCreate(SCIP *scip, GCG_PRICINGPROB **pricingprob, SCIP *pricingscip, int probnr, int nroundscol)
Definition: pricingprob.c:51