BCP_lp_user.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #include <cmath>
4 #include <cstdarg>
5 #include <cstdio>
6 
7 #include "CoinHelperFunctions.hpp"
8 #include "CoinTime.hpp"
9 
10 #include "BCP_math.hpp"
11 #include "BCP_error.hpp"
12 #include "BCP_USER.hpp"
13 #include "BCP_var.hpp"
14 #include "BCP_cut.hpp"
15 #include "BCP_problem_core.hpp"
16 #include "BCP_lp_user.hpp"
17 #include "BCP_lp.hpp"
18 #include "BCP_lp_pool.hpp"
19 #include "BCP_lp_result.hpp"
20 #include "BCP_lp_node.hpp"
21 #include "BCP_lp_branch.hpp"
22 #include "BCP_problem_core.hpp"
23 #include "BCP_solution.hpp"
24 #include "BCP_functions.hpp"
25 #include "BCP_lp_functions.hpp"
26 
27 //#############################################################################
28 // Informational methods for the user
29 double BCP_lp_user::upper_bound() const { return p->ub(); }
30 bool BCP_lp_user::over_ub(double lb) const { return p->over_ub(lb); }
31 int BCP_lp_user::current_phase() const { return p->phase; }
32 int BCP_lp_user::current_level() const { return p->node->level; }
33 int BCP_lp_user::current_index() const { return p->node->index; }
35 double BCP_lp_user::start_time() const { return p->start_time; }
37 
38 void BCP_lp_user::print(const bool ifprint, const char * format, ...) const {
39  if (ifprint) {
40  va_list valist;
41  va_start(valist, format);
42  vprintf(format, valist);
43  va_end(valist);
44  }
45 }
46 
47 //#############################################################################
48 // Informational methods for the user
49 /* Methods to get/set BCP parameters on the fly */
50 char
52 { return p->par.entry(key); }
53 int
55 { return p->par.entry(key); }
56 double
58 { return p->par.entry(key); }
59 const BCP_string&
61 { return p->par.entry(key); }
62 
63 void BCP_lp_user::set_param(const BCP_lp_par::chr_params key, const bool val)
64 { p->par.set_entry(key, val); }
65 void BCP_lp_user::set_param(const BCP_lp_par::chr_params key, const char val)
66 { p->par.set_entry(key, val); }
67 void BCP_lp_user::set_param(const BCP_lp_par::int_params key, const int val)
68 { p->par.set_entry(key, val); }
69 void BCP_lp_user::set_param(const BCP_lp_par::dbl_params key, const double val)
70 { p->par.set_entry(key, val); }
71 void BCP_lp_user::set_param(const BCP_lp_par::str_params key, const char * val)
72 { p->par.set_entry(key, val); }
73 
74 //#############################################################################
75 
76 void
78 {
79  // send the feas sol to the tree manager
80  p->msg_buf.clear();
82  p->msg_env->send(p->get_parent() /*tree_manager*/,
84 
85  // update the UB if necessary
86  const double obj = sol->objective_value();
87  if (p->ub(obj) && p->node->colgen != BCP_GenerateColumns) {
88  // FIXME: If we had a flag in the node that indicates not to
89  // generate cols in it and in its descendants then the dual obj
90  // limit could still be set...
91  p->lp_solver->setDblParam(OsiDualObjectiveLimit, obj-p->granularity());
92  }
93 }
94 
95 //#############################################################################
96 
97 // These functions are member functions of the VIRTUAL class BCP_lp_user.
98 // Therefore any concrete class derived from BCP_lp_user can override these
99 // definitions. These are here as default functions.
100 
101 //#############################################################################
102 // a few helper functions for selecting a subset of a double vector
103 void
104 BCP_lp_user::select_nonzeros(const double * first, const double * last,
105  const double etol,
106  BCP_vec<int>& nonzeros) const {
107  nonzeros.reserve(last - first);
108  BCP_vec<double>::const_iterator current = first;
109  for ( ; current != last; ++current)
110  if (CoinAbs(*current) > etol)
111  nonzeros.unchecked_push_back(current - first);
112 }
113 //-----------------------------------------------------------------------------
114 void
115 BCP_lp_user::select_zeros(const double * first, const double * last,
116  const double etol,
117  BCP_vec<int>& zeros) const {
118  zeros.reserve(last - first);
119  BCP_vec<double>::const_iterator current = first;
120  for ( ; current != last; ++current)
121  if (CoinAbs(*current) <= etol)
122  zeros.unchecked_push_back(current - first);
123 }
124 //-----------------------------------------------------------------------------
125 void
126 BCP_lp_user::select_positives(const double * first, const double * last,
127  const double etol,
128  BCP_vec<int>& positives) const {
129  positives.reserve(last - first);
130  BCP_vec<double>::const_iterator current = first;
131  for ( ; current != last; ++current)
132  if (*current > etol)
133  positives.unchecked_push_back(current - first);
134 }
135 //-----------------------------------------------------------------------------
136 void
137 BCP_lp_user::select_fractions(const double * first, const double * last,
138  const double etol,
139  BCP_vec<int>& fractions) const {
140  fractions.reserve(last - first);
141  BCP_vec<double>::const_iterator current = first;
142  for ( ; current != last; ++current)
143  if (*current-floor(*current) > etol && ceil(*current)-*current > etol)
144  fractions.unchecked_push_back(current - first);
145 }
146 
147 //#############################################################################
148 //#############################################################################
149 // unpack the initial info for the appropriate process
150 void
152 {
154  "LP: Default unpack_module_data() executed.\n");
155 }
156 
157 //#############################################################################
158 
160 int
162 {
163  return p->get_process_id();
164 }
165 
167 int
169 {
170  return p->get_parent();
171 }
172 
174 void
175 BCP_lp_user::send_message(const int target, const BCP_buffer& buf,
176  BCP_message_tag tag)
177 {
178  p->msg_env->send(target, tag, buf);
179 }
180 
182 void
184  BCP_message_tag tag)
185 {
186  p->msg_env->receive(sender, tag, buf, -1);
187 }
188 
190 void
192  const BCP_buffer& buf)
193 {
194  throw BCP_fatal_error("\
195 BCP_lp_user::broadcast_message: can't broadcast from an LP process.\n");
196 }
197 
200 void
202 {
203  throw BCP_fatal_error("\
204 BCP_lp_user::process_message() invoked but not overridden!\n");
205 }
206 
207 //#############################################################################
208 
209 OsiSolverInterface *
211 {
212  throw BCP_fatal_error("\
213 BCP_lp_user::initialize_solver_interface() invoked but not overridden!\n");
214  return 0;
215 }
216 
217 //#############################################################################
218 
219 void
220 BCP_lp_user::initialize_int_and_sos_list(std::vector<OsiObject *>& intAndSosObjects)
221 {
222  return;
223 }
224 
225 //#############################################################################
226 void
228  const BCP_vec<BCP_cut*>& cuts,
229  const BCP_vec<BCP_obj_status>& vs,
230  const BCP_vec<BCP_obj_status>& cs,
231  BCP_vec<int>& var_changed_pos,
232  BCP_vec<double>& var_new_bd,
233  BCP_vec<int>& cut_changed_pos,
234  BCP_vec<double>& cut_new_bd)
235 {
237  "LP: Default initialize_new_search_tree_node() executed.\n");
238 }
239 
240 //#############################################################################
241 
242 void
243 BCP_lp_user::load_problem(OsiSolverInterface& osi, BCP_problem_core* core,
244  BCP_var_set& vars, BCP_cut_set& cuts)
245 {
246  const int varnum = vars.size();
247  const int cutnum = cuts.size();
248 
249  if (varnum == 0) {
250  // *FIXME* : kill all the processes
251  throw BCP_fatal_error("There are no vars in the description for node %i!\n",
252  current_index());
253  }
254 
255  if (cutnum == 0) {
256  // *FIXME* : kill all the processes
257  throw BCP_fatal_error("There are no cuts in the description for node %i!\n",
258  current_index());
259  }
260 
261  BCP_vec<BCP_col*> cols;
262  BCP_vec<BCP_row*> rows;
263 
264  int bvarnum = core->varnum();
265  int bcutnum = core->cutnum();
266 
267  if (varnum == 0 || cutnum == 0){
268  throw BCP_fatal_error("No rows or no cols to create a matrix from!\n");
269  }
270 
271  BCP_lp_relax* m = 0;
272  if (bvarnum == 0) {
273  // no core vars. doesn't matter if there're any core cuts, the starting
274  // matrix is computed the same way
275  cols.reserve(varnum);
276  vars_to_cols(cuts, vars, cols,
278  BCP_vec<double> RLB;
279  BCP_vec<double> RUB;
280  RLB.reserve(cutnum);
281  RUB.reserve(cutnum);
283  BCP_cut_set::const_iterator lastci = cuts.end();
284  for ( ; ci != lastci; ++ci) {
285  RLB.unchecked_push_back((*ci)->lb());
286  RUB.unchecked_push_back((*ci)->ub());
287  }
288  m = new BCP_lp_relax(cols, RLB, RUB);
289  purge_ptr_vector(cols);
290  } else {
291  if (bcutnum == 0) {
292  rows.reserve(cutnum);
293  cuts_to_rows(vars, cuts, rows,
295  BCP_vec<double> CLB;
296  BCP_vec<double> CUB;
297  BCP_vec<double> OBJ;
298  CLB.reserve(varnum);
299  CUB.reserve(varnum);
300  OBJ.reserve(varnum);
302  BCP_var_set::const_iterator lastvi = vars.end();
303  for ( ; vi != lastvi; ++vi) {
304  CLB.unchecked_push_back((*vi)->lb());
305  CUB.unchecked_push_back((*vi)->ub());
306  OBJ.unchecked_push_back((*vi)->obj());
307  }
308  m = new BCP_lp_relax(rows, CLB, CUB, OBJ);
309  purge_ptr_vector(rows);
310  } else {
311  // has core vars and cuts, the starting matrix is the core matrix
312  m = core->matrix;
313  }
314  }
315 
316  // We have the description in p.node. Load it into the lp solver.
317  // First load the core matrix
318  osi.loadProblem(*m,
319  m->ColLowerBound().begin(), m->ColUpperBound().begin(),
320  m->Objective().begin(),
321  m->RowLowerBound().begin(), m->RowUpperBound().begin());
322 
323  if (bvarnum > 0 && bcutnum > 0) {
324  //-----------------------------------------------------------------------
325  // We have to add the 'added' stuff only if we had a core matrix
326  //-----------------------------------------------------------------------
327  // Add the Named and Algo cols if there are any (and if we have any cols)
328  if (varnum > bvarnum && bcutnum > 0) {
329  BCP_vec<BCP_var*> added_vars(vars.entry(bvarnum), vars.end());
330  BCP_vec<BCP_cut*> core_cuts(cuts.begin(), cuts.entry(bcutnum));
331  cols.reserve(vars.size());
332  vars_to_cols(core_cuts, added_vars, cols,
334  BCP_lp_add_cols_to_lp(cols, &osi);
335  purge_ptr_vector(cols);
336  }
337  //-----------------------------------------------------------------------
338  // Add the Named and Algo rows if there are any (and if we have any such
339  // rows AND if there are core vars)
340  if (cutnum > bcutnum) {
341  BCP_vec<BCP_cut*> added_cuts(cuts.entry(bcutnum), cuts.end());
342  rows.reserve(added_cuts.size());
344  try {
345  cuts_to_rows(vars, added_cuts, rows,
347  }
348  catch (...) {
349  }
351  BCP_lp_add_rows_to_lp(rows, &osi);
352  purge_ptr_vector(rows);
353  }
354  } else {
355  // Otherwise (i.e., if we had no core matrix) we just have to get rid of
356  // 'm'.
357  delete m;
358  }
359  const bool dumpcuts = get_param(BCP_lp_par::Lp_DumpNodeDescCuts);
360  const bool dumpvars = get_param(BCP_lp_par::Lp_DumpNodeDescVars);
361  if (dumpcuts || dumpvars) {
362  printf("LP: NEW ACTIVE NODE %i DUMP START ===========================\n",
363  current_index());
364  if (dumpvars) {
365  printf(" Core Vars (bvarnum %i)\n", bvarnum);
366  for (int i = 0; i < bvarnum; ++i) {
367  printf(" var %4i: bcpind %i, status %i, lb %f, ub %f\n",
368  i, vars[i]->bcpind(), vars[i]->status(),
369  vars[i]->lb(), vars[i]->ub());
370  }
371  }
372  if (dumpcuts) {
373  printf(" Core Cuts (bcutnum %i)\n", bcutnum);
374  for (int i = 0; i < bcutnum; ++i) {
375  printf(" cut %4i: bcpind %i, status %i, lb %f, ub %f\n",
376  i, cuts[i]->bcpind(), cuts[i]->status(),
377  cuts[i]->lb(), cuts[i]->ub());
378  }
379  }
380  if (dumpvars) {
381  printf(" Extra Vars (extra varnum %i)\n", varnum - bvarnum);
382  for (int i = bvarnum; i < varnum; ++i) {
383  printf(" var %4i: bcpind %i, status %i, lb %f, ub %f\n",
384  i, vars[i]->bcpind(), vars[i]->status(),
385  vars[i]->lb(), vars[i]->ub());
386  }
387  }
388  if (dumpcuts) {
389  printf(" Extra Cuts (extra cutnum %i)\n", cutnum - bcutnum);
390  for (int i = bcutnum; i < cutnum; ++i) {
391  printf(" cut %4i: bcpind %i, status %i, lb %f, ub %f\n",
392  i, cuts[i]->bcpind(), cuts[i]->status(),
393  cuts[i]->lb(), cuts[i]->ub());
394  }
395  }
396  printf("LP: NEW ACTIVE NODE %i DUMP END ===========================\n",
397  current_index());
398  }
399 }
400 
401 //#############################################################################
402 // Opportunity to reset things before optimization
403 void
404 BCP_lp_user::modify_lp_parameters(OsiSolverInterface* lp, const int changeType,
405  bool in_strong_branching)
406 {
408  "LP: Default prepare_for_optimization() executed.\n");
409 
410  if (changeType == 1) { // primal feas was affected
411  lp->setHintParam(OsiDoDualInResolve, true, OsiHintTry);
412  return;
413  }
414  if (changeType == 2) { // dual feas was affected
415  lp->setHintParam(OsiDoDualInResolve, false, OsiHintTry);
416  return;
417  }
418  // Neither or both, so let the solver decide
419  lp->setHintParam(OsiDoDualInResolve, true, OsiHintIgnore);
420 }
421 
422 //#############################################################################
423 void
425  const BCP_vec<BCP_var*>& vars,
426  const BCP_vec<BCP_cut*>& cuts,
427  const double old_lower_bound,
428  double& true_lower_bound,
429  BCP_solution*& sol,
430  BCP_vec<BCP_cut*>& new_cuts,
431  BCP_vec<BCP_row*>& new_rows,
432  BCP_vec<BCP_var*>& new_vars,
433  BCP_vec<BCP_col*>& new_cols)
434 {
436 }
437 
438 //#############################################################################
439 // Generating a true lower bound
440 double
441 BCP_lp_user::compute_lower_bound(const double old_lower_bound,
442  const BCP_lp_result& lpres,
443  const BCP_vec<BCP_var*>& vars,
444  const BCP_vec<BCP_cut*>& cuts)
445 {
446  // If columns are to be generated then we can't say anything, just return
447  // the current lower bound
449  return old_lower_bound;
450 
451  // Otherwise we got the examine the termination code and the objective
452  // value of the LP solution
453  const int tc = lpres.termcode();
454  if (tc & BCP_ProvenOptimal)
455  return lpres.objval();
456 
457  // The limit (the upper bound) on the dual objective is proven to be
458  // reached, but the objval might not reflect this! (the LP solver may not
459  // make the last iteration that pushes objval over the limit). So we return
460  // a high value ourselves.
461  if (tc & BCP_DualObjLimReached)
462  return p->ub() + 1e-5;
463 
464  // We can't say anything in any other case
465  // (BCP_ProvenPrimalInf | BCP_ProvenDualInf | BCP_PrimalObjLimReached |
466  // BCP_TimeLimit | BCP_Abandoned), not to mention that some of these are
467  // impossible. Just return the current bound.
468  return old_lower_bound;
469 }
470 
471 //#############################################################################
472 // Feasibility testing
475  const BCP_vec<BCP_var*>& vars,
476  const BCP_vec<BCP_cut*>& cuts)
477 {
479  "LP: Default test_feasibility() executed.\n");
480 
481  const double etol = p->param(BCP_lp_par::IntegerTolerance);
482  BCP_feasibility_test test =
484 
485  BCP_solution* sol = NULL;
486  switch (test){
487  case BCP_Binary_Feasible: sol = test_binary(lpres, vars, etol); break;
488  case BCP_Integral_Feasible: sol = test_integral(lpres, vars, etol); break;
489  case BCP_FullTest_Feasible: sol = test_full(lpres, vars, etol); break;
490  default:
491  throw BCP_fatal_error("LP: unknown test_feasibility() rule.\n");
492  }
493 
494  return sol;
495 }
496 
497 //-----------------------------------------------------------------------------
498 
501  const BCP_vec<BCP_var*>& vars,
502  const double etol) const
503 {
505  "LP: Default test_binary() executed.\n");
506 
507  // Do anything only if the termination code is sensible
508  const int tc = lpres.termcode();
509  if (! (tc & BCP_ProvenOptimal))
510  return 0;
511 
512  const double * x = lpres.x();
513  const int varnum = vars.size();
514  const double etol1 = 1 - etol;
515  int i;
516 
517  for (i = 0 ; i < varnum; ++i) {
518  const double xi = x[i];
519  if (xi > etol && xi < etol1)
520  return(NULL);
521  }
522 
523  // This solution does not own the pointers to the variables
524  BCP_solution_generic* sol = new BCP_solution_generic(false);
525  double obj = 0;
526  for (i = 0 ; i < varnum; ++i) {
527  if (x[i] > etol1) {
528  sol->add_entry(vars[i], 1.0);
529  obj += vars[i]->obj();
530  }
531  }
532  sol->_objective = obj;
533  return sol;
534 }
535 //-----------------------------------------------------------------------------
538  const BCP_vec<BCP_var*>& vars,
539  const double etol) const
540 {
542  "LP: Default test_integral() executed.\n");
543 
544  // Do anything only if the termination code is sensible
545  const int tc = lpres.termcode();
546  if (! (tc & BCP_ProvenOptimal))
547  return 0;
548 
549  const double * x = lpres.x();
550  const int varnum = vars.size();
551  const double etol1 = 1 - etol;
552  int i;
553 
554  for (i = 0 ; i < varnum; ++i) {
555  const double val = x[i] - floor(x[i]);
556  if (val > etol && val < etol1)
557  return(NULL);
558  }
559 
560  // This solution does not own the pointers to the variables
561  BCP_solution_generic* sol = new BCP_solution_generic(false);
562  double obj = 0;
563  for (i = 0 ; i < varnum; ++i) {
564  const double val = floor(x[i] + 0.5);
565  if (val != 0.0) { // it's OK to test the double against 0,
566  // since we took the floor()
567  sol->add_entry(vars[i], val);
568  obj += val * vars[i]->obj();
569  }
570  }
571  sol->_objective = obj;
572  return sol;
573 }
574 //-----------------------------------------------------------------------------
577  const BCP_vec<BCP_var*>& vars,
578  const double etol) const
579 {
581  "LP: Default test_full() executed.\n");
582 
583  // Do anything only if the termination code is sensible
584  const int tc = lpres.termcode();
585  if (! (tc & BCP_ProvenOptimal))
586  return 0;
587 
588  const double * x = lpres.x();
589  const int varnum = vars.size();
590  const double etol1 = 1 - etol;
591  int i;
592 
593  for (i = 0 ; i < varnum; ++i) {
594  switch (vars[i]->var_type()){
595  case BCP_BinaryVar:
596  {
597  const double val = x[i];
598  if (val > etol && val < etol1)
599  return(NULL);
600  }
601  break;
602  case BCP_IntegerVar:
603  {
604  const double val = x[i] - floor(x[i]);
605  if (val > etol && val < etol1)
606  return(NULL);
607  }
608  break;
609  case BCP_ContinuousVar:
610  break;
611  }
612  }
613 
614  // This solution does not own the pointers to the variables
615  BCP_solution_generic* sol = new BCP_solution_generic(false);
616  double obj = 0;
617  for (i = 0 ; i < varnum; ++i) {
618  // round the integer vars
619  const double val = (vars[i]->var_type() == BCP_ContinuousVar) ?
620  x[i] : floor(x[i] + 0.5);
621  if (val < -etol || val > etol) {
622  sol->add_entry(vars[i], val);
623  obj += val * vars[i]->obj();
624  }
625  }
626  sol->_objective = obj;
627  return sol;
628 }
629 
630 //#############################################################################
631 // Heuristic solution generation
634  const BCP_vec<BCP_var*>& vars,
635  const BCP_vec<BCP_cut*>& cuts)
636 {
638  "LP: Default generate_heuristic_solution() executed.\n");
639  return NULL;
640 }
641 //#############################################################################
642 // Feasible solution packing
643 void
645 {
647  "LP: Default pack_feasible_solution() executed.\n");
648 
649  const BCP_solution_generic* gensol =
650  dynamic_cast<const BCP_solution_generic*>(sol);
651  const BCP_vec<BCP_var*> solvars = gensol->_vars;
652  const BCP_vec<double> values = gensol->_values;
653  const int size = solvars.size();
654  buf.pack(size);
655  for (int i = 0; i < size; ++i) {
656  buf.pack(values[i]);
657  p->pack_var(*solvars[i]);
658  }
659  buf.pack(gensol->objective_value());
660 }
661 
662 //#############################################################################
663 // pack message for CG/CP
664 
665 void
667  const BCP_lp_result& lpres,
668  const BCP_vec<BCP_var*>& vars,
669  const BCP_vec<BCP_cut*>& cuts)
670 {
672  "LP: Default pack_for_cg() executed.\n");
673 
674  BCP_vec<int> coll;
675 
676  const double petol = lpres.primalTolerance();
677  const double * x = lpres.x();
678  const int varnum = vars.size();
679 
680  switch (p->param(BCP_lp_par::InfoForCG)){
682  select_nonzeros(x, x + varnum, petol, coll);
684  break;
686  select_fractions(x, x+varnum, petol, coll);
688  break;
690  coll.reserve(varnum);
691  for (int i = 0; i < varnum; ++i) {
692  coll.unchecked_push_back(i);
693  }
695  break;
696  default:
697  throw BCP_fatal_error("Incorrect msgtag in pack_for_cg() !\n");
698  }
699 
700  const int size = coll.size();
701  buf.pack(size);
702  if (size > 0){
703  BCP_vec<int>::const_iterator pos = coll.begin() - 1;
704  const BCP_vec<int>::const_iterator last_pos = coll.end();
705  while (++pos != last_pos) {
706  buf.pack(x[*pos]);
707  p->pack_var(*vars[*pos]);
708  }
709  }
710 }
711 
712 //=============================================================================
713 // pack message for VG/VP
714 
715 void
717  const BCP_lp_result& lpres,
718  const BCP_vec<BCP_var*>& vars,
719  const BCP_vec<BCP_cut*>& cuts)
720 {
722  "LP: Default pack_for_vg() executed.\n");
723 
724  BCP_vec<int> coll;
725 
726  const double detol = lpres.dualTolerance();
727  const double * pi = lpres.pi();
728  const int cutnum = cuts.size();
729 
730  switch (p->param(BCP_lp_par::InfoForVG)){
732  select_nonzeros(pi, pi+cutnum, detol, coll);
734  break;
736  coll.reserve(cutnum);
737  for (int i = 0; i < cutnum; ++i) {
738  coll.unchecked_push_back(i);
739  }
741  break;
742  default:
743  throw BCP_fatal_error("Incorrect msgtag in pack_lp_solution() !\n");
744  }
745 
746  const int size = coll.size();
747  buf.pack(size);
748  if (size > 0){
749  BCP_vec<int>::const_iterator pos = coll.begin() - 1;
750  const BCP_vec<int>::const_iterator last_pos = coll.end();
751  while (++pos != last_pos) {
752  buf.pack(pi[*pos]);
753  p->pack_cut(*cuts[*pos]);
754  }
755  }
756 }
757 
758 //#############################################################################
759 // lp solution displaying
760 void
762  const BCP_vec<BCP_var*>& vars,
763  const BCP_vec<BCP_cut*>& cuts,
764  const bool final_lp_solution)
765 {
767  "LP: Default display_lp_solution() executed.\n");
768 
769  if (final_lp_solution) {
771  return;
772  print(true," LP : Displaying LP solution (FinalRelaxedSolution) :\n");
773  } else {
775  return;
776  print(true," LP : Displaying LP solution (RelaxedSolution) :\n");
777  }
778 
779  const double ietol = p->param(BCP_lp_par::IntegerTolerance);
780 
781  print(true, " LP : Displaying solution :\n");
782  BCP_vec<int> coll;
783  const double * x = lpres.x();
784  select_nonzeros(x, x+vars.size(), ietol, coll);
785  const int size = coll.size();
786  for (int i = 0; i < size; ++i) {
787  const int ind = coll[i];
788  vars[ind]->display(x[ind]);
789  }
790 }
791 
792 //#############################################################################
793 // restoring feasibility
794 void
796  const std::vector<double*> dual_rays,
797  const BCP_vec<BCP_var*>& vars,
798  const BCP_vec<BCP_cut*>& cuts,
799  BCP_vec<BCP_var*>& vars_to_add,
800  BCP_vec<BCP_col*>& cols_to_add)
801 {
803  "LP: Default restore_feasibility() executed.\n");
804 }
805 
806 //#############################################################################
807 //#############################################################################
808 
809 void
810 BCP_lp_user::cuts_to_rows(const BCP_vec<BCP_var*>& vars, // on what to expand
811  BCP_vec<BCP_cut*>& cuts, // what to expand
812  BCP_vec<BCP_row*>& rows, // the expanded rows
813  // things that the user can use for lifting cuts
814  // if allowed
815  const BCP_lp_result& lpres,
816  BCP_object_origin origin, bool allow_multiple)
817 {
819  "LP: Default cuts_to_rows() executed.\n");
820  throw BCP_fatal_error("cuts_to_rows() missing.\n");
821 }
822 //-----------------------------------------------------------------------------
823 void
824 BCP_lp_user::vars_to_cols(const BCP_vec<BCP_cut*>& cuts, // on what to expand
825  BCP_vec<BCP_var*>& vars, // what to expand
826  BCP_vec<BCP_col*>& cols, // the expanded cols
827  // things that the user can use for lifting vars
828  // if allowed
829  const BCP_lp_result& lpres,
830  BCP_object_origin origin, bool allow_multiple)
831 {
833  "LP: Default vars_to_cols() executed.\n");
834  throw BCP_fatal_error("vars_to_cols() missing.\n");
835 }
836 
837 //#############################################################################
838 
839 void
841  const BCP_vec<BCP_var*>& vars,
842  const BCP_vec<BCP_cut*>& cuts,
843  BCP_vec<BCP_cut*>& new_cuts,
844  BCP_vec<BCP_row*>& new_rows)
845 {
847  "LP: Default generate_cuts_in_lp() executed.\n");
848 }
849 //-----------------------------------------------------------------------------
850 void
852  const BCP_vec<BCP_var*>& vars,
853  const BCP_vec<BCP_cut*>& cuts,
854  const bool before_fathom,
855  BCP_vec<BCP_var*>& new_vars,
856  BCP_vec<BCP_col*>& new_cols)
857 {
859  "LP: Default generate_vars_in_lp() executed.\n");
860 }
861 //-----------------------------------------------------------------------------
864 {
866  "LP: Default compare_cuts() executed.\n");
867  return BCP_DifferentObjs;
868 }
869 //-----------------------------------------------------------------------------
872 {
874  "LP: Default compare_vars() executed.\n");
875  return BCP_DifferentObjs;
876 }
877 
878 //#############################################################################
879 
880 void
882  const BCP_vec<BCP_var*>& vars,
883  const BCP_vec<BCP_cut*>& cuts,
884  const bool before_fathom,
885  BCP_vec<int>& deletable)
886 {
887  if (before_fathom && p->param(BCP_lp_par::NoCompressionAtFathom))
888  return;
889  const int varnum = vars.size();
890  deletable.reserve(varnum);
891  for (int i = p->core->varnum(); i < varnum; ++i) {
892  BCP_var *var = vars[i];
893  if (var->is_to_be_removed() ||
894  (! var->is_non_removable() && var->lb() == 0 && var->ub() == 0)) {
895  deletable.unchecked_push_back(i);
896  }
897  }
898 }
899 
900 //=============================================================================
901 
902 void
904  const BCP_vec<BCP_var*>& vars,
905  const BCP_vec<BCP_cut*>& cuts,
906  const bool before_fathom,
907  BCP_vec<int>& deletable)
908 {
909  if (before_fathom && p->param(BCP_lp_par::NoCompressionAtFathom))
910  return;
911  const int cutnum = cuts.size();
912  const int ineff_to_delete = p->param(BCP_lp_par::IneffectiveBeforeDelete);
913  const double lb = lpres.objval();
914  const BCP_vec<double>& lb_at_cutgen = p->node->lb_at_cutgen;
915  deletable.reserve(cutnum);
916  for (int i = p->core->cutnum(); i < cutnum; ++i) {
917  BCP_cut *cut = cuts[i];
918  if (cut->is_to_be_removed() ||
919  (! cut->is_non_removable() &&
920  cut->effective_count() <= -ineff_to_delete &&
921  lb_at_cutgen[i] < lb - 0.0001)) {
922  deletable.unchecked_push_back(i);
923  }
924  }
925 }
926 
927 //#############################################################################
928 
929 void
931  const BCP_vec<BCP_var*>& vars,
932  const BCP_vec<BCP_cut*>& cuts,
933  const BCP_vec<BCP_obj_status>& var_status,
934  const BCP_vec<BCP_obj_status>& cut_status,
935  const int var_bound_changes_since_logical_fixing,
936  BCP_vec<int>& changed_pos,
937  BCP_vec<double>& new_bd)
938 {
940  "LP: Default logical_fixing() executed.\n");
941 }
942 
943 //#############################################################################
944 void
945 BCP_lp_user::reduced_cost_fixing(const double* dj, const double* x,
946  const double gap,
947  BCP_vec<BCP_var*>& vars, int& newly_changed)
948 {
949  OsiBabSolver* babSolver = getOsiBabSolver();
950  if (babSolver && !babSolver->reducedCostsAccurate())
951  return;
952 
953  newly_changed = 0;
956 
957  if (! atZero && ! atAny)
958  return;
959 
960  double petol = 0.0;
961  p->lp_solver->getDblParam(OsiPrimalTolerance, petol);
962  double detol = 0.0;
963  p->lp_solver->getDblParam(OsiDualTolerance, detol);
964 
965  // If the gap is negative that means that we are above the limit, so
966  // don't do anything.
967  if (gap < 0)
968  return;
969 
970  const int varnum = vars.size();
971  BCP_vec<int> changed_indices;
972  changed_indices.reserve(varnum);
973  BCP_vec<double> changed_bounds;
974  changed_bounds.reserve(2 * varnum);
975 
976  // Note that when this function is called, we must have a dual
977  // feasible dual solution. Therefore we can use the lagrangean
978  // relaxation to fix variables.
979 
980  // *FIXME* : If we knew that there are integral vars only, then
981  // we could leave out the test for BCP_ContinuousVar...
982  for (int i = 0; i < varnum; ++i) {
983  BCP_var* var = vars[i];
984  if (! var->is_fixed() && var->var_type() != BCP_ContinuousVar){
985  if (dj[i] > detol) {
986  const double lb = var->lb();
987  const double new_ub = lb + floor(gap / dj[i]);
988  if (new_ub < var->ub() && (atAny || CoinAbs(x[i])<petol) ) {
989  vars[i]->set_ub(new_ub);
990  changed_indices.unchecked_push_back(i);
991  changed_bounds.unchecked_push_back(lb);
992  changed_bounds.unchecked_push_back(new_ub);
993  }
994  } else if (dj[i] < -detol) {
995  const double ub = var->ub();
996  const double new_lb = ub - floor(gap / (-dj[i]));
997  if (new_lb > var->lb() && (atAny || CoinAbs(x[i])<petol) ) {
998  vars[i]->set_lb(new_lb);
999  changed_indices.unchecked_push_back(i);
1000  changed_bounds.unchecked_push_back(new_lb);
1001  changed_bounds.unchecked_push_back(ub);
1002  }
1003  }
1004  }
1005  }
1006  newly_changed = changed_indices.size();
1007  if (newly_changed > 0) {
1008  p->lp_solver->setColSetBounds(changed_indices.begin(),
1009  changed_indices.end(),
1010  changed_bounds.begin());
1011  }
1012 }
1013 
1014 //#############################################################################
1015 //#############################################################################
1016 
1017 int
1018 BCP_lp_user::try_to_branch(OsiBranchingInformation& branchInfo,
1019  OsiSolverInterface* solver,
1020  OsiChooseVariable* choose,
1021  OsiBranchingObject*& branchObject,
1022  bool allowVarFix)
1023 {
1024  int returnStatus = 0;
1025  int numUnsatisfied = choose->setupList(&branchInfo, true);
1026  choose->setBestObjectIndex(-1);
1027  if (numUnsatisfied > 0) {
1028  if (choose->numberOnList() == 0) {
1029  // Nothing left for strong branching to evaluate
1030  if (choose->numberOnList() > 0 || choose->numberStrong() == 0) {
1031  // There is something on the list
1032  choose->setBestObjectIndex(choose->candidates()[0]);
1033  } else {
1034  // There is nothing on the list
1035  numUnsatisfied = choose->setupList(&branchInfo, false);
1036  if (numUnsatisfied > 0) {
1037  choose->setBestObjectIndex(choose->candidates()[0]);
1038  }
1039  }
1040  } else {
1041  // Do the strong branching
1042  int ret = choose->chooseVariable(solver, &branchInfo, allowVarFix);
1043  /* Check if SB has fixed anything, and if so, apply the same
1044  changes to the vars */
1045  const double * clb = solver->getColLower();
1046  const double * cub = solver->getColUpper();
1047  BCP_vec<BCP_var*>& vars = p->node->vars;
1048  for (int i = numUnsatisfied - 1; i >= 0; --i) {
1049  const int ind =
1050  solver->object(choose->candidates()[i])->columnNumber();
1051  if (ind >= 0) {
1052  assert(vars[ind]->lb() <= clb[ind]);
1053  assert(vars[ind]->ub() >= cub[ind]);
1054  vars[ind]->set_lb_ub(clb[ind], cub[ind]);
1055  }
1056  }
1057 
1058  /* update number of strong iterations etc
1059  model->incrementStrongInfo(choose->numberStrongDone(),
1060  choose->numberStrongIterations(),
1061  ret==-1 ? 0:choose->numberStrongFixed(),
1062  ret==-1);
1063  */
1064  if (ret > 1) {
1065  // has fixed some
1066  returnStatus = -1;
1067  } else if (ret == -1) {
1068  // infeasible
1069  returnStatus = -2;
1070  } else if (ret == 0) {
1071  // normal
1072  returnStatus = 0;
1073  numUnsatisfied = 1;
1074  } else {
1075  // ones on list satisfied - double check
1076  numUnsatisfied = choose->setupList(&branchInfo, false);
1077  if (numUnsatisfied > 0) {
1078  choose->setBestObjectIndex(choose->candidates()[0]);
1079  }
1080  }
1081  }
1082  }
1083  if (! returnStatus) {
1084  if (numUnsatisfied > 0) {
1085  // create branching object
1086  /* FIXME: how the objects are created? */
1087  const OsiObject * obj = solver->object(choose->bestObjectIndex());
1088  branchObject = obj->createBranch(solver,
1089  &branchInfo,
1090  obj->whichWay());
1091  }
1092  }
1093 
1094  return returnStatus;
1095 }
1096 
1097 //#############################################################################
1098 
1101  const BCP_vec<BCP_var*>& vars,
1102  const BCP_vec<BCP_cut*>& cuts,
1103  const BCP_lp_var_pool& local_var_pool,
1104  const BCP_lp_cut_pool& local_cut_pool,
1106  bool force_branch)
1107 {
1109  "LP: Default select_branching_candidates() executed.\n");
1110 
1111  if (lpres.termcode() & BCP_Abandoned) {
1112  // *THINK*: maybe we should branch through...
1113  print(true, "\
1114 LP: ############ LP solver abandoned. Branching through...\n");
1115  }
1116 
1117  // *THINK* : this branching object selection is very primitive
1118  // *THINK* : should check for tail-off, could check for branching cuts, etc
1119  if (! force_branch &&
1120  (local_var_pool.size() > 0 || local_cut_pool.size() > 0))
1121  return BCP_DoNotBranch;
1122 
1123  OsiSolverInterface* lp = p->lp_solver;
1124 
1125  /* The last true: make a copy in brInfo of the sol of solver
1126  instead of just pointing into the solver's copy */
1127  OsiBranchingInformation brInfo(lp, true, true);
1128  lp->getDblParam(OsiDualObjectiveLimit, brInfo.cutoff_);
1129  brInfo.integerTolerance_ = p->param(BCP_lp_par::IntegerTolerance);
1130  brInfo.timeRemaining_ = get_param(BCP_lp_par::MaxRunTime) - CoinCpuTime();
1131  brInfo.numberSolutions_ = 0; /*FIXME*/
1132  brInfo.numberBranchingSolutions_ = 0; /*FIXME numBranchingSolutions_;*/
1133  brInfo.depth_ = current_level();
1134 
1135  OsiChooseStrong* strong = new OsiChooseStrong(lp);
1136  strong->setNumberBeforeTrusted(5); // the default in Cbc
1137  strong->setNumberStrong(p->param(BCP_lp_par::StrongBranchNum));
1138  strong->setTrustStrongForSolution(false);
1144  strong->setShadowPriceMode(0);
1145 
1146  OsiChooseVariable * choose = strong;
1147  OsiBranchingObject* brObj = NULL;
1148 
1149  bool allowVarFix = true;
1150  /*
1151  <li> 0: A branching object has been installed
1152  <li> -1: A monotone object was discovered
1153  <li> -2: An infeasible object was discovered
1154  */
1155  int brResult =
1156  try_to_branch(brInfo, lp, choose, brObj, allowVarFix);
1157  const int bestWhichWay = choose->bestWhichWay();
1158 
1159 #if 0
1160  /* FIXME:before doing anything check if we have found a new solution */
1161  if (choose->goodSolution()
1162  &&model->problemFeasibility()->feasible(model,-1)>=0) {
1163  // yes
1164  double objValue = choose->goodObjectiveValue();
1165  model->setBestSolution(CBC_STRONGSOL,
1166  objValue,
1167  choose->goodSolution()) ;
1168  model->setLastHeuristic(NULL);
1169  model->incrementUsed(choose->goodSolution());
1170  choose->clearGoodSolution();
1171  }
1172 #endif
1173 
1174  delete choose;
1175 
1176  switch (brResult) {
1177  case -2:
1178  // when doing strong branching a candidate has proved that the
1179  // problem is infeasible
1180  delete brObj;
1181  return BCP_DoNotBranch_Fathomed;
1182  case -1:
1183  // OsiChooseVariable::chooseVariable() returned 2, 3, or 4
1184  if (!brObj) {
1185  // just go back and resolve
1186  return BCP_DoNotBranch;
1187  }
1188  // otherwise might as well branch. The forced variable is
1189  // unlikely to jump up one more (though who knows...)
1190  break;
1191  case 0:
1192  if (!brObj) {
1193  // nothing got fixed, yet couldn't find something to branch on
1194  throw BCP_fatal_error("BM: Couldn't branch!\n");
1195  }
1196  // we've got a branching object
1197  break;
1198  default:
1199  throw BCP_fatal_error("\
1200 BCP: BCP_lp_user::try_to_branch returned with unknown return code.\n");
1201  }
1202 
1203  // If there were some fixings (brResult < 0) then propagate them where
1204  // needed
1205  if (allowVarFix && brResult < 0) {
1206  const double* clb = lp->getColLower();
1207  const double* cub = lp->getColUpper();
1208  /* There may or may not have been changes, but faster to set then to
1209  test... */
1210  BCP_vec<BCP_var*>& vars = p->node->vars;
1211  int numvars = vars.size();
1212  for (int i = 0; i < numvars; ++i) {
1213  vars[i]->change_bounds(clb[i], cub[i]);
1214  }
1215  }
1216 
1217  // all possibilities are 2-way branches
1218  int order[2] = {0, 1};
1219  if (bestWhichWay == 1) {
1220  order[0] = 1;
1221  order[1] = 0;
1222  }
1223 
1224  // Now interpret the result (at this point we must have a brObj
1225  OsiIntegerBranchingObject* intBrObj =
1226  dynamic_cast<OsiIntegerBranchingObject*>(brObj);
1227  if (intBrObj) {
1228  BCP_lp_integer_branching_object o(intBrObj);
1229  cands.push_back(new BCP_lp_branching_object(o, order));
1230  }
1231  OsiSOSBranchingObject* sosBrObj =
1232  dynamic_cast<OsiSOSBranchingObject*>(brObj);
1233  if (sosBrObj) {
1234  BCP_lp_sos_branching_object o(sosBrObj);
1235  cands.push_back(new BCP_lp_branching_object(lp, o, order));
1236  }
1237 
1238  delete brObj;
1239 
1240  if (cands.size() == 0) {
1241  throw BCP_fatal_error("\
1242  LP : No var/cut in pool but couldn't select branching object.\n");
1243  }
1244  return BCP_DoBranch;
1245 }
1246 
1247 //-----------------------------------------------------------------------------
1248 void
1250  const BCP_vec<BCP_var*>& vars,
1251  const BCP_vec<int>& select_pos,
1253 {
1255  BCP_vec<double> vbd(4, 0.0);
1256  BCP_vec<int> vpos(1, 0);
1257 
1258  for (spi = select_pos.begin(); spi != select_pos.end(); ++spi) {
1259  const int pos = *spi;
1260  vpos[0] = pos;
1261  vbd[0] = vars[pos]->lb();
1262  vbd[1] = floor(x[pos]);
1263  vbd[2] = ceil(x[pos]);
1264  vbd[3] = vars[pos]->ub();
1265  cans.push_back
1266  (new BCP_lp_branching_object(2,
1267  0, 0, /* vars/cuts_to_add */
1268  &vpos, 0, &vbd, 0, /* forced parts */
1269  0, 0, 0, 0 /* implied parts */));
1270  }
1271 }
1272 
1273 //-----------------------------------------------------------------------------
1276  BCP_presolved_lp_brobj* old_presolved)
1277 {
1279  "LP: Default compare_presolved_branching_objects() executed.\n");
1280 
1281  // change the objvals according to the termcodes (in order to be able to
1282  // make decisions based on objval, no matter what the termcode is).
1283  new_presolved->fake_objective_values(p->lp_result->objval());
1284 
1285  // If using this branching object we can fathom all children, then choose
1286  // this object
1287  if (new_presolved->fathomable(p->ub() - p->granularity()))
1289 
1290  // If this is the first, keep it
1291  if (! old_presolved)
1292  return(BCP_NewPresolvedIsBetter);
1293 
1294  // If something had gone wrong with at least one descendant in the new then
1295  // we prefer to keep the old.
1296  if (new_presolved->had_numerical_problems())
1297  return(BCP_OldPresolvedIsBetter);
1298 
1299  // OK, so all descendants finished just fine. Do whatever the parameter
1300  // says
1301 
1303  const double objetol = 1e-7;
1304 
1305  BCP_vec<double> new_obj;
1306  new_presolved->get_lower_bounds(new_obj);
1307  std::sort(new_obj.begin(), new_obj.end());
1308  const int new_not_fathomed =
1309  new_obj.index(std::lower_bound(new_obj.begin(), new_obj.end(),
1310  BCP_DBL_MAX / 10));
1311 
1312  BCP_vec<double> old_obj;
1313  old_presolved->get_lower_bounds(old_obj);
1314  std::sort(old_obj.begin(), old_obj.end());
1315  const int old_not_fathomed =
1316  old_obj.index(std::lower_bound(old_obj.begin(), old_obj.end(),
1317  BCP_DBL_MAX / 10));
1318 
1319  if (new_not_fathomed < old_not_fathomed)
1320  return BCP_NewPresolvedIsBetter;
1321 
1322  if (new_not_fathomed > old_not_fathomed)
1323  return BCP_OldPresolvedIsBetter;
1324 
1325  BCP_vec<double>::const_iterator new_first = new_obj.begin();
1326  BCP_vec<double>::const_iterator new_last = new_obj.end();
1327  BCP_vec<double>::const_iterator old_first = old_obj.begin();
1328  BCP_vec<double>::const_iterator old_last = old_obj.end();
1329 
1333  {
1334  double newavg = 0;
1335  for ( ; new_first != new_last; ++new_first) {
1336  if (*new_first < BCP_DBL_MAX / 10)
1337  newavg += *new_first;
1338  }
1339  newavg /= new_not_fathomed;
1340  double oldavg = 0;
1341  for ( ; old_first != old_last; ++old_first) {
1342  if (*old_first < BCP_DBL_MAX / 10)
1343  oldavg += *old_first;
1344  }
1345  oldavg /= old_not_fathomed;
1346  const bool high =
1349  return (high && newavg > oldavg) || (!high && newavg < oldavg)?
1351  }
1352 
1353  case BCP_LowestLowObjval:
1354  for ( ; new_first != new_last && old_first != old_last;
1355  ++new_first, ++old_first) {
1356  if (*new_first < *old_first - objetol)
1357  return BCP_NewPresolvedIsBetter;
1358  if (*new_first > *old_first + objetol)
1359  return BCP_OldPresolvedIsBetter;
1360  }
1361  return old_first == old_last ?
1363 
1364  case BCP_HighestLowObjval:
1365  for ( ; new_first != new_last && old_first != old_last;
1366  ++new_first, ++old_first) {
1367  if (*new_first > *old_first + objetol)
1368  return BCP_NewPresolvedIsBetter;
1369  if (*new_first < *old_first - objetol)
1370  return BCP_OldPresolvedIsBetter;
1371  }
1372  return old_first == old_last ?
1374 
1375  case BCP_LowestHighObjval:
1376  while (new_first != new_last && old_first != old_last) {
1377  --new_last;
1378  --old_last;
1379  if (*new_last < *old_last - objetol)
1380  return BCP_NewPresolvedIsBetter;
1381  if (*new_last > *old_last + objetol)
1382  return BCP_OldPresolvedIsBetter;
1383  }
1384  return old_first == old_last ?
1386 
1387  case BCP_HighestHighObjval:
1388  while (new_first != new_last && old_first != old_last) {
1389  --new_last;
1390  --old_last;
1391  if (*new_last > *old_last + objetol)
1392  return BCP_NewPresolvedIsBetter;
1393  if (*new_last < *old_last - objetol)
1394  return BCP_OldPresolvedIsBetter;
1395  }
1396  return old_first == old_last ?
1398  default:
1399  throw BCP_fatal_error("\
1400 Unknown branching object comparison rule.\n");
1401  }
1402  }
1403 
1404  // shouldn't ever get here
1405  throw BCP_fatal_error("No branching object comparison rule is chosen.\n");
1406 
1407  // fake return
1408  return BCP_NewPresolvedIsBetter;
1409 }
1410 
1411 //-----------------------------------------------------------------------------
1412 void
1414 {
1416  "LP: Default set_actions_for_children() executed.\n");
1417 
1418  // by default every action is set to BCP_ReturnChild
1419  if (p->node->dive == BCP_DoNotDive)
1420  return;
1421 
1422  BCP_vec<BCP_child_action>& action = best->action();
1423  int i, ind;
1424 
1425  switch (p->param(BCP_lp_par::ChildPreference)){
1426  case BCP_PreferDiveDown:
1427  ind = 0;
1428  break;
1429 
1430  case BCP_PreferDiveUp:
1431  ind = best->candidate()->child_num - 1;
1432  break;
1433 
1435  // NOTE: if the lowest objval child is fathomed then everything is
1436  for (ind = 0, i = best->candidate()->child_num - 1; i > 0; --i){
1437  if (best->lpres(i).objval() < best->lpres(ind).objval())
1438  ind = i;
1439  }
1440  break;
1441 
1443  // NOTE: this selects the highest objval child NOT FATHOMED, thus if
1444  // the highest objval child is fathomed then everything is
1445  for (ind = 0, i = best->candidate()->child_num - 1; i > 0; --i) {
1446  if (! p->over_ub(best->lpres(i).objval()) &&
1447  best->lpres(i).objval() < best->lpres(ind).objval())
1448  ind = i;
1449  }
1450  break;
1451  default:
1452  // *THINK* : fractional branching
1453  throw BCP_fatal_error("LP : Unrecognized child preference.\n");
1454  }
1455  // mark the ind-th to be kept (if not over ub)
1456  if (! p->over_ub(best->lpres(ind).objval()))
1457  action[ind] = BCP_KeepChild;
1458 }
1459 
1460 //#############################################################################
1461 
1462 void
1464  const int selected)
1465 {
1469  "\
1470 *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***\n\
1471 You have overridden\n\
1472  BCP_lp_user::set_user_data_for_children(BCP_presolved_lp_brobj* best)\n\
1473 which is a deprecated virtual function. Please override\n\
1474  BCP_lp_user::set_user_data_for_children(BCP_presolved_lp_brobj* best,\n\
1475  const int selected)\n\
1476 instead. The old version will go away, your code will still compile, but it\n\
1477 will not do what you intend it to be doing.\n\
1478 *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***\n"\
1479  );
1480 }
1481 
1482 //#############################################################################
1483 
1484 void
1486 {
1489  "LP: Default set_user_data_for_children() executed.\n");
1490 }
1491 
1492 //#############################################################################
1493 // purging the slack cut pool (candidates for branching on cut)
1494 void
1496  BCP_vec<int>& to_be_purged)
1497 {
1499  "LP: Default purge_slack_pool() executed.\n");
1500 
1503  if (current_iteration() != 1)
1504  break;
1506  {
1507  const int size = slack_pool.size();
1508  if (size > 0) {
1509  to_be_purged.reserve(size);
1510  for (int i = 0; i < size; ++i)
1511  to_be_purged.unchecked_push_back(i);
1512  }
1513  }
1514  break;
1515  }
1516 }
1517 
1518 //#############################################################################
Binary (0-1) variable.
Definition: BCP_enum.hpp:163
BCP_object_origin
This enumerative constant describes the origin (originating process) of an object (variable or cut)...
Definition: BCP_enum.hpp:249
size_t index(const_iterator pos) const
Return the index of the entry pointed to by pos.
Definition: BCP_vector.hpp:114
double * values
char get_param(const BCP_lp_par::chr_params key) const
Definition: BCP_lp_user.cpp:51
int_params
Integer parameters.
How many times in a row a constraint must be found ineffective before it is marked for deletion...
Values not further from an integer value than the value of this parameter are considered to be intege...
void BCP_lp_add_rows_to_lp(const BCP_vec< BCP_row * > &rows, OsiSolverInterface *lp)
const BCP_vec< double > & RowLowerBound() const
A const reference to the vector of lower bounds on the cuts.
Definition: BCP_matrix.hpp:298
BCP_message_tag
This enumerative constant describes the message tags different processes of BCP understand.
virtual void send(const int target, const BCP_message_tag tag)=0
Send an empty message (message tag only) to the process given by the frist argument.
This class describes the core of the MIP problem, the variables/cuts in it as well as the matrix corr...
This child should be kept and dived into (provided diving is decided on.
If true the BCP will attempt to do reduced cost fixing for any variable, no matter what is their curr...
BCP_parameter_set< BCP_lp_par > par
Definition: BCP_lp.hpp:145
str_params
String parameters.
BCP_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
Specifies which built-in MIP feasibility testing routine should be invoked (if a buit-in routine is u...
int get_process_id() const
Definition: BCP_process.hpp:24
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
virtual void process_lp_result(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const double old_lower_bound, double &true_lower_bound, BCP_solution *&sol, BCP_vec< BCP_cut * > &new_cuts, BCP_vec< BCP_row * > &new_rows, BCP_vec< BCP_var * > &new_vars, BCP_vec< BCP_col * > &new_cols)
Process the result of an iteration.
int parent() const
the process id of the parent
Mainly for binary choices: take the down branch unconditionally.
virtual void process_message(BCP_buffer &buf)
Process a message that has been sent by another process&#39; user part to this process&#39; user part...
Pack all dual variables.
Definition: BCP_enum.hpp:152
bool is_fixed() const
Return whether the variable is fixed or not.
Definition: BCP_var.hpp:106
virtual OsiSolverInterface * initialize_solver_interface()
Create LP solver environment.
virtual double objective_value() const =0
The method returning the objective value of the solution.
Keep the child that has the highest presolved objective value.
virtual void receive(const int source, const BCP_message_tag tag, BCP_buffer &buf, const double timeout)=0
Blocking receive with timeout.
pos
position where the operator should be printed when printing the expression
char param(BCP_lp_par::chr_params key) const
Definition: BCP_lp.hpp:275
Pack only those variables that are currently at nonzero levels.
Definition: BCP_enum.hpp:135
BCP_feasibility_test
This enumerative constant describes which built-in feasibility-testing routine should be invoked...
Definition: BCP_enum.hpp:217
Print out a message when the default version of an overridable method is executed.
void select_fractions(const double *first, const double *last, const double etol, BCP_vec< int > &fractions) const
Select all fractional entries.
If true the BCP will attempt to do reduced cost fixing only for variables currently at zero...
The problem is feasible if all non-continuous variables are integral.
Definition: BCP_enum.hpp:225
void reduced_cost_fixing(const double *dj, const double *x, const double gap, BCP_vec< BCP_var * > &vars, int &newly_changed)
Reduced cost fixing.
BCP_var_set vars
double granularity() const
Definition: BCP_lp.hpp:289
Specifies the rule used for built-in branching object comparison (if the buit-in routine is used at a...
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
Pack only those variables that are currently at fractional (i.e., non-integral) levels.
Definition: BCP_enum.hpp:138
void BCP_lp_add_cols_to_lp(const BCP_vec< BCP_col * > &cols, OsiSolverInterface *lp)
Indicates what part of the primal solution is sent to the Cut Generator process if the BCP_lp_user::p...
&quot;new&quot; is better, discard &quot;old&quot;.
BCP_lp_relax * matrix
A pointer to the constraint matrix corresponding to the core variables and cuts.
BCP_process_t
This enumerative constant describes the various process types.
All primal variables.
This class exist only so that we can extract information from OsiIntegerBranchingObject.
char entry(const chr_params key) const
Pack all dual variables.
virtual double compute_lower_bound(const double old_lower_bound, const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
Compute a true lower bound for the subproblem.
Maximum allowed running time.
BCP_diving_status dive
void set_param(const BCP_lp_par::chr_params key, const bool val)
Definition: BCP_lp_user.cpp:63
Purge the slack cuts at every iteration while processing search tree nodes.
Definition: BCP_enum.hpp:21
int current_level() const
Return the level of the search tree node being processed.
Definition: BCP_lp_user.cpp:32
Turn on the user hook &quot;display_lp_solution&quot;.
virtual void generate_vars_in_lp(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const bool before_fathom, BCP_vec< BCP_var * > &new_vars, BCP_vec< BCP_col * > &new_cols)
Generate variables within the LP process.
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.
double start_time() const
Return when the LP process started.
Definition: BCP_lp_user.cpp:35
bool had_numerical_problems() const
Return true if at least one child had numerical difficulties while presolving.
const double * x() const
virtual void initialize_int_and_sos_list(std::vector< OsiObject * > &intAndSosObjects)
Create the list of objects that can be used for branching (simple integer vars and SOS sets)...
This class is just a collection of pointers to cuts with a number of methods to manipulate these cuts...
Definition: BCP_cut.hpp:279
void pack_var(const BCP_var &var)
Definition: BCP_lp.cpp:115
void reserve(const size_t n)
Reallocate the object to make space for n entries.
virtual void pack_primal_solution(BCP_buffer &buf, const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
Pack the information necessary for cut generation into the buffer.
Pack only dual variables currently at nonzero level.
int current_iteration() const
Return the iteration count within the search tree node being processed.
Definition: BCP_lp_user.cpp:34
const BCP_vec< double > & ColUpperBound() const
A const reference to the vector of upper bounds on the variables.
Definition: BCP_matrix.hpp:296
This class is a very simple impelementation of a constant length string.
Definition: BCP_string.hpp:13
int current_phase() const
Return the phase the algorithm is in.
Definition: BCP_lp_user.cpp:31
The problem is feasible if all primal variables take values 0 or 1.
Definition: BCP_enum.hpp:220
bool fathomable(const double objval_limit) const
Return true if every children can be fathomed.
static const CouNumber pi
Definition: exprCos.cpp:23
void push_back(const_reference x)
Append x to the end of the vector.
Only primal variables currently at nonzero level.
void broadcast_message(const BCP_process_t proc_type, const BCP_buffer &buf)
Broadcast the message to all processes of the given type.
BCP_solution_generic * test_integral(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const double etol) const
Test whether all variables are integer.
&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...
virtual void purge_slack_pool(const BCP_vec< BCP_cut * > &slack_pool, BCP_vec< int > &to_be_purged)
Selectively purge the list of slack cuts.
void send_message(const int target, const BCP_buffer &buf, BCP_message_tag tag=BCP_Msg_User)
Send a message to a particular process.
size_t varnum() const
Return the number of variables in the core.
Attempt column generation.
Definition: BCP_enum.hpp:73
The problem is feasible if all primal variables are integral.
Definition: BCP_enum.hpp:223
virtual void restore_feasibility(const BCP_lp_result &lpres, const std::vector< double * > dual_rays, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, BCP_vec< BCP_var * > &vars_to_add, BCP_vec< BCP_col * > &cols_to_add)
Restoring feasibility.
#define BCP_DBL_MAX
Definition: BCP_math.hpp:6
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.
void fint fint fint real fint real real real real real real real real real * e
void get_lower_bounds(BCP_vec< double > &obj)
Fill up obj with the lower bound on each child.
bool is_non_removable() const
Return whether the cut marked as NotRemovable.
Definition: BCP_cut.hpp:100
double ub() const
Return the upper bound.
Definition: BCP_var.hpp:91
BCP_user_data * get_user_data()
Return a pointer to the BCP_user_data structure the user (may have) stored in this node...
Definition: BCP_lp_user.cpp:36
double primalTolerance() const
Return the primal tolerance of the solver.
virtual BCP_object_compare_result compare_vars(const BCP_var *v0, const BCP_var *v1)
Compare two generated variables.
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...
&quot;old&quot; is better, discard &quot;new&quot;.
Purge the slack cuts when the LP starts processing a new search tree node.
Definition: BCP_enum.hpp:18
virtual BCP_object_compare_result compare_cuts(const BCP_cut *c0, const BCP_cut *c1)
Compare two generated cuts.
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
void set_msgtag(const BCP_message_tag tag)
Set the message tag on the buffer.
Definition: BCP_buffer.hpp:116
int child_num
The number of children for this branching object.
Specifies how many branching variables with values close to half between two integers should be chose...
Pack only those variables that are currently at nonzero levels.
Definition: BCP_enum.hpp:150
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.
size_t cutnum() const
Return the number of cuts in the core.
The slack cut discarding strategy used in the default version of the function purge_slack_pool().
BCP_solution_generic * test_binary(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const double etol) const
Test whether all variables are 0/1.
void select_positives(const double *first, const double *last, const double etol, BCP_vec< int > &positives) const
Select all positive entries.
double objval() const
int get_parent() const
Definition: BCP_process.hpp:25
This class describes a generic branching object.
virtual BCP_solution * generate_heuristic_solution(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
Try to generate a heuristic solution (or return one generated during cut/variable generation...
virtual void unpack_module_data(BCP_buffer &buf)
Unpack the initial information sent to the LP process by the Tree Manager.
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_...
chr_params
Character parameters.
double ub() const
Definition: BCP_lp.hpp:300
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
const BCP_vec< double > & Objective() const
A const reference to the vector of objective coefficients.
Definition: BCP_matrix.hpp:292
const BCP_lp_result & lpres(const int child_ind) const
Return a const reference to the presolved results of the child_ind-th child.
BCP_var_t var_type() const
Return the integrality type of the variable.
Definition: BCP_var.hpp:85
bool over_ub(double lb) const
Definition: BCP_lp.hpp:310
virtual void select_vars_to_delete(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const bool before_fathom, BCP_vec< int > &deletable)
void add_entry(BCP_var *var, double value)
Append a variable and the corresponding value to the end of the appropriate vectors.
static bool ifprint
const BCP_vec< double > & ColLowerBound() const
A const reference to the vector of lower bounds on the variables.
Definition: BCP_matrix.hpp:294
Continuous variable.
Definition: BCP_enum.hpp:167
virtual void logical_fixing(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const BCP_vec< BCP_obj_status > &var_status, const BCP_vec< BCP_obj_status > &cut_status, const int var_bound_changes_since_logical_fixing, BCP_vec< int > &changed_pos, BCP_vec< double > &new_bd)
This method provides an opportunity for the user to tighten the bounds of variables.
bool is_non_removable() const
Return whether the variable is marked NotRemovable.
Definition: BCP_var.hpp:115
void pack_cut(const BCP_cut &cut)
Definition: BCP_lp.cpp:174
double upper_bound() const
Return what is the best known upper bound (might be BCP_DBL_MAX)
Definition: BCP_lp_user.cpp:29
The object is from the Tree Manager.
Definition: BCP_enum.hpp:261
Abstract base class that defines members common to all types of variables.
Definition: BCP_var.hpp:28
int effective_count() const
Return the effectiveness count of the cut (only in LP process).
Definition: BCP_cut.hpp:80
bool user_has_lp_result_processing
Definition: BCP_lp.hpp:244
virtual BCP_solution * test_feasibility(const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
Evaluate and return MIP feasibility of the current solution.
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
Only primal variables currently at fractional level.
Indicates what part of the dual solution is sent to the Variable Generator process if the BCP_lp_user...
virtual void display_lp_solution(const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const bool final_lp_solution)
Display the result of most recent LP optimization.
The node should be fathomed without even trying to branch.
A presolved branching object candidate.
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 int try_to_branch(OsiBranchingInformation &branchInfo, OsiSolverInterface *solver, OsiChooseVariable *choose, OsiBranchingObject *&branchObject, bool allowVarFix)
Select the &quot;close-to-half&quot; variables for strong branching.
virtual void select_cuts_to_delete(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const bool before_fathom, BCP_vec< int > &deletable)
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
void receive_message(const int sender, BCP_buffer &buf, BCP_message_tag tag=BCP_Msg_User)
Wait for a message and receive it.
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
void select_zeros(const double *first, const double *last, const double etol, BCP_vec< int > &zeros) const
Select all zero entries.
BCP_column_generation colgen
This class is just a collection of pointers to variables with a number of methods to manipulate these...
Definition: BCP_var.hpp:316
Whether we should refrain from compressing the problem description right before a fathomed node&#39;s des...
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()...
Do fathom the node.
Definition: BCP_enum.hpp:67
After branching all children must be returned to the Tree Manager and the LP process should wait for ...
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
const double * pi() const
Turn on the user hook &quot;display_lp_solution&quot; for the last LP relaxation solved at a search tree node...
double _objective
The objective value of the solution.
Keep the child that has the lowest presolved objective value.
double dualTolerance() const
Return the dual tolerance of the solver.
The two objects are not comparable or neither is better than the other.
Definition: BCP_enum.hpp:285
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
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
Mainly for binary choices: take the up branch unconditionally.
BCP_branching_object_relation
This enumerative constant is the return value of the compare_presolved_branching_objects() method in ...
double start_time
Definition: BCP_lp.hpp:211
int termcode() const
BCP_vec< BCP_child_action > & action()
Return a reference to the actions to be taken.
Specifies the rule used for selecting one of the children of the search tree node for diving...
This class exist only so that we can extract information from OsiIntegerBranchingObject.
BCP_message_environment * msg_env
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:139
void fint * m
BCP_lp_prob * p
Definition: BCP_lp_user.hpp:82
BCP_user_data * user_data
Data the user wants to pass along with the search tree node.
This class holds the results after solving an LP relaxation.
Branching must be done.
Pack all primal variables.
Definition: BCP_enum.hpp:140
iterator entry(const int i)
Return an iterator to the i-th entry.
Definition: BCP_vector.hpp:109
bool over_ub(double lb) const
Return true / false depending on whether the lb argument is over the current upper bound or not...
Definition: BCP_lp_user.cpp:30
virtual void pack_dual_solution(BCP_buffer &buf, const BCP_lp_result &lp_result, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts)
Pack the information necessary for variable generation into the buffer.
virtual void load_problem(OsiSolverInterface &osi, BCP_problem_core *core, BCP_var_set &vars, BCP_cut_set &cuts)
Load the problem specified by core, vars, and cuts into the solver interface.
virtual void pack_feasible_solution(BCP_buffer &buf, const BCP_solution *sol)
Pack a MIP feasible solution into a buffer.
bool is_to_be_removed() const
Return whether the cut must be removed from the formulation.
Definition: BCP_cut.hpp:106
BCP_lp_branching_object * candidate()
Return a pointer to the candidate.
This class holds a MIP feasible primal solution.
void send_feasible_solution(const BCP_solution *sol)
Definition: BCP_lp_user.cpp:77
const BCP_vec< double > & RowUpperBound() const
A const reference to the vector of upper bounds on the cuts.
Definition: BCP_matrix.hpp:300
BCP_buffer msg_buf
Definition: BCP_lp.hpp:239
void fake_objective_values(const double itlim_objval)
Examine the termination codes for the children and for those that do not have a valid lower bound fak...
virtual void modify_lp_parameters(OsiSolverInterface *lp, const int changeType, bool in_strong_branching)
Modify parameters of the LP solver before optimization.
dbl_params
Double parameters.
General integer variable.
Definition: BCP_enum.hpp:165
BCP_object_compare_result
This enumerative constant describes the possible outcomes when comparing two objects (variables or cu...
Definition: BCP_enum.hpp:276
An object of type BCP_lp_relax holds the description of an lp relaxation.
Definition: BCP_matrix.hpp:267
void select_nonzeros(const double *first, const double *last, const double etol, BCP_vec< int > &nonzeros) const
Select all nonzero entries.
BCP_solution_generic * test_full(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const double etol) const
Test whether the variables specified as integers are really integer.
The message contains a new MIP feasible solution.
virtual void initialize_new_search_tree_node(const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const BCP_vec< BCP_obj_status > &var_status, const BCP_vec< BCP_obj_status > &cut_status, BCP_vec< int > &var_changed_pos, BCP_vec< double > &var_new_bd, BCP_vec< int > &cut_changed_pos, BCP_vec< double > &cut_new_bd)
Initializing a new search tree node.
void fint fint fint real fint real * x
bool is_to_be_removed() const
Return whether the variable must be removed from the formulation.
Definition: BCP_var.hpp:127
This is the abstract base class for a solution to a Mixed Integer Programming problem.
int process_id() const
What is the process id of the current process.
bool using_deprecated_set_user_data_for_children
Definition: BCP_lp_user.hpp:81