int main(void) { // Create a problem pointer. We use the base class here. OsiSolverInterface *si; // When we instantiate the object, we need a specific derived class. si = new OsiClpSolverInterface; // Read in an mps file. This one's from the MIPLIB library. si->readMps("../../Data/Sample/p0033"); // Solve the (relaxation of the) problem si->initialSolve(); // Check the solution if ( si->isProvenOptimal() ) { std::cout << "Found optimal solution!" << std::endl; std::cout << "Objective value is " << si->getObjValue() << std::endl; int n = si->getNumCols(); const double *solution; solution = si->getColSolution(); // We could then print the solution or examine it. } else { std::cout << "Didn't find optimal solution." << std::endl; // Could then check other status functions. } return 0; }
//-------------------------------------------------------------------------- // test cut debugger methods. void OsiRowCutDebuggerUnitTest(const OsiSolverInterface * baseSiP, const std::string & mpsDir) { CoinRelFltEq eq; // Test default constructor { OsiRowCutDebugger r; OSIUNITTEST_ASSERT_ERROR(r.integerVariable_ == NULL, {}, "osirowcutdebugger", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.knownSolution_ == NULL, {}, "osirowcutdebugger", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.numberColumns_ == 0, {}, "osirowcutdebugger", "default constructor"); } { // Get non trivial instance OsiSolverInterface * imP = baseSiP->clone(); std::string fn = mpsDir+"exmip1"; imP->readMps(fn.c_str(),"mps"); OSIUNITTEST_ASSERT_ERROR(imP->getNumRows() == 5, {}, "osirowcutdebugger", "read exmip1"); /* Activate the debugger. The garbled name here is deliberate; the debugger should isolate the portion of the string between '/' and '.' (in normal use, this would be the base file name, stripped of the prefix and extension). */ imP->activateRowCutDebugger("ab cd /x/ /exmip1.asc"); int i; // return debugger const OsiRowCutDebugger * debugger = imP->getRowCutDebugger(); OSIUNITTEST_ASSERT_ERROR(debugger != NULL, {}, "osirowcutdebugger", "return debugger"); OSIUNITTEST_ASSERT_ERROR(debugger->numberColumns_ == 8, {}, "osirowcutdebugger", "return debugger"); const bool type[]={0,0,1,1,0,0,0,0}; const double values[]= {2.5, 0, 1, 1, 0.5, 3, 0, 0.26315789473684253}; CoinPackedVector objCoefs(8,imP->getObjCoefficients()); bool type_ok = true; #if 0 for (i=0;i<8;i++) type_ok &= type[i] == debugger->integerVariable_[i]; OSIUNITTEST_ASSERT_ERROR(type_ok, {}, "osirowcutdebugger", "???"); #endif double objValue = objCoefs.dotProduct(values); double debuggerObjValue = objCoefs.dotProduct(debugger->knownSolution_); OSIUNITTEST_ASSERT_ERROR(eq(objValue, debuggerObjValue), {}, "osirowcutdebugger", "objective value"); OsiRowCutDebugger rhs; { OsiRowCutDebugger rC1(*debugger); OSIUNITTEST_ASSERT_ERROR(rC1.numberColumns_ == 8, {}, "osirowcutdebugger", "copy constructor"); type_ok = true; for (i=0;i<8;i++) type_ok &= type[i] == rC1.integerVariable_[i]; OSIUNITTEST_ASSERT_ERROR(type_ok, {}, "osirowcutdebugger", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(eq(objValue,objCoefs.dotProduct(rC1.knownSolution_)), {}, "osirowcutdebugger", "copy constructor"); rhs = rC1; OSIUNITTEST_ASSERT_ERROR(rhs.numberColumns_ == 8, {}, "osirowcutdebugger", "assignment operator"); type_ok = true; for (i=0;i<8;i++) type_ok &= type[i] == rhs.integerVariable_[i]; OSIUNITTEST_ASSERT_ERROR(type_ok, {}, "osirowcutdebugger", "assignment operator"); OSIUNITTEST_ASSERT_ERROR(eq(objValue,objCoefs.dotProduct(rhs.knownSolution_)), {}, "osirowcutdebugger", "assignment operator"); } // Test that rhs has correct values even though lhs has gone out of scope OSIUNITTEST_ASSERT_ERROR(rhs.numberColumns_ == 8, {}, "osirowcutdebugger", "assignment operator"); type_ok = true; for (i=0;i<8;i++) type_ok &= type[i] == rhs.integerVariable_[i]; OSIUNITTEST_ASSERT_ERROR(type_ok, {}, "osirowcutdebugger", "assignment operator"); OSIUNITTEST_ASSERT_ERROR(eq(objValue,objCoefs.dotProduct(rhs.knownSolution_)), {}, "osirowcutdebugger", "assignment operator"); OsiRowCut cut[2]; const int ne = 3; int inx[ne] = { 0, 2, 3 }; double el[ne] = { 1., 1., 1. }; cut[0].setRow(ne,inx,el); cut[0].setUb(5.); el[1]=5; cut[1].setRow(ne,inx,el); cut[1].setUb(5); OsiCuts cs; cs.insert(cut[0]); cs.insert(cut[1]); OSIUNITTEST_ASSERT_ERROR(!debugger->invalidCut(cut[0]), {}, "osirowcutdebugger", "recognize (in)valid cut"); OSIUNITTEST_ASSERT_ERROR( debugger->invalidCut(cut[1]), {}, "osirowcutdebugger", "recognize (in)valid cut"); OSIUNITTEST_ASSERT_ERROR(debugger->validateCuts(cs,0,2) == 1, {}, "osirowcutdebugger", "recognize (in)valid cut"); OSIUNITTEST_ASSERT_ERROR(debugger->validateCuts(cs,0,1) == 0, {}, "osirowcutdebugger", "recognize (in)valid cut"); delete imP; } }
//-------------------------------------------------------------------------- // test the simple rounding cut generators methods. void CglSimpleRoundingUnitTest( const OsiSolverInterface * baseSiP, const std::string mpsDir ) { // Test default constructor { CglSimpleRounding cg; } // Test copy & assignment { CglSimpleRounding rhs; { CglSimpleRounding cg; CglSimpleRounding cgC(cg); rhs=cg; } } // Test gcd and gcdn { CglSimpleRounding cg; int v = cg.gcd(122,356); assert(v==2); v=cg.gcd(356,122); assert(v==2); v=cg.gcd(54,67); assert(v==1); v=cg.gcd(67,54); assert(v==1); v=cg.gcd(485,485); assert(v==485); v=cg.gcd(17*13,17*23); assert( v==17); v=cg.gcd(17*13*5,17*23); assert( v==17); v=cg.gcd(17*13*23,17*23); assert(v==17*23); int a[4] = {12, 20, 32, 400}; v= cg.gcdv(4,a); assert(v== 4); int b[4] = {782, 4692, 51, 2754}; v= cg.gcdv(4,b); assert(v== 17); int c[4] = {50, 40, 30, 10}; v= cg.gcdv(4,c); assert(v== 10); } // Test generate cuts method on exmip1.5.mps { CglSimpleRounding cg; OsiSolverInterface * siP = baseSiP->clone(); std::string fn = mpsDir+"exmip1.5.mps"; siP->readMps(fn.c_str(),""); OsiCuts cuts; cg.generateCuts(*siP,cuts); // there should be 3 cuts int nRowCuts = cuts.sizeRowCuts(); assert(nRowCuts==3); // get the last "sr"=simple rounding cut that was derived OsiRowCut srRowCut2 = cuts.rowCut(2); CoinPackedVector srRowCutPV2 = srRowCut2.row(); // this is what the last cut should look like: i.e. the "solution" const int solSize = 2; int solCols[solSize]={2,3}; double solCoefs[solSize]={5.0, 4.0}; OsiRowCut solRowCut; solRowCut.setRow(solSize,solCols,solCoefs); solRowCut.setLb(-COIN_DBL_MAX); solRowCut.setUb(2.0); // Test for equality between the derived cut and the solution cut // Note: testing two OsiRowCuts are equal invokes testing two // CoinPackedVectors are equal which invokes testing two doubles // are equal. Usually not a good idea to test that two doubles are equal, // but in this cut the "doubles" represent integer values. Also allow that // different solvers have different orderings in packed vectors, which may // not match the ordering defined for solRowCut. assert(srRowCut2.OsiCut::operator==(solRowCut)) ; assert(srRowCut2.row().isEquivalent(solRowCut.row())) ; assert(srRowCut2.lb() == solRowCut.lb()) ; assert(srRowCut2.ub() == solRowCut.ub()) ; delete siP; } // Test generate cuts method on p0033 { CglSimpleRounding cg; OsiSolverInterface * siP = baseSiP->clone(); std::string fn = mpsDir+"p0033"; siP->readMps(fn.c_str(),"mps"); OsiCuts cuts; cg.generateCuts(*siP,cuts); // p0033 is the optimal solution to p0033 int objIndices[14] = { 0, 6, 7, 9, 13, 17, 18, 22, 24, 25, 26, 27, 28, 29 }; CoinPackedVector p0033(14,objIndices,1.0); // test that none of the generated cuts // chops off the optimal solution int nRowCuts = cuts.sizeRowCuts(); OsiRowCut rcut; CoinPackedVector rpv; int i; for (i=0; i<nRowCuts; i++){ rcut = cuts.rowCut(i); rpv = rcut.row(); double p0033Sum = (rpv*p0033).sum(); double rcutub = rcut.ub(); assert (p0033Sum <= rcutub); } // test that the cuts improve the // lp objective function value siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("Final LP min=%f\n\n",lpRelaxAfter); #endif assert( lpRelaxBefore < lpRelaxAfter ); delete siP; } }
//-------------------------------------------------------------------------- // test EKKsolution methods. void CglOddHoleUnitTest( const OsiSolverInterface * baseSiP, const std::string mpsDir ) { CoinRelFltEq eq(0.000001); // Test default constructor { CglOddHole aGenerator; } // Test copy & assignment { CglOddHole rhs; { CglOddHole bGenerator; CglOddHole cGenerator(bGenerator); rhs=bGenerator; } } // test on simple case { const int nRows=3; const int nCols=3; const int nEls=6; const double elem[]={1.0,1.0,1.0,1.0,1.0,1.0}; const int row[]={0,1,0,2,1,2}; const CoinBigIndex start[]={0,2,4}; const int len[]={2,2,2}; CoinPackedMatrix matrix(true,nRows,nCols,nEls,elem,row,start,len); const double sol[]={0.5,0.5,0.5}; const double dj[]={0,0,0}; const int which[]={1,1,1}; const int fixed[]={0,0,0}; OsiCuts cs; CglOddHole test1; CglTreeInfo info; info.randomNumberGenerator=NULL; test1.generateCuts(NULL,matrix,sol,dj,cs,which,fixed,info,true); CoinPackedVector check; int index[] = {0,1,2}; double el[] = {1,1,1}; check.setVector(3,index,el); //assert (cs.sizeRowCuts()==2); assert (cs.sizeRowCuts()==1); // sort Elements in increasing order CoinPackedVector rpv=cs.rowCut(0).row(); rpv.sortIncrIndex(); assert (check==rpv); } // Testcase /u/rlh/osl2/mps/scOneInt.mps // Model has 3 continous, 2 binary, and 1 general // integer variable. { OsiSolverInterface * siP = baseSiP->clone(); std::string fn = mpsDir+"scOneInt"; siP->readMps(fn.c_str(),"mps"); #if 0 CglOddHole cg; int nCols=siP->getNumCols(); // Test the siP methods for detecting // variable type int numCont=0, numBinary=0, numIntNonBinary=0, numInt=0; for (int thisCol=0; thisCol<nCols; thisCol++) { if ( siP->isContinuous(thisCol) ) numCont++; if ( siP->isBinary(thisCol) ) numBinary++; if ( siP->isIntegerNonBinary(thisCol) ) numIntNonBinary++; if ( siP->isInteger(thisCol) ) numInt++; } assert(numCont==3); assert(numBinary==2); assert(numIntNonBinary==1); assert(numInt==3); // Test initializeCutGenerator siP->initialSolve(); assert(xstar !=NULL); for (i=0; i<nCols; i++){ assert(complement[i]==0); } int nRows=siP->getNumRows(); for (i=0; i<nRows; i++){ int vectorsize = siP->getMatrixByRow()->getVectorSize(i); assert(vectorsize==2); } kccg.cleanUpCutGenerator(complement,xstar); #endif delete siP; } }
void CglTwomirUnitTest(const OsiSolverInterface *baseSiP, const std::string mpsDir) { // Test default constructor { CglTwomir aGenerator; } // Test copy & assignment { CglTwomir rhs; { CglTwomir bGenerator; CglTwomir cGenerator(bGenerator); rhs=bGenerator; } } // Test get/set methods { CglTwomir getset; int gtmin = getset.getTmin() + 1; int gtmax = getset.getTmax() + 1; getset.setMirScale(gtmin, gtmax); double gtmin2 = getset.getTmin(); double gtmax2 = getset.getTmax(); assert(gtmin == gtmin2); assert(gtmax == gtmax2); int gamax = 2 * getset.getAmax() + 1; getset.setAMax(gamax); int gamax2 = getset.getAmax(); assert(gamax == gamax2); } // Test generateCuts { CglTwomir gct; OsiSolverInterface *siP = baseSiP->clone(); std::string fn = mpsDir+"capPlan1"; std::string fn2 = mpsDir+"capPlan1.mps"; FILE *in_f = fopen(fn2.c_str(), "r"); if(in_f == NULL) { std::cout<<"Can not open file "<<fn2<<std::endl<<"Skip test of CglTwomir::generateCuts()"<<std::endl; } else { fclose(in_f); siP->readMps(fn.c_str(),"mps"); siP->initialSolve(); double lpRelax = siP->getObjValue(); OsiCuts cs; gct.generateCuts(*siP, cs); int nRowCuts = cs.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" Twomir cuts"<<std::endl; assert(cs.sizeRowCuts() > 0); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cs); siP->resolve(); double lpRelaxAfter= siP->getObjValue(); std::cout<<"Initial LP value: "<<lpRelax<<std::endl; std::cout<<"LP value with cuts: "<<lpRelaxAfter<<std::endl; assert( lpRelax < lpRelaxAfter ); assert(lpRelaxAfter < 964); } delete siP; } }
void CglCliqueUnitTest(const OsiSolverInterface *baseSiP, const std::string mpsDir) { // Test default constructor { CglClique aGenerator; } // Test copy & assignment { CglClique rhs; { CglClique bGenerator; CglClique cGenerator(bGenerator); //rhs=bGenerator; } } // Test get/set methods { CglClique getset; // None to test } // Test generateCuts { CglClique gct; OsiSolverInterface *siP = baseSiP->clone(); std::string fn = mpsDir+"l152lav"; std::string fn2 = mpsDir+"l152lav.mps"; FILE *in_f = fopen(fn2.c_str(), "r"); if(in_f == NULL) { std::cout<<"Can not open file "<<fn2<<std::endl<<"Skip test of CglClique::generateCuts()"<<std::endl; } else { fclose(in_f); siP->readMps(fn.c_str(),"mps"); siP->initialSolve(); double lpRelax = siP->getObjValue(); OsiCuts cs; gct.generateCuts(*siP, cs); int nRowCuts = cs.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" Clique cuts"<<std::endl; assert(cs.sizeRowCuts() > 0); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cs); siP->resolve(); double lpRelaxAfter= siP->getObjValue(); std::cout<<"Initial LP value: "<<lpRelax<<std::endl; std::cout<<"LP value with cuts: "<<lpRelaxAfter<<std::endl; assert( lpRelax < lpRelaxAfter ); assert(lpRelaxAfter < 4722.1); } delete siP; } }
void CglResidualCapacityUnitTest(const OsiSolverInterface *baseSiP, const std::string mpsDir) { // Test default constructor { CglResidualCapacity aGenerator; } // Test copy & assignment { CglResidualCapacity rhs; { CglResidualCapacity bGenerator; CglResidualCapacity cGenerator(bGenerator); rhs=bGenerator; } } // Test get/set methods { CglResidualCapacity getset; double geps = 10 * getset.getEpsilon(); getset.setEpsilon(geps); double geps2 = getset.getEpsilon(); assert(geps == geps2); double gtol = 10 * getset.getTolerance(); getset.setTolerance(gtol); double gtol2 = getset.getTolerance(); assert(gtol == gtol2); int gpre = getset.getDoPreproc(); gpre = (gpre + 1) % 3 - 1; getset.setDoPreproc(gpre); int gpre2 = getset.getDoPreproc(); assert(gpre == gpre2); } // Test generateCuts { CglResidualCapacity gct; OsiSolverInterface *siP = baseSiP->clone(); std::string fn = mpsDir+"capPlan1"; std::string fn2 = mpsDir+"capPlan1.mps"; FILE *in_f = fopen(fn2.c_str(), "r"); if(in_f == NULL) { std::cout<<"Can not open file "<<fn2<<std::endl<<"Skip test of CglResidualCapacity::generateCuts()"<<std::endl; } else { fclose(in_f); siP->readMps(fn.c_str(),"mps"); siP->initialSolve(); double lpRelax = siP->getObjValue(); OsiCuts cs; gct.setDoPreproc(1); // Needed for DyLP gct.generateCuts(*siP, cs); int nRowCuts = cs.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" Residual Capacity cuts"<<std::endl; assert(cs.sizeRowCuts() > 0); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cs); siP->resolve(); double lpRelaxAfter= siP->getObjValue(); std::cout<<"Initial LP value: "<<lpRelax<<std::endl; std::cout<<"LP value with cuts: "<<lpRelaxAfter<<std::endl; assert( lpRelax < lpRelaxAfter ); assert(lpRelaxAfter < 964); } delete siP; } }
void CglMixedIntegerRoundingUnitTest(const OsiSolverInterface *baseSiP, const std::string mpsDir) { // Test default constructor { CglMixedIntegerRounding aGenerator; } // Test copy & assignment { CglMixedIntegerRounding rhs; { CglMixedIntegerRounding bGenerator; CglMixedIntegerRounding cGenerator(bGenerator); rhs=bGenerator; } } // Test get/set methods { CglMixedIntegerRounding getset; int gagg = 10 * getset.getMAXAGGR_(); getset.setMAXAGGR_(gagg); int gagg2 = getset.getMAXAGGR_(); assert(gagg == gagg2); bool gmult = !getset.getMULTIPLY_(); getset.setMULTIPLY_(gmult); bool gmult2 = getset.getMULTIPLY_(); assert(gmult == gmult2); int gcrit = getset.getCRITERION_(); gcrit = (gcrit) % 3 + 1; getset.setCRITERION_(gcrit); int gcrit2 = getset.getCRITERION_(); assert(gcrit == gcrit2); int gpre = getset.getDoPreproc(); gpre = (gpre + 1) % 3 - 1; getset.setDoPreproc(gpre); int gpre2 = getset.getDoPreproc(); assert(gpre == gpre2); } // Test generateCuts { CglMixedIntegerRounding gct; OsiSolverInterface *siP = baseSiP->clone(); std::string fn = mpsDir+"capPlan1"; std::string fn2 = mpsDir+"capPlan1.mps"; FILE *in_f = fopen(fn2.c_str(), "r"); if(in_f == NULL) { std::cout<<"Can not open file "<<fn2<<std::endl<<"Skip test of CglMixedIntegerRounding::generateCuts()"<<std::endl; } else { fclose(in_f); siP->readMps(fn.c_str(),"mps"); siP->initialSolve(); double lpRelax = siP->getObjValue(); OsiCuts cs; gct.generateCuts(*siP, cs); int nRowCuts = cs.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" MIR cuts"<<std::endl; assert(cs.sizeRowCuts() > 0); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cs); siP->resolve(); double lpRelaxAfter= siP->getObjValue(); std::cout<<"Initial LP value: "<<lpRelax<<std::endl; std::cout<<"LP value with cuts: "<<lpRelaxAfter<<std::endl; assert( lpRelax < lpRelaxAfter ); assert(lpRelaxAfter < 964); } delete siP; } }
//-------------------------------------------------------------------------- // test EKKsolution methods. void CglProbingUnitTest( const OsiSolverInterface * baseSiP, const std::string mpsDir ) { # ifdef CGL_DEBUG int i ; // define just once # endif CoinRelFltEq eq(0.000001); // Test default constructor { CglProbing aGenerator; } // Test copy & assignment { CglProbing rhs; { CglProbing bGenerator; CglProbing cGenerator(bGenerator); rhs=bGenerator; } } { OsiCuts osicuts; CglProbing test1; OsiSolverInterface * siP = baseSiP->clone(); int nColCuts; int nRowCuts; std::string fn = mpsDir+"p0033"; siP->readMps(fn.c_str(),"mps"); siP->initialSolve(); // just unsatisfied variables test1.generateCuts(*siP,osicuts); nColCuts = osicuts.sizeColCuts(); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" probing cuts"<<std::endl; { std::cout<<"there are "<<nColCuts<<" probing column cuts"<<std::endl; #ifdef CGL_DEBUG const double * lo = siP->getColLower(); const double * up = siP->getColUpper(); for (i=0; i<nColCuts; i++){ OsiColCut ccut; CoinPackedVector cpv; ccut = osicuts.colCut(i); cpv = ccut.lbs(); int n = cpv.getNumElements(); int j; const int * indices = cpv.getIndices(); double* elements = cpv.getElements(); for (j=0;j<n;j++) { int icol=indices[j]; if (elements[j]>lo[icol]) std::cout<<"Can increase lb on "<<icol<<" from "<<lo[icol]<< " to "<<elements[j]<<std::endl; } cpv = ccut.ubs(); n = cpv.getNumElements(); indices = cpv.getIndices(); elements = cpv.getElements(); for (j=0;j<n;j++) { int icol=indices[j]; if (elements[j]<up[icol]) std::cout<<"Can decrease ub on "<<icol<<" from "<<up[icol]<< " to "<<elements[j]<<std::endl; } } #endif } #ifdef CGL_DEBUG for (i=0; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; const double * colsol = siP->getColSolution(); rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; double lb=rcut.lb(); double ub=rcut.ub(); for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } } #endif if (nRowCuts==1) { CoinPackedVector check; int index[] = {6,32}; double el[] = {1,1}; check.setVector(2,index,el); // sort Elements in increasing order CoinPackedVector rpv=osicuts.rowCut(0).row(); assert (rpv.getNumElements()==2); rpv.sortIncrIndex(); assert (check==rpv); assert (osicuts.rowCut(0).lb()==1.0); } // now all variables osicuts=OsiCuts(); test1.setMode(2); test1.setRowCuts(3); test1.generateCuts(*siP,osicuts); nColCuts = osicuts.sizeColCuts(); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" probing cuts"<<std::endl; { std::cout<<"there are "<<nColCuts<<" probing column cuts"<<std::endl; #ifdef CGL_DEBUG const double * lo = siP->getColLower(); const double * up = siP->getColUpper(); for (i=0; i<nColCuts; i++){ OsiColCut ccut; CoinPackedVector cpv; ccut = osicuts.colCut(i); cpv = ccut.lbs(); int n = cpv.getNumElements(); int j; const int * indices = cpv.getIndices(); double* elements = cpv.getElements(); for (j=0;j<n;j++) { int icol=indices[j]; if (elements[j]>lo[icol]) std::cout<<"Can increase lb on "<<icol<<" from "<<lo[icol]<< " to "<<elements[j]<<std::endl; } cpv = ccut.ubs(); n = cpv.getNumElements(); indices = cpv.getIndices(); elements = cpv.getElements(); for (j=0;j<n;j++) { int icol=indices[j]; if (elements[j]<up[icol]) std::cout<<"Can decrease ub on "<<icol<<" from "<<up[icol]<< " to "<<elements[j]<<std::endl; } } #endif } #ifdef CGL_DEBUG for (i=0; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; const double * colsol = siP->getColSolution(); rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; double lb=rcut.lb(); double ub=rcut.ub(); for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } } #endif assert (osicuts.sizeRowCuts()>=4); delete siP; } }
//-------------------------------------------------------------------------- // ** At present this does not use any solver void CglGomoryUnitTest( const OsiSolverInterface * baseSiP, const std::string mpsDir ) { CoinRelFltEq eq(0.000001); // Test default constructor { CglGomory aGenerator; assert (aGenerator.getLimit()==50); assert (aGenerator.getAway()==0.05); } // Test copy & assignment etc { CglGomory rhs; { CglGomory bGenerator; bGenerator.setLimit(99); bGenerator.setAway(0.2); CglGomory cGenerator(bGenerator); rhs=bGenerator; assert (rhs.getLimit()==99); assert (rhs.getAway()==0.2); } } // Test explicit form - all integer (pg 125 Wolsey) if (1) { OsiCuts osicuts; CglGomory test1; int i; int nOldCuts=0,nRowCuts; // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5]={0,4,7,8,9}; int length[5]={2,3,1,1,1}; int rows[11]={0,2,-1,-1,0,1,2,0,1,2}; double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,1,1}; CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length); // rim data (objective not used just yet) double rowLower[5]={14.0,3.0,3.0,1.0e10,1.0e10}; double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10}; double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0}; double colUpper[7]={100.0,100.0,100.0,100.0,100.0,100.0,100.0}; // integer char intVar[7]={2,2,2,2,2,2,2}; // basis 1 int rowBasis1[3]={-1,-1,-1}; int colBasis1[5]={1,1,-1,-1,1}; CoinWarmStartBasis warm; warm.setSize(5,3); for (i=0;i<3;i++) { if (rowBasis1[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<5;i++) { if (colBasis1[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 1 double colsol1[5]={20.0/7.0,3.0,0.0,0.0,23.0/7.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol1, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==2); // cuts always <= int testCut=0; // test first cut as stronger double rhs=-6.0; double testCut1[5]={0.0,0.0,-1.0,-2.0,0.0}; double * cut = testCut1; double * colsol = colsol1; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==2); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut // explicit slack matrix.setDimensions(-1,6); rpv.insert(5,1.0*7.0); // to get cut in book rowLower[3]=ub; rowUpper[3]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 2 int rowBasis2[4]={-1,-1,-1,-1}; int colBasis2[6]={1,1,1,1,-1,-1}; warm.setSize(6,4); for (i=0;i<4;i++) { if (rowBasis2[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<6;i++) { if (colBasis2[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 2 double colsol2[6]={2.0,0.5,1.0,2.5,0.0,0.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol2, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts-nOldCuts==2); // cuts always <= testCut=0; // test first cut as stronger rhs=-1.0; double testCut2[6]={0.0,0.0,0.0,0.0,-1.0,0.0}; cut = testCut2; colsol = colsol2; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==1); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut // explicit slack matrix.setDimensions(-1,7); rpv.insert(6,1.0); rowLower[4]=ub; rowUpper[4]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 3 int rowBasis3[5]={-1,-1,-1,-1,-1}; int colBasis3[7]={1,1,1,1,1,-1,-1}; warm.setSize(7,5); for (i=0;i<5;i++) { if (rowBasis3[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<7;i++) { if (colBasis3[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 3 double colsol3[7]={2.0,1.0,2.0,2.0,1.0,0.0,0.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol3, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==nOldCuts); } // Test explicit form - this time with x4 flipped if (1) { OsiCuts osicuts; CglGomory test1; int i; int nOldCuts=0,nRowCuts; // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5]={0,4,7,8,9}; int length[5]={2,3,1,1,1}; int rows[11]={0,2,-1,-1,0,1,2,0,1,2}; double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,-1,1}; CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length); // rim data (objective not used just yet) double rowLower[5]={14.0,-5.0,3.0,1.0e10,1.0e10}; double rowUpper[5]={14.0,-5.0,3.0,-1.0e10,-1.0e10}; double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0}; double colUpper[7]={100.0,100.0,100.0,8.0,100.0,100.0,100.0}; // integer char intVar[7]={2,2,2,2,2,2,2}; // basis 1 int rowBasis1[3]={-1,-1,-1}; int colBasis1[5]={1,1,-1,-1,1}; CoinWarmStartBasis warm; warm.setSize(5,3); for (i=0;i<3;i++) { if (rowBasis1[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<5;i++) { if (colBasis1[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 1 double colsol1[5]={20.0/7.0,3.0,0.0,8.0,23.0/7.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol1, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==2); // cuts always <= int testCut=0; // test first cut as stronger double rhs=10.0; double testCut1[5]={0.0,0.0,-1.0,2.0,0.0}; double * cut = testCut1; double * colsol = colsol1; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==2); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut // explicit slack matrix.setDimensions(-1,6); rpv.insert(5,1.0*7.0); // to get cut in book rowLower[3]=ub; rowUpper[3]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 2 int rowBasis2[4]={-1,-1,-1,-1}; int colBasis2[6]={1,1,1,1,-1,-1}; warm.setSize(6,4); for (i=0;i<4;i++) { if (rowBasis2[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<6;i++) { if (colBasis2[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 2 double colsol2[6]={2.0,0.5,1.0,5.5,0.0,0.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol2, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts-nOldCuts==2); // cuts always <= testCut=0; // test first cut as stronger rhs=-1.0; double testCut2[6]={0.0,0.0,0.0,0.0,-1.0,0.0}; cut = testCut2; colsol = colsol2; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==1); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut // explicit slack matrix.setDimensions(-1,7); rpv.insert(6,1.0); rowLower[4]=ub; rowUpper[4]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 3 int rowBasis3[5]={-1,-1,-1,-1,-1}; int colBasis3[7]={1,1,1,1,1,-1,-1}; warm.setSize(7,5); for (i=0;i<5;i++) { if (rowBasis3[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<7;i++) { if (colBasis3[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 3 double colsol3[7]={2.0,1.0,2.0,6.0,1.0,0.0,0.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol3, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==nOldCuts); } // Test with slacks if (1) { OsiCuts osicuts; CglGomory test1; int i; int nOldCuts=0,nRowCuts; // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5]={0,4}; int length[5]={2,3}; int rows[11]={0,2,-1,-1,0,1,2}; double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0}; CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length); // rim data (objective not used just yet) double rowLower[5]={-1.0e10,-1.0e10,-1.0e10,1.0e10,1.0e10}; double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10}; double colLower[2]={0.0,0.0}; double colUpper[2]={100.0,100.0}; // integer char intVar[2]={2,2}; // basis 1 int rowBasis1[3]={-1,-1,1}; int colBasis1[2]={1,1}; CoinWarmStartBasis warm; warm.setSize(2,3); for (i=0;i<3;i++) { if (rowBasis1[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis1[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 1 double colsol1[2]={20.0/7.0,3.0}; test1.generateCuts(NULL, osicuts, matrix, /* objective,*/ colsol1, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==1); // cuts always <= int testCut=0; // test first cut as stronger double rhs=2.0; double testCut1[2]={1.0,0.0}; double * cut = testCut1; double * colsol = colsol1; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==1); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut rowLower[3]=-1.0e100; rowUpper[3]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 2 int rowBasis2[4]={1,1,-1,-1}; int colBasis2[2]={1,1}; warm.setSize(2,4); for (i=0;i<4;i++) { if (rowBasis2[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis2[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 2 double colsol2[2]={2.0,0.5}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol2, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts-nOldCuts==1); // cuts always <= testCut=0; // test first cut as stronger rhs=1.0; double testCut2[2]={1.0,-1.0}; cut = testCut2; colsol = colsol2; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==2); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut rowLower[4]=-1.0e100; rowUpper[4]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 3 int rowBasis3[5]={1,1,1,-1,-1}; int colBasis3[2]={1,1}; warm.setSize(2,5); for (i=0;i<5;i++) { if (rowBasis3[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis3[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 3 double colsol3[2]={2.0,1.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol3, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==nOldCuts); } // swap some rows to G if (1) { OsiCuts osicuts; CglGomory test1; int i; int nOldCuts=0,nRowCuts; // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5]={0,4}; int length[5]={2,3}; int rows[11]={0,2,-1,-1,0,1,2}; double elements[11]={-7.0,-2.0,1.0e10,1.0e10,+2.0,1.0,+2.0}; CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length); // rim data (objective not used just yet) double rowUpper[5]={1.0e10,3.0,1.0e10,-1.0e10,-1.0e10}; double rowLower[5]={-14.0,-1.0e10,-3.0,1.0e10,1.0e10}; double colLower[2]={0.0,0.0}; double colUpper[2]={100.0,100.0}; // integer char intVar[2]={2,2}; // basis 1 int rowBasis1[3]={-1,-1,1}; int colBasis1[2]={1,1}; CoinWarmStartBasis warm; warm.setSize(2,3); for (i=0;i<3;i++) { if (rowBasis1[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis1[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 1 double colsol1[2]={20.0/7.0,3.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol1, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==1); // cuts always <= int testCut=0; // test first cut as stronger double rhs=2.0; double testCut1[2]={1.0,0.0}; double * cut = testCut1; double * colsol = colsol1; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==1); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut rowLower[3]=-1.0e100; rowUpper[3]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 2 int rowBasis2[4]={1,1,-1,-1}; int colBasis2[2]={1,1}; warm.setSize(2,4); for (i=0;i<4;i++) { if (rowBasis2[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis2[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 2 double colsol2[2]={2.0,0.5}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol2, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts-nOldCuts==1); // cuts always <= testCut=0; // test first cut as stronger rhs=1.0; double testCut2[2]={1.0,-1.0}; cut = testCut2; colsol = colsol2; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==2); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut rowLower[4]=-1.0e100; rowUpper[4]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 3 int rowBasis3[5]={1,1,1,-1,-1}; int colBasis3[2]={1,1}; warm.setSize(2,5); for (i=0;i<5;i++) { if (rowBasis3[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis3[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 3 double colsol3[2]={2.0,1.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol3, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==nOldCuts); } // NOW mixed integer gomory cuts // Test explicit form - (pg 130 Wolsey) // Some arrays left same size as previously although not used in full if (1) { OsiCuts osicuts; CglGomory test1; int i; int nOldCuts=0,nRowCuts; // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5]={0,4,7,8,9}; int length[5]={2,3,1,1,1}; int rows[11]={0,2,-1,-1,0,1,2,0,1,2}; double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,1,1}; CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length); // rim data (objective not used just yet) double rowLower[5]={14.0,3.0,3.0,1.0e10,1.0e10}; double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10}; double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0}; double colUpper[7]={100.0,100.0,100.0,100.0,100.0,100.0,100.0}; // integer char intVar[7]={2,0,0,0,0,0,0}; // basis 1 int rowBasis1[3]={-1,-1,-1}; int colBasis1[5]={1,1,-1,-1,1}; CoinWarmStartBasis warm; warm.setSize(5,3); for (i=0;i<3;i++) { if (rowBasis1[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<5;i++) { if (colBasis1[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 1 double colsol1[5]={20.0/7.0,3.0,0.0,0.0,23.0/7.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol1, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==1); // cuts always <= int testCut=0; // test first cut as stronger double rhs=-6.0/7.0; double testCut1[5]={0.0,0.0,-1.0/7.0,-2.0/7.0,0.0}; double * cut = testCut1; double * colsol = colsol1; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==2); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut // explicit slack matrix.setDimensions(-1,6); rpv.insert(5,1.0); // to get cut in book rowLower[3]=ub; rowUpper[3]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 2 int rowBasis2[4]={-1,-1,-1,-1}; int colBasis2[6]={1,1,1,1,-1,-1}; warm.setSize(6,4); for (i=0;i<4;i++) { if (rowBasis2[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<6;i++) { if (colBasis2[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 2 double colsol2[6]={2.0,0.5,1.0,2.5,0.0,0.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol2, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==nOldCuts); } // Test explicit form - this time with x4 flipped if (1) { OsiCuts osicuts; CglGomory test1; int i; int nOldCuts=0,nRowCuts; // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5]={0,4,7,8,9}; int length[5]={2,3,1,1,1}; int rows[11]={0,2,-1,-1,0,1,2,0,1,2}; double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,-1,1}; CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length); // rim data (objective not used just yet) double rowLower[5]={14.0,-5.0,3.0,1.0e10,1.0e10}; double rowUpper[5]={14.0,-5.0,3.0,-1.0e10,-1.0e10}; double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0}; double colUpper[7]={100.0,100.0,100.0,8.0,100.0,100.0,100.0}; // integer char intVar[7]={2,0,0,0,0,0,0}; // basis 1 int rowBasis1[3]={-1,-1,-1}; int colBasis1[5]={1,1,-1,-1,1}; CoinWarmStartBasis warm; warm.setSize(5,3); for (i=0;i<3;i++) { if (rowBasis1[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<5;i++) { if (colBasis1[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 1 double colsol1[5]={20.0/7.0,3.0,0.0,8.0,23.0/7.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol1, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==1); // cuts always <= int testCut=0; double rhs=10.0/7.0; double testCut1[5]={0.0,0.0,-1.0/7.0,2.0/7.0,0.0}; double * cut = testCut1; double * colsol = colsol1; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==2); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut // explicit slack matrix.setDimensions(-1,6); rpv.insert(5,1.0); // to get cut in book rowLower[3]=ub; rowUpper[3]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 2 int rowBasis2[4]={-1,-1,-1,-1}; int colBasis2[6]={1,1,1,1,-1,-1}; warm.setSize(6,4); for (i=0;i<4;i++) { if (rowBasis2[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<6;i++) { if (colBasis2[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 2 double colsol2[6]={2.0,0.5,1.0,5.5,0.0,0.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol2, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==nOldCuts); } // Test with slacks if (1) { OsiCuts osicuts; CglGomory test1; int i; int nOldCuts=0,nRowCuts; // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5]={0,4}; int length[5]={2,3}; int rows[11]={0,2,-1,-1,0,1,2}; double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0}; CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length); // rim data (objective not used just yet) double rowLower[5]={-1.0e10,-1.0e10,-1.0e10,1.0e10,1.0e10}; double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10}; double colLower[2]={0.0,0.0}; double colUpper[2]={100.0,100.0}; // integer char intVar[2]={2,0}; // basis 1 int rowBasis1[3]={-1,-1,1}; int colBasis1[2]={1,1}; CoinWarmStartBasis warm; warm.setSize(2,3); for (i=0;i<3;i++) { if (rowBasis1[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis1[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 1 double colsol1[2]={20.0/7.0,3.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol1, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==1); // cuts always <= int testCut=0; // test first cut as stronger double rhs=2.0; double testCut1[2]={1.0,0.0}; double * cut = testCut1; double * colsol = colsol1; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==1); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut rowLower[3]=-1.0e100; rowUpper[3]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 2 int rowBasis2[4]={1,1,-1,-1}; int colBasis2[2]={1,1}; warm.setSize(2,4); for (i=0;i<4;i++) { if (rowBasis2[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis2[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 2 double colsol2[2]={2.0,0.5}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol2, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==nOldCuts); } // swap some rows to G if (1) { OsiCuts osicuts; CglGomory test1; int i; int nOldCuts=0,nRowCuts; // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5]={0,4}; int length[5]={2,3}; int rows[11]={0,2,-1,-1,0,1,2}; double elements[11]={-7.0,-2.0,1.0e10,1.0e10,+2.0,1.0,+2.0}; CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length); // rim data (objective not used just yet) double rowUpper[5]={1.0e10,3.0,1.0e10,-1.0e10,-1.0e10}; double rowLower[5]={-14.0,-1.0e10,-3.0,1.0e10,1.0e10}; double colLower[2]={0.0,0.0}; double colUpper[2]={100.0,100.0}; // integer char intVar[2]={2,0}; // basis 1 int rowBasis1[3]={-1,-1,1}; int colBasis1[2]={1,1}; CoinWarmStartBasis warm; warm.setSize(2,3); for (i=0;i<3;i++) { if (rowBasis1[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis1[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 1 double colsol1[2]={20.0/7.0,3.0}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol1, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==1); // cuts always <= int testCut=0; // test first cut as stronger double rhs=2.0; double testCut1[2]={1.0,0.0}; double * cut = testCut1; double * colsol = colsol1; for (i=nOldCuts; i<nRowCuts; i++){ OsiRowCut rcut; CoinPackedVector rpv; rcut = osicuts.rowCut(i); rpv = rcut.row(); const int n = rpv.getNumElements(); const int * indices = rpv.getIndices(); double* elements = rpv.getElements(); double sum2=0.0; int k=0; for (k=0; k<n; k++){ int column=indices[k]; sum2 += colsol[column]*elements[k]; } double ub=rcut.ub(); #ifdef CGL_DEBUG double lb=rcut.lb(); if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) { std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl; for (k=0; k<n; k++){ int column=indices[k]; std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<< colsol[column]<<") "; } std::cout <<std::endl; } #endif if (i-nOldCuts==testCut) { assert( eq(rhs,ub)); assert(n==1); for (k=0; k<n; k++){ int column=indices[k]; assert (eq(cut[column],elements[k])); } // add cut rowLower[3]=-1.0e100; rowUpper[3]=ub; matrix.appendRow(rpv); } } nOldCuts=nRowCuts; // basis 2 int rowBasis2[4]={1,1,-1,-1}; int colBasis2[2]={1,1}; warm.setSize(2,4); for (i=0;i<4;i++) { if (rowBasis2[i]<0) { warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setArtifStatus(i,CoinWarmStartBasis::basic); } } for (i=0;i<2;i++) { if (colBasis2[i]<0) { warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound); } else { warm.setStructStatus(i,CoinWarmStartBasis::basic); } } // solution 2 double colsol2[2]={2.0,0.5}; test1.generateCuts(NULL, osicuts, matrix, /*objective,*/ colsol2, colLower, colUpper, rowLower, rowUpper, intVar, &warm); nRowCuts = osicuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl; assert (nRowCuts==nOldCuts); } // Miplib3 problem p0033 if (1) { // Setup OsiSolverInterface * siP = baseSiP->clone(); std::string fn(mpsDir+"p0033"); siP->readMps(fn.c_str(),"mps"); siP->activateRowCutDebugger("p0033"); CglGomory test; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); std::cout<<"Initial LP value: "<<lpRelaxBefore<<std::endl; assert( eq(lpRelaxBefore, 2520.5717391304347) ); // Fails with OsiCpx, OsiXpr: /********** double mycs[] = {0, 1, 0, 0, -2.0837010502455788e-19, 1, 0, 0, 1, 0.021739130434782594, 0.35652173913043478, -6.7220534694101275e-18, 5.3125906451789717e-18, 1, 0, 1.9298798670241979e-17, 0, 0, 0, 7.8875708048320448e-18, 0.5, 0, 0.85999999999999999, 1, 1, 0.57999999999999996, 1, 0, 1, 0, 0.25, 0, 0.67500000000000004}; siP->setColSolution(mycs); ****/ OsiCuts cuts; // Test generateCuts method test.generateCuts(*siP,cuts); int nRowCuts = cuts.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" Gomory cuts"<<std::endl; assert(cuts.sizeRowCuts() > 0); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); std::cout<<"LP value with cuts: "<<lpRelaxAfter<<std::endl; //assert( eq(lpRelaxAfter, 2592.1908295194507) ); assert( lpRelaxAfter> 2550.0 ); assert( lpRelaxBefore < lpRelaxAfter ); assert(lpRelaxAfter < 3089.1); delete siP; } }
void CglRedSplitUnitTest(const OsiSolverInterface *baseSiP, const std::string mpsDir) { // Test default constructor { CglRedSplit aGenerator; } // Test copy & assignment { CglRedSplit rhs; { CglRedSplit bGenerator; CglRedSplit cGenerator(bGenerator); rhs=bGenerator; } } // Test get/set methods { CglRedSplit getset; CglRedSplitParam gsparam = getset.getParam(); double geps = 10 * gsparam.getEPS(); gsparam.setEPS(geps); double geps2 = gsparam.getEPS(); assert(geps == geps2); double gepse = 10 * gsparam.getEPS_ELIM(); gsparam.setEPS_ELIM(gepse); double gepse2 = gsparam.getEPS_ELIM(); assert(gepse == gepse2); double gmv = 10 * gsparam.getMINVIOL(); gsparam.setMINVIOL(gmv); double gmv2 = gsparam.getMINVIOL(); assert(gmv == gmv2); int gucg = gsparam.getUSE_CG2(); gucg = 1 - gucg; gsparam.setUSE_CG2(gucg); int gucg2 = gsparam.getUSE_CG2(); assert(gucg == gucg2); } // Test generateCuts { CglRedSplit gct; OsiSolverInterface *siP = baseSiP->clone(); std::string fn = mpsDir+"p0033"; std::string fn2 = mpsDir+"p0033.mps"; FILE *in_f = fopen(fn2.c_str(), "r"); if(in_f == NULL) { std::cout<<"Can not open file "<<fn2<<std::endl<<"Skip test of CglRedSplit::generateCuts()"<<std::endl; } else { fclose(in_f); siP->readMps(fn.c_str(),"mps"); siP->initialSolve(); double lpRelax = siP->getObjValue(); OsiCuts cs; gct.getParam().setMAX_SUPPORT(34); gct.getParam().setUSE_CG2(1); // gct.getParam().setUSE_CG2(1); gct.generateCuts(*siP, cs); int nRowCuts = cs.sizeRowCuts(); std::cout<<"There are "<<nRowCuts<<" Reduce-and-Split cuts"<<std::endl; assert(cs.sizeRowCuts() > 0); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cs); siP->resolve(); double lpRelaxAfter= siP->getObjValue(); std::cout<<"Initial LP value: "<<lpRelax<<std::endl; std::cout<<"LP value with cuts: "<<lpRelaxAfter<<std::endl; assert( lpRelax < lpRelaxAfter ); assert(lpRelaxAfter < 3089.1); } delete siP; } }
void CglLandPUnitTest( OsiSolverInterface * si, const std::string &mpsDir) { CoinRelFltEq eq(1e-05); // Test default constructor { CglLandP aGenerator; assert(aGenerator.parameter().pivotLimit==20); assert(aGenerator.parameter().maxCutPerRound==5000); assert(aGenerator.parameter().failedPivotLimit==1); assert(aGenerator.parameter().degeneratePivotLimit==0); assert(eq(aGenerator.parameter().pivotTol, 1e-04)); assert(eq(aGenerator.parameter().away, 5e-04)); assert(eq(aGenerator.parameter().timeLimit, COIN_DBL_MAX)); assert(eq(aGenerator.parameter().singleCutTimeLimit, COIN_DBL_MAX)); assert(aGenerator.parameter().useTableauRow==true); assert(aGenerator.parameter().modularize==false); assert(aGenerator.parameter().strengthen==true); assert(aGenerator.parameter().perturb==true); assert(aGenerator.parameter().pivotSelection==CglLandP::mostNegativeRc); } // Test copy constructor { CglLandP a; { CglLandP b; b.parameter().pivotLimit = 100; b.parameter().maxCutPerRound = 100; b.parameter().failedPivotLimit = 10; b.parameter().degeneratePivotLimit = 10; b.parameter().pivotTol = 1e-07; b.parameter().away = 1e-10; b.parameter().timeLimit = 120; b.parameter().singleCutTimeLimit = 15; b.parameter().useTableauRow = true; b.parameter().modularize = true; b.parameter().strengthen = false; b.parameter().perturb = false; b.parameter().pivotSelection=CglLandP::bestPivot; //Test Copy CglLandP c(b); assert(c.parameter().pivotLimit == 100); assert(c.parameter().maxCutPerRound == 100); assert(c.parameter().failedPivotLimit == 10); assert(c.parameter().degeneratePivotLimit == 10); assert(c.parameter().pivotTol == 1e-07); assert(c.parameter().away == 1e-10); assert(c.parameter().timeLimit == 120); assert(c.parameter().singleCutTimeLimit == 15); assert(c.parameter().useTableauRow == true); assert(c.parameter().modularize == true); assert(c.parameter().strengthen == false); assert(c.parameter().perturb == false); assert(c.parameter().pivotSelection == CglLandP::bestPivot); a=b; assert(a.parameter().pivotLimit == 100); assert(a.parameter().maxCutPerRound == 100); assert(a.parameter().failedPivotLimit == 10); assert(a.parameter().degeneratePivotLimit == 10); assert(a.parameter().pivotTol == 1e-07); assert(a.parameter().away == 1e-10); assert(a.parameter().timeLimit == 120); assert(a.parameter().singleCutTimeLimit == 15); assert(a.parameter().useTableauRow == true); assert(a.parameter().modularize == true); assert(a.parameter().strengthen == false); assert(a.parameter().perturb == false); assert(a.parameter().pivotSelection == CglLandP::bestPivot); } } { // Maximize 2 x2 // s.t. // 2x1 + 2x2 <= 3 // -2x1 + 2x2 <= 1 // 7x1 + 4x2 <= 8 // -7x1 + 4x2 <= 1 // x1, x2 >= 0 and x1, x2 integer // Slacks are s1, s2, s3, s4 //Test that problem is correct // Optimal Basis is x1, x2, s3, s4 with tableau // x1 0.25 s1 -0.25 s2 = 0.5 // x2 0.25 s1 0.25 s2 = 1 // -2.75 s1 0.75 s2 s3 = 0.5 // 0.75 s1 -2.75 s2 s4 = 0.5 // z= -0.25 s1 -0.25 s2 = -1 // Gomory cut from variable x1 is x2 <= 0.5 // Can be improved by first pivoting s2 in and s4 out, then s1 in and s3 out // to x2 <= 0.25 { int start[2] = {0,4}; int length[2] = {4,4}; int rows[8] = {0,1,2,3,0,1,2,3}; double elements[8] = {2.0,-2.0,7.0,-7.0,2.0,2.0,4.0,4.0}; CoinPackedMatrix columnCopy(true,4,2,8,elements,rows,start,length); double rowLower[4]={-COIN_DBL_MAX,-COIN_DBL_MAX, -COIN_DBL_MAX,-COIN_DBL_MAX}; double rowUpper[4]={3.,1.,8.,1.}; double colLower[2]={0.0,0.0}; double colUpper[2]={1.0,1.0}; double obj[2]={-1,-1}; int intVar[2]={0,1}; OsiSolverInterface * siP = si->clone(); siP->loadProblem(columnCopy, colLower, colUpper, obj, rowLower, rowUpper); siP->setInteger(intVar,2); CglLandP test; test.setLogLevel(2); test.parameter().sepSpace = CglLandP::Full; siP->resolve(); // Test generateCuts method { OsiCuts cuts; test.generateCuts(*siP,cuts); cuts.printCuts(); assert(cuts.sizeRowCuts()==1); OsiRowCut aCut = cuts.rowCut(0); assert(eq(aCut.lb(), -.0714286)); CoinPackedVector row = aCut.row(); if (row.getNumElements() == 1) { assert(row.getIndices()[0]==1); assert(eq(row.getElements()[0], -4*.0714286)); } else if (row.getNumElements() == 2) { assert(row.getIndices()[0]==0); assert(eq(row.getElements()[0], 0.)); assert(row.getIndices()[1]==1); assert(eq(row.getElements()[1], -1)); } OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); } if (0) { OsiCuts cuts; test.generateCuts(*siP,cuts); cuts.printCuts(); assert(cuts.sizeRowCuts()==1); OsiRowCut aCut = cuts.rowCut(0); CoinPackedVector row = aCut.row(); if (row.getNumElements() == 1) { assert(row.getIndices()[0]==1); assert(eq(row.getElements()[0], -1)); } else if (row.getNumElements() == 2) { assert(row.getIndices()[0]==0); assert(eq(row.getElements()[0], 0.)); assert(row.getIndices()[1]==1); assert(eq(row.getElements()[1], -1)); } assert(eq(aCut.lb(), 0.)); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); } delete siP; } } if (1) //Test on p0033 { // Setup OsiSolverInterface * siP = si->clone(); std::string fn(mpsDir+"p0033"); siP->readMps(fn.c_str(),"mps"); siP->activateRowCutDebugger("p0033"); CglLandP test; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, 2520.5717391304347) ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); #endif OsiCuts cuts; // Test generateCuts method test.generateCuts(*siP,cuts); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); //assert( eq(lpRelaxAfter, 2592.1908295194507) ); std::cout<<"Relaxation after "<<lpRelaxAfter<<std::endl; assert( lpRelaxAfter> 2840. ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif assert( lpRelaxBefore < lpRelaxAfter ); delete siP; } if (1) //test again with modularization { // Setup OsiSolverInterface * siP = si->clone(); std::string fn(mpsDir+"p0033"); siP->readMps(fn.c_str(),"mps"); siP->activateRowCutDebugger("p0033"); CglLandP test; test.parameter().modularize = true; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, 2520.5717391304347) ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); #endif OsiCuts cuts; // Test generateCuts method test.generateCuts(*siP,cuts); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); //assert( eq(lpRelaxAfter, 2592.1908295194507) ); std::cout<<"Relaxation after "<<lpRelaxAfter<<std::endl; assert( lpRelaxAfter> 2840. ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif assert( lpRelaxBefore < lpRelaxAfter ); delete siP; } if (1) //test again with alternate pivoting rule { // Setup OsiSolverInterface * siP = si->clone(); std::string fn(mpsDir+"p0033"); siP->readMps(fn.c_str(),"mps"); siP->activateRowCutDebugger("p0033"); CglLandP test; test.parameter().pivotSelection = CglLandP::bestPivot; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, 2520.5717391304347) ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); #endif OsiCuts cuts; // Test generateCuts method test.generateCuts(*siP,cuts); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); //assert( eq(lpRelaxAfter, 2592.1908295194507) ); std::cout<<"Relaxation after "<<lpRelaxAfter<<std::endl; assert( lpRelaxAfter> 2840. ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif assert( lpRelaxBefore < lpRelaxAfter ); delete siP; } if (1) //Finally test code in documentation { // Setup OsiSolverInterface * siP = si->clone(); std::string fn(mpsDir+"p0033"); siP->readMps(fn.c_str(),"mps"); siP->activateRowCutDebugger("p0033"); CglLandP landpGen; landpGen.parameter().timeLimit = 10.; landpGen.parameter().pivotLimit = 2; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, 2520.5717391304347) ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); #endif OsiCuts cuts; // Test generateCuts method landpGen.generateCuts(*siP, cuts); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); //assert( eq(lpRelaxAfter, 2592.1908295194507) ); std::cout<<"Relaxation after "<<lpRelaxAfter<<std::endl; assert( lpRelaxAfter> 2840. ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif assert( lpRelaxBefore < lpRelaxAfter ); delete siP; } }
//-------------------------------------------------------------------------- void OsiColCutUnitTest(const OsiSolverInterface *baseSiP, const std::string &mpsDir) { // Test default constructor { OsiColCut r; OSIUNITTEST_ASSERT_ERROR(r.lbs_.getIndices() == NULL, {}, "osicolcut", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.lbs_.getElements() == NULL, {}, "osicolcut", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.lbs_.getNumElements() == 0, {}, "osicolcut", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.lbs().getNumElements() == 0, {}, "osicolcut", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.ubs_.getIndices() == NULL, {}, "osicolcut", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.ubs_.getElements() == NULL, {}, "osicolcut", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.ubs_.getNumElements() == 0, {}, "osicolcut", "default constructor"); OSIUNITTEST_ASSERT_ERROR(r.ubs().getNumElements() == 0, {}, "osicolcut", "default constructor"); } // Test set and get methods const int ne = 4; int inx[ne] = { 1, 3, 4, 7 }; double el[ne] = { 1.2, 3.4, 5.6, 7.8 }; const int ne3 = 0; int *inx3 = NULL; double *el3 = NULL; { OsiColCut r; // Test setting/getting bounds r.setLbs(ne, inx, el); r.setEffectiveness(222.); OSIUNITTEST_ASSERT_ERROR(r.lbs().getNumElements() == ne, return, "osicolcut", "setting bounds"); bool bounds_ok = true; for (int i = 0; i < ne; i++) { bounds_ok &= r.lbs().getIndices()[i] == inx[i]; bounds_ok &= r.lbs().getElements()[i] == el[i]; } OSIUNITTEST_ASSERT_ERROR(bounds_ok, {}, "osicolcut", "setting bounds"); OSIUNITTEST_ASSERT_ERROR(r.effectiveness() == 222.0, {}, "osicolcut", "setting bounds"); r.setUbs(ne3, inx3, el3); OSIUNITTEST_ASSERT_ERROR(r.ubs().getNumElements() == 0, {}, "osicolcut", "setting bounds"); OSIUNITTEST_ASSERT_ERROR(r.ubs().getIndices() == NULL, {}, "osicolcut", "setting bounds"); OSIUNITTEST_ASSERT_ERROR(r.ubs().getElements() == NULL, {}, "osicolcut", "setting bounds"); } // Test copy constructor and assignment operator { OsiColCut rhs; { OsiColCut r; OsiColCut rC1(r); OSIUNITTEST_ASSERT_ERROR(rC1.lbs().getNumElements() == r.lbs().getNumElements(), {}, "osicolcut", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(rC1.ubs().getNumElements() == r.ubs().getNumElements(), {}, "osicolcut", "copy constructor"); r.setLbs(ne, inx, el); r.setUbs(ne, inx, el); r.setEffectiveness(121.); OSIUNITTEST_ASSERT_ERROR(rC1.lbs().getNumElements() != r.lbs().getNumElements(), {}, "osicolcut", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(rC1.ubs().getNumElements() != r.lbs().getNumElements(), {}, "osicolcut", "copy constructor"); OsiColCut rC2(r); OSIUNITTEST_ASSERT_ERROR(rC2.lbs().getNumElements() == r.lbs().getNumElements(), {}, "osicolcut", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(rC2.ubs().getNumElements() == r.ubs().getNumElements(), {}, "osicolcut", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(rC2.lbs().getNumElements() == ne, return, "osicolcut", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(rC2.ubs().getNumElements() == ne, return, "osicolcut", "copy constructor"); bool bounds_ok = true; for (int i = 0; i < ne; i++) { bounds_ok &= rC2.lbs().getIndices()[i] == inx[i]; bounds_ok &= rC2.lbs().getElements()[i] == el[i]; bounds_ok &= rC2.ubs().getIndices()[i] == inx[i]; bounds_ok &= rC2.ubs().getElements()[i] == el[i]; } OSIUNITTEST_ASSERT_ERROR(bounds_ok, {}, "osicolcut", "copy constructor"); OSIUNITTEST_ASSERT_ERROR(rC2.effectiveness() == 121.0, {}, "osicolcut", "copy constructor"); rhs = rC2; } // Test that rhs has correct values even though lhs has gone out of scope OSIUNITTEST_ASSERT_ERROR(rhs.lbs().getNumElements() == ne, return, "osicolcut", "assignment operator"); OSIUNITTEST_ASSERT_ERROR(rhs.ubs().getNumElements() == ne, return, "osicolcut", "assignment operator"); bool bounds_ok = true; for (int i = 0; i < ne; i++) { bounds_ok &= rhs.lbs().getIndices()[i] == inx[i]; bounds_ok &= rhs.lbs().getElements()[i] == el[i]; bounds_ok &= rhs.ubs().getIndices()[i] == inx[i]; bounds_ok &= rhs.ubs().getElements()[i] == el[i]; } OSIUNITTEST_ASSERT_ERROR(bounds_ok, {}, "osicolcut", "assignment operator"); OSIUNITTEST_ASSERT_ERROR(rhs.effectiveness() == 121.0, {}, "osicolcut", "assignment operator"); } // Test setting bounds with packed vector and operator== { const int ne1 = 4; int inx1[ne] = { 1, 3, 4, 7 }; double el1[ne] = { 1.2, 3.4, 5.6, 7.8 }; const int ne2 = 2; int inx2[ne2] = { 1, 3 }; double el2[ne2] = { 1.2, 3.4 }; CoinPackedVector v1, v2; v1.setVector(ne1, inx1, el1); v2.setVector(ne2, inx2, el2); OsiColCut c1, c2; OSIUNITTEST_ASSERT_ERROR(c1 == c2, {}, "osicolcut", "setting bounds with packed vector and operator =="); OSIUNITTEST_ASSERT_ERROR(!(c1 != c2), {}, "osicolcut", "setting bounds with packed vector and operator !="); c1.setLbs(v1); OSIUNITTEST_ASSERT_ERROR(c1 != c2, {}, "osicolcut", "setting bounds with packed vector and operator !="); OSIUNITTEST_ASSERT_ERROR(!(c1 == c2), {}, "osicolcut", "setting bounds with packed vector and operator =="); OSIUNITTEST_ASSERT_ERROR(c1.lbs() == v1, {}, "osicolcut", "setting bounds with packed vector and operator !="); c1.setUbs(v2); OSIUNITTEST_ASSERT_ERROR(c1.ubs() == v2, {}, "osicolcut", "setting bounds with packed vector and operator !="); c1.setEffectiveness(3.); OSIUNITTEST_ASSERT_ERROR(c1.effectiveness() == 3.0, {}, "osicolcut", "setting bounds with packed vector and operator !="); { OsiColCut c3(c1); OSIUNITTEST_ASSERT_ERROR(c3 == c1, {}, "osicolcut", "operator =="); OSIUNITTEST_ASSERT_ERROR(!(c3 != c1), {}, "osicolcut", "operator !="); } { OsiColCut c3(c1); c3.setLbs(v2); OSIUNITTEST_ASSERT_ERROR(c3 != c1, {}, "osicolcut", "operator !="); OSIUNITTEST_ASSERT_ERROR(!(c3 == c1), {}, "osicolcut", "operator =="); } { OsiColCut c3(c1); c3.setUbs(v1); OSIUNITTEST_ASSERT_ERROR(c3 != c1, {}, "osicolcut", "operator !="); OSIUNITTEST_ASSERT_ERROR(!(c3 == c1), {}, "osicolcut", "operator =="); } { OsiColCut c3(c1); c3.setEffectiveness(5.); OSIUNITTEST_ASSERT_ERROR(c3 != c1, {}, "osicolcut", "operator !="); OSIUNITTEST_ASSERT_ERROR(!(c3 == c1), {}, "osicolcut", "operator =="); } } // internal consistency { const int ne = 1; int inx[ne] = { -3 }; double el[ne] = { 1.2 }; OsiColCut r; r.setLbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(!r.consistent(), {}, "osicolcut", "consistent"); } { const int ne = 1; int inx[ne] = { -3 }; double el[ne] = { 1.2 }; OsiColCut r; r.setUbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(!r.consistent(), {}, "osicolcut", "consistent"); } { const int ne = 1; int inx[ne] = { 100 }; double el[ne] = { 1.2 }; const int ne1 = 2; int inx1[ne1] = { 50, 100 }; double el1[ne1] = { 100., 100. }; OsiColCut r; r.setUbs(ne, inx, el); r.setLbs(ne1, inx1, el1); OSIUNITTEST_ASSERT_ERROR(r.consistent(), {}, "osicolcut", "consistent"); OsiSolverInterface *imP = baseSiP->clone(); assert(imP != NULL); std::string fn = mpsDir + "exmip1"; imP->readMps(fn.c_str(), "mps"); OSIUNITTEST_ASSERT_ERROR(!r.consistent(*imP), {}, "osicolcut", "consistent"); delete imP; } { const int ne = 1; int inx[ne] = { 100 }; double el[ne] = { 1.2 }; const int ne1 = 2; int inx1[ne1] = { 50, 100 }; double el1[ne1] = { 100., 1. }; OsiColCut r; r.setUbs(ne, inx, el); r.setLbs(ne1, inx1, el1); OSIUNITTEST_ASSERT_ERROR(r.consistent(), {}, "osicolcut", "consistent"); } { // Test consistent(IntegerModel) method. OsiSolverInterface *imP = baseSiP->clone(); assert(imP != NULL); std::string fn = mpsDir + "exmip1"; imP->readMps(fn.c_str(), "mps"); OsiColCut cut; const int ne = 1; int inx[ne] = { 20 }; double el[ne] = { 0.25 }; cut.setLbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(!cut.consistent(*imP), {}, "osicolcut", "consistent(IntegerModel)"); cut.setLbs(0, NULL, NULL); cut.setUbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(!cut.consistent(*imP), {}, "osicolcut", "consistent(IntegerModel)"); inx[0] = 4; cut.setLbs(ne, inx, el); cut.setUbs(0, NULL, NULL); OSIUNITTEST_ASSERT_ERROR(cut.consistent(*imP), {}, "osicolcut", "consistent(IntegerModel)"); el[0] = 4.5; cut.setLbs(0, NULL, NULL); cut.setUbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(cut.consistent(*imP), {}, "osicolcut", "consistent(IntegerModel)"); cut.setLbs(ne, inx, el); cut.setUbs(0, NULL, NULL); OSIUNITTEST_ASSERT_ERROR(cut.consistent(*imP), {}, "osicolcut", "consistent(IntegerModel)"); OSIUNITTEST_ASSERT_ERROR(cut.infeasible(*imP), {}, "osicolcut", "infeasible(IntegerModel)"); el[0] = 3.0; cut.setLbs(ne, inx, el); cut.setUbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(cut.consistent(*imP), {}, "osicolcut", "consistent(IntegerModel)"); delete imP; } { //Test infeasible(im) method // Test consistent(IntegerModel) method. OsiSolverInterface *imP = baseSiP->clone(); assert(imP != NULL); std::string fn = mpsDir + "exmip1"; imP->readMps(fn.c_str(), "mps"); OsiColCut cut; const int ne = 1; int inx[ne] = { 4 }; double el[ne] = { 4.5 }; cut.setLbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(cut.infeasible(*imP), {}, "osicolcut", "infeasible(IntegerModel)"); el[0] = 0.25; cut.setLbs(0, NULL, NULL); cut.setUbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(cut.infeasible(*imP), {}, "osicolcut", "infeasible(IntegerModel)"); el[0] = 3.0; cut.setLbs(ne, inx, el); cut.setUbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(!cut.infeasible(*imP), {}, "osicolcut", "infeasible(IntegerModel)"); delete imP; } { //Test violation double solution[] = { 1.0 }; OsiColCut cut; const int ne = 1; int inx[ne] = { 0 }; double el[ne] = { 4.5 }; cut.setLbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(cut.violated(solution), {}, "osicolcut", "violated"); el[0] = 0.25; cut.setLbs(0, NULL, NULL); cut.setUbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(cut.violated(solution), {}, "osicolcut", "violated"); el[0] = 1.0; cut.setLbs(ne, inx, el); cut.setUbs(ne, inx, el); OSIUNITTEST_ASSERT_ERROR(!cut.violated(solution), {}, "osicolcut", "violated"); } }
//Solver function int sci_rmps(char *fname) { //creating a problem pointer using base class of OsiSolverInterface and //instantiate the object using derived class of ClpSolverInterface OsiSolverInterface* si = new OsiClpSolverInterface(); // Error management variable SciErr sciErr; //data declarations int *piAddressVarOne = NULL; //pointer used to access argument of the function char* ptr; //pointer to point to address of file name double* options_; //options to set maximum iterations CheckInputArgument(pvApiCtx, 2,2 ); //Check we have exactly two arguments as input or not CheckOutputArgument(pvApiCtx, 6, 6); //Check we have exactly six arguments on output side or not //Getting the input arguments from Scilab //Getting the MPS file path //Reading mps file getStringFromScilab(1,&ptr); std::cout<<ptr; //get options from Scilab if(getFixedSizeDoubleMatrixInList(2 , 2 , 1 , 1 , &options_)) { return 1; } //Read the MPS file si->readMps(ptr); //setting options for maximum iterations si->setIntParam(OsiMaxNumIteration,options_[0]); //Solve the problem si->initialSolve(); //Quering about the problem //get number of variables double numVars_; numVars_ = si->getNumCols(); //get number of constraint equations double numCons_; numCons_ = si->getNumRows(); //Output the solution to Scilab //get solution for x const double* xValue = si->getColSolution(); //get objective value double objValue = si->getObjValue(); //get Status value double status; if(si->isProvenOptimal()) status=0; else if(si->isProvenPrimalInfeasible()) status=1; else if(si->isProvenDualInfeasible()) status=2; else if(si->isIterationLimitReached()) status=3; else if(si->isAbandoned()) status=4; else if(si->isPrimalObjectiveLimitReached()) status=5; else if(si->isDualObjectiveLimitReached()) status=6; //get number of iterations double iterations = si->getIterationCount(); //get reduced cost const double* reducedCost = si->getReducedCost(); //get dual vector const double* dual = si->getRowPrice(); returnDoubleMatrixToScilab(1 , 1 , numVars_ , xValue); returnDoubleMatrixToScilab(2 , 1 , 1 , &objValue); returnDoubleMatrixToScilab(3 , 1 , 1 , &status); returnDoubleMatrixToScilab(4 , 1 , 1 , &iterations); returnDoubleMatrixToScilab(5 , 1 , numVars_ , reducedCost); returnDoubleMatrixToScilab(6 , 1 , numCons_ , dual); free(xValue); free(dual); free(reducedCost); }
//-------------------------------------------------------------------------- void CglKnapsackCoverUnitTest( const OsiSolverInterface * baseSiP, const std::string mpsDir ) { int i; CoinRelFltEq eq(0.000001); // Test default constructor { CglKnapsackCover kccGenerator; } // Test copy & assignment { CglKnapsackCover rhs; { CglKnapsackCover kccGenerator; CglKnapsackCover cgC(kccGenerator); rhs=kccGenerator; } } // test exactSolveKnapsack { CglKnapsackCover kccg; const int n=7; double c=50; double p[n] = {70,20,39,37,7,5,10}; double w[n] = {31, 10, 20, 19, 4, 3, 6}; double z; int x[n]; int exactsol = kccg.exactSolveKnapsack(n, c, p, w, z, x); assert(exactsol==1); assert (z == 107); assert (x[0]==1); assert (x[1]==0); assert (x[2]==0); assert (x[3]==1); assert (x[4]==0); assert (x[5]==0); assert (x[6]==0); } /* // Testcase /u/rlh/osl2/mps/scOneInt.mps // Model has 3 continous, 2 binary, and 1 general // integer variable. { OsiSolverInterface * siP = baseSiP->clone(); int * complement=NULL; double * xstar=NULL; siP->readMps("../Mps/scOneInt","mps"); CglKnapsackCover kccg; int nCols=siP->getNumCols(); // Test the siP methods for detecting // variable type int numCont=0, numBinary=0, numIntNonBinary=0, numInt=0; for (int thisCol=0; thisCol<nCols; thisCol++) { if ( siP->isContinuous(thisCol) ) numCont++; if ( siP->isBinary(thisCol) ) numBinary++; if ( siP->isIntegerNonBinary(thisCol) ) numIntNonBinary++; if ( siP->isInteger(thisCol) ) numInt++; } assert(numCont==3); assert(numBinary==2); assert(numIntNonBinary==1); assert(numInt==3); // Test initializeCutGenerator siP->initialSolve(); assert(xstar !=NULL); for (i=0; i<nCols; i++){ assert(complement[i]==0); } int nRows=siP->getNumRows(); for (i=0; i<nRows; i++){ int vectorsize = siP->getMatrixByRow()->vectorSize(i); assert(vectorsize==2); } kccg.cleanUpCutGenerator(complement,xstar); delete siP; } */ // Testcase /u/rlh/osl2/mps/tp3.mps // Models has 3 cols, 3 rows // Row 0 yields a knapsack, others do not. { // setup OsiSolverInterface * siP = baseSiP->clone(); std::string fn(mpsDir+"tp3"); siP->readMps(fn.c_str(),"mps"); // All integer variables should be binary. // Assert that this is true. for ( i = 0; i < siP->getNumCols(); i++ ) if ( siP->isInteger(i) ) assert(siP->getColUpper()[i]==1.0 && siP->isBinary(i)); OsiCuts cs; CoinPackedVector krow; double b=0; int nCols=siP->getNumCols(); int * complement=new int [nCols]; double * xstar=new double [nCols]; CglKnapsackCover kccg; // solve LP relaxation // a "must" before calling initialization siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); std::cout<<"Initial LP value: "<<lpRelaxBefore<<std::endl; assert( eq(siP->getObjValue(), 97.185) ); double mycs[] = {.627, .667558333333, .038}; siP->setColSolution(mycs); const double *colsol = siP->getColSolution(); int k; for (k=0; k<nCols; k++){ xstar[k]=colsol[k]; complement[k]=0; } // test deriveAKnapsack int rind = ( siP->getRowSense()[0] == 'N' ) ? 1 : 0; const CoinShallowPackedVector reqdBySunCC = siP->getMatrixByRow()->getVector(rind) ; int deriveaknap = kccg.deriveAKnapsack(*siP, cs, krow,b,complement,xstar,rind,reqdBySunCC); assert(deriveaknap ==1); assert(complement[0]==0); assert(complement[1]==1); assert(complement[2]==1); int inx[3] = {0,1,2}; double el[3] = {161, 120, 68}; CoinPackedVector r; r.setVector(3,inx,el); assert (krow == r); //assert (b == 183.0); ????? but x1 and x2 at 1 is valid // test findGreedyCover CoinPackedVector cover,remainder; #if 0 int findgreedy = kccg.findGreedyCover( 0, krow, b, xstar, cover, remainder ); assert( findgreedy == 1 ); int coveri = cover.getNumElements(); assert( cover.getNumElements() == 2); coveri = cover.getIndices()[0]; assert( cover.getIndices()[0] == 0); assert( cover.getIndices()[1] == 1); assert( cover.getElements()[0] == 161.0); assert( cover.getElements()[1] == 120.0); assert( remainder.getNumElements() == 1); assert( remainder.getIndices()[0] == 2); assert( remainder.getElements()[0] == 68.0); // test liftCoverCut CoinPackedVector cut; double * rowupper = ekk_rowupper(model); double cutRhs = cover.getNumElements() - 1.0; kccg.liftCoverCut(b, krow.getNumElements(), cover, remainder, cut); assert ( cut.getNumElements() == 3 ); assert ( cut.getIndices()[0] == 0 ); assert ( cut.getIndices()[1] == 1 ); assert ( cut.getIndices()[2] == 2 ); assert( cut.getElements()[0] == 1 ); assert( cut.getElements()[1] == 1 ); assert( eq(cut.getElements()[2], 0.087719) ); // test liftAndUncomplementAndAdd OsiCuts cuts; kccg.liftAndUncomplementAndAdd(*siP.getRowUpper()[0],krow,b,complement,0, cover,remainder,cuts); int sizerowcuts = cuts.sizeRowCuts(); assert ( sizerowcuts== 1 ); OsiRowCut testRowCut = cuts.rowCut(0); CoinPackedVector testRowPV = testRowCut.row(); OsiRowCut sampleRowCut; const int sampleSize = 3; int sampleCols[sampleSize]={0,1,2}; double sampleElems[sampleSize]={1.0,-1.0,-0.087719}; sampleRowCut.setRow(sampleSize,sampleCols,sampleElems); sampleRowCut.setLb(-DBL_MAX); sampleRowCut.setUb(-0.087719); bool equiv = testRowPV.equivalent(sampleRowCut.row(),CoinRelFltEq(1.0e-05) ); assert ( equiv ); #endif // test find PseudoJohnAndEllisCover cover.setVector(0,NULL, NULL); remainder.setVector(0,NULL,NULL); rind = ( siP->getRowSense()[0] == 'N' ) ? 1 : 0; int findPJE = kccg.findPseudoJohnAndEllisCover( rind, krow, b, xstar, cover, remainder ); assert( findPJE == 1 ); assert ( cover.getIndices()[0] == 0 ); assert ( cover.getIndices()[1] == 2 ); assert ( cover.getElements()[0] == 161 ); assert ( cover.getElements()[1] == 68 ); assert ( remainder.getIndices()[0] == 1 ); assert ( remainder.getElements()[0] == 120 ); OsiCuts cuts; kccg.liftAndUncomplementAndAdd((*siP).getRowUpper()[rind],krow,b, complement, rind, cover,remainder,cuts); assert (cuts.sizeRowCuts() == 1 ); OsiRowCut testRowCut = cuts.rowCut(0); CoinPackedVector testRowPV = testRowCut.row(); const int sampleSize = 3; int sampleCols[sampleSize]={0,1,2}; double sampleElems[sampleSize]={1.0, -1.0, -1.0}; OsiRowCut sampleRowCut; sampleRowCut.setRow(sampleSize,sampleCols,sampleElems); sampleRowCut.setLb(-COIN_DBL_MAX); sampleRowCut.setUb(-1.0); // test for 'close enough' assert( testRowPV.isEquivalent(sampleRowCut.row(),CoinRelFltEq(1.0e-05) ) ); // Reset complement & test next row for (i=0; i<nCols; i++){ complement[i]=0; } rind++; const CoinShallowPackedVector reqdBySunCC2 = siP->getMatrixByRow()->getVector(rind) ; deriveaknap = kccg.deriveAKnapsack(*siP,cuts,krow,b,complement,xstar,rind,reqdBySunCC2); assert(deriveaknap==0); // Reset complement & test next row for (i=0; i<nCols; i++){ complement[i]=0; } const CoinShallowPackedVector reqdBySunCC3 = siP->getMatrixByRow()->getVector(2) ; deriveaknap = kccg.deriveAKnapsack(*siP,cuts,krow,b,complement,xstar,2, reqdBySunCC3); assert(deriveaknap == 0); // Clean up delete [] complement; delete [] xstar; delete siP; } #if 0 // Testcase /u/rlh/osl2/mps/tp4.mps // Models has 6 cols, 1 knapsack row and // 3 rows explicily bounding variables // Row 0 yields a knapsack cover cut // using findGreedyCover which moves the // LP objective function value. { // Setup EKKContext * env=ekk_initializeContext(); EKKModel * model = ekk_newModel(env,""); OsiSolverInterface si(model); ekk_importModel(model, "tp4.mps"); CglKnapsackCover kccg; kccg.ekk_validateIntType(si); // Solve the LP relaxation of the model and // print out ofv for sake of comparison ekk_allSlackBasis(model); ekk_crash(model,1); ekk_primalSimplex(model,1); double lpRelaxBefore=ekk_getRobjvalue(model); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); #endif // Determine if lp sol is ip optimal // Note: no ekk_function to do this int nCols=ekk_getInumcols(model); double * optLpSol = ekk_colsol(model); int ipOpt = 1; i=0; while (i++<nCols && ipOpt){ if(optLpSol[i] < 1.0-1.0e-08 && optLpSol[i]> 1.0e-08) ipOpt = 0; } if (ipOpt){ #ifdef CGL_DEBUG printf("Lp solution is within ip optimality tolerance\n"); #endif } else { OsiSolverInterface iModel(model); OsiCuts cuts; // Test generateCuts method kccg.generateCuts(iModel,cuts); OsiSolverInterface::ApplyCutsReturnCode rc = iModel.applyCuts(cuts); ekk_mergeBlocks(model,1); ekk_dualSimplex(model); double lpRelaxAfter=ekk_getRobjvalue(model); #ifdef CGL_DEBUG printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif assert( lpRelaxBefore < lpRelaxAfter ); // This may need to be updated as other // minimal cover finders are added assert( cuts.sizeRowCuts() == 1 ); OsiRowCut testRowCut = cuts.rowCut(0); CoinPackedVector testRowPV = testRowCut.row(); OsiRowCut sampleRowCut; const int sampleSize = 6; int sampleCols[sampleSize]={0,1,2,3,4,5}; double sampleElems[sampleSize]={1.0,1.0,1.0,1.0,0.5, 2.0}; sampleRowCut.setRow(sampleSize,sampleCols,sampleElems); sampleRowCut.setLb(-DBL_MAX); sampleRowCut.setUb(3.0); bool equiv = testRowPV.equivalent(sampleRowCut.row(),CoinRelFltEq(1.0e-05) ); assert( testRowPV.equivalent(sampleRowCut.row(),CoinRelFltEq(1.0e-05) ) ); } // Exit out of OSL ekk_deleteModel(model); ekk_endContext(env); } #endif // Testcase /u/rlh/osl2/mps/tp5.mps // Models has 6 cols, 1 knapsack row and // 3 rows explicily bounding variables // Row 0 yields a knapsack cover cut // using findGreedyCover which moves the // LP objective function value. { // Setup OsiSolverInterface * siP = baseSiP->clone(); std::string fn(mpsDir+"tp5"); siP->readMps(fn.c_str(),"mps"); // All integer variables should be binary. // Assert that this is true. for ( i = 0; i < siP->getNumCols(); i++ ) if ( siP->isInteger(i) ) assert(siP->getColUpper()[i]==1.0 && siP->isBinary(i)); CglKnapsackCover kccg; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, -51.66666666667) ); double mycs[] = {.8999999999, .899999999999, .89999999999, 1.110223e-16, .5166666666667, 0}; siP->setColSolution(mycs); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); #endif // Determine if lp sol is 0/1 optimal int nCols=siP->getNumCols(); const double * optLpSol = siP->getColSolution(); bool ipOpt = true; i=0; while (i++<nCols && ipOpt){ if(optLpSol[i] > kccg.epsilon_ && optLpSol[i] < kccg.onetol_) ipOpt = false; } if (ipOpt){ #ifdef CGL_DEBUG printf("Lp solution is within ip optimality tolerance\n"); #endif } else { // set up OsiCuts cuts; CoinPackedVector krow; double b=0.0; int * complement=new int[nCols]; double * xstar=new double[nCols]; // initialize cut generator const double *colsol = siP->getColSolution(); for (i=0; i<nCols; i++){ xstar[i]=colsol[i]; complement[i]=0; } int row = ( siP->getRowSense()[0] == 'N' ) ? 1 : 0; // transform row into canonical knapsack form const CoinShallowPackedVector reqdBySunCC = siP->getMatrixByRow()->getVector(row) ; if (kccg.deriveAKnapsack(*siP, cuts, krow, b, complement, xstar, row,reqdBySunCC)){ CoinPackedVector cover, remainder; // apply greedy logic to detect violated minimal cover inequalities if (kccg.findGreedyCover(row, krow, b, xstar, cover, remainder) == 1){ // lift, uncomplements, and add cut to cut set kccg.liftAndUncomplementAndAdd((*siP).getRowUpper()[row],krow, b, complement, row, cover, remainder, cuts); } // reset optimal column solution (xstar) information in OSL const double * rowupper = siP->getRowUpper(); int k; if (fabs(b-rowupper[row]) > 1.0e-05) { for(k=0; k<krow.getNumElements(); k++) { if (complement[krow.getIndices()[k]]){ xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]]; complement[krow.getIndices()[k]]=0; } } } // clean up delete [] complement; delete [] xstar; } // apply the cuts OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); assert( eq(lpRelaxAfter, -30.0) ); #ifdef CGL_DEBUG printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif // test that expected cut was detected assert( lpRelaxBefore < lpRelaxAfter ); assert( cuts.sizeRowCuts() == 1 ); OsiRowCut testRowCut = cuts.rowCut(0); CoinPackedVector testRowPV = testRowCut.row(); OsiRowCut sampleRowCut; const int sampleSize = 6; int sampleCols[sampleSize]={0,1,2,3,4,5}; double sampleElems[sampleSize]={1.0,1.0,1.0,0.25,1.0,2.0}; sampleRowCut.setRow(sampleSize,sampleCols,sampleElems); sampleRowCut.setLb(-COIN_DBL_MAX); sampleRowCut.setUb(3.0); assert(testRowPV.isEquivalent(sampleRowCut.row(),CoinRelFltEq(1.0e-05))); } delete siP; } // Testcase /u/rlh/osl2/mps/p0033 // Miplib3 problem p0033 // Test that no cuts chop off the optimal solution { // Setup OsiSolverInterface * siP = baseSiP->clone(); std::string fn(mpsDir+"p0033"); siP->readMps(fn.c_str(),"mps"); // All integer variables should be binary. // Assert that this is true. for ( i = 0; i < siP->getNumCols(); i++ ) if ( siP->isInteger(i) ) assert(siP->getColUpper()[i]==1.0 && siP->isBinary(i)); int nCols=siP->getNumCols(); CglKnapsackCover kccg; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, 2520.5717391304347) ); double mycs[] = {0, 1, 0, 0, -2.0837010502455788e-19, 1, 0, 0, 1, 0.021739130434782594, 0.35652173913043478, -6.7220534694101275e-18, 5.3125906451789717e-18, 1, 0, 1.9298798670241979e-17, 0, 0, 0, 7.8875708048320448e-18, 0.5, 0, 0.85999999999999999, 1, 1, 0.57999999999999996, 1, 0, 1, 0, 0.25, 0, 0.67500000000000004}; siP->setColSolution(mycs); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); #endif OsiCuts cuts; // Test generateCuts method kccg.generateCuts(*siP,cuts); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); assert( eq(lpRelaxAfter, 2829.0597826086955) ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif assert( lpRelaxBefore < lpRelaxAfter ); // the CoinPackedVector p0033 is the optimal // IP solution to the miplib problem p0033 int objIndices[14] = { 0, 6, 7, 9, 13, 17, 18, 22, 24, 25, 26, 27, 28, 29 }; CoinPackedVector p0033(14,objIndices,1.0); // Sanity check const double * objective=siP->getObjCoefficients(); double ofv =0 ; int r; for (r=0; r<nCols; r++){ ofv=ofv + p0033[r]*objective[r]; } CoinRelFltEq eq; assert( eq(ofv,3089.0) ); int nRowCuts = cuts.sizeRowCuts(); OsiRowCut rcut; CoinPackedVector rpv; for (i=0; i<nRowCuts; i++){ rcut = cuts.rowCut(i); rpv = rcut.row(); double p0033Sum = (rpv*p0033).sum(); assert (p0033Sum <= rcut.ub() ); } delete siP; } // if a debug file is there then look at it { FILE * fp = fopen("knapsack.debug","r"); if (fp) { int ncol,nel; double up; int x = fscanf(fp,"%d %d %lg",&ncol,&nel,&up); if (x<=0) throw("bad fscanf"); printf("%d columns, %d elements, upper %g\n",ncol,nel,up); double * sol1 = new double[nel]; double * el1 = new double[nel]; int * col1 = new int[nel]; CoinBigIndex * start = new CoinBigIndex [ncol+1]; memset(start,0,ncol*sizeof(CoinBigIndex )); int * row = new int[nel]; int i; for (i=0;i<nel;i++) { x=fscanf(fp,"%d %lg %lg",col1+i,el1+i,sol1+i); if (x<=0) throw("bad fscanf"); printf("[%d, e=%g, v=%g] ",col1[i],el1[i],sol1[i]); start[col1[i]]=1; row[i]=0; } printf("\n"); // Setup OsiSolverInterface * siP = baseSiP->clone(); double lo=-1.0e30; double * upper = new double[ncol]; start[ncol]=nel; int last=0; for (i=0;i<ncol;i++) { upper[i]=1.0; int marked=start[i]; start[i]=last; if (marked) last++; } siP->loadProblem(ncol,1,start,row,el1,NULL,upper,NULL,&lo,&up); // use upper for solution memset(upper,0,ncol*sizeof(double)); for (i=0;i<nel;i++) { int icol=col1[i]; upper[icol]=sol1[i]; siP->setInteger(icol); } siP->setColSolution(upper); delete [] sol1; delete [] el1; delete [] col1; delete [] start; delete [] row; delete [] upper; CglKnapsackCover kccg; OsiCuts cuts; // Test generateCuts method kccg.generateCuts(*siP,cuts); // print out and compare to known cuts int numberCuts = cuts.sizeRowCuts(); if (numberCuts) { for (i=0;i<numberCuts;i++) { OsiRowCut * thisCut = cuts.rowCutPtr(i); int n=thisCut->row().getNumElements(); printf("Cut %d has %d entries, rhs %g %g =>",i,n,thisCut->lb(), thisCut->ub()); int j; const int * index = thisCut->row().getIndices(); const double * element = thisCut->row().getElements(); for (j=0;j<n;j++) { printf(" (%d,%g)",index[j],element[j]); } printf("\n"); } } fclose(fp); } } // Testcase /u/rlh/osl2/mps/p0201 // Miplib3 problem p0282 // Test that no cuts chop off the optimal ip solution { // Setup OsiSolverInterface * siP = baseSiP->clone(); std::string fn(mpsDir+"p0201"); siP->readMps(fn.c_str(),"mps"); // All integer variables should be binary. // Assert that this is true. for ( i = 0; i < siP->getNumCols(); i++ ) if ( siP->isInteger(i) ) assert(siP->getColUpper()[i]==1.0 && siP->isBinary(i)); const int nCols=siP->getNumCols(); CglKnapsackCover kccg; // Solve the LP relaxation of the model and // print out ofv for sake of comparisn siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, 6875.) ); double mycs[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; siP->setColSolution(mycs); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); #endif OsiCuts cuts; // Test generateCuts method kccg.generateCuts(*siP,cuts); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); assert( eq(lpRelaxAfter, 7125) ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif assert( lpRelaxBefore < lpRelaxAfter ); // Optimal IP solution to p0201 int objIndices[22] = { 8, 10, 21, 38, 39, 56, 60, 74, 79, 92, 94, 110, 111, 128, 132, 146, 151,164, 166, 182,183, 200 }; CoinPackedVector p0201(22,objIndices,1.0); // Sanity check const double * objective=siP->getObjCoefficients(); double ofv =0 ; int r; for (r=0; r<nCols; r++){ ofv=ofv + p0201[r]*objective[r]; } CoinRelFltEq eq; assert( eq(ofv,7615.0) ); //printf("p0201 optimal ofv = %g\n",ofv); int nRowCuts = cuts.sizeRowCuts(); OsiRowCut rcut; CoinPackedVector rpv; for (i=0; i<nRowCuts; i++){ rcut = cuts.rowCut(i); rpv = rcut.row(); double p0201Sum = (rpv*p0201).sum(); assert (p0201Sum <= rcut.ub() ); } delete siP; } // see if I get the same covers that N&W get { OsiSolverInterface * siP=baseSiP->clone(); std::string fn(mpsDir+"nw460"); siP->readMps(fn.c_str(),"mps"); // All integer variables should be binary. // Assert that this is true. for ( i = 0; i < siP->getNumCols(); i++ ) if ( siP->isInteger(i) ) assert(siP->getColUpper()[i]==1.0 && siP->isBinary(i)); CglKnapsackCover kccg; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, -225.68951787852194) ); double mycs[] = {0.7099213482046447, 0, 0.34185802225477174, 1, 1, 0, 1, 1, 0}; siP->setColSolution(mycs); OsiCuts cuts; // Test generateCuts method kccg.generateCuts(*siP,cuts); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); assert( eq(lpRelaxAfter, -176) ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif #ifdef MJS assert( lpRelaxBefore < lpRelaxAfter ); #endif int nRowCuts = cuts.sizeRowCuts(); OsiRowCut rcut; CoinPackedVector rpv; for (i=0; i<nRowCuts; i++){ rcut = cuts.rowCut(i); rpv = rcut.row(); int j; printf("Row cut number %i has rhs = %g\n",i,rcut.ub()); for (j=0; j<rpv.getNumElements(); j++){ printf("index %i, element %g\n", rpv.getIndices()[j], rpv.getElements()[j]); } printf("\n"); } delete siP; } // Debugging: try "exmip1.mps" { // Setup OsiSolverInterface * siP = baseSiP->clone(); std::string fn(mpsDir+"exmip1"); siP->readMps(fn.c_str(),"mps"); // All integer variables should be binary. // Assert that this is true. for ( i = 0; i < siP->getNumCols(); i++ ) if ( siP->isInteger(i) ) assert(siP->getColUpper()[i]==1.0 && siP->isBinary(i)); CglKnapsackCover kccg; // Solve the LP relaxation of the model and // print out ofv for sake of comparison siP->initialSolve(); double lpRelaxBefore=siP->getObjValue(); assert( eq(lpRelaxBefore, 3.2368421052631575) ); double mycs[] = {2.5, 0, 0, 0.6428571428571429, 0.5, 4, 0, 0.26315789473684253}; siP->setColSolution(mycs); // Test generateCuts method OsiCuts cuts; kccg.generateCuts(*siP,cuts); OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts); siP->resolve(); double lpRelaxAfter=siP->getObjValue(); assert( eq(lpRelaxAfter, 3.2368421052631575) ); #ifdef CGL_DEBUG printf("\n\nOrig LP min=%f\n",lpRelaxBefore); printf("\n\nFinal LP min=%f\n",lpRelaxAfter); #endif assert( lpRelaxBefore <= lpRelaxAfter ); delete siP; } #ifdef CGL_DEBUG // See what findLPMostViolatedMinCover for knapsack with 2 elements does { int nCols = 2; int row = 1; CoinPackedVector krow; double e[2] = {5,10}; int ii[2] = {0,1}; krow.setVector(nCols,ii,e); double b=11; double xstar[2] = {.2,.9}; CoinPackedVector cover; CoinPackedVector remainder; CglKnapsackCover kccg; kccg.findLPMostViolatedMinCover(nCols, row, krow, b, xstar, cover, remainder); printf("num in cover = %i\n",cover.getNumElements()); int j; for (j=0; j<cover.getNumElements(); j++){ printf(" index %i element % g\n", cover.getIndices()[j], cover.getElements()[j]); } } #endif #ifdef CGL_DEBUG // see what findLPMostViolatedMinCover does { int nCols = 5; int row = 1; CoinPackedVector krow; double e[5] = {1,1,1,1,10}; int ii[5] = {0,1,2,3,4}; krow.setVector(nCols,ii,e); double b=11; double xstar[5] = {.9,.9,1,1,.1}; CoinPackedVector cover; CoinPackedVector remainder; CglKnapsackCover kccg; kccg.findLPMostViolatedMinCover(nCols, row, krow, b, xstar, cover, remainder); printf("num in cover = %i\n",cover.getNumElements()); int j; for (j=0; j<cover.getNumElements(); j++){ printf(" index %i element % g\n", cover.getIndices()[j], cover.getElements()[j]); } } #endif }