limp-cbc-0.3.2.0: cbits/coin/OsiColCut.hpp
// Copyright (C) 2000, International Business Machines
// Corporation and others. All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).
#ifndef OsiColCut_H
#define OsiColCut_H
#include <string>
#include "CoinPackedVector.hpp"
#include "OsiCollections.hpp"
#include "OsiCut.hpp"
/** Column Cut Class
Column Cut Class has:
<ul>
<li>a sparse vector of column lower bounds
<li>a sparse vector of column upper bounds
</ul>
*/
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:
<ul>
<li>The bound vectors do not have duplicate indices,
<li>The bound vectors indices are >=0
</ul>
*/
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:
<ul>
<li>do not have an index >= the number of column is the model.
</ul>
*/
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:
<ul>
<li>the maximum of the new and existing lower bounds is strictly
greater than the minimum of the new and existing upper bounds.
</ul>
*/
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<cutLbs.size(); i++ ) {
int colIndx = cutLbs.indices()[i];
double newLb;
if ( cutLbs.elements()[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<cutUbs.size(); i++ ) {
int colIndx = cutUbs.indices()[i];
double newUb = cutUbs.elements()[i] < oldColUb[colIndx] ? cutUbs.elements()[i] : oldColUb[colIndx];
double newLb = oldColLb[colIndx];
if ( cutLbs.indexExists(colIndx) )
if ( cutLbs[colIndx] > 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<cutLbs.getNumElements(); i++ ) {
int colIndx = cutLbs.getIndices()[i];
double newLb= cutLbs.getElements()[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<cutUbs.getNumElements(); i++ ) {
int colIndx = cutUbs.getIndices()[i];
double newUb = cutUbs.getElements()[i] < oldColUb[colIndx] ?
cutUbs.getElements()[i] : oldColUb[colIndx];
double newLb = oldColLb[colIndx];
if ( cutLbs.isExistingIndex(colIndx) )
if ( cutLbs[colIndx] > newLb ) newLb = cutLbs[colIndx];
if ( newUb < newLb )
return true;
}
return false;
}
#endif