void OsiCpxSolverInterface::printBounds()
{
  int nc = getNumCols();
  int nr = getNumRows();
  const char * s = getRowSense();
  const double * b = getRightHandSide();
  const double * rng = getRowRange();
  const double * cl = getColLower();
  const double * cu = getColUpper();
  const double * rl = getRowLower();
  const double * ru = getRowUpper();
  
  std::cout << "ncols=" << nc << ", nrows=" << nr;
  std::cout << std::endl << "sns=";
  int i;
  for( i = 0; i < nr; ++i )
    std::cout << " " << s[i];
  std::cout << std::endl << "rhs=";
  for( i = 0; i < nr; ++i )
    std::cout << " " << b[i];
  std::cout << std::endl << "rng=";
  for( i = 0; i < nr; ++i )
    std::cout << " " << rng[i];
  std::cout << std::endl << "cl =";
  for( i = 0; i < nc; ++i )
    std::cout << " " << cl[i];
  std::cout << std::endl << "cu =";
  for( i = 0; i < nc; ++i )
    std::cout << " " << cu[i];
  std::cout << std::endl << "rl =";
  for( i = 0; i < nr; ++i )
    std::cout << " " << rl[i];
  std::cout << std::endl << "ru =";
  for( i = 0; i < nr; ++i )
    std::cout << " " << ru[i];
  std::cout << std::endl;
}
예제 #2
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_;
}