BCP_lp_branching.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 //#include <cfloat>
4 #include <cstdio>
5 #include <numeric>
6 #include <utility> // for pair<>
7 
8 #include "CoinWarmStart.hpp"
9 #include "CoinTime.hpp"
10 
11 #include "BCP_math.hpp"
12 #include "BCP_enum.hpp"
13 #include "BCP_matrix.hpp"
14 #include "BCP_warmstart.hpp"
15 #include "BCP_lp_result.hpp"
16 #include "BCP_lp_node.hpp"
17 #include "BCP_lp_user.hpp"
18 #include "BCP_lp_functions.hpp"
19 #include "BCP_lp_pool.hpp"
20 #include "BCP_lp_branch.hpp"
21 #include "BCP_lp.hpp"
22 
23 //#############################################################################
24 
25 static inline std::pair<int,int>
28 static inline void
30  const BCP_lp_branching_object* can,
31  const int added_col_num,
32  const int added_row_num);
33 static inline BCP_branching_decision
35  BCP_presolved_lp_brobj*& best_presolved);
36 static inline void
38 
39 //#############################################################################
40 
41 static inline void
43  const int orig_varnum,
44  const int candidate_num, const int selected,
45  const BCP_presolved_lp_brobj* best_presolved)
46 {
47  const BCP_lp_branching_object* can = best_presolved->candidate();
48 
50  p.user->print(true, "\nLP: SB selected candidate %i out of %i.\n\n",
51  selected, candidate_num);
52  p.user->print(true, "LP: The selected object is:");
54  can->print_branching_info(orig_varnum,
55  p.lp_result->x(),
56  p.lp_solver->getObjCoefficients());
57  }
58  for (int i = 0; i < can->child_num; ++i) {
59  const BCP_lp_result& res = best_presolved->lpres(i);
60  const double lb = res.objval();
61  p.user->print(true,
62  (lb>BCP_DBL_MAX/10 ? " [%e,%i,%i]":" [%.4f,%i,%i]"),
63  lb, res.termcode(), res.iternum());
64  }
65  p.user->print(true, "\n");
66  }
67  // Print some statistics
69  const BCP_vec<BCP_child_action>& action = best_presolved->action();
70  for (int i = can->child_num - 1; i >= 0; --i)
71  switch (action[i]){
72  case BCP_KeepChild:
73  case BCP_ReturnChild:
74  break;
75  case BCP_FathomChild:
76  p.user->print(true, "LP: Child %i is fathomed.\n", i);
77  break;
78  }
79  }
80 }
81 
82 //#############################################################################
83 
84 static inline std::pair<int,int>
87  // to make things short
88  if (candidates.size() == 0)
89  return std::pair<int,int>(0, 0);
90 
93  BCP_vec<BCP_lp_branching_object*>::iterator lastcani = candidates.end();
94  BCP_var_set& vars = p.node->vars;
95  BCP_cut_set& cuts = p.node->cuts;
96 
97  // first count the number of cols/rows to add
98  int newvar_num = 0;
99  int newcut_num = 0;
100  for (cani = candidates.begin(); cani != lastcani; ++cani){
101  can = *cani;
102  can->init_pos_for_added(vars.size() + newvar_num,
103  cuts.size() + newcut_num);
104  if (can->vars_to_add)
105  newvar_num += can->vars_to_add->size();
106  if (can->cuts_to_add)
107  newcut_num += can->cuts_to_add->size();
108  }
109 
110  const int orig_col_num = vars.size();
111  const int orig_row_num = cuts.size();
112 
113  OsiSolverInterface* lp = p.lp_solver;
114 
115  // deal with the vars
116  if (newvar_num > 0){
117  BCP_vec<BCP_var*> new_vars;
118  new_vars.reserve(newvar_num);
119  for (cani = candidates.begin(); cani != lastcani; ++cani){
120  can = *cani;
121  if (can->vars_to_add)
122  new_vars.append(*can->vars_to_add);
123  }
124 
125  BCP_vec<BCP_col*> cols;
126  cols.reserve(newvar_num);
127  p.user->vars_to_cols(cuts, new_vars, cols,
128  *p.lp_result, BCP_Object_Branching, false);
129  BCP_lp_add_cols_to_lp(cols, lp);
130  purge_ptr_vector(cols);
131 
132  for (int i = 0; i < newvar_num; ++i) {
133  new_vars[i]->set_bcpind(-BCP_lp_next_var_index(p));
134  }
135  vars.append(new_vars);
136  }
137 
138  // now add the rows
139  if (newcut_num > 0){
140  BCP_vec<BCP_cut*> new_cuts;
141  new_cuts.reserve(newcut_num);
142  for (cani = candidates.begin(); cani != lastcani; ++cani){
143  can = *cani;
144  if (can->cuts_to_add)
145  new_cuts.append(*can->cuts_to_add);
146  }
147 
148  BCP_vec<BCP_row*> rows;
149  rows.reserve(newcut_num);
151  try {
152  p.user->cuts_to_rows(vars, new_cuts, rows,
153  *p.lp_result, BCP_Object_Branching, false);
154  }
155  catch (...) {
156  }
158  BCP_lp_add_rows_to_lp(rows, lp);
159  purge_ptr_vector(rows);
160 
161  for (int i = 0; i < newcut_num; ++i) {
162  new_cuts[i]->set_bcpind(-BCP_lp_next_cut_index(p));
163  }
164  cuts.append(new_cuts);
165  p.node->lb_at_cutgen.insert(p.node->lb_at_cutgen.end(), newcut_num,
166  p.lp_result->objval());
167  }
168 
169  // mark the newly added vars as fixed to 0, and the newly added cuts as
170  // free. (var_indices and cut_indices simply contain the indices of the
171  // added vars/cuts.)
172 
173  if (newvar_num > 0) {
174  for (int i = orig_col_num; i < orig_col_num + newvar_num; ++i)
175  lp->setColBounds(i, 0.0, 0.0);
176  }
177  if (newcut_num > 0) {
178  const double inf = lp->getInfinity();
179  for (int i = orig_row_num; i < orig_row_num + newcut_num; ++i)
180  lp->setRowBounds(i, -inf, inf);
181  }
182 
183  return std::pair<int,int>(newvar_num, newcut_num);
184 }
185 
186 //#############################################################################
187 
188 static inline void
190  const BCP_lp_branching_object* can,
191  const int added_col_num,
192  const int added_row_num)
193 {
194  BCP_var_set& vars = p.node->vars;
195  if (can->forced_var_pos) {
198  for ( ; ii != lastii; ++ii)
199  vars[*ii]->make_non_removable();
200  }
201  if (can->implied_var_pos) {
202  // just to make sure that these vars are not deleted before the implied
203  // bound change takes place...
206  for ( ; ii != lastii; ++ii)
207  vars[*ii]->make_active();
208  }
209 
210  if (added_col_num) {
211  BCP_var_set::iterator vari = vars.entry(vars.size() - added_col_num);
212  BCP_var_set::const_iterator lastvari = vars.end();
213  for ( ; vari != lastvari; ++vari) {
214  if (! (*vari)->is_non_removable())
215  (*vari)->make_to_be_removed();
216  }
217  }
218 
219  BCP_cut_set& cuts = p.node->cuts;
220  if (can->forced_cut_pos) {
223  for ( ; ii != lastii; ++ii)
224  cuts[*ii]->make_non_removable();
225  }
226  if (can->implied_cut_pos) {
227  // just to make sure that these cuts are not deleted before the implied
228  // bound change takes place...
231  for ( ; ii != lastii; ++ii)
232  cuts[*ii]->make_active();
233  }
234  if (added_row_num > 0){
235  BCP_cut_set::iterator cuti = cuts.entry(cuts.size() - added_row_num);
236  BCP_cut_set::const_iterator lastcuti = cuts.end();
237  for ( ; cuti != lastcuti; ++cuti) {
238  if (! (*cuti)->is_non_removable())
239  (*cuti)->make_to_be_removed();
240  }
241  }
242 }
243 
244 //#############################################################################
245 
246 static inline int
249  BCP_presolved_lp_brobj*& best_presolved)
250 {
251  OsiSolverInterface* lp = p.lp_solver;
252  BCP_var_set& vars = p.node->vars;
253  BCP_cut_set& cuts = p.node->cuts;
254 
255  const int orig_colnum = vars.size();
256 
257  const std::pair<int,int> added_object_num =
258  BCP_add_branching_objects(p, candidates);
259 
260  const int added_colnum = added_object_num.first;
261  const int added_rownum = added_object_num.second;
262 
263  const int colnum = vars.size();
264  const int rownum = cuts.size();
265 
266  int i, j; // loop variable
267 
268  const CoinWarmStart * ws = p.lp_solver->getWarmStart();
269 
270  // prepare for strong branching
271  lp->markHotStart();
272 
273  // save the lower/upper bounds of every var/cut
274  BCP_vec<double> rowbounds(2 * rownum, 0.0);
275  BCP_vec<double> colbounds(2 * colnum, 0.0);
276 
277  const int maxind = std::max<int>(rownum, colnum);
278  BCP_vec<int> all_indices(maxind, 0);
279  for (i = 0; i < maxind; ++i)
280  all_indices[i] = i;
281 
282  const double * rlb_orig = lp->getRowLower();
283  const double * rub_orig = lp->getRowUpper();
284  for (j = -1, i = 0; i < rownum; ++i) {
285  rowbounds[++j] = rlb_orig[i];
286  rowbounds[++j] = rub_orig[i];
287  }
288 
289  const double * clb_orig = lp->getColLower();
290  const double * cub_orig = lp->getColUpper();
291  for (j = -1, i = 0; i < colnum; ++i) {
292  colbounds[++j] = clb_orig[i];
293  colbounds[++j] = cub_orig[i];
294  }
295 
296  best_presolved = 0;
297 
298  // Look at the candidates one-by-one and presolve them.
300 
301  if (p.param(BCP_lp_par::MaxPresolveIter) > 0) {
302  lp->setIntParam(OsiMaxNumIterationHotStart,
304  }
305 
307  "\nLP: Starting strong branching:\n\n");
308 
309  const OsiBabSolver* babSolver = p.user->getOsiBabSolver();
310 
311  int cand_ind = -1;
312  for (cani = candidates.begin(); cani != candidates.end(); ++cani){
313  // Create a temporary branching object to hold the current results
314  BCP_presolved_lp_brobj* tmp_presolved =
315  new BCP_presolved_lp_brobj(*cani);
316  const BCP_lp_branching_object* can = *cani;
317  ++cand_ind;
318  for (i = 0; i < can->child_num; ++i){
319  can->apply_child_bd(lp, i);
320  // bound changes always imply that primal feasibility is lost.
321  p.user->modify_lp_parameters(p.lp_solver, 1, true);
322 #if 0
323  char fname[1000];
324  sprintf(fname, "matrix-%i.%i.%i-child-%i.%i",
326  cand_ind, i);
327  lp->writeMps(fname, "mps");
328 #endif
329  lp->solveFromHotStart();
330  tmp_presolved->get_results(*lp, i);
331  BCP_lp_test_feasibility(p, tmp_presolved->lpres(i));
332  if (babSolver) {
333  p.user->generate_cuts_in_lp(tmp_presolved->lpres(i),
334  p.node->vars, p.node->cuts,
335  tmp_presolved->get_new_cuts()[i],
336  tmp_presolved->get_new_rows()[i]);
337  }
338  }
339  // reset the bounds of the affected vars/cuts
340  if (can->cuts_affected() > 0)
341  lp->setRowSetBounds(all_indices.begin(), all_indices.entry(rownum),
342  rowbounds.begin());
343  if (can->vars_affected() > 0)
344  lp->setColSetBounds(all_indices.begin(), all_indices.entry(colnum),
345  colbounds.begin());
346 
348  p.user->print(true, "LP: Presolving:");
350  can->print_branching_info(orig_colnum,
351  p.lp_result->x(),
352  p.lp_solver->getObjCoefficients());
353  }
354  for (i = 0; i < can->child_num; ++i) {
355  const BCP_lp_result& res = tmp_presolved->lpres(i);
356  const double lb = res.objval();
357  p.user->print(true,
358  (lb>BCP_DBL_MAX/10 ? " [%e,%i,%i]":" [%.4f,%i,%i]"),
359  lb, res.termcode(), res.iternum());
360  }
361  p.user->print(true, "\n");
362  }
363  // Compare the current one with the best so far
364  switch (p.user->compare_branching_candidates(tmp_presolved,
365  best_presolved)) {
367  break;
369  std::swap(tmp_presolved, best_presolved);
370  break;
372  // Free the remaining candidates if there are any. This also resets
373  // candidates.end(), thus
374  purge_ptr_vector(candidates, cani + 1, candidates.end());
375  std::swap(tmp_presolved, best_presolved);
376  break;
377  }
378  delete tmp_presolved;
379  }
380 
381  // indicate to the lp solver that strong branching is done
382  lp->unmarkHotStart();
383  p.lp_solver->setWarmStart(ws);
384 
385  // delete all the candidates but the selected one (candidates will just
386  // silently go out of scope and we'll be left with a pointer to the final
387  // candidate in best_presolved).
388  BCP_lp_branching_object* can = best_presolved->candidate();
389  int selected = 0;
390  for (i=0, cani=candidates.begin(); cani != candidates.end(); ++cani, ++i) {
391  if (*cani != can) {
392  delete *cani;
393  } else {
394  selected = i;
395  }
396  }
397 
398  // Mark the cols/rows of the OTHER candidates as removable
399  BCP_mark_result_of_strong_branching(p, can, added_colnum, added_rownum);
400  // Delete whatever cols/rows we want to delete. This function also updates
401  // var/cut_positions !!!
402  BCP_lp_delete_cols_and_rows(p, can, added_colnum, added_rownum,
403  false /* not from fathom */,
404  true /* to force deletion */);
405 
406  delete ws;
407 
408  return selected;
409 }
410 
411 //#############################################################################
412 
413 static inline BCP_branching_decision
415  BCP_presolved_lp_brobj*& best_presolved)
416 {
417  BCP_var_set& vars = p.node->vars;
418  BCP_cut_set& cuts = p.node->cuts;
420 
421  bool force_branch = (p.lp_result->termcode() & BCP_Abandoned) != 0;
422 
423  BCP_branching_decision do_branch =
425  vars, cuts,
426  *p.local_var_pool,
427  *p.local_cut_pool,
428  candidates,
429  force_branch);
430  switch (do_branch){
433  case BCP_DoNotBranch:
434  if (p.local_var_pool->size() == 0 && p.local_cut_pool->size() == 0) {
435  /* Hmmm... check whether some magic was done and the former sol is
436  now infeasible, so resolving is perfectly normal.
437  NOTE: We only check whether the former primal sol and lhs
438  values are within the bounds! */
439  const double petol = p.lp_result->primalTolerance();
440  const double * x = p.lp_result->x();
441  for (int i = vars.size() - 1; i >= 0; --i) {
442  const BCP_var* v = vars[i];
443  if (x[i] + petol < v->lb() || x[i] - petol > v->ub()) {
444  return BCP_DoNotBranch; // YES...
445  }
446  }
447  const double * lhs = p.lp_result->lhs();
448  for (int i = cuts.size() - 1; i >= 0; --i) {
449  const BCP_cut* c = cuts[i];
450  if (lhs[i] + petol < c->lb() || lhs[i] - petol > c->ub()) {
451  return BCP_DoNotBranch; // YES...
452  }
453  }
454  p.user->print(true, "\
455 LP: ***WARNING*** : BCP_DoNotBranch, but nothing can be added! ***WARNING***\n");
456  //throw BCP_fatal_error("BCP_DoNotBranch, but nothing can be added!\n");
457  }
458  return BCP_DoNotBranch;
459  case BCP_DoBranch:
460  break;
461  }
462 
463  // give error message if there are no branching candidates
464  if (candidates.size() < 1) {
465  throw BCP_fatal_error("\
466 BCP_lp_select_branching_object: branching forced but no candidates selected\n");
467  }
468 
469  // ** OK, now we have to branch. **
470  double time0 = CoinCpuTime();
471  const int orig_colnum = p.node->vars.size();
472 
473  // if branching candidates are not presolved then choose the first
474  // branching candidate as the best candidate.
475  int selected = 0;
476  if (p.param(BCP_lp_par::MaxPresolveIter) < 0) {
477  if (candidates.size() > 1) {
478  p.user->print(true, "\
479 LP: Strong branching is disabled but more than one candidate is selected.\n\
480  Deleting all candidates but the first.\n");
481  // delete all other candidates
483  candidates.begin();
484  for (++can; can != candidates.end(); ++can) {
485  delete *can;
486  }
487  candidates.erase(candidates.begin()+1, candidates.end());
488  }
489  BCP_add_branching_objects(p, candidates);
490  best_presolved = new BCP_presolved_lp_brobj(candidates[0]);
491  if (candidates[0]->objval_) {
492  best_presolved->set_objective_values(*candidates[0]->objval_,
493  *candidates[0]->termcode_,
495  } else {
496  best_presolved->initialize_lower_bound(p.node->true_lower_bound);
497  }
498  } else {
499  selected = BCP_lp_perform_strong_branching(p, candidates,
500  best_presolved);
501  }
502 
503  const BCP_lp_branching_object* can = best_presolved->candidate();
504 
505  // decide what to do with each child
506  p.user->set_actions_for_children(best_presolved);
507  BCP_vec<BCP_child_action>& action = best_presolved->action();
508  // override the set values if we won't dive
509  if (p.node->dive == BCP_DoNotDive){
510  bool needed_overriding = false;
511  for (int i = can->child_num - 1; i >= 0; --i) {
512  if (action[i] == BCP_KeepChild) {
513  action[i] = BCP_ReturnChild;
514  needed_overriding = true;
515  }
516  }
517  p.user->print(needed_overriding &&
519  "LP: Every child is returned because of not diving.\n");
520  }
521 
522  // We don't know what is fathomable! strong branching may give an approx
523  // sol for the children's subproblems, but it may not be a lower
524  // bound. Let the tree manager decide what to do with them.
525 
526  // now throw out the fathomable ones. This can be done only if nothing
527  // needs to be priced, there already is an upper bound and strong branching
528  // was enabled (otherwise we don't have the LPs solved)
529  if (p.param(BCP_lp_par::MaxPresolveIter) >= 0) {
530  BCP_print_brobj_stat(p, orig_colnum, candidates.size(), selected,
531  best_presolved);
532  }
533 
534  // finally get the user data for the children
535  p.user->set_user_data_for_children(best_presolved, selected);
536 
537  // Now just resolve the LP to get what'll be sent to the TM.
538  // 2nd arg is 1, since only only bd changes happened which can afffect
539  // only primal feasibility
540  p.user->modify_lp_parameters(p.lp_solver, 1, false);
541  p.lp_solver->initialSolve();
543  p.node->quality = p.lp_result->objval();
544 
545  p.stat.time_branching += CoinCpuTime() - time0;
546 
547  return BCP_DoBranch;
548 }
549 
550 //#############################################################################
551 
552 static inline void
554 {
555  BCP_lp_parent& parent = *p.parent;
556  BCP_lp_node& node = *p.node;
557 
558  const int bvarnum = p.core->varnum();
559  const int bcutnum = p.core->cutnum();
560 
561  // deal with parent's fields one-by-one
562 
563  // core_as_change has already been updated correctly in BCP_lp_pack_core()
564  node.tm_storage.core_change = (bvarnum + bcutnum > 0 ?
566  int i;
567 
568  const BCP_var_set& vars = node.vars;
569  const int varnum = vars.size();
570  BCP_obj_set_change& var_set = parent.var_set;
571  BCP_vec<int>& var_ind = var_set._new_objs;
572  BCP_vec<BCP_obj_change>& var_ch = var_set._change;
573  var_ind.clear();
574  var_ch.clear();
575  var_ind.reserve(varnum - bvarnum);
576  var_ch.reserve(varnum - bvarnum);
577  for (i = bvarnum; i < varnum; ++i) {
578  const BCP_var* var = vars[i];
579  assert(var->bcpind() > 0);
580  var_ind.unchecked_push_back(var->bcpind());
581  var_ch.unchecked_push_back(BCP_obj_change(var->lb(), var->ub(),
582  var->status()));
583  }
585 
586  const BCP_cut_set& cuts = node.cuts;
587  const int cutnum = cuts.size();
588  BCP_obj_set_change& cut_set = parent.cut_set;
589  BCP_vec<int>& cut_ind = cut_set._new_objs;
590  BCP_vec<BCP_obj_change>& cut_ch = cut_set._change;
591  cut_ind.clear();
592  cut_ch.clear();
593  cut_ind.reserve(cutnum - bcutnum);
594  cut_ch.reserve(cutnum - bcutnum);
595  for (i = bcutnum; i < cutnum; ++i) {
596  const BCP_cut* cut = cuts[i];
597  assert(cut->bcpind() > 0);
598  cut_ind.unchecked_push_back(cut->bcpind());
599  cut_ch.unchecked_push_back(BCP_obj_change(cut->lb(), cut->ub(),
600  cut->status()));
601  }
603 
604  delete parent.warmstart;
605  parent.warmstart = node.warmstart;
606  node.warmstart = 0;
608 
609  parent.index = node.index;
610 
611  delete node.user_data;
612  node.user_data = 0;
613 }
614 
615 //#############################################################################
616 
619 {
620  BCP_presolved_lp_brobj* best_presolved = 0;
621 
622  // this is needed to stop gcc complaining about uninitialized use of
623  // do_branch (this complaint might arise from inlining)
625  do_branch = BCP_lp_select_branching_object(p, best_presolved);
626 
627  switch (do_branch){
629  BCP_lp_send_cuts_to_cp(p, -1);
630  BCP_lp_perform_fathom(p,"LP: Forcibly fathoming node in branch().\n",
633  case BCP_DoNotBranch:
636  // the branching objects are already added and we will add from the
637  // local pools as well.
639  break;
640  case BCP_DoBranch:
641  break;
642  }
643 
644  // Now p.node has the final set of vars/cuts for this node, and this
645  // routine will extract the final warmstart information. Send this all off
646  // to the the TM. This function also sends off the branching info, and gets
647  // diving info from TM. In case of diving it receives/updates the index of
648  // the node and the internal indices of the not yet indexed vars/cuts.
649  int keep = BCP_lp_send_node_description(p, best_presolved,
651 
652  // send out the cuts to be sent to the CP
653  BCP_lp_send_cuts_to_cp(p, -1);
654 
655  if (keep < 0){ // if no diving then return quickly
657  if (best_presolved->is_pruned())
658  p.user->print(true, "LP: Forcibly Pruning node\n");
659  else
660  p.user->print(true, "LP: Returned children to TM. Waiting for new node.\n");
661  }
662  delete best_presolved->candidate();
663  delete best_presolved;
666  }
667 
668  // Otherwise we dive. start updating things.
669  // first move the current node to be the parent
671 
672  // now apply the bounds of the kept child
673  BCP_lp_branching_object* can = best_presolved->candidate();
674  can->apply_child_bd(p.lp_solver, keep);
675  if (can->vars_affected()) {
676  BCP_var_set& vars = p.node->vars;
677  if (can->forced_var_pos) {
678  vars.set_lb_ub(*can->forced_var_pos, can->forced_var_bd_child(keep));
679  const BCP_vec<int>& pos = *can->forced_var_pos;
680  for (int p = pos.size() - 1; p >= 0; --p) {
681  vars[pos[p]]->make_non_removable();
682  }
683  }
684  if (can->implied_var_pos)
685  vars.set_lb_ub(*can->implied_var_pos,can->implied_var_bd_child(keep));
686  }
687  if (can->cuts_affected()) {
688  BCP_cut_set& cuts = p.node->cuts;
689  if (can->forced_cut_pos) {
690  cuts.set_lb_ub(*can->forced_cut_pos, can->forced_cut_bd_child(keep));
691  const BCP_vec<int>& pos = *can->forced_cut_pos;
692  for (int p = pos.size() - 1; p >= 0; --p) {
693  cuts[pos[p]]->make_non_removable();
694  }
695  }
696  if (can->implied_cut_pos)
697  cuts.set_lb_ub(*can->implied_cut_pos,can->implied_cut_bd_child(keep));
698  }
699  // Delete the old user data before getting new
700  delete p.node->user_data;
701  p.node->user_data = best_presolved->user_data()[keep];
702  best_presolved->user_data()[keep] = 0;
703 
704  // Get rid of best_presolved
705  delete best_presolved->candidate();
706  delete best_presolved;
707 
709 }
int BCP_lp_send_node_description(BCP_lp_prob &p, BCP_presolved_lp_brobj *brobj, BCP_message_tag msgtag)
bool is_pruned() const
Fill up obj with the lower bound on each child.
BCP_vec< double >::const_iterator implied_cut_bd_child(const int index) const
Return a const iterator to the position in the implied cut bound changes where the new bounds for the...
void BCP_lp_add_rows_to_lp(const BCP_vec< BCP_row * > &rows, OsiSolverInterface *lp)
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...
BCP_vec< int > * implied_var_pos
BCP_warmstart * warmstart
this is always explicit, it&#39;s just that coding is simpler if we reuse the BCP_obj_set_change object ...
Definition: BCP_lp_node.hpp:64
This child should be kept and dived into (provided diving is decided on.
This class stores data about how an object set (set of vars or set of cuts) changes.
BCP_storage_t cut_change
Definition: BCP_lp_node.hpp:31
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
void print(const bool ifprint, const char *format,...) const
A method to print a message with the process id.
Definition: BCP_lp_user.cpp:38
Used to indicate that there is no message in the buffer of a process.
static void BCP_print_brobj_stat(BCP_lp_prob &p, const int orig_varnum, const int candidate_num, const int selected, const BCP_presolved_lp_brobj *best_presolved)
No branching happend, continue to work on the same node.
BCP_lp_parent * parent
Description of the parent of the current node.
Definition: BCP_lp.hpp:170
pos
position where the operator should be printed when printing the expression
void clear()
Delete every entry.
char param(BCP_lp_par::chr_params key) const
Definition: BCP_lp.hpp:275
int BCP_lp_next_var_index(BCP_lp_prob &p)
Print information on the branching candidate selected by strong branching.
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
void set_objective_values(const BCP_vec< double > &obj, const BCP_vec< int > &termcode, const double itlim_objval)
Set the appropriate fields of all _lpres to the given termcode and objval if the termcode is &quot;normal&quot;...
double quality
Abstract base class that defines members common to all types of cuts.
Definition: BCP_cut.hpp:29
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.
OsiBabSolver * getOsiBabSolver()
Definition: BCP_lp_user.hpp:99
BCP_node_storage_in_tm tm_storage
int vars_affected() const
Return the number of variables whose bounds are affected by the branching.
BCP_vec< double >::const_iterator forced_var_bd_child(const int index) const
Return a const iterator to the position in the forced variable bound changes where the new bounds for...
BCP_lp_statistics stat
Definition: BCP_lp.hpp:213
void BCP_lp_add_cols_to_lp(const BCP_vec< BCP_col * > &cols, OsiSolverInterface *lp)
&quot;new&quot; is better, discard &quot;old&quot;.
BCP_branching_result BCP_lp_branch(BCP_lp_prob &p)
void BCP_lp_test_feasibility(BCP_lp_prob &p, const BCP_lp_result &lpres)
Definition: BCP_lp_misc.cpp:35
BCP_obj_set_change cut_set
this is always explicit, it&#39;s just that coding is simpler if we reuse the BCP_obj_set_change object ...
Definition: BCP_lp_node.hpp:62
BCP_diving_status dive
double time_branching
Definition: BCP_lp.hpp:69
BCP_storage_t warmstart
Definition: BCP_lp_node.hpp:33
No data is stored.
Definition: BCP_enum.hpp:86
static std::pair< int, int > BCP_add_branching_objects(BCP_lp_prob &p, BCP_vec< BCP_lp_branching_object * > &candidates)
iterator begin()
Return an iterator to the beginning of the object.
Definition: BCP_vector.hpp:99
BCP_vec< BCP_vec< BCP_row * > > & get_new_rows()
Fill up obj with the lower bound on each child.
double ub() const
Return the upper bound on the cut.
Definition: BCP_cut.hpp:84
BCP should continue to work on this node.
const double * lhs() const
const double * x() const
NO OLD DOC.
Definition: BCP_lp.hpp:102
This class is just a collection of pointers to cuts with a number of methods to manipulate these cuts...
Definition: BCP_cut.hpp:279
BCP_vec< int > _new_objs
void reserve(const size_t n)
Reallocate the object to make space for n entries.
BCP_branching_result
This enumerative constant describes the possible outcomes of a branching attempt. ...
void BCP_lp_perform_fathom(BCP_lp_prob &p, const char *msg, BCP_message_tag msgtag)
void append(const BCP_vec< BCP_cut * > &x)
Append the cuts in the vector x to the end of the cut set.
Definition: BCP_cut.hpp:304
static char * j
Definition: OSdtoa.cpp:3622
T * iterator
Definition: BCP_vector.hpp:33
int index
this is always explicit, it&#39;s just that coding is simpler if we reuse the BCP_obj_set_change object ...
Definition: BCP_lp_node.hpp:66
&quot;new&quot; is better and it&#39;s so good that even if there are more candidates forget them and use &quot;new&quot; a...
size_t varnum() const
Return the number of variables in the core.
BCP_cut_set cuts
#define BCP_DBL_MAX
Definition: BCP_math.hpp:6
double lb() const
Return the lower bound on the cut.
Definition: BCP_cut.hpp:82
virtual void set_actions_for_children(BCP_presolved_lp_brobj *best)
Decide what to do with the children of the selected branching object.
virtual void vars_to_cols(const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_var * > &vars, BCP_vec< BCP_col * > &cols, const BCP_lp_result &lpres, BCP_object_origin origin, bool allow_multiple)
Convert a set of variables into corresponding columns for the current LP relaxation.
BCP_vec< int > * implied_cut_pos
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)
double ub() const
Return the upper bound.
Definition: BCP_var.hpp:91
void erase(iterator pos)
Erase the entry pointed to by pos.
BCP_vec< BCP_user_data * > & user_data()
Return a reference to the user data vector.
double primalTolerance() const
Return the primal tolerance of the solver.
BCP_lp_user * user
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:131
BCP_vec< int > * forced_cut_pos
Positions of cuts whose bounds change (&quot;forcibly&quot;, by branching) in the children. ...
Print detailed information on the branching candidate selected by strong branching.
BCP_warmstart * warmstart
void fint fint fint real fint real real real real real real real real real fint real fint * lp
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 * > &cands, bool force_branch=false)
Decide whether to branch or not and select a set of branching candidates if branching is decided upon...
NO OLD DOC.
Definition: BCP_lp_node.hpp:92
&quot;old&quot; is better, discard &quot;new&quot;.
The node is fathomed, the LP process should wait for a new node.
void get_results(OsiSolverInterface &lp, const int child_ind)
Extract the lp results from the LP solver for the child_ind-th child.
The node is discarded (fathomed).
OsiSolverInterface * lp_solver
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:137
BCP_lp_result * lp_result
Definition: BCP_lp.hpp:185
int child_num
The number of children for this branching object.
size_t cutnum() const
Return the number of cuts in the core.
BCP_obj_set_change var_set
this is always explicit, it&#39;s just that coding is simpler if we reuse the BCP_obj_set_change object ...
Definition: BCP_lp_node.hpp:59
void BCP_lp_send_cuts_to_cp(BCP_lp_prob &p, const int eff_cnt_limit)
After a branching object is selected print what happens to the presolved children (e...
double objval() const
int cuts_affected() const
Return the number of cuts whose bounds are affected by the branching.
BCP_obj_status status() const
Return the status of the cut.
Definition: BCP_cut.hpp:91
This class describes a generic branching object.
The data stored is with respect to the same kind of data in the parent of the search tree node...
Definition: BCP_enum.hpp:91
BCP_vec< double > lb_at_cutgen
BCP_branching_decision
This enumerative constant is the return value of the select_branching_candidates() method in [BCP_lp_...
Branching happened, one of the children is kept and that&#39;s what the LP process will continue to work ...
BCP_vec< BCP_var * > * vars_to_add
Variables to be added to the formulation.
BCP_lp_var_pool * local_var_pool
Definition: BCP_lp.hpp:191
const BCP_lp_result & lpres(const int child_ind) const
Return a const reference to the presolved results of the child_ind-th child.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real * ws
void insert(iterator position, const void *first, const size_t num)
Insert num entries starting from memory location first into the vector from position pos...
BCP_vec< double >::const_iterator implied_var_bd_child(const int index) const
Return a const iterator to the position in the implied variable bound changes where the new bounds fo...
NO OLD DOC.
Definition: BCP_lp_node.hpp:42
This child should be returned to the Tree Manager for later processing.
The object originates from a branching object.
Definition: BCP_enum.hpp:255
BCP_vec< int > * forced_var_pos
Positions of variables whose bounds change (&quot;forcibly&quot;, by branching) in the children.
void set_lb_ub(const BCP_vec< int > &pos, BCP_vec< double >::const_iterator bounds)
Set the lower/upper bound pairs of the entries given by the contents of pos to the values in [bounds...
Definition: BCP_var.cpp:10
Print information related to fathoming.
Abstract base class that defines members common to all types of variables.
Definition: BCP_var.hpp:28
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
BCP_storage_t core_change
Definition: BCP_lp_node.hpp:27
BCP_vec< double >::const_iterator forced_cut_bd_child(const int index) const
Return a const iterator to the position in the forced cut bound changes where the new bounds for the ...
The node should be fathomed without even trying to branch.
A presolved branching object candidate.
BCP_storage_t var_change
Definition: BCP_lp_node.hpp:29
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...
int bcpind() const
Return the internal index of the variable.
Definition: BCP_var.hpp:93
void BCP_lp_clean_up_node(BCP_lp_prob &p)
Definition: BCP_lp_misc.cpp:59
static bool abort_on_error
Definition: BCP_error.hpp:22
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
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.
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.
BCP_obj_status status() const
Return the status of the variable.
Definition: BCP_var.hpp:98
static void BCP_lp_make_parent_from_node(BCP_lp_prob &p)
This class is just a collection of pointers to variables with a number of methods to manipulate these...
Definition: BCP_var.hpp:316
virtual void set_user_data_for_children(BCP_presolved_lp_brobj *best, const int selected)
For each child create a user data object and put it into the appropriate entry in best-&gt;user_data()...
The class BCP_vec serves the same purpose as the vector class in the standard template library...
Definition: BCP_vector.hpp:24
double true_lower_bound
After branching all children must be returned to the Tree Manager and the LP process should wait for ...
BCP_vec< BCP_cut * > * cuts_to_add
Cuts to be added to the formulation.
BCP_vec< BCP_vec< BCP_cut * > > & get_new_cuts()
Fill up obj with the lower bound on each child.
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
void get_results(OsiSolverInterface &lp_solver)
Get the result from the LP solver.
BCP_problem_core * core
Definition: BCP_lp.hpp:153
double lb() const
Return the lower bound.
Definition: BCP_var.hpp:89
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
void append(const BCP_vec< BCP_var * > &x)
Append the variables in the vector x to the end of the variable set.
Definition: BCP_var.hpp:342
int termcode() const
BCP_vec< BCP_child_action > & action()
Return a reference to the actions to be taken.
static int BCP_lp_perform_strong_branching(BCP_lp_prob &p, BCP_vec< BCP_lp_branching_object * > &candidates, BCP_presolved_lp_brobj *&best_presolved)
BCP_user_data * user_data
Data the user wants to pass along with the search tree node.
void set_lb_ub(const BCP_vec< int > &pos, BCP_vec< double >::const_iterator bounds)
Set the lower/upper bound pairs of the entries given by the contents of pos to the values in [bounds...
Definition: BCP_cut.cpp:12
This class holds the results after solving an LP relaxation.
void make_to_be_removed()
Mark the cut as ToBeRemoved.
Definition: BCP_cut.hpp:178
Branching must be done.
iterator entry(const int i)
Return an iterator to the i-th entry.
Definition: BCP_vector.hpp:109
static void BCP_mark_result_of_strong_branching(BCP_lp_prob &p, const BCP_lp_branching_object *can, const int added_col_num, const int added_row_num)
A cut has to remain effective through this many iterations in the LP before it is sent to the Cut Poo...
BCP_vec< BCP_obj_change > _change
int bcpind() const
Return the internal index of the cut.
Definition: BCP_cut.hpp:86
BCP_lp_branching_object * candidate()
Return a pointer to the candidate.
real c
void initialize_lower_bound(const double val)
Fill up obj with the lower bound on each child.
virtual void modify_lp_parameters(OsiSolverInterface *lp, const int changeType, bool in_strong_branching)
Modify parameters of the LP solver before optimization.
void init_pos_for_added(const int added_vars_start, const int added_cuts_start)
This method &quot;cleans up&quot; the positions and bounds.
void BCP_lp_delete_cols_and_rows(BCP_lp_prob &p, BCP_lp_branching_object *can, const int added_colnum, const int added_rownum, const bool from_fathom, const bool force_delete)
void append(const BCP_vec< T > &x)
Append the entries in x to the end of the vector.
Definition: BCP_vector.hpp:169
void make_to_be_removed()
Mark the variable as ToBeRemoved.
Definition: BCP_var.hpp:207
static BCP_branching_decision BCP_lp_select_branching_object(BCP_lp_prob &p, BCP_presolved_lp_brobj *&best_presolved)
Print detailed information about all the branching candidates during strong branching.
void fint fint fint real fint real * x
This child should be fathomed.