// Copyright (C) 2000, International Business Machines
// Corporation and others. All Rights Reserved.
#ifndef OsiRowCut_H
#define OsiRowCut_H
#include "CoinPackedVector.hpp"
#include "OsiCollections.hpp"
#include "OsiCut.hpp"
//#define OSI_INLINE_ROWCUT_METHODS
#ifdef OSI_INLINE_ROWCUT_METHODS
#define OsiRowCut_inline inline
#else
#define OsiRowCut_inline
#endif
/** Row Cut Class
A row cut has:
- a lower bound
- an upper bound
- a vector of row elements
*/
class OsiRowCut : public OsiCut {
friend void OsiRowCutUnitTest(const OsiSolverInterface * baseSiP,
const std::string & mpsDir);
public:
/**@name Row bounds */
//@{
/// Get lower bound
OsiRowCut_inline double lb() const;
/// Set lower bound
OsiRowCut_inline void setLb(double lb);
/// Get upper bound
OsiRowCut_inline double ub() const;
/// Set upper bound
OsiRowCut_inline void setUb(double ub);
//@}
/**@name Row rhs, sense, range */
//@{
/// Get sense ('E', 'G', 'L', 'N', 'R')
char sense() const;
/// Get right-hand side
double rhs() const;
/// Get range (ub - lb for 'R' rows, 0 otherwise)
double range() const;
//@}
//-------------------------------------------------------------------
/**@name Row elements */
//@{
/// Set row elements
OsiRowCut_inline void setRow(
int size,
const int * colIndices,
const double * elements );
/// Set row elements from a packed vector
OsiRowCut_inline void setRow( const CoinPackedVector & v );
/// Get row elements
OsiRowCut_inline const CoinPackedVector & row() const;
//@}
/**@name Comparison operators */
//@{
/** equal - true if lower bound, upper bound, row elements,
and OsiCut are equal.
*/
OsiRowCut_inline bool operator==(const OsiRowCut& rhs) const;
/// not equal
OsiRowCut_inline bool operator!=(const OsiRowCut& rhs) const;
//@}
//----------------------------------------------------------------
/**@name Sanity checks on cut */
//@{
/** Returns true if the cut is consistent.
This checks to ensure that:
- The row element vector does not have duplicate indices
- The row element vector indices are >= 0
*/
OsiRowCut_inline bool consistent() const;
/** Returns true if cut is consistent with respect to the solver
interface's model.
This checks to ensure that
- The row element vector indices are < the number of columns
in the model
*/
OsiRowCut_inline bool consistent(const OsiSolverInterface& im) const;
/** Returns true if the row cut itself is infeasible and cannot be satisfied.
This checks whether
- the lower bound is strictly greater than the
upper bound.
*/
OsiRowCut_inline bool infeasible(const OsiSolverInterface &im) const;
//@}
/**@name Constructors and destructors */
//@{
/// Assignment operator
OsiRowCut & operator=( const OsiRowCut& rhs);
/// Copy constructor
OsiRowCut ( const OsiRowCut &);
/// Clone
virtual OsiRowCut * clone() const;
/// Default Constructor
OsiRowCut ();
/// Destructor
virtual ~OsiRowCut ();
//@}
private:
/**@name Private member data */
//@{
/// Row elements
CoinPackedVector row_;
/// Row lower bound
double lb_;
/// Row upper bound
double ub_;
//@}
};
#ifdef OSI_INLINE_ROWCUT_METHODS
//-------------------------------------------------------------------
// Set/Get lower & upper bounds
//-------------------------------------------------------------------
double OsiRowCut::lb() const { return lb_; }
void OsiRowCut::setLb(double lb) { lb_ = lb; }
double OsiRowCut::ub() const { return ub_; }
void OsiRowCut::setUb(double ub) { ub_ = ub; }
//-------------------------------------------------------------------
// Set row elements
//-------------------------------------------------------------------
void OsiRowCut::setRow(int size,
const int * colIndices, const double * elements)
{
row_.setVector(size,colIndices,elements);
}
void OsiRowCut::setRow( const CoinPackedVector & v )
{
row_ = v;
}
//-------------------------------------------------------------------
// Get the row
//-------------------------------------------------------------------
const CoinPackedVector & OsiRowCut::row() const
{
return row_;
}
//----------------------------------------------------------------
// == operator
//-------------------------------------------------------------------
bool
OsiRowCut::operator==(const OsiRowCut& rhs) const
{
if ( this->OsiCut::operator!=(rhs) ) return false;
if ( row() != rhs.row() ) return false;
if ( lb() != rhs.lb() ) return false;
if ( ub() != rhs.ub() ) return false;
return true;
}
bool
OsiRowCut::operator!=(const OsiRowCut& rhs) const
{
return !( (*this)==rhs );
}
//----------------------------------------------------------------
// consistent & infeasible
//-------------------------------------------------------------------
bool OsiRowCut::consistent() const
{
const CoinPackedVector & r=row();
r.duplicateIndex("consistent", "OsiRowCut");
if ( r.getMinIndex() < 0 ) return false;
return true;
}
bool OsiRowCut::consistent(const OsiSolverInterface& im) const
{
const CoinPackedVector & r=row();
if ( r.getMaxIndex() >= im.getNumCols() ) return false;
return true;
}
bool OsiRowCut::infeasible(const OsiSolverInterface &im) const
{
if ( lb() > ub() ) return true;
return false;
}
#endif
//#############################################################################
/** A function that tests the methods in the OsiRowCut 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
OsiRowCutUnitTest(const OsiSolverInterface * baseSiP,
const std::string & mpsDir);
#endif