ip.cpp 7.58 KB

/*
 * Copyright (C) 2012 Kengo Sato
 *
 * This file comes from RactIP.
 *
 */


#include "ip.h"
#include <vector>
#include <cassert>
#include <stdexcept>
#include <iostream>

#include <ilcplex/cplex.h>

#include <cfloat>


class IPimpl
{
public:

  IPimpl(){};


  IPimpl(IP::DirType dir, int ncores)
    : env_(NULL), lp_(NULL), dir_(dir)
  {
    int status;
    env_ = CPXopenCPLEX(&status);
    if (env_==NULL)
    {
      char errmsg[CPXMESSAGEBUFSIZE];
      CPXgeterrorstring (env_, status, errmsg);
      throw std::runtime_error(errmsg);
    }
    status = CPXsetintparam(env_, CPXPARAM_Threads, ncores);
  }

  ~IPimpl()
  {
    if (lp_) CPXfreeprob(env_, &lp_);
    if (env_) CPXcloseCPLEX(&env_);
  }

  int make_variable(double coef)
  {
    int col = vars_.size();
    vars_.push_back('B');
    coef_.push_back(coef);
    vlb_.push_back(0.0);
    vub_.push_back(1.0);
    return col;
  }

  int make_variable_r(double coef)
  {
    int col = vars_.size();
    vars_.push_back('R');
    coef_.push_back(coef);
    vlb_.push_back(0.0);
    vub_.push_back(1.0);
    return col;
  }

  int make_variable(double coef, int lo, int hi)
  {
    int col = vars_.size();
    vars_.push_back('I');
    coef_.push_back(coef);
    vlb_.push_back(lo);
    vub_.push_back(hi);
    return col;
  }

  int make_constraint(IP::BoundType bnd, double l, double u)
  {
    int row = bnd_.size();
    bnd_.resize(bnd_.size()+1);
    rhs_.resize(rhs_.size()+1);
    rngval_.resize(rngval_.size()+1);
    switch (bnd)
    {
      case IP::LO: bnd_[row]='G'; rhs_[row]=l; break;	//... >= l
      case IP::UP: bnd_[row]='L'; rhs_[row]=u; break; //... <= u
      case IP::DB: bnd_[row]='R'; rhs_[row]=l; rngval_[row]=u-l; break; //u <= ... <= l
      case IP::FX: bnd_[row]='E'; rhs_[row]=l; break; // =
      case IP::FR: bnd_[row]='R'; rhs_[row]=DBL_MIN; rngval_[row]=DBL_MAX; break;
    }
    return row;
  }

  void chg_constraint(int row, IP::BoundType bnd, double l, double u){
    switch (bnd)
    {
      case IP::LO: bnd_[row]='G'; rhs_[row]=l; break;   // >=
      case IP::UP: bnd_[row]='L'; rhs_[row]=u; break; // <=
      case IP::DB: bnd_[row]='R'; rhs_[row]=l; rngval_[row]=u-l; break; // <= ... <=
      case IP::FX: bnd_[row]='E'; rhs_[row]=l; break; // =
      case IP::FR: bnd_[row]='R'; rhs_[row]=DBL_MIN; rngval_[row]=DBL_MAX; break;
    }
  }


  void add_constraint(int row, int col, double val)
  {
    std::make_pair(row, val);
    m_[col];
    m_[col].push_back(std::make_pair(row, val));
  }

  void update()
  {
    m_.resize(vars_.size());
  }

  int solve()
  {
      //std::cout << "debut solve ip" << std::endl;
    int numcols = vars_.size();
    int numrows = bnd_.size();
    int status;
    lp_ = CPXcreateprob(env_, &status, "");
    if (lp_==NULL)
      throw std::runtime_error("failed to create LP");

        // std::cout << "parametre solve ip" << std::endl;
    unsigned int n_nonzero=0;
    for (unsigned int i=0; i!=m_.size(); ++i)
      n_nonzero += m_[i].size();
    std::vector<int> matbeg(numcols, 0);
    std::vector<int> matcnt(numcols, 0);
    std::vector<int> matind(n_nonzero);
    std::vector<double> matval(n_nonzero);
    for (unsigned int i=0, k=0; i!=m_.size(); ++i)
    {
      matbeg[i] = i==0 ? 0 : matbeg[i-1]+matcnt[i-1];
      matcnt[i] = m_[i].size();
      for (unsigned int j=0; j!=m_[i].size(); ++j, ++k)
      {
        matind[k] = m_[i][j].first;
        matval[k] = m_[i][j].second;
      }
    }
         //std::cout << "avant copie" << std::endl;
    status = CPXcopylp(env_, lp_, numcols, numrows,
                        dir_==IP::MIN ? CPX_MIN : CPX_MAX,
                        &coef_[0], &rhs_[0], &bnd_[0],
                        &matbeg[0], &matcnt[0], &matind[0], &matval[0],
                        &vlb_[0], &vub_[0], &rngval_[0] );
        //std::cout << "avant copie" << std::endl;
    status = CPXcopyctype(env_, lp_, &vars_[0]);
        //std::cout << "apres copie" << std::endl;

    CPXsetintparam(env_, CPXPARAM_MIP_Display, 0);
    CPXsetintparam(env_, CPXPARAM_Barrier_Display, 0);
    CPXsetintparam(env_, CPXPARAM_Tune_Display, 0);
    CPXsetintparam(env_, CPXPARAM_Network_Display, 0);
    CPXsetintparam(env_, CPXPARAM_Sifting_Display, 0);
    CPXsetintparam(env_, CPXPARAM_Simplex_Display, 0);
    CPXsetintparam(env_, CPX_PARAM_SCRIND, CPX_OFF);
    CPXsetintparam(env_, CPX_PARAM_CONFLICTDISPLAY, 0);
    CPXsetintparam(env_, CPX_PARAM_MIPINTERVAL, 0);
  /*  CPXsetintparam(env_, CPXPARAM_MIP_Display, 1);
    CPXsetintparam(env_, CPXPARAM_Barrier_Display, 1);
    CPXsetintparam(env_, CPXPARAM_Tune_Display, 1);
    CPXsetintparam(env_, CPXPARAM_Network_Display, 1);
    CPXsetintparam(env_, CPXPARAM_Sifting_Display, 1);
    CPXsetintparam(env_, CPXPARAM_Simplex_Display, 1);
    CPXsetintparam(env_, CPX_PARAM_SCRIND, CPX_ON);
    CPXsetintparam(env_, CPX_PARAM_CONFLICTDISPLAY, 2);
    CPXsetintparam(env_, CPX_PARAM_MIPINTERVAL, 1);*/
    //std::cout << "avant opt" << std::endl;
    status = CPXmipopt(env_, lp_);
        //std::cout << "apres opt" << std::endl;
    if (status == 0){
            //std::cout << "status 0" << std::endl;
        status = CPXgetobjval(env_, lp_, &objval_);
        res_cols_.resize(CPXgetnumcols(env_, lp_));
        status = CPXgetx(env_, lp_, &res_cols_[0], 0, res_cols_.size()-1);
    }
    else
    {
        /*status = CPXcopylp(env_, lp_, numcols, numrows,
                        dir_==IP::MIN ? CPX_MIN : CPX_MAX,
                        &coef_[0], &rhs_[0], &bnd_[0],
                        &matbeg[0], &matcnt[0], &matind[0], &matval[0],
                        &vlb_[0], &vub_[0], &rngval_[0] );
       int CPXPUBLIC
       CPXcopylp (CPXCENVptr env, CPXLPptr lp, int numcols, int numrows,
                                           int objsense, double const *objective, double const *rhs,
                                           char const *sense, int const *matbeg, int const *matcnt,
                                           int const *matind, double const *matval,
                                           double const *lb, double const *ub, double const *rngval);

     CPXgetconflict (env_, lp_, int *confstat_p,
                        int *rowind, int *rowbdstat, int *confnumrows_p,
                        int *colind, int *colbdstat, int *confnumcols_p);
*/
    }
    return status;
  }

  double get_value(int col) //const
  {
    return res_cols_[col];
  }

  double get_obj()
  {
    return objval_;
  }

private:
  CPXENVptr env_;
  CPXLPptr lp_;
  IP::DirType dir_;
  std::vector<char> vars_;
  std::vector<double> coef_;
  std::vector<double> vlb_;
  std::vector<double> vub_;
  std::vector<char> bnd_;
  std::vector<double> rhs_;
  std::vector<double> rngval_;
  std::vector< std::vector< std::pair<int,double> > > m_;
  std::vector<double> res_cols_;
  double objval_;
};



IP::IP(){}



IP::IP(DirType dir, int n_th) : impl_(new IPimpl(dir, n_th))
{
}

IP::
~IP()
{
  delete impl_;
}

int
IP::
make_variable(double coef)
{
  return impl_->make_variable(coef);
}

int
IP::
make_variable_r(double coef)
{
  return impl_->make_variable(coef);
}

int
IP::
make_variable(double coef, int lo, int hi)
{
  return impl_->make_variable(coef, lo, hi);
}

int
IP::
make_constraint(BoundType bnd, double l, double u)
{
  return impl_->make_constraint(bnd, l, u);
}

void
IP::
add_constraint(int row, int col, double val)
{
  return impl_->add_constraint(row, col, val);
}

void
IP::
chg_constraint(int row, BoundType bnd, double l, double u)
{
    return impl_->chg_constraint(row, bnd, l, u);
}




void
IP::
update()
{
  impl_->update();
}

int
IP::
solve()
{
  return impl_->solve();
}

double
IP::
get_value(int col)
{
  return impl_->get_value(col);
}

double
IP::
get_obj()
{
  return impl_->get_obj();
}