source: trunk/Cbc/src/CbcGenCtlBlk.cpp @ 2464

Last change on this file since 2464 was 2464, checked in by unxusr, 8 months ago

.clang-format with proposal for formatting code

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