// Copyright (C) 2005, International Business Machines // Corporation and others. All Rights Reserved. #if defined(_MSC_VER) // Turn off compiler warning about long names # pragma warning(disable:4786) #endif #include "CoinHelperFunctions.hpp" #include "CoinWarmStartBasis.hpp" #include "OsiSolverInterface.hpp" #include "OsiSolverBranch.hpp" #include #include #include #include "CoinFinite.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiSolverBranch::OsiSolverBranch () : indices_(NULL), bound_(NULL) { memset(start_,0,sizeof(start_)); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiSolverBranch::OsiSolverBranch (const OsiSolverBranch & rhs) { memcpy(start_,rhs.start_,sizeof(start_)); int size = start_[4]; if (size) { indices_ = CoinCopyOfArray(rhs.indices_,size); bound_ = CoinCopyOfArray(rhs.bound_,size); } else { indices_=NULL; bound_=NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiSolverBranch::~OsiSolverBranch () { delete [] indices_; delete [] bound_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiSolverBranch & OsiSolverBranch::operator=(const OsiSolverBranch& rhs) { if (this != &rhs) { delete [] indices_; delete [] bound_; memcpy(start_,rhs.start_,sizeof(start_)); int size = start_[4]; if (size) { indices_ = CoinCopyOfArray(rhs.indices_,size); bound_ = CoinCopyOfArray(rhs.bound_,size); } else { indices_=NULL; bound_=NULL; } } return *this; } //----------------------------------------------------------------------------- // add simple branch //----------------------------------------------------------------------------- void OsiSolverBranch::addBranch(int iColumn, double value) { delete [] indices_; delete [] bound_; indices_ = new int[2]; bound_ = new double[2]; indices_[0]=iColumn; indices_[1]=iColumn; start_[0]=0; start_[1]=0; start_[2]=1; bound_[0]=floor(value); start_[3]=2; bound_[1]=ceil(value); start_[4]=2; assert (bound_[0]!=bound_[1]); } //----------------------------------------------------------------------------- // Add bounds - way =-1 is first , +1 is second //----------------------------------------------------------------------------- void OsiSolverBranch::addBranch(int way,int numberTighterLower, const int * whichLower, const double * newLower, int numberTighterUpper, const int * whichUpper, const double * newUpper) { assert (way==-1||way==1); int numberNew = numberTighterLower+numberTighterUpper; int base = way+1; // will be 0 or 2 int numberNow = start_[4-base]-start_[2-base]; int * tempI = new int[numberNow+numberNew]; double * tempD = new double[numberNow+numberNew]; int putNew = (way==-1) ? 0 : start_[2]; int putNow = (way==-1) ? numberNew : 0; memcpy(tempI+putNow,indices_+start_[2-base],numberNow*sizeof(int)); memcpy(tempD+putNow,bound_+start_[2-base],numberNow*sizeof(double)); memcpy(tempI+putNew,whichLower,numberTighterLower*sizeof(int)); memcpy(tempD+putNew,newLower,numberTighterLower*sizeof(double)); putNew += numberTighterLower; memcpy(tempI+putNew,whichUpper,numberTighterUpper*sizeof(int)); memcpy(tempD+putNew,newUpper,numberTighterUpper*sizeof(double)); delete [] indices_; indices_ = tempI; delete [] bound_; bound_ = tempD; int numberOldLower = start_[3-base]-start_[2-base]; int numberOldUpper = start_[4-base]-start_[3-base]; start_[0]=0; if (way==-1) { start_[1] = numberTighterLower; start_[2] = start_[1] + numberTighterUpper; start_[3] = start_[2] + numberOldLower; start_[4] = start_[3] + numberOldUpper; } else { start_[1] = numberOldLower; start_[2] = start_[1] + numberOldUpper; start_[3] = start_[2] + numberTighterLower; start_[4] = start_[3] + numberTighterUpper; } } //----------------------------------------------------------------------------- // Add bounds - way =-1 is first , +1 is second //----------------------------------------------------------------------------- void OsiSolverBranch::addBranch(int way,int numberColumns, const double * oldLower, const double * newLower2, const double * oldUpper, const double * newUpper2) { assert (way==-1||way==1); // find int i; int * whichLower = new int[numberColumns]; double * newLower = new double[numberColumns]; int numberTighterLower=0; for (i=0;ioldLower[i]) { whichLower[numberTighterLower]=i; newLower[numberTighterLower++]=newLower2[i]; } } int * whichUpper = new int[numberColumns]; double * newUpper = new double[numberColumns]; int numberTighterUpper=0; for (i=0;ivalue+primalTolerance) { feasible=false; break; } } else { abort(); // do later (other stuff messed up anyway - e.g. CBC) } } if (feasible) break; // OK this way } return feasible; } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiSolverResult::OsiSolverResult () : objectiveValue_(COIN_DBL_MAX), primalSolution_(NULL), dualSolution_(NULL) { } //------------------------------------------------------------------- // Constructor from solver //------------------------------------------------------------------- OsiSolverResult::OsiSolverResult (const OsiSolverInterface & solver,const double * lowerBefore, const double * upperBefore) : objectiveValue_(COIN_DBL_MAX), primalSolution_(NULL), dualSolution_(NULL) { if (solver.isProvenOptimal()&&!solver.isDualObjectiveLimitReached()) { objectiveValue_ = solver.getObjValue()*solver.getObjSense(); CoinWarmStartBasis * basis = dynamic_cast (solver.getWarmStart()); assert (basis); basis_ = * basis; delete basis; int numberRows = basis_.getNumArtificial(); int numberColumns = basis_.getNumStructural(); assert (numberColumns==solver.getNumCols()); assert (numberRows==solver.getNumRows()); primalSolution_ = CoinCopyOfArray(solver.getColSolution(),numberColumns); dualSolution_ = CoinCopyOfArray(solver.getRowPrice(),numberRows); fixed_.addBranch(-1,numberColumns,lowerBefore,solver.getColLower(), upperBefore,solver.getColUpper()); } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiSolverResult::OsiSolverResult (const OsiSolverResult & rhs) { objectiveValue_ = rhs.objectiveValue_; basis_ = rhs.basis_; fixed_ = rhs.fixed_; int numberRows = basis_.getNumArtificial(); int numberColumns = basis_.getNumStructural(); if (numberColumns) { primalSolution_ = CoinCopyOfArray(rhs.primalSolution_,numberColumns); dualSolution_ = CoinCopyOfArray(rhs.dualSolution_,numberRows); } else { primalSolution_=NULL; dualSolution_=NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiSolverResult::~OsiSolverResult () { delete [] primalSolution_; delete [] dualSolution_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiSolverResult & OsiSolverResult::operator=(const OsiSolverResult& rhs) { if (this != &rhs) { delete [] primalSolution_; delete [] dualSolution_; objectiveValue_ = rhs.objectiveValue_; basis_ = rhs.basis_; fixed_ = rhs.fixed_; int numberRows = basis_.getNumArtificial(); int numberColumns = basis_.getNumStructural(); if (numberColumns) { primalSolution_ = CoinCopyOfArray(rhs.primalSolution_,numberColumns); dualSolution_ = CoinCopyOfArray(rhs.dualSolution_,numberRows); } else { primalSolution_=NULL; dualSolution_=NULL; } } return *this; } // Create result void OsiSolverResult::createResult(const OsiSolverInterface & solver, const double * lowerBefore, const double * upperBefore) { delete [] primalSolution_; delete [] dualSolution_; if (solver.isProvenOptimal()&&!solver.isDualObjectiveLimitReached()) { objectiveValue_ = solver.getObjValue()*solver.getObjSense(); CoinWarmStartBasis * basis = dynamic_cast (solver.getWarmStart()); assert (basis); basis_ = * basis; int numberRows = basis_.getNumArtificial(); int numberColumns = basis_.getNumStructural(); assert (numberColumns==solver.getNumCols()); assert (numberRows==solver.getNumRows()); primalSolution_ = CoinCopyOfArray(solver.getColSolution(),numberColumns); dualSolution_ = CoinCopyOfArray(solver.getRowPrice(),numberRows); fixed_.addBranch(-1,numberColumns,lowerBefore,solver.getColLower(), upperBefore,solver.getColUpper()); } else { // infeasible objectiveValue_ = COIN_DBL_MAX; basis_ = CoinWarmStartBasis();; primalSolution_=NULL; dualSolution_=NULL; } } // Restore result void OsiSolverResult::restoreResult(OsiSolverInterface & solver) const { //solver.setObjValue(objectiveValue_)*solver.getObjSense(); solver.setWarmStart(&basis_); solver.setColSolution(primalSolution_); solver.setRowPrice(dualSolution_); fixed_.applyBounds(solver,-1); }