OsiRowCut.hpp 8.19 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
// 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 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:
  <ul>
  <li>a lower bound<br>
  <li>an upper bound<br>
  <li>a vector of row elements
  </ul>
*/
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,
    bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE);
  /// Set row elements from a packed vector
  OsiRowCut_inline void setRow(const CoinPackedVector &v);
  /// Get row elements
  OsiRowCut_inline const CoinPackedVector &row() const;
  /// Get row elements for changing
  OsiRowCut_inline CoinPackedVector &mutableRow();
  //@}

  /**@name Comparison operators  */
  //@{
#if __GNUC__ != 2
  using OsiCut::operator==;
#endif
  /** equal - true if lower bound, upper bound, row elements,
        and OsiCut are equal.
    */
  OsiRowCut_inline bool operator==(const OsiRowCut &rhs) const;

#if __GNUC__ != 2
  using OsiCut::operator!=;
#endif
  /// 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:
        <ul>
        <li>The row element vector does not have duplicate indices
        <li>The row element vector indices are >= 0
        </ul>
    */
  OsiRowCut_inline bool consistent() const;

  /** Returns true if cut is consistent with respect to the solver
        interface's model.
        This checks to ensure that
        <ul>
        <li>The row element vector indices are < the number of columns
            in the model
        </ul>
    */
  OsiRowCut_inline bool consistent(const OsiSolverInterface &im) const;

  /** Returns true if the row cut itself is infeasible and cannot be satisfied.       
        This checks whether
        <ul>
        <li>the lower bound is strictly greater than the
            upper bound.
        </ul>
    */
  OsiRowCut_inline 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 Arithmetic operators. Apply CoinPackedVector methods to the vector */
  //@{
  /// add <code>value</code> to every vector entry
  void operator+=(double value)
  {
    row_ += value;
  }

  /// subtract <code>value</code> from every vector entry
  void operator-=(double value)
  {
    row_ -= value;
  }

  /// multiply every vector entry by <code>value</code>
  void operator*=(double value)
  {
    row_ *= value;
  }

  /// divide every vector entry by <code>value</code>
  void operator/=(double value)
  {
    row_ /= value;
  }
  //@}

  /// Allow access row sorting function
  void sortIncrIndex()
  {
    row_.sortIncrIndex();
  }

  /**@name Constructors and destructors */
  //@{
  /// Assignment operator
  OsiRowCut &operator=(const OsiRowCut &rhs);

  /// Copy constructor
  OsiRowCut(const OsiRowCut &);

  /// Clone
  virtual OsiRowCut *clone() const;

  /// Default Constructor
  OsiRowCut();

  /** \brief Ownership Constructor

      This constructor assumes ownership of the vectors passed as parameters
      for indices and elements. \p colIndices and \p elements will be NULL
      on return.
    */
  OsiRowCut(double cutlb, double cutub,
    int capacity, int size,
    int *&colIndices, double *&elements);

  /// Destructor
  virtual ~OsiRowCut();
  //@}

  /**@name Debug stuff */
  //@{
  /// Print cuts in collection
  virtual void print() const;
  //@}

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_;
}

//-------------------------------------------------------------------
// Get the row so we can change
//-------------------------------------------------------------------
CoinPackedVector &OsiRowCut::mutableRow()
{
  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

/** Row Cut Class which refers back to row which created it.
    It may be useful to strengthen a row rather than add a cut.  To do this
    we need to know which row is strengthened.  This trivial extension
    to OsiRowCut does that.

*/
class OsiRowCut2 : public OsiRowCut {

public:
  /**@name Which row */
  //@{
  /// Get row
  inline int whichRow() const
  {
    return whichRow_;
  }
  /// Set row
  inline void setWhichRow(int row)
  {
    whichRow_ = row;
  }
  //@}

  /**@name Constructors and destructors */
  //@{
  /// Assignment operator
  OsiRowCut2 &operator=(const OsiRowCut2 &rhs);

  /// Copy constructor
  OsiRowCut2(const OsiRowCut2 &);

  /// Clone
  virtual OsiRowCut *clone() const;

  /// Default Constructor
  OsiRowCut2(int row = -1);

  /// Destructor
  virtual ~OsiRowCut2();
  //@}

private:
  /**@name Private member data */
  //@{
  /// Which row
  int whichRow_;
  //@}
};
#endif

/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
*/