source: branches/devel/Cbc/src/CbcStrategy.cpp @ 648

Last change on this file since 648 was 617, checked in by forrest, 12 years ago

for sos

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