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

Last change on this file since 1121 was 1121, checked in by forrest, 11 years ago

compiler warnings, deterministic parallel and stability

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