1 // $Id$
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 "CbcConfig.h"
7 
8 #include "CoinPragma.hpp"
9 
10 #include <cassert>
11 #include <iomanip>
12 
13 // For Branch and bound
14 #include "OsiSolverInterface.hpp"
15 #include "CbcModel.hpp"
16 #include "CbcBranchUser.hpp"
17 #include "CbcBranchActual.hpp"
18 #include "CbcCompareUser.hpp"
19 #include "CoinTime.hpp"
20 #include "OsiClpSolverInterface.hpp"
21 
22 //#############################################################################
23 
24 /************************************************************************
25 
26 This main program reads in an SOS model (rgn) from an mps file.
27 
28 It then solves it three ways :-
29 
30 a) As normal
31 b) SOS 1
32 c) SOS 2 (so answer will be different)
33 
34 ************************************************************************/
35 
main(int argc,const char * argv[])36 int main(int argc, const char *argv[])
37 {
38 
39   // Define your favorite OsiSolver
40 
41   OsiClpSolverInterface solver1;
42   //solver1.messageHandler()->setLogLevel(0);
43   CbcModel model(solver1);
44   model.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
45 
46   // Read in rgn.mps
47   std::string mpsFileName;
48 #if defined(MIPLIB3DIR)
49   mpsFileName = MIPLIB3DIR "/rgn";
50 #else
51   if (argc < 2) {
52     fprintf(stderr, "Do not know where to find miplib3 MPS files.\n");
53     exit(1);
54   }
55 #endif
56   if (argc >= 2)
57     mpsFileName = argv[1];
58   int numMpsReadErrors = model.solver()->readMps(mpsFileName.c_str(), "");
59   if (numMpsReadErrors != 0) {
60     printf("%d errors reading MPS file\n", numMpsReadErrors);
61     return numMpsReadErrors;
62   }
63 
64   // Definition of node choice
65   CbcCompareUser compare;
66   compare.setWeight(0.0);
67   model.setNodeComparison(compare);
68   // Reduce output
69   model.messageHandler()->setLogLevel(1);
70   // Get branching messages
71   model.messageHandler()->setLogLevel(3);
72 
73   // Do initial solve to continuous
74   model.initialSolve();
75 
76   // Save model
77   CbcModel model2 = model;
78   int numberColumns = model.getNumCols();
79   int numberIntegers = 0;
80   int *integerVariable = new int[numberColumns];
81   int i;
82   for (i = 0; i < numberColumns; i++) {
83     if (model.isInteger(i)) {
84       integerVariable[numberIntegers++] = i;
85     }
86   }
87 
88   if (numberColumns != 180 || numberIntegers != 100) {
89     printf("Incorrect model for example\n");
90     exit(1);
91   }
92 
93   double time1 = CoinCpuTime();
94 
95   model.branchAndBound();
96 
97   std::cout << "rgn.mps"
98             << " took " << CoinCpuTime() - time1 << " seconds, "
99             << model.getNodeCount() << " nodes with objective "
100             << model.getObjValue()
101             << (!model.status() ? " Finished" : " Not finished")
102             << std::endl;
103 
104   const double *solution = model.solver()->getColSolution();
105 
106   std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14);
107 
108   std::cout << "--------------------------------------" << std::endl;
109   for (i = 0; i < numberIntegers; i++) {
110     int iColumn = integerVariable[i];
111     double value = solution[iColumn];
112     if (fabs(value) > 1.0e-7)
113       std::cout << std::setw(6) << iColumn << " " << value << std::endl;
114   }
115   std::cout << "--------------------------------------" << std::endl;
116 
117   std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific);
118 
119   // Restore model
120   model = model2;
121 
122   // Convert slacks to variables
123   CoinBigIndex start[5] = { 0, 1, 2, 3, 4 };
124   int row[4] = { 0, 1, 2, 3 };
125   double element[4] = { 1.0, 1.0, 1.0, 1.0 };
126   double up[4] = { 1.0, 1.0, 1.0, 1.0 };
127   model.solver()->addCols(4, start, row, element, NULL, up, NULL);
128   // Now use SOS1
129   int numberSets = 4;
130   int which[104];
131   double weights[104];
132   int starts[5];
133   // load
134   int n = 0;
135   starts[0] = 0;
136   for (int iSet = 0; iSet < 4; iSet++) {
137     for (int i = 0; i < 25; i++) {
138       weights[n] = i + 1.0;
139       which[n] = iSet * 25 + i;
140       n++;
141     }
142     // slack - make sure first branch is on slack
143     weights[n] = 1000.0;
144     which[n] = 180 + iSet;
145     n++;
146     starts[iSet + 1] = n;
147   }
148   for (i = 0; i < numberIntegers; i++) {
149     int iColumn = integerVariable[i];
150     // Stop being integer
151     model.solver()->setContinuous(iColumn);
152   }
153   // save model in this state
154   CbcModel modelSOS = model;
155   CbcObject **objects = new CbcObject *[numberSets];
156   for (i = 0; i < numberSets; i++) {
157     objects[i] = new CbcSOS(&model, starts[i + 1] - starts[i], which + starts[i],
158       weights, i);
159   }
160   model.addObjects(numberSets, objects);
161   for (i = 0; i < numberSets; i++)
162     delete objects[i];
163   delete[] objects;
164 
165   time1 = CoinCpuTime();
166 
167   model.branchAndBound();
168 
169   std::cout << "rgn.mps"
170             << " took " << CoinCpuTime() - time1 << " seconds, "
171             << model.getNodeCount() << " nodes with objective "
172             << model.getObjValue()
173             << (!model.status() ? " Finished" : " Not finished")
174             << std::endl;
175 
176   solution = model.solver()->getColSolution();
177 
178   std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14);
179 
180   std::cout << "--------------------------------------" << std::endl;
181   for (i = 0; i < numberIntegers; i++) {
182     int iColumn = integerVariable[i];
183     double value = solution[iColumn];
184     if (fabs(value) > 1.0e-7)
185       std::cout << std::setw(6) << iColumn << " " << value << std::endl;
186   }
187   std::cout << "--------------------------------------" << std::endl;
188 
189   std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific);
190 
191   // Restore SOS model
192   model = modelSOS;
193 
194   // Now use SOS2
195   objects = new CbcObject *[numberSets];
196   for (i = 0; i < numberSets; i++) {
197     objects[i] = new CbcSOS(&model, starts[i + 1] - starts[i], which + starts[i],
198       weights, i, 2);
199   }
200   model.addObjects(numberSets, objects);
201   for (i = 0; i < numberSets; i++)
202     delete objects[i];
203   delete[] objects;
204 
205   time1 = CoinCpuTime();
206 
207   model.branchAndBound();
208 
209   std::cout << "rgn.mps"
210             << " took " << CoinCpuTime() - time1 << " seconds, "
211             << model.getNodeCount() << " nodes with objective "
212             << model.getObjValue()
213             << (!model.status() ? " Finished" : " Not finished")
214             << std::endl;
215 
216   solution = model.solver()->getColSolution();
217 
218   std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14);
219 
220   std::cout << "--------------------------------------" << std::endl;
221 
222   for (i = 0; i < numberIntegers; i++) {
223     int iColumn = integerVariable[i];
224     double value = solution[iColumn];
225     if (fabs(value) > 1.0e-7)
226       std::cout << std::setw(6) << iColumn << " " << value
227                 << std::endl;
228   }
229   std::cout << "--------------------------------------" << std::endl;
230 
231   std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific);
232 
233   delete[] integerVariable;
234   return 0;
235 }
236