source: stable/2.4/Cbc/src/CbcStrategy.cpp @ 1271

Last change on this file since 1271 was 1271, checked in by forrest, 10 years ago

Creating new stable branch 2.4 from trunk (rev 1270)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.3 KB
Line 
1/* $Id: CbcStrategy.cpp 1271 2009-11-05 15:57:25Z forrest $ */
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.