source: stable/2.0/Cbc/src/CbcStrategy.cpp @ 905

Last change on this file since 905 was 905, checked in by ladanyi, 13 years ago

include cstdlib before cmath to get things to compile on AIX with xlC (same as changeset 904 in trunk)

  • 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 <cstdlib>
12#include <cmath>
13#include <cfloat>
14
15#include "OsiSolverInterface.hpp"
16#ifdef COIN_HAS_CLP
17#include "OsiClpSolverInterface.hpp"
18#endif
19#include "CbcModel.hpp"
20#include "CbcMessage.hpp"
21#include "CbcStrategy.hpp"
22#include "CbcCutGenerator.hpp"
23#include "CbcBranchActual.hpp"
24#include "CbcNode.hpp"
25#include "CoinWarmStart.hpp"
26#include "CglPreProcess.hpp"
27// Cuts
28
29#include "CglGomory.hpp"
30#include "CglProbing.hpp"
31#include "CglKnapsackCover.hpp"
32#include "CglOddHole.hpp"
33#include "CglClique.hpp"
34#include "CglFlowCover.hpp"
35#include "CglMixedIntegerRounding2.hpp"
36
37// Heuristics
38
39#include "CbcHeuristic.hpp"
40#include "CbcHeuristicLocal.hpp"
41
42// Default Constructor
43CbcStrategy::CbcStrategy() 
44  :depth_(0),
45   preProcessState_(0),
46   process_(NULL)
47{
48}
49
50// Destructor
51CbcStrategy::~CbcStrategy ()
52{
53  delete process_;
54}
55// Delete pre-processing object to save memory
56void 
57CbcStrategy::deletePreProcess()
58{ 
59  delete process_;
60  process_=NULL;
61}
62// Return a new Full node information pointer (descendant of CbcFullNodeInfo)
63CbcNodeInfo * 
64CbcStrategy::fullNodeInfo(CbcModel * model,int numberRowsAtContinuous) const
65{
66  return new CbcFullNodeInfo(model,numberRowsAtContinuous);
67}
68// Return a new Partial node information pointer (descendant of CbcPartialNodeInfo)
69CbcNodeInfo * 
70CbcStrategy::partialNodeInfo(CbcModel * model, CbcNodeInfo * parent, CbcNode * owner,
71                             int numberChangedBounds,const int * variables,
72                             const double * boundChanges,
73                             const CoinWarmStartDiff *basisDiff) const
74{
75  return new CbcPartialNodeInfo(parent, owner, numberChangedBounds, variables,
76                            boundChanges,basisDiff);
77}
78/* After a CbcModel::resolve this can return a status
79   -1 no effect
80   0 treat as optimal
81   1 as 0 but do not do any more resolves (i.e. no more cuts)
82   2 treat as infeasible
83*/
84int
85CbcStrategy::status(CbcModel * model, CbcNodeInfo * parent,int whereFrom)
86{
87  return -1;
88}
89
90// Default Constructor
91CbcStrategyDefault::CbcStrategyDefault(bool cutsOnlyAtRoot,
92                                       int numberStrong,
93                                       int numberBeforeTrust,
94                                       int printLevel)
95  :CbcStrategy(),
96   cutsOnlyAtRoot_(cutsOnlyAtRoot),
97   numberStrong_(numberStrong),
98   numberBeforeTrust_(numberBeforeTrust),
99   printLevel_(printLevel),
100   desiredPreProcess_(0),
101   preProcessPasses_(0)
102{
103}
104
105
106// Destructor
107CbcStrategyDefault::~CbcStrategyDefault ()
108{
109}
110
111// Clone
112CbcStrategy *
113CbcStrategyDefault::clone() const
114{
115  return new CbcStrategyDefault(*this);
116}
117
118// Copy constructor
119CbcStrategyDefault::CbcStrategyDefault(const CbcStrategyDefault & rhs)
120:
121  CbcStrategy(rhs),
122  cutsOnlyAtRoot_(rhs.cutsOnlyAtRoot_),
123  numberStrong_(rhs.numberStrong_),
124  numberBeforeTrust_(rhs.numberBeforeTrust_),
125  printLevel_(rhs.printLevel_),
126  desiredPreProcess_(rhs.desiredPreProcess_),
127  preProcessPasses_(rhs.preProcessPasses_)
128{
129  setNested(rhs.getNested());
130}
131
132// Setup cut generators
133void 
134CbcStrategyDefault::setupCutGenerators(CbcModel & model)
135{
136  // Set up some cut generators and defaults
137  // Probing first as gets tight bounds on continuous
138
139  CglProbing generator1;
140  generator1.setUsingObjective(true);
141  generator1.setMaxPass(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(3);
374    generator1.setMaxProbeRoot(solver->getNumCols());
375    generator1.setMaxElements(100);
376    generator1.setMaxLookRoot(50);
377    generator1.setRowCuts(3);
378    //generator1.messageHandler()->setLogLevel(logLevel);
379    // Not needed with pass in process->messageHandler()->setLogLevel(logLevel);
380    // Add in generators
381    process->addCutGenerator(&generator1);
382    int translate[]={9999,0,3,2,-1,-2};
383    OsiSolverInterface * solver2 = 
384      process->preProcessNonDefault(*solver,
385                                    translate[desiredPreProcess_],preProcessPasses_);
386    // Tell solver we are not in Branch and Cut
387    solver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;
388    if (solver2)
389      solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;
390    bool feasible=true;
391    if (!solver2) {
392      feasible = false;
393      //printf("Pre-processing says infeasible\n");
394      delete process;
395      preProcessState_=-1;
396      process_=NULL;
397    } else {
398      // now tighten bounds
399#ifdef COIN_HAS_CLP
400      if (clpSolver) {
401        // model has changed
402        solver = model.solver();
403        OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
404        ClpSimplex * lpSolver = clpSolver->getModelPtr();
405        lpSolver->passInMessageHandler(solver->messageHandler());
406        if (lpSolver->tightenPrimalBounds()==0) {
407          lpSolver->dual();
408        } else {
409          feasible = false;
410        }
411      }
412#endif
413      if (feasible) {
414        preProcessState_=1;
415        process_=process;
416        /* Note that original solver will be kept (with false)
417           and that final solver will also be kept.
418           This is for post-processing
419        */
420        OsiSolverInterface * solver3 = solver2->clone();
421        model.assignSolver(solver3,false);
422        if (process_->numberSOS()) {
423          int numberSOS = process_->numberSOS();
424          int numberIntegers = model.numberIntegers();
425          /* model may not have created objects
426             If none then create
427             NOTE - put back to original column numbers as
428             CbcModel will pack down ALL as it doesn't know where from
429          */
430          bool someObjects = model.numberObjects()>0;
431          if (!numberIntegers||!model.numberObjects()) {
432            model.findIntegers(true);
433            numberIntegers = model.numberIntegers();
434          }
435          OsiObject ** oldObjects = model.objects();
436          // Do sets and priorities
437          OsiObject ** objects = new OsiObject * [numberSOS];
438          // set old objects to have low priority
439          int numberOldObjects = model.numberObjects();
440          int numberColumns = model.getNumCols();
441          for (int iObj = 0;iObj<numberOldObjects;iObj++) {
442            int oldPriority = oldObjects[iObj]->priority();
443            oldObjects[iObj]->setPriority(numberColumns+oldPriority);
444          }
445          const int * starts = process_->startSOS();
446          const int * which = process_->whichSOS();
447          const int * type = process_->typeSOS();
448          const double * weight = process_->weightSOS();
449          int iSOS;
450          for (iSOS =0;iSOS<numberSOS;iSOS++) {
451            int iStart = starts[iSOS];
452            int n=starts[iSOS+1]-iStart;
453            objects[iSOS] = new CbcSOS(&model,n,which+iStart,weight+iStart,
454                                       iSOS,type[iSOS]);
455            // branch on long sets first
456            objects[iSOS]->setPriority(numberColumns-n);
457          }
458          model.addObjects(numberSOS,objects);
459          for (iSOS=0;iSOS<numberSOS;iSOS++)
460            delete objects[iSOS];
461          delete [] objects;
462          if (!someObjects) {
463            // put back old column numbers
464            const int * originalColumns = process_->originalColumns();
465            // use reverse lookup to fake it
466            int n=originalColumns[numberColumns-1]+1;
467            int * fake = new int[n];
468            int i;
469            for ( i=0;i<n;i++)
470              fake[i]=-1;
471            for (i=0;i<numberColumns;i++)
472              fake[originalColumns[i]]=i;
473            for (int iObject=0;iObject<model.numberObjects();iObject++) {
474              // redo ids etc
475              CbcSimpleInteger * obj =
476                dynamic_cast <CbcSimpleInteger *>(model.modifiableObject(iObject)) ;
477              if (obj) {
478                obj->resetSequenceEtc(n,fake);
479              } else {
480                // redo ids etc
481                CbcObject * obj =
482                  dynamic_cast <CbcObject *>(model.modifiableObject(iObject)) ;
483                assert (obj);
484                obj->redoSequenceEtc(&model,n,fake);
485              }
486            }
487            delete [] fake;
488          }
489        }
490      } else {
491        //printf("Pre-processing says infeasible\n");
492        delete process;
493        preProcessState_=-1;
494        process_=NULL;
495      }
496    }
497  }
498  model.setNumberStrong(numberStrong_);
499  model.setNumberBeforeTrust(numberBeforeTrust_);
500}
501// Create C++ lines to get to current state
502void 
503CbcStrategyDefault::generateCpp( FILE * fp) 
504{
505  fprintf(fp,"0#include \"CbcStrategy.hpp\"\n");
506  fprintf(fp,"3  CbcStrategyDefault strategy(%s,%d,%d,%d);\n",
507          cutsOnlyAtRoot_ ? "true" : "false",
508          numberStrong_,
509          numberBeforeTrust_,
510          printLevel_);
511  fprintf(fp,"3  strategy.setupPreProcessing(%d,%d);\n",
512          desiredPreProcess_,preProcessPasses_);
513}
514// Default Constructor
515CbcStrategyDefaultSubTree::CbcStrategyDefaultSubTree(CbcModel * parent ,
516                                                     bool cutsOnlyAtRoot,
517                                       int numberStrong,
518                                       int numberBeforeTrust,
519                                       int printLevel)
520  :CbcStrategy(),
521   parentModel_(parent),
522   cutsOnlyAtRoot_(cutsOnlyAtRoot),
523   numberStrong_(numberStrong),
524   numberBeforeTrust_(numberBeforeTrust),
525   printLevel_(printLevel)
526{
527}
528
529
530// Destructor
531CbcStrategyDefaultSubTree::~CbcStrategyDefaultSubTree ()
532{
533}
534
535// Clone
536CbcStrategy *
537CbcStrategyDefaultSubTree::clone() const
538{
539  return new CbcStrategyDefaultSubTree(*this);
540}
541
542// Copy constructor
543CbcStrategyDefaultSubTree::CbcStrategyDefaultSubTree(const CbcStrategyDefaultSubTree & rhs)
544:
545  CbcStrategy(rhs),
546  parentModel_(rhs.parentModel_),
547  cutsOnlyAtRoot_(rhs.cutsOnlyAtRoot_),
548  numberStrong_(rhs.numberStrong_),
549  numberBeforeTrust_(rhs.numberBeforeTrust_),
550  printLevel_(rhs.printLevel_)
551{
552  setNested(rhs.getNested());
553}
554
555// Setup cut generators
556void 
557CbcStrategyDefaultSubTree::setupCutGenerators(CbcModel & model)
558{
559  // Set up some cut generators and defaults
560  // Probing first as gets tight bounds on continuous
561
562  CglProbing generator1;
563  generator1.setUsingObjective(true);
564  generator1.setMaxPass(1);
565  // Number of unsatisfied variables to look at
566  generator1.setMaxProbe(10);
567  // How far to follow the consequences
568  generator1.setMaxLook(10);
569  // Only look at rows with fewer than this number of elements
570  generator1.setMaxElements(200);
571  //generator1.setRowCuts(3);
572
573  CglGomory generator2;
574  // try larger limit
575  generator2.setLimit(300);
576
577  CglKnapsackCover generator3;
578
579  //CglOddHole generator4;
580  //generator4.setMinimumViolation(0.005);
581  //generator4.setMinimumViolationPer(0.00002);
582  // try larger limit
583  //generator4.setMaximumEntries(200);
584
585  CglClique generator5;
586  generator5.setStarCliqueReport(false);
587  generator5.setRowCliqueReport(false);
588
589  CglMixedIntegerRounding2 mixedGen;
590  CglFlowCover flowGen;
591 
592  // Add in generators
593  int setting = cutsOnlyAtRoot_ ? -99 : -1;
594  int numberGenerators = model.numberCutGenerators();
595  int numberParentGenerators = parentModel_->numberCutGenerators();
596  int iGenerator;
597  bool found;
598  found=false;
599  int howOften=0;
600  for (iGenerator=0;iGenerator<numberParentGenerators;iGenerator++) {
601    CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
602    CglProbing * cgl = dynamic_cast<CglProbing *>(generator);
603    if (cgl) {
604      found=true;
605      howOften = parentModel_->cutGenerator(iGenerator)->howOften();
606      break;
607    }
608  }
609  if (found&&howOften>=0) {
610    found=false;
611    for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
612      CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
613      CglProbing * cgl = dynamic_cast<CglProbing *>(generator);
614      if (cgl) {
615        found=true;
616        break;
617      }
618    }
619    if (!found) 
620      model.addCutGenerator(&generator1,setting,"Probing");
621  }
622  found=false;
623  for (iGenerator=0;iGenerator<numberParentGenerators;iGenerator++) {
624    CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
625    CglGomory * cgl = dynamic_cast<CglGomory *>(generator);
626    if (cgl) {
627      found=true;
628      howOften = parentModel_->cutGenerator(iGenerator)->howOften();
629      break;
630    }
631  }
632  if (found&&howOften>=0) {
633    found=false;
634    for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
635      CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
636      CglGomory * cgl = dynamic_cast<CglGomory *>(generator);
637      if (cgl) {
638        found=true;
639        break;
640      }
641    }
642    if (!found)
643      model.addCutGenerator(&generator2,setting,"Gomory");
644  }
645  found=false;
646  for (iGenerator=0;iGenerator<numberParentGenerators;iGenerator++) {
647    CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
648    CglKnapsackCover * cgl = dynamic_cast<CglKnapsackCover *>(generator);
649    if (cgl) {
650      found=true;
651      howOften = parentModel_->cutGenerator(iGenerator)->howOften();
652      break;
653    }
654  }
655  if (found&&howOften>=0) {
656    found=false;
657    for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
658      CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
659      CglKnapsackCover * cgl = dynamic_cast<CglKnapsackCover *>(generator);
660      if (cgl) {
661        found=true;
662        break;
663      }
664    }
665    if (!found)
666      model.addCutGenerator(&generator3,setting,"Knapsack");
667  }
668  found=false;
669  for (iGenerator=0;iGenerator<numberParentGenerators;iGenerator++) {
670    CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
671    CglClique * cgl = dynamic_cast<CglClique *>(generator);
672    if (cgl) {
673      found=true;
674      howOften = parentModel_->cutGenerator(iGenerator)->howOften();
675      break;
676    }
677  }
678  if (found&&howOften>=0) {
679    found=false;
680    for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
681      CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
682      CglClique * cgl = dynamic_cast<CglClique *>(generator);
683      if (cgl) {
684        found=true;
685        break;
686      }
687    }
688    if (!found)
689      model.addCutGenerator(&generator5,setting,"Clique");
690  }
691  found=false;
692  for (iGenerator=0;iGenerator<numberParentGenerators;iGenerator++) {
693    CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
694    CglFlowCover * cgl = dynamic_cast<CglFlowCover *>(generator);
695    if (cgl) {
696      found=true;
697      howOften = parentModel_->cutGenerator(iGenerator)->howOften();
698      break;
699    }
700  }
701  if (found&&howOften>=0) {
702    found=false;
703    for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
704      CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
705      CglFlowCover * cgl = dynamic_cast<CglFlowCover *>(generator);
706      if (cgl) {
707        found=true;
708        break;
709      }
710    }
711    if (!found)
712      model.addCutGenerator(&flowGen,setting,"FlowCover");
713    found=false;
714  }
715  for (iGenerator=0;iGenerator<numberParentGenerators;iGenerator++) {
716    CglCutGenerator * generator = parentModel_->cutGenerator(iGenerator)->generator();
717    CglMixedIntegerRounding2 * cgl = dynamic_cast<CglMixedIntegerRounding2 *>(generator);
718    if (cgl) {
719      found=true;
720      howOften = parentModel_->cutGenerator(iGenerator)->howOften();
721      break;
722    }
723  }
724  if (found&&howOften>=0) {
725    found=false;
726    for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
727      CglCutGenerator * generator = model.cutGenerator(iGenerator)->generator();
728      CglMixedIntegerRounding2 * cgl = dynamic_cast<CglMixedIntegerRounding2 *>(generator);
729      if (cgl) {
730        found=true;
731        break;
732      }
733    }
734    if (!found)
735      model.addCutGenerator(&mixedGen,setting,"MixedIntegerRounding2");
736  }
737#if 0
738  // Say we want timings
739  int newNumberGenerators = model.numberCutGenerators();
740  for (iGenerator=numberGenerators;iGenerator<newNumberGenerators;iGenerator++) {
741    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
742    generator->setTiming(true);
743  }
744#endif
745  if (model.getNumCols()<500)
746    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
747  else if (model.getNumCols()<5000)
748    model.setMaximumCutPassesAtRoot(100); // use minimum drop
749  else
750    model.setMaximumCutPassesAtRoot(20);
751}
752// Setup heuristics
753void 
754CbcStrategyDefaultSubTree::setupHeuristics(CbcModel & model)
755{
756  // Allow rounding heuristic
757
758  CbcRounding heuristic1(model);
759  heuristic1.setHeuristicName("rounding");
760  int numberHeuristics = model.numberHeuristics();
761  int iHeuristic;
762  bool found;
763  found=false;
764  for (iHeuristic=0;iHeuristic<numberHeuristics;iHeuristic++) {
765    CbcHeuristic * heuristic = model.heuristic(iHeuristic);
766    CbcRounding * cgl = dynamic_cast<CbcRounding *>(heuristic);
767    if (cgl) {
768      found=true;
769      break;
770    }
771  }
772  if (!found)
773    model.addHeuristic(&heuristic1);
774}
775// Do printing stuff
776void 
777CbcStrategyDefaultSubTree::setupPrinting(CbcModel & model,int modelLogLevel)
778{
779  if (!modelLogLevel) {
780    model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
781    model.messageHandler()->setLogLevel(0);
782    model.solver()->messageHandler()->setLogLevel(0);
783  } else if (modelLogLevel==1) {
784    model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
785    model.messageHandler()->setLogLevel(1);
786    model.solver()->messageHandler()->setLogLevel(0);
787  } else {
788    model.messageHandler()->setLogLevel(2);
789    model.solver()->messageHandler()->setLogLevel(1);
790    model.setPrintFrequency(50);
791  }
792}
793// Other stuff e.g. strong branching
794void 
795CbcStrategyDefaultSubTree::setupOther(CbcModel & model)
796{
797  model.setNumberStrong(numberStrong_);
798  model.setNumberBeforeTrust(numberBeforeTrust_);
799}
800
801
802 
Note: See TracBrowser for help on using the repository browser.