source: trunk/Cbc/examples/qmip.cpp @ 1173

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

add $id

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.3 KB
Line 
1/* $Id: qmip.cpp 1173 2009-06-04 09:44:10Z forrest $ */
2// Copyright (C) 2004, International Business Machines
3// Corporation and others.  All Rights Reserved.
4#if defined(_MSC_VER)
5// Turn off compiler warning about long names
6#  pragma warning(disable:4786)
7#endif
8
9#include <cassert>
10#include <iomanip>
11
12
13// For Branch and bound
14#include "OsiSolverInterface.hpp"
15#include "CbcModel.hpp"
16#include "CbcBranchUser.hpp"
17#include "CbcCompareUser.hpp"
18#include "CbcCutGenerator.hpp"
19#include "CbcHeuristicLocal.hpp"
20#include "ClpQuadInterface.hpp"
21
22// Cuts - some may work but be very very careful
23
24#include "CglProbing.hpp"
25
26// Heuristics would need adapting
27
28#include "CbcHeuristic.hpp"
29
30
31// Time
32#include "CoinTime.hpp"
33
34
35/************************************************************************
36
37This main program reads in a quadratic integer model from an mps file.
38
39It then sets up some Cgl cut generators and calls branch and cut.
40
41Branching is simple binary branching on integer variables.
42
43Node selection is depth first until first solution is found and then
44based on objective and number of unsatisfied integer variables.
45In this example the functionality is the same as default but it is
46a user comparison function.
47
48Variable branching selection is on maximum minimum-of-up-down change
49after strong branching on 5 variables closest to 0.5.
50
51A simple rounding heuristic could be used.but is switched off as needs work for quadratic
52
53This is NOT meant to be a serious MIQP code;  it is to show how you can use
54ClpQuadInterface.hpp to solve a QP at each node.  You could pick up data in that interface
55and use any QP solver (e.g. one that works)
56
57************************************************************************/
58
59int main (int argc, const char *argv[])
60{
61
62  // Define a Solver which inherits from OsiClpsolverInterface -> OsiSolverInterface
63 
64  ClpQuadInterface solver1;
65
66  // Read in model using argv[1]
67  // must use clp to get a quadratic model
68  ClpSimplex * clp = solver1.getModelPtr();
69  int numMpsReadErrors = clp->readMps(argv[1]);
70  // and assert that it is a clean model
71  assert(numMpsReadErrors==0);
72
73  // This clones solver
74  CbcModel model(solver1);
75  // But now model doesn't know about integers!
76  const char * integerInfo = clp->integerInformation();
77  int numberColumns = clp->numberColumns();
78  // and point to solver
79  OsiSolverInterface * solver2 = model.solver();
80  for (int iColumn=0;iColumn<numberColumns;iColumn++) {
81    if (integerInfo[iColumn]) 
82      solver2->setInteger(iColumn);
83  }
84  // Okay - now we have a good MIQP solver
85  // Within branch and cut it is better (at present) to switch off all objectives
86
87  ClpQuadInterface * osiclp = dynamic_cast< ClpQuadInterface*> (solver2);
88  assert (osiclp);
89  // Set fake objective so Cbc not confused
90  osiclp->initialize();
91  solver2->setHintParam(OsiDoReducePrint,true,OsiHintTry);
92
93  // Set up some cut generators and defaults
94  // Probing first as gets tight bounds on continuous
95
96  CglProbing generator1;
97  // can not use objective
98  generator1.setUsingObjective(false);
99  generator1.setMaxPass(3);
100  generator1.setMaxProbe(100);
101  generator1.setMaxLook(50);
102  generator1.setRowCuts(3);
103
104  // Add in generators
105  // Only some generators work (and even then try without first)
106  model.addCutGenerator(&generator1,1,"Probing");
107  // Allow rounding heuristic
108
109  CbcRounding heuristic1(model);
110  // do not add yet as don't know how to deal with quadratic objective
111  //model.addHeuristic(&heuristic1);
112
113
114  // Redundant definition of default branching (as Default == User)
115  CbcBranchUserDecision branch;
116  model.setBranchingMethod(&branch);
117
118  // Definition of node choice
119  CbcCompareUser compare;
120  // breadth first
121  //compare.setWeight(0.0);
122  model.setNodeComparison(compare);
123
124
125  // Do initial solve to continuous
126  model.initialSolve();
127
128  // Could tune more
129  model.setMinimumDrop(CoinMin(1.0,
130                             fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4));
131
132  model.setMaximumCutPassesAtRoot(0);
133  model.setMaximumCutPasses(0);
134
135  // Switch off strong branching if wanted
136  //model.setNumberStrong(5);
137 
138  model.solver()->setIntParam(OsiMaxNumIterationHotStart,10000);
139
140  // If time is given then stop after that number of minutes
141  if (argc>2) {
142    int minutes = atoi(argv[2]);
143    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
144    assert (minutes>=0);
145    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
146  }
147  // Switch off most output
148  if (model.getNumCols()<3000) {
149    model.messageHandler()->setLogLevel(1);
150    //model.solver()->messageHandler()->setLogLevel(0);
151  } else {
152    model.messageHandler()->setLogLevel(2);
153    model.solver()->messageHandler()->setLogLevel(1);
154  }
155  model.setPrintFrequency(50);
156 
157  double time1 = CoinCpuTime();
158
159  // Do complete search
160 
161  model.branchAndBound();
162
163  std::cout<<argv[1]<<" took "<<CoinCpuTime()-time1<<" seconds, "
164           <<model.getNodeCount()<<" nodes with objective "
165           <<model.getObjValue()
166           <<(!model.status() ? " Finished" : " Not finished")
167           <<std::endl;
168
169  // Print more statistics
170  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
171           <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;
172
173  int numberGenerators = model.numberCutGenerators();
174  for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
175    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
176    std::cout<<generator->cutGeneratorName()<<" was tried "
177             <<generator->numberTimesEntered()<<" times and created "
178             <<generator->numberCutsInTotal()<<" cuts of which "
179             <<generator->numberCutsActive()<<" were active after adding rounds of cuts"
180             <<std::endl;
181  }
182  // Print solution if finished - we can't get names from Osi!
183
184  if (!model.status()&&model.getMinimizationObjValue()<1.0e50) {
185    int numberColumns = model.solver()->getNumCols();
186   
187    const double * solution = model.solver()->getColSolution();
188   
189    int iColumn;
190    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
191   
192    std::cout<<"--------------------------------------"<<std::endl;
193    for (iColumn=0;iColumn<numberColumns;iColumn++) {
194      double value=solution[iColumn];
195      if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) 
196        std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
197    }
198    std::cout<<"--------------------------------------"<<std::endl;
199 
200    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
201  }
202  return 0;
203}   
Note: See TracBrowser for help on using the repository browser.