MC_lp_branch.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 
4 #include <cstdio>
5 #include <algorithm>
6 
7 #include "CoinTime.hpp"
8 
9 #include "OsiVolSolverInterface.hpp"
10 #include "OsiClpSolverInterface.hpp"
11 #include "ClpDualRowSteepest.hpp"
12 #include "ClpPrimalColumnSteepest.hpp"
13 #include "ClpSimplex.hpp"
14 
15 #include "MC_lp.hpp"
16 
17 #include "BCP_math.hpp"
18 #include "BCP_lp.hpp"
19 #include "BCP_lp_node.hpp"
20 #include "BCP_lp_functions.hpp"
21 
22 //#############################################################################
23 
24 bool
25 MC_lp::is_gap_tailoff_rel(const int k, const double minimp,
26  const double objval) const
27 {
28  const int iteration_count = current_iteration();
29  if (k <= 0 || iteration_count <= k)
30  return false;
31 
32  const int hist_size = CoinMin(iteration_count, hist_len);
33  const double* obj_k_hist = objhist + (hist_size - k);
34 
35  // There is tailing off if in the last k steps we haven't closed a certain
36  // fraction of the gap
37  const double ub = upper_bound();
38  return ((ub - objval) > (ub - obj_k_hist[0]) * (1-minimp));
39 }
40 
41 //#############################################################################
42 
43 bool
44 MC_lp::is_lb_tailoff_rel(const int k, const double minimp,
45  const double objval) const
46 {
47  const int iteration_count = current_iteration();
48  if (k <= 0 || iteration_count <= k)
49  return false;
50 
51  const int hist_size = CoinMin(iteration_count, hist_len);
52  const double* obj_k_hist = objhist + (hist_size - k);
53 
54  // There is tailing off if in the last k steps we haven't increased the lb
55  return (objval - obj_k_hist[0] < minimp * CoinAbs(obj_k_hist[0]));
56 }
57 
58 //#############################################################################
59 
60 bool
61 MC_lp::is_lb_tailoff_abs(const int k, const double minimp,
62  const double objval) const
63 {
64 // printf("k: %i iteration_count: %i hist_len: %i\n",
65 // k, current_iteration(), hist_len);
66  const int iteration_count = current_iteration();
67  if (k <= 0 || iteration_count <= k)
68  return false;
69 
70  const int hist_size = CoinMin(iteration_count, hist_len);
71  const double* obj_k_hist = objhist + (hist_size - k);
72 
73  // There is tailing off if in the last k steps we haven't increased the lb
74  return (objval - obj_k_hist[0] < minimp);
75 }
76 
77 //#############################################################################
78 
79 void
80 MC_lp::tailoff_test(bool& tailoff_gap_rel, bool& tailoff_lb_abs,
81  bool& tailoff_lb_rel, const double objval) const
82 {
83  tailoff_gap_rel =
86  objval);
87  tailoff_lb_abs =
90  objval);
91  tailoff_lb_rel =
94  objval);
95  const int iteration_count = current_iteration();
96  const int hist_size = CoinMin(iteration_count - 1, hist_len);
97  printf("MC: Tailoff check: objval: %.3f, UB: %.0f\n",
98  objval, upper_bound());
99  for (int i = hist_size - 1; i >= 0; --i) {
100  printf(" LB[%3i]: %.3f\n", i-hist_size, objhist[i]);
101  }
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);
106 }
107 
108 //#############################################################################
109 
110 /* Return true if solved to optimality (otherwise the node can be fathomed) */
111 bool
112 MC_solveClp(ClpSimplex& clp_simplex, OsiVolSolverInterface* vollp)
113 {
114  double t = CoinCpuTime();
115 
116  // Set message handler to have same levels etc
117  // clp_simplex.passInMessageHandler(clp->messageHandler());
118  // set reasonable defaults
119  clp_simplex.scaling(0); // this is 1 in OsiClpSolverInterface
120  ClpDualRowSteepest steep;
121  clp_simplex.setDualRowPivotAlgorithm(steep);
122  ClpPrimalColumnSteepest steepP;
123  clp_simplex.setPrimalColumnPivotAlgorithm(steepP);
124 
125  ClpSolve clp_options;
126  // useDual, usePrimal, usePrimalorSprint, automatic
127  clp_options.setSolveType(ClpSolve::useDual);
128  // presolveOn, presolveOff, presolveNumber
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);
154 
155  t = CoinCpuTime() - t;
156  printf("LP: exact optimization took %.3f seconds\n", t);
157 
158  if (clp_simplex.isProvenPrimalInfeasible()) {
159  printf("MC: Solving LP to optimality: infeas.\n");
160  printf("MC: Forcing BCP to prune the node.\n");
161  return false;
162  }
163  return true;
164 }
165 
166 //#############################################################################
167 
168 OsiSolverInterface*
169 MC_lp::solveToOpt(OsiVolSolverInterface* vollp,
170  const BCP_lp_result& lpres,
171  const BCP_vec<BCP_var*>& vars,
172  const BCP_vec<BCP_cut*>& cuts,
173  double& exact_obj)
174 {
175  if ((par.entry(MC_lp_par::LpSolver) & MC_UseClp) == 0) {
176  throw BCP_fatal_error("\
177 MC_lp::solveToOpt: got here but no simplex based solver is enabled in the\n\
178  MC_LpSolver parameter.\n");
179  }
180 
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();
186 
188  ClpSimplex clp_slack(clp);
189  ClpSimplex& model = clp;
190  ClpSimplex& model2 = clp_slack;
191 
192  int numcols = model.numberColumns();
193  int numrows = model.numberRows();
194 
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];
200 
201  double * lower = model2.rowLower();
202  double * upper = model2.rowUpper();
203  int iRow, iColumn;
204  // Simplest is to change all rhs to zero
205  // One should skip E rows but this is simpler coding
206  for (iRow=0;iRow<numrows;iRow++) {
207  newUpper[iRow]=upper[iRow];
208  upper[iRow]=0.0;
209  newLower[iRow]=lower[iRow];
210  lower[iRow]=0.0;
211  addRow[iRow]=iRow;
212  addElement[iRow]=-1.0;
213  addStarts[iRow]=iRow;
214  }
215  addStarts[numrows]=numrows;
216  model2.addColumns(numrows,newLower,newUpper,NULL,
217  addStarts,addRow,addElement);
218  delete [] addStarts;
219  delete [] addRow;
220  delete [] addElement;
221  delete [] newLower;
222  delete [] newUpper;
223 
224  // Modify costs
225  model2.transposeTimes(1.0,vollp->getRowPrice(),model2.objective());
226  // solve
227  if (!MC_solveClp(model2, vollp)) {
228  delete solver;
229  return NULL;
230  }
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);
238  }
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);
244  }
245  solver->setWarmStart(&basis);
246  solver->resolve();
247  } else {
248  if (!MC_solveClp(clp, vollp)) {
249  delete solver;
250  return NULL;
251  }
252  }
253 
254  exact_obj = solver->getObjValue();
255 
256  soln = mc_generate_heuristic_solution(solver->getColSolution(), vars, cuts);
257  if (soln && soln->objective_value() < upper_bound()) {
259  }
260 
261  // Run the heuristics.
262  printf("MC: Solving LP to optimality before branching: %.3f",
263  exact_obj);
264  const double gap =
266  printf(" Gap: %.3f\n",gap);
267  if (gap < 0) {
268  printf("MC: exact LP solving proved fathomability.\n");
269  delete solver;
270  return NULL;
271  }
272 
273  // In any case, do a reduced cost fixing here.
274  int fix = 0;
275  reduced_cost_fixing(solver->getReducedCost(), solver->getColSolution(), gap,
276  // need to do this since rc_fixing expects non-const
277  getLpProblemPointer()->node->vars, fix);
278  printf("MC: rc fixing with exact opt and dj of exact fixed %i vars.\n", fix);
279  return solver;
280 }
281 
282 //#############################################################################
283 
284 void
286  const int cand_num,
288 {
289  // Try to branch on the variables when they are ordered by abs((distance
290  // from integrality) * cost)
291  const int m = mc.num_edges;
292  const MC_graph_edge* edges = mc.edges;
293 
294  BCP_vec<int> perm;
295  perm.reserve(m);
296 
297  BCP_vec<double> dist;
298  dist.reserve(m);
299 
300  const double etol = par.entry(MC_lp_par::IntegerTolerance);
301 
302  int i;
303 
304  // If it's an Ising problem AND there's an external field then check only
305  // the edges coming out of the external node
306  if (mc.ising_triangles) {
307  const int grid = static_cast<int>(sqrt(mc.num_nodes + 1.0));
308  i = 2 * grid * grid; // number of grid edges
309  } else {
310  i = 0;
311  }
312  for ( ; i < m; ++i) {
313  const double xi = x[i];
314  if (xi > etol && xi < 1-etol) {
315  perm.unchecked_push_back(i);
316  const double w = (0.5 - CoinAbs(xi-0.5)) * edges[i].cost;
317  dist.unchecked_push_back(-CoinAbs(w));
318  }
319  }
320 
321  const int distsize = dist.size();
322  if (distsize > cand_num) {
323  CoinSort_2(dist.begin(), dist.end(), perm.begin());
324  perm.erase(perm.entry(cand_num), perm.end());
325  }
326 
327  if (perm.size() > 0) {
328  append_branching_vars(x, vars, perm, cands);
329  }
330 }
331 
332 //#############################################################################
333 
336  const BCP_vec<BCP_var*>& vars,
337  const BCP_vec<BCP_cut*>& cuts,
338  const BCP_lp_var_pool& local_var_pool,
339  const BCP_lp_cut_pool& local_cut_pool,
341  bool force_branch)
342 {
343  OsiSolverInterface* lp = getLpProblemPointer()->lp_solver;
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;
350 
351  const int solver_t = par.entry(MC_lp_par::LpSolver);
352  const bool has_vol = (solver_t & MC_UseVol);
353  const bool has_simplex = (solver_t & MC_UseClp);
354 
355  int pool_size = local_cut_pool.size();
356 
357  if (current_index() != 0 && has_vol && has_simplex) {
358  started_exact = true;
359  }
360 
361  const int iteration_count = current_iteration();
362  bool solve_to_opt = false;
363 
364  if (started_exact) {
365  // must be has_vol && has_simplex
366  solve_to_opt = true;
367  } else {
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))) {
371  solve_to_opt = true;
372  }
373  }
374 
375  if (solve_to_opt) {
376  exact_solver = solveToOpt(vollp, lpres, vars, cuts, objval);
378  started_exact = true;
379  }
380  if (exact_solver == NULL)
382  tailoff_test(tailoff_gap_rel, tailoff_lb_abs, tailoff_lb_rel, objval);
383 
384  // Generate cuts from the exact soln (if there's any)
387  BCP_vec<BCP_cut*> new_cuts;
388  BCP_vec<BCP_row*> new_rows;
389  generate_cuts_in_lp(exact_solver->getColSolution(),
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) {
395  cp.reserve(cp.size() + new_size);
396  if (new_rows.size() == 0) {
397  new_rows.reserve(new_size);
398  cuts_to_rows(vars, new_cuts, new_rows,
399  lpres, BCP_Object_FromGenerator, false);
400  }
401  for (int i = 0; i < new_size; ++i) {
402  new_cuts[i]->set_bcpind(-BCP_lp_next_cut_index(*p));
403  cp.unchecked_push_back(new BCP_lp_waiting_row(new_cuts[i],
404  new_rows[i]));
405  }
406  }
407  printf("MC: Generated %i cuts from exact solution.\n", new_size);
408  pool_size = cp.size();
409 
416  // swap solvers
417  getLpProblemPointer()->lp_solver = exact_solver;
418  getLpProblemPointer()->master_lp = new OsiClpSolverInterface;
419  getLpProblemPointer()->lp_result->get_results(*exact_solver);
420  exact_solver = 0;
421  delete vollp;
422  vollp = 0;
423  // Now it is possible (though highly unlikely) that:
424  // No cut was found for volume, there's tailoff even with the exact
425  // opt, and the exact solution IS the opt solution (so no cut for
426  // that one either). In this case (after switching to the simplex
427  // solver) we can't branch, but we can't add a cut either. Best is
428  // just to go back and force another round (feasibility will be
429  // discovered there).
430  return BCP_DoNotBranch;
431  }
432  }
433 
434  // Update the history
435  if (iteration_count > hist_len) {
436  if (objval < objhist[hist_len-1]) {
437  objval = objhist[hist_len-1];
438  }
439  std::rotate(objhist, objhist+1, objhist+hist_len);
440  objhist[hist_len-1] = objval;
441  } else {
442  if (iteration_count > 1) {
443  if (objval < objhist[iteration_count-2]) {
444  objval = objhist[iteration_count-2];
445  }
446  }
447  objhist[iteration_count-1] = objval;
448  }
449 
450  if (pool_size != 0 &&
451  !(tailoff_gap_rel && (tailoff_lb_abs || tailoff_lb_rel))) {
452  delete exact_solver;
453  return BCP_DoNotBranch;
454  }
455 
456  // OK, we need to branch (or fathom if there's a limit on the depth)
458  printf("MC: Maximum depth reached, pruning node.\n");
460  }
461 
462  // As a last ditch effort, try to solve the problem to optimality to see if
463  // we can fathom the node
464  if (vollp && !exact_solver) {
465  exact_solver = solveToOpt(vollp, lpres, vars, cuts, objval);
466  if (exact_solver == NULL) {
468  }
469  }
470 
471  // OK, branch
472 
473  choose_branching_vars(vars, lpres.x(),
475 
476  if (cands.size() == 0) {
477  // Now THIS is impossible. Well, no... However unlikely, it is possible
478  // that we had tailing off, had an integer solution and had violated
479  // cycle inequalities. Absurd, isn't it? But it did happen to me...
480  // In this case just continue...
481  if (local_cut_pool.size() == 0) {
482  throw BCP_fatal_error("What the heck?! No cuts, integer & tailoff!\n");
483  }
484  delete exact_solver;
485  return BCP_DoNotBranch;
486  }
487 
488  // If we have an exact solver (i.e., we used volume) then perform the strong
489  // branching ourselves. It's way faster to do it with the simplex. And it
490  // may be better, too.
491  // BTW, this routine just throws out all but one candidate from cands.
492  if (exact_solver) {
493  perform_strong_branching(lpres, exact_solver, cands);
494  delete exact_solver;
495  }
496 
497  return BCP_DoBranch;
498 }
499 
500 //#############################################################################
501 
504  BCP_presolved_lp_brobj* oldobj)
505 {
506  // *FIXME*: For now just use the default, later we might want to choose the
507  // one that makes things more integral.
508  return BCP_lp_user::compare_branching_candidates(newobj, oldobj);
509 }
510 
511 //#############################################################################
512 
513 void
515 {
516  // We have stored our own presolved brobj if we performed strong branching.
517  // In that case just initialize the action vector then swap best with
518  // best_presolved, and finally let BCP adjust the actions for the children
519  if (best_presolved) {
520  best->swap(*best_presolved);
521  delete best_presolved;
522  best_presolved = 0;
523  }
525 }
526 
527 //#############################################################################
528 
529 
530 void
532  OsiSolverInterface* exact_solver,
534 {
535  int i;
536 
537  // prepare for strong branching
538  exact_solver->markHotStart();
539 
540  // Look at the candidates one-by-one and presolve them.
542 
543  printf("\n\
544 MC: Starting strong branching (the objective is transformed!):\
545  The objective shift is %.4f\n\n", obj_shift);
546 
547  assert(best_presolved == 0);
548  int best_fathom_child = 0;
549  double best_objsum = BCP_DBL_MAX;
550  BCP_vec<double> tmpobj;
551 
552  for (cani = cands.begin(); cani != cands.end(); ++cani){
553  // Create a temporary branching object to hold the current results
554  BCP_presolved_lp_brobj* tmp_presolved= new BCP_presolved_lp_brobj(*cani);
555  const BCP_lp_branching_object* can = *cani;
556  for (i = 0; i < can->child_num; ++i){
557  can->apply_child_bd(exact_solver, i);
558  exact_solver->solveFromHotStart();
559  tmp_presolved->get_results(*exact_solver, i);
560  }
561  // add the shift to the objective values
562  tmp_presolved->get_lower_bounds(tmpobj);
563  for (i = 0; i < can->child_num; ++i) {
564  tmpobj[i] += obj_shift;
565  }
566  tmp_presolved->set_lower_bounds(tmpobj);
567  // reset the bounds of the affected var
568  const int bvar_ind = (*can->forced_var_pos)[0];
569  exact_solver->setColBounds(bvar_ind, 0.0, 1.0);
571  printf("MC strong branch: Presolving:");
573  can->print_branching_info(exact_solver->getNumCols(), lpres.x(),
574  exact_solver->getObjCoefficients());
575  }
576  for (i = 0; i < can->child_num; ++i) {
577  const BCP_lp_result& res = tmp_presolved->lpres(i);
578  const double lb = res.objval();
579  printf((lb > BCP_DBL_MAX / 10 ? " [%e,%i,%i]" : " [%.4f,%i,%i]"),
580  lb, res.termcode(), res.iternum());
581  }
582  printf("\n");
583  }
584 
585  // Compare the current one with the best so far
586  // First see how many children would be fathomed
587  int fathom_child = 0;
588  double objsum = 0.0;
589  for (i = 0; i < can->child_num; ++i) {
590  const BCP_lp_result& res = tmp_presolved->lpres(i);
591  if (res.termcode() == BCP_ProvenPrimalInf) {
592  ++fathom_child;
593  continue;
594  }
595  if (res.termcode() == BCP_ProvenOptimal &&
597  upper_bound()) {
598  ++fathom_child;
599  continue;
600  }
601  objsum += res.objval();
602  }
603  if (best_fathom_child < fathom_child) {
604  std::swap(tmp_presolved, best_presolved);
605  best_fathom_child = fathom_child;
606  delete tmp_presolved;
607  if (best_fathom_child == can->child_num) {
608  purge_ptr_vector(cands, cani + 1, cands.end());
609  }
610  best_objsum = objsum;
611  continue;
612  }
613 
614  if (objsum < best_objsum) {
615  best_objsum = objsum;
616  std::swap(tmp_presolved, best_presolved);
617  }
618  delete tmp_presolved;
619  }
620 
621  // indicate to the lp solver that strong branching is done
622  exact_solver->unmarkHotStart();
623 
624  // delete all the candidates but the selected one
626  for (cani = cands.begin(); cani != cands.end(); ++cani) {
627  if (*cani != can)
628  delete *cani;
629  }
630 
631  cands.clear();
632  cands.push_back(can);
633 }
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
Definition: BCP_lp_user.cpp:51
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...
int num_edges
Definition: MC.hpp:92
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.
Definition: BCP_lp.hpp:168
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.
BCP_var_set vars
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.
int num_nodes
Definition: MC.hpp:91
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
MC_graph_edge * edges
Definition: MC.hpp:95
double * objhist
Definition: MC_lp.hpp:27
OsiSolverInterface * master_lp
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:135
void set_param(const BCP_lp_par::chr_params key, const bool val)
Definition: BCP_lp_user.cpp:63
int current_level() const
Return the level of the search tree node being processed.
Definition: BCP_lp_user.cpp:32
int current_index() const
Return the internal index of the search tree node being processed.
Definition: BCP_lp_user.cpp:33
iterator begin()
Return an iterator to the beginning of the object.
Definition: BCP_vector.hpp:99
BCP should continue to work on this node.
const double * x() const
NO OLD DOC.
Definition: BCP_lp.hpp:102
void reserve(const size_t n)
Reallocate the object to make space for n entries.
int * ising_triangles
Definition: MC.hpp:107
int current_iteration() const
Return the iteration count within the search tree node being processed.
Definition: BCP_lp_user.cpp:34
MC_solution * soln
Definition: MC_lp.hpp:30
bool started_exact
Definition: MC_lp.hpp:32
void push_back(const_reference x)
Append x to the end of the vector.
BCP_parameter_set< MC_lp_par > par
Definition: MC_lp.hpp:21
double obj_shift
Definition: MC_lp.hpp:38
#define BCP_DBL_MAX
Definition: BCP_math.hpp:6
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...
Definition: MC_lp.cpp:356
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
Definition: BCP_lp.hpp:193
int iternum() const
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.
Definition: BCP_lp_user.hpp:95
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.
Definition: BCP_lp.hpp:137
void set_entry(const chr_params key, const char val)
BCP_lp_result * lp_result
Definition: BCP_lp.hpp:185
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.
double objval() const
void fint fint * k
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.
Definition: MC_solution.hpp:27
int hist_len
Definition: MC_lp.hpp:26
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)
Definition: BCP_lp_user.cpp:29
BCP_vec< int > * forced_var_pos
Positions of variables whose bounds change (&quot;forcibly&quot;, by branching) in the children.
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
The node should be fathomed without even trying to branch.
A presolved branching object candidate.
BCP_presolved_lp_brobj * best_presolved
Definition: MC_lp.hpp:40
The object was generated by a variable or cut generator.
Definition: BCP_enum.hpp:257
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
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.
Definition: BCP_vector.hpp:104
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.
Definition: MC_lp.cpp:241
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.
Definition: BCP_vector.hpp:266
BCP_branching_object_relation
This enumerative constant is the return value of the compare_presolved_branching_objects() method in ...
int termcode() const
void fint * m
BCP_lp_prob * p
Definition: BCP_lp_user.hpp:82
This class holds the results after solving an LP relaxation.
Branching must be done.
iterator entry(const int i)
Return an iterator to the i-th entry.
Definition: BCP_vector.hpp:109
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.
static char * t
Definition: OSdtoa.cpp:3645
void send_feasible_solution(const BCP_solution *sol)
Definition: BCP_lp_user.cpp:77
void choose_branching_vars(const BCP_vec< BCP_var * > &vars, const double *x, const int cand_num, BCP_vec< BCP_lp_branching_object * > &cands)
MC_problem mc
Definition: MC_lp.hpp:22
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.
Definition: MC_lp.cpp:581