// Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. #ifndef OsiColCut_H #define OsiColCut_H #include #include "CoinPackedVector.hpp" #include "OsiCollections.hpp" #include "OsiCut.hpp" /** Column Cut Class Column Cut Class has: */ class OsiColCut : public OsiCut { friend void OsiColCutUnitTest(const OsiSolverInterface * baseSiP, const std::string & mpsDir); public: //---------------------------------------------------------------- /**@name Setting column bounds */ //@{ /// Set column lower bounds inline void setLbs( int nElements, const int * colIndices, const double * lbElements ); /// Set column lower bounds from a packed vector inline void setLbs( const CoinPackedVector & lbs ); /// Set column upper bounds inline void setUbs( int nElements, const int * colIndices, const double * ubElements ); /// Set column upper bounds from a packed vector inline void setUbs( const CoinPackedVector & ubs ); //@} //---------------------------------------------------------------- /**@name Getting column bounds */ //@{ /// Get column lower bounds inline const CoinPackedVector & lbs() const; /// Get column upper bounds inline const CoinPackedVector & ubs() const; //@} /**@name Comparison operators */ //@{ #if __GNUC__ != 2 using OsiCut::operator== ; #endif /** equal - true if lower bounds, upper bounds, and OsiCut are equal. */ inline virtual bool operator==(const OsiColCut& rhs) const; #if __GNUC__ != 2 using OsiCut::operator!= ; #endif /// not equal inline virtual bool operator!=(const OsiColCut& rhs) const; //@} //---------------------------------------------------------------- /**@name Sanity checks on cut */ //@{ /** Returns true if the cut is consistent with respect to itself. This checks to ensure that: */ inline virtual bool consistent() const; /** Returns true if cut is consistent with respect to the solver interface's model. This checks to ensure that the lower & upperbound packed vectors: */ inline virtual bool consistent(const OsiSolverInterface& im) const; /** Returns true if the cut is infeasible with respect to its bounds and the column bounds in the solver interface's models. This checks whether: */ inline virtual bool infeasible(const OsiSolverInterface &im) const; /** Returns infeasibility of the cut with respect to solution passed in i.e. is positive if cuts off that solution. solution is getNumCols() long.. */ virtual double violated(const double * solution) const; //@} //---------------------------------------------------------------- /**@name Constructors and destructors */ //@{ /// Assignment operator OsiColCut & operator=( const OsiColCut& rhs); /// Copy constructor OsiColCut ( const OsiColCut &); /// Default Constructor OsiColCut (); /// Clone virtual OsiColCut * clone() const; /// Destructor virtual ~OsiColCut (); //@} /**@name Debug stuff */ //@{ /// Print cuts in collection virtual void print() const; //@} private: /**@name Private member data */ //@{ /// Lower bounds CoinPackedVector lbs_; /// Upper bounds CoinPackedVector ubs_; //@} }; //------------------------------------------------------------------- // Set lower & upper bound vectors //------------------------------------------------------------------- void OsiColCut::setLbs( int size, const int * colIndices, const double * lbElements ) { lbs_.setVector(size,colIndices,lbElements); } // void OsiColCut::setUbs( int size, const int * colIndices, const double * ubElements ) { ubs_.setVector(size,colIndices,ubElements); } // void OsiColCut::setLbs( const CoinPackedVector & lbs ) { lbs_ = lbs; } // void OsiColCut::setUbs( const CoinPackedVector & ubs ) { ubs_ = ubs; } //------------------------------------------------------------------- // Get Column Lower Bounds and Column Upper Bounds //------------------------------------------------------------------- const CoinPackedVector & OsiColCut::lbs() const { return lbs_; } // const CoinPackedVector & OsiColCut::ubs() const { return ubs_; } //---------------------------------------------------------------- // == operator //------------------------------------------------------------------- bool OsiColCut::operator==( const OsiColCut& rhs) const { if ( this->OsiCut::operator!=(rhs) ) return false; if ( lbs() != rhs.lbs() ) return false; if ( ubs() != rhs.ubs() ) return false; return true; } // bool OsiColCut::operator!=( const OsiColCut& rhs) const { return !( (*this)==rhs ); } //---------------------------------------------------------------- // consistent & infeasible //------------------------------------------------------------------- bool OsiColCut::consistent() const { const CoinPackedVector & lb = lbs(); const CoinPackedVector & ub = ubs(); // Test for consistent cut. // Are packed vectors consistent? lb.duplicateIndex("consistent", "OsiColCut"); ub.duplicateIndex("consistent", "OsiColCut"); if ( lb.getMinIndex() < 0 ) return false; if ( ub.getMinIndex() < 0 ) return false; return true; } // bool OsiColCut::consistent(const OsiSolverInterface& im) const { const CoinPackedVector & lb = lbs(); const CoinPackedVector & ub = ubs(); // Test for consistent cut. if ( lb.getMaxIndex() >= im.getNumCols() ) return false; if ( ub.getMaxIndex() >= im.getNumCols() ) return false; return true; } #if 0 bool OsiColCut::feasible(const OsiSolverInterface &im) const { const double * oldColLb = im.getColLower(); const double * oldColUb = im.getColUpper(); const CoinPackedVector & cutLbs = lbs(); const CoinPackedVector & cutUbs = ubs(); int i; for ( i=0; i oldColLb[colIndx] ) newLb = cutLbs.elements()[i]; else newLb = oldColLb[colIndx]; double newUb = oldColUb[colIndx]; if ( cutUbs.indexExists(colIndx) ) if ( cutUbs[colIndx] < newUb ) newUb = cutUbs[colIndx]; if ( newLb > newUb ) return false; } for ( i=0; i newLb ) newLb = cutLbs[colIndx]; if ( newUb < newLb ) return false; } return true; } #endif bool OsiColCut::infeasible(const OsiSolverInterface &im) const { const double * oldColLb = im.getColLower(); const double * oldColUb = im.getColUpper(); const CoinPackedVector & cutLbs = lbs(); const CoinPackedVector & cutUbs = ubs(); int i; for ( i=0; i oldColLb[colIndx] ? cutLbs.getElements()[i] : oldColLb[colIndx]; double newUb = oldColUb[colIndx]; if ( cutUbs.isExistingIndex(colIndx) ) if ( cutUbs[colIndx] < newUb ) newUb = cutUbs[colIndx]; if ( newLb > newUb ) return true; } for ( i=0; i newLb ) newLb = cutLbs[colIndx]; if ( newUb < newLb ) return true; } return false; } //############################################################################# /** A function that tests the methods in the OsiColCut class. The only reason for it not to be a member method is that this way it doesn't have to be compiled into the library. And that's a gain, because the library should be compiled with optimization on, but this method should be compiled with debugging. */ void OsiColCutUnitTest(const OsiSolverInterface * baseSiP, const std::string & mpsDir); #endif