// 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).

#if defined(_MSC_VER)
// Turn off compiler warning about long names
#pragma warning(disable : 4786)
#endif

#include "OsiColCut.hpp"
#include <cstdlib>
#include <cstdio>
#include <iostream>

//-------------------------------------------------------------------
// Default Constructor
//-------------------------------------------------------------------
OsiColCut::OsiColCut()
  : OsiCut()
  , lbs_()
  , ubs_()
{
  // nothing to do here
}
//-------------------------------------------------------------------
// Copy constructor
//-------------------------------------------------------------------
OsiColCut::OsiColCut(const OsiColCut &source)
  : OsiCut(source)
  , lbs_(source.lbs_)
  , ubs_(source.ubs_)
{
  // Nothing to do here
}

//----------------------------------------------------------------
// Clone
//----------------------------------------------------------------
OsiColCut *OsiColCut::clone() const
{
  return (new OsiColCut(*this));
}

//-------------------------------------------------------------------
// Destructor
//-------------------------------------------------------------------
OsiColCut::~OsiColCut()
{
  // Nothing to do here
}

//----------------------------------------------------------------
// Assignment operator
//-------------------------------------------------------------------
OsiColCut &
OsiColCut::operator=(const OsiColCut &rhs)
{
  if (this != &rhs) {

    OsiCut::operator=(rhs);
    lbs_ = rhs.lbs_;
    ubs_ = rhs.ubs_;
  }
  return *this;
}
//----------------------------------------------------------------
// Print
//-------------------------------------------------------------------

void OsiColCut::print() const
{
  const CoinPackedVector &cutLbs = lbs();
  const CoinPackedVector &cutUbs = ubs();
  int i;
  std::cout << "Column cut has "
            << cutLbs.getNumElements()
            << " lower bound cuts and "
            << cutUbs.getNumElements()
            << " upper bound cuts"
            << std::endl;
  for (i = 0; i < cutLbs.getNumElements(); i++) {
    int colIndx = cutLbs.getIndices()[i];
    double newLb = cutLbs.getElements()[i];
    std::cout << "[ x" << colIndx << " >= " << newLb << "] ";
  }
  for (i = 0; i < cutUbs.getNumElements(); i++) {
    int colIndx = cutUbs.getIndices()[i];
    double newUb = cutUbs.getElements()[i];
    std::cout << "[ x" << colIndx << " <= " << newUb << "] ";
  }
  std::cout << std::endl;
}
/* Returns infeasibility of the cut with respect to solution 
    passed in i.e. is positive if cuts off that solution.  
    solution is getNumCols() long..
*/
double
OsiColCut::violated(const double *solution) const
{
  const CoinPackedVector &cutLbs = lbs();
  const CoinPackedVector &cutUbs = ubs();
  double sum = 0.0;
  int i;
  const int *column = cutLbs.getIndices();
  int number = cutLbs.getNumElements();
  const double *bound = cutLbs.getElements();
  for (i = 0; i < number; i++) {
    int colIndx = column[i];
    double newLb = bound[i];
    if (newLb > solution[colIndx])
      sum += newLb - solution[colIndx];
  }
  column = cutUbs.getIndices();
  number = cutUbs.getNumElements();
  bound = cutUbs.getElements();
  for (i = 0; i < number; i++) {
    int colIndx = column[i];
    double newUb = bound[i];
    if (newUb < solution[colIndx])
      sum += solution[colIndx] - newUb;
  }
  return sum;
}

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