source: trunk/Cbc/examples/qmip.cpp

Last change on this file was 1898, checked in by stefan, 5 years ago

fixup examples

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