source: branches/heur/Cbc/src/CbcStrategy.cpp @ 885

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

try and make a bit faster

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