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

Last change on this file since 1574 was 1574, checked in by lou, 8 years ago

Change to EPL license notice.

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