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

Last change on this file since 1432 was 1432, checked in by bjarni, 10 years ago

Added extra return at end of each source file where needed, to remove possible linefeed conflicts (NightlyBuild? errors)

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.