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; }
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_; }