source: trunk/Cbc/src/CbcStrategy.cpp @ 838

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

for deterministic parallel

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