CoinWarmStartBasis *CoinPrePostsolveMatrix::getStatus () { int n = ncols_ ; int m = nrows_ ; CoinWarmStartBasis *wsb = new CoinWarmStartBasis() ; wsb->setSize(n,m) ; for (int j = 0 ; j < n ; j++) { CoinWarmStartBasis::Status statj = CoinWarmStartBasis::Status(getColumnStatus(j)) ; wsb->setStructStatus(j,statj) ; } for (int i = 0 ; i < m ; i++) { CoinWarmStartBasis::Status stati = CoinWarmStartBasis::Status(getRowStatus(i)) ; wsb->setArtifStatus(i,stati) ; } return (wsb) ; }
/* This version of presolve returns a pointer to a new presolved model. NULL if infeasible doStatus controls activities required to transform an existing solution to match the presolved problem. I'd (lh) argue that this should default to false, but to maintain previous behaviour it defaults to true. Really, this is only useful if you've already optimised before applying presolve and also want to work with the solution after presolve. I think that this is the less common case. The more common situation is to apply presolve before optimising. */ OsiSolverInterface * OsiPresolve::presolvedModel(OsiSolverInterface & si, double feasibilityTolerance, bool keepIntegers, int numberPasses, const char * prohibited, bool doStatus, const char * rowProhibited) { ncols_ = si.getNumCols(); nrows_ = si.getNumRows(); nelems_ = si.getNumElements(); numberPasses_ = numberPasses; double maxmin = si.getObjSense(); originalModel_ = &si; delete [] originalColumn_; originalColumn_ = new int[ncols_]; delete [] originalRow_; originalRow_ = new int[nrows_]; int i; for (i=0;i<ncols_;i++) originalColumn_[i]=i; for (i=0;i<nrows_;i++) originalRow_[i]=i; // result is 0 - okay, 1 infeasible, -1 go round again int result = -1; // User may have deleted - its their responsibility presolvedModel_=NULL; // Messages CoinMessages messages = CoinMessage(si.messages().language()); // Only go round 100 times even if integer preprocessing int totalPasses=100; while (result==-1) { // make new copy delete presolvedModel_; presolvedModel_ = si.clone(); totalPasses--; // drop integer information if wanted if (!keepIntegers) { int i; for (i=0;i<ncols_;i++) presolvedModel_->setContinuous(i); } CoinPresolveMatrix prob(ncols_, maxmin, presolvedModel_, nrows_, nelems_,doStatus,nonLinearValue_,prohibited, rowProhibited); // make sure row solution correct if (doStatus) { double *colels = prob.colels_; int *hrow = prob.hrow_; CoinBigIndex *mcstrt = prob.mcstrt_; int *hincol = prob.hincol_; int ncols = prob.ncols_; double * csol = prob.sol_; double * acts = prob.acts_; int nrows = prob.nrows_; int colx; memset(acts,0,nrows*sizeof(double)); for (colx = 0; colx < ncols; ++colx) { double solutionValue = csol[colx]; for (int i=mcstrt[colx]; i<mcstrt[colx]+hincol[colx]; ++i) { int row = hrow[i]; double coeff = colels[i]; acts[row] += solutionValue*coeff; } } } // move across feasibility tolerance prob.feasibilityTolerance_ = feasibilityTolerance; /* Do presolve. Allow for the possibility that presolve might be ineffective (i.e., we're feasible but no postsolve actions are queued. */ paction_ = presolve(&prob) ; result = 0 ; // Get rid of useful arrays prob.deleteStuff(); /* This we don't need to do unless presolve actually reduced the system. */ if (prob.status_==0&&paction_) { // Looks feasible but double check to see if anything slipped through int n = prob.ncols_; double * lo = prob.clo_; double * up = prob.cup_; int i; for (i=0;i<n;i++) { if (up[i]<lo[i]) { if (up[i]<lo[i]-1.0e-8) { // infeasible prob.status_=1; } else { up[i]=lo[i]; } } } n = prob.nrows_; lo = prob.rlo_; up = prob.rup_; for (i=0;i<n;i++) { if (up[i]<lo[i]) { if (up[i]<lo[i]-1.0e-8) { // infeasible prob.status_=1; } else { up[i]=lo[i]; } } } } /* If we're feasible, load the presolved system into the solver. Presumably we could skip model update and copying of status and solution if presolve took no action. */ if (prob.status_ == 0) { prob.update_model(presolvedModel_, nrows_, ncols_, nelems_); # if PRESOLVE_CONSISTENCY if (doStatus) { int basicCnt = 0 ; int basicColumns = 0; int i ; CoinPresolveMatrix::Status status ; for (i = 0 ; i < prob.ncols_ ; i++) { status = prob.getColumnStatus(i); if (status == CoinPrePostsolveMatrix::basic) basicColumns++ ; } basicCnt = basicColumns; for (i = 0 ; i < prob.nrows_ ; i++) { status = prob.getRowStatus(i); if (status == CoinPrePostsolveMatrix::basic) basicCnt++ ; } # if PRESOLVE_DEBUG presolve_check_nbasic(&prob) ; # endif if (basicCnt>prob.nrows_) { // Take out slacks double * acts = prob.acts_; double * rlo = prob.rlo_; double * rup = prob.rup_; double infinity = si.getInfinity(); for (i = 0 ; i < prob.nrows_ ; i++) { status = prob.getRowStatus(i); if (status == CoinPrePostsolveMatrix::basic) { basicCnt-- ; double down = acts[i]-rlo[i]; double up = rup[i]-acts[i]; if (CoinMin(up,down)<infinity) { if (down<=up) prob.setRowStatus(i,CoinPrePostsolveMatrix::atLowerBound); else prob.setRowStatus(i,CoinPrePostsolveMatrix::atUpperBound); } else { prob.setRowStatus(i,CoinPrePostsolveMatrix::isFree); } } if (basicCnt==prob.nrows_) break; } } } #endif /* Install the status and primal solution, if we've been carrying them along. The code that copies status is efficient but brittle. The current definitions for CoinWarmStartBasis::Status and CoinPrePostsolveMatrix::Status are in one-to-one correspondence. This code will fail if that ever changes. */ if (doStatus) { presolvedModel_->setColSolution(prob.sol_); CoinWarmStartBasis *basis = dynamic_cast<CoinWarmStartBasis *>(presolvedModel_->getEmptyWarmStart()); basis->resize(prob.nrows_,prob.ncols_); int i; for (i=0;i<prob.ncols_;i++) { CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getColumnStatus(i)); basis->setStructStatus(i,status); } for (i=0;i<prob.nrows_;i++) { CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getRowStatus(i)); basis->setArtifStatus(i,status); } presolvedModel_->setWarmStart(basis); delete basis ; delete [] prob.sol_; delete [] prob.acts_; delete [] prob.colstat_; prob.sol_=NULL; prob.acts_=NULL; prob.colstat_=NULL; } /* Copy original column and row information from the CoinPresolveMatrix object so it'll be available for postsolve. */ int ncolsNow = presolvedModel_->getNumCols(); memcpy(originalColumn_,prob.originalColumn_,ncolsNow*sizeof(int)); delete [] prob.originalColumn_; prob.originalColumn_=NULL; int nrowsNow = presolvedModel_->getNumRows(); memcpy(originalRow_,prob.originalRow_,nrowsNow*sizeof(int)); delete [] prob.originalRow_; prob.originalRow_=NULL; // now clean up integer variables. This can modify original { int numberChanges=0; const double * lower0 = originalModel_->getColLower(); const double * upper0 = originalModel_->getColUpper(); const double * lower = presolvedModel_->getColLower(); const double * upper = presolvedModel_->getColUpper(); for (i=0;i<ncolsNow;i++) { if (!presolvedModel_->isInteger(i)) continue; int iOriginal = originalColumn_[i]; double lowerValue0 = lower0[iOriginal]; double upperValue0 = upper0[iOriginal]; double lowerValue = ceil(lower[i]-1.0e-5); double upperValue = floor(upper[i]+1.0e-5); presolvedModel_->setColBounds(i,lowerValue,upperValue); if (lowerValue>upperValue) { numberChanges++; presolvedModel_->messageHandler()->message(COIN_PRESOLVE_COLINFEAS, messages) <<iOriginal <<lowerValue <<upperValue <<CoinMessageEol; result=1; } else { if (lowerValue>lowerValue0+1.0e-8) { originalModel_->setColLower(iOriginal,lowerValue); numberChanges++; } if (upperValue<upperValue0-1.0e-8) { originalModel_->setColUpper(iOriginal,upperValue); numberChanges++; } } } if (numberChanges) { presolvedModel_->messageHandler()->message(COIN_PRESOLVE_INTEGERMODS, messages) <<numberChanges <<CoinMessageEol; if (!result&&totalPasses>0&& // we can't go round again in integer if dupcols (prob.presolveOptions_ & 0x80000000) == 0) { result = -1; // round again const CoinPresolveAction *paction = paction_; while (paction) { const CoinPresolveAction *next = paction->next; delete paction; paction = next; } paction_=NULL; } } } } else if (prob.status_ != 0) { // infeasible or unbounded result = 1 ; } } if (!result) { int nrowsAfter = presolvedModel_->getNumRows(); int ncolsAfter = presolvedModel_->getNumCols(); CoinBigIndex nelsAfter = presolvedModel_->getNumElements(); presolvedModel_->messageHandler()->message(COIN_PRESOLVE_STATS, messages) <<nrowsAfter<< -(nrows_ - nrowsAfter) << ncolsAfter<< -(ncols_ - ncolsAfter) <<nelsAfter<< -(nelems_ - nelsAfter) <<CoinMessageEol; } else { gutsOfDestroy(); delete presolvedModel_; presolvedModel_=NULL; } return presolvedModel_; }
//-------------------------------------------------------------------------- // ** 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 OsiPresolve::postsolve(bool updateStatus) { // Messages CoinMessages messages = CoinMessage(presolvedModel_->messages().language()); if (!presolvedModel_->isProvenOptimal()) { presolvedModel_->messageHandler()->message(COIN_PRESOLVE_NONOPTIMAL, messages) <<CoinMessageEol; } // this is the size of the original problem const int ncols0 = ncols_; const int nrows0 = nrows_; const CoinBigIndex nelems0 = nelems_; // reality check assert(ncols0==originalModel_->getNumCols()); assert(nrows0==originalModel_->getNumRows()); // this is the reduced problem int ncols = presolvedModel_->getNumCols(); int nrows = presolvedModel_->getNumRows(); double *acts = new double [nrows0]; double *sol = new double [ncols0]; CoinZeroN(acts,nrows0); CoinZeroN(sol,ncols0); unsigned char * rowstat=NULL; unsigned char * colstat = NULL; CoinWarmStartBasis * presolvedBasis = dynamic_cast<CoinWarmStartBasis*>(presolvedModel_->getWarmStart()); if (!presolvedBasis) updateStatus=false; if (updateStatus) { colstat = new unsigned char[ncols0+nrows0]; # ifdef ZEROFAULT memset(colstat,0,((ncols0+nrows0)*sizeof(char))) ; # endif rowstat = colstat + ncols0; int i; for (i=0;i<ncols;i++) { colstat[i] = presolvedBasis->getStructStatus(i); } for (i=0;i<nrows;i++) { rowstat[i] = presolvedBasis->getArtifStatus(i); } } delete presolvedBasis; # if PRESOLVE_CONSISTENCY > 0 if (updateStatus) { int basicCnt = 0 ; int i ; for (i = 0 ; i < ncols ; i++) { if (colstat[i] == CoinWarmStartBasis::basic) basicCnt++ ; } for (i = 0 ; i < nrows ; i++) { if (rowstat[i] == CoinWarmStartBasis::basic) basicCnt++ ; } assert (basicCnt == nrows) ; } # endif /* Postsolve back to the original problem. The CoinPostsolveMatrix object assumes ownership of sol, acts, colstat, and rowstat. */ CoinPostsolveMatrix prob(presolvedModel_, ncols0, nrows0, nelems0, presolvedModel_->getObjSense(), sol, acts, colstat, rowstat); postsolve(prob); # if PRESOLVE_CONSISTENCY > 0 if (updateStatus) { int basicCnt = 0 ; int i ; for (i = 0 ; i < ncols0 ; i++) { if (prob.getColumnStatus(i) == CoinWarmStartBasis::basic) basicCnt++ ; } for (i = 0 ; i < nrows0 ; i++) { if (prob.getRowStatus(i) == CoinWarmStartBasis::basic) basicCnt++ ; } assert (basicCnt == nrows0) ; } # endif originalModel_->setColSolution(sol); if (updateStatus) { CoinWarmStartBasis *basis = dynamic_cast<CoinWarmStartBasis *>(presolvedModel_->getEmptyWarmStart()); basis->setSize(ncols0,nrows0); int i; for (i=0;i<ncols0;i++) { CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getColumnStatus(i)); /* FIXME: these asserts seem correct, but seem to reveal some bugs in CoinPresolve */ // assert(status != CoinWarmStartBasis::atLowerBound || originalModel_->getColLower()[i] > -originalModel_->getInfinity()); // assert(status != CoinWarmStartBasis::atUpperBound || originalModel_->getColUpper()[i] < originalModel_->getInfinity()); basis->setStructStatus(i,status); } for (i=0;i<nrows0;i++) { CoinWarmStartBasis::Status status = static_cast<CoinWarmStartBasis::Status> (prob.getRowStatus(i)); /* FIXME: these asserts seem correct, but seem to reveal some bugs in CoinPresolve */ // assert(status != CoinWarmStartBasis::atUpperBound || originalModel_->getRowLower()[i] > -originalModel_->getInfinity()); // assert(status != CoinWarmStartBasis::atLowerBound || originalModel_->getRowUpper()[i] < originalModel_->getInfinity()); basis->setArtifStatus(i,status); } originalModel_->setWarmStart(basis); delete basis ; } }
void OsiIF::_loadBasis( Array<LPVARSTAT::STATUS> &lpVarStat, Array<SlackStat::STATUS> &slackStat) { int lps = lpVarStat.size(); int sls = slackStat.size(); CoinWarmStartBasis *ws = nullptr; ws = new CoinWarmStartBasis(); ws->setSize(numCols_, numRows_); if (osiLP_->getNumCols() > lps) { Logger::ifout() << "OsiIF::_loadBasis: mismatch in number of columns: OSI " << osiLP_->getNumCols() << ", Abacus: " << lps << "\n"; OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf); } for (int i = 0; i < numCols_; i++) ws->setStructStatus(i, lpVarStat2osi(lpVarStat[i])); if (osiLP_->getNumRows() > sls) { Logger::ifout() << "OsiIF::_loadBasis: mismatch in number of rows: OSI " << osiLP_->getNumCols() << ", Abacus: " << sls << "\n"; OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf); } for (int i = 0; i < numRows_; i++) ws->setArtifStatus(i, slackStat2osi(slackStat[i])); lpSolverTime_.start(); slackStatus_ = basisStatus_ = Missing; int status = 0; // FIXME loadBasis // better test whether the number of basic structurals is correct? if (ws->numberBasicStructurals() > 0) { status = osiLP_->setWarmStart(dynamic_cast<CoinWarmStart *> (ws)); if (ws_ != nullptr) delete ws_; ws_ = dynamic_cast<CoinWarmStartBasis*> (osiLP_->getWarmStart()); if (ws_ != nullptr) { delete[] cStat_; int nStructBytes = (int) ceil( ws_->getNumStructural() / 4.0); cStat_ = new char[nStructBytes]; for(int i = 0; i < nStructBytes; i++) { cStat_[i] = ws_->getStructuralStatus()[i]; } delete[] rStat_; int nArtBytes = (int) ceil( ws_->getNumArtificial() / 4.0 ); rStat_ = new char[nArtBytes]; for(int i = 0; i < nArtBytes; i++) { rStat_[i] = ws_->getArtificialStatus()[i]; } basisStatus_ = Available; } else basisStatus_ = Missing; } else status = 2; lpSolverTime_.stop(); delete ws; if (status == 0) { Logger::ifout() << "OsiIF::_loadBasis(): loading the new basis has failed. Status " << status << endl; // FIXME loadBasis return; } else return; }