source: branches/devel/Cbc/src/CbcGenCtlBlk.cpp @ 591

Last change on this file since 591 was 591, checked in by lou, 13 years ago

Initial commit of cbc-generic source.

  • Property svn:eol-style set to native
File size: 15.7 KB
Line 
1/*
2  Copyright (C) 2007, Lou Hafer, International Business Machines Corporation
3  and others.  All Rights Reserved.
4
5  This file is part of cbc-generic.
6*/
7
8#include "CbcConfig.h"
9#include "CoinPragma.hpp"
10
11#include <cassert>
12
13#include "CbcGenCtlBlk.hpp"
14
15/*
16  Constructor for cbc-generic control block.
17
18  Set up defaults for the cbc-generic control block. Note that prototypes for
19  cut generators and heuristics will be created on demand; see the access
20  functions.
21
22  Once this structure settles down, simple intialisation should move up to
23  the standard `:' block. In the meantime, this avoids complaints about
24  ordering.
25*/
26
27CbcGenCtlBlk::CbcGenCtlBlk ()
28
29{ version_ = CBC_GENERIC_VERSION ;
30/*
31  It's unclear to me that this is a good choice for dfltDirectory. Makes
32  sense for commands, but seems unnecessary for data files. Perhaps a null
33  string instead?
34*/
35  char dirsep = CoinFindDirSeparator() ;
36  dfltDirectory_ = (dirsep == '/' ? "./" : ".\\") ;
37  lastMpsIn_ = "" ;
38  allowImportErrors_ = false ;
39  lastSolnOut_ = "stdout" ;
40  printMode_ = 0 ;
41  printMask_ = "" ;
42
43  paramVec_ = 0 ;
44  genParams_.first_ = 0 ;
45  genParams_.last_ = 0 ;
46  cbcParams_.first_ = 0 ;
47  cbcParams_.last_ = 0 ;
48  osiParams_.first_ = 0 ;
49  osiParams_.last_ = 0 ;
50
51  verbose_ = 0 ;
52  paramsProcessed_ = 0 ;
53  defaultSettings_ = true ;
54
55  debugCreate_ = "" ;
56  debugFile_ = "" ;
57  debugSol_.numCols_ = -1 ;
58  debugSol_.values_ = 0 ;
59
60  printOpt_ = 0 ;
61
62  totalTime_ = 0.0 ;
63
64  model_ = 0 ;
65  dfltSolver_ = 0 ;
66  goodModel_ = false ;
67  bab_.majorStatus_ = BACInvalid ;
68  bab_.minorStatus_ = BACmInvalid ;
69  bab_.where_ = BACwInvalid ;
70  bab_.haveAnswer_ = false ;
71  bab_.answerSolver_ = 0 ;
72
73  preProcess_ = CbcGenCtlBlk::IPPSOS ;
74  cutDepth_ = -1 ;
75
76  probing_.action_ = CbcGenCtlBlk::CGIfMove ;
77  probing_.proto_ = 0 ;
78  probing_.usingObjective_ = true ;
79  probing_.maxPass_ = 3 ;
80  probing_.maxPassRoot_ = 3 ;
81  probing_.maxProbe_ = 10 ;
82  probing_.maxProbeRoot_ = 50 ;
83  probing_.maxLook_ = 10 ;
84  probing_.maxLookRoot_ = 50 ;
85  probing_.maxElements_ = 200 ;
86  probing_.rowCuts_ = 3 ;
87
88  clique_.action_ = CbcGenCtlBlk::CGIfMove ;
89  clique_.proto_ = 0 ;
90  clique_.starCliqueReport_ = false ;
91  clique_.rowCliqueReport_ = false ;
92  clique_.minViolation_ = 0.1 ;
93
94  flow_.action_ = CbcGenCtlBlk::CGIfMove ;
95  flow_.proto_ = 0 ;
96
97  gomory_.action_ = CbcGenCtlBlk::CGIfMove ;
98  gomory_.proto_ = 0 ;
99  gomory_.limit_ = 50 ;
100  gomory_.limitAtRoot_ = 512 ;
101
102  knapsack_.action_ = CbcGenCtlBlk::CGIfMove ;
103  knapsack_.proto_ = 0 ;
104
105  // landp_action_ = CbcGenCtlBlk::CGOff ;
106  // landp_.proto_ = 0 ;
107
108  mir_.action_ = CbcGenCtlBlk::CGIfMove ;
109  mir_.proto_ = 0 ;
110
111  oddHole_.action_ = CbcGenCtlBlk::CGOff ;
112  oddHole_.proto_ = 0 ;
113
114  redSplit_.action_ = CbcGenCtlBlk::CGRoot ;
115  redSplit_.proto_ = 0 ;
116
117  twomir_.action_ = CbcGenCtlBlk::CGRoot ;
118  twomir_.proto_ = 0 ;
119  twomir_.maxElements_ = 250 ;
120
121  fpump_.action_ = CbcGenCtlBlk::CGOn ;
122  fpump_.proto_ = 0 ;
123
124  combine_.action_ = CbcGenCtlBlk::CGOn ;
125  combine_.proto_ = 0 ;
126  combine_.trySwap_ = 1 ;
127
128  greedyCover_.action_ = CbcGenCtlBlk::CGOn ;
129  greedyCover_.proto_ = 0 ;
130  greedyEquality_.action_ = CbcGenCtlBlk::CGOn ;
131  greedyEquality_.proto_ = 0 ;
132
133  localTree_.action_ = CbcGenCtlBlk::CGOff ;
134  localTree_.proto_ = 0 ;
135  localTree_.soln_ = 0 ;
136  localTree_.range_ = 10 ;
137  localTree_.typeCuts_ = 0 ;
138  localTree_.maxDiverge_ = 0 ;
139  localTree_.timeLimit_ = 10000 ;
140  localTree_.nodeLimit_ = 2000 ;
141  localTree_.refine_ = true ;
142
143  rounding_.action_ = CbcGenCtlBlk::CGOn ;
144  rounding_.proto_ = 0 ;
145
146  djFix_.action_ = false ;
147  djFix_.threshold_ = 1.0e100 ;
148
149  priorityAction_ = CbcGenCtlBlk::BPOff ;
150/*
151  The value for numBeforeTrust is as recommended by Achterberg. Cbc's
152  implementation doesn't really have a parameter equivalent to Achterberg's
153  dynamic limit on number of strong branching evaluations, so go with a fairly
154  large default. As of 06.12.16, the magic number for shadow price mode meant
155  `use shadow prices (penalties, I think) if there's no strong branching info'.
156*/
157  chooseStrong_.numBeforeTrust_ = 8 ;
158  chooseStrong_.numStrong_ = 100 ;
159  chooseStrong_.shadowPriceMode_ = 1 ;
160
161  return ; }
162
163/*
164  Note that we don't want to delete dfltSolver_ here because it's just a
165  copy of the pointer held in the solvers map over in CbcGenSolvers.cpp.
166*/
167CbcGenCtlBlk::~CbcGenCtlBlk ()
168
169{ if (model_) delete model_ ;
170  if (bab_.answerSolver_) delete bab_.answerSolver_ ;
171
172  if (probing_.proto_) delete probing_.proto_ ;
173  if (clique_.proto_) delete clique_.proto_ ;
174  if (flow_.proto_) delete flow_.proto_ ;
175  if (gomory_.proto_) delete gomory_.proto_ ;
176  if (knapsack_.proto_) delete knapsack_.proto_ ;
177  if (mir_.proto_) delete mir_.proto_ ;
178  if (oddHole_.proto_) delete oddHole_.proto_ ;
179  if (redSplit_.proto_) delete redSplit_.proto_ ;
180  if (twomir_.proto_) delete twomir_.proto_ ;
181
182  if (fpump_.proto_) delete fpump_.proto_ ;
183  if (combine_.proto_) delete combine_.proto_ ;
184  if (greedyCover_.proto_) delete greedyCover_.proto_ ;
185  if (greedyEquality_.proto_) delete greedyEquality_.proto_ ;
186  if (rounding_.proto_) delete rounding_.proto_ ;
187
188  return ; }
189
190/*
191  Access functions for cut generators and heuristics. These support lazy
192  creation --- if action_ is other than CGOff, an object is created if
193  necessary and a pointer is stored in proto_. The pointer is returned as
194  a generic CglCutGenerator or CbcHeuristic. The return value of the function
195  is the value of action_.
196
197  Because the model may have changed, the default for heuristics is to delete
198  any existing object and create a new one. This can be suppressed if desired.
199*/
200
201CbcGenCtlBlk::CGControl CbcGenCtlBlk::getProbing (CglCutGenerator *&gen)
202
203{ if (probing_.action_ != CbcGenCtlBlk::CGOff && probing_.proto_ == 0)
204  { probing_.proto_ = new CglProbing() ;
205    probing_.proto_->setUsingObjective(probing_.usingObjective_) ;
206    probing_.proto_->setMaxPass(probing_.maxPass_) ;
207    probing_.proto_->setMaxPassRoot(probing_.maxPassRoot_) ;
208    probing_.proto_->setMaxProbe(probing_.maxProbe_) ;
209    probing_.proto_->setMaxProbeRoot(probing_.maxProbeRoot_) ;
210    probing_.proto_->setMaxLook(probing_.maxLook_) ;
211    probing_.proto_->setMaxLookRoot(probing_.maxLookRoot_) ;
212    probing_.proto_->setMaxElements(probing_.maxElements_) ;
213    probing_.proto_->setRowCuts(probing_.rowCuts_) ; }
214  gen = dynamic_cast<CglCutGenerator *>(probing_.proto_) ;
215
216  return (probing_.action_) ; }
217
218
219CbcGenCtlBlk::CGControl CbcGenCtlBlk::getClique (CglCutGenerator *&gen)
220
221{ if (clique_.action_ != CbcGenCtlBlk::CGOff && clique_.proto_ == 0)
222  { clique_.proto_ = new CglClique() ;
223    clique_.proto_->setStarCliqueReport(clique_.starCliqueReport_) ;
224    clique_.proto_->setRowCliqueReport(clique_.rowCliqueReport_) ;
225    clique_.proto_->setMinViolation(clique_.minViolation_) ; }
226  gen = dynamic_cast<CglCutGenerator *>(clique_.proto_) ;
227
228  return (clique_.action_) ; }
229
230
231CbcGenCtlBlk::CGControl CbcGenCtlBlk::getFlow (CglCutGenerator *&gen)
232
233{ if (flow_.action_ != CbcGenCtlBlk::CGOff && flow_.proto_ == 0)
234  { flow_.proto_ = new CglFlowCover() ; }
235  gen = dynamic_cast<CglCutGenerator *>(flow_.proto_) ;
236
237  return (flow_.action_) ; }
238
239
240CbcGenCtlBlk::CGControl CbcGenCtlBlk::getGomory (CglCutGenerator *&gen)
241
242{ if (gomory_.action_ != CbcGenCtlBlk::CGOff && gomory_.proto_ == 0)
243  { gomory_.proto_ = new CglGomory() ;
244    gomory_.proto_->setLimitAtRoot(gomory_.limitAtRoot_) ;
245    gomory_.proto_->setLimit(gomory_.limit_) ; }
246  gen = dynamic_cast<CglCutGenerator *>(gomory_.proto_) ;
247
248  return (gomory_.action_) ; }
249
250
251CbcGenCtlBlk::CGControl CbcGenCtlBlk::getKnapsack (CglCutGenerator *&gen)
252
253{ if (knapsack_.action_ != CbcGenCtlBlk::CGOff && knapsack_.proto_ == 0)
254  { knapsack_.proto_ = new CglKnapsackCover() ; }
255  gen = dynamic_cast<CglCutGenerator *>(knapsack_.proto_) ;
256
257  return (knapsack_.action_) ; }
258
259
260CbcGenCtlBlk::CGControl CbcGenCtlBlk::getMir (CglCutGenerator *&gen)
261
262{ if (mir_.action_ != CbcGenCtlBlk::CGOff && mir_.proto_ == 0)
263  { mir_.proto_ = new CglMixedIntegerRounding2() ; }
264  gen = dynamic_cast<CglCutGenerator *>(mir_.proto_) ;
265
266  return (mir_.action_) ; }
267
268
269CbcGenCtlBlk::CGControl CbcGenCtlBlk::getRedSplit (CglCutGenerator *&gen)
270
271{ if (redSplit_.action_ != CbcGenCtlBlk::CGOff && redSplit_.proto_ == 0)
272  { redSplit_.proto_ = new CglRedSplit() ; }
273  gen = dynamic_cast<CglCutGenerator *>(redSplit_.proto_) ;
274
275  return (redSplit_.action_) ; }
276
277
278CbcGenCtlBlk::CGControl CbcGenCtlBlk::getTwomir (CglCutGenerator *&gen)
279
280{ if (twomir_.action_ != CbcGenCtlBlk::CGOff && twomir_.proto_ == 0)
281  { twomir_.proto_ = new CglTwomir() ;
282    twomir_.proto_->setMaxElements(twomir_.maxElements_) ; }
283  gen = dynamic_cast<CglCutGenerator *>(twomir_.proto_) ;
284
285  return (twomir_.action_) ; }
286
287
288CbcGenCtlBlk::CGControl
289CbcGenCtlBlk::getFPump (CbcHeuristic *&gen, CbcModel *model,
290                        bool alwaysCreate)
291
292{ if (fpump_.action_ != CbcGenCtlBlk::CGOff &&
293      (fpump_.proto_ == 0 || alwaysCreate))
294  { if (fpump_.proto_)
295    { delete fpump_.proto_ ; }
296    fpump_.proto_ = new CbcHeuristicFPump(*model) ;
297    fpump_.proto_->setMaximumPasses(fpump_.iters_) ; }
298  gen = dynamic_cast<CbcHeuristic *>(fpump_.proto_) ;
299
300  return (fpump_.action_) ; }
301
302
303CbcGenCtlBlk::CGControl
304CbcGenCtlBlk::getCombine (CbcHeuristic *&gen, CbcModel *model,
305                          bool alwaysCreate)
306
307{ if (combine_.action_ != CbcGenCtlBlk::CGOff &&
308      (combine_.proto_ == 0 || alwaysCreate))
309  { if (combine_.proto_)
310    { delete combine_.proto_ ; }
311    combine_.proto_ = new CbcHeuristicLocal(*model) ;
312    combine_.proto_->setSearchType(combine_.trySwap_) ; }
313  gen = dynamic_cast<CbcHeuristic *>(combine_.proto_) ;
314
315  return (combine_.action_) ; }
316
317
318CbcGenCtlBlk::CGControl
319CbcGenCtlBlk::getGreedyCover (CbcHeuristic *&gen, CbcModel *model,
320                              bool alwaysCreate)
321
322{ if (greedyCover_.action_ != CbcGenCtlBlk::CGOff &&
323      (greedyCover_.proto_ == 0 || alwaysCreate))
324  { if (greedyCover_.proto_)
325    { delete greedyCover_.proto_ ; }
326    greedyCover_.proto_ = new CbcHeuristicGreedyCover(*model) ; }
327  gen = dynamic_cast<CbcHeuristic *>(greedyCover_.proto_) ;
328
329  return (greedyCover_.action_) ; }
330
331
332CbcGenCtlBlk::CGControl
333CbcGenCtlBlk::getGreedyEquality (CbcHeuristic *&gen, CbcModel *model,
334                                 bool alwaysCreate)
335
336{ if (greedyEquality_.action_ != CbcGenCtlBlk::CGOff &&
337      (greedyEquality_.proto_ == 0 || alwaysCreate))
338  { if (greedyEquality_.proto_)
339    { delete greedyEquality_.proto_ ; }
340    greedyEquality_.proto_ = new CbcHeuristicGreedyEquality(*model) ; }
341  gen = dynamic_cast<CbcHeuristic *>(greedyEquality_.proto_) ;
342
343  return (greedyEquality_.action_) ; }
344
345
346CbcGenCtlBlk::CGControl
347CbcGenCtlBlk::getRounding (CbcHeuristic *&gen, CbcModel *model,
348                           bool alwaysCreate)
349
350{ if (rounding_.action_ != CbcGenCtlBlk::CGOff &&
351      (rounding_.proto_ == 0 || alwaysCreate))
352  { if (rounding_.proto_)
353    { delete rounding_.proto_ ; }
354    rounding_.proto_ = new CbcRounding(*model) ; }
355  gen = dynamic_cast<CbcHeuristic *>(rounding_.proto_) ;
356
357  return (rounding_.action_) ; }
358
359
360CbcGenCtlBlk::CGControl
361CbcGenCtlBlk::getTreeLocal (CbcTreeLocal *&localTree, CbcModel *model,
362                            bool alwaysCreate)
363
364{ if (localTree_.action_ != CbcGenCtlBlk::CGOff &&
365      (localTree_.proto_ == 0 || alwaysCreate))
366  { if (localTree_.proto_)
367    { delete localTree_.proto_ ; }
368    localTree_.proto_ =
369        new CbcTreeLocal(model,localTree_.soln_,localTree_.range_,
370                         localTree_.typeCuts_,localTree_.maxDiverge_,
371                         localTree_.timeLimit_,localTree_.nodeLimit_,
372                         localTree_.refine_) ; }
373  localTree = localTree_.proto_ ; 
374 
375  return (localTree_.action_) ; }
376
377/*
378  A bunch of little translation helper routines leading up to a version of
379  setBaBStatus that figures it all out given a CbcModel and BACWhere code.
380  This translation needs to be centralised to avoid sprinkling magic numbers
381  all through the code.
382
383  Be a bit careful with the translation routines --- they aren't sensitive to
384  where the search stopped.
385*/
386
387CbcGenCtlBlk::BACMajor CbcGenCtlBlk::translateMajor (int status)
388
389{ switch (status)
390  { case -1:
391    { return (BACNotRun) ; }
392    case  0:
393    { return (BACFinish) ; }
394    case  1:
395    { return (BACStop) ; }
396    case  2:
397    { return (BACAbandon) ; }
398    case  5:
399    { return (BACUser) ; }
400    default:
401    { return (BACInvalid) ; } } }
402
403
404CbcGenCtlBlk::BACMinor CbcGenCtlBlk::translateMinor (int status)
405
406{ switch (status)
407  { case -1:
408    { return (BACmInvalid) ; }
409    case  0:
410    { return (BACmFinish) ; }
411    case  1:
412    { return (BACmInfeas) ; }
413    case  2:
414    { return (BACmGap) ; }
415    case  3:
416    { return (BACmNodeLimit) ; }
417    case  4:
418    { return (BACmTimeLimit) ; }
419    case  5:
420    { return (BACmUser) ; }
421    case  6:
422    { return (BACmSolnLimit) ; }
423    case  7:
424    { return (BACmUbnd) ; }
425    default:
426    { return (BACmOther) ; } } }
427
428/*
429  A bit different --- given an OSI, use its interrogation functions to choose
430  an appropriate BACMinor code. Not everything matches up, eh?
431*/
432CbcGenCtlBlk::BACMinor
433CbcGenCtlBlk::translateMinor (const OsiSolverInterface *osi)
434
435{ if (osi->isProvenOptimal())
436  { return (BACmFinish) ; }
437  else
438  if (osi->isProvenPrimalInfeasible())
439  { return (BACmInfeas) ; }
440  else
441  if (osi->isProvenDualInfeasible())
442  { return (BACmUbnd) ; }
443  else
444  { return (BACmOther) ; } }
445
446
447/*
448  A routine to set the bab_ status block given a CbcModel and an indication
449  of where we're at in the search. Really, this is just a big mapping from
450  CbcModel codes to CbcGeneric codes.
451*/
452
453void CbcGenCtlBlk::setBaBStatus (const CbcModel *model, BACWhere where,
454                                 bool haveAnswer,
455                                 OsiSolverInterface *answerSolver)
456
457{ CbcGenCtlBlk::BACMajor major ;
458  CbcGenCtlBlk::BACMinor minor ;
459
460  major = translateMajor(model->status()) ;
461
462  if (where == CbcGenCtlBlk::BACwBareRoot ||
463      where == CbcGenCtlBlk::BACwIPPRelax)
464  { minor = translateMinor(model->solver()) ; }
465  else
466  { minor = translateMinor(model->secondaryStatus()) ; }
467
468  setBaBStatus(major,minor,where,haveAnswer,answerSolver) ;
469
470  return ; }
471
472
473/*
474  Last, but not least, a routine to print the result.
475*/
476
477void CbcGenCtlBlk::printBaBStatus ()
478
479{ std::cout << "BAC result: stopped " ;
480
481  switch (bab_.where_)
482  { case BACwNotStarted:
483    { std::cout << "before root relaxation" ;
484      break ; }
485    case BACwBareRoot:
486    { std::cout << "after root relaxation" ;
487      break ; }
488    case BACwIPP:
489    { std::cout << "after integer preprocessing" ;
490      break ; }
491    case BACwIPPRelax:
492    { std::cout << "after solving preprocessed relaxation" ;
493      break ; }
494    case BACwBAC:
495    { std::cout << "after branch-and-cut" ;
496      break ; }
497    default:
498    { std::cout << "!!invalid phase code!!" ;
499      break ; } }
500
501  std::cout << std::endl << "    Branch-and-cut " ;
502
503  switch (bab_.majorStatus_)
504  { case BACNotRun:
505    { std::cout << "never got started" ;
506      break ; }
507    case BACFinish:
508    { std::cout << "finished" ;
509      break ; }
510    case BACStop:
511    { std::cout << "stopped on a limit" ;
512      break ; }
513    case BACAbandon:
514    { std::cout << "was abandoned" ;
515      break ; }
516    case BACUser:
517    { std::cout << "stopped due to a user event" ;
518      break ; }
519    default:
520    { std::cout << "!!invalid major status code!!" ;
521      break ; } }
522
523  std::cout << "; minor status is " ;
524
525  switch (bab_.minorStatus_)
526  { case BACmFinish:
527    { std::cout << "optimal" ;
528      break ; }
529    case BACmInfeas:
530    { std::cout << "infeasible" ;
531      break ; }
532    case BACmUbnd:
533    { std::cout << "unbounded" ;
534      break ; }
535    case BACmGap:
536    { std::cout << "reached specified integrality gap." ;
537      break ; }
538    case BACmNodeLimit:
539    { std::cout << "reached node limit" ;
540      break ; }
541    case BACmTimeLimit:
542    { std::cout << "reached time limit" ;
543      break ; }
544    case BACmSolnLimit:
545    { std::cout << "reached limit on number of solutions" ;
546      break ; }
547    case BACmUser:
548    { std::cout << "stopped due to a user event" ;
549      break ; }
550    case BACmOther:
551    { std::cout << "other" ;
552      break ; }
553    default:
554    { std::cout << "!!invalid minor status code!!" ;
555      break ; } }
556
557  std::cout << "." << std::endl ; }
Note: See TracBrowser for help on using the repository browser.