int 
OsiVolSolverInterface::readMps(const char *filename, const char *extension)
{
   CoinMpsIO reader;
   reader.setInfinity(getInfinity());
   int retVal = reader.readMps(filename, extension);
   loadProblem(*reader.getMatrixByCol(),
	       reader.getColLower(), reader.getColUpper(),
	       reader.getObjCoefficients(),
	       reader.getRowLower(), reader.getRowUpper());
   int nc = getNumCols();
   assert (continuous_);
   CoinFillN(continuous_, nc, true);
   return retVal;
}
void 
OsiVolSolverInterface::writeMps(const char *filename,
				const char *extension,
				double /*objSense*/) const
{
   CoinMpsIO writer;
   writer.setMpsData(*getMatrixByCol(), getInfinity(),
		     getColLower(), getColUpper(),
		     getObjCoefficients(), 
		     reinterpret_cast<const char *> (NULL) /*integrality*/,
		     getRowLower(), getRowUpper(),
		     reinterpret_cast<const char **> (NULL) /*colnam*/, 
		     reinterpret_cast<const char **> (NULL) /*rownam*/);
   std::string fname = filename;
   if (extension)
   { if (extension[0] != '\0' && extension[0] != '.')
     fname += "." ; }
   fname += extension;
   writer.writeMps(fname.c_str());
}
void 
OsiTestSolverInterface::resolve()
{
  int i;
  
  checkData_();

  // Only one of these can do any work
  updateRowMatrix_();
  updateColMatrix_();

  const int dsize = getNumRows();
  const int psize = getNumCols();

  // Negate the objective coefficients if necessary
  if (objsense_ < 0) {
    std::transform(objcoeffs_, objcoeffs_+psize, objcoeffs_,
		   std::negate<double>());
  }

  // Set the lb/ub on the duals
  volprob_.dual_lb.allocate(dsize);
  volprob_.dual_ub.allocate(dsize);
  double * dlb = volprob_.dual_lb.v;
  double * dub = volprob_.dual_ub.v;
  for (i = 0; i < dsize; ++i) {
    dlb[i] = rowupper_[i] <  getInfinity() ? -1.0e31 : 0.0;
    dub[i] = rowlower_[i] > -getInfinity() ?  1.0e31 : 0.0;
  }
  volprob_.dsize = dsize;
  volprob_.psize = psize;
  
  // Set the dual starting point
  VOL_dvector& dsol = volprob_.dsol;
  dsol.allocate(dsize);
  std::transform(rowprice_, rowprice_+dsize, dsol.v,
		 std::bind2nd(std::multiplies<double>(), objsense_));

  // adjust the dual vector (if necessary) to be sure it's feasible
  double * dv = dsol.v;
  for (i = 0; i < dsize; ++i) {
    if (dv[i] < dlb[i]) {
      dv[i] = dlb[i];
    } else if (dv[i] > dub[i]) {
      dv[i] = dub[i];
    }
  }

  // If requested, check whether the matrix contains anything but 0/1/-1
#if 0
  isZeroOneMinusOne_ = false;
#else
  isZeroOneMinusOne_ = test_zero_one_minusone_(colMatrix_);
  if (isZeroOneMinusOne_) {
    colMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(colMatrix_);
    rowMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(rowMatrix_);
  }
#endif

  volprob_.solve(*this, true);

  // extract the solution

  // the lower bound on the objective value
  lagrangeanCost_ = objsense_ * volprob_.value;
  // the primal solution
  CoinDisjointCopyN(volprob_.psol.v, psize, colsol_);

  // Reset the objective coefficients if necessary
  if (objsense_ < 0) {
    std::transform(objcoeffs_, objcoeffs_ + psize, objcoeffs_,
		   std::negate<double>());
    // also, multiply the dual solution by -1
    std::transform(volprob_.dsol.v, volprob_.dsol.v+dsize, rowprice_,
		   std::negate<double>());
  } else {
    // now we just have to copy the dual
    CoinDisjointCopyN(volprob_.dsol.v, dsize, rowprice_);
  }

  // Compute the reduced costs
  compute_rc_(rowprice_, rc_);

  // Compute the left hand side (row activity levels)
  if (isZeroOneMinusOne_) {
    colMatrixOneMinusOne_->timesMajor(colsol_, lhs_);
  } else {
    colMatrix_.times(colsol_, lhs_);
  }

  if (isZeroOneMinusOne_) {
    delete colMatrixOneMinusOne_;
    colMatrixOneMinusOne_ = NULL;
    delete rowMatrixOneMinusOne_;
    rowMatrixOneMinusOne_ = NULL;
  }
}
Esempio n. 4
0
ProblemStatus ColaModel::solve_numeric() {
  solve(false);
  // 1. determine original binding constraints
  std::vector<int> binding;
  int num_rows = getNumRows();
  int orig_num_rows = num_rows - total_num_cuts_;
  int num_cols = getNumCols();
  int * cstat = new int[num_cols];
  int * rstat = new int[num_rows];
  getBasisStatus(cstat, rstat);
  for (int i=0; i<orig_num_rows; ++i) {
    if (rstat[i]==2 or rstat[i]==3) {
      binding.push_back(i);
    }
  }
  int num_binding = binding.size();
  delete[] cstat;
  delete[] rstat;
  // 2. compute AA^T
  // A is sparse and instance of CoinPackedMatrix
  // 2.1 get A
  CoinPackedMatrix const * mat = getMatrixByRow();
  CoinPackedMatrix * A = new CoinPackedMatrix(false, 500, 500);
  std::vector<int>::const_iterator it;
  for (it=binding.begin(); it!=binding.end(); ++it) {
    int first = mat->getVectorFirst(*it);
    int last = mat->getVectorLast(*it);
    int num_elem  = last-first;
    int const * mat_cols = mat->getIndices() + first;
    double const * mat_value = mat->getElements() + first;
    A->appendRow(CoinPackedVector(num_elem, mat_cols, mat_value));
  }
  // 2.2 Compute AAt
  CoinPackedMatrix * AAt = new CoinPackedMatrix();
  double * Aa_i = new double[num_binding];
  int * Aa_i_cols = new int[num_binding];
  double * Aa_i_vals = new double[num_binding];
  for (it=binding.begin(); it!=binding.end(); ++it) {
    // A times row i of A
    int first = mat->getVectorFirst(*it);
    int last = mat->getVectorLast(*it);
    int num_elem  = last-first;
    int const * mat_cols = mat->getIndices() + first;
    double const * mat_value = mat->getElements() + first;
    A->times(CoinPackedVector(num_elem, mat_cols, mat_value), Aa_i);
    // sparsify and insert Aa_i
    int Aa_i_size = 0;
    for (int i=0; i<num_binding; ++i) {
      if (Aa_i[i]!=0.0) {
        Aa_i_cols[Aa_i_size] = i;
        Aa_i_vals[Aa_i_size] = Aa_i[i];
        Aa_i_size++;
      }
    }
    AAt->appendCol(CoinPackedVector(Aa_i_size, Aa_i_cols, Aa_i_vals));
  }
  delete[] Aa_i;
  delete[] Aa_i_cols;
  delete[] Aa_i_vals;
  //AAt->dumpMatrix();
  // 3. compute Ac
  double * Ac = new double[num_binding];
  double const * obj = getObjCoefficients();
  int obj_size;
  int * obj_cols = new int[num_cols];
  double * obj_vals = new double[num_cols];
  for (int i=0; i<num_cols; ++i) {
    if (obj[i]!=0) {
      obj_cols[obj_size] = i;
      obj_vals[obj_size] = obj[i];
      obj_size++;
    }
  }
  A->times(CoinPackedVector(obj_size, obj_cols, obj_vals), Ac);
  delete[] obj_cols;
  delete[] obj_vals;
  // 4. compute (b-Ac)
  double * b = new double[num_binding];
  int k=0;
  for (it=binding.begin(); it!=binding.end(); ++it) {
    b[k] = getRightHandSide()[*it];
    k++;
  }
  double * b_Ac = new double[num_binding];
  for (int i=0; i<num_binding; ++i) {
    b_Ac[i] = b[i] - Ac[i];
  }
  // 5. solve AA^Ty=(b-Ac)
  // 5.1 get AAt in lower triangular format
  double ** AAt_dense = new double*[num_binding];
  for (int i=0; i<num_binding; ++i) {
    AAt_dense[i] = new double[num_binding]();
  }
  int const * AAt_cols = AAt->getIndices();
  double const * AAt_value = AAt->getElements();
  for (int i=0; i<num_binding; ++i) {
    // get row i
    int first = AAt->getVectorFirst(i);
    int last = AAt->getVectorLast(i);
    //int num_elem  = last-first;
    for (int j=first; j<last; ++j) {
      AAt_dense[i][AAt_cols[j]] = AAt_value[j];
    }
  }
  // 5.2 call lapack routine to solve the system
  double * y = new double[num_binding];
  lapack_solve(AAt_dense, b_Ac, y, num_binding);
  // 6. compute d <- c+A^Ty
  // in other words x <- c + A'(AA')^{-1}b - A'(AA')^{-1}Ac when
  // we insert for y.
  // 6.1 compute Aty
  double * Aty = new double[num_cols];
  A->transposeTimes(y, Aty);
  // 6.2 compute d <- c+A^Ty
  double * dir = new double[num_cols];
  double const * cur_sol = getColSolution();
  for (int i=0; i<num_cols; ++i) {
    dir[i] = -obj[i] - Aty[i];
  }
  // 7. go along direction until we hit boundry, ie. compute step_size
  double step_size = 0.0;
  int num_cones = getNumCones();
  imp_solution_ = new double[num_cols];
  std::copy(cur_sol, cur_sol+num_cols, imp_solution_);
  double * par_sol;
  double * par_dir;
  for (int i=0; i<num_cones; ++i) {
    int cone_size = cones_[i]->size();
    LorentzCone * con = dynamic_cast<LorentzCone*>(cones_[i]);
    int const * members = con->members();
    par_sol = new double[cone_size];
    par_dir = new double[cone_size];
    // 7.1 compute step size
    // 7.2 compute a in ax^2+bx+c=0
    // 7.3 compute b in ax^2+bx+c=0
    // 7.4 compute c in ax^2+bx+c=0
    for (int j=0; j<con->size(); j++) {
      par_sol[j] = cur_sol[members[j]];
      par_dir[j] = dir[members[j]];
    }
    double feas_i = par_sol[0]*par_sol[0]-std::inner_product(par_sol+1, par_sol+cone_size, par_sol+1, 0.0);
    if (feas_i > options_->get_dbl_option(TOL)) {
      delete[] par_sol;
      delete[] par_dir;
      continue;
    }
    double a = par_dir[0]*par_dir[0];
    double b = par_sol[0]*par_dir[0];
    double c = par_sol[0]*par_sol[0];
    a = a - std::inner_product(par_dir+1, par_dir+con->size(), par_dir+1, 0.0);
    b = b - std::inner_product(par_sol+1, par_sol+con->size(), par_dir+1, 0.0);
    b = 2.0*b;
    c = c - std::inner_product(par_sol+1, par_sol+con->size(), par_sol+1, 0.0);
    // 7.5 compute step size
    double alpha1 = (-b+sqrt(b*b-4.0*a*c))/(2.0*a);
    double alpha2 = (-b-sqrt(b*b-4.0*a*c))/(2.0*a);
    double alpha=alpha1;
    std::cout << "alpha1 " << alpha1 << std::endl;
    std::cout << "alpha2 " << alpha2 << std::endl;
    // if (alpha2<alpha1)
    //   alpha=alpha2;
    for (int j=0; j<con->size(); j++) {
      imp_solution_[members[j]] = cur_sol[members[j]] + alpha*par_dir[j];
    }
    delete[] par_sol;
    delete[] par_dir;
    // get related portion of direction
    // get related portion of solution
  }
  delete A;
  delete AAt;
  delete[] Ac;
  delete[] b;
  delete[] b_Ac;
  for (int i=0; i<num_binding; ++i) {
    delete[] AAt_dense[i];
  }
  delete[] AAt_dense;
  delete[] y;
  delete[] Aty;
  delete[] dir;
  // remove all the cuts and add a cut using the improved solution
  int * indices = new int[total_num_cuts_];
  for (int i=0; i<total_num_cuts_; ++i) {
    indices[i] = orig_num_rows+i;
  }
  deleteRows(total_num_cuts_, indices);
  delete[] indices;
  total_num_cuts_ = 0;
  num_lp_solved_ = 0;
  std::fill(num_cuts_, num_cuts_+num_cones, 0);
  // separate from imp_solution
  Separate * sep = new Separate(cones_, imp_solution_, getNumCols(), options_);
  // returns true if given point is feasible for all cones.
  int feasible = sep->is_feasible();
  while(!feasible) {
    // number of cuts generated
    // std::cout << "ColaModel: " << sep->cuts()->size() << " cuts generated." << std::endl;
    // add all the cuts generated
        // Add all the cuts generated
    std::vector<CoinPackedVector*> cut = sep->cuts();
    std::vector<double> rhs = sep->rhs();
    std::vector<int> gen_cone = sep->generating_cone();
    int num_cuts = cut.size();
    for (int i=0; i<num_cuts; ++i) {
      addRow(*cut[i], -getInfinity(), rhs[i]);
      // print cut
      // end of cut print
      total_num_cuts_++;
      num_cuts_[gen_cone[i]]++;
    }
    // if (num_lp_solved_%2==0) {
    //   clean_redundant_constraints();
    // }
    // resolve the problem
    num_lp_solved_++;
    OsiClpSolverInterface::resolve();
    // update problem status
    update_problem_status();
    // check problem status
    if (soco_status_!=OPTIMAL)
      break;
    delete sep;
    // chec if the new solution is feasible for cones
    sep = new Separate(cones_, getColSolution(), getNumCols(), options_);
    feasible = sep->is_feasible();
  }
  delete sep;
  // update problem status
  update_problem_status();
  // report feasibility of imp_solution_
  double lhs = 0.0;
  double lhs_real = 0.0;
  std::cout << "Conic Constraints feasibility report" << std::endl;
  std::cout << std::setw(5) << std::left << "Cone";
  // todo(aykut) this is not true all the time, what if cone is rotated.
  std::cout << std::setw(20) << std::left << "x1^2-sum x_i^2"
            << std::setw(20) << std::left << "x1-||x_{2:n}||"
            << std::endl;
  const double * full_sol = imp_solution_;
  //double * par_sol;
  for (int i=0; i<num_cones; ++i) {
    int cone_size = cones_[i]->size();
    LorentzCone * con = dynamic_cast<LorentzCone*>(cones_[i]);
    const int * members = con->members();
    par_sol = new double[cone_size];
    for (int j=0; j<cone_size; ++j) {
      par_sol[j] = full_sol[members[j]];
    }
    if (con->type()==LORENTZ) {
      lhs = par_sol[0]*par_sol[0]
        - std::inner_product(par_sol+1, par_sol+cone_size, par_sol+1, 0.0);
      lhs_real = par_sol[0]
        -sqrt(std::inner_product(par_sol+1, par_sol+cone_size, par_sol+1, 0.0));
    }
    else if (con->type()==RLORENTZ) {
      lhs = 2.0*par_sol[0]*par_sol[1]
        - std::inner_product(par_sol+2, par_sol+cone_size, par_sol+2, 0.0);
      lhs_real = lhs;
    }
    std::cout << std::setw(5) << std::left << i
              << std::setw(20) << std::left << lhs
              << std::setw(20) << std::left << lhs_real
              << std::endl;
    delete[] par_sol;
  }
  return soco_status_;
}
Esempio n. 5
0
// solves problem using ben-tal nemirovski approximation
// v is approximation parameter
// resolve is false, then solve from scratch
// resolve is true, use Clp's resolve.
ProblemStatus ColaModel::solve_with_bn(bool resolve, int v) {
  // if we have rotated cones bail out,


  // create approximation
  // = first reduce all cones to 3 dimensional cones.
  // conic constraints obtained by reducing cone i
  std::vector<Cone*> reduced_cones_i;
  // set of conic constraints we get by reducing all cones of original problem
  std::vector<Cone*> reduced_cones;
  int num_cones = cones_.size();
  int num_var = getNumCols();
  for (int i=0; i<num_cones; ++i) {
    if (cones_[i]->size()<=3) {
      continue;
    }
    // reduce conic constraint i to smaller cones, save them in reduced_cc_i
    LorentzCone * c = dynamic_cast<LorentzCone*>(cones_[i]);
    reduce_cone (c->size(), c->members(), reduced_cones_i, num_var);
    // add new cones to problem
    int num_cones_i = reduced_cones_i.size();
    for (int i=0; i<num_cones_i; ++i) {
      reduced_cones.push_back(reduced_cones_i[i]);
    }
    //    std::copy(reduced_cones_i, reduced_cones_i+reduced_cones_i.size(),
    //        reduced_cones+reduced_cones.size());
    // reset reduced_cc_i
    reduced_cones_i.clear();
  }
  // print new cones of the problem
  //reduced_cc->dump_cones();
  // = add new variables to the model
  int diff = num_var - getNumCols();
  double infinity = getInfinity();
  for(int i=0; i<diff; ++i) {
    addCol(0, NULL, NULL, 0.0, infinity, 0.0);
  }
  // int num_rows = getNumRows();
  // int diff = num_var - getNumCols();
  // double * collb = new double[diff]();
  // double * colub = new double[diff]();
  // double * obj = new double[diff]();
  // double infinity = getInfinity();
  // std::fill(colub, colub+diff, infinity);
  // CoinPackedVectorBase ** cols = 0;
  // cols = new CoinPackedVectorBase*[diff];
  // int * inds = 0;
  // for (int i=0; i<diff; ++i) {
  //   cols[i] = new CoinPackedVector(num_rows, inds, 0.0);
  // }
  // addCols(diff, cols, collb, colub, obj);
  // std::cout << "Num Cols: " << getNumCols();
  // delete[] collb;
  // delete[] colub;
  // delete[] obj;
  //writeMps("reduced", "mps");
  // if reduced cone is not empty
  if (!reduced_cones.empty()) {
    setConicConstraints(reduced_cones);
  }
  int nOfCones = getNumCones();
  if (num_cuts_!=0) {
    delete[] num_cuts_;
  }
  if (num_supports_!=0) {
    delete num_supports_;
  }
  num_cuts_ = new int[nOfCones]();
  num_supports_ = new int[nOfCones]();
  solve(resolve);
  // set columns for new variables to 0
}
Esempio n. 6
0
// first reduces all conic constraints to 3 dimentional second order conic
// constraints as described in ben-tal nemirovski, then solves the conic
// problem using liner approximations
ProblemStatus ColaModel::solve_reducing_cones(bool resolve) {
  int num_cones = cones_.size();
  // if we have Scaled cones bail out,
  std::vector<Cone*>::const_iterator it;
  for (it=cones_.begin(); it!=cones_.end(); it++) {
    if ((*it)->type()==SCALED) {
      std::cerr << "Cola: This method is only for Lorentz cones."
                << std::endl;
      std::cerr << "Cola: Terminating..." << std::endl;
      soco_status_ = ABANDONED;
      return ABANDONED;
    }
  }
  // if we have rotated cones bail out,
  for (int i=0; i<num_cones; ++i) {
    if (cones_[i]->type()==SCALED or cones_[i]->type()==RLORENTZ) {
      std::cerr << "Cola: This method is only for canonical cones."
                << std::endl;
      std::cerr << "Cola: Terminating..." << std::endl;
      soco_status_ = ABANDONED;
      return ABANDONED;
    }
  }
  // create approximation
  // = first reduce all cones to 3 dimensional cones.
  // conic constraints obtained by reducing cone i
  std::vector<Cone*> reduced_cones_i;
  // set of conic constraints we get by reducing all cones of original problem
  std::vector<Cone*>  reduced_cones;
  int num_var = getNumCols();
  for (int i=0; i<num_cones; ++i) {
    LorentzCone * c = dynamic_cast<LorentzCone*>(cones_[i]);
    if (c->size()<=3) {
      continue;
    }
    // reduce conic constraint i to smaller cones, save them in reduced_cc_i
    reduce_cone (c->size(), c->members(), reduced_cones_i, num_var);
    // add new cones to problem
    int num_cones_i = reduced_cones_i.size();
    for (int i=0; i<num_cones_i; ++i) {
      reduced_cones.push_back(reduced_cones_i[i]);
    }
    // copy all from reduced_cones_i vector to reduced_cones
    //    std::copy(reduced_cones_i, reduced_cones_i+reduced_cones_i.size(),
    //        reduced_cones+reduced_cones.size());
    // reset reduced_cc_i
    reduced_cones_i.clear();;
  }
  // print new cones of the problem
  //reduced_cc->dump_cones();
  // = add new variables to the model
  int diff = num_var - getNumCols();
  double infinity = getInfinity();
  for(int i=0; i<diff; ++i) {
    addCol(0, NULL, NULL, 0.0, infinity, 0.0);
  }
  // int num_rows = getNumRows();
  // int diff = num_var - getNumCols();
  // double * collb = new double[diff]();
  // double * colub = new double[diff]();
  // double * obj = new double[diff]();
  // double infinity = getInfinity();
  // std::fill(colub, colub+diff, infinity);
  // CoinPackedVectorBase ** cols = 0;
  // cols = new CoinPackedVectorBase*[diff];
  // int * inds = 0;
  // for (int i=0; i<diff; ++i) {
  //   cols[i] = new CoinPackedVector(num_rows, inds, 0.0);
  // }
  // addCols(diff, cols, collb, colub, obj);
  // std::cout << "Num Cols: " << getNumCols();
  // delete[] collb;
  // delete[] colub;
  // delete[] obj;
  //writeMps("reduced", "mps");
  // if reduced cone is not empty
  if (!reduced_cones.empty()) {
    setConicConstraints(reduced_cones);
  }
  int nOfCones = getNumCones();
  if (num_cuts_!=0) {
    delete[] num_cuts_;
  }
  if (num_supports_!=0) {
    delete num_supports_;
  }
  num_cuts_ = new int[nOfCones]();
  num_supports_ = new int[nOfCones]();
  solve(resolve);
  // set columns for new variables to 0
}
Esempio n. 7
0
ProblemStatus ColaModel::solve(bool resolve) {
  // todo(aykut) now we should check if the cone related data is initialized
  // properly. This is a problem when the user does not read problem from mps
  // file but builds the model herself using cola as a library.
  if (num_cuts_==0) {
    int nOfCones = getNumCones();
    if (num_cuts_==0) {
      num_cuts_ = new int[nOfCones]();
    }
    if (num_supports_==0) {
      num_supports_ = new int[nOfCones]();
    }
  }
  if (first_solve_) {
    initialSolve();
    first_solve_ = false;
  }
  // solve linear problem
  bool feasible = false;
  Separate * sep;
  // add nonnegativity of leading variables
  std::vector<Cone*>::const_iterator it;
  for (it=cones_.begin(); it!=cones_.end(); ++it) {
    (*it)->relax(*this);
  }
  // ===== End Of adding nonnegativity of leading variables
  //writeMps("initial", "mps");
  num_lp_solved_++;
  if (resolve==false) {
    // if this function is called from OsiConicSolverInterface::initialSolve then
    OsiClpSolverInterface::initialSolve();
  }
  else {
    // if it is called from OsiConicSolverInterface::resolve
    OsiClpSolverInterface::resolve();
  }
  // check problem status
  update_problem_status();
  if ((soco_status_!=OPTIMAL) && (soco_status_!=DUAL_INFEASIBLE))
    return soco_status_;
  // if problem is unbounded add supporting hyperplanes for each cone using
  // objective coefficients.
  // todo(aykut) I guess SOCO is unbounded if LP is unbounded after all these
  // supporting hyperplanes. Check if this is true theoretically.
  if (soco_status_==DUAL_INFEASIBLE) {
    if (options_->get_int_option(LOG_LEVEL)>0) {
      std::cout << "Cola: Problem without conic constraints is unbounded. Adding"
        " supporting hyperplanes to resolve..."
                << std::endl;
    }
    while (soco_status_==DUAL_INFEASIBLE) {
      // check if primal is infeasible, then the problem is infeasible
      if (isProvenPrimalInfeasible()) {
        // Both LP primal and dual is infeasible, conic problem is infeasible
        std::cout << "Cola: Conic problem is infeasible."
                  << std::endl
                  << "Cola: Terminating...";
      }

      // get one ray
      // todo(aykut) for now we get only one ray
      std::vector<double*> rays = getPrimalRays(1);
      const double * vec = 0;
      if (!rays.empty() and rays[0]!=0) {
        vec = rays[0];
      }
      else {
        std::cout << "Cola: Warning! "
                  << "LP is unbounded but solver did not return a "
          "direction of unboundedness." << std::endl
                  << "Cola: Trying to generate supports using objective "
          "function coefficients..." << std::endl;
        vec = getObjCoefficients();
      }
      // PRINT UNBDDNESS DIRECTION
      // std::cout << "Unboundedness direction is " << std::endl  << "[";
      // for (int i=0; i<getNumCols(); ++i) {
      //	std::cout << std::setw(10) << vec[i] << "; ";
      // }
      // std::cout << "]" << std::endl;
      // END OF DIRECTION PRINT
      sep = new Separate(cones_, vec, getNumCols(), options_);
      // returns true if direction is feasible for all cones.
      feasible = sep->is_feasible();
      if (feasible) {
        // primal ray is feasible for all cone constraints,
        // problem is unbounded
        delete sep;
        soco_status_ = DUAL_INFEASIBLE;
        return DUAL_INFEASIBLE;
      }
      else {
        // Add all the cuts generated
        std::vector<CoinPackedVector*> cut = sep->cuts();
        std::vector<double> rhs = sep->rhs();
        std::vector<int> gen_cone = sep->generating_cone();
        int num_cuts = cut.size();
        for (int i=0; i<num_cuts; ++i) {
          addRow(*cut[i], -getInfinity(), rhs[i]);
          // print cut
          // end of cut print
          total_num_supports_++;
          num_supports_[gen_cone[i]]++;
        }
      }
      // todo(aykut) delete all rays not just first one.
      if (!rays.empty()) {
        for(int i=0; i<rays.size(); ++i)
          delete[] rays[i];
        rays.clear();
      }
      delete sep;
      num_lp_solved_++;
      OsiClpSolverInterface::resolve();
      // update soco_status_
      update_problem_status();
    }
  }
  if (soco_status_!=OPTIMAL) {
    // it means it is not optimal after resolving unbounded directions
    std::cout << "Cola: Problem status is not optimal after adding "
      "supporting hyperplanes."
              << std::endl;
    std::cout << "Cola: Terminating..." << std::endl;
    return soco_status_;
  }
  // when we reached here, it means the problem is not unbounded anymore.
  // todo(aykut) pick the cone and all those logs and stuff. it can all go to separate.
  sep = new Separate(cones_, getColSolution(), getNumCols(), options_);
  // returns true if given point is feasible for all cones.
  feasible = sep->is_feasible();
  while(!feasible) {
    // number of cuts generated
    // std::cout << "ColaModel: " << sep->cuts()->size() << " cuts generated." << std::endl;
    // add all the cuts generated
    // Add all the cuts generated
    std::vector<CoinPackedVector*> cut = sep->cuts();
    std::vector<double> rhs = sep->rhs();
    std::vector<int> gen_cone = sep->generating_cone();
    int num_cuts = cut.size();
    for (int i=0; i<num_cuts; ++i) {
      addRow(*cut[i], -getInfinity(), rhs[i]);
      // print cut
      // end of cut print
      total_num_cuts_++;
      num_cuts_[gen_cone[i]]++;
    }
    // if (num_lp_solved_%2==0) {
    //   clean_redundant_constraints();
    // }
    // resolve the problem
    num_lp_solved_++;
    OsiClpSolverInterface::resolve();
    // update problem status
    update_problem_status();
    // check problem status
    if (soco_status_!=OPTIMAL)
      break;
    delete sep;
    // chec if the new solution is feasible for cones
    sep = new Separate(cones_, getColSolution(), getNumCols(), options_);
    feasible = sep->is_feasible();
  }
  delete sep;
  // update problem status
  update_problem_status();
  // clean redundant constraints
  // clean_redundant_constraints();
  return soco_status_;
}