source: branches/sandbox/Cbc/src/CbcStrategy.cpp @ 1286

Last change on this file since 1286 was 1286, checked in by EdwinStraver, 10 years ago

Changed formatting using AStyle -A4 -p

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.2 KB
Line 
1/* $Id: CbcStrategy.cpp 1286 2009-11-09 23:33:07Z EdwinStraver $ */
2// Copyright (C) 2005, International Business Machines
3// Corporation and others.  All Rights Reserved.
4#if defined(_MSC_VER)
5// Turn off compiler warning about long names
6#  pragma warning(disable:4786)
7#endif
8
9#include "CbcConfig.h"
10
11#include <cassert>
12#include <cstdlib>
13#include <cmath>
14#include <cfloat>
15
16#include "OsiSolverInterface.hpp"
17#ifdef COIN_HAS_CLP
18#include "OsiClpSolverInterface.hpp"
19#endif
20#include "CbcModel.hpp"
21#include "CbcMessage.hpp"
22#include "CbcStrategy.hpp"
23#include "CbcCutGenerator.hpp"
24#include "CbcBranchActual.hpp"
25#include "CbcNode.hpp"
26#include "CoinWarmStart.hpp"
27#include "CglPreProcess.hpp"
28// Cuts
29
30#include "CglGomory.hpp"
31#include "CglProbing.hpp"
32#include "CglKnapsackCover.hpp"
33#include "CglOddHole.hpp"
34#include "CglClique.hpp"
35#include "CglFlowCover.hpp"
36#include "CglMixedIntegerRounding2.hpp"
37
38// Heuristics
39
40#include "CbcHeuristic.hpp"
41#include "CbcHeuristicLocal.hpp"
42
43// Default Constructor
44CbcStrategy::CbcStrategy()
45        : depth_(0),
46        preProcessState_(0),
47        process_(NULL)
48{
49}
50
51// Destructor
52CbcStrategy::~CbcStrategy ()
53{
54    delete process_;
55}
56// Delete pre-processing object to save memory
57void
58CbcStrategy::deletePreProcess()
59{
60    delete process_;
61    process_ = NULL;
62}
63// Return a new Full node information pointer (descendant of CbcFullNodeInfo)
64CbcNodeInfo *
65CbcStrategy::fullNodeInfo(CbcModel * model, int numberRowsAtContinuous) const
66{
67    return new CbcFullNodeInfo(model, numberRowsAtContinuous);
68}
69// Return a new Partial node information pointer (descendant of CbcPartialNodeInfo)
70CbcNodeInfo *
71CbcStrategy::partialNodeInfo(CbcModel * /*model*/,
72                             CbcNodeInfo * parent, CbcNode * owner,
73                             int numberChangedBounds, const int * variables,
74                             const double * boundChanges,
75                             const CoinWarmStartDiff *basisDiff) const
76{
77    return new CbcPartialNodeInfo(parent, owner, numberChangedBounds, variables,
78                                  boundChanges, basisDiff);
79}
80/* After a CbcModel::resolve this can return a status
81   -1 no effect
82   0 treat as optimal
83   1 as 0 but do not do any more resolves (i.e. no more cuts)
84   2 treat as infeasible
85*/
86int
87CbcStrategy::status(CbcModel * /*model*/, CbcNodeInfo * /*parent*/,
88                    int /*whereFrom*/)
89{
90    return -1;
91}
92
93// Default Constructor
94CbcStrategyDefault::CbcStrategyDefault(int cutsOnlyAtRoot,
95                                       int numberStrong,
96                                       int numberBeforeTrust,
97                                       int printLevel)
98        : CbcStrategy(),
99        cutsOnlyAtRoot_(cutsOnlyAtRoot),
100        numberStrong_(numberStrong),
101        numberBeforeTrust_(numberBeforeTrust),
102        printLevel_(printLevel),
103        desiredPreProcess_(0),
104        preProcessPasses_(0)
105{
106}
107
108
109// Destructor
110CbcStrategyDefault::~CbcStrategyDefault ()
111{
112}
113
114// Clone
115CbcStrategy *
116CbcStrategyDefault::clone() const
117{
118    return new CbcStrategyDefault(*this);
119}
120
121// Copy constructor
122CbcStrategyDefault::CbcStrategyDefault(const CbcStrategyDefault & rhs)
123        :
124        CbcStrategy(rhs),
125        cutsOnlyAtRoot_(rhs.cutsOnlyAtRoot_),
126        numberStrong_(rhs.numberStrong_),
127        numberBeforeTrust_(rhs.numberBeforeTrust_),
128        printLevel_(rhs.printLevel_),
129        desiredPreProcess_(rhs.desiredPreProcess_),
130        preProcessPasses_(rhs.preProcessPasses_)
131{
132    setNested(rhs.getNested());
133}
134
135// Setup cut generators
136void
137CbcStrategyDefault::setupCutGenerators(CbcModel & model)
138{
139    if (cutsOnlyAtRoot_ < 0)
140        return; // no cuts wanted
141    // Set up some cut generators and defaults
142    // Probing first as gets tight bounds on continuous
143    int genFlags = 63;
144    //#define CBC_GENERATE_TEST
145#ifdef CBC_GENERATE_TEST
146    int nNodes = model.getMaximumNodes();
147    if (nNodes >= 190000 && nNodes < 190064)
148        genFlags = nNodes - 190000;
149#endif
150
151    CglProbing generator1;
152    generator1.setUsingObjective(true);
153    generator1.setMaxPass(1);
154    generator1.setMaxPassRoot(1);
155    // Number of unsatisfied variables to look at
156    generator1.setMaxProbe(10);
157    // How far to follow the consequences
158    generator1.setMaxLook(10);
159    // Only look at rows with fewer than this number of elements
160    generator1.setMaxElements(200);
161    generator1.setMaxElementsRoot(300);
162    //generator1.setRowCuts(3);
163
164    CglGomory generator2;
165    // try larger limit
166    generator2.setLimit(300);
167
168    CglKnapsackCover generator3;
169
170    //CglOddHole generator4;
171    //generator4.setMinimumViolation(0.005);
172    //generator4.setMinimumViolationPer(0.00002);
173    // try larger limit
174    //generator4.setMaximumEntries(200);
175
176    CglClique generator5;
177    generator5.setStarCliqueReport(false);
178    generator5.setRowCliqueReport(false);
179
180    CglMixedIntegerRounding2 mixedGen;
181    CglFlowCover flowGen;
182
183    // Add in generators
184    int setting = cutsOnlyAtRoot_ ? -99 : -1;
185    int numberGenerators = model.numberCutGenerators();
186    int iGenerator;
187    bool found;
188    found = false;
189    for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
190        CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
191        CglProbing * cgl = dynamic_cast<CglProbing *>(generator);
192        if (cgl) {
193            found = true;
194            break;
195        }
196    }
197    if (!found && (genFlags&1) != 0)
198        model.addCutGenerator(&generator1, setting, "Probing");
199    found = false;
200    for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
201        CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
202        CglGomory * cgl = dynamic_cast<CglGomory *>(generator);
203        if (cgl) {
204            found = true;
205            break;
206        }
207    }
208    if (!found && (genFlags&2) != 0)
209        model.addCutGenerator(&generator2, setting, "Gomory");
210    found = false;
211    for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
212        CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
213        CglKnapsackCover * cgl = dynamic_cast<CglKnapsackCover *>(generator);
214        if (cgl) {
215            found = true;
216            break;
217        }
218    }
219    if (!found && (genFlags&4) != 0)
220        model.addCutGenerator(&generator3, setting, "Knapsack");
221    //model.addCutGenerator(&generator4,setting,"OddHole");
222    found = false;
223    for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
224        CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
225        CglClique * cgl = dynamic_cast<CglClique *>(generator);
226        if (cgl) {
227            found = true;
228            break;
229        }
230    }
231    if (!found && (genFlags&8) != 0)
232        model.addCutGenerator(&generator5, setting, "Clique");
233    found = false;
234    for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
235        CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
236        CglFlowCover * cgl = dynamic_cast<CglFlowCover *>(generator);
237        if (cgl) {
238            found = true;
239            break;
240        }
241    }
242    if (!found && (genFlags&16) != 0)
243        model.addCutGenerator(&flowGen, setting, "FlowCover");
244    found = false;
245    for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
246        CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
247        CglMixedIntegerRounding2 * cgl = dynamic_cast<CglMixedIntegerRounding2 *>(generator);
248        if (cgl) {
249            found = true;
250            break;
251        }
252    }
253    if (!found && (genFlags&32) != 0)
254        model.addCutGenerator(&mixedGen, setting, "MixedIntegerRounding2");
255    // Say we want timings
256    int newNumberGenerators = model.numberCutGenerators();
257    for (iGenerator = numberGenerators; iGenerator < newNumberGenerators; iGenerator++) {
258        CbcCutGenerator * generator = model.cutGenerator(iGenerator);
259        generator->setTiming(true);
260    }
261    int currentPasses = model.getMaximumCutPassesAtRoot();
262    if (currentPasses >= 0) {
263        if (model.getNumCols() < 5000)
264            model.setMaximumCutPassesAtRoot(CoinMax(50, currentPasses)); // use minimum drop
265        else
266            model.setMaximumCutPassesAtRoot(CoinMax(20, currentPasses));
267    } else {
268        currentPasses = -currentPasses;
269        if (model.getNumCols() < 500)
270            model.setMaximumCutPassesAtRoot(-CoinMax(100, currentPasses)); // always do 100 if possible
271        else
272            model.setMaximumCutPassesAtRoot(-CoinMax(20, currentPasses));
273    }
274}
275// Setup heuristics
276void
277CbcStrategyDefault::setupHeuristics(CbcModel & model)
278{
279    // Allow rounding heuristic
280
281    CbcRounding heuristic1(model);
282    heuristic1.setHeuristicName("rounding");
283    int numberHeuristics = model.numberHeuristics();
284    int iHeuristic;
285    bool found;
286    found = false;
287    for (iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) {
288        CbcHeuristic * heuristic = model.heuristic(iHeuristic);
289        CbcRounding * cgl = dynamic_cast<CbcRounding *>(heuristic);
290        if (cgl) {
291            found = true;
292            break;
293        }
294    }
295    if (!found)
296        model.addHeuristic(&heuristic1);
297#if 0
298    // Allow join solutions
299    CbcHeuristicLocal heuristic2(model);
300    heuristic2.setHeuristicName("join solutions");
301    heuristic2.setSearchType(1);
302    found = false;
303    for (iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) {
304        CbcHeuristic * heuristic = model.heuristic(iHeuristic);
305        CbcHeuristicLocal * cgl = dynamic_cast<CbcHeuristicLocal *>(heuristic);
306        if (cgl) {
307            found = true;
308            break;
309        }
310    }
311    if (!found)
312        model.addHeuristic(&heuristic2);
313#endif
314}
315// Do printing stuff
316void
317CbcStrategyDefault::setupPrinting(CbcModel & model, int modelLogLevel)
318{
319    if (!modelLogLevel) {
320        model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
321        model.messageHandler()->setLogLevel(0);
322        model.solver()->messageHandler()->setLogLevel(0);
323    } else if (modelLogLevel == 1) {
324        model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
325        model.messageHandler()->setLogLevel(1);
326        model.solver()->messageHandler()->setLogLevel(0);
327    } else {
328        model.messageHandler()->setLogLevel(CoinMax(2, model.messageHandler()->logLevel()));
329        model.solver()->messageHandler()->setLogLevel(CoinMax(1, model.solver()->messageHandler()->logLevel()));
330        model.setPrintFrequency(CoinMin(50, model.printFrequency()));
331    }
332}
333// Other stuff e.g. strong branching
334void
335CbcStrategyDefault::setupOther(CbcModel & model)
336{
337    // See if preprocessing wanted
338    if (desiredPreProcess_) {
339        delete process_;
340        // solver_ should have been cloned outside
341        CglPreProcess * process = new CglPreProcess();
342        // Pass in models message handler
343        process->passInMessageHandler(model.messageHandler());
344        OsiSolverInterface * solver = model.solver();
345#ifdef COIN_HAS_CLP
346        OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
347        if (clpSolver && false) {
348            // see if all coefficients multiple of 0.01 (close enough)
349            CoinPackedMatrix * matrix = clpSolver->getModelPtr()->matrix();
350            double * element = matrix->getMutableElements();
351            //const int * row = matrix->getIndices();
352            const CoinBigIndex * columnStart = matrix->getVectorStarts();
353            const int * columnLength = matrix->getVectorLengths();
354            int numberInt = 0;
355            int numberNon = 0;
356            int numberClose = 0;
357            int numberColumns = clpSolver->getNumCols();
358            int iColumn;
359            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
360                for (int j = columnStart[iColumn];
361                        j < columnStart[iColumn] + columnLength[iColumn]; j++) {
362                    //int iRow = row[j];
363                    double value1 = element[j];
364                    double value = fabs(value1);
365                    if (value > 1.0e7) {
366                        if (value != floor(value))
367                            numberNon++;
368                        else
369                            numberInt++;
370                    } else {
371                        int iValue = static_cast<int>( 100 * (value + 0.005));
372                        double value2 = iValue;
373                        if (value2 == 100.0*value) {
374                            numberInt++;
375                        } else if (fabs(value2 - 100.0*value) < 1.0e-5) {
376                            numberClose++;
377                        } else {
378                            numberNon++;
379                        }
380                    }
381                }
382            }
383            if (!numberNon && numberClose) {
384                printf("Tidying %d multiples of 0.01, %d close\n",
385                       numberInt, numberClose);
386                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
387                    for (int j = columnStart[iColumn];
388                            j < columnStart[iColumn] + columnLength[iColumn]; j++) {
389                        //int iRow = row[j];
390                        double value1 = element[j];
391                        double value = fabs(value1);
392                        if (value < 1.0e7) {
393                            int iValue = static_cast<int>( 100 * (value + 0.005));
394                            double value2 = iValue;
395                            if (value2 != 100.0*value) {
396                                value2 *= 0.01;
397                                if (fabs(value - floor(value + 0.5)) <= 1.0e-7)
398                                    value2 = floor(value + 0.5);
399                                if (value1 < 0.0)
400                                    value2 = -value2;
401                                element[j] = value2;
402                            }
403                        }
404                    }
405                }
406            }
407        }
408#endif
409        {
410            // mark some columns as ineligible for presolve
411            int numberColumns = solver->getNumCols();
412            char * prohibited = new char[numberColumns];
413            memset(prohibited, 0, numberColumns);
414            int numberProhibited = 0;
415            // convert to Cbc integers
416            model.findIntegers(false);
417            int numberObjects = model.numberObjects();
418            if (numberObjects) {
419                OsiObject ** objects = model.objects();
420                for (int iObject = 0; iObject < numberObjects; iObject++) {
421                    CbcSOS * obj =
422                        dynamic_cast <CbcSOS *>(objects[iObject]) ;
423                    if (obj) {
424                        // SOS
425                        int n = obj->numberMembers();
426                        const int * which = obj->members();
427                        for (int i = 0; i < n; i++) {
428                            int iColumn = which[i];
429                            prohibited[iColumn] = 1;
430                            numberProhibited++;
431                        }
432                    }
433                }
434            }
435            if (numberProhibited)
436                process->passInProhibited(prohibited, numberColumns);
437            delete [] prohibited;
438        }
439        int logLevel = model.messageHandler()->logLevel();
440#ifdef COIN_HAS_CLP
441        //OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
442        ClpSimplex * lpSolver = NULL;
443        if (clpSolver) {
444            if (clpSolver->messageHandler()->logLevel())
445                clpSolver->messageHandler()->setLogLevel(1);
446            if (logLevel > -1)
447                clpSolver->messageHandler()->setLogLevel(CoinMin(logLevel, clpSolver->messageHandler()->logLevel()));
448            lpSolver = clpSolver->getModelPtr();
449            /// If user left factorization frequency then compute
450            lpSolver->defaultFactorizationFrequency();
451        }
452#endif
453        // Tell solver we are in Branch and Cut
454        solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ;
455        // Default set of cut generators
456        CglProbing generator1;
457        generator1.setUsingObjective(true);
458        generator1.setMaxPass(1);
459        generator1.setMaxPassRoot(1);
460        generator1.setMaxProbeRoot(CoinMin(3000, solver->getNumCols()));
461        generator1.setMaxProbeRoot(123);
462        generator1.setMaxElements(100);
463        generator1.setMaxElementsRoot(200);
464        generator1.setMaxLookRoot(50);
465        generator1.setRowCuts(3);
466        //generator1.messageHandler()->setLogLevel(logLevel);
467        // Not needed with pass in process->messageHandler()->setLogLevel(logLevel);
468        // Add in generators
469        process->addCutGenerator(&generator1);
470        int translate[] = {9999, 0, 2, -2, 3, 4, 4, 4};
471        OsiSolverInterface * solver2 =
472            process->preProcessNonDefault(*solver,
473                                          translate[desiredPreProcess_], preProcessPasses_, 6);
474        // Tell solver we are not in Branch and Cut
475        solver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
476        if (solver2)
477            solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
478        bool feasible = true;
479        if (!solver2) {
480            feasible = false;
481            //printf("Pre-processing says infeasible\n");
482            delete process;
483            preProcessState_ = -1;
484            process_ = NULL;
485        } else {
486            // now tighten bounds
487#ifdef COIN_HAS_CLP
488            if (clpSolver) {
489                // model has changed
490                solver = model.solver();
491                OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
492                ClpSimplex * lpSolver = clpSolver->getModelPtr();
493                lpSolver->passInMessageHandler(solver->messageHandler());
494                if (lpSolver->tightenPrimalBounds() == 0) {
495                    lpSolver->dual();
496                } else {
497                    feasible = false;
498                }
499            }
500#endif
501            if (feasible) {
502                preProcessState_ = 1;
503                process_ = process;
504                /* Note that original solver will be kept (with false)
505                   and that final solver will also be kept.
506                   This is for post-processing
507                */
508                OsiSolverInterface * solver3 = solver2->clone();
509                model.assignSolver(solver3, false);
510                if (process_->numberSOS()) {
511                    int numberSOS = process_->numberSOS();
512                    int numberIntegers = model.numberIntegers();
513                    /* model may not have created objects
514                       If none then create
515                       NOTE - put back to original column numbers as
516                       CbcModel will pack down ALL as it doesn't know where from
517                    */
518                    bool someObjects = model.numberObjects() > 0;
519                    if (!numberIntegers || !model.numberObjects()) {
520                        model.findIntegers(true);
521                        numberIntegers = model.numberIntegers();
522                    }
523                    OsiObject ** oldObjects = model.objects();
524                    // Do sets and priorities
525                    OsiObject ** objects = new OsiObject * [numberSOS];
526                    // set old objects to have low priority
527                    int numberOldObjects = model.numberObjects();
528                    int numberColumns = model.getNumCols();
529                    for (int iObj = 0; iObj < numberOldObjects; iObj++) {
530                        int oldPriority = oldObjects[iObj]->priority();
531                        oldObjects[iObj]->setPriority(numberColumns + oldPriority);
532                    }
533                    const int * starts = process_->startSOS();
534                    const int * which = process_->whichSOS();
535                    const int * type = process_->typeSOS();
536                    const double * weight = process_->weightSOS();
537                    int iSOS;
538                    for (iSOS = 0; iSOS < numberSOS; iSOS++) {
539                        int iStart = starts[iSOS];
540                        int n = starts[iSOS+1] - iStart;
541                        objects[iSOS] = new CbcSOS(&model, n, which + iStart, weight + iStart,
542                                                   iSOS, type[iSOS]);
543                        // branch on long sets first
544                        objects[iSOS]->setPriority(numberColumns - n);
545                    }
546                    model.addObjects(numberSOS, objects);
547                    for (iSOS = 0; iSOS < numberSOS; iSOS++)
548                        delete objects[iSOS];
549                    delete [] objects;
550                    if (!someObjects) {
551                        // put back old column numbers
552                        const int * originalColumns = process_->originalColumns();
553                        // use reverse lookup to fake it
554                        int n = originalColumns[numberColumns-1] + 1;
555                        int * fake = new int[n];
556                        int i;
557                        // This was wrong (now is correct) - so could never have been called
558                        abort();
559                        for ( i = 0; i < n; i++)
560                            fake[i] = -1;
561                        for (i = 0; i < numberColumns; i++)
562                            fake[originalColumns[i]] = i;
563                        for (int iObject = 0; iObject < model.numberObjects(); iObject++) {
564                            // redo ids etc
565                            CbcSimpleInteger * obj =
566                                dynamic_cast <CbcSimpleInteger *>(model.modifiableObject(iObject)) ;
567                            if (obj) {
568                                obj->resetSequenceEtc(n, fake);
569                            } else {
570                                // redo ids etc
571                                CbcObject * obj =
572                                    dynamic_cast <CbcObject *>(model.modifiableObject(iObject)) ;
573                                assert (obj);
574                                obj->redoSequenceEtc(&model, n, fake);
575                            }
576                        }
577                        delete [] fake;
578                    }
579                }
580            } else {
581                //printf("Pre-processing says infeasible\n");
582                delete process;
583                preProcessState_ = -1;
584                process_ = NULL;
585            }
586        }
587    }
588    model.setNumberStrong(numberStrong_);
589    model.setNumberBeforeTrust(numberBeforeTrust_);
590}
591// Create C++ lines to get to current state
592void
593CbcStrategyDefault::generateCpp( FILE * fp)
594{
595    fprintf(fp, "0#include \"CbcStrategy.hpp\"\n");
596    fprintf(fp, "3  CbcStrategyDefault strategy(%s,%d,%d,%d);\n",
597            cutsOnlyAtRoot_ ? "1" : "0",
598            numberStrong_,
599            numberBeforeTrust_,
600            printLevel_);
601    fprintf(fp, "3  strategy.setupPreProcessing(%d,%d);\n",
602            desiredPreProcess_, preProcessPasses_);
603}
604// Default Constructor
605CbcStrategyDefaultSubTree::CbcStrategyDefaultSubTree(CbcModel * parent ,
606        int cutsOnlyAtRoot,
607        int numberStrong,
608        int numberBeforeTrust,
609        int printLevel)
610        : CbcStrategy(),
611        parentModel_(parent),
612        cutsOnlyAtRoot_(cutsOnlyAtRoot),
613        numberStrong_(numberStrong),
614        numberBeforeTrust_(numberBeforeTrust),
615        printLevel_(printLevel)
616{
617}
618
619
620// Destructor
621CbcStrategyDefaultSubTree::~CbcStrategyDefaultSubTree ()
622{
623}
624
625// Clone
626CbcStrategy *
627CbcStrategyDefaultSubTree::clone() const
628{
629    return new CbcStrategyDefaultSubTree(*this);
630}
631
632// Copy constructor
633CbcStrategyDefaultSubTree::CbcStrategyDefaultSubTree(const CbcStrategyDefaultSubTree & rhs)
634        :
635        CbcStrategy(rhs),
636        parentModel_(rhs.parentModel_),
637        cutsOnlyAtRoot_(rhs.cutsOnlyAtRoot_),
638        numberStrong_(rhs.numberStrong_),
639        numberBeforeTrust_(rhs.numberBeforeTrust_),
640        printLevel_(rhs.printLevel_)
641{
642    setNested(rhs.getNested());
643}
644
645// Setup cut generators
646void
647CbcStrategyDefaultSubTree::setupCutGenerators(CbcModel & model)
648{
649    // Set up some cut generators and defaults
650    if (cutsOnlyAtRoot_ < 0)
651        return; // no cuts wanted
652    // Probing first as gets tight bounds on continuous
653
654    CglProbing generator1;
655    generator1.setUsingObjective(true);
656    generator1.setMaxPass(1);
657    // Number of unsatisfied variables to look at
658    generator1.setMaxProbe(10);
659    // How far to follow the consequences
660    generator1.setMaxLook(10);
661    // Only look at rows with fewer than this number of elements
662    generator1.setMaxElements(200);
663    //generator1.setRowCuts(3);
664
665    CglGomory generator2;
666    // try larger limit
667    generator2.setLimit(300);
668
669    CglKnapsackCover generator3;
670
671    //CglOddHole generator4;
672    //generator4.setMinimumViolation(0.005);
673    //generator4.setMinimumViolationPer(0.00002);
674    // try larger limit
675    //generator4.setMaximumEntries(200);
676
677    CglClique generator5;
678    generator5.setStarCliqueReport(false);
679    generator5.setRowCliqueReport(false);
680
681    CglMixedIntegerRounding2 mixedGen;
682    CglFlowCover flowGen;
683
684    // Add in generators
685    int setting = cutsOnlyAtRoot_ ? -99 : -1;
686    int numberGenerators = model.numberCutGenerators();
687    int numberParentGenerators = parentModel_->numberCutGenerators();
688    int iGenerator;
689    bool found;
690    found = false;
691    int howOften = 0;
692    for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) {
693        CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
694        CglProbing * cgl = dynamic_cast<CglProbing *>(generator);
695        if (cgl) {
696            found = true;
697            howOften = parentModel_->cutGenerator(iGenerator)->howOften();
698            break;
699        }
700    }
701
702    if (found && (howOften >= -1 || howOften == -98)) {
703        found = false;
704        for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
705            CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
706            CglProbing * cgl = dynamic_cast<CglProbing *>(generator);
707            if (cgl) {
708                found = true;
709                break;
710            }
711        }
712        if (!found) {
713            if (howOften == -1)
714                howOften = -98;
715            else if (howOften == -98)
716                howOften = -99;
717            model.addCutGenerator(&generator1, setting, "Probing");
718            CbcCutGenerator * generator =
719                model.cutGenerator(numberGenerators);
720            generator->setHowOften(howOften);
721            numberGenerators++;
722        }
723    }
724    found = false;
725    for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) {
726        CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
727        CglGomory * cgl = dynamic_cast<CglGomory *>(generator);
728        if (cgl) {
729            found = true;
730            howOften = parentModel_->cutGenerator(iGenerator)->howOften();
731            break;
732        }
733    }
734    if (found && howOften >= 0) {
735        found = false;
736        for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
737            CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
738            CglGomory * cgl = dynamic_cast<CglGomory *>(generator);
739            if (cgl) {
740                found = true;
741                break;
742            }
743        }
744        if (!found)
745            model.addCutGenerator(&generator2, setting, "Gomory");
746    }
747    found = false;
748    for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) {
749        CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
750        CglKnapsackCover * cgl = dynamic_cast<CglKnapsackCover *>(generator);
751        if (cgl) {
752            found = true;
753            howOften = parentModel_->cutGenerator(iGenerator)->howOften();
754            break;
755        }
756    }
757    if (found && howOften >= 0) {
758        found = false;
759        for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
760            CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
761            CglKnapsackCover * cgl = dynamic_cast<CglKnapsackCover *>(generator);
762            if (cgl) {
763                found = true;
764                break;
765            }
766        }
767        if (!found)
768            model.addCutGenerator(&generator3, setting, "Knapsack");
769    }
770    found = false;
771    for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) {
772        CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
773        CglClique * cgl = dynamic_cast<CglClique *>(generator);
774        if (cgl) {
775            found = true;
776            howOften = parentModel_->cutGenerator(iGenerator)->howOften();
777            break;
778        }
779    }
780    if (found && howOften >= 0) {
781        found = false;
782        for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
783            CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
784            CglClique * cgl = dynamic_cast<CglClique *>(generator);
785            if (cgl) {
786                found = true;
787                break;
788            }
789        }
790        if (!found)
791            model.addCutGenerator(&generator5, setting, "Clique");
792    }
793    found = false;
794    for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) {
795        CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
796        CglFlowCover * cgl = dynamic_cast<CglFlowCover *>(generator);
797        if (cgl) {
798            found = true;
799            howOften = parentModel_->cutGenerator(iGenerator)->howOften();
800            break;
801        }
802    }
803    if (found && howOften >= 0) {
804        found = false;
805        for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
806            CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
807            CglFlowCover * cgl = dynamic_cast<CglFlowCover *>(generator);
808            if (cgl) {
809                found = true;
810                break;
811            }
812        }
813        if (!found)
814            model.addCutGenerator(&flowGen, setting, "FlowCover");
815        found = false;
816    }
817    for (iGenerator = 0; iGenerator < numberParentGenerators; iGenerator++) {
818        CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
819        CglMixedIntegerRounding2 * cgl = dynamic_cast<CglMixedIntegerRounding2 *>(generator);
820        if (cgl) {
821            found = true;
822            howOften = parentModel_->cutGenerator(iGenerator)->howOften();
823            break;
824        }
825    }
826    if (found && howOften >= 0) {
827        found = false;
828        for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
829            CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
830            CglMixedIntegerRounding2 * cgl = dynamic_cast<CglMixedIntegerRounding2 *>(generator);
831            if (cgl) {
832                found = true;
833                break;
834            }
835        }
836        if (!found)
837            model.addCutGenerator(&mixedGen, setting, "MixedIntegerRounding2");
838    }
839#if 0
840    // Say we want timings
841    int newNumberGenerators = model.numberCutGenerators();
842    for (iGenerator = numberGenerators; iGenerator < newNumberGenerators; iGenerator++) {
843        CbcCutGenerator * generator = model.cutGenerator(iGenerator);
844        generator->setTiming(true);
845    }
846#endif
847    if (model.getNumCols() < -500)
848        model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
849    else if (model.getNumCols() < 5000)
850        model.setMaximumCutPassesAtRoot(100); // use minimum drop
851    else
852        model.setMaximumCutPassesAtRoot(20);
853}
854// Setup heuristics
855void
856CbcStrategyDefaultSubTree::setupHeuristics(CbcModel & model)
857{
858    // Allow rounding heuristic
859
860    CbcRounding heuristic1(model);
861    heuristic1.setHeuristicName("rounding");
862    int numberHeuristics = model.numberHeuristics();
863    int iHeuristic;
864    bool found;
865    found = false;
866    for (iHeuristic = 0; iHeuristic < numberHeuristics; iHeuristic++) {
867        CbcHeuristic * heuristic = model.heuristic(iHeuristic);
868        CbcRounding * cgl = dynamic_cast<CbcRounding *>(heuristic);
869        if (cgl) {
870            found = true;
871            break;
872        }
873    }
874    if (!found)
875        model.addHeuristic(&heuristic1);
876}
877// Do printing stuff
878void
879CbcStrategyDefaultSubTree::setupPrinting(CbcModel & model, int modelLogLevel)
880{
881    if (!modelLogLevel) {
882        model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
883        model.messageHandler()->setLogLevel(0);
884        model.solver()->messageHandler()->setLogLevel(0);
885    } else if (modelLogLevel == 1) {
886        model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
887        model.messageHandler()->setLogLevel(1);
888        model.solver()->messageHandler()->setLogLevel(0);
889    } else {
890        model.messageHandler()->setLogLevel(2);
891        model.solver()->messageHandler()->setLogLevel(1);
892        model.setPrintFrequency(50);
893    }
894}
895// Other stuff e.g. strong branching
896void
897CbcStrategyDefaultSubTree::setupOther(CbcModel & model)
898{
899    model.setNumberStrong(numberStrong_);
900    model.setNumberBeforeTrust(numberBeforeTrust_);
901}
902// For uniform setting of cut and heuristic options
903void
904setCutAndHeuristicOptions(CbcModel & model)
905{
906    int numberGenerators = model.numberCutGenerators();
907    int iGenerator;
908    for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
909        CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
910        CglProbing * cglProbing = dynamic_cast<CglProbing *>(generator);
911        if (cglProbing) {
912            cglProbing->setUsingObjective(1);
913            cglProbing->setMaxPass(1);
914            cglProbing->setMaxPassRoot(1);
915            // Number of unsatisfied variables to look at
916            cglProbing->setMaxProbe(10);
917            cglProbing->setMaxProbeRoot(50);
918            //cglProbing->setMaxProbeRoot(123);
919            // How far to follow the consequences
920            cglProbing->setMaxLook(5);
921            cglProbing->setMaxLookRoot(50);
922            cglProbing->setMaxLookRoot(10);
923            // Only look at rows with fewer than this number of elements
924            cglProbing->setMaxElements(200);
925            cglProbing->setMaxElementsRoot(300);
926            cglProbing->setRowCuts(3);
927        }
928#if 0
929        CglGomory * cglGomory = dynamic_cast<CglGomory *>(generator);
930        if (cglGomory) {
931            // try larger limit
932            cglGomory->setLimitAtRoot(1000);
933            cglGomory->setLimit(50);
934        }
935        CglKnapsackCover * cglKnapsackCover = dynamic_cast<CglKnapsackCover *>(generator);
936        if (cglKnapsackCover) {
937        }
938#endif
939    }
940}
941
942
943
Note: See TracBrowser for help on using the repository browser.