OaDecompositionBase::solverManip::solverManip (const OsiSolverInterface & si): si_(NULL), initialNumberRows_(-1), colLower_(NULL), colUpper_(NULL), warm_(NULL), cutoff_(DBL_MAX), deleteSolver_(true), objects_(NULL), nObjects_(0) { si_ = si.clone(); getCached(); }
void LinearCutsGenerator::generateCuts(const OsiSolverInterface &solver, OsiCuts &cs, const CglTreeInfo info) const { //const OsiTMINLPInterface * tmp = dynamic_cast<const OsiTMINLPInterface *>(&solver); OsiTMINLPInterface * nlp = dynamic_cast<OsiTMINLPInterface *>(solver.clone());//const_cast<OsiTMINLPInterface *>(tmp); assert(nlp); OuterApprox oa; //si.writeMps("toto"); int numberRows = nlp->getNumRows(); for(int i = 0 ; i < 5 ; i++){ nlp->resolve(); OsiClpSolverInterface si; oa(*nlp, &si, solver.getColSolution(), true); si.resolve(); OsiCuts cuts; for(std::list<Coin::SmartPtr<CuttingMethod> >::const_iterator i = methods_.begin() ; i != methods_.end() ; i++){ (*i)->cgl->generateCuts(si, cuts, info); } std::vector<OsiRowCut *> mycuts(cuts.sizeRowCuts()); for(int i = 0 ; i < cuts.sizeRowCuts() ; i++){ mycuts[i] = cuts.rowCutPtr(i); cs.insert(*mycuts[i]); } nlp->applyRowCuts(mycuts.size(), const_cast<const OsiRowCut **> (&mycuts[0])); } // Take off slack cuts std::vector<int> kept; int numberRowsNow = nlp->getNumRows(); int * del = new int [numberRowsNow-numberRows]; nlp->resolve(); const double * activity = nlp->getRowActivity(); const double * lb = nlp->getRowLower(); const double * ub = nlp->getRowUpper(); CoinRelFltEq eq(1e-06); //int nDelete=0; for (int i=numberRowsNow -1;i>=numberRows;i--) { if ( !(eq(activity[i], lb[i]) || eq(activity[i], ub[i])) ) cs.eraseRowCut(i - numberRows); } delete [] del; delete nlp; }
int changeCbcSolver (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast<CbcGenParam *>(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; CoinMessageHandler *msghandler = ctlBlk->messageHandler() ; /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Try to locate the solver specified by the user. */ const std::string solverName = genParam->kwdVal() ; OsiSolverInterface *protoOsi = solvers[solverName] ; if (protoOsi == 0) { std::cerr << "Can't find solver \"" << solverName << "\" in the solvers vector." << std::endl ; return (retval) ; } ctlBlk->dfltSolver_ = protoOsi ; /* We have a solver. */ ctlBlk->message(CBCGEN_NEW_SOLVER) << solverName << CoinMessageEol ; CbcModel *model = ctlBlk->model_ ; assert (model != 0) ; OsiSolverInterface *newOsi = protoOsi->clone() ; model->assignSolver(newOsi) ; return (0) ; }
//-------------------------------------------------------------------------- // test solution methods. void OsiCbcSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir) { { CoinRelFltEq eq; OsiCbcSolverInterface m; std::string fn = mpsDir+"exmip1"; m.readMps(fn.c_str(),"mps"); { OsiCbcSolverInterface im; OSIUNITTEST_ASSERT_ERROR(im.getNumCols() == 0, {}, "cbc", "default constructor"); OSIUNITTEST_ASSERT_ERROR(im.getModelPtr() != NULL, {}, "cbc", "default constructor"); } // Test copy constructor and assignment operator { OsiCbcSolverInterface lhs; { OsiCbcSolverInterface im(m); OsiCbcSolverInterface imC1(im); OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getNumCols() == im.getNumCols(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getNumRows() == im.getNumRows(), {}, "cbc", "copy constructor"); OsiCbcSolverInterface imC2(im); OSIUNITTEST_ASSERT_ERROR(imC2.getModelPtr() != im.getModelPtr(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC2.getNumCols() == im.getNumCols(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC2.getNumRows() == im.getNumRows(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != imC2.getModelPtr(), {}, "cbc", "copy constructor"); lhs = imC2; } // Test that lhs has correct values even though rhs has gone out of scope OSIUNITTEST_ASSERT_ERROR(lhs.getModelPtr() != m.getModelPtr(), {}, "cbc", "assignment operator"); OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols() == m.getNumCols(), {}, "cbc", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows() == m.getNumRows(), {}, "cbc", "copy constructor"); } // Test clone { OsiCbcSolverInterface cbcSi(m); OsiSolverInterface * siPtr = &cbcSi; OsiSolverInterface * siClone = siPtr->clone(); OsiCbcSolverInterface * cbcClone = dynamic_cast<OsiCbcSolverInterface*>(siClone); OSIUNITTEST_ASSERT_ERROR(cbcClone != NULL, {}, "cbc", "clone"); OSIUNITTEST_ASSERT_ERROR(cbcClone->getModelPtr() != cbcSi.getModelPtr(), {}, "cbc", "clone"); OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumRows() == cbcSi.getNumRows(), {}, "cbc", "clone"); OSIUNITTEST_ASSERT_ERROR(cbcClone->getNumCols() == m.getNumCols(), {}, "cbc", "clone"); delete siClone; } // test infinity { OsiCbcSolverInterface si; OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == OsiCbcInfinity, {}, "cbc", "infinity"); } // Test some catches if (!OsiCbcHasNDEBUG()) { OsiCbcSolverInterface solver; try { solver.setObjCoeff(0,0.0); OSIUNITTEST_ADD_OUTCOME("cbc", "setObjCoeff on empty model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false); } catch (CoinError e) { if (OsiUnitTest::verbosity >= 1) std::cout<<"Correct throw from setObjCoeff on empty model"<<std::endl; } std::string fn = mpsDir+"exmip1"; solver.readMps(fn.c_str(),"mps"); OSIUNITTEST_CATCH_ERROR(solver.setObjCoeff(0,0.0), {}, "cbc", "setObjCoeff on nonempty model"); try { int index[]={0,20}; double value[]={0.0,0.0,0.0,0.0}; solver.setColSetBounds(index,index+2,value); OSIUNITTEST_ADD_OUTCOME("cbc", "setColSetBounds on cols not in model", "should throw exception", OsiUnitTest::TestOutcome::ERROR, false); } catch (CoinError e) { if (OsiUnitTest::verbosity >= 1) std::cout<<"Correct throw from setObjCoeff on empty model"<<std::endl; } } { OsiCbcSolverInterface cbcSi(m); int nc = cbcSi.getNumCols(); int nr = cbcSi.getNumRows(); const double * cl = cbcSi.getColLower(); const double * cu = cbcSi.getColUpper(); const double * rl = cbcSi.getRowLower(); const double * ru = cbcSi.getRowUpper(); OSIUNITTEST_ASSERT_ERROR(nc == 8, return, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(nr == 5, return, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cl[0],2.5), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cl[1],0.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cu[1],4.1), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cu[2],1.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(rl[0],2.5), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(rl[4],3.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(ru[1],2.1), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(ru[4],15.), {}, "cbc", "read and copy exmip1"); const double * cs = cbcSi.getColSolution(); OSIUNITTEST_ASSERT_ERROR(eq(cs[0],2.5), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cs[7],0.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(!eq(cl[3],1.2345), {}, "cbc", "set col lower"); cbcSi.setColLower( 3, 1.2345 ); OSIUNITTEST_ASSERT_ERROR( eq(cbcSi.getColLower()[3],1.2345), {}, "cbc", "set col lower"); OSIUNITTEST_ASSERT_ERROR(!eq(cbcSi.getColUpper()[4],10.2345), {}, "cbc", "set col upper"); cbcSi.setColUpper( 4, 10.2345 ); OSIUNITTEST_ASSERT_ERROR( eq(cbcSi.getColUpper()[4],10.2345), {}, "cbc", "set col upper"); // LH: Objective will depend on how underlying solver constructs and maintains initial solution double objValue = cbcSi.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,3.5) || eq(objValue,10.5), {}, "cbc", "getObjValue() before solve"); OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[0], 1.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[1], 0.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[2], 0.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[3], 0.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[4], 2.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[5], 0.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[6], 0.0), {}, "cbc", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cbcSi.getObjCoefficients()[7],-1.0), {}, "cbc", "read and copy exmip1"); } // Test matrixByRow method { const OsiCbcSolverInterface si(m); const CoinPackedMatrix * smP = si.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim() == 5, return, "cbc", "getMatrixByRow: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim() == 8, return, "cbc", "getMatrixByRow: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByRow: num elements"); OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 6, return, "cbc", "getMatrixByRow: num elements"); #ifdef OSICBC_TEST_MTX_STRUCTURE CoinRelFltEq eq; const double * ev = smP->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[0], 3.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[1], 1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[2], -2.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[3], -1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[4], -1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[5], 2.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[6], 1.1), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[7], 1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[8], 1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[9], 2.8), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "getMatrixByRow: elements"); const int * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "getMatrixByRow: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "getMatrixByRow: indices"); #else // OSICBC_TEST_MTX_STRUCTURE CoinPackedMatrix exmip1Mtx ; exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ; OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByRow") ; #endif // OSICBC_TEST_MTX_STRUCTURE } // Test adding several cuts, and handling of a coefficient of infinity // in the constraint matrix. { OsiCbcSolverInterface fim; std::string fn = mpsDir+"exmip1"; fim.readMps(fn.c_str(),"mps"); // exmip1.mps has 2 integer variables with index 2 & 3 fim.initialSolve(); OsiRowCut cuts[3]; // Generate one ineffective cut plus two trivial cuts int c; int nc = fim.getNumCols(); int *inx = new int[nc]; for (c=0;c<nc;c++) inx[c]=c; double *el = new double[nc]; for (c=0;c<nc;c++) el[c]=1.0e-50+((double)c)*((double)c); cuts[0].setRow(nc,inx,el); cuts[0].setLb(-100.); cuts[0].setUb(500.); cuts[0].setEffectiveness(22); el[4]=0.0; // to get inf later for (c=2;c<4;c++) { el[0]=1.0; inx[0]=c; cuts[c-1].setRow(1,inx,el); cuts[c-1].setLb(1.); cuts[c-1].setUb(100.); cuts[c-1].setEffectiveness(c); } fim.writeMps("x1.mps"); fim.applyRowCuts(3,cuts); fim.writeMps("x2.mps"); // resolve - should get message about zero elements fim.resolve(); fim.writeMps("x3.mps"); // check integer solution const double * cs = fim.getColSolution(); CoinRelFltEq eq; OSIUNITTEST_ASSERT_ERROR(eq(cs[2], 1.0), {}, "cbc", "add cuts"); OSIUNITTEST_ASSERT_ERROR(eq(cs[3], 1.0), {}, "cbc", "add cuts"); // check will find invalid matrix el[0]=1.0/el[4]; inx[0]=0; cuts[0].setRow(nc,inx,el); cuts[0].setLb(-100.); cuts[0].setUb(500.); cuts[0].setEffectiveness(22); fim.applyRowCut(cuts[0]); // resolve - should get message about zero elements fim.resolve(); OSIUNITTEST_ASSERT_WARNING(fim.isAbandoned(), {}, "cbc", "add cuts"); delete[]el; delete[]inx; } // Test matrixByCol method { const OsiCbcSolverInterface si(m); const CoinPackedMatrix * smP = si.getMatrixByCol(); OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim() == 8, return, "cbc", "getMatrixByCol: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim() == 5, return, "cbc", "getMatrixByCol: minor dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "cbc", "getMatrixByCol: number of elements"); OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 9, return, "cbc", "getMatrixByCol: vector starts size"); #ifdef OSICBC_TEST_MTX_STRUCTURE CoinRelFltEq eq; const double * ev = smP->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 5.6), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2], 1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 2.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 1.1), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6],-2.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 2.8), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8],-1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11],-1.2), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12],-1.0), {}, "cbc", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "getMatrixByCol: elements"); const CoinBigIndex * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 2, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 4, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 6, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 8, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 10, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[6] == 11, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[7] == 12, {}, "cbc", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[8] == 14, {}, "cbc", "getMatrixByCol: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 1, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 3, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 4, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 2, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 3, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 0, {}, "cbc", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 4, {}, "cbc", "getMatrixByCol: indices"); #else // OSICBC_TEST_MTX_STRUCTURE CoinPackedMatrix &exmip1Mtx = BuildExmip1Mtx() ; OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*smP), {}, "cbc", "getMatrixByCol"); #endif // OSICBC_TEST_MTX_STRUCTURE } //-------------- // Test rowsense, rhs, rowrange, matrixByRow, solver assignment { OsiCbcSolverInterface lhs; { OsiCbcSolverInterface siC1(m); const char * siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense"); const double * siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "cbc", "right hand side"); const double * siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "cbc", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "cbc", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "cbc", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "cbc", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "cbc", "row range"); const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "cbc", "matrix by row"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim() == 5, return, "cbc", "matrix by row: major dim"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMinorDim() == 8, return, "cbc", "matrix by row: major dim"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "cbc", "matrix by row: num elements"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getSizeVectorStarts() == 6, return, "cbc", "matrix by row: num elements"); #ifdef OSICBC_TEST_MTX_STRUCTURE const double * ev = siC1mbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row: elements"); const CoinBigIndex * mi = siC1mbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row: vector starts"); const int * ei = siC1mbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row: indices"); #else // OSICBC_TEST_MTX_STRUCTURE CoinPackedMatrix exmip1Mtx ; exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ; OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*siC1mbr), {}, "cbc", "matrix by row"); #endif // OSICBC_TEST_MTX_STRUCTURE OSIUNITTEST_ASSERT_WARNING(siC1rs == siC1.getRowSense(), {}, "cbc", "row sense"); OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "cbc", "right hand side"); OSIUNITTEST_ASSERT_WARNING(siC1rr == siC1.getRowRange(), {}, "cbc", "row range"); // Change CBC Model by adding free row OsiRowCut rc; rc.setLb(-COIN_DBL_MAX); rc.setUb( COIN_DBL_MAX); OsiCuts cuts; cuts.insert(rc); siC1.applyCuts(cuts); siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "cbc", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "cbc", "row sense after adding row"); siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "cbc", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "cbc", "right hand side after adding row"); siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "cbc", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "cbc", "row range after adding row"); lhs = siC1; } // Test that lhs has correct values even though siC1 has gone out of scope const char * lhsrs = lhs.getRowSense(); OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "cbc", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "cbc", "row sense after assignment"); const double * lhsrhs = lhs.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "cbc", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "cbc", "right hand side after assignment"); const double *lhsrr = lhs.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "cbc", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "cbc", "row range after assignment"); const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "cbc", "matrix by row after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim() == 6, return, "cbc", "matrix by row after assignment: major dim"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "cbc", "matrix by row after assignment: num elements"); #ifdef OSICBC_TEST_MTX_STRUCTURE const double * ev = lhsmbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "cbc", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "cbc", "matrix by row after assignment: elements"); const CoinBigIndex * mi = lhsmbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "cbc", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "cbc", "matrix by row after assignment: vector starts"); const int * ei = lhsmbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "cbc", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "cbc", "matrix by row after assignment: indices"); #else // OSICBC_TEST_MTX_STRUCTURE /* This admittedly looks bogus, but it's the equivalent operation on the matrix for inserting a cut of the form -Inf <= +Inf (i.e., a cut with no coefficients). */ CoinPackedMatrix exmip1Mtx ; exmip1Mtx.reverseOrderedCopyOf(BuildExmip1Mtx()) ; CoinPackedVector freeRow ; exmip1Mtx.appendRow(freeRow) ; OSIUNITTEST_ASSERT_ERROR(exmip1Mtx.isEquivalent(*lhsmbr), {}, "cbc", "matrix by row after assignment"); #endif // OSICBC_TEST_MTX_STRUCTURE } } // Test add/delete columns { OsiCbcSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); double inf = m.getInfinity(); CoinPackedVector c0; c0.insert(0, 4); c0.insert(1, 1); m.addCol(c0, 0, inf, 3); m.initialSolve(); double objValue = m.getObjValue(); CoinRelFltEq eq(1.0e-2); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "cbc", "objvalue after adding col"); // Try deleting first column that's nonbasic at lower bound (0). int * d = new int[1]; CoinWarmStartBasis *cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ; OSIUNITTEST_ASSERT_ERROR(cwsb != NULL, {}, "cbc", "get warmstart basis"); CoinWarmStartBasis::Status stati ; int iCol ; for (iCol = 0 ; iCol < cwsb->getNumStructural() ; iCol++) { stati = cwsb->getStructStatus(iCol) ; if (stati == CoinWarmStartBasis::atLowerBound) break ; } d[0]=iCol; m.deleteCols(1,d); delete [] d; delete cwsb; d=NULL; m.resolve(); objValue = m.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting first col"); // Try deleting column we added. If basic, go to initialSolve as deleting // basic variable trashes basis required for warm start. iCol = m.getNumCols()-1; cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ; stati = cwsb->getStructStatus(iCol) ; delete cwsb; m.deleteCols(1,&iCol); if (stati == CoinWarmStartBasis::basic) { m.initialSolve() ; } else { m.resolve(); } objValue = m.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting added col"); } // Build a model { OsiCbcSolverInterface model; std::string fn = mpsDir+"p0033"; model.readMps(fn.c_str(),"mps"); // Point to data int numberRows = model.getNumRows(); const double * rowLower = model.getRowLower(); const double * rowUpper = model.getRowUpper(); int numberColumns = model.getNumCols(); const double * columnLower = model.getColLower(); const double * columnUpper = model.getColUpper(); const double * columnObjective = model.getObjCoefficients(); // get row copy CoinPackedMatrix rowCopy = *model.getMatrixByRow(); const int * column = rowCopy.getIndices(); const int * rowLength = rowCopy.getVectorLengths(); const CoinBigIndex * rowStart = rowCopy.getVectorStarts(); const double * element = rowCopy.getElements(); // solve model.initialSolve(); // Now build new model CoinModel build; // Row bounds int iRow; for (iRow=0;iRow<numberRows;iRow++) { build.setRowBounds(iRow,rowLower[iRow],rowUpper[iRow]); } // Column bounds and objective int iColumn; for (iColumn=0;iColumn<numberColumns;iColumn++) { build.setColumnLower(iColumn,columnLower[iColumn]); build.setColumnUpper(iColumn,columnUpper[iColumn]); build.setObjective(iColumn,columnObjective[iColumn]); } // Adds elements one by one by row (backwards by row) for (iRow=numberRows-1;iRow>=0;iRow--) { int start = rowStart[iRow]; for (int j=start;j<start+rowLength[iRow];j++) build(iRow,column[j],element[j]); } // Now create Model OsiCbcSolverInterface model2; model2.loadFromCoinModel(build); model2.initialSolve(); // Save - should be continuous model2.writeMps("continuous"); int * whichInteger = new int[numberColumns]; for (iColumn=0;iColumn<numberColumns;iColumn++) whichInteger[iColumn]=iColumn; // mark as integer model2.setInteger(whichInteger,numberColumns); delete [] whichInteger; // save - should be integer model2.writeMps("integer"); // Now do with strings attached // Save build to show how to go over rows CoinModel saveBuild = build; build = CoinModel(); // Column bounds for (iColumn=0;iColumn<numberColumns;iColumn++) { build.setColumnLower(iColumn,columnLower[iColumn]); build.setColumnUpper(iColumn,columnUpper[iColumn]); } // Objective - half the columns as is and half with multiplier of "1.0+multiplier" // Pick up from saveBuild (for no reason at all) for (iColumn=0;iColumn<numberColumns;iColumn++) { double value = saveBuild.objective(iColumn); if (iColumn*2<numberColumns) { build.setObjective(iColumn,columnObjective[iColumn]); } else { // create as string char temp[100]; sprintf(temp,"%g + abs(%g*multiplier)",value,value); build.setObjective(iColumn,temp); } } // It then adds rows one by one but for half the rows sets their values // with multiplier of "1.0+1.5*multiplier" for (iRow=0;iRow<numberRows;iRow++) { if (iRow*2<numberRows) { // add row in simple way int start = rowStart[iRow]; build.addRow(rowLength[iRow],column+start,element+start, rowLower[iRow],rowUpper[iRow]); } else { // As we have to add one by one let's get from saveBuild CoinModelLink triple=saveBuild.firstInRow(iRow); while (triple.column()>=0) { int iColumn = triple.column(); if (iColumn*2<numberColumns) { // just value as normal build(iRow,triple.column(),triple.value()); } else { // create as string char temp[100]; sprintf(temp,"%g + (1.5*%g*multiplier)",triple.value(), triple.value()); build(iRow,iColumn,temp); } triple=saveBuild.next(triple); } // but remember to do rhs build.setRowLower(iRow,rowLower[iRow]); build.setRowUpper(iRow,rowUpper[iRow]); } } // If small switch on error printing if (numberColumns<50) build.setLogLevel(1); // should fail as we never set multiplier OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) != 0, {}, "cbc", "build model with missing multipliers"); build.associateElement("multiplier",0.0); OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build) == 0, {}, "cbc", "build model"); model2.initialSolve(); // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1 for (double multiplier=0.0;multiplier<2.0;multiplier+= 0.1) { build.associateElement("multiplier",multiplier); OSIUNITTEST_ASSERT_ERROR(model2.loadFromCoinModel(build,true) == 0, {}, "cbc", "build model with increasing multiplier"); model2.resolve(); } } // branch and bound { OsiCbcSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); m.initialSolve(); //m.messageHandler()->setLogLevel(0); m.getModelPtr()->messageHandler()->setLogLevel(0); m.branchAndBound(); } // branch and bound using CbcModel!!!!!!! { OsiCbcSolverInterface mm; OsiCbcSolverInterface m(&mm); std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); m.initialSolve(); m.branchAndBound(); } // Do common solverInterface testing { OsiCbcSolverInterface m; OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir); } { OsiCbcSolverInterface mm; OsiCbcSolverInterface m(&mm); OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir); } }
void OsiSpxSolverInterfaceUnitTest( const std::string & mpsDir, const std::string & netlibDir ) { // Test default constructor { OsiSpxSolverInterface m; OSIUNITTEST_ASSERT_ERROR(m.soplex_ != NULL, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.getNumCols() == 0, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rowsense_ == NULL, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rhs_ == NULL, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rowrange_ == NULL, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.colsol_ == NULL, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rowsol_ == NULL, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.matrixByRow_ == NULL, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.matrixByCol_ == NULL, {}, "SoPlex", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.getApplicationData() == NULL, {}, "SoPlex", "default constructor"); int i=2346; m.setApplicationData(&i); OSIUNITTEST_ASSERT_ERROR(*((int *)(m.getApplicationData())) == i, {}, "SoPlex", "set application data"); } { CoinRelFltEq eq; OsiSpxSolverInterface m; std::string fn = mpsDir+"exmip1"; m.readMps(fn.c_str(),"mps"); // int ad = 13579; // m.setApplicationData(&ad); // OSIUNITTEST_ASSERT_ERROR(*((int *)(m.getApplicationData())) == ad, {}, "SoPlex", "set application data"); { const CoinPackedMatrix * colCopy = m.getMatrixByCol(); OSIUNITTEST_ASSERT_ERROR(colCopy->getNumCols() == 8, {}, "SoPlex", "exmip1 matrix"); OSIUNITTEST_ASSERT_ERROR(colCopy->getMajorDim() == 8, {}, "SoPlex", "exmip1 matrix"); OSIUNITTEST_ASSERT_ERROR(colCopy->getNumRows() == 5, {}, "SoPlex", "exmip1 matrix"); OSIUNITTEST_ASSERT_ERROR(colCopy->getMinorDim() == 5, {}, "SoPlex", "exmip1 matrix"); OSIUNITTEST_ASSERT_ERROR(colCopy->getVectorLengths()[7] == 2, {}, "SoPlex", "exmip1 matrix"); CoinPackedMatrix revColCopy; revColCopy.reverseOrderedCopyOf(*colCopy); CoinPackedMatrix rev2ColCopy; rev2ColCopy.reverseOrderedCopyOf(revColCopy); OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getNumCols() == 8, {}, "SoPlex", "twice reverse matrix copy"); OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getMajorDim() == 8, {}, "SoPlex", "twice reverse matrix copy"); OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getNumRows() == 5, {}, "SoPlex", "twice reverse matrix copy"); OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getMinorDim() == 5, {}, "SoPlex", "twice reverse matrix copy"); OSIUNITTEST_ASSERT_ERROR(rev2ColCopy.getVectorLengths()[7] == 2, {}, "SoPlex", "twice reverse matrix copy"); } // Test copy constructor and assignment operator { OsiSpxSolverInterface lhs; { OsiSpxSolverInterface im(m); OsiSpxSolverInterface imC1(im); OsiSpxSolverInterface imC2(im); lhs = imC2; } // Test that lhs has correct values even though rhs has gone out of scope OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols() == m.getNumCols(), {}, "SoPlex", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows() == m.getNumRows(), {}, "SoPlex", "copy constructor"); } // Test clone { OsiSpxSolverInterface soplexSi(m); OsiSolverInterface * siPtr = &soplexSi; OsiSolverInterface * siClone = siPtr->clone(); OsiSpxSolverInterface * soplexClone = dynamic_cast<OsiSpxSolverInterface*>(siClone); OSIUNITTEST_ASSERT_ERROR(soplexClone != NULL, {}, "SoPlex", "clone"); OSIUNITTEST_ASSERT_ERROR(soplexClone->getNumRows() == soplexSi.getNumRows(), {}, "SoPlex", "clone"); OSIUNITTEST_ASSERT_ERROR(soplexClone->getNumCols() == m.getNumCols(), {}, "SoPlex", "clone"); delete siClone; } // test infinity { OsiSpxSolverInterface si; OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == soplex::infinity, {}, "SoPlex", "value for infinity"); } { OsiSpxSolverInterface soplexSi(m); int nc = soplexSi.getNumCols(); int nr = soplexSi.getNumRows(); const double * cl = soplexSi.getColLower(); const double * cu = soplexSi.getColUpper(); const double * rl = soplexSi.getRowLower(); const double * ru = soplexSi.getRowUpper(); OSIUNITTEST_ASSERT_ERROR(nc == 8, return, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(nr == 5, return, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cl[0],2.5), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cl[1],0.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cu[1],4.1), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cu[2],1.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(rl[0],2.5), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(rl[4],3.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(ru[1],2.1), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(ru[4],15.), {}, "SoPlex", "read and copy exmip1"); double newCs[8] = {1., 2., 3., 4., 5., 6., 7., 8.}; soplexSi.setColSolution(newCs); const double * cs = soplexSi.getColSolution(); OSIUNITTEST_ASSERT_ERROR(eq(cs[0],1.0), {}, "SoPlex", "set col solution"); OSIUNITTEST_ASSERT_ERROR(eq(cs[7],8.0), {}, "SoPlex", "set col solution"); { OsiSpxSolverInterface solnSi(soplexSi); const double * cs = solnSi.getColSolution(); OSIUNITTEST_ASSERT_ERROR(eq(cs[0],1.0), {}, "SoPlex", "set col solution and copy"); OSIUNITTEST_ASSERT_ERROR(eq(cs[7],8.0), {}, "SoPlex", "set col solution and copy"); } OSIUNITTEST_ASSERT_ERROR(!eq(cl[3],1.2345), {}, "SoPlex", "set col lower"); soplexSi.setColLower( 3, 1.2345 ); OSIUNITTEST_ASSERT_ERROR( eq(cl[3],1.2345), {}, "SoPlex", "set col lower"); OSIUNITTEST_ASSERT_ERROR(!eq(cu[4],10.2345), {}, "SoPlex", "set col upper"); soplexSi.setColUpper( 4, 10.2345 ); OSIUNITTEST_ASSERT_ERROR( eq(cu[4],10.2345), {}, "SoPlex", "set col upper"); OSIUNITTEST_ASSERT_ERROR(eq(soplexSi.getObjCoefficients()[0], 1.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(soplexSi.getObjCoefficients()[1], 0.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(soplexSi.getObjCoefficients()[2], 0.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(soplexSi.getObjCoefficients()[3], 0.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(soplexSi.getObjCoefficients()[4], 2.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(soplexSi.getObjCoefficients()[5], 0.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(soplexSi.getObjCoefficients()[6], 0.0), {}, "SoPlex", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(soplexSi.getObjCoefficients()[7],-1.0), {}, "SoPlex", "read and copy exmip1"); } // Test getMatrixByRow method { const OsiSpxSolverInterface si(m); const CoinPackedMatrix * smP = si.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim() == 5, return, "SoPlex", "getMatrixByRow: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "SoPlex", "getMatrixByRow: num elements"); CoinRelFltEq eq; const double * ev = smP->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[0], 3.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[1], 1.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[2], -2.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[3], -1.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[4], -1.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[5], 2.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[6], 1.1), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[7], 1.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[8], 1.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[9], 2.8), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "SoPlex", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "SoPlex", "getMatrixByRow: elements"); const int * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "SoPlex", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "SoPlex", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "SoPlex", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "SoPlex", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "SoPlex", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "SoPlex", "getMatrixByRow: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "SoPlex", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "SoPlex", "getMatrixByRow: indices"); } //-------------- // Test rowsense, rhs, rowrange, getMatrixByRow { OsiSpxSolverInterface lhs; { OsiSpxSolverInterface siC1(m); OSIUNITTEST_ASSERT_WARNING(siC1.rowrange_ == NULL, {}, "SoPlex", "row range"); OSIUNITTEST_ASSERT_WARNING(siC1.rowsense_ == NULL, {}, "SoPlex", "row sense"); OSIUNITTEST_ASSERT_WARNING(siC1.rhs_ == NULL, {}, "SoPlex", "right hand side"); OSIUNITTEST_ASSERT_WARNING(siC1.matrixByRow_ == NULL, {}, "SoPlex", "matrix by row"); OSIUNITTEST_ASSERT_WARNING(siC1.colsol_ == NULL, {}, "SoPlex", "col solution"); OSIUNITTEST_ASSERT_WARNING(siC1.rowsol_ == NULL, {}, "SoPlex", "row solution"); const char * siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "SoPlex", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "SoPlex", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "SoPlex", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "SoPlex", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "SoPlex", "row sense"); const double * siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "SoPlex", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "SoPlex", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "SoPlex", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "SoPlex", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "SoPlex", "right hand side"); const double * siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "SoPlex", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "SoPlex", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "SoPlex", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "SoPlex", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "SoPlex", "row range"); const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "SoPlex", "matrix by row"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim() == 5, return, "SoPlex", "matrix by row: major dim"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "SoPlex", "matrix by row: num elements"); const double * ev = siC1mbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "SoPlex", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "SoPlex", "matrix by row: elements"); const CoinBigIndex * mi = siC1mbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "SoPlex", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "SoPlex", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "SoPlex", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "SoPlex", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "SoPlex", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "SoPlex", "matrix by row: vector starts"); const int * ei = siC1mbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "SoPlex", "matrix by row: indices"); OSIUNITTEST_ASSERT_WARNING(siC1rs == siC1.getRowSense(), {}, "SoPlex", "row sense"); OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "SoPlex", "right hand side"); OSIUNITTEST_ASSERT_WARNING(siC1rr == siC1.getRowRange(), {}, "SoPlex", "row range"); // Change SOPLEX Model by adding free row OsiRowCut rc; rc.setLb(-COIN_DBL_MAX); rc.setUb( COIN_DBL_MAX); OsiCuts cuts; cuts.insert(rc); siC1.applyCuts(cuts); // Since model was changed, test that cached data is now freed. OSIUNITTEST_ASSERT_ERROR(siC1.rowrange_ == NULL, {}, "SoPlex", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.rowsense_ == NULL, {}, "SoPlex", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.rhs_ == NULL, {}, "SoPlex", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.matrixByRow_ == NULL, {}, "SoPlex", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.matrixByCol_ == NULL, {}, "SoPlex", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.colsol_ == NULL, {}, "SoPlex", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.rowsol_ == NULL, {}, "SoPlex", "free cached data after adding row"); siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "SoPlex", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "SoPlex", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "SoPlex", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "SoPlex", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "SoPlex", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "SoPlex", "row sense after adding row"); siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "SoPlex", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "SoPlex", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "SoPlex", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "SoPlex", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "SoPlex", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "SoPlex", "right hand side after adding row"); siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "SoPlex", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "SoPlex", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "SoPlex", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "SoPlex", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "SoPlex", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "SoPlex", "row range after adding row"); lhs = siC1; } // Test that lhs has correct values even though siC1 has gone out of scope OSIUNITTEST_ASSERT_ERROR(lhs.rowrange_ == NULL, {}, "SoPlex", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.rowsense_ == NULL, {}, "SoPlex", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.rhs_ == NULL, {}, "SoPlex", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.matrixByRow_ == NULL, {}, "SoPlex", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.matrixByCol_ == NULL, {}, "SoPlex", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.colsol_ == NULL, {}, "SoPlex", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.rowsol_ == NULL, {}, "SoPlex", "freed origin after assignment"); const char * lhsrs = lhs.getRowSense(); OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "SoPlex", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "SoPlex", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "SoPlex", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "SoPlex", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "SoPlex", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "SoPlex", "row sense after assignment"); const double * lhsrhs = lhs.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "SoPlex", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "SoPlex", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "SoPlex", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "SoPlex", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "SoPlex", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "SoPlex", "right hand side after assignment"); const double *lhsrr = lhs.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "SoPlex", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "SoPlex", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "SoPlex", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "SoPlex", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "SoPlex", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "SoPlex", "row range after assignment"); const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "SoPlex", "matrix by row after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim() == 6, return, "SoPlex", "matrix by row after assignment: major dim"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "SoPlex", "matrix by row after assignment: num elements"); const double * ev = lhsmbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "SoPlex", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "SoPlex", "matrix by row after assignment: elements"); const CoinBigIndex * mi = lhsmbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "SoPlex", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "SoPlex", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "SoPlex", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "SoPlex", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "SoPlex", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "SoPlex", "matrix by row after assignment: vector starts"); const int * ei = lhsmbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "SoPlex", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "SoPlex", "matrix by row after assignment: indices"); } //-------------- } // Do common solverInterface testing by calling the // base class testing method. { OsiSpxSolverInterface m; OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir); } }
//----------------------------------------------------------------------------- // Generate Lift-and-Project cuts //------------------------------------------------------------------- void CglLiftAndProject::generateCuts(const OsiSolverInterface& si, OsiCuts& cs, const CglTreeInfo /*info*/) { // Assumes the mixed 0-1 problem // // min {cx: <Atilde,x> >= btilde} // // is in canonical form with all bounds, // including x_t>=0, -x_t>=-1 for x_t binary, // explicitly stated in the constraint matrix. // See ~/COIN/Examples/Cgl2/cgl2.cpp // for a general purpose "convert" function. // Reference [BCC]: Balas, Ceria, and Corneujols, // "A lift-and-project cutting plane algorithm // for mixed 0-1 program", Math Prog 58, (1993) // 295-324. // This implementation uses Normalization 1. // Given canonical problem and // the lp-relaxation solution, x, // the LAP cut generator attempts to construct // a cut for every x_j such that 0<x_j<1 // [BCC:307] // x_j is the strictly fractional binary variable // the cut is generated from int j = 0; // Get basic problem information // let Atilde be an m by n matrix const int m = si.getNumRows(); const int n = si.getNumCols(); const double * x = si.getColSolution(); // Remember - Atildes may have gaps.. const CoinPackedMatrix * Atilde = si.getMatrixByRow(); const double * AtildeElements = Atilde->getElements(); const int * AtildeIndices = Atilde->getIndices(); const CoinBigIndex * AtildeStarts = Atilde->getVectorStarts(); const int * AtildeLengths = Atilde->getVectorLengths(); const int AtildeFullSize = AtildeStarts[m]; const double * btilde = si.getRowLower(); // Set up memory for system (10) [BCC:307] // (the problem over the norm intersected // with the polar cone) // // min <<x^T,Atilde^T>,u> + x_ju_0 // s.t. // <B,w> = (0,...,0,beta_,beta)^T // w is nonneg for all but the // last two entries, which are free. // where // w = (u,v,v_0,u_0)in BCC notation // u and v are m-vectors; u,v >=0 // v_0 and u_0 are free-scalars, and // // B = Atilde^T -Atilde^T -e_j e_j // btilde^T e_0^T 0 0 // e_0^T btilde^T 1 0 // ^T indicates Transpose // e_0 is a (AtildeNCols x 1) vector of all zeros // e_j is e_0 with a 1 in the jth position // Storing B in column order. B is a (n+2 x 2m+2) matrix // But need to allow for possible gaps in Atilde. // At each iteration, only need to change 2 cols and objfunc // Sane design of OsiSolverInterface does not permit mucking // with matrix. // Because we must delete and add cols to alter matrix, // and we can only add columns on the end of the matrix // put the v_0 and u_0 columns on the end. // rather than as described in [BCC] // Initially allocating B with space for v_0 and u_O cols // but not populating, for efficiency. // B without u_0 and v_0 is a (n+2 x 2m) size matrix. int twoM = 2*m; int BNumRows = n+2; int BNumCols = twoM+2; int BFullSize = 2*AtildeFullSize+twoM+3; double * BElements = new double[BFullSize]; int * BIndices = new int[BFullSize]; CoinBigIndex * BStarts = new CoinBigIndex [BNumCols+1]; int * BLengths = new int[BNumCols]; int i, ij, k=0; int nPlus1=n+1; int offset = AtildeStarts[m]+m; for (i=0; i<m; i++){ for (ij=AtildeStarts[i];ij<AtildeStarts[i]+AtildeLengths[i];ij++){ BElements[k]=AtildeElements[ij]; BElements[k+offset]=-AtildeElements[ij]; BIndices[k]= AtildeIndices[ij]; BIndices[k+offset]= AtildeIndices[ij]; k++; } BElements[k]=btilde[i]; BElements[k+offset]=btilde[i]; BIndices[k]=n; BIndices[k+offset]=nPlus1; BStarts[i]= AtildeStarts[i]+i; BStarts[i+m]=offset+BStarts[i];// = AtildeStarts[m]+m+AtildeStarts[i]+i BLengths[i]= AtildeLengths[i]+1; BLengths[i+m]= AtildeLengths[i]+1; k++; } BStarts[twoM]=BStarts[twoM-1]+BLengths[twoM-1]; // Cols that will be deleted each iteration int BNumColsLessOne=BNumCols-1; int BNumColsLessTwo=BNumCols-2; const int delCols[2] = {BNumColsLessOne, BNumColsLessTwo}; // Set lower bound on u and v // u_0, v_0 will be reset as free const double solverINFINITY = si.getInfinity(); double * BColLowers = new double[BNumCols]; double * BColUppers = new double[BNumCols]; CoinFillN(BColLowers,BNumCols,0.0); CoinFillN(BColUppers,BNumCols,solverINFINITY); // Set row lowers and uppers. // The rhs is zero, for but the last two rows. // For these the rhs is beta_ double * BRowLowers = new double[BNumRows]; double * BRowUppers = new double[BNumRows]; CoinFillN(BRowLowers,BNumRows,0.0); CoinFillN(BRowUppers,BNumRows,0.0); BRowLowers[BNumRows-2]=beta_; BRowUppers[BNumRows-2]=beta_; BRowLowers[BNumRows-1]=beta_; BRowUppers[BNumRows-1]=beta_; // Calculate base objective <<x^T,Atilde^T>,u> // Note: at each iteration coefficient u_0 // changes to <x^T,e_j> // w=(u,v,beta,v_0,u_0) size 2m+3 // So, BOjective[2m+2]=x[j] double * BObjective= new double[BNumCols]; double * Atildex = new double[m]; CoinFillN(BObjective,BNumCols,0.0); Atilde->times(x,Atildex); // Atildex is size m, x is size n CoinDisjointCopyN(Atildex,m,BObjective); // Number of cols and size of Elements vector // in B without the v_0 and u_0 cols int BFullSizeLessThree = BFullSize-3; // Load B matrix into a column orders CoinPackedMatrix CoinPackedMatrix * BMatrix = new CoinPackedMatrix(true, BNumRows, BNumColsLessTwo, BFullSizeLessThree, BElements,BIndices, BStarts,BLengths); // Assign problem into a solver interface // Note: coneSi will cleanup the memory itself OsiSolverInterface * coneSi = si.clone(false); coneSi->assignProblem (BMatrix, BColLowers, BColUppers, BObjective, BRowLowers, BRowUppers); // Problem sense should default to "min" by default, // but just to be virtuous... coneSi->setObjSense(1.0); // The plot outline from here on down: // coneSi has been assigned B without the u_0 and v_0 columns // Calculate base objective <<x^T,Atilde^T>,u> // bool haveWarmStart = false; // For (j=0; j<n, j++) // if (!isBinary(x_j) || x_j<=0 || x_j>=1) continue; // // IMPROVEME: if(haveWarmStart) check if j attractive // add {-e_j,0,-1} matrix column for v_0 // add {e_j,0,0} matrix column for u_0 // objective coefficient for u_0 is x_j // if (haveWarmStart) // set warmstart info // solve min{objw:Bw=0; w>=0,except v_0, u_0 free} // if (bounded) // get warmstart info // haveWarmStart=true; // ustar = optimal u solution // ustar_0 = optimal u_0 solution // alpha^T= <ustar^T,Atilde> -ustar_0e_j^T // (double check <alpha^T,x> >= beta_ should be violated) // add <alpha^T,x> >= beta_ to cutset // endif // delete column for u_0 // this deletes all column info. // delete column for v_0 // endFor // clean up memory // return 0; int * nVectorIndices = new int[n]; CoinIotaN(nVectorIndices, n, 0); bool haveWarmStart = false; bool equalObj1, equalObj2; CoinRelFltEq eq; double v_0Elements[2] = {-1,1}; double u_0Elements[1] = {1}; CoinWarmStart * warmStart = 0; double * ustar = new double[m]; CoinFillN(ustar, m, 0.0); double* alpha = new double[n]; CoinFillN(alpha, n, 0.0); for (j=0;j<n;j++){ if (!si.isBinary(j)) continue; // Better to ask coneSi? No! // coneSi has no binInfo. equalObj1=eq(x[j],0); equalObj2=eq(x[j],1); if (equalObj1 || equalObj2) continue; // IMPROVEME: if (haveWarmStart) check if j attractive; // AskLL:wanted to declare u_0 and v_0 packedVec outside loop // and setIndices, but didn't see a method to do that(?) // (Could "insert". Seems inefficient) int v_0Indices[2]={j,nPlus1}; int u_0Indices[1]={j}; // CoinPackedVector v_0(2,v_0Indices,v_0Elements,false); CoinPackedVector u_0(1,u_0Indices,u_0Elements,false); #if CGL_DEBUG const CoinPackedMatrix *see1 = coneSi->getMatrixByRow(); #endif coneSi->addCol(v_0,-solverINFINITY,solverINFINITY,0); coneSi->addCol(u_0,-solverINFINITY,solverINFINITY,x[j]); if(haveWarmStart) { coneSi->setWarmStart(warmStart); coneSi->resolve(); } else { #if CGL_DEBUG const CoinPackedMatrix *see2 = coneSi->getMatrixByRow(); #endif coneSi->initialSolve(); } if(coneSi->isProvenOptimal()){ warmStart = coneSi->getWarmStart(); haveWarmStart=true; const double * wstar = coneSi->getColSolution(); CoinDisjointCopyN(wstar, m, ustar); Atilde->transposeTimes(ustar,alpha); alpha[j]+=wstar[BNumCols-1]; #if debug int p; double sum; for(p=0;p<n;p++)sum+=alpha[p]*x[p]; if (sum<=beta_){ throw CoinError("Cut not violated", "cutGeneration", "CglLiftAndProject"); } #endif // add <alpha^T,x> >= beta_ to cutset OsiRowCut rc; rc.setRow(n,nVectorIndices,alpha); rc.setLb(beta_); rc.setUb(solverINFINITY); cs.insert(rc); } // delete col for u_o and v_0 coneSi->deleteCols(2,delCols); // clean up memory } // clean up delete [] alpha; delete [] ustar; delete [] nVectorIndices; // BMatrix, BColLowers,BColUppers, BObjective, BRowLowers, BRowUppers // are all freed by OsiSolverInterface destructor (?) delete [] BLengths; delete [] BStarts; delete [] BIndices; delete [] BElements; }
void CglLandP::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info ) { if ((info.pass == 0) && !info.inTree) { numrows_ = si.getNumRows(); } // scanExtraCuts(cs, si.getColSolution()); Parameters params = params_; params.rhsWeight = numrows_ + 2; handler_->message(CUT_GAP, messages_)<<info.pass<<si.getObjValue() <<CoinMessageEol; if (info.inTree) //put lower pivot limit { params.pivotLimit = std::min(params.pivotLimit, params.pivotLimitInTree); params.countMistakenRc = true; } if (params.timeLimit < 0) { params.pivotLimit = 0; } assert(si.basisIsAvailable()); #ifdef APPEND_ROW OsiSolverInterface * t_si = si.clone(); if (params.modularize) { int new_idx = si.getNumCols(); int v_idx[1] = {new_idx}; double v_val[1] = {-1}; CoinPackedVector v(1, v_idx, v_val, false); t_si->addCol(CoinPackedVector(), 0, 1, 0); t_si->setInteger(new_idx); t_si->addRow(v,0, 0); t_si->resolve(); } #else const OsiSolverInterface * t_si = &si; #endif cached_.getData(*t_si); CglLandPSimplex landpSi(*t_si, cached_, params, validator_); if (params.generateExtraCuts == CglLandP::AllViolatedMigs) { landpSi.genThisBasisMigs(cached_, params); } landpSi.setLogLevel(handler_->logLevel()); int nCut = 0; std::vector<int> indices; getSortedFractionalIndices(indices,cached_, params); #ifndef NDEBUG int numrows = si.getNumRows(); #endif #ifdef DO_STAT //Get informations on current optimum { OsiSolverInterface * gapTester = si.clone(); gapTester->resolve(); roundsStats_.analyseOptimalBasis(gapTester,info.pass, numrows_); delete gapTester; } #endif params_.timeLimit += CoinCpuTime(); CoinRelFltEq eq(1e-04); for (unsigned int i = 0; i < indices.size() && nCut < params.maxCutPerRound && nCut < cached_.nBasics_ ; i++) { //Check for time limit int iRow = indices[i]; assert(iRow < numrows); OsiRowCut cut; int code=1; OsiSolverInterface * ncSi = NULL; if (params.pivotLimit != 0) { ncSi = t_si->clone(); landpSi.setSi(ncSi); ncSi->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); ncSi->messageHandler()->setLogLevel(0); } int generated = 0; if (params.pivotLimit == 0) { generated = landpSi.generateMig(iRow, cut, params); } else { generated = landpSi.optimize(iRow, cut, cached_, params); if (params.generateExtraCuts == CglLandP::AllViolatedMigs) { landpSi.genThisBasisMigs(cached_, params); } landpSi.resetSolver(cached_.basis_); } code = 0; if (generated) code = validator_(cut, cached_.colsol_, si, params, originalColLower_, originalColUpper_); if (!generated || code) { if (params.pivotLimit !=0) { handler_->message(LAP_CUT_FAILED_DO_MIG, messages_)<<validator_.failureString(code)<<CoinMessageEol; landpSi.freeSi(); OsiSolverInterface * ncSi = t_si->clone(); landpSi.setSi(ncSi); params.pivotLimit = 0; if (landpSi.optimize(iRow, cut, cached_, params)) { code = validator_(cut, cached_.colsol_, si, params, originalColLower_, originalColUpper_); } params.pivotLimit = params_.pivotLimit; } } if (params.pivotLimit != 0) { landpSi.freeSi(); } if (code) { handler_->message(CUT_REJECTED, messages_)<< validator_.failureString(code)<<CoinMessageEol; } else { if (canLift_) { cut.setGloballyValid(true); } cs.insertIfNotDuplicate(cut, eq); //cs.insert(cut); { //std::cout<<"Violation "<<cut.violated(cached_.colsol_)<<std::endl; nCut++; } } } Cuts& extra = landpSi.extraCuts(); for (int i = 0 ; i < cached_.nNonBasics_; i++) { OsiRowCut * cut = extra.rowCut(i); if (cut == NULL) continue; int code = validator_(*cut, cached_.colsol_, si, params, originalColLower_, originalColUpper_); if (code) { handler_->message(LAP_CUT_FAILED_DO_MIG, messages_) <<validator_.failureString(code)<<CoinMessageEol; } else { cs.insertIfNotDuplicate(*cut, eq); { nCut++; } } delete cut; } landpSi.outPivInfo(nCut); params_.timeLimit -= CoinCpuTime(); cached_.clean(); #ifdef APPEND_ROW assert(t_si != &si); delete t_si; #endif }
void CglLandP::CachedData::getData(const OsiSolverInterface &si) { int nBasics = si.getNumRows(); int nNonBasics = si.getNumCols(); if (basis_ != NULL) delete basis_; basis_ = dynamic_cast<CoinWarmStartBasis *> (si.getWarmStart()); if (!basis_) throw NoBasisError(); if (nBasics_ > 0 || nBasics != nBasics_) { delete [] basics_; basics_ = NULL; } if (basics_ == NULL) { basics_ = new int[nBasics]; nBasics_ = nBasics; } if (nNonBasics_ > 0 || nNonBasics != nNonBasics_) { delete [] nonBasics_; nonBasics_ = NULL; } if (nonBasics_ == NULL) { nonBasics_ = new int[nNonBasics]; nNonBasics_ = nNonBasics; } int n = nBasics + nNonBasics; if ( nBasics_ + nNonBasics_ > 0 || nBasics_ + nNonBasics_ != n) { delete [] colsol_; delete [] integers_; integers_ = NULL; colsol_ = NULL; slacks_ = NULL; } if (colsol_ == NULL) { colsol_ = new double[n]; slacks_ = &colsol_[nNonBasics]; } if (integers_ == NULL) { integers_ = new bool[n]; } const double * rowLower = si.getRowLower(); const double * rowUpper = si.getRowUpper(); //determine which slacks are integer const CoinPackedMatrix * m = si.getMatrixByCol(); const double * elems = m->getElements(); const int * inds = m->getIndices(); const CoinBigIndex * starts = m->getVectorStarts(); const int * lengths = m->getVectorLengths(); // int numElems = m->getNumElements(); int numCols = m->getNumCols(); assert(numCols == nNonBasics_); // int numRows = m->getNumRows(); CoinFillN(integers_ ,n, true); for (int i = 0 ; i < numCols ; i++) { if (si.isContinuous(i)) integers_[i] = false; } bool * integerSlacks = integers_ + numCols; for (int i = 0 ; i < nBasics ; i++) { if (rowLower[i] > -1e50 && INT_INFEAS(rowLower[i]) > 1e-15) integerSlacks[i] = false; if (rowUpper[i] < 1e50 && INT_INFEAS(rowUpper[i]) > 1e-15) integerSlacks[i] = false; } for (int i = 0 ; i < numCols ; i++) { CoinBigIndex end = starts[i] + lengths[i]; if (integers_[i]) { for (CoinBigIndex k=starts[i] ; k < end; k++) { if (integerSlacks[inds[k]] && INT_INFEAS(elems[k])>1e-15 ) integerSlacks[inds[k]] = false; } } else { for (CoinBigIndex k=starts[i] ; k < end; k++) { if (integerSlacks[inds[k]]) integerSlacks[inds[k]] = false; } } } CoinCopyN(si.getColSolution(), si.getNumCols(), colsol_); CoinCopyN(si.getRowActivity(), si.getNumRows(), slacks_); for (int i = 0 ; i < si.getNumRows() ; i++) { slacks_[i]*=-1; if (rowLower[i]>-1e50) { slacks_[i] += rowLower[i]; } else { slacks_[i] += rowUpper[i]; } } //Now get the fill the arrays; nNonBasics = 0; nBasics = 0; //For having the index variables correctly ordered we need to access to OsiSimplexInterface { OsiSolverInterface * ncSi = (const_cast<OsiSolverInterface *>(&si)); ncSi->enableSimplexInterface(0); ncSi->getBasics(basics_); // Save enabled solver solver_ = si.clone(); #ifdef COIN_HAS_OSICLP OsiClpSolverInterface * clpSi = dynamic_cast<OsiClpSolverInterface *>(solver_); const OsiClpSolverInterface * clpSiRhs = dynamic_cast<const OsiClpSolverInterface *>(&si); if (clpSi) clpSi->getModelPtr()->copyEnabledStuff(clpSiRhs->getModelPtr());; #endif ncSi->disableSimplexInterface(); } int numStructural = basis_->getNumStructural(); for (int i = 0 ; i < numStructural ; i++) { if (basis_->getStructStatus(i)== CoinWarmStartBasis::basic) { nBasics++; //Basically do nothing } else { nonBasics_[nNonBasics++] = i; } } int numArtificial = basis_->getNumArtificial(); for (int i = 0 ; i < numArtificial ; i++) { if (basis_->getArtifStatus(i)== CoinWarmStartBasis::basic) { //Just check number of basics nBasics++; } else { nonBasics_[nNonBasics++] = i + basis_->getNumStructural(); } } }
void OsiGlpkSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir) { // Test default constructor { OsiGlpkSolverInterface m; OSIUNITTEST_ASSERT_ERROR(m.obj_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.collower_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.colupper_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.ctype_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rowsense_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rhs_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rowrange_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rowlower_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rowupper_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.colsol_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.rowsol_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.matrixByRow_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.matrixByCol_ == NULL, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(m.getApplicationData() == NULL, {}, "glpk", "default constructor"); int i=2346; m.setApplicationData(&i); OSIUNITTEST_ASSERT_ERROR(*((int *)(m.getApplicationData())) == i, {}, "glpk", "default constructor"); } { CoinRelFltEq eq; OsiGlpkSolverInterface m; std::string fn = mpsDir+"exmip1"; m.readMps(fn.c_str(),"mps"); { OsiGlpkSolverInterface im; OSIUNITTEST_ASSERT_ERROR(im.getNumCols() == 0, {}, "glpk", "default constructor"); OSIUNITTEST_ASSERT_ERROR(im.getModelPtr() != NULL, {}, "glpk", "default constructor"); // Test reset im.reset(); OSIUNITTEST_ASSERT_ERROR(m.obj_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.collower_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.colupper_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.ctype_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.rowsense_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.rhs_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.rowrange_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.rowlower_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.rowupper_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.colsol_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.rowsol_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.matrixByRow_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.matrixByCol_ == NULL, {}, "glpk", "reset"); OSIUNITTEST_ASSERT_ERROR(m.getApplicationData() == NULL, {}, "glpk", "reset"); } // Test copy constructor and assignment operator { OsiGlpkSolverInterface lhs; { OsiGlpkSolverInterface im(m); OsiGlpkSolverInterface imC1(im); OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != im.getModelPtr(), {}, "glpk", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getNumCols() == im.getNumCols(), {}, "glpk", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getNumRows() == im.getNumRows(), {}, "glpk", "copy constructor"); OsiGlpkSolverInterface imC2(im); OSIUNITTEST_ASSERT_ERROR(imC2.getModelPtr() != im.getModelPtr(), {}, "glpk", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC2.getNumCols() == im.getNumCols(), {}, "glpk", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC2.getNumRows() == im.getNumRows(), {}, "glpk", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(imC1.getModelPtr() != imC2.getModelPtr(), {}, "glpk", "copy constructor"); lhs = imC2; } // Test that lhs has correct values even though rhs has gone out of scope OSIUNITTEST_ASSERT_ERROR(lhs.getModelPtr() != m.getModelPtr(), {}, "glpk", "assignment operator"); OSIUNITTEST_ASSERT_ERROR(lhs.getNumCols() == m.getNumCols(), {}, "glpk", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(lhs.getNumRows() == m.getNumRows(), {}, "glpk", "copy constructor"); } // Test clone { OsiGlpkSolverInterface glpkSi(m); OsiSolverInterface * siPtr = &glpkSi; OsiSolverInterface * siClone = siPtr->clone(); OsiGlpkSolverInterface * glpkClone = dynamic_cast<OsiGlpkSolverInterface*>(siClone); OSIUNITTEST_ASSERT_ERROR(glpkClone != NULL, {}, "glpk", "clone"); OSIUNITTEST_ASSERT_ERROR(glpkClone->getModelPtr() != glpkSi.getModelPtr(), {}, "glpk", "clone"); OSIUNITTEST_ASSERT_ERROR(glpkClone->getNumRows() == glpkSi.getNumRows(), {}, "glpk", "clone"); OSIUNITTEST_ASSERT_ERROR(glpkClone->getNumCols() == glpkSi.getNumCols(), {}, "glpk", "clone"); delete siClone; } // test infinity { OsiGlpkSolverInterface si; OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == COIN_DBL_MAX, {}, "glpk", "infinity"); } #if 0 // ??? These index error 'throw's aren't in OsiGlpk // Test some catches { OsiGlpkSolverInterface solver; try { solver.setObjCoeff(0,0.0); } catch (CoinError e) { std::cout<<"Correct throw"<<std::endl; } std::string fn = mpsDir+"exmip1"; solver.readMps(fn.c_str(),"mps"); try { solver.setObjCoeff(0,0.0); } catch (CoinError e) { std::cout<<"** Incorrect throw"<<std::endl; abort(); } try { int index[]={0,20}; double value[]={0.0,0.0,0.0,0.0}; solver.setColSetBounds(index,index+2,value); } catch (CoinError e) { std::cout<<"Correct throw"<<std::endl; } } #endif { OsiGlpkSolverInterface glpkSi(m); int nc = glpkSi.getNumCols(); int nr = glpkSi.getNumRows(); const double * cl = glpkSi.getColLower(); const double * cu = glpkSi.getColUpper(); const double * rl = glpkSi.getRowLower(); const double * ru = glpkSi.getRowUpper(); OSIUNITTEST_ASSERT_ERROR(nc == 8, return, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(nr == 5, return, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cl[0],2.5), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cl[1],0.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cu[1],4.1), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cu[2],1.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(rl[0],2.5), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(rl[4],3.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(ru[1],2.1), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(ru[4],15.), {}, "glpk", "read and copy exmip1"); const double * cs = glpkSi.getColSolution(); OSIUNITTEST_ASSERT_ERROR(eq(cs[0],2.5), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(cs[7],0.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(!eq(cl[3],1.2345), {}, "glpk", "set col lower"); glpkSi.setColLower( 3, 1.2345 ); OSIUNITTEST_ASSERT_ERROR( eq(cl[3],1.2345), {}, "glpk", "set col lower"); OSIUNITTEST_ASSERT_ERROR(!eq(glpkSi.getColUpper()[4],10.2345), {}, "glpk", "set col upper"); glpkSi.setColUpper( 4, 10.2345 ); OSIUNITTEST_ASSERT_ERROR( eq(glpkSi.getColUpper()[4],10.2345), {}, "glpk", "set col upper"); double objValue = glpkSi.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,3.5), {}, "glpk", "getObjValue() before solve"); OSIUNITTEST_ASSERT_ERROR(eq(glpkSi.getObjCoefficients()[0], 1.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(glpkSi.getObjCoefficients()[1], 0.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(glpkSi.getObjCoefficients()[2], 0.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(glpkSi.getObjCoefficients()[3], 0.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(glpkSi.getObjCoefficients()[4], 2.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(glpkSi.getObjCoefficients()[5], 0.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(glpkSi.getObjCoefficients()[6], 0.0), {}, "glpk", "read and copy exmip1"); OSIUNITTEST_ASSERT_ERROR(eq(glpkSi.getObjCoefficients()[7],-1.0), {}, "glpk", "read and copy exmip1"); } // Test matrixByRow method { const OsiGlpkSolverInterface si(m); const CoinPackedMatrix * smP = si.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim() == 5, return, "glpk", "getMatrixByRow: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "glpk", "getMatrixByRow: num elements"); CoinRelFltEq eq; const double * ev = smP->getElements(); // GLPK returns each row in reverse order. This is consistent with // the sparse matrix format but is not what most solvers do. That's // why this section is different. OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 3.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 1.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1],-1.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0],-1.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 2.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.1), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 2.8), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9],-1.2), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 5.6), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "glpk", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 1.9), {}, "glpk", "getMatrixByRow: elements"); const CoinBigIndex * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "glpk", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "glpk", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "glpk", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "glpk", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "glpk", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "glpk", "getMatrixByRow: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 0, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 7, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 1, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 2, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 5, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 3, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 6, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 0, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "glpk", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 7, {}, "glpk", "getMatrixByRow: indices"); } // Test adding several cuts { OsiGlpkSolverInterface fim; std::string fn = mpsDir+"exmip1"; fim.readMps(fn.c_str(),"mps"); // exmip1.mps has 2 integer variables with index 2 & 3 fim.initialSolve(); OsiRowCut cuts[3]; // Generate one ineffective cut plus two trivial cuts int c; int nc = fim.getNumCols(); int *inx = new int[nc]; for (c=0;c<nc;c++) inx[c]=c; double *el = new double[nc]; for (c=0;c<nc;c++) el[c]=1.0e-50+((double)c)*((double)c); cuts[0].setRow(nc,inx,el); cuts[0].setLb(-100.); cuts[0].setUb(500.); cuts[0].setEffectiveness(22); el[4]=0.0; // to get inf later for (c=2;c<4;c++) { el[0]=1.0; inx[0]=c; cuts[c-1].setRow(1,inx,el); cuts[c-1].setLb(1.); cuts[c-1].setUb(100.); cuts[c-1].setEffectiveness(c); } fim.writeMps("x1.mps"); fim.applyRowCuts(3,cuts); fim.writeMps("x2.mps"); // resolve - should get message about zero elements fim.resolve(); fim.writeMps("x3.mps"); // check integer solution const double * cs = fim.getColSolution(); CoinRelFltEq eq; OSIUNITTEST_ASSERT_ERROR(eq(cs[2], 1.0), {}, "glpk", "add cuts"); OSIUNITTEST_ASSERT_ERROR(eq(cs[3], 1.0), {}, "glpk", "add cuts"); #if 0 // ??? Not working for some reason. // check will find invalid matrix el[0]=1.0/el[4]; inx[0]=0; cuts[0].setRow(nc,inx,el); cuts[0].setLb(-100.); cuts[0].setUb(500.); cuts[0].setEffectiveness(22); fim.applyRowCut(cuts[0]); // resolve - should get message about zero elements fim.resolve(); OSIUNITTEST_ASSERT_WARNING(fim.isAbandoned(), {}, "glpk", "add cuts"); #endif delete[]el; delete[]inx; } // Test matrixByCol method { const OsiGlpkSolverInterface si(m); const CoinPackedMatrix * smP = si.getMatrixByCol(); OSIUNITTEST_ASSERT_ERROR(smP->getMajorDim() == 8, return, "glpk", "getMatrixByCol: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim() == 5, return, "glpk", "getMatrixByCol: minor dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "glpk", "getMatrixByCol: number of elements"); OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 9, return, "glpk", "getMatrixByCol: vector starts size"); CoinRelFltEq eq; const double * ev = smP->getElements(); // Unlike row-ordered matrices, GLPK does column-ordered the "normal" way OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 5.6), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2], 1.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 2.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 1.1), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6],-2.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 2.8), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8],-1.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 1.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 1.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11],-1.2), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12],-1.0), {}, "glpk", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "glpk", "getMatrixByCol: elements"); const CoinBigIndex * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "glpk", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 2, {}, "glpk", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 4, {}, "glpk", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 6, {}, "glpk", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 8, {}, "glpk", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 10, {}, "glpk", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[6] == 11, {}, "glpk", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[7] == 12, {}, "glpk", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[8] == 14, {}, "glpk", "getMatrixByCol: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 0, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 1, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 0, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 3, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 0, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 4, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 2, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 3, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 0, {}, "glpk", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 4, {}, "glpk", "getMatrixByCol: indices"); } //-------------- // Test rowsense, rhs, rowrange, matrixByRow { OsiGlpkSolverInterface lhs; { #if 0 // FIXME ??? these won't work because the copy constructor changes the values in m OSIUNITTEST_ASSERT_ERROR(m.rowrange_ == NULL, {}, "glpk", "???"); OSIUNITTEST_ASSERT_ERROR(m.rowsense_ == NULL, {}, "glpk", "???"); OSIUNITTEST_ASSERT_ERROR(m.rhs_ == NULL, {}, "glpk", "???"); OSIUNITTEST_ASSERT_ERROR(m.matrixByRow_ == NULL, {}, "glpk", "???"); #endif OsiGlpkSolverInterface siC1(m); OSIUNITTEST_ASSERT_WARNING(siC1.rowrange_ == NULL, {}, "glpk", "row range"); OSIUNITTEST_ASSERT_WARNING(siC1.rowsense_ == NULL, {}, "glpk", "row sense"); OSIUNITTEST_ASSERT_WARNING(siC1.rhs_ == NULL, {}, "glpk", "right hand side"); OSIUNITTEST_ASSERT_WARNING(siC1.matrixByRow_ == NULL, {}, "glpk", "matrix by row"); const char * siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "glpk", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "glpk", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "glpk", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "glpk", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "glpk", "row sense"); const double * siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "glpk", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "glpk", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "glpk", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "glpk", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "glpk", "right hand side"); const double * siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "glpk", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "glpk", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "glpk", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "glpk", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "glpk", "row range"); const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "glpk", "matrix by row"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim() == 5, return, "glpk", "matrix by row: major dim"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "glpk", "matrix by row: num elements"); const double * ev = siC1mbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 3.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 1.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1],-1.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0],-1.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 2.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.1), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 2.8), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9],-1.2), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 5.6), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "glpk", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 1.9), {}, "glpk", "matrix by row: elements"); const CoinBigIndex * mi = siC1mbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "glpk", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "glpk", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "glpk", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "glpk", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "glpk", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "glpk", "matrix by row: vector starts"); const int * ei = siC1mbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 0, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 7, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 1, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 2, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 5, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 3, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 6, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 0, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 7, {}, "glpk", "matrix by row: indices"); OSIUNITTEST_ASSERT_WARNING(siC1rs == siC1.getRowSense(), {}, "glpk", "row sense"); OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "glpk", "right hand side"); OSIUNITTEST_ASSERT_WARNING(siC1rr == siC1.getRowRange(), {}, "glpk", "row range"); // Change glpk Model by adding free row OsiRowCut rc; rc.setLb(-COIN_DBL_MAX); rc.setUb( COIN_DBL_MAX); OsiCuts cuts; cuts.insert(rc); siC1.applyCuts(cuts); // Since model was changed, test that cached data is now freed. OSIUNITTEST_ASSERT_ERROR(siC1.rowrange_ == NULL, {}, "glpk", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.rowsense_ == NULL, {}, "glpk", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.rhs_ == NULL, {}, "glpk", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.matrixByRow_ == NULL, {}, "glpk", "free cached data after adding row"); siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "glpk", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "glpk", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "glpk", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "glpk", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "glpk", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "glpk", "row sense after adding row"); siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "glpk", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "glpk", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "glpk", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "glpk", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "glpk", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "glpk", "right hand side after adding row"); siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "glpk", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "glpk", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "glpk", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "glpk", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "glpk", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "glpk", "row range after adding row"); lhs = siC1; } // Test that lhs has correct values even though siC1 has gone out of scope OSIUNITTEST_ASSERT_ERROR(lhs.rowrange_ == NULL, {}, "glpk", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.rowsense_ == NULL, {}, "glpk", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.rhs_ == NULL, {}, "glpk", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.matrixByRow_ == NULL, {}, "glpk", "freed origin after assignment"); const char * lhsrs = lhs.getRowSense(); OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "glpk", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "glpk", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "glpk", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "glpk", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "glpk", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "glpk", "row sense after assignment"); const double * lhsrhs = lhs.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "glpk", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "glpk", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "glpk", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "glpk", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "glpk", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "glpk", "right hand side after assignment"); const double *lhsrr = lhs.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "glpk", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "glpk", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "glpk", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "glpk", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "glpk", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "glpk", "row range after assignment"); const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, return, "glpk", "matrix by row after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim() == 6, return, "glpk", "matrix by row after assignment: major dim"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "glpk", "matrix by row after assignment: num elements"); const double * ev = lhsmbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 3.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 1.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1],-1.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0],-1.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 2.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.1), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 2.8), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9],-1.2), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 5.6), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "glpk", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 1.9), {}, "glpk", "matrix by row after assignment: elements"); const CoinBigIndex * mi = lhsmbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "glpk", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "glpk", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "glpk", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "glpk", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "glpk", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "glpk", "matrix by row after assignment: vector starts"); const int * ei = lhsmbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 0, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 7, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 1, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 2, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 5, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 3, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 6, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 0, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "glpk", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 7, {}, "glpk", "matrix by row after assignment: indices"); } } // Test add/delete columns { OsiGlpkSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); double inf = m.getInfinity(); CoinPackedVector c0; c0.insert(0, 4); c0.insert(1, 1); m.addCol(c0, 0, inf, 3); m.initialSolve(); double objValue = m.getObjValue(); CoinRelFltEq eq(1.0e-2); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "glpk", "add/delete columns: first optimal value"); // Try deleting first column that's nonbasic at lower bound (0). int * d = new int[1]; CoinWarmStartBasis *cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ; OSIUNITTEST_ASSERT_ERROR(cwsb != NULL, {}, "glpk", "add/delete columns: have warm start basis"); CoinWarmStartBasis::Status stati ; int iCol ; for (iCol = 0 ; iCol < cwsb->getNumStructural() ; iCol++) { stati = cwsb->getStructStatus(iCol) ; if (stati == CoinWarmStartBasis::atLowerBound) break ; } d[0]=iCol; m.deleteCols(1,d); delete [] d; delete cwsb; d=NULL; m.resolve(); objValue = m.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "glpk", "add/delete columns: optimal value after deleting nonbasic column"); // Try deleting column we added. If basic, go to initialSolve as deleting // basic variable trashes basis required for warm start. iCol = m.getNumCols()-1; cwsb = dynamic_cast<CoinWarmStartBasis *>(m.getWarmStart()) ; stati = cwsb->getStructStatus(iCol) ; delete cwsb; m.deleteCols(1,&iCol); if (stati == CoinWarmStartBasis::basic) { m.initialSolve() ; } else { m.resolve(); } objValue = m.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "glpk", "add/delete columns: optimal value after deleting added column"); } #if 0 // ??? Simplex routines not adapted to OsiGlpk yet // Solve an lp by hand { OsiGlpkSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); m.setObjSense(-1.0); m.getModelPtr()->messageHandler()->setLogLevel(4); m.initialSolve(); m.getModelPtr()->factorization()->maximumPivots(5); m.setObjSense(1.0); // enable special mode m.enableSimplexInterface(true); // we happen to know that variables are 0-1 and rows are L int numberIterations=0; int numberColumns = m.getNumCols(); int numberRows = m.getNumRows(); double * fakeCost = new double[numberColumns]; double * duals = new double [numberRows]; double * djs = new double [numberColumns]; const double * solution = m.getColSolution(); memcpy(fakeCost,m.getObjCoefficients(),numberColumns*sizeof(double)); while (1) { const double * dj; const double * dual; if ((numberIterations&1)==0) { // use given ones dj = m.getReducedCost(); dual = m.getRowPrice(); } else { // create dj = djs; dual = duals; m.getReducedGradient(djs,duals,fakeCost); } int i; int colIn=9999; int direction=1; double best=1.0e-6; // find most negative reduced cost // Should check basic - but should be okay on this problem for (i=0;i<numberRows;i++) { double value=dual[i]; if (value>best) { direction=-1; best=value; colIn=-i-1; } } for (i=0;i<numberColumns;i++) { double value=dj[i]; if (value<-best&&solution[i]<1.0e-6) { direction=1; best=-value; colIn=i; } else if (value>best&&solution[i]>1.0-1.0e-6) { direction=-1; best=value; colIn=i; } } if (colIn==9999) break; // should be optimal int colOut; int outStatus; double theta; OSIUNITTEST_ASSERT_ERROR(m.primalPivotResult(colIn,direction,colOut,outStatus,theta,NULL) == 0, {}, "glpk", "simplex routines"); printf("out %d, direction %d theta %g\n", colOut,outStatus,theta); numberIterations++; } delete [] fakeCost; delete [] duals; delete [] djs; // exit special mode m.disableSimplexInterface(); m.getModelPtr()->messageHandler()->setLogLevel(4); m.resolve(); OSIUNITTEST_ASSERT_ERROR(m.getIterationCount() == 0, {}, "glpk", "simplex routines"); m.setObjSense(-1.0); m.initialSolve(); } // Solve an lp when interface is on { OsiGlpkSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); // enable special mode m.setHintParam(OsiDoScale,false,OsiHintDo); m.setHintParam(OsiDoPresolveInInitial,false,OsiHintDo); m.setHintParam(OsiDoDualInInitial,false,OsiHintDo); m.setHintParam(OsiDoPresolveInResolve,false,OsiHintDo); m.setHintParam(OsiDoDualInResolve,false,OsiHintDo); m.enableSimplexInterface(true); m.initialSolve(); } // Check tableau stuff when simplex interface is on { OsiGlpkSolverInterface m; /* Wolsey : Page 130 max 4x1 - x2 7x1 - 2x2 <= 14 x2 <= 3 2x1 - 2x2 <= 3 x1 in Z+, x2 >= 0 */ double inf_ = m.getInfinity(); int n_cols = 2; int n_rows = 3; double obj[2] = {-4.0, 1.0}; double collb[2] = {0.0, 0.0}; double colub[2] = {inf_, inf_}; double rowlb[3] = {-inf_, -inf_, -inf_}; double rowub[3] = {14.0, 3.0, 3.0}; int rowIndices[5] = {0, 2, 0, 1, 2}; int colIndices[5] = {0, 0, 1, 1, 1}; double elements[5] = {7.0, 2.0, -2.0, 1.0, -2.0}; CoinPackedMatrix M(true, rowIndices, colIndices, elements, 5); m.loadProblem(M, collb, colub, obj, rowlb, rowub); m.enableSimplexInterface(true); m.initialSolve(); //check that the tableau matches wolsey (B-1 A) // slacks in second part of binvA double * binvA = (double*) malloc((n_cols+n_rows) * sizeof(double)); printf("B-1 A"); for(int i = 0; i < n_rows; i++){ m.getBInvARow(i, binvA,binvA+n_cols); printf("\nrow: %d -> ",i); for(int j=0; j < n_cols+n_rows; j++){ printf("%g, ", binvA[j]); } } printf("\n"); m.disableSimplexInterface(); free(binvA); } #endif /* Read in exmip1 and solve it with verbose output setting. */ { OsiGlpkSolverInterface osi ; std::cout << "Boosting verbosity.\n" ; osi.setHintParam(OsiDoReducePrint,false,OsiForceDo) ; std::string exmpsfile = mpsDir+"exmip1" ; std::string probname ; std::cout << "Reading mps file \"" << exmpsfile << "\"\n" ; osi.readMps(exmpsfile.c_str(), "mps") ; OSIUNITTEST_ASSERT_ERROR(osi.getStrParam(OsiProbName,probname), {}, "glpk", "get problem name"); std::cout << "Solving " << probname << " ... \n" ; osi.initialSolve() ; double val = osi.getObjValue() ; std::cout << "And the answer is " << val << ".\n" ; OSIUNITTEST_ASSERT_ERROR(fabs(val - 3.23) < 0.01, {}, "glpk", "solve exmip1"); } // Do common solverInterface testing { OsiGlpkSolverInterface m; OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir); } }
//-------------------------------------------------------------------------- void OsiCpxSolverInterfaceUnitTest( const std::string & mpsDir, const std::string & netlibDir ) { // Test default constructor { OsiCpxSolverInterface m; assert( m.obj_==NULL ); assert( m.collower_==NULL ); assert( m.colupper_==NULL ); assert( m.coltype_==NULL ); assert( m.rowsense_==NULL ); assert( m.rhs_==NULL ); assert( m.rowrange_==NULL ); assert( m.rowlower_==NULL ); assert( m.rowupper_==NULL ); assert( m.colsol_==NULL ); assert( m.rowsol_==NULL ); assert( m.matrixByRow_==NULL ); assert( m.matrixByCol_==NULL ); assert( m.coltype_==NULL ); assert( m.coltypesize_==0 ); assert( m.getApplicationData() == NULL ); int i=2346; m.setApplicationData(&i); assert( *((int *)(m.getApplicationData())) == i ); } { CoinRelFltEq eq; OsiCpxSolverInterface m; std::string fn = mpsDir+"exmip1"; m.readMps(fn.c_str(),"mps"); int ad = 13579; m.setApplicationData(&ad); assert( *((int *)(m.getApplicationData())) == ad ); { assert( m.getNumCols()==8 ); const CoinPackedMatrix * colCopy = m.getMatrixByCol(); assert( colCopy->getNumCols() == 8 ); assert( colCopy->getMajorDim() == 8 ); assert( colCopy->getNumRows() == 5 ); assert( colCopy->getMinorDim() == 5 ); assert (colCopy->getVectorLengths()[7] == 2 ); CoinPackedMatrix revColCopy; revColCopy.reverseOrderedCopyOf(*colCopy); CoinPackedMatrix rev2ColCopy; rev2ColCopy.reverseOrderedCopyOf(revColCopy); assert( rev2ColCopy.getNumCols() == 8 ); assert( rev2ColCopy.getMajorDim() == 8 ); assert( rev2ColCopy.getNumRows() == 5 ); assert( rev2ColCopy.getMinorDim() == 5 ); assert( rev2ColCopy.getVectorLengths()[7] == 2 ); } { OsiCpxSolverInterface im; assert( im.getNumCols() == 0 ); } // Test copy constructor and assignment operator { OsiCpxSolverInterface lhs; { assert( *((int *)(m.getApplicationData())) == ad ); OsiCpxSolverInterface im(m); assert( *((int *)(im.getApplicationData())) == ad ); OsiCpxSolverInterface imC1(im); assert( imC1.lp_ != im.lp_ ); assert( imC1.getNumCols() == im.getNumCols() ); assert( imC1.getNumRows() == im.getNumRows() ); assert( *((int *)(imC1.getApplicationData())) == ad ); //im.setModelPtr(m); OsiCpxSolverInterface imC2(im); assert( imC2.lp_ != im.lp_ ); assert( imC2.getNumCols() == im.getNumCols() ); assert( imC2.getNumRows() == im.getNumRows() ); assert( *((int *)(imC2.getApplicationData())) == ad ); assert( imC2.lp_ != imC1.lp_ ); lhs=imC2; } // Test that lhs has correct values even though rhs has gone out of scope assert( lhs.lp_ != m.lp_ ); assert( lhs.getNumCols() == m.getNumCols() ); assert( lhs.getNumRows() == m.getNumRows() ); assert( *((int *)(lhs.getApplicationData())) == ad ); } // Test clone { OsiCpxSolverInterface cplexSi(m); OsiSolverInterface * siPtr = &cplexSi; OsiSolverInterface * siClone = siPtr->clone(); OsiCpxSolverInterface * cplexClone = dynamic_cast<OsiCpxSolverInterface*>(siClone); assert( cplexClone != NULL ); assert( cplexClone->lp_ != cplexSi.lp_ ); assert( cplexClone->getNumRows() == cplexSi.getNumRows() ); assert( cplexClone->getNumCols() == m.getNumCols() ); assert( *((int *)(cplexClone->getApplicationData())) == ad ); delete siClone; } // test infinity { OsiCpxSolverInterface si; assert( eq( si.getInfinity(), CPX_INFBOUND ) ); } // Test setting solution { OsiCpxSolverInterface m1(m); int i; double * cs = new double[m1.getNumCols()]; for ( i = 0; i < m1.getNumCols(); i++ ) cs[i] = i + .5; m1.setColSolution(cs); for ( i = 0; i < m1.getNumCols(); i++ ) assert(m1.getColSolution()[i] == i + .5); double * rs = new double[m1.getNumRows()]; for ( i = 0; i < m1.getNumRows(); i++ ) rs[i] = i - .5; m1.setRowPrice(rs); for ( i = 0; i < m1.getNumRows(); i++ ) assert(m1.getRowPrice()[i] == i - .5); delete [] cs; delete [] rs; } // Test fraction Indices { OsiCpxSolverInterface fim; std::string fn = mpsDir+"exmip1"; fim.readMps(fn.c_str(),"mps"); //fim.setModelPtr(m); // exmip1.mps has 2 integer variables with index 2 & 3 assert( fim.isContinuous(0) ); assert( fim.isContinuous(1) ); assert( !fim.isContinuous(2) ); assert( !fim.isContinuous(3) ); assert( fim.isContinuous(4) ); assert( !fim.isInteger(0) ); assert( !fim.isInteger(1) ); assert( fim.isInteger(2) ); assert( fim.isInteger(3) ); assert( !fim.isInteger(4) ); assert( !fim.isBinary(0) ); assert( !fim.isBinary(1) ); assert( fim.isBinary(2) ); assert( fim.isBinary(3) ); assert( !fim.isBinary(4) ); assert( !fim.isIntegerNonBinary(0) ); assert( !fim.isIntegerNonBinary(1) ); assert( !fim.isIntegerNonBinary(2) ); assert( !fim.isIntegerNonBinary(3) ); assert( !fim.isIntegerNonBinary(4) ); // Test fractionalIndices { // Set a solution vector double * cs = new double[fim.getNumCols()]; for ( int i = 0; i < fim.getNumCols(); cs[i++] = 0.0 ); cs[2] = 2.9; cs[3] = 3.0; fim.setColSolution(cs); OsiVectorInt fi = fim.getFractionalIndices(); assert( fi.size() == 1 ); assert( fi[0]==2 ); // Set integer variables very close to integer values cs[2] = 5 + .00001/2.; cs[3] = 8 - .00001/2.; fim.setColSolution(cs); fi = fim.getFractionalIndices(1e-5); assert( fi.size() == 0 ); // Set integer variables close, but beyond tolerances cs[2] = 5 + .00001*2.; cs[3] = 8 - .00001*2.; fim.setColSolution(cs); fi = fim.getFractionalIndices(1e-5); assert( fi.size() == 2 ); assert( fi[0]==2 ); assert( fi[1]==3 ); delete [] cs; } // Change data so column 2 & 3 are integerNonBinary fim.setColUpper(2, 5); fim.setColUpper(3, 6.0); assert( !fim.isBinary(0) ); assert( !fim.isBinary(1) ); assert( !fim.isBinary(2) ); assert( !fim.isBinary(3) ); assert( !fim.isBinary(4) ); assert( !fim.isIntegerNonBinary(0) ); assert( !fim.isIntegerNonBinary(1) ); assert( fim.isIntegerNonBinary(2) ); assert( fim.isIntegerNonBinary(3) ); assert( !fim.isIntegerNonBinary(4) ); } // Test apply cuts method { OsiCpxSolverInterface im(m); OsiCuts cuts; // Generate some cuts { // Get number of rows and columns in model int nr=im.getNumRows(); int nc=im.getNumCols(); assert( nr == 5 ); assert( nc == 8 ); // Generate a valid row cut from thin air int c; { int *inx = new int[nc]; for (c=0;c<nc;c++) inx[c]=c; double *el = new double[nc]; for (c=0;c<nc;c++) el[c]=((double)c)*((double)c); OsiRowCut rc; rc.setRow(nc,inx,el); rc.setLb(-100.); rc.setUb(100.); rc.setEffectiveness(22); cuts.insert(rc); delete[]el; delete[]inx; } // Generate valid col cut from thin air { const double * cplexColLB = im.getColLower(); const double * cplexColUB = im.getColUpper(); int *inx = new int[nc]; for (c=0;c<nc;c++) inx[c]=c; double *lb = new double[nc]; double *ub = new double[nc]; for (c=0;c<nc;c++) lb[c]=cplexColLB[c]+0.001; for (c=0;c<nc;c++) ub[c]=cplexColUB[c]-0.001; OsiColCut cc; cc.setLbs(nc,inx,lb); cc.setUbs(nc,inx,ub); cuts.insert(cc); delete [] ub; delete [] lb; delete [] inx; } { // Generate a row and column cut which have are ineffective OsiRowCut * rcP= new OsiRowCut; rcP->setEffectiveness(-1.); cuts.insert(rcP); assert(rcP==NULL); OsiColCut * ccP= new OsiColCut; ccP->setEffectiveness(-12.); cuts.insert(ccP); assert(ccP==NULL); } { //Generate inconsistent Row cut OsiRowCut rc; const int ne=1; int inx[ne]={-10}; double el[ne]={2.5}; rc.setRow(ne,inx,el); rc.setLb(3.); rc.setUb(4.); assert(!rc.consistent()); cuts.insert(rc); } { //Generate inconsistent col cut OsiColCut cc; const int ne=1; int inx[ne]={-10}; double el[ne]={2.5}; cc.setUbs(ne,inx,el); assert(!cc.consistent()); cuts.insert(cc); } { // Generate row cut which is inconsistent for model m OsiRowCut rc; const int ne=1; int inx[ne]={10}; double el[ne]={2.5}; rc.setRow(ne,inx,el); assert(rc.consistent()); assert(!rc.consistent(im)); cuts.insert(rc); } { // Generate col cut which is inconsistent for model m OsiColCut cc; const int ne=1; int inx[ne]={30}; double el[ne]={2.0}; cc.setLbs(ne,inx,el); assert(cc.consistent()); assert(!cc.consistent(im)); cuts.insert(cc); } { // Generate col cut which is infeasible OsiColCut cc; const int ne=1; int inx[ne]={0}; double el[ne]={2.0}; cc.setUbs(ne,inx,el); cc.setEffectiveness(1000.); assert(cc.consistent()); assert(cc.consistent(im)); assert(cc.infeasible(im)); cuts.insert(cc); } } assert(cuts.sizeRowCuts()==4); assert(cuts.sizeColCuts()==5); OsiSolverInterface::ApplyCutsReturnCode rc = im.applyCuts(cuts); assert( rc.getNumIneffective() == 2 ); assert( rc.getNumApplied() == 2 ); assert( rc.getNumInfeasible() == 1 ); assert( rc.getNumInconsistentWrtIntegerModel() == 2 ); assert( rc.getNumInconsistent() == 2 ); assert( cuts.sizeCuts() == rc.getNumIneffective() + rc.getNumApplied() + rc.getNumInfeasible() + rc.getNumInconsistentWrtIntegerModel() + rc.getNumInconsistent() ); } { OsiCpxSolverInterface cplexSi(m); int nc = cplexSi.getNumCols(); int nr = cplexSi.getNumRows(); const double * cl = cplexSi.getColLower(); const double * cu = cplexSi.getColUpper(); const double * rl = cplexSi.getRowLower(); const double * ru = cplexSi.getRowUpper(); assert( nc == 8 ); assert( nr == 5 ); assert( eq(cl[0],2.5) ); assert( eq(cl[1],0.0) ); assert( eq(cu[1],4.1) ); assert( eq(cu[2],1.0) ); assert( eq(rl[0],2.5) ); assert( eq(rl[4],3.0) ); assert( eq(ru[1],2.1) ); assert( eq(ru[4],15.0) ); double newCs[8] = {1., 2., 3., 4., 5., 6., 7., 8.}; cplexSi.setColSolution(newCs); const double * cs = cplexSi.getColSolution(); assert( eq(cs[0],1.0) ); assert( eq(cs[7],8.0) ); { OsiCpxSolverInterface solnSi(cplexSi); const double * cs = solnSi.getColSolution(); assert( eq(cs[0],1.0) ); assert( eq(cs[7],8.0) ); } assert( !eq(cl[3],1.2345) ); cplexSi.setColLower( 3, 1.2345 ); assert( eq(cplexSi.getColLower()[3],1.2345) ); assert( !eq(cu[4],10.2345) ); cplexSi.setColUpper( 4, 10.2345 ); assert( eq(cplexSi.getColUpper()[4],10.2345) ); assert( eq(cplexSi.getObjValue(),0.0) ); assert( eq( cplexSi.getObjCoefficients()[0], 1.0) ); assert( eq( cplexSi.getObjCoefficients()[1], 0.0) ); assert( eq( cplexSi.getObjCoefficients()[2], 0.0) ); assert( eq( cplexSi.getObjCoefficients()[3], 0.0) ); assert( eq( cplexSi.getObjCoefficients()[4], 2.0) ); assert( eq( cplexSi.getObjCoefficients()[5], 0.0) ); assert( eq( cplexSi.getObjCoefficients()[6], 0.0) ); assert( eq( cplexSi.getObjCoefficients()[7], -1.0) ); } // Test getMatrixByRow method { const OsiCpxSolverInterface si(m); const CoinPackedMatrix * smP = si.getMatrixByRow(); //const CoinPackedMatrix * osmP = dynamic_cast(const OsiCpxPackedMatrix*)(smP); //assert( osmP!=NULL ); CoinRelFltEq eq; const double * ev = smP->getElements(); assert( eq(ev[0], 3.0) ); assert( eq(ev[1], 1.0) ); assert( eq(ev[2], -2.0) ); assert( eq(ev[3], -1.0) ); assert( eq(ev[4], -1.0) ); assert( eq(ev[5], 2.0) ); assert( eq(ev[6], 1.1) ); assert( eq(ev[7], 1.0) ); assert( eq(ev[8], 1.0) ); assert( eq(ev[9], 2.8) ); assert( eq(ev[10], -1.2) ); assert( eq(ev[11], 5.6) ); assert( eq(ev[12], 1.0) ); assert( eq(ev[13], 1.9) ); const int * mi = smP->getVectorStarts(); assert( mi[0]==0 ); assert( mi[1]==5 ); assert( mi[2]==7 ); assert( mi[3]==9 ); assert( mi[4]==11 ); assert( mi[5]==14 ); const int * ei = smP->getIndices(); assert( ei[0] == 0 ); assert( ei[1] == 1 ); assert( ei[2] == 3 ); assert( ei[3] == 4 ); assert( ei[4] == 7 ); assert( ei[5] == 1 ); assert( ei[6] == 2 ); assert( ei[7] == 2 ); assert( ei[8] == 5 ); assert( ei[9] == 3 ); assert( ei[10] == 6 ); assert( ei[11] == 0 ); assert( ei[12] == 4 ); assert( ei[13] == 7 ); assert( smP->getMajorDim() == 5 ); assert( smP->getNumElements() == 14 ); } //-------------- // Test rowsense, rhs, rowrange, getMatrixByRow { OsiCpxSolverInterface lhs; { #if 0 assert( m.obj_==NULL ); assert( m.collower_==NULL ); assert( m.colupper_==NULL ); assert( m.rowrange_==NULL ); assert( m.rowsense_==NULL ); assert( m.rhs_==NULL ); assert( m.rowlower_==NULL ); assert( m.rowupper_==NULL ); assert( m.colsol_==NULL ); assert( m.rowsol_==NULL ); assert( m.getMatrixByRow_==NULL ); #endif OsiCpxSolverInterface siC1(m); assert( siC1.obj_==NULL ); assert( siC1.collower_==NULL ); assert( siC1.colupper_==NULL ); // assert( siC1.coltype_==NULL ); assert( siC1.rowrange_==NULL ); assert( siC1.rowsense_==NULL ); assert( siC1.rhs_==NULL ); assert( siC1.rowlower_==NULL ); assert( siC1.rowupper_==NULL ); assert( siC1.colsol_!=NULL ); assert( siC1.rowsol_!=NULL ); assert( siC1.matrixByRow_==NULL ); const char * siC1rs = siC1.getRowSense(); assert( siC1rs[0]=='G' ); assert( siC1rs[1]=='L' ); assert( siC1rs[2]=='E' ); assert( siC1rs[3]=='R' ); assert( siC1rs[4]=='R' ); const double * siC1rhs = siC1.getRightHandSide(); assert( eq(siC1rhs[0],2.5) ); assert( eq(siC1rhs[1],2.1) ); assert( eq(siC1rhs[2],4.0) ); assert( eq(siC1rhs[3],5.0) ); assert( eq(siC1rhs[4],15.) ); const double * siC1rr = siC1.getRowRange(); assert( eq(siC1rr[0],0.0) ); assert( eq(siC1rr[1],0.0) ); assert( eq(siC1rr[2],0.0) ); assert( eq(siC1rr[3],5.0-1.8) ); assert( eq(siC1rr[4],15.0-3.0) ); const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow(); assert( siC1mbr != NULL ); const double * ev = siC1mbr->getElements(); assert( eq(ev[0], 3.0) ); assert( eq(ev[1], 1.0) ); assert( eq(ev[2], -2.0) ); assert( eq(ev[3], -1.0) ); assert( eq(ev[4], -1.0) ); assert( eq(ev[5], 2.0) ); assert( eq(ev[6], 1.1) ); assert( eq(ev[7], 1.0) ); assert( eq(ev[8], 1.0) ); assert( eq(ev[9], 2.8) ); assert( eq(ev[10], -1.2) ); assert( eq(ev[11], 5.6) ); assert( eq(ev[12], 1.0) ); assert( eq(ev[13], 1.9) ); const int * mi = siC1mbr->getVectorStarts(); assert( mi[0]==0 ); assert( mi[1]==5 ); assert( mi[2]==7 ); assert( mi[3]==9 ); assert( mi[4]==11 ); assert( mi[5]==14 ); const int * ei = siC1mbr->getIndices(); assert( ei[0] == 0 ); assert( ei[1] == 1 ); assert( ei[2] == 3 ); assert( ei[3] == 4 ); assert( ei[4] == 7 ); assert( ei[5] == 1 ); assert( ei[6] == 2 ); assert( ei[7] == 2 ); assert( ei[8] == 5 ); assert( ei[9] == 3 ); assert( ei[10] == 6 ); assert( ei[11] == 0 ); assert( ei[12] == 4 ); assert( ei[13] == 7 ); assert( siC1mbr->getMajorDim() == 5 ); assert( siC1mbr->getNumElements() == 14 ); assert( siC1rs == siC1.getRowSense() ); assert( siC1rhs == siC1.getRightHandSide() ); assert( siC1rr == siC1.getRowRange() ); // Change CPLEX Model by adding free row OsiRowCut rc; rc.setLb(-COIN_DBL_MAX); rc.setUb( COIN_DBL_MAX); OsiCuts cuts; cuts.insert(rc); siC1.applyCuts(cuts); // Since model was changed, test that cached // data is now freed. assert( siC1.obj_==NULL ); assert( siC1.collower_==NULL ); assert( siC1.colupper_==NULL ); // assert( siC1.coltype_==NULL ); assert( siC1.rowrange_==NULL ); assert( siC1.rowsense_==NULL ); assert( siC1.rhs_==NULL ); assert( siC1.rowlower_==NULL ); assert( siC1.rowupper_==NULL ); assert( siC1.colsol_==NULL ); assert( siC1.rowsol_==NULL ); assert( siC1.matrixByRow_==NULL ); siC1rs = siC1.getRowSense(); siC1rhs = siC1.getRightHandSide(); siC1rr = siC1.getRowRange(); assert( siC1rs[0]=='G' ); assert( siC1rs[1]=='L' ); assert( siC1rs[2]=='E' ); assert( siC1rs[3]=='R' ); assert( siC1rs[4]=='R' ); assert( siC1rs[5]=='N' ); assert( eq(siC1rhs[0],2.5) ); assert( eq(siC1rhs[1],2.1) ); assert( eq(siC1rhs[2],4.0) ); assert( eq(siC1rhs[3],5.0) ); assert( eq(siC1rhs[4],15.) ); assert( eq(siC1rhs[5],0.0) ); assert( eq(siC1rr[0],0.0) ); assert( eq(siC1rr[1],0.0) ); assert( eq(siC1rr[2],0.0) ); assert( eq(siC1rr[3],5.0-1.8) ); assert( eq(siC1rr[4],15.0-3.0) ); assert( eq(siC1rr[5],0.0) ); lhs=siC1; } // Test that lhs has correct values even though siC1 has gone out of scope assert( lhs.obj_==NULL ); assert( lhs.collower_==NULL ); assert( lhs.colupper_==NULL ); // assert( lhs.coltype_==NULL ); assert( lhs.rowrange_==NULL ); assert( lhs.rowsense_==NULL ); assert( lhs.rhs_==NULL ); assert( lhs.rowlower_==NULL ); assert( lhs.rowupper_==NULL ); assert( lhs.colsol_!=NULL ); assert( lhs.rowsol_!=NULL ); assert( lhs.matrixByRow_==NULL ); const char * lhsrs = lhs.getRowSense(); assert( lhsrs[0]=='G' ); assert( lhsrs[1]=='L' ); assert( lhsrs[2]=='E' ); assert( lhsrs[3]=='R' ); assert( lhsrs[4]=='R' ); assert( lhsrs[5]=='N' ); const double * lhsrhs = lhs.getRightHandSide(); assert( eq(lhsrhs[0],2.5) ); assert( eq(lhsrhs[1],2.1) ); assert( eq(lhsrhs[2],4.0) ); assert( eq(lhsrhs[3],5.0) ); assert( eq(lhsrhs[4],15.) ); assert( eq(lhsrhs[5],0.0) ); const double *lhsrr = lhs.getRowRange(); assert( eq(lhsrr[0],0.0) ); assert( eq(lhsrr[1],0.0) ); assert( eq(lhsrr[2],0.0) ); assert( eq(lhsrr[3],5.0-1.8) ); assert( eq(lhsrr[4],15.0-3.0) ); assert( eq(lhsrr[5],0.0) ); const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow(); assert( lhsmbr != NULL ); const double * ev = lhsmbr->getElements(); assert( eq(ev[0], 3.0) ); assert( eq(ev[1], 1.0) ); assert( eq(ev[2], -2.0) ); assert( eq(ev[3], -1.0) ); assert( eq(ev[4], -1.0) ); assert( eq(ev[5], 2.0) ); assert( eq(ev[6], 1.1) ); assert( eq(ev[7], 1.0) ); assert( eq(ev[8], 1.0) ); assert( eq(ev[9], 2.8) ); assert( eq(ev[10], -1.2) ); assert( eq(ev[11], 5.6) ); assert( eq(ev[12], 1.0) ); assert( eq(ev[13], 1.9) ); const int * mi = lhsmbr->getVectorStarts(); assert( mi[0]==0 ); assert( mi[1]==5 ); assert( mi[2]==7 ); assert( mi[3]==9 ); assert( mi[4]==11 ); assert( mi[5]==14 ); const int * ei = lhsmbr->getIndices(); assert( ei[0] == 0 ); assert( ei[1] == 1 ); assert( ei[2] == 3 ); assert( ei[3] == 4 ); assert( ei[4] == 7 ); assert( ei[5] == 1 ); assert( ei[6] == 2 ); assert( ei[7] == 2 ); assert( ei[8] == 5 ); assert( ei[9] == 3 ); assert( ei[10] == 6 ); assert( ei[11] == 0 ); assert( ei[12] == 4 ); assert( ei[13] == 7 ); int md = lhsmbr->getMajorDim(); assert( md == 6 ); assert( lhsmbr->getNumElements() == 14 ); } } // Do common solverInterface testing by calling the // base class testing method. { OsiCpxSolverInterface m; OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir); } }
//----------------------------------------------------------------------- // Test XPRESS-MP solution methods. void OsiXprSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir) { #if 0 // Test to at least see if licence managment is working { int iret = initlz(NULL, 0); if ( iret != 0 ) getipv(N_ERRNO, &iret); assert(iret == 0); } #endif // Test default constructor { assert( OsiXprSolverInterface::getNumInstances()==0 ); OsiXprSolverInterface m; // assert( m.xprSaved_ == false ); // assert( m.xprMatrixId_ = -1 ); assert( m.xprProbname_ == "" ); assert( m.matrixByRow_ == NULL ); assert( m.colupper_ == NULL ); assert( m.collower_ == NULL ); assert( m.rowupper_ == NULL ); assert( m.rowlower_ == NULL ); assert( m.rowsense_ == NULL ); assert( m.rhs_ == NULL ); assert( m.rowrange_ == NULL ); assert( m.colsol_ == NULL ); assert( m.rowprice_ == NULL ); assert( m.ivarind_ == NULL ); assert( m.ivartype_ == NULL ); assert( m.vartype_ == NULL ); assert( OsiXprSolverInterface::getNumInstances() == 1 ); // assert( OsiXprSolverInterface::xprCurrentProblem_ == NULL ); assert( m.getApplicationData() == NULL ); int i = 2346; m.setApplicationData(&i); assert( *((int *)(m.getApplicationData())) == i ); } assert( OsiXprSolverInterface::getNumInstances() == 0 ); { CoinRelFltEq eq; OsiXprSolverInterface m; assert( OsiXprSolverInterface::getNumInstances() == 1 ); std::string fn = mpsDir+"exmip1"; m.readMps(fn.c_str()); // assert( OsiXprSolverInterface::xprCurrentProblem_ == &m ); // This assert fails on windows because fn is mixed case and xprProbname_is uppercase. //assert( m.xprProbname_ == fn ); int ad = 13579; m.setApplicationData(&ad); assert( *((int *)(m.getApplicationData())) == ad ); { OsiXprSolverInterface im; // assert( im.modelPtr_==NULL ); assert( im.getNumCols() == 0 ); // assert( im.modelPtr()!=NULL ); // assert( im.mutableModelPtr()!=NULL ); // assert( im.modelPtr() == im.mutableModelPtr() ); } // Test copy constructor and assignment operator { OsiXprSolverInterface lhs; { assert( *((int *)(m.getApplicationData())) == ad ); OsiXprSolverInterface im(m); assert( *((int *)(im.getApplicationData())) == ad ); OsiXprSolverInterface imC1(im); // assert( imC1.mutableModelPtr()!=im.mutableModelPtr() ); // assert( imC1.modelPtr()!=im.modelPtr() ); assert( imC1.getNumCols() == im.getNumCols() ); assert( imC1.getNumRows() == im.getNumRows() ); assert( *((int *)(imC1.getApplicationData())) == ad ); //im.setModelPtr(m); OsiXprSolverInterface imC2(im); // assert( imC2.mutableModelPtr()!=im.mutableModelPtr() ); // assert( imC2.modelPtr()!=im.modelPtr() ); assert( imC2.getNumCols() == im.getNumCols() ); assert( imC2.getNumRows() == im.getNumRows() ); assert( *((int *)(imC2.getApplicationData())) == ad ); // assert( imC2.mutableModelPtr()!=imC1.mutableModelPtr() ); // assert( imC2.modelPtr()!=imC1.modelPtr() ); lhs=imC2; } // Test that lhs has correct values even though rhs has gone out of scope // assert( lhs.mutableModelPtr() != m.mutableModelPtr() ); // assert( lhs.modelPtr() != m.modelPtr() ); assert( lhs.getNumCols() == m.getNumCols() ); assert( lhs.getNumRows() == m.getNumRows() ); assert( *((int *)(lhs.getApplicationData())) == ad ); } // Test clone { OsiXprSolverInterface xprSi(m); OsiSolverInterface * siPtr = &xprSi; OsiSolverInterface * siClone = siPtr->clone(); OsiXprSolverInterface * xprClone = dynamic_cast<OsiXprSolverInterface*>(siClone); assert( xprClone != NULL ); // assert( xprClone->modelPtr() != xprSi.modelPtr() ); // assert( xprClone->modelPtr() != m.modelPtr() ); assert( xprClone->getNumRows() == xprSi.getNumRows() ); assert( xprClone->getNumCols() == m.getNumCols() ); assert( *((int *)(xprClone->getApplicationData())) == ad ); delete siClone; } // Test infinity { OsiXprSolverInterface si; assert( eq(si.getInfinity(), XPRS_PLUSINFINITY) ); } // Test setting solution { OsiXprSolverInterface m1(m); int i; double * cs = new double[m1.getNumCols()]; for ( i = 0; i < m1.getNumCols(); i++ ) cs[i] = i + .5; m1.setColSolution(cs); for ( i = 0; i < m1.getNumCols(); i++ ) assert(m1.getColSolution()[i] == i + .5); double * rs = new double[m1.getNumRows()]; for ( i = 0; i < m1.getNumRows(); i++ ) rs[i] = i - .5; m1.setRowPrice(rs); for ( i = 0; i < m1.getNumRows(); i++ ) assert(m1.getRowPrice()[i] == i - .5); delete [] cs; delete [] rs; } // Test fraction Indices { OsiXprSolverInterface fim; std::string fn = mpsDir+"exmip1"; fim.readMps(fn.c_str()); //fim.setModelPtr(m); // exmip1.mps has 2 integer variables with index 2 & 3 assert( fim.isContinuous(0) ); assert( fim.isContinuous(1) ); assert( !fim.isContinuous(2) ); assert( !fim.isContinuous(3) ); assert( fim.isContinuous(4) ); assert( !fim.isInteger(0) ); assert( !fim.isInteger(1) ); assert( fim.isInteger(2) ); assert( fim.isInteger(3) ); assert( !fim.isInteger(4) ); // XPRESS-MP incorrectly treats unbounded integer variables as // general integers instead of binary (as in MPSX standard) assert( !fim.isBinary(0) ); assert( !fim.isBinary(1) ); assert( fim.isBinary(2) ); assert( fim.isBinary(3) ); assert( !fim.isBinary(4) ); assert( !fim.isIntegerNonBinary(0) ); assert( !fim.isIntegerNonBinary(1) ); assert( !fim.isIntegerNonBinary(2) ); assert( !fim.isIntegerNonBinary(3) ); assert( !fim.isIntegerNonBinary(4) ); // Test fractionalIndices { // Set a solution vector double * cs = new double[fim.getNumCols()]; for ( int i = 0; i < fim.getNumCols(); cs[i++] = 0.0 ); cs[2] = 2.9; cs[3] = 3.0; fim.setColSolution(cs); OsiVectorInt fi = fim.getFractionalIndices(); assert( fi.size() == 1 ); assert( fi[0]==2 ); // Set integer variables very close to integer values cs[2] = 5 + .00001/2.; cs[3] = 8 - .00001/2.; fim.setColSolution(cs); fi = fim.getFractionalIndices(1e-5); assert( fi.size() == 0 ); // Set integer variables close, but beyond tolerances cs[2] = 5 + .00001*2.; cs[3] = 8 - .00001*2.; fim.setColSolution(cs); fi = fim.getFractionalIndices(1e-5); assert( fi.size() == 2 ); assert( fi[0]==2 ); assert( fi[1]==3 ); delete [] cs; } // Change data so column 2 & 3 are integerNonBinary fim.setColUpper(2, 5); fim.setColUpper(3, 6.0); assert( !fim.isBinary(0) ); assert( !fim.isBinary(1) ); assert( !fim.isBinary(2) ); assert( !fim.isBinary(3) ); assert( !fim.isBinary(4) ); assert( !fim.isIntegerNonBinary(0) ); assert( !fim.isIntegerNonBinary(1) ); assert( fim.isIntegerNonBinary(2) ); assert( fim.isIntegerNonBinary(3) ); assert( !fim.isIntegerNonBinary(4) ); } // Test apply cut method { OsiXprSolverInterface im(m); OsiCuts cuts; // Generate some cuts //cg.generateCuts(im,cuts); { // Get number of rows and columns in model int nr=im.getNumRows(); int nc=im.getNumCols(); assert ( nr == 5 ); assert ( nc == 8 ); // Generate a valid row cut from thin air int c; { int *inx = new int[nc]; for (c=0;c<nc;c++) inx[c]=c; double *el = new double[nc]; for (c=0;c<nc;c++) el[c]=((double)c)*((double)c); OsiRowCut rc; rc.setRow(nc,inx,el); rc.setLb(-100.); rc.setUb(100.); rc.setEffectiveness(22); cuts.insert(rc); delete[]el; delete[]inx; } // Generate valid col cut from thin air { const double * xprColLB = im.getColLower(); const double * xprColUB = im.getColUpper(); int *inx = new int[nc]; for (c=0;c<nc;c++) inx[c]=c; double *lb = new double[nc]; double *ub = new double[nc]; for (c=0;c<nc;c++) lb[c]=xprColLB[c]+0.001; for (c=0;c<nc;c++) ub[c]=xprColUB[c]-0.001; OsiColCut cc; cc.setLbs(nc,inx,lb); cc.setUbs(nc,inx,ub); cuts.insert(cc); delete [] ub; delete [] lb; delete [] inx; } { // Generate a row and column cut which have are ineffective OsiRowCut * rcP= new OsiRowCut; rcP->setEffectiveness(-1.); cuts.insert(rcP); assert(rcP==NULL); OsiColCut * ccP= new OsiColCut; ccP->setEffectiveness(-12.); cuts.insert(ccP); assert(ccP==NULL); } { //Generate inconsistent Row cut OsiRowCut rc; const int ne=1; int inx[ne]={-10}; double el[ne]={2.5}; rc.setRow(ne,inx,el); rc.setLb(3.); rc.setUb(4.); assert(!rc.consistent()); cuts.insert(rc); } { //Generate inconsistent col cut OsiColCut cc; const int ne=1; int inx[ne]={-10}; double el[ne]={2.5}; cc.setUbs(ne,inx,el); assert(!cc.consistent()); cuts.insert(cc); } { // Generate row cut which is inconsistent for model m OsiRowCut rc; const int ne=1; int inx[ne]={10}; double el[ne]={2.5}; rc.setRow(ne,inx,el); assert(rc.consistent()); assert(!rc.consistent(im)); cuts.insert(rc); } { // Generate col cut which is inconsistent for model m OsiColCut cc; const int ne=1; int inx[ne]={30}; double el[ne]={2.0}; cc.setLbs(ne,inx,el); assert(cc.consistent()); assert(!cc.consistent(im)); cuts.insert(cc); } { // Generate col cut which is infeasible OsiColCut cc; const int ne=1; int inx[ne]={0}; double el[ne]={2.0}; cc.setUbs(ne,inx,el); cc.setEffectiveness(1000.); assert(cc.consistent()); assert(cc.consistent(im)); assert(cc.infeasible(im)); cuts.insert(cc); } } assert(cuts.sizeRowCuts()==4); assert(cuts.sizeColCuts()==5); OsiSolverInterface::ApplyCutsReturnCode rc = im.applyCuts(cuts); assert( rc.getNumIneffective() == 2 ); assert( rc.getNumApplied() == 2 ); assert( rc.getNumInfeasible() == 1 ); assert( rc.getNumInconsistentWrtIntegerModel() == 2 ); assert( rc.getNumInconsistent() == 2 ); assert( cuts.sizeCuts() == rc.getNumIneffective() + rc.getNumApplied() + rc.getNumInfeasible() + rc.getNumInconsistentWrtIntegerModel() + rc.getNumInconsistent() ); } { OsiXprSolverInterface xprSi(m); int nc = xprSi.getNumCols(); int nr = xprSi.getNumRows(); assert( nc == 8 ); assert( nr == 5 ); assert( eq(xprSi.getColLower()[0],2.5) ); assert( eq(xprSi.getColLower()[1],0.0) ); assert( eq(xprSi.getColUpper()[1],4.1) ); assert( eq(xprSi.getRowLower()[0],2.5) ); assert( eq(xprSi.getRowLower()[4],3.0) ); assert( eq(xprSi.getRowUpper()[1],2.1) ); assert( eq(xprSi.getRowUpper()[4],15.0) ); // const double * cs = xprSi.getColSolution(); // assert( eq(cs[0],2.5) ); // assert( eq(cs[7],0.0) ); assert( !eq(xprSi.getColLower()[3],1.2345) ); xprSi.setColLower( 3, 1.2345 ); assert( eq(xprSi.getColLower()[3],1.2345) ); assert( !eq(xprSi.getColUpper()[4],10.2345) ); xprSi.setColUpper( 4, 10.2345 ); assert( eq(xprSi.getColUpper()[4],10.2345) ); //assert( eq(xprSi.getObjValue(),0.0) ); assert( eq( xprSi.getObjCoefficients()[0], 1.0) ); assert( eq( xprSi.getObjCoefficients()[1], 0.0) ); assert( eq( xprSi.getObjCoefficients()[2], 0.0) ); assert( eq( xprSi.getObjCoefficients()[3], 0.0) ); assert( eq( xprSi.getObjCoefficients()[4], 2.0) ); assert( eq( xprSi.getObjCoefficients()[5], 0.0) ); assert( eq( xprSi.getObjCoefficients()[6], 0.0) ); assert( eq( xprSi.getObjCoefficients()[7], -1.0) ); } // Test matrixByRow method { const OsiXprSolverInterface si(m); const CoinPackedMatrix * smP = si.getMatrixByRow(); CoinRelFltEq eq; const double * ev = smP->getElements(); assert( eq(ev[0], 3.0) ); assert( eq(ev[1], 1.0) ); assert( eq(ev[2], -2.0) ); assert( eq(ev[3], -1.0) ); assert( eq(ev[4], -1.0) ); assert( eq(ev[5], 2.0) ); assert( eq(ev[6], 1.1) ); assert( eq(ev[7], 1.0) ); assert( eq(ev[8], 1.0) ); assert( eq(ev[9], 2.8) ); assert( eq(ev[10], -1.2) ); assert( eq(ev[11], 5.6) ); assert( eq(ev[12], 1.0) ); assert( eq(ev[13], 1.9) ); const int * mi = smP->getVectorStarts(); assert( mi[0]==0 ); assert( mi[1]==5 ); assert( mi[2]==7 ); assert( mi[3]==9 ); assert( mi[4]==11 ); assert( mi[5]==14 ); const int * ei = smP->getIndices(); assert( ei[0] == 0 ); assert( ei[1] == 1 ); assert( ei[2] == 3 ); assert( ei[3] == 4 ); assert( ei[4] == 7 ); assert( ei[5] == 1 ); assert( ei[6] == 2 ); assert( ei[7] == 2 ); assert( ei[8] == 5 ); assert( ei[9] == 3 ); assert( ei[10] == 6 ); assert( ei[11] == 0 ); assert( ei[12] == 4 ); assert( ei[13] == 7 ); assert( smP->getMajorDim() == 5 ); assert( smP->getMinorDim() == 8 ); assert( smP->getNumElements() == 14 ); assert( smP->getSizeVectorStarts()==6 ); } //-------------- // Test rowsense, rhs, rowrange, matrixByRow { OsiXprSolverInterface lhs; { assert( m.rowrange_==NULL ); assert( m.rowsense_==NULL ); assert( m.rhs_==NULL ); OsiXprSolverInterface siC1(m); assert( siC1.rowrange_==NULL ); assert( siC1.rowsense_==NULL ); assert( siC1.rhs_==NULL ); const char * siC1rs = siC1.getRowSense(); assert( siC1rs[0] == 'G' ); assert( siC1rs[1] == 'L' ); assert( siC1rs[2] == 'E' ); assert( siC1rs[3] == 'R' ); assert( siC1rs[4] == 'R' ); const double * siC1rhs = siC1.getRightHandSide(); assert( eq(siC1rhs[0], 2.5) ); assert( eq(siC1rhs[1], 2.1) ); assert( eq(siC1rhs[2], 4.0) ); assert( eq(siC1rhs[3], 5.0) ); assert( eq(siC1rhs[4], 15.0) ); const double * siC1rr = siC1.getRowRange(); assert( eq(siC1rr[0], 0.0) ); assert( eq(siC1rr[1], 0.0) ); assert( eq(siC1rr[2], 0.0) ); assert( eq(siC1rr[3], 5.0 - 1.8) ); assert( eq(siC1rr[4], 15.0 - 3.0) ); const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow(); assert( siC1mbr != NULL ); const double * ev = siC1mbr->getElements(); assert( eq(ev[0], 3.0) ); assert( eq(ev[1], 1.0) ); assert( eq(ev[2], -2.0) ); assert( eq(ev[3], -1.0) ); assert( eq(ev[4], -1.0) ); assert( eq(ev[5], 2.0) ); assert( eq(ev[6], 1.1) ); assert( eq(ev[7], 1.0) ); assert( eq(ev[8], 1.0) ); assert( eq(ev[9], 2.8) ); assert( eq(ev[10], -1.2) ); assert( eq(ev[11], 5.6) ); assert( eq(ev[12], 1.0) ); assert( eq(ev[13], 1.9) ); const int * mi = siC1mbr->getVectorStarts(); assert( mi[0]==0 ); assert( mi[1]==5 ); assert( mi[2]==7 ); assert( mi[3]==9 ); assert( mi[4]==11 ); assert( mi[5]==14 ); const int * ei = siC1mbr->getIndices(); assert( ei[0] == 0 ); assert( ei[1] == 1 ); assert( ei[2] == 3 ); assert( ei[3] == 4 ); assert( ei[4] == 7 ); assert( ei[5] == 1 ); assert( ei[6] == 2 ); assert( ei[7 ] == 2 ); assert( ei[8 ] == 5 ); assert( ei[9 ] == 3 ); assert( ei[10] == 6 ); assert( ei[11] == 0 ); assert( ei[12] == 4 ); assert( ei[13] == 7 ); assert( siC1mbr->getMajorDim() == 5 ); assert( siC1mbr->getMinorDim() == 8 ); assert( siC1mbr->getNumElements() == 14 ); assert( siC1mbr->getSizeVectorStarts()==6 ); assert( siC1rs == siC1.getRowSense() ); assert( siC1rhs == siC1.getRightHandSide() ); assert( siC1rr == siC1.getRowRange() ); // Change XPRESS Model by adding free row OsiRowCut rc; rc.setLb(-COIN_DBL_MAX); rc.setUb(COIN_DBL_MAX); OsiCuts cuts; cuts.insert(rc); siC1.applyCuts(cuts); // Since model was changed, test that cached // data is now freed. assert( siC1.rowrange_ == NULL ); assert( siC1.rowsense_ == NULL ); assert( siC1.rhs_ == NULL ); assert( siC1.matrixByRow_ == NULL ); siC1rs = siC1.getRowSense(); assert( siC1rs[0] == 'G' ); assert( siC1rs[1] == 'L' ); assert( siC1rs[2] == 'E' ); assert( siC1rs[3] == 'R' ); assert( siC1rs[4] == 'R' ); assert( siC1rs[5] == 'N' ); siC1rhs = siC1.getRightHandSide(); assert( eq(siC1rhs[0],2.5) ); assert( eq(siC1rhs[1],2.1) ); assert( eq(siC1rhs[2],4.0) ); assert( eq(siC1rhs[3],5.0) ); assert( eq(siC1rhs[4],15.0) ); assert( eq(siC1rhs[5],0.0) ); siC1rr = siC1.getRowRange(); assert( eq(siC1rr[0], 0.0) ); assert( eq(siC1rr[1], 0.0) ); assert( eq(siC1rr[2], 0.0) ); assert( eq(siC1rr[3], 5.0 - 1.8) ); assert( eq(siC1rr[4], 15.0 - 3.0) ); assert( eq(siC1rr[5], 0.0) ); lhs=siC1; } // Test that lhs has correct values even though siC1 has gone out of scope assert( lhs.rowrange_ == NULL ); assert( lhs.rowsense_ == NULL ); assert( lhs.rhs_ == NULL ); assert( lhs.matrixByRow_ == NULL ); const char * lhsrs = lhs.getRowSense(); assert( lhsrs[0] == 'G' ); assert( lhsrs[1] == 'L' ); assert( lhsrs[2] == 'E' ); assert( lhsrs[3] == 'R' ); assert( lhsrs[4] == 'R' ); assert( lhsrs[5] == 'N' ); const double * lhsrhs = lhs.getRightHandSide(); assert( eq(lhsrhs[0], 2.5) ); assert( eq(lhsrhs[1], 2.1) ); assert( eq(lhsrhs[2], 4.0) ); assert( eq(lhsrhs[3], 5.0) ); assert( eq(lhsrhs[4], 15.0) ); assert( eq(lhsrhs[5], 0.0) ); const double *lhsrr = lhs.getRowRange(); assert( eq(lhsrr[0], 0.0) ); assert( eq(lhsrr[1], 0.0) ); assert( eq(lhsrr[2], 0.0) ); assert( eq(lhsrr[3], 5.0 - 1.8) ); assert( eq(lhsrr[4], 15.0 - 3.0) ); assert( eq(lhsrr[5], 0.0) ); const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow(); assert( lhsmbr != NULL ); const double * ev = lhsmbr->getElements(); assert( eq(ev[0], 3.0) ); assert( eq(ev[1], 1.0) ); assert( eq(ev[2], -2.0) ); assert( eq(ev[3], -1.0) ); assert( eq(ev[4], -1.0) ); assert( eq(ev[5], 2.0) ); assert( eq(ev[6], 1.1) ); assert( eq(ev[7], 1.0) ); assert( eq(ev[8], 1.0) ); assert( eq(ev[9], 2.8) ); assert( eq(ev[10], -1.2) ); assert( eq(ev[11], 5.6) ); assert( eq(ev[12], 1.0) ); assert( eq(ev[13], 1.9) ); const int * mi = lhsmbr->getVectorStarts(); assert( mi[0]==0 ); assert( mi[1]==5 ); assert( mi[2]==7 ); assert( mi[3]==9 ); assert( mi[4]==11 ); assert( mi[5]==14 ); const int * ei = lhsmbr->getIndices(); assert( ei[0] == 0 ); assert( ei[1] == 1 ); assert( ei[2] == 3 ); assert( ei[3] == 4 ); assert( ei[4] == 7 ); assert( ei[5] == 1 ); assert( ei[6] == 2 ); assert( ei[7] == 2 ); assert( ei[8] == 5 ); assert( ei[9] == 3 ); assert( ei[10] == 6 ); assert( ei[11] == 0 ); assert( ei[12] == 4 ); assert( ei[13] == 7 ); assert( lhsmbr->getMajorDim() == 6 ); assert( lhsmbr->getMinorDim() == 8 ); assert( lhsmbr->getNumElements() == 14 ); assert( lhsmbr->getSizeVectorStarts()==7 ); } //-------------- // Test load problem { OsiXprSolverInterface base(m); base.initialSolve(); assert(m.getNumRows() == base.getNumRows()); OsiXprSolverInterface si1,si2,si3,si4; si1.loadProblem( *base.getMatrixByCol(), base.getColLower(),base.getColUpper(),base.getObjCoefficients(), base.getRowSense(),base.getRightHandSide(),base.getRowRange()); si1.initialSolve(); assert(eq(base.getObjValue(), si1.getObjValue())); assert(m.getNumRows() == si1.getNumRows()); si2.loadProblem( *base.getMatrixByRow(), base.getColLower(),base.getColUpper(),base.getObjCoefficients(), base.getRowSense(),base.getRightHandSide(),base.getRowRange()); si2.initialSolve(); assert(eq(base.getObjValue(), si2.getObjValue())); assert(m.getNumRows() == si2.getNumRows()); si3.loadProblem( *base.getMatrixByCol(), base.getColLower(),base.getColUpper(),base.getObjCoefficients(), base.getRowLower(),base.getRowUpper() ); si3.initialSolve(); assert(eq(base.getObjValue(), si3.getObjValue())); assert(m.getNumRows() == si3.getNumRows()); si4.loadProblem( *base.getMatrixByCol(), base.getColLower(),base.getColUpper(),base.getObjCoefficients(), base.getRowLower(),base.getRowUpper() ); si4.initialSolve(); assert(eq(base.getObjValue(), si4.getObjValue())); assert(m.getNumRows() == si4.getNumRows()); base.initialSolve(); si1.initialSolve(); si2.initialSolve(); si3.initialSolve(); si4.initialSolve(); // Create an indices vector assert(base.getNumCols()<10); assert(base.getNumRows()<10); int indices[10]; int i; for (i=0; i<10; i++) indices[i]=i; // Test collower CoinPackedVector basePv,pv; basePv.setVector(base.getNumCols(),indices,base.getColLower()); pv.setVector( si1.getNumCols(),indices, si1.getColLower()); assert(basePv.isEquivalent(pv)); pv.setVector( si2.getNumCols(),indices, si2.getColLower()); assert(basePv.isEquivalent(pv)); pv.setVector( si3.getNumCols(),indices, si3.getColLower()); assert(basePv.isEquivalent(pv)); pv.setVector( si4.getNumCols(),indices, si4.getColLower()); assert(basePv.isEquivalent(pv)); // Test colupper basePv.setVector(base.getNumCols(),indices,base.getColUpper()); pv.setVector( si1.getNumCols(),indices, si1.getColUpper()); assert(basePv.isEquivalent(pv)); pv.setVector( si2.getNumCols(),indices, si2.getColUpper()); assert(basePv.isEquivalent(pv)); pv.setVector( si3.getNumCols(),indices, si3.getColUpper()); assert(basePv.isEquivalent(pv)); pv.setVector( si4.getNumCols(),indices, si4.getColUpper()); assert(basePv.isEquivalent(pv)); // Test getObjCoefficients basePv.setVector(base.getNumCols(),indices,base.getObjCoefficients()); pv.setVector( si1.getNumCols(),indices, si1.getObjCoefficients()); assert(basePv.isEquivalent(pv)); pv.setVector( si2.getNumCols(),indices, si2.getObjCoefficients()); assert(basePv.isEquivalent(pv)); pv.setVector( si3.getNumCols(),indices, si3.getObjCoefficients()); assert(basePv.isEquivalent(pv)); pv.setVector( si4.getNumCols(),indices, si4.getObjCoefficients()); assert(basePv.isEquivalent(pv)); // Test rowlower basePv.setVector(base.getNumRows(),indices,base.getRowLower()); pv.setVector( si1.getNumRows(),indices, si1.getRowLower()); assert( eq(base.getRowLower()[3],si1.getRowLower()[3]) ); assert(basePv.isEquivalent(pv)); pv.setVector( si2.getNumRows(),indices, si2.getRowLower()); assert(basePv.isEquivalent(pv)); pv.setVector( si3.getNumRows(),indices, si3.getRowLower()); assert(basePv.isEquivalent(pv)); pv.setVector( si4.getNumRows(),indices, si4.getRowLower()); assert(basePv.isEquivalent(pv)); // Test rowupper basePv.setVector(base.getNumRows(),indices,base.getRowUpper()); pv.setVector( si1.getNumRows(),indices, si1.getRowUpper()); assert(basePv.isEquivalent(pv)); pv.setVector( si2.getNumRows(),indices, si2.getRowUpper()); assert(basePv.isEquivalent(pv)); pv.setVector( si3.getNumRows(),indices, si3.getRowUpper()); assert(basePv.isEquivalent(pv)); pv.setVector( si4.getNumRows(),indices, si4.getRowUpper()); assert(basePv.isEquivalent(pv)); // Test Constraint Matrix assert( base.getMatrixByCol()->isEquivalent(*si1.getMatrixByCol()) ); assert( base.getMatrixByRow()->isEquivalent(*si1.getMatrixByRow()) ); assert( base.getMatrixByCol()->isEquivalent(*si2.getMatrixByCol()) ); assert( base.getMatrixByRow()->isEquivalent(*si2.getMatrixByRow()) ); assert( base.getMatrixByCol()->isEquivalent(*si3.getMatrixByCol()) ); assert( base.getMatrixByRow()->isEquivalent(*si3.getMatrixByRow()) ); assert( base.getMatrixByCol()->isEquivalent(*si4.getMatrixByCol()) ); assert( base.getMatrixByRow()->isEquivalent(*si4.getMatrixByRow()) ); // Test Objective Value assert( eq(base.getObjValue(),si1.getObjValue()) ); assert( eq(base.getObjValue(),si2.getObjValue()) ); assert( eq(base.getObjValue(),si3.getObjValue()) ); assert( eq(base.getObjValue(),si4.getObjValue()) ); } //-------------- assert(OsiXprSolverInterface::getNumInstances()==1); } assert(OsiXprSolverInterface::getNumInstances()==0); // Do common solverInterface testing by calling the // base class testing method. { OsiXprSolverInterface m; OsiSolverInterfaceCommonUnitTest(&m, mpsDir,netlibDir); } }
int doBaCParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast<CbcGenParam *>(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; CbcModel *model = ctlBlk->model_ ; assert (model != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } ctlBlk->setBaBStatus(CbcGenCtlBlk::BACAbandon, CbcGenCtlBlk::BACmInvalid, CbcGenCtlBlk::BACwNotStarted, false, 0) ; /* We ain't gonna do squat without a good model. */ if (!ctlBlk->goodModel_) { std::cout << "** Current model not valid!" << std::endl ; return (retval) ; } /* Start the clock ticking. */ double time1 = CoinCpuTime() ; double time2 ; /* Create a clone of the model which we can modify with impunity. Extract the underlying solver for convenient access. */ CbcModel babModel(*model) ; OsiSolverInterface *babSolver = babModel.solver() ; assert (babSolver != 0) ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: initial babSolver is " << std::hex << babSolver << std::dec << ", log level " << babSolver->messageHandler()->logLevel() << "." << std::endl ; # endif /* Solve the root relaxation. Bail unless it solves to optimality. */ if (!solveRelaxation(&babModel)) { ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBareRoot) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 std::cout << "doBaCParam: initial relaxation z = " << babSolver->getObjValue() << "." << std::endl ; # endif /* Are we up for fixing variables based on reduced cost alone? */ if (ctlBlk->djFix_.action_ == true) { reducedCostHack(babSolver, ctlBlk->djFix_.threshold_) ; } /* Time to consider preprocessing. We'll do a bit of setup before getting to the meat of the issue. preIppSolver will hold a clone of the unpreprocessed constraint system. We'll need it when we postprocess. ippSolver holds the preprocessed constraint system. Again, we clone it and give the clone to babModel for B&C. Presumably we need an unmodified copy of the preprocessed system to do postprocessing, but the copy itself is hidden inside the preprocess object. */ OsiSolverInterface *preIppSolver = 0 ; CglPreProcess ippObj ; bool didIPP = false ; int numberChanged = 0 ; int numberOriginalColumns = babSolver->getNumCols() ; CbcGenCtlBlk::IPPControl ippAction = ctlBlk->getIPPAction() ; if (!(ippAction == CbcGenCtlBlk::IPPOff || ippAction == CbcGenCtlBlk::IPPStrategy)) { double timeLeft = babModel.getMaximumSeconds() ; preIppSolver = babSolver->clone() ; OsiSolverInterface *ippSolver ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: clone made prior to IPP is " << std::hex << preIppSolver << std::dec << ", log level " << preIppSolver->messageHandler()->logLevel() << "." << std::endl ; # endif preIppSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ; ippObj.messageHandler()->setLogLevel(babModel.logLevel()) ; CglProbing probingGen ; probingGen.setUsingObjective(true) ; probingGen.setMaxPass(3) ; probingGen.setMaxProbeRoot(preIppSolver->getNumCols()) ; probingGen.setMaxElements(100) ; probingGen.setMaxLookRoot(50) ; probingGen.setRowCuts(3) ; ippObj.addCutGenerator(&probingGen) ; /* For preProcessNonDefault, the 2nd parameter controls the conversion of clique and SOS constraints. 0 does nothing, -1 converts <= to ==, and 2 and 3 form SOS sets under strict and not-so-strict conditions, respectively. */ int convert = 0 ; if (ippAction == CbcGenCtlBlk::IPPEqual) { convert = -1 ; } else if (ippAction == CbcGenCtlBlk::IPPEqualAll) { convert = -2 ; } else if (ippAction == CbcGenCtlBlk::IPPSOS) { convert = 2 ; } else if (ippAction == CbcGenCtlBlk::IPPTrySOS) { convert = 3 ; } ippSolver = ippObj.preProcessNonDefault(*preIppSolver, convert, 10) ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver returned from IPP is " << std::hex << ippSolver << std::dec ; if (ippSolver) { std::cout << ", log level " << ippSolver->messageHandler()->logLevel() ; } std::cout << "." << std::endl ; # endif /* ippSolver == 0 is success of a sort --- integer preprocess has found the problem to be infeasible or unbounded. Need to think about how to indicate status. */ if (!ippSolver) { std::cout << "Integer preprocess says infeasible or unbounded" << std::endl ; delete preIppSolver ; ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPP) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 else { std::cout << "After integer preprocessing, model has " << ippSolver->getNumRows() << " rows, " << ippSolver->getNumCols() << " columns, and " << ippSolver->getNumElements() << " elements." << std::endl ; } # endif preIppSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; ippSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (ippAction == CbcGenCtlBlk::IPPSave) { ippSolver->writeMps("presolved", "mps", 1.0) ; std::cout << "Integer preprocessed model written to `presolved.mps' " << "as minimisation problem." << std::endl ; } OsiSolverInterface *osiTmp = ippSolver->clone() ; babModel.assignSolver(osiTmp) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: clone of IPP solver passed to babModel is " << std::hex << babSolver << std::dec << ", log level " << babSolver->messageHandler()->logLevel() << "." << std::endl ; # endif if (!solveRelaxation(&babModel)) { delete preIppSolver ; ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPPRelax) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 std::cout << "doBaCParam: presolved relaxation z = " << babSolver->getObjValue() << "." << std::endl ; # endif babModel.setMaximumSeconds(timeLeft - (CoinCpuTime() - time1)) ; didIPP = true ; } /* At this point, babModel and babSolver hold the constraint system we'll use for B&C (either the original system or the preprocessed system) and we have a solution to the lp relaxation. If we're using the COSTSTRATEGY option, set up priorities here and pass them to the babModel. */ if (ctlBlk->priorityAction_ != CbcGenCtlBlk::BPOff) { setupPriorities(&babModel, ctlBlk->priorityAction_) ; } /* Install heuristics and cutting planes. */ installHeuristics(ctlBlk, &babModel) ; installCutGenerators(ctlBlk, &babModel) ; /* Set up status print frequency for babModel. */ if (babModel.getNumCols() > 2000 || babModel.getNumRows() > 1500 || babModel.messageHandler()->logLevel() > 1) babModel.setPrintFrequency(100) ; /* If we've read in a known good solution for debugging, activate the row cut debugger. */ if (ctlBlk->debugSol_.values_) { if (ctlBlk->debugSol_.numCols_ == babModel.getNumCols()) { babSolver->activateRowCutDebugger(ctlBlk->debugSol_.values_) ; } else { std::cout << "doBaCParam: debug file has incorrect number of columns." << std::endl ; } } /* Set ratio-based integrality gap, if specified by user. */ if (ctlBlk->setByUser_[CbcCbcParam::GAPRATIO] == true) { double obj = babSolver->getObjValue() ; double gapRatio = babModel.getDblParam(CbcModel::CbcAllowableFractionGap) ; double gap = gapRatio * (1.0e-5 + fabs(obj)) ; babModel.setAllowableGap(gap) ; std::cout << "doBaCParam: Continuous objective = " << obj << ", so allowable gap set to " << gap << std::endl ; } /* A bit of mystery code. As best I can figure, setSpecialOptions(2) suppresses the removal of warm start information when checkSolution runs an lp to check a solution. John's comment, ``probably faster to use a basis to get integer solutions'' makes some sense in this context. Didn't try to track down moreMipOptions just yet. */ babModel.setSpecialOptions(babModel.specialOptions() | 2) ; /* { int ndx = whichParam(MOREMIPOPTIONS,numberParameters,parameters) ; int moreMipOptions = parameters[ndx].intValue() ; if (moreMipOptions >= 0) { printf("more mip options %d\n",moreMipOptions); babModel.setSearchStrategy(moreMipOptions); } } */ /* Begin the final run-up to branch-and-cut. Make sure that objects are set up in the solver. It's possible that whoever loaded the model into the solver also set up objects. But it's also entirely likely that none exist to this point (and interesting to note that IPP doesn't need to know anything about objects). */ setupObjects(babSolver, didIPP, &ippObj) ; /* Set the branching method. We can't do this until we establish objects, because the constructor will set up arrays based on the number of objects, and there's no provision to set this information after creation. Arguably not good --- it'd be nice to set this in the prototype model that's cloned for this routine. In CoinSolve, shadowPriceMode is handled with the TESTOSI option. */ OsiChooseStrong strong(babSolver) ; strong.setNumberBeforeTrusted(babModel.numberBeforeTrust()) ; strong.setNumberStrong(babModel.numberStrong()) ; strong.setShadowPriceMode(ctlBlk->chooseStrong_.shadowPriceMode_) ; CbcBranchDefaultDecision decision ; decision.setChooseMethod(strong) ; babModel.setBranchingMethod(decision) ; /* Here I've deleted a huge block of code that deals with external priorities, branch direction, pseudocosts, and solution. (PRIORITYIN) Also a block of code that generates C++ code. */ /* Set up strategy for branch-and-cut. Note that the integer code supplied to setupPreProcessing is *not* compatible with the IPPAction enum. But at least it's documented. See desiredPreProcess_ in CbcStrategyDefault. `1' is accidentally equivalent to IPPOn. */ if (ippAction == CbcGenCtlBlk::IPPStrategy) { CbcStrategyDefault strategy(true, 5, 5) ; strategy.setupPreProcessing(1) ; babModel.setStrategy(strategy) ; } /* Yes! At long last, we're ready for the big call. Do branch and cut. In general, the solver used to return the solution will not be the solver we passed in, so reset babSolver here. */ int statistics = (ctlBlk->printOpt_ > 0) ? ctlBlk->printOpt_ : 0 ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver at call to branchAndBound is " << std::hex << babModel.solver() << std::dec << ", log level " << babModel.solver()->messageHandler()->logLevel() << "." << std::endl ; # endif babModel.branchAndBound(statistics) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver at return from branchAndBound is " << std::hex << babModel.solver() << std::dec << ", log level " << babModel.solver()->messageHandler()->logLevel() << "." << std::endl ; # endif /* Write out solution to preprocessed model. */ if (ctlBlk->debugCreate_ == "createAfterPre" && babModel.bestSolution()) { CbcGenParamUtils::saveSolution(babSolver, "debug.file") ; } /* Print some information about branch-and-cut. */ # if COIN_CBC_VERBOSITY > 0 std::cout << "Cuts at root node changed objective from " << babModel.getContinuousObjective() << " to " << babModel.rootObjectiveAfterCuts() << std::endl ; for (int iGen = 0 ; iGen < babModel.numberCutGenerators() ; iGen++) { CbcCutGenerator *generator = babModel.cutGenerator(iGen) ; std::cout << generator->cutGeneratorName() << " was tried " << generator->numberTimesEntered() << " times and created " << generator->numberCutsInTotal() << " cuts of which " << generator->numberCutsActive() << " were active after adding rounds of cuts" ; if (generator->timing()) { std::cout << " ( " << generator->timeInCutGenerator() << " seconds)" ; } std::cout << std::endl ; } # endif time2 = CoinCpuTime(); ctlBlk->totalTime_ += time2 - time1; /* If we performed integer preprocessing, time to back it out. */ if (ippAction != CbcGenCtlBlk::IPPOff) { # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver passed to IPP postprocess is " << std::hex << babSolver << std::dec << "." << std::endl ; # endif ippObj.postProcess(*babSolver); babModel.assignSolver(preIppSolver) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver in babModel after IPP postprocess is " << std::hex << babSolver << std::dec << "." << std::endl ; # endif } /* Write out postprocessed solution to debug file, if requested. */ if (ctlBlk->debugCreate_ == "create" && babModel.bestSolution()) { CbcGenParamUtils::saveSolution(babSolver, "debug.file") ; } /* If we have a good solution, detach the solver with the answer. Fill in the rest of the status information for the benefit of the wider world. */ bool keepAnswerSolver = false ; OsiSolverInterface *answerSolver = 0 ; if (babModel.bestSolution()) { babModel.setModelOwnsSolver(false) ; keepAnswerSolver = true ; answerSolver = babSolver ; } ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBAC, keepAnswerSolver, answerSolver) ; /* And one last bit of information & statistics. */ ctlBlk->printBaBStatus() ; std::cout << " " ; if (keepAnswerSolver) { std::cout << "objective " << babModel.getObjValue() << "; " ; } std::cout << babModel.getNodeCount() << " nodes and " << babModel.getIterationCount() << " iterations - took " << time2 - time1 << " seconds" << std::endl ; return (0) ; }