// copy constructor LorentzCone::LorentzCone(LorentzCone const & other): Cone(other) { size_ = other.size(); // copy members members_ = new int[size_]; int const * other_members = other.members(); std::copy(other_members, other_members+size_, members_); }
void ColaModel::getConicConstraint(int index, OsiLorentzConeType & type, int & numMembers, int *& members) const { ConeType t = cones_[index]->type(); if (t==SCALED) { std::cerr << "this function is for Lorentz cones!" << std::endl; throw std::exception(); } if (t==LORENTZ) type = OSI_QUAD; else if (t==RLORENTZ) type = OSI_RQUAD; numMembers = cones_[index]->size(); members = new int[numMembers]; LorentzCone * c = dynamic_cast<LorentzCone*>(cones_[index]); const int * m = c->members(); std::copy(m, m+numMembers, members); }
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_; }
// 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 }
// 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 }