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) ; }
/** Create a set of candidate branching objects. */ int BlisBranchStrategyPseudo::createCandBranchObjects(int numPassesLeft, double ub) { int bStatus = 0; int i, pass, colInd; int preferDir, saveLimit; int numFirsts = 0; int numInfs = 0; int minCount = 0; int numLowerTightens = 0; int numUpperTightens = 0; double lpX, score, infeasibility, downDeg, upDeg, sumDeg = 0.0; bool roundAgain, downKeep, downGood, upKeep, upGood; int *lbInd = NULL; int *ubInd = NULL; double *newLB = NULL; double *newUB = NULL; double *saveUpper = NULL; double *saveLower = NULL; double *saveSolution = NULL; BlisModel *model = dynamic_cast<BlisModel *>(model_); OsiSolverInterface *solver = model->solver(); int numCols = model->getNumCols(); int numObjects = model->numObjects(); int aveIterations = model->getAveIterations(); //std::cout << "aveIterations = " << aveIterations << std::endl; //------------------------------------------------------ // Check if max time is reached or no pass is left. //------------------------------------------------------ double timeLimit = model->AlpsPar()->entry(AlpsParams::timeLimit); AlpsKnowledgeBroker *broker = model->getKnowledgeBroker(); bool maxTimeReached = (broker->timer().getTime() > timeLimit); bool selectNow = false; if (maxTimeReached || !numPassesLeft) { selectNow = true; #ifdef BLIS_DEBUG printf("PSEUDO: CREATE: maxTimeReached %d, numPassesLeft %d\n", maxTimeReached, numPassesLeft); #endif } // Store first time objects. std::vector<BlisObjectInt *> firstObjects; // Store infeasible objects. std::vector<BlisObjectInt *> infObjects; // TODO: check if sorting is expensive. std::multimap<double, BcpsBranchObject*, BlisPseuoGreater> candObjects; double objValue = solver->getObjSense() * solver->getObjValue(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); saveSolution = new double[numCols]; memcpy(saveSolution, solver->getColSolution(), numCols*sizeof(double)); //-------------------------------------------------- // Find the infeasible objects. // NOTE: we might go round this loop twice if we are feed in // a "feasible" solution. //-------------------------------------------------- for (pass = 0; pass < 2; ++pass) { numInfs = 0; BcpsObject * object = NULL; BlisObjectInt * intObject = NULL; infObjects.clear(); firstObjects.clear(); for (i = 0; i < numObjects; ++i) { object = model->objects(i); infeasibility = object->infeasibility(model, preferDir); if (infeasibility) { ++numInfs; intObject = dynamic_cast<BlisObjectInt *>(object); if (intObject) { infObjects.push_back(intObject); if (!selectNow) { minCount = ALPS_MIN(intObject->pseudocost().getDownCount(), intObject->pseudocost().getUpCount()); if (minCount < 1) { firstObjects.push_back(intObject); } } #ifdef BLIS_DEBUG if (intObject->columnIndex() == 40) { std::cout << "x[40] = " << saveSolution[40] << std::endl; } #endif intObject = NULL; } else { // TODO: currently all are integer objects. #ifdef BLIS_DEBU assert(0); #endif } } } if (numInfs) { #if 0 std::cout << "PSEUDO: numInfs = " << numInfs << std::endl; #endif break; } else if (pass == 0) { // The first pass and is IP feasible. #if 1 std::cout << "ERROR: PSEUDO: given a integer feasible sol, no fraction variable" << std::endl; assert(0); #endif roundAgain = false; CoinWarmStartBasis * ws = dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart()); if (!ws) break; // Force solution values within bounds for (i = 0; i < numCols; ++i) { lpX = saveSolution[i]; if (lpX < lower[i]) { saveSolution[i] = lower[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound); } else if (lpX > upper[i]) { saveSolution[i] = upper[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound); } } if (roundAgain) { // Need resolve and do the second round selection. solver->setWarmStart(ws); delete ws; // Resolve. solver->resolve(); if (!solver->isProvenOptimal()) { // Become infeasible, can do nothing. bStatus = -2; goto TERM_CREATE; } else { // Save new lp solution. memcpy(saveSolution, solver->getColSolution(), numCols * sizeof(double)); objValue = solver->getObjSense() * solver->getObjValue(); } } else { delete ws; break; } } } // EOF 2 pass //-------------------------------------------------- // If we have a set of first time object, // branch up and down to initialize pseudo-cost. //-------------------------------------------------- numFirsts = static_cast<int> (firstObjects.size()); //std::cout << "PSEUDO: numFirsts = " << numFirsts << std::endl; if (numFirsts > 0) { //std::cout << "PSEUDO: numFirsts = " << numFirsts << std::endl; //-------------------------------------------------- // Backup solver status and mark hot start. //-------------------------------------------------- saveLower = new double[numCols]; saveUpper = new double[numCols]; memcpy(saveLower, lower, numCols * sizeof(double)); memcpy(saveUpper, upper, numCols * sizeof(double)); CoinWarmStart * ws = solver->getWarmStart(); solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); aveIterations = ALPS_MIN(50, aveIterations); solver->setIntParam(OsiMaxNumIterationHotStart, aveIterations); solver->markHotStart(); lbInd = new int [numFirsts]; ubInd = new int [numFirsts]; newLB = new double [numFirsts]; newUB = new double [numFirsts]; for (i = 0; i < numFirsts && bStatus != -2; ++i) { colInd = firstObjects[i]->columnIndex(); lpX = saveSolution[colInd]; BlisStrongBranch(model, objValue, colInd, lpX, saveLower, saveUpper, downKeep, downGood, downDeg, upKeep, upGood, upDeg); if(!downKeep && !upKeep) { // Both branch can be fathomed bStatus = -2; } else if (!downKeep) { // Down branch can be fathomed. lbInd[numLowerTightens] = colInd; newLB[numLowerTightens++] = ceil(lpX); } else if (!upKeep) { // Up branch can be fathomed. ubInd[numUpperTightens] = colInd; newUB[numUpperTightens++] = floor(lpX); } } //-------------------------------------------------- // Set new bounds in lp solver for resolving //-------------------------------------------------- if (bStatus != -2) { if (numUpperTightens > 0) { bStatus = -1; for (i = 0; i < numUpperTightens; ++i) { solver->setColUpper(ubInd[i], newUB[i]); } } if (numLowerTightens > 0) { bStatus = -1; for (i = 0; i < numLowerTightens; ++i) { solver->setColLower(lbInd[i], newLB[i]); } } } //-------------------------------------------------- // Unmark hotstart and recover LP solver. //-------------------------------------------------- solver->unmarkHotStart(); solver->setColSolution(saveSolution); solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); solver->setWarmStart(ws); delete ws; } if (bStatus < 0) { goto TERM_CREATE; } else { // Create a set of candidate branching objects. numBranchObjects_ = numInfs; branchObjects_ = new BcpsBranchObject* [numInfs]; // NOTE: it set model->savedLpSolution. sumDeg = 0.0; for (i = 0; i < numInfs; ++i) { if (infObjects[i]->pseudocost().getUpCost() < infObjects[i]->pseudocost().getDownCost()) { preferDir = 1; } else { preferDir = -1; } branchObjects_[i] = infObjects[i]->createBranchObject(model, preferDir); score = infObjects[i]->pseudocost().getScore(); branchObjects_[i]->setUpScore(score); sumDeg += score; #ifdef BLIS_DEBUG_MORE std::cout << "col[" << infObjects[i]->columnIndex() << "]: score=" << score << ", dir=" << branchObjects_[i]->getDirection() << ", up=" << infObjects[i]->pseudocost().getUpCost() << ", down=" << infObjects[i]->pseudocost().getDownCost() << std::endl; #endif } model->setSolEstimate(objValue + sumDeg); } TERM_CREATE: //------------------------------------------------------ // Cleanup. //------------------------------------------------------ delete [] lbInd; delete [] ubInd; delete [] newLB; delete [] newUB; delete [] saveSolution; delete [] saveLower; delete [] saveUpper; return bStatus; }
/* 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_; }
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 ; } }
/** Create a set of candidate branching objects. */ int BlisBranchStrategyRel::createCandBranchObjects(int numPassesLeft) { int bStatus = 0; int i, pass, colInd; int preferDir, saveLimit; int numFirsts = 0; int numInfs = 0; int minCount = 0; int numLowerTightens = 0; int numUpperTightens = 0; double lpX, score, infeasibility, downDeg, upDeg, sumDeg = 0.0; bool roundAgain, downKeep, downGood, upKeep, upGood; int *lbInd = NULL; int *ubInd = NULL; double *newLB = NULL; double *newUB = NULL; double * saveUpper = NULL; double * saveLower = NULL; double * saveSolution = NULL; BlisModel *model = dynamic_cast<BlisModel *>(model_); OsiSolverInterface * solver = model->solver(); int numCols = model->getNumCols(); int numObjects = model->numObjects(); //int lookAhead = dynamic_cast<BlisParams*> // (model->blisPar())->entry(BlisParams::lookAhead); //------------------------------------------------------ // Check if max time is reached or no pass is left. //------------------------------------------------------ double timeLimit = model->AlpsPar()->entry(AlpsParams::timeLimit); bool maxTimeReached = (CoinCpuTime() - model->startTime_ > timeLimit); bool selectNow = false; if (maxTimeReached || !numPassesLeft) { selectNow = true; #ifdef BLIS_DEBUG printf("REL: CREATE: maxTimeReached %d, numPassesLeft %d\n", maxTimeReached, numPassesLeft); #endif } // Store first time objects. std::vector<BlisObjectInt *> firstObjects; // Store infeasible objects. std::vector<BlisObjectInt *> infObjects; // TODO: check if sorting is expensive. std::multimap<double, BlisObjectInt*, BlisPseuoGreater> sortedObjects; double objValue = solver->getObjSense() * solver->getObjValue(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); int lookAhead = dynamic_cast<BlisParams*> (model->BlisPar())->entry(BlisParams::lookAhead); BlisObjectInt * intObject = NULL; //------------------------------------------------------ // Backup solver status and mark hot start. //----------------------------------------------------- saveSolution = new double[numCols]; memcpy(saveSolution, solver->getColSolution(), numCols*sizeof(double)); saveLower = new double[numCols]; saveUpper = new double[numCols]; memcpy(saveLower, lower, numCols * sizeof(double)); memcpy(saveUpper, upper, numCols * sizeof(double)); //------------------------------------------------------ // Find the infeasible objects. // NOTE: we might go round this loop twice if we are feed in // a "feasible" solution. //------------------------------------------------------ for (pass = 0; pass < 2; ++pass) { numInfs = 0; BcpsObject * object = NULL; infObjects.clear(); firstObjects.clear(); for (i = 0; i < numObjects; ++i) { object = model->objects(i); infeasibility = object->infeasibility(model, preferDir); if (infeasibility) { ++numInfs; intObject = dynamic_cast<BlisObjectInt *>(object); if (intObject) { //score = object->pseudocost().getScore(); //tempBO = object->createBranchObject(model, preferDir); //candObjects.insert(std::make_pair(score, tempBO)); //tempBO = NULL; infObjects.push_back(intObject); if (!selectNow) { minCount = ALPS_MIN(intObject->pseudocost().getDownCount(), intObject->pseudocost().getUpCount()); if (minCount < 1) { firstObjects.push_back(intObject); } } #ifdef BLIS_DEBUG_MORE if (intObject->columnIndex() == 15) { std::cout << "x[15] = " << saveSolution[15] << std::endl; } #endif intObject = NULL; } else { // TODO: currently all are integer objects. #ifdef BLIS_DEBU assert(0); #endif } } } if (numInfs) { #ifdef BLIS_DEBUG_MORE std::cout << "REL: numInfs = " << numInfs << std::endl; #endif break; } else if (pass == 0) { // The first pass and is IP feasible. #ifdef BLIS_DEBUG std::cout << "REL: given a feasible sol" << std::endl; #endif roundAgain = false; CoinWarmStartBasis * ws = dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart()); if (!ws) break; // Force solution values within bounds for (i = 0; i < numCols; ++i) { lpX = saveSolution[i]; if (lpX < lower[i]) { saveSolution[i] = lower[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound); } else if (lpX > upper[i]) { saveSolution[i] = upper[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound); } } if (roundAgain) { // Need resolve and do the second round selection. solver->setWarmStart(ws); delete ws; // Resolve. solver->resolve(); if (!solver->isProvenOptimal()) { // Become infeasible, can do nothing. bStatus = -2; goto TERM_CREATE; } else { // Save new lp solution. memcpy(saveSolution, solver->getColSolution(), numCols * sizeof(double)); objValue = solver->getObjSense() * solver->getObjValue(); } } else { delete ws; break; } } } // EOF 2 pass //-------------------------------------------------- // If we have a set of first time object, // branch up and down to initialize pseudo-cost. //-------------------------------------------------- numFirsts = static_cast<int> (firstObjects.size()); if (numFirsts > 0) { CoinWarmStart * ws = solver->getWarmStart(); solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); int maxIter = ALPS_MAX(model->getAveIterations(), 50); solver->setIntParam(OsiMaxNumIterationHotStart, maxIter); solver->markHotStart(); lbInd = new int [numFirsts]; ubInd = new int [numFirsts]; newLB = new double [numFirsts]; newUB = new double [numFirsts]; for (i = 0; i < numFirsts && bStatus != -2; ++i) { colInd = firstObjects[i]->columnIndex(); lpX = saveSolution[colInd]; BlisStrongBranch(model, objValue, colInd, lpX, saveLower, saveUpper, downKeep, downGood, downDeg, upKeep, upGood, upDeg); if(!downKeep && !upKeep) { // Both branch can be fathomed bStatus = -2; } else if (!downKeep) { // Down branch can be fathomed. lbInd[numLowerTightens] = colInd; newLB[numLowerTightens++] = ceil(lpX); //break; } else if (!upKeep) { // Up branch can be fathomed. ubInd[numUpperTightens] = colInd; newUB[numUpperTightens++] = floor(lpX); // break; } // Update pseudocost. if(downGood) { firstObjects[i]->pseudocost().update(-1, downDeg, lpX); } if(downGood) { firstObjects[i]->pseudocost().update(1, upDeg, lpX); } } //-------------------------------------------------- // Set new bounds in lp solver for resolving //-------------------------------------------------- if (bStatus != -2) { if (numUpperTightens > 0) { bStatus = -1; for (i = 0; i < numUpperTightens; ++i) { solver->setColUpper(ubInd[i], newUB[i]); } } if (numLowerTightens > 0) { bStatus = -1; for (i = 0; i < numLowerTightens; ++i) { solver->setColLower(lbInd[i], newLB[i]); } } } //-------------------------------------------------- // Unmark hotstart and recover LP solver. //-------------------------------------------------- solver->unmarkHotStart(); solver->setColSolution(saveSolution); solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); solver->setWarmStart(ws); delete ws; } //std::cout << "REL: bStatus = " << bStatus << std::endl; if (bStatus < 0) { // Infeasible or monotone. goto TERM_CREATE; } else { // All object's pseudocost have been initialized. // Sort them, and do strong branch for the unreliable one // NOTE: it set model->savedLpSolution. // model->feasibleSolution(numIntegerInfs, numObjectInfs); sumDeg = 0.0; for (i = 0; i < numInfs; ++i) { score = infObjects[i]->pseudocost().getScore(); sumDeg += score; std::pair<const double, BlisObjectInt*> sa(score, infObjects[i]); sortedObjects.insert(sa); #ifdef BLIS_DEBUG_MORE std::cout << "col[" << infObjects[i]->columnIndex() << "]=" << score << ", "<< std::endl; #endif } int numNotChange = 0; std::multimap< double, BlisObjectInt*, BlisPseuoGreater >::iterator pos; CoinWarmStart * ws = solver->getWarmStart(); solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); int maxIter = ALPS_MAX(model->getAveIterations(), 50); solver->setIntParam(OsiMaxNumIterationHotStart, maxIter); solver->markHotStart(); BlisObjectInt *bestObject = NULL; double bestScore = -10.0; for (pos = sortedObjects.begin(); pos != sortedObjects.end(); ++pos) { intObject = pos->second; colInd = intObject->columnIndex(); #ifdef BLIS_DEBUG_MORE std::cout << "col[" << colInd << "]: " << "score=" << pos->first << ", upCount=" << intObject->pseudocost().getUpCount() <<", downCount="<< intObject->pseudocost().getDownCount() << std::endl; #endif // Check if reliable. int objRelibility=ALPS_MIN(intObject->pseudocost().getUpCount(), intObject->pseudocost().getDownCount()); if (objRelibility < relibility_) { // Unrelible object. Do strong branching. lpX = saveSolution[colInd]; BlisStrongBranch(model, objValue, colInd, lpX, saveLower, saveUpper, downKeep, downGood, downDeg, upKeep, upGood, upDeg); // Update pseudocost. if(downGood) { intObject->pseudocost().update(-1, downDeg, lpX); } if(downGood) { intObject->pseudocost().update(1, upDeg, lpX); } } // Compare with the best. if (intObject->pseudocost().getScore() > bestScore) { bestScore = intObject->pseudocost().getScore(); bestObject = intObject; // Reset numNotChange = 0; } else { // If best doesn't change for "lookAhead" comparisons, then // the best is reliable. if (++numNotChange > lookAhead) { if (bestObject->pseudocost().getUpCost() > bestObject->pseudocost().getDownCost()) { preferDir = 1; } else { preferDir = -1; } break; } } } solver->unmarkHotStart(); solver->setColSolution(saveSolution); solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); solver->setWarmStart(ws); delete ws; model->setSolEstimate(objValue + sumDeg); assert(bestObject != NULL); bestBranchObject_ = bestObject->createBranchObject(model, preferDir); } TERM_CREATE: //------------------------------------------------------ // Cleanup. //------------------------------------------------------ delete [] lbInd; delete [] ubInd; delete [] newLB; delete [] newUB; delete [] saveSolution; delete [] saveLower; delete [] saveUpper; return bStatus; }
//-------------------------------------------------------------------------- // ** 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 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; }