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

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

Cbc-generic: Add message handler, separate libCbc and cbc-generic main log
level parameters.

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