7 #include "CoinTime.hpp"
9 #include "OsiVolSolverInterface.hpp"
10 #include "OsiClpSolverInterface.hpp"
11 #include "ClpDualRowSteepest.hpp"
12 #include "ClpPrimalColumnSteepest.hpp"
13 #include "ClpSimplex.hpp"
26 const double objval)
const
29 if (k <= 0 || iteration_count <= k)
32 const int hist_size = CoinMin(iteration_count,
hist_len);
33 const double* obj_k_hist =
objhist + (hist_size -
k);
38 return ((ub - objval) > (ub - obj_k_hist[0]) * (1-minimp));
45 const double objval)
const
48 if (k <= 0 || iteration_count <= k)
51 const int hist_size = CoinMin(iteration_count,
hist_len);
52 const double* obj_k_hist =
objhist + (hist_size -
k);
55 return (objval - obj_k_hist[0] < minimp * CoinAbs(obj_k_hist[0]));
62 const double objval)
const
67 if (k <= 0 || iteration_count <= k)
70 const int hist_size = CoinMin(iteration_count,
hist_len);
71 const double* obj_k_hist =
objhist + (hist_size -
k);
74 return (objval - obj_k_hist[0] < minimp);
81 bool& tailoff_lb_rel,
const double objval)
const
96 const int hist_size = CoinMin(iteration_count - 1,
hist_len);
97 printf(
"MC: Tailoff check: objval: %.3f, UB: %.0f\n",
99 for (
int i = hist_size - 1; i >= 0; --i) {
100 printf(
" LB[%3i]: %.3f\n", i-hist_size,
objhist[i]);
102 printf(
" gap_rel: %i lb_abs: %i lb_rel: %i\n",
103 tailoff_gap_rel ? 1 : 0,
104 tailoff_lb_abs ? 1 : 0,
105 tailoff_lb_rel ? 1 : 0);
112 MC_solveClp(ClpSimplex& clp_simplex, OsiVolSolverInterface* vollp)
114 double t = CoinCpuTime();
119 clp_simplex.scaling(0);
120 ClpDualRowSteepest steep;
121 clp_simplex.setDualRowPivotAlgorithm(steep);
122 ClpPrimalColumnSteepest steepP;
123 clp_simplex.setPrimalColumnPivotAlgorithm(steepP);
125 ClpSolve clp_options;
127 clp_options.setSolveType(ClpSolve::useDual);
129 clp_options.setPresolveType(ClpSolve::presolveOn);
150 clp_options.setSpecialOption(0, 1);
151 clp_options.setSpecialOption(2, 0);
152 clp_options.setSpecialOption(3, 0);
153 clp_simplex.initialSolve(clp_options);
155 t = CoinCpuTime() -
t;
156 printf(
"LP: exact optimization took %.3f seconds\n", t);
158 if (clp_simplex.isProvenPrimalInfeasible()) {
159 printf(
"MC: Solving LP to optimality: infeas.\n");
160 printf(
"MC: Forcing BCP to prune the node.\n");
177 MC_lp::solveToOpt: got here but no simplex based solver is enabled in the\n\
178 MC_LpSolver parameter.\n");
181 OsiClpSolverInterface* solver =
new OsiClpSolverInterface;
182 solver->loadProblem(*vollp->getMatrixByCol(), vollp->getColLower(),
183 vollp->getColUpper(), vollp->getObjCoefficients(),
184 vollp->getRowLower(), vollp->getRowUpper());
185 ClpSimplex& clp = *solver->getModelPtr();
188 ClpSimplex clp_slack(clp);
189 ClpSimplex& model = clp;
190 ClpSimplex& model2 = clp_slack;
192 int numcols = model.numberColumns();
193 int numrows = model.numberRows();
195 int * addStarts =
new int [numrows+1];
196 int * addRow =
new int[numrows];
197 double * addElement =
new double[numrows];
198 double * newUpper =
new double[numrows];
199 double * newLower =
new double[numrows];
201 double * lower = model2.rowLower();
202 double * upper = model2.rowUpper();
206 for (iRow=0;iRow<numrows;iRow++) {
207 newUpper[iRow]=upper[iRow];
209 newLower[iRow]=lower[iRow];
212 addElement[iRow]=-1.0;
213 addStarts[iRow]=iRow;
215 addStarts[numrows]=numrows;
216 model2.addColumns(numrows,newLower,newUpper,NULL,
217 addStarts,addRow,addElement);
220 delete [] addElement;
225 model2.transposeTimes(1.0,vollp->getRowPrice(),model2.objective());
231 int lookup[]={0,1,2,3,0,3};
232 CoinWarmStartBasis basis;
233 basis.setSize(numcols,numrows);
234 for (iColumn = 0; iColumn < numcols; iColumn++) {
235 int iStatus = model2.getColumnStatus(iColumn);
236 iStatus = lookup[iStatus];
237 basis.setStructStatus(iColumn,(CoinWarmStartBasis::Status) iStatus);
239 for (iRow=0;iRow<numrows;iRow++) {
240 int iStatus = model2.getRowStatus(iRow) == ClpSimplex::basic ?
241 ClpSimplex::basic : model2.getColumnStatus(iRow+numcols);
242 iStatus = lookup[iStatus];
243 basis.setArtifStatus(iRow,(CoinWarmStartBasis::Status) iStatus);
245 solver->setWarmStart(&basis);
254 exact_obj = solver->getObjValue();
262 printf(
"MC: Solving LP to optimality before branching: %.3f",
266 printf(
" Gap: %.3f\n",gap);
268 printf(
"MC: exact LP solving proved fathomability.\n");
278 printf(
"MC: rc fixing with exact opt and dj of exact fixed %i vars.\n", fix);
307 const int grid =
static_cast<int>(sqrt(
mc.
num_nodes + 1.0));
312 for ( ; i <
m; ++i) {
313 const double xi = x[i];
314 if (xi > etol && xi < 1-etol) {
316 const double w = (0.5 - CoinAbs(xi-0.5)) * edges[i].cost;
321 const int distsize = dist.
size();
322 if (distsize > cand_num) {
327 if (perm.
size() > 0) {
344 OsiVolSolverInterface* vollp =
dynamic_cast<OsiVolSolverInterface*
>(
lp);
345 OsiSolverInterface* exact_solver = NULL;
346 double objval = lpres.
objval();
347 bool tailoff_gap_rel =
false;
348 bool tailoff_lb_abs =
false;
349 bool tailoff_lb_rel =
false;
352 const bool has_vol = (solver_t &
MC_UseVol);
353 const bool has_simplex = (solver_t &
MC_UseClp);
355 int pool_size = local_cut_pool.
size();
362 bool solve_to_opt =
false;
368 tailoff_test(tailoff_gap_rel, tailoff_lb_abs, tailoff_lb_rel, objval);
369 if (has_vol && has_simplex &&
370 (tailoff_gap_rel && (tailoff_lb_abs || tailoff_lb_rel))) {
376 exact_solver =
solveToOpt(vollp, lpres, vars, cuts, objval);
380 if (exact_solver == NULL)
382 tailoff_test(tailoff_gap_rel, tailoff_lb_abs, tailoff_lb_rel, objval);
390 exact_solver->getRowActivity(),
391 exact_solver->getObjValue(),
392 vars, cuts, new_cuts, new_rows);
393 const int new_size = new_cuts.size();
394 if (new_rows.
size() != 0) {
396 if (new_rows.
size() == 0) {
401 for (
int i = 0; i < new_size; ++i) {
407 printf(
"MC: Generated %i cuts from exact solution.\n", new_size);
408 pool_size = cp.
size();
442 if (iteration_count > 1) {
443 if (objval <
objhist[iteration_count-2]) {
444 objval =
objhist[iteration_count-2];
447 objhist[iteration_count-1] = objval;
450 if (pool_size != 0 &&
451 !(tailoff_gap_rel && (tailoff_lb_abs || tailoff_lb_rel))) {
458 printf(
"MC: Maximum depth reached, pruning node.\n");
464 if (vollp && !exact_solver) {
465 exact_solver =
solveToOpt(vollp, lpres, vars, cuts, objval);
466 if (exact_solver == NULL) {
476 if (cands.
size() == 0) {
481 if (local_cut_pool.
size() == 0) {
482 throw BCP_fatal_error(
"What the heck?! No cuts, integer & tailoff!\n");
532 OsiSolverInterface* exact_solver,
538 exact_solver->markHotStart();
544 MC: Starting strong branching (the objective is transformed!):\
545 The objective shift is %.4f\n\n",
obj_shift);
548 int best_fathom_child = 0;
552 for (cani = cands.
begin(); cani != cands.
end(); ++cani){
558 exact_solver->solveFromHotStart();
569 exact_solver->setColBounds(bvar_ind, 0.0, 1.0);
571 printf(
"MC strong branch: Presolving:");
574 exact_solver->getObjCoefficients());
578 const double lb = res.
objval();
579 printf((lb >
BCP_DBL_MAX / 10 ?
" [%e,%i,%i]" :
" [%.4f,%i,%i]"),
587 int fathom_child = 0;
603 if (best_fathom_child < fathom_child) {
605 best_fathom_child = fathom_child;
606 delete tmp_presolved;
607 if (best_fathom_child == can->
child_num) {
610 best_objsum = objsum;
614 if (objsum < best_objsum) {
615 best_objsum = objsum;
618 delete tmp_presolved;
622 exact_solver->unmarkHotStart();
626 for (cani = cands.
begin(); cani != cands.
end(); ++cani) {
virtual BCP_branching_object_relation compare_branching_candidates(BCP_presolved_lp_brobj *new_presolved, BCP_presolved_lp_brobj *old_presolved)
Decide which branching object is preferred for branching.
char get_param(const BCP_lp_par::chr_params key) const
void apply_child_bd(OsiSolverInterface *lp, const int child_ind) const
This method invokes the appropriate methods of lp to apply the forced and implied bound changes of th...
Upper limit on the number of iterations performed in each of the children of the search tree node whe...
BCP_lp_node * node
Description he current search tree node.
The minimum difference between the objective value of any two feasible solution (with different objec...
void clear()
Delete every entry.
void reduced_cost_fixing(const double *dj, const double *x, const double gap, BCP_vec< BCP_var * > &vars, int &newly_changed)
Reduced cost fixing.
void print_branching_info(const int orig_varnum, const double *x, const double *obj) const
This method prints out some information about the branching object.
bool is_lb_tailoff_rel(const int k, const double minimp, const double objval) const
virtual BCP_branching_object_relation compare_branching_candidates(BCP_presolved_lp_brobj *new_solved, BCP_presolved_lp_brobj *old_solved)
Decide which branching object is preferred for branching.
void perform_strong_branching(const BCP_lp_result &lpres, OsiSolverInterface *exact_solver, BCP_vec< BCP_lp_branching_object * > &cands)
char entry(const chr_params key) const
OsiSolverInterface * master_lp
A class that holds the methods about how to pack things.
void set_param(const BCP_lp_par::chr_params key, const bool val)
int current_level() const
Return the level of the search tree node being processed.
int current_index() const
Return the internal index of the search tree node being processed.
iterator begin()
Return an iterator to the beginning of the object.
BCP should continue to work on this node.
void reserve(const size_t n)
Reallocate the object to make space for n entries.
int current_iteration() const
Return the iteration count within the search tree node being processed.
void push_back(const_reference x)
Append x to the end of the vector.
BCP_parameter_set< MC_lp_par > par
virtual void cuts_to_rows(const BCP_vec< BCP_var * > &vars, BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_row * > &rows, const BCP_lp_result &lpres, BCP_object_origin origin, bool allow_multiple)
Convert (and possibly lift) a set of cuts into corresponding rows for the current LP relaxation...
virtual void set_actions_for_children(BCP_presolved_lp_brobj *best)
Decide what to do with the children of the selected branching object.
void get_lower_bounds(BCP_vec< double > &obj)
Fill up obj with the lower bound on each child.
BCP_lp_cut_pool * local_cut_pool
int BCP_lp_next_cut_index(BCP_lp_prob &p)
void erase(iterator pos)
Erase the entry pointed to by pos.
void fint fint fint real fint real real real real real real real real real fint real fint * lp
BCP_lp_prob * getLpProblemPointer()
Get the pointer.
void get_results(OsiSolverInterface &lp, const int child_ind)
Extract the lp results from the LP solver for the child_ind-th child.
OsiSolverInterface * solveToOpt(OsiVolSolverInterface *vollp, const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, double &exact_obj)
OsiSolverInterface * lp_solver
A class that holds the methods about how to pack things.
void set_entry(const chr_params key, const char val)
BCP_lp_result * lp_result
int child_num
The number of children for this branching object.
void append_branching_vars(const double *x, const BCP_vec< BCP_var * > &vars, const BCP_vec< int > &select_pos, BCP_vec< BCP_lp_branching_object * > &candidates)
This helper method creates branching variable candidates and appends them to cans.
This class describes a generic branching object.
void tailoff_test(bool &tailoff_gap_rel, bool &tailoff_lb_abs, bool &tailoff_lb_rel, const double objval) const
bool MC_solveClp(ClpSimplex &clp_simplex, OsiVolSolverInterface *vollp)
BCP_branching_decision
This enumerative constant is the return value of the select_branching_candidates() method in [BCP_lp_...
const BCP_lp_result & lpres(const int child_ind) const
Return a const reference to the presolved results of the child_ind-th child.
virtual double objective_value() const
The method returning the objective value of the solution.
virtual void set_actions_for_children(BCP_presolved_lp_brobj *best)
Decide what to do with the children of the selected branching object.
double upper_bound() const
Return what is the best known upper bound (might be BCP_DBL_MAX)
BCP_vec< int > * forced_var_pos
Positions of variables whose bounds change ("forcibly", by branching) in the children.
Currently there isn't any error handling in BCP.
The node should be fathomed without even trying to branch.
A presolved branching object candidate.
BCP_presolved_lp_brobj * best_presolved
The object was generated by a variable or cut generator.
size_t size() const
Return the current number of entries.
void set_lower_bounds(const BCP_vec< double > &obj)
Fill up the lower bounds on the children with the content of obj.
iterator end()
Return an iterator to the end of the object.
Print information on the presolved branching candidates during strong branching.
void swap(BCP_presolved_lp_brobj &rhs)
swap the two presolved branching object
MC_solution * mc_generate_heuristic_solution(const double *x, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
A local helper function.
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
bool is_lb_tailoff_abs(const int k, const double minimp, const double objval) const
void get_results(OsiSolverInterface &lp_solver)
Get the result from the LP solver.
void purge_ptr_vector(BCP_vec< T * > &pvec, typename BCP_vec< T * >::iterator first, typename BCP_vec< T * >::iterator last)
This function purges the entries [first,last) from the vector of pointers pvec.
BCP_branching_object_relation
This enumerative constant is the return value of the compare_presolved_branching_objects() method in ...
This class holds the results after solving an LP relaxation.
iterator entry(const int i)
Return an iterator to the i-th entry.
void fint fint fint real fint real real real real real real real real * w
BCP_lp_branching_object * candidate()
Return a pointer to the candidate.
void send_feasible_solution(const BCP_solution *sol)
void choose_branching_vars(const BCP_vec< BCP_var * > &vars, const double *x, const int cand_num, BCP_vec< BCP_lp_branching_object * > &cands)
virtual BCP_branching_decision select_branching_candidates(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const BCP_lp_var_pool &local_var_pool, const BCP_lp_cut_pool &local_cut_pool, BCP_vec< BCP_lp_branching_object * > &candidates, bool force_branch=false)
Decide whether to branch or not and select a set of branching candidates if branching is decided upon...
The maximum number of violated valid inequalities that can be added per iteration.
Print detailed information about all the branching candidates during strong branching.
bool is_gap_tailoff_rel(const int k, const double minimp, const double objval) const
void fint fint fint real fint real * x
virtual void generate_cuts_in_lp(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows)
Generate cuts within the LP process.