source: trunk/Cbc/test/OsiCbcSolverInterfaceTest.cpp

Last change on this file was 2469, checked in by unxusr, 5 months ago

formatting

  • Property svn:keywords set to Author Date Id Revision
File size: 39.1 KB
Line 
1// $Id: OsiCbcSolverInterfaceTest.cpp 2469 2019-01-06 23:17:46Z tkr $
2// Copyright (C) 2005, 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 "CoinPragma.hpp"
7
8//#include <cassert>
9//#include <cstdlib>
10//#include <cstdio>
11//#include <iostream>
12
13#include "OsiCbcSolverInterface.hpp"
14#include "OsiCuts.hpp"
15#include "OsiRowCut.hpp"
16#include "OsiColCut.hpp"
17#include "OsiUnitTests.hpp"
18#include "CoinMessage.hpp"
19#include "CoinModel.hpp"
20
21//#############################################################################
22
23namespace {
24CoinPackedMatrix &BuildExmip1Mtx()
25/*
26  Simple function to build a packed matrix for the exmip1 example used in
27  tests. The function exists solely to hide the intermediate variables.
28  Probably could be written as an initialised declaration.
29  See COIN/Mps/Sample/exmip1.mps for a human-readable presentation.
30
31  Ordered triples seem easiest. They're listed in row-major order.
32*/
33
34{
35  int rowndxs[] = { 0, 0, 0, 0, 0,
36    1, 1,
37    2, 2,
38    3, 3,
39    4, 4, 4 };
40  int colndxs[] = { 0, 1, 3, 4, 7,
41    1, 2,
42    2, 5,
43    3, 6,
44    0, 4, 7 };
45  double coeffs[] = { 3.0, 1.0, -2.0, -1.0, -1.0,
46    2.0, 1.1,
47    1.0, 1.0,
48    2.8, -1.2,
49    5.6, 1.0, 1.9 };
50
51  static CoinPackedMatrix exmip1mtx = CoinPackedMatrix(true, &rowndxs[0], &colndxs[0], &coeffs[0], 14);
52
53  return (exmip1mtx);
54}
55}
56
57//--------------------------------------------------------------------------
58// test solution methods.
59void OsiCbcSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir)
60{
61  {
62    CoinRelFltEq eq;
63    OsiCbcSolverInterface m;
64    std::string fn = mpsDir + "exmip1";
65    m.readMps(fn.c_str(), "mps");
66
67    {
68      OsiCbcSolverInterface im;
69      OSIUNITTEST_ASSERT_ERROR(im.getNumCols() == 0, {}, "cbc", "default constructor");
70      OSIUNITTEST_ASSERT_ERROR(im.getModelPtr() != NULL, {}, "cbc", "default constructor");
71    }
72
73    // Test copy constructor and assignment operator
74    {
75      OsiCbcSolverInterface lhs;
76      {
77        OsiCbcSolverInterface im(m);
78
79        OsiCbcSolverInterface imC1(im);
80        OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor");
81        OSIUNITTEST_ASSERT_ERROR(imC1.getNumCols() == im.getNumCols(), {}, "cbc", "copy constructor");
82        OSIUNITTEST_ASSERT_ERROR(imC1.getNumRows() == im.getNumRows(), {}, "cbc", "copy constructor");
83
84        OsiCbcSolverInterface imC2(im);
85        OSIUNITTEST_ASSERT_ERROR(imC2.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor");
86        OSIUNITTEST_ASSERT_ERROR(imC2.getNumCols() == im.getNumCols(), {}, "cbc", "copy constructor");
87        OSIUNITTEST_ASSERT_ERROR(imC2.getNumRows() == im.getNumRows(), {}, "cbc", "copy constructor");
88
89        OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != imC2.getModelPtr(), {}, "cbc", "copy constructor");
90
91        lhs = imC2;
92      }
93
94      // Test that lhs has correct values even though rhs has gone out of scope
95      OSIUNITTEST_ASSERT_ERROR(lhs.getModelPtr() != m.getModelPtr(), {}, "cbc", "assignment operator");
96      OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols() == m.getNumCols(), {}, "cbc", "copy constructor");
97      OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows() == m.getNumRows(), {}, "cbc", "copy constructor");
98    }
99
100    // Test clone
101    {
102      OsiCbcSolverInterface cbcSi(m);
103      OsiSolverInterface *siPtr = &cbcSi;
104      OsiSolverInterface *siClone = siPtr->clone();
105      OsiCbcSolverInterface *cbcClone = dynamic_cast< OsiCbcSolverInterface * >(siClone);
106
107      OSIUNITTEST_ASSERT_ERROR(cbcClone != NULL, {}, "cbc", "clone");
108      OSIUNITTEST_ASSERT_ERROR(cbcClone->getModelPtr() != cbcSi.getModelPtr(), {}, "cbc", "clone");
109      OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumRows() == cbcSi.getNumRows(), {}, "cbc", "clone");
110      OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumCols() == m.getNumCols(), {}, "cbc", "clone");
111
112      delete siClone;
113    }
114
115    // test infinity
116    {
117      OsiCbcSolverInterface si;
118      OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == OsiCbcInfinity, {}, "cbc", "infinity");
119    }
120
121    // Test some catches
122    if (!OsiCbcHasNDEBUG()) {
123      OsiCbcSolverInterface solver;
124      try {
125        solver.setObjCoeff(0, 0.0);
126        OSIUNITTEST_ADD_OUTCOME("cbc", "setObjCoeff on empty model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false);
127      } catch (CoinError e) {
128        if (OsiUnitTest::verbosity >= 1)
129          std::cout << "Correct throw from setObjCoeff on empty model" << std::endl;
130      }
131
132      std::string fn = mpsDir + "exmip1";
133      solver.readMps(fn.c_str(), "mps");
134      OSIUNITTEST_CATCH_ERROR(solver.setObjCoeff(0, 0.0), {}, "cbc", "setObjCoeff on nonempty model");
135
136      try {
137        int index[] = { 0, 20 };
138        double value[] = { 0.0, 0.0, 0.0, 0.0 };
139        solver.setColSetBounds(index, index + 2, value);
140        OSIUNITTEST_ADD_OUTCOME("cbc", "setColSetBounds on cols not in model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false);
141      } catch (CoinError e) {
142        if (OsiUnitTest::verbosity >= 1)
143          std::cout << "Correct throw from setObjCoeff on empty model" << std::endl;
144      }
145    }
146
147    {
148      OsiCbcSolverInterface cbcSi(m);
149      int nc = cbcSi.getNumCols();
150      int nr = cbcSi.getNumRows();
151      const double *cl = cbcSi.getColLower();
152      const double *cu = cbcSi.getColUpper();
153      const double *rl = cbcSi.getRowLower();
154      const double *ru = cbcSi.getRowUpper();
155      OSIUNITTEST_ASSERT_ERROR(nc == 8, return, "cbc", "read and copy exmip1");
156      OSIUNITTEST_ASSERT_ERROR(nr == 5, return, "cbc", "read and copy exmip1");
157      OSIUNITTEST_ASSERT_ERROR(eq(cl[0], 2.5), {}, "cbc", "read and copy exmip1");
158      OSIUNITTEST_ASSERT_ERROR(eq(cl[1], 0.0), {}, "cbc", "read and copy exmip1");
159      OSIUNITTEST_ASSERT_ERROR(eq(cu[1], 4.1), {}, "cbc", "read and copy exmip1");
160      OSIUNITTEST_ASSERT_ERROR(eq(cu[2], 1.0), {}, "cbc", "read and copy exmip1");
161      OSIUNITTEST_ASSERT_ERROR(eq(rl[0], 2.5), {}, "cbc", "read and copy exmip1");
162      OSIUNITTEST_ASSERT_ERROR(eq(rl[4], 3.0), {}, "cbc", "read and copy exmip1");
163      OSIUNITTEST_ASSERT_ERROR(eq(ru[1], 2.1), {}, "cbc", "read and copy exmip1");
164      OSIUNITTEST_ASSERT_ERROR(eq(ru[4], 15.), {}, "cbc", "read and copy exmip1");
165
166      const double *cs = cbcSi.getColSolution();
167      OSIUNITTEST_ASSERT_ERROR(eq(cs[0], 2.5), {}, "cbc", "read and copy exmip1");
168      OSIUNITTEST_ASSERT_ERROR(eq(cs[7], 0.0), {}, "cbc", "read and copy exmip1");
169
170      OSIUNITTEST_ASSERT_ERROR(!eq(cl[3], 1.2345), {}, "cbc", "set col lower");
171      cbcSi.setColLower(3, 1.2345);
172      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getColLower()[3], 1.2345), {}, "cbc", "set col lower");
173
174      OSIUNITTEST_ASSERT_ERROR(!eq(cbcSi.getColUpper()[4], 10.2345), {}, "cbc", "set col upper");
175      cbcSi.setColUpper(4, 10.2345);
176      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getColUpper()[4], 10.2345), {}, "cbc", "set col upper");
177
178      // LH: Objective will depend on how underlying solver constructs and maintains initial solution
179      double objValue = cbcSi.getObjValue();
180      OSIUNITTEST_ASSERT_ERROR(eq(objValue, 3.5) || eq(objValue, 10.5), {}, "cbc", "getObjValue() before solve");
181
182      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[0], 1.0), {}, "cbc", "read and copy exmip1");
183      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[1], 0.0), {}, "cbc", "read and copy exmip1");
184      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[2], 0.0), {}, "cbc", "read and copy exmip1");
185      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[3], 0.0), {}, "cbc", "read and copy exmip1");
186      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[4], 2.0), {}, "cbc", "read and copy exmip1");
187      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[5], 0.0), {}, "cbc", "read and copy exmip1");
188      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[6], 0.0), {}, "cbc", "read and copy exmip1");
189      OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[7], -1.0), {}, "cbc", "read and copy exmip1");
190    }
191
192    // Test matrixByRow method
193    {
194      const OsiCbcSolverInterface si(m);
195      const CoinPackedMatrix *smP = si.getMatrixByRow();
196
197      OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim() == 5, return, "cbc", "getMatrixByRow: major dim");
198      OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim() == 8, return, "cbc", "getMatrixByRow: major dim");
199      OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByRow: num elements");
200      OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 6, return, "cbc", "getMatrixByRow: num elements");
201
202#ifdef OSICBC_TEST_MTX_STRUCTURE
203      CoinRelFltEq eq;
204      const double *ev = smP->getElements();
205      OSIUNITTEST_ASSERT_ERROR(eq(ev[0], 3.0), {}, "cbc", "getMatrixByRow: elements");
206      OSIUNITTEST_ASSERT_ERROR(eq(ev[1], 1.0), {}, "cbc", "getMatrixByRow: elements");
207      OSIUNITTEST_ASSERT_ERROR(eq(ev[2], -2.0), {}, "cbc", "getMatrixByRow: elements");
208      OSIUNITTEST_ASSERT_ERROR(eq(ev[3], -1.0), {}, "cbc", "getMatrixByRow: elements");
209      OSIUNITTEST_ASSERT_ERROR(eq(ev[4], -1.0), {}, "cbc", "getMatrixByRow: elements");
210      OSIUNITTEST_ASSERT_ERROR(eq(ev[5], 2.0), {}, "cbc", "getMatrixByRow: elements");
211      OSIUNITTEST_ASSERT_ERROR(eq(ev[6], 1.1), {}, "cbc", "getMatrixByRow: elements");
212      OSIUNITTEST_ASSERT_ERROR(eq(ev[7], 1.0), {}, "cbc", "getMatrixByRow: elements");
213      OSIUNITTEST_ASSERT_ERROR(eq(ev[8], 1.0), {}, "cbc", "getMatrixByRow: elements");
214      OSIUNITTEST_ASSERT_ERROR(eq(ev[9], 2.8), {}, "cbc", "getMatrixByRow: elements");
215      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "cbc", "getMatrixByRow: elements");
216      OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "getMatrixByRow: elements");
217      OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "getMatrixByRow: elements");
218      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "getMatrixByRow: elements");
219
220      const int *mi = smP->getVectorStarts();
221      OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "getMatrixByRow: vector starts");
222      OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "getMatrixByRow: vector starts");
223      OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "getMatrixByRow: vector starts");
224      OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "getMatrixByRow: vector starts");
225      OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "getMatrixByRow: vector starts");
226      OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "getMatrixByRow: vector starts");
227
228      const int *ei = smP->getIndices();
229      OSIUNITTEST_ASSERT_ERROR(ei[0] == 0, {}, "cbc", "getMatrixByRow: indices");
230      OSIUNITTEST_ASSERT_ERROR(ei[1] == 1, {}, "cbc", "getMatrixByRow: indices");
231      OSIUNITTEST_ASSERT_ERROR(ei[2] == 3, {}, "cbc", "getMatrixByRow: indices");
232      OSIUNITTEST_ASSERT_ERROR(ei[3] == 4, {}, "cbc", "getMatrixByRow: indices");
233      OSIUNITTEST_ASSERT_ERROR(ei[4] == 7, {}, "cbc", "getMatrixByRow: indices");
234      OSIUNITTEST_ASSERT_ERROR(ei[5] == 1, {}, "cbc", "getMatrixByRow: indices");
235      OSIUNITTEST_ASSERT_ERROR(ei[6] == 2, {}, "cbc", "getMatrixByRow: indices");
236      OSIUNITTEST_ASSERT_ERROR(ei[7] == 2, {}, "cbc", "getMatrixByRow: indices");
237      OSIUNITTEST_ASSERT_ERROR(ei[8] == 5, {}, "cbc", "getMatrixByRow: indices");
238      OSIUNITTEST_ASSERT_ERROR(ei[9] == 3, {}, "cbc", "getMatrixByRow: indices");
239      OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "getMatrixByRow: indices");
240      OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "getMatrixByRow: indices");
241      OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "getMatrixByRow: indices");
242      OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "getMatrixByRow: indices");
243#else // OSICBC_TEST_MTX_STRUCTURE
244
245      CoinPackedMatrix exmip1Mtx;
246      exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx());
247      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByRow");
248#endif // OSICBC_TEST_MTX_STRUCTURE
249    }
250
251    // Test adding several cuts, and handling of a coefficient of infinity
252    // in the constraint matrix.
253    {
254      OsiCbcSolverInterface fim;
255      std::string fn = mpsDir + "exmip1";
256      fim.readMps(fn.c_str(), "mps");
257      // exmip1.mps has 2 integer variables with index 2 & 3
258      fim.initialSolve();
259      OsiRowCut cuts[3];
260
261      // Generate one ineffective cut plus two trivial cuts
262      int c;
263      int nc = fim.getNumCols();
264      int *inx = new int[nc];
265      for (c = 0; c < nc; c++)
266        inx[c] = c;
267      double *el = new double[nc];
268      for (c = 0; c < nc; c++)
269        el[c] = 1.0e-50 + ((double)c) * ((double)c);
270
271      cuts[0].setRow(nc, inx, el);
272      cuts[0].setLb(-100.);
273      cuts[0].setUb(500.);
274      cuts[0].setEffectiveness(22);
275      el[4] = 0.0; // to get inf later
276
277      for (c = 2; c < 4; c++) {
278        el[0] = 1.0;
279        inx[0] = c;
280        cuts[c - 1].setRow(1, inx, el);
281        cuts[c - 1].setLb(1.);
282        cuts[c - 1].setUb(100.);
283        cuts[c - 1].setEffectiveness(c);
284      }
285      fim.writeMps("x1.mps");
286      fim.applyRowCuts(3, cuts);
287      fim.writeMps("x2.mps");
288      // resolve - should get message about zero elements
289      fim.resolve();
290      fim.writeMps("x3.mps");
291      // check integer solution
292      const double *cs = fim.getColSolution();
293      CoinRelFltEq eq;
294      OSIUNITTEST_ASSERT_ERROR(eq(cs[2], 1.0), {}, "cbc", "add cuts");
295      OSIUNITTEST_ASSERT_ERROR(eq(cs[3], 1.0), {}, "cbc", "add cuts");
296      // check will find invalid matrix
297      el[0] = 1.0 / el[4];
298      inx[0] = 0;
299      cuts[0].setRow(nc, inx, el);
300      cuts[0].setLb(-100.);
301      cuts[0].setUb(500.);
302      cuts[0].setEffectiveness(22);
303      fim.applyRowCut(cuts[0]);
304      // resolve - should get message about zero elements
305      fim.resolve();
306      OSIUNITTEST_ASSERT_WARNING(fim.isAbandoned(), {}, "cbc", "add cuts");
307      delete[] el;
308      delete[] inx;
309    }
310
311    // Test matrixByCol method
312    {
313      const OsiCbcSolverInterface si(m);
314      const CoinPackedMatrix *smP = si.getMatrixByCol();
315
316      OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim() == 8, return, "cbc", "getMatrixByCol: major dim");
317      OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim() == 5, return, "cbc", "getMatrixByCol: minor dim");
318      OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByCol: number of elements");
319      OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 9, return, "cbc", "getMatrixByCol: vector starts size");
320
321#ifdef OSICBC_TEST_MTX_STRUCTURE
322      CoinRelFltEq eq;
323      const double *ev = smP->getElements();
324      OSIUNITTEST_ASSERT_ERROR(eq(ev[0], 3.0), {}, "cbc", "getMatrixByCol: elements");
325      OSIUNITTEST_ASSERT_ERROR(eq(ev[1], 5.6), {}, "cbc", "getMatrixByCol: elements");
326      OSIUNITTEST_ASSERT_ERROR(eq(ev[2], 1.0), {}, "cbc", "getMatrixByCol: elements");
327      OSIUNITTEST_ASSERT_ERROR(eq(ev[3], 2.0), {}, "cbc", "getMatrixByCol: elements");
328      OSIUNITTEST_ASSERT_ERROR(eq(ev[4], 1.1), {}, "cbc", "getMatrixByCol: elements");
329      OSIUNITTEST_ASSERT_ERROR(eq(ev[5], 1.0), {}, "cbc", "getMatrixByCol: elements");
330      OSIUNITTEST_ASSERT_ERROR(eq(ev[6], -2.0), {}, "cbc", "getMatrixByCol: elements");
331      OSIUNITTEST_ASSERT_ERROR(eq(ev[7], 2.8), {}, "cbc", "getMatrixByCol: elements");
332      OSIUNITTEST_ASSERT_ERROR(eq(ev[8], -1.0), {}, "cbc", "getMatrixByCol: elements");
333      OSIUNITTEST_ASSERT_ERROR(eq(ev[9], 1.0), {}, "cbc", "getMatrixByCol: elements");
334      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 1.0), {}, "cbc", "getMatrixByCol: elements");
335      OSIUNITTEST_ASSERT_ERROR(eq(ev[11], -1.2), {}, "cbc", "getMatrixByCol: elements");
336      OSIUNITTEST_ASSERT_ERROR(eq(ev[12], -1.0), {}, "cbc", "getMatrixByCol: elements");
337      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "getMatrixByCol: elements");
338
339      const CoinBigIndex *mi = smP->getVectorStarts();
340      OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "getMatrixByCol: vector starts");
341      OSIUNITTEST_ASSERT_ERROR(mi[1] == 2, {}, "cbc", "getMatrixByCol: vector starts");
342      OSIUNITTEST_ASSERT_ERROR(mi[2] == 4, {}, "cbc", "getMatrixByCol: vector starts");
343      OSIUNITTEST_ASSERT_ERROR(mi[3] == 6, {}, "cbc", "getMatrixByCol: vector starts");
344      OSIUNITTEST_ASSERT_ERROR(mi[4] == 8, {}, "cbc", "getMatrixByCol: vector starts");
345      OSIUNITTEST_ASSERT_ERROR(mi[5] == 10, {}, "cbc", "getMatrixByCol: vector starts");
346      OSIUNITTEST_ASSERT_ERROR(mi[6] == 11, {}, "cbc", "getMatrixByCol: vector starts");
347      OSIUNITTEST_ASSERT_ERROR(mi[7] == 12, {}, "cbc", "getMatrixByCol: vector starts");
348      OSIUNITTEST_ASSERT_ERROR(mi[8] == 14, {}, "cbc", "getMatrixByCol: vector starts");
349
350      const int *ei = smP->getIndices();
351      OSIUNITTEST_ASSERT_ERROR(ei[0] == 0, {}, "cbc", "getMatrixByCol: indices");
352      OSIUNITTEST_ASSERT_ERROR(ei[1] == 4, {}, "cbc", "getMatrixByCol: indices");
353      OSIUNITTEST_ASSERT_ERROR(ei[2] == 0, {}, "cbc", "getMatrixByCol: indices");
354      OSIUNITTEST_ASSERT_ERROR(ei[3] == 1, {}, "cbc", "getMatrixByCol: indices");
355      OSIUNITTEST_ASSERT_ERROR(ei[4] == 1, {}, "cbc", "getMatrixByCol: indices");
356      OSIUNITTEST_ASSERT_ERROR(ei[5] == 2, {}, "cbc", "getMatrixByCol: indices");
357      OSIUNITTEST_ASSERT_ERROR(ei[6] == 0, {}, "cbc", "getMatrixByCol: indices");
358      OSIUNITTEST_ASSERT_ERROR(ei[7] == 3, {}, "cbc", "getMatrixByCol: indices");
359      OSIUNITTEST_ASSERT_ERROR(ei[8] == 0, {}, "cbc", "getMatrixByCol: indices");
360      OSIUNITTEST_ASSERT_ERROR(ei[9] == 4, {}, "cbc", "getMatrixByCol: indices");
361      OSIUNITTEST_ASSERT_ERROR(ei[10] == 2, {}, "cbc", "getMatrixByCol: indices");
362      OSIUNITTEST_ASSERT_ERROR(ei[11] == 3, {}, "cbc", "getMatrixByCol: indices");
363      OSIUNITTEST_ASSERT_ERROR(ei[12] == 0, {}, "cbc", "getMatrixByCol: indices");
364      OSIUNITTEST_ASSERT_ERROR(ei[13] == 4, {}, "cbc", "getMatrixByCol: indices");
365#else // OSICBC_TEST_MTX_STRUCTURE
366
367      CoinPackedMatrix &exmip1Mtx = BuildExmip1Mtx();
368      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByCol");
369#endif // OSICBC_TEST_MTX_STRUCTURE
370    }
371
372    //--------------
373    // Test rowsense, rhs, rowrange, matrixByRow, solver assignment
374    {
375      OsiCbcSolverInterface lhs;
376      {
377        OsiCbcSolverInterface siC1(m);
378
379        const char *siC1rs = siC1.getRowSense();
380        OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense");
381        OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense");
382        OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense");
383        OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense");
384        OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense");
385
386        const double *siC1rhs = siC1.getRightHandSide();
387        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0], 2.5), {}, "cbc", "right hand side");
388        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1], 2.1), {}, "cbc", "right hand side");
389        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2], 4.0), {}, "cbc", "right hand side");
390        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3], 5.0), {}, "cbc", "right hand side");
391        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4], 15.), {}, "cbc", "right hand side");
392
393        const double *siC1rr = siC1.getRowRange();
394        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0], 0.0), {}, "cbc", "row range");
395        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1], 0.0), {}, "cbc", "row range");
396        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2], 0.0), {}, "cbc", "row range");
397        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3], 5.0 - 1.8), {}, "cbc", "row range");
398        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4], 15.0 - 3.0), {}, "cbc", "row range");
399
400        const CoinPackedMatrix *siC1mbr = siC1.getMatrixByRow();
401        OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "cbc", "matrix by row");
402        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim() == 5, return, "cbc", "matrix by row: major dim");
403        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMinorDim() == 8, return, "cbc", "matrix by row: major dim");
404        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "cbc", "matrix by row: num elements");
405        OSIUNITTEST_ASSERT_ERROR(siC1mbr->getSizeVectorStarts() == 6, return, "cbc", "matrix by row: num elements");
406
407#ifdef OSICBC_TEST_MTX_STRUCTURE
408        const double *ev = siC1mbr->getElements();
409        OSIUNITTEST_ASSERT_ERROR(eq(ev[0], 3.0), {}, "cbc", "matrix by row: elements");
410        OSIUNITTEST_ASSERT_ERROR(eq(ev[1], 1.0), {}, "cbc", "matrix by row: elements");
411        OSIUNITTEST_ASSERT_ERROR(eq(ev[2], -2.0), {}, "cbc", "matrix by row: elements");
412        OSIUNITTEST_ASSERT_ERROR(eq(ev[3], -1.0), {}, "cbc", "matrix by row: elements");
413        OSIUNITTEST_ASSERT_ERROR(eq(ev[4], -1.0), {}, "cbc", "matrix by row: elements");
414        OSIUNITTEST_ASSERT_ERROR(eq(ev[5], 2.0), {}, "cbc", "matrix by row: elements");
415        OSIUNITTEST_ASSERT_ERROR(eq(ev[6], 1.1), {}, "cbc", "matrix by row: elements");
416        OSIUNITTEST_ASSERT_ERROR(eq(ev[7], 1.0), {}, "cbc", "matrix by row: elements");
417        OSIUNITTEST_ASSERT_ERROR(eq(ev[8], 1.0), {}, "cbc", "matrix by row: elements");
418        OSIUNITTEST_ASSERT_ERROR(eq(ev[9], 2.8), {}, "cbc", "matrix by row: elements");
419        OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "cbc", "matrix by row: elements");
420        OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row: elements");
421        OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row: elements");
422        OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row: elements");
423
424        const CoinBigIndex *mi = siC1mbr->getVectorStarts();
425        OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "matrix by row: vector starts");
426        OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "matrix by row: vector starts");
427        OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "matrix by row: vector starts");
428        OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "matrix by row: vector starts");
429        OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row: vector starts");
430        OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row: vector starts");
431
432        const int *ei = siC1mbr->getIndices();
433        OSIUNITTEST_ASSERT_ERROR(ei[0] == 0, {}, "cbc", "matrix by row: indices");
434        OSIUNITTEST_ASSERT_ERROR(ei[1] == 1, {}, "cbc", "matrix by row: indices");
435        OSIUNITTEST_ASSERT_ERROR(ei[2] == 3, {}, "cbc", "matrix by row: indices");
436        OSIUNITTEST_ASSERT_ERROR(ei[3] == 4, {}, "cbc", "matrix by row: indices");
437        OSIUNITTEST_ASSERT_ERROR(ei[4] == 7, {}, "cbc", "matrix by row: indices");
438        OSIUNITTEST_ASSERT_ERROR(ei[5] == 1, {}, "cbc", "matrix by row: indices");
439        OSIUNITTEST_ASSERT_ERROR(ei[6] == 2, {}, "cbc", "matrix by row: indices");
440        OSIUNITTEST_ASSERT_ERROR(ei[7] == 2, {}, "cbc", "matrix by row: indices");
441        OSIUNITTEST_ASSERT_ERROR(ei[8] == 5, {}, "cbc", "matrix by row: indices");
442        OSIUNITTEST_ASSERT_ERROR(ei[9] == 3, {}, "cbc", "matrix by row: indices");
443        OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row: indices");
444        OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row: indices");
445        OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row: indices");
446        OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row: indices");
447#else // OSICBC_TEST_MTX_STRUCTURE
448
449        CoinPackedMatrix exmip1Mtx;
450        exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx());
451        OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*siC1mbr), {}, "cbc", "matrix by row");
452#endif // OSICBC_TEST_MTX_STRUCTURE
453
454        OSIUNITTEST_ASSERT_WARNING(siC1rs == siC1.getRowSense(), {}, "cbc", "row sense");
455        OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "cbc", "right hand side");
456        OSIUNITTEST_ASSERT_WARNING(siC1rr == siC1.getRowRange(), {}, "cbc", "row range");
457
458        // Change CBC Model by adding free row
459        OsiRowCut rc;
460        rc.setLb(-COIN_DBL_MAX);
461        rc.setUb(COIN_DBL_MAX);
462        OsiCuts cuts;
463        cuts.insert(rc);
464        siC1.applyCuts(cuts);
465
466        siC1rs = siC1.getRowSense();
467        OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense after adding row");
468        OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense after adding row");
469        OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense after adding row");
470        OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense after adding row");
471        OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense after adding row");
472        OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "cbc", "row sense after adding row");
473
474        siC1rhs = siC1.getRightHandSide();
475        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0], 2.5), {}, "cbc", "right hand side after adding row");
476        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1], 2.1), {}, "cbc", "right hand side after adding row");
477        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2], 4.0), {}, "cbc", "right hand side after adding row");
478        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3], 5.0), {}, "cbc", "right hand side after adding row");
479        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4], 15.), {}, "cbc", "right hand side after adding row");
480        OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5], 0.0), {}, "cbc", "right hand side after adding row");
481
482        siC1rr = siC1.getRowRange();
483        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0], 0.0), {}, "cbc", "row range after adding row");
484        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1], 0.0), {}, "cbc", "row range after adding row");
485        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2], 0.0), {}, "cbc", "row range after adding row");
486        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3], 5.0 - 1.8), {}, "cbc", "row range after adding row");
487        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4], 15.0 - 3.0), {}, "cbc", "row range after adding row");
488        OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5], 0.0), {}, "cbc", "row range after adding row");
489
490        lhs = siC1;
491      }
492
493      // Test that lhs has correct values even though siC1 has gone out of scope
494      const char *lhsrs = lhs.getRowSense();
495      OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "cbc", "row sense after assignment");
496      OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "cbc", "row sense after assignment");
497      OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "cbc", "row sense after assignment");
498      OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "cbc", "row sense after assignment");
499      OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "cbc", "row sense after assignment");
500      OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "cbc", "row sense after assignment");
501
502      const double *lhsrhs = lhs.getRightHandSide();
503      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0], 2.5), {}, "cbc", "right hand side after assignment");
504      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1], 2.1), {}, "cbc", "right hand side after assignment");
505      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2], 4.0), {}, "cbc", "right hand side after assignment");
506      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3], 5.0), {}, "cbc", "right hand side after assignment");
507      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4], 15.), {}, "cbc", "right hand side after assignment");
508      OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5], 0.0), {}, "cbc", "right hand side after assignment");
509
510      const double *lhsrr = lhs.getRowRange();
511      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0], 0.0), {}, "cbc", "row range after assignment");
512      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1], 0.0), {}, "cbc", "row range after assignment");
513      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2], 0.0), {}, "cbc", "row range after assignment");
514      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3], 5.0 - 1.8), {}, "cbc", "row range after assignment");
515      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4], 15.0 - 3.0), {}, "cbc", "row range after assignment");
516      OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5], 0.0), {}, "cbc", "row range after assignment");
517
518      const CoinPackedMatrix *lhsmbr = lhs.getMatrixByRow();
519      OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "cbc", "matrix by row after assignment");
520      OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim() == 6, return, "cbc", "matrix by row after assignment: major dim");
521      OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "cbc", "matrix by row after assignment: num elements");
522
523#ifdef OSICBC_TEST_MTX_STRUCTURE
524      const double *ev = lhsmbr->getElements();
525      OSIUNITTEST_ASSERT_ERROR(eq(ev[0], 3.0), {}, "cbc", "matrix by row after assignment: elements");
526      OSIUNITTEST_ASSERT_ERROR(eq(ev[1], 1.0), {}, "cbc", "matrix by row after assignment: elements");
527      OSIUNITTEST_ASSERT_ERROR(eq(ev[2], -2.0), {}, "cbc", "matrix by row after assignment: elements");
528      OSIUNITTEST_ASSERT_ERROR(eq(ev[3], -1.0), {}, "cbc", "matrix by row after assignment: elements");
529      OSIUNITTEST_ASSERT_ERROR(eq(ev[4], -1.0), {}, "cbc", "matrix by row after assignment: elements");
530      OSIUNITTEST_ASSERT_ERROR(eq(ev[5], 2.0), {}, "cbc", "matrix by row after assignment: elements");
531      OSIUNITTEST_ASSERT_ERROR(eq(ev[6], 1.1), {}, "cbc", "matrix by row after assignment: elements");
532      OSIUNITTEST_ASSERT_ERROR(eq(ev[7], 1.0), {}, "cbc", "matrix by row after assignment: elements");
533      OSIUNITTEST_ASSERT_ERROR(eq(ev[8], 1.0), {}, "cbc", "matrix by row after assignment: elements");
534      OSIUNITTEST_ASSERT_ERROR(eq(ev[9], 2.8), {}, "cbc", "matrix by row after assignment: elements");
535      OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "cbc", "matrix by row after assignment: elements");
536      OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row after assignment: elements");
537      OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row after assignment: elements");
538      OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row after assignment: elements");
539
540      const CoinBigIndex *mi = lhsmbr->getVectorStarts();
541      OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "matrix by row after assignment: vector starts");
542      OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "matrix by row after assignment: vector starts");
543      OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "matrix by row after assignment: vector starts");
544      OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "matrix by row after assignment: vector starts");
545      OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row after assignment: vector starts");
546      OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row after assignment: vector starts");
547
548      const int *ei = lhsmbr->getIndices();
549      OSIUNITTEST_ASSERT_ERROR(ei[0] == 0, {}, "cbc", "matrix by row after assignment: indices");
550      OSIUNITTEST_ASSERT_ERROR(ei[1] == 1, {}, "cbc", "matrix by row after assignment: indices");
551      OSIUNITTEST_ASSERT_ERROR(ei[2] == 3, {}, "cbc", "matrix by row after assignment: indices");
552      OSIUNITTEST_ASSERT_ERROR(ei[3] == 4, {}, "cbc", "matrix by row after assignment: indices");
553      OSIUNITTEST_ASSERT_ERROR(ei[4] == 7, {}, "cbc", "matrix by row after assignment: indices");
554      OSIUNITTEST_ASSERT_ERROR(ei[5] == 1, {}, "cbc", "matrix by row after assignment: indices");
555      OSIUNITTEST_ASSERT_ERROR(ei[6] == 2, {}, "cbc", "matrix by row after assignment: indices");
556      OSIUNITTEST_ASSERT_ERROR(ei[7] == 2, {}, "cbc", "matrix by row after assignment: indices");
557      OSIUNITTEST_ASSERT_ERROR(ei[8] == 5, {}, "cbc", "matrix by row after assignment: indices");
558      OSIUNITTEST_ASSERT_ERROR(ei[9] == 3, {}, "cbc", "matrix by row after assignment: indices");
559      OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row after assignment: indices");
560      OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row after assignment: indices");
561      OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row after assignment: indices");
562      OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row after assignment: indices");
563#else // OSICBC_TEST_MTX_STRUCTURE
564
565      /*
566  This admittedly looks bogus, but it's the equivalent operation on the matrix
567  for inserting a cut of the form -Inf <= +Inf (i.e., a cut with no
568  coefficients).
569*/
570      CoinPackedMatrix exmip1Mtx;
571      exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx());
572      CoinPackedVector freeRow;
573      exmip1Mtx.appendRow(freeRow);
574      OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*lhsmbr), {}, "cbc", "matrix by row after assignment");
575#endif // OSICBC_TEST_MTX_STRUCTURE
576    }
577  }
578
579  // Test add/delete columns
580  {
581    OsiCbcSolverInterface m;
582    std::string fn = mpsDir + "p0033";
583    m.readMps(fn.c_str(), "mps");
584    double inf = m.getInfinity();
585
586    CoinPackedVector c0;
587    c0.insert(0, 4);
588    c0.insert(1, 1);
589    m.addCol(c0, 0, inf, 3);
590    m.initialSolve();
591    double objValue = m.getObjValue();
592    CoinRelFltEq eq(1.0e-2);
593    OSIUNITTEST_ASSERT_ERROR(eq(objValue, 2520.57), {}, "cbc", "objvalue after adding col");
594
595    // Try deleting first column that's nonbasic at lower bound (0).
596    int *d = new int[1];
597    CoinWarmStartBasis *cwsb = dynamic_cast< CoinWarmStartBasis * >(m.getWarmStart());
598    OSIUNITTEST_ASSERT_ERROR(cwsb != NULL, {}, "cbc", "get warmstart basis");
599    CoinWarmStartBasis::Status stati;
600    int iCol;
601    for (iCol = 0; iCol < cwsb->getNumStructural(); iCol++) {
602      stati = cwsb->getStructStatus(iCol);
603      if (stati == CoinWarmStartBasis::atLowerBound)
604        break;
605    }
606    d[0] = iCol;
607    m.deleteCols(1, d);
608    delete[] d;
609    delete cwsb;
610    d = NULL;
611    m.resolve();
612    objValue = m.getObjValue();
613    OSIUNITTEST_ASSERT_ERROR(eq(objValue, 2520.57), {}, "clp", "objvalue after deleting first col");
614
615    // Try deleting column we added. If basic, go to initialSolve as deleting
616    // basic variable trashes basis required for warm start.
617    iCol = m.getNumCols() - 1;
618    cwsb = dynamic_cast< CoinWarmStartBasis * >(m.getWarmStart());
619    stati = cwsb->getStructStatus(iCol);
620    delete cwsb;
621    m.deleteCols(1, &iCol);
622    if (stati == CoinWarmStartBasis::basic) {
623      m.initialSolve();
624    } else {
625      m.resolve();
626    }
627    objValue = m.getObjValue();
628    OSIUNITTEST_ASSERT_ERROR(eq(objValue, 2520.57), {}, "clp", "objvalue after deleting added col");
629  }
630
631  // Build a model
632  {
633    OsiCbcSolverInterface model;
634    std::string fn = mpsDir + "p0033";
635    model.readMps(fn.c_str(), "mps");
636    // Point to data
637    int numberRows = model.getNumRows();
638    const double *rowLower = model.getRowLower();
639    const double *rowUpper = model.getRowUpper();
640    int numberColumns = model.getNumCols();
641    const double *columnLower = model.getColLower();
642    const double *columnUpper = model.getColUpper();
643    const double *columnObjective = model.getObjCoefficients();
644    // get row copy
645    CoinPackedMatrix rowCopy = *model.getMatrixByRow();
646    const int *column = rowCopy.getIndices();
647    const int *rowLength = rowCopy.getVectorLengths();
648    const CoinBigIndex *rowStart = rowCopy.getVectorStarts();
649    const double *element = rowCopy.getElements();
650
651    // solve
652    model.initialSolve();
653    // Now build new model
654    CoinModel build;
655    // Row bounds
656    int iRow;
657    for (iRow = 0; iRow < numberRows; iRow++) {
658      build.setRowBounds(iRow, rowLower[iRow], rowUpper[iRow]);
659    }
660    // Column bounds and objective
661    int iColumn;
662    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
663      build.setColumnLower(iColumn, columnLower[iColumn]);
664      build.setColumnUpper(iColumn, columnUpper[iColumn]);
665      build.setObjective(iColumn, columnObjective[iColumn]);
666    }
667    // Adds elements one by one by row (backwards by row)
668    for (iRow = numberRows - 1; iRow >= 0; iRow--) {
669      int start = rowStart[iRow];
670      for (int j = start; j < start + rowLength[iRow]; j++)
671        build(iRow, column[j], element[j]);
672    }
673    // Now create Model
674    OsiCbcSolverInterface model2;
675    model2.loadFromCoinModel(build);
676    model2.initialSolve();
677    // Save - should be continuous
678    model2.writeMps("continuous");
679    int *whichInteger = new int[numberColumns];
680    for (iColumn = 0; iColumn < numberColumns; iColumn++)
681      whichInteger[iColumn] = iColumn;
682    // mark as integer
683    model2.setInteger(whichInteger, numberColumns);
684    delete[] whichInteger;
685    // save - should be integer
686    model2.writeMps("integer");
687
688    // Now do with strings attached
689    // Save build to show how to go over rows
690    CoinModel saveBuild = build;
691    build = CoinModel();
692    // Column bounds
693    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
694      build.setColumnLower(iColumn, columnLower[iColumn]);
695      build.setColumnUpper(iColumn, columnUpper[iColumn]);
696    }
697    // Objective - half the columns as is and half with multiplier of "1.0+multiplier"
698    // Pick up from saveBuild (for no reason at all)
699    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
700      double value = saveBuild.objective(iColumn);
701      if (iColumn * 2 < numberColumns) {
702        build.setObjective(iColumn, columnObjective[iColumn]);
703      } else {
704        // create as string
705        char temp[100];
706        sprintf(temp, "%g + abs(%g*multiplier)", value, value);
707        build.setObjective(iColumn, temp);
708      }
709    }
710    // It then adds rows one by one but for half the rows sets their values
711    //      with multiplier of "1.0+1.5*multiplier"
712    for (iRow = 0; iRow < numberRows; iRow++) {
713      if (iRow * 2 < numberRows) {
714        // add row in simple way
715        int start = rowStart[iRow];
716        build.addRow(rowLength[iRow], column + start, element + start,
717          rowLower[iRow], rowUpper[iRow]);
718      } else {
719        // As we have to add one by one let's get from saveBuild
720        CoinModelLink triple = saveBuild.firstInRow(iRow);
721        while (triple.column() >= 0) {
722          int iColumn = triple.column();
723          if (iColumn * 2 < numberColumns) {
724            // just value as normal
725            build(iRow, triple.column(), triple.value());
726          } else {
727            // create as string
728            char temp[100];
729            sprintf(temp, "%g + (1.5*%g*multiplier)", triple.value(), triple.value());
730            build(iRow, iColumn, temp);
731          }
732          triple = saveBuild.next(triple);
733        }
734        // but remember to do rhs
735        build.setRowLower(iRow, rowLower[iRow]);
736        build.setRowUpper(iRow, rowUpper[iRow]);
737      }
738    }
739    // If small switch on error printing
740    if (numberColumns < 50)
741      build.setLogLevel(1);
742    // should fail as we never set multiplier
743    OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) != 0, {}, "cbc", "build model with missing multipliers");
744    build.associateElement("multiplier", 0.0);
745    OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) == 0, {}, "cbc", "build model");
746    model2.initialSolve();
747    // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1
748    for (double multiplier = 0.0; multiplier < 2.0; multiplier += 0.1) {
749      build.associateElement("multiplier", multiplier);
750      OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build, true) == 0, {}, "cbc", "build model with increasing multiplier");
751      model2.resolve();
752    }
753  }
754
755  // branch and bound
756  {
757    OsiCbcSolverInterface m;
758    std::string fn = mpsDir + "p0033";
759    m.readMps(fn.c_str(), "mps");
760    m.initialSolve();
761    //m.messageHandler()->setLogLevel(0);
762    m.getModelPtr()->messageHandler()->setLogLevel(0);
763    m.branchAndBound();
764  }
765
766  // branch and bound using CbcModel!!!!!!!
767  {
768    OsiCbcSolverInterface mm;
769    OsiCbcSolverInterface m(&mm);
770    std::string fn = mpsDir + "p0033";
771    m.readMps(fn.c_str(), "mps");
772    m.initialSolve();
773    m.branchAndBound();
774  }
775
776  // Do common solverInterface testing
777  {
778    OsiCbcSolverInterface m;
779    OsiSolverInterfaceCommonUnitTest(&m, mpsDir, netlibDir);
780  }
781  {
782    OsiCbcSolverInterface mm;
783    OsiCbcSolverInterface m(&mm);
784    OsiSolverInterfaceCommonUnitTest(&m, mpsDir, netlibDir);
785  }
786}
Note: See TracBrowser for help on using the repository browser.