source: stable/2.6/Cbc/src/CbcGenCtlBlk.cpp @ 2122

Last change on this file since 2122 was 1464, checked in by stefan, 9 years ago

merge split branch into trunk; fix some examples

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