BCP_lp_msg_node_send.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #include <functional>
4 
5 #include "BCP_message.hpp"
6 #include "BCP_problem_core.hpp"
7 #include "BCP_branch.hpp"
8 #include "BCP_warmstart.hpp"
9 #include "BCP_lp.hpp"
10 #include "BCP_lp_user.hpp"
11 #include "BCP_lp_branch.hpp"
12 #include "BCP_lp_node.hpp"
13 #include "BCP_lp_functions.hpp"
14 #include "BCP_lp_functions.hpp"
15 #include "BCP_vector.hpp"
16 
17 #include "BCP_USER.hpp"
18 
19 //#############################################################################
20 static inline void BCP_lp_pack_core(BCP_lp_prob& p);
21 static inline void BCP_lp_pack_noncore_vars(BCP_lp_prob& p,
22  BCP_vec<int>& deleted_pos);
23 static inline void BCP_lp_pack_noncore_cuts(BCP_lp_prob& p,
24  BCP_vec<int>& deleted_pos);
25 static inline void BCP_lp_pack_warmstart(BCP_lp_prob& p,
26  BCP_vec<int>& del_vars,
27  BCP_vec<int>& del_cuts);
28 static inline void BCP_lp_pack_user_data(BCP_lp_prob& p);
29 
30 //-----------------------------------------------------------------------------
31 
32 static inline int BCP_lp_pack_branching_info(BCP_lp_prob& p,
33  BCP_presolved_lp_brobj* brobj);
34 
35 //#############################################################################
36 
37 static inline void
39 {
40  if (p.core->varnum() + p.core->cutnum() > 0){
41  const bool dumpcuts = p.param(BCP_lp_par::Lp_DumpNodeDescCuts);
42  const bool dumpvars = p.param(BCP_lp_par::Lp_DumpNodeDescVars);
43  if (dumpvars) {
44  const int bvarnum = p.core->varnum();
45  const BCP_vec<BCP_var*>& vars = p.node->vars;
46  printf(" Core Vars (bvarnum %i)\n", bvarnum);
47  for (int i = 0; i < bvarnum; ++i) {
48  printf(" var %4i: bcpind %i, status %i, lb %f, ub %f\n",
49  i, vars[i]->bcpind(), vars[i]->status(),
50  vars[i]->lb(), vars[i]->ub());
51  }
52  }
53  if (dumpcuts) {
54  const int bcutnum = p.core->cutnum();
55  const BCP_vec<BCP_cut*>& cuts = p.node->cuts;
56  printf(" Core Cuts (bcutnum %i)\n", bcutnum);
57  for (int i = 0; i < bcutnum; ++i) {
58  printf(" cut %4i: bcpind %i, status %i, lb %f, ub %f\n",
59  i, cuts[i]->bcpind(), cuts[i]->status(),
60  cuts[i]->lb(), cuts[i]->ub());
61  }
62  }
64  p.core->cutnum(), p.node->cuts);
65  switch (p.node->tm_storage.core_change){
67  {
69  *p.core_as_change, exp_bc);
70  wrtcore_bc.pack(p.msg_buf);
71  }
72  break;
73 
75  exp_bc.pack(p.msg_buf);
76  break;
77 
79  {
81  p.parent->core_as_change, exp_bc);
83  *p.core_as_change, exp_bc);
84  if (exp_bc.pack_size() <= wrtparent_bc.pack_size()){
85  if (exp_bc.pack_size() <= wrtcore_bc.pack_size()){
86  exp_bc.pack(p.msg_buf);
87  }else{
88  wrtcore_bc.pack(p.msg_buf);
89  }
90  }else{
91  if (wrtparent_bc.pack_size() < wrtcore_bc.pack_size()){
92  wrtparent_bc.pack(p.msg_buf);
93  }else{
94  wrtcore_bc.pack(p.msg_buf);
95  }
96  }
97  }
98  break;
99 
100  default: // including BCP_Storage_NoData
101  throw BCP_fatal_error("BCP_lp_pack_core() : Bad storage.\n");
102  }
103  // look ahead (the current node may become the parent) and replace the
104  // parent's core to be exp_bc
105  p.parent->core_as_change.swap(exp_bc);
106  }
107 }
108 
109 //#############################################################################
110 
111 static inline void
113 {
114  const bool dumpvars = p.param(BCP_lp_par::Lp_DumpNodeDescVars);
115  if (dumpvars) {
116  const int bvarnum = p.core->varnum();
117  const int varnum = p.node->vars.size();
118  const BCP_vec<BCP_var*>& vars = p.node->vars;
119  printf(" Extra Vars (extra varnum %i)\n", varnum - bvarnum);
120  for (int i = bvarnum; i < varnum; ++i) {
121  printf(" var %4i: bcpind %i, status %i, lb %f, ub %f\n",
122  i, vars[i]->bcpind(), vars[i]->status(),
123  vars[i]->lb(), vars[i]->ub());
124  }
125  }
126 
127  // No matter whether we'll use an explicit description or WrtParent, all
128  // vars with negative bcpind will have to be sent to the TM. These vars
129  // will be collected in this vector.
130  BCP_vec<BCP_var*> vars_to_tm;
131 
132  // First create an explicit description
133  BCP_obj_set_change expl;
134 
135  BCP_var** vars = &p.node->vars[p.core->varnum()];
136  const int new_added_num = p.node->vars.size() - p.core->varnum();
137  if (new_added_num > 0) {
138  expl._new_objs.reserve(new_added_num);
139  expl._change.reserve(new_added_num);
140  for (int i = 0; i < new_added_num; ++i) {
141  BCP_var* v = vars[i];
142  const int bcpind = v->bcpind();
143  // while we make the explicit description make sure that all extra
144  // vars have positive bcpind. After all, they are being sent to
145  // the TM right now.
146  if (bcpind < 0) {
147  vars_to_tm.push_back(v);
148  expl._new_objs.unchecked_push_back(-bcpind);
149  } else {
150  expl._new_objs.unchecked_push_back(bcpind);
151  }
153  v->status()));
154  }
155  }
156 
157  // Whether we'll pack the Explicit or the WrtParent description, the new
158  // vars need to be packed. Pack them first, so by the time the positive
159  // bcpind in expl (or wrtp) arrives to the TM, the var already exists in
160  // the TM.
161  int num = vars_to_tm.size();
162  p.msg_buf.pack(num);
163  for (int i = 0; i < num; ++i) {
164  assert(vars_to_tm[i]->bcpind() < 0);
165  p.pack_var(*vars_to_tm[i]);
166  vars_to_tm[i]->set_bcpind_flip();
167  }
168 
170  if (dumpvars) {
171  expl.print();
172  }
173  expl.pack(p.msg_buf);
174  return;
175  }
176 
177  // Now create a WrtParent description and see which one is shorter. Also,
178  // we'll need the list of deleted variable positions when we set of the
179  // warmstart information to be sent.
180  BCP_obj_set_change wrtp;
182 
183  const BCP_vec<int>& old_added_bcpind = p.parent->var_set._new_objs;
184  const BCP_vec<BCP_obj_change>& old_added_desc = p.parent->var_set._change;
185  const int old_added_num = old_added_bcpind.size();
186  wrtp._del_change_pos.reserve(old_added_num);
187 
188  BCP_vec<int> chpos;
189  chpos.reserve(new_added_num);
190 
191  int i, j;
192 
193  // first check how many entry has been deleted from oldvars
194  for (i = 0, j = 0; i < new_added_num && j < old_added_num; ++j) {
195  const BCP_var* const v = vars[i];
196  const BCP_obj_change& old = old_added_desc[j];
197  if (v->bcpind() == old_added_bcpind[j]) {
198  // added_bcpind ALWAYS has real indices, so this really separates
199  if (v->lb()!=old.lb || v->ub()!=old.ub || v->status()!=old.stat)
200  chpos.unchecked_push_back(i);
201  ++i;
202  } else {
204  }
205  }
206  // append the remains of old_added to _del_change_pos
207  for ( ; j < old_added_num; ++j) {
209  }
210  // _deleted_num is the current length of _del_change_pos
211  wrtp._deleted_num = wrtp._del_change_pos.size();
212 
213  // the rest are the set of really new vars, and also the position of those
214  // vars must be appended to chpos.
215  wrtp._new_objs.reserve(new_added_num - i);
216  for ( ; i < new_added_num; ++i){
217  const int bcpind = vars[i]->bcpind();
218  wrtp._new_objs.unchecked_push_back(bcpind > 0 ? bcpind : -bcpind);
219  chpos.unchecked_push_back(i);
220  }
221  // append chpos to _del_change_pos to get the final list
222  wrtp._del_change_pos.append(chpos);
223 
224  // finally, create _change: just pick up things based on chpos
225  const int chnum = chpos.size();
226  wrtp._change.reserve(chnum);
227  for (i = 0; i < chnum; ++i) {
228  const BCP_var* const var = vars[chpos[i]];
229  wrtp._change.unchecked_push_back(BCP_obj_change(var->lb(), var->ub(),
230  var->status()));
231  }
232 
233  deleted_pos.clear();
234  deleted_pos.append(wrtp._del_change_pos.begin(),
235  wrtp._del_change_pos.entry(wrtp.deleted_num()));
236 
237  // if the TM storage is WrtParent then pack the shorter
238  // FIXME: why only if TM storage is WrtParent ???
240  (expl.pack_size() > wrtp.pack_size())) {
241  if (dumpvars) {
242  wrtp.print();
243  }
244  wrtp.pack(p.msg_buf);
245  } else {
246  if (dumpvars) {
247  expl.print();
248  }
249  expl.pack(p.msg_buf);
250  }
251 }
252 
253 //#############################################################################
254 
255 static inline void
257 {
258  const bool dumpcuts = p.param(BCP_lp_par::Lp_DumpNodeDescCuts);
259  if (dumpcuts) {
260  const int bcutnum = p.core->cutnum();
261  const int cutnum = p.node->cuts.size();
262  const BCP_vec<BCP_cut*>& cuts = p.node->cuts;
263  printf(" Extra Cuts (extra cutnum %i)\n", cutnum - bcutnum);
264  for (int i = bcutnum; i < cutnum; ++i) {
265  printf(" cut %4i: bcpind %i, status %i, lb %f, ub %f\n",
266  i, cuts[i]->bcpind(), cuts[i]->status(),
267  cuts[i]->lb(), cuts[i]->ub());
268  }
269  }
270 
271  // No matter whether we'll use an explicit description or WrtParent, all
272  // cuts with negative bcpind will have to be sent to the TM. These cuts
273  // will be collected in this vector.
274  BCP_vec<BCP_cut*> cuts_to_tm;
275 
276  // First create an explicit description
277  BCP_obj_set_change expl;
278 
279  BCP_cut** cuts = &p.node->cuts[p.core->cutnum()];
280  const int new_added_num = p.node->cuts.size() - p.core->cutnum();
281  if (new_added_num > 0) {
282  expl._new_objs.reserve(new_added_num);
283  expl._change.reserve(new_added_num);
284  for (int i = 0; i < new_added_num; ++i) {
285  BCP_cut* c = cuts[i];
286  const int bcpind = c->bcpind();
287  // while we make the explicit description make sure that all extra
288  // cuts have positive bcpind. After all, they are being sent to
289  // the TM right now.
290  if (bcpind < 0) {
291  cuts_to_tm.push_back(c);
292  expl._new_objs.unchecked_push_back(-bcpind);
293  } else {
294  expl._new_objs.unchecked_push_back(bcpind);
295  }
297  c->status()));
298  }
299  }
300 
301  // Whether we'll pack the Explicit or the WrtParent description, the new
302  // cuts need to be packed. Pack them first, so by the time the positive
303  // bcpind in expl (or wrtp) arrives to the TM, the cut already exists in
304  // the TM.
305  int num = cuts_to_tm.size();
306  p.msg_buf.pack(num);
307  for (int i = 0; i < num; ++i) {
308  assert(cuts_to_tm[i]->bcpind() < 0);
309  p.pack_cut(*cuts_to_tm[i]);
310  cuts_to_tm[i]->set_bcpind_flip();
311  }
312 
314  if (dumpcuts) {
315  expl.print();
316  }
317  expl.pack(p.msg_buf);
318  return;
319  }
320 
321  // Now create a WrtParent description and see which one is shorter. Also,
322  // we'll need the list of deleted cutiable positions when we set of the
323  // warmstart information to be sent.
324  BCP_obj_set_change wrtp;
326 
327  const BCP_vec<int>& old_added_bcpind = p.parent->cut_set._new_objs;
328  const BCP_vec<BCP_obj_change>& old_added_desc = p.parent->cut_set._change;
329  const int old_added_num = old_added_bcpind.size();
330  wrtp._del_change_pos.reserve(old_added_num);
331 
332  BCP_vec<int> chpos;
333  chpos.reserve(new_added_num);
334 
335  int i, j;
336 
337  // first check how many entry has been deleted from oldcuts
338  for (i = 0, j = 0; i < new_added_num && j < old_added_num; ++j) {
339  const BCP_cut* const c = cuts[i];
340  const BCP_obj_change& old = old_added_desc[j];
341  if (c->bcpind() == old_added_bcpind[j]) {
342  // added_bcpind ALWAYS has real indices, so this really separates
343  if (c->lb()!=old.lb || c->ub()!=old.ub || c->status()!=old.stat)
344  chpos.unchecked_push_back(i);
345  ++i;
346  } else {
348  }
349  }
350  // append the remains of old_added to _del_change_pos
351  for ( ; j < old_added_num; ++j) {
353  }
354  // _deleted_num is the current length of _del_change_pos
355  wrtp._deleted_num = wrtp._del_change_pos.size();
356 
357  // the rest are the set of really new cuts, and also the position of those
358  // cuts must be appended to chpos.
359  wrtp._new_objs.reserve(new_added_num - i);
360  for ( ; i < new_added_num; ++i){
361  const int bcpind = cuts[i]->bcpind();
362  wrtp._new_objs.unchecked_push_back(bcpind > 0 ? bcpind : -bcpind);
363  chpos.unchecked_push_back(i);
364  }
365  // append chpos to _del_change_pos to get the final list
366  wrtp._del_change_pos.append(chpos);
367 
368  // finally, create _change: just pick up things based on chpos
369  const int chnum = chpos.size();
370  wrtp._change.reserve(chnum);
371  for (i = 0; i < chnum; ++i) {
372  const BCP_cut* const cut = cuts[chpos[i]];
373  wrtp._change.unchecked_push_back(BCP_obj_change(cut->lb(), cut->ub(),
374  cut->status()));
375  }
376 
377  deleted_pos.clear();
378  deleted_pos.append(wrtp._del_change_pos.begin(),
379  wrtp._del_change_pos.entry(wrtp.deleted_num()));
380 
381  // if the TM storage is WrtParent then pack the shorter
382  // FIXME: why only if TM storage is WrtParent ???
384  (expl.pack_size() > wrtp.pack_size())) {
385  if (dumpcuts) {
386  wrtp.print();
387  }
388  wrtp.pack(p.msg_buf);
389  } else {
390  if (dumpcuts) {
391  expl.print();
392  }
393  expl.pack(p.msg_buf);
394  }
395 }
396 
397 //#############################################################################
398 
399 static inline void
401  BCP_vec<int>& del_vars, BCP_vec<int>& del_cuts)
402 {
403  bool has_data = p.node->warmstart != 0;
404  p.msg_buf.pack(has_data);
405 
406  if (has_data) {
409  p.packer->pack_warmstart(p.node->warmstart, p.msg_buf, def);
410  } else {
411  double petol = 0.0;
412  double detol = 0.0;
413  p.lp_solver->getDblParam(OsiPrimalTolerance, petol);
414  p.lp_solver->getDblParam(OsiDualTolerance, detol);
415  // this return an explicit storage if that's shorter!
416  BCP_warmstart* ws_change =
418  del_vars, del_cuts, petol, detol);
419  p.packer->pack_warmstart(ws_change, p.msg_buf, def);
420  delete ws_change;
421  ws_change = 0;
422  }
423  }
424 }
425 
426 //#############################################################################
427 
428 static inline void BCP_lp_pack_user_data(BCP_lp_prob& p)
429 {
430  bool has_data = p.node->user_data != 0;
431  p.msg_buf.pack(has_data);
432  if (has_data) {
434  }
435 }
436 
437 //#############################################################################
438 
439 static inline int
441 {
442  const int child_num = lp_brobj->candidate()->child_num;
443 
444  // collect the lower bounds on the children
445  BCP_vec<double> lpobj;
446  lpobj.reserve(child_num);
447  for (int i = 0; i < child_num; ++i) {
448  lpobj.unchecked_push_back(lp_brobj->lpres(i).objval());
449  }
450 
451  // The qualities are the same (for now) as the lpobjs
452  BCP_vec<double> qualities(lpobj);
453 
454  const BCP_vec<BCP_child_action>& action = lp_brobj->action();
455  const BCP_vec<BCP_user_data*>& user_data = lp_brobj->user_data();
456 
457  // now pack all those stuff
458  BCP_buffer& buf = p.msg_buf;
459  buf.pack(p.node->dive).pack(action).pack(qualities).pack(lpobj);
460 
461  for (int i = 0; i < child_num; ++i) {
462  bool has_user_data = user_data[i] != 0;
463  buf.pack(has_user_data);
464  if (has_user_data) {
465  p.packer->pack_user_data(user_data[i], buf);
466  }
467  }
468 
469  BCP_internal_brobj int_brobj(*lp_brobj->candidate());
470  int_brobj.pack(buf);
471 
472  int keep = -1;
473  if (p.node->dive != BCP_DoNotDive){
474  for (int i = child_num - 1; i >= 0; --i)
475  if (action[i] == BCP_KeepChild) {
476  if (keep == -1)
477  keep = i;
478  else
479  throw BCP_fatal_error("LP : Can't keep more than one child!\n");
480  }
481  }
482  return keep;
483 }
484 
485 //#############################################################################
486 
487 // brobj is 0, msgtag is 'real' when invoked from fathom().
488 // brobj is 'real', msgtag is BCP_Msg_NoMessage when invoked from branch()
489 
491  BCP_presolved_lp_brobj* brobj,
492  BCP_message_tag msgtag)
493 {
494  BCP_buffer& buf = p.msg_buf;
495  BCP_lp_node& node = *p.node;
496 
497  // let's start with saying who this node is and what is the lb we got
498  buf.clear();
499  buf.pack(node.index).pack(node.quality).pack(node.true_lower_bound);
500 
501  const bool dumpcuts = p.param(BCP_lp_par::Lp_DumpNodeDescCuts);
502  const bool dumpvars = p.param(BCP_lp_par::Lp_DumpNodeDescVars);
503  if (dumpcuts || dumpvars) {
504  printf("LP: FINISHED NODE %i DUMP START ===========================\n",
505  node.index);
506  }
507  // Send the node description only if this node is branched on (i.e., brobj
508  // is non-null) or if we got to send the description of fathomed nodes, too.
509  const bool send_desc = brobj || p.param(BCP_lp_par::SendFathomedNodeDesc);
510  buf.pack(send_desc);
511  if (send_desc) {
512  // Pack the core (WrtCore, WrtParent or Explicit)
513  BCP_lp_pack_core(p); // BCP_problem_core_change
514  // pack the algo var set change (or pack them explicitly)
515  BCP_vec<int> del_vars;
516  BCP_lp_pack_noncore_vars(p, del_vars);
517 
518  BCP_vec<int> del_cuts;
519  BCP_lp_pack_noncore_cuts(p, del_cuts);
520 
521  // At this point there aren't supposed to be any ws info. It was deleted
522  // when the lp formulation was created. Test this.
523  if (p.node->warmstart) {
524  throw BCP_fatal_error("\
525 LP: there is ws info in BCP_lp_send_node_description()!\n");
526  }
527  // If necessary, get and pack the warmstart info
528  CoinWarmStart* ws = NULL;
529  switch (p.param(BCP_lp_par::WarmstartInfo)) {
530  case BCP_WarmstartNone:
531  break;
532  case BCP_WarmstartRoot:
533  if (node.index == 0) { // we are in the root
534  ws = p.lp_solver->getWarmStart();
535  if (ws) {
537  if (bws) {
539  BCP_buffer wsbuf;
540  p.packer->pack_warmstart(bws, wsbuf, def);
541  p.msg_env->send(p.get_parent() /*tree_manager*/,
542  BCP_Msg_WarmstartRoot, wsbuf);
543  p.warmstartRoot = ws;
544  delete bws;
545  }
546  }
547  }
548  break;
549  case BCP_WarmstartParent:
550  ws = p.lp_solver->getWarmStart();
552  BCP_lp_pack_warmstart(p, del_vars, del_cuts);
553  }
555  }
556 
557  int keep = -1;
558 
559  if (dumpcuts || dumpvars) {
560  printf("LP: FINISHED NODE %i DUMP END ===========================\n",
561  node.index);
562  }
563  if (brobj) {
564  // we came here from branch()
565  // pack the branching info, 'keep' will tell whether we wish to dive
566  keep = BCP_lp_pack_branching_info(p, brobj);
567  // In a single process environment (message driven) the reaction in the
568  // TM to the send below will reset p.node->dive. In a multi-process
569  // environment p.node->dive will remain Unknown. This will help later
570  // (20 lines below) to decide whether we have to get the diving info or
571  // not.
573  p.msg_env->send(p.get_parent() /*tree_manager*/,
575  }else{
576  // we came from fathom()
577  p.msg_env->send(p.get_parent() /*tree_manager*/, msgtag, buf);
578  }
579 
580  if (keep == -1){
581  // we don't wan't to dive (or we came from fathom()),
582  // don't wait for the names of the ones not having global internal index
583  return -1;
584  }
585 
586  // We did want to dive
587 
588  // In the single process environment the diving info already came back
589  // (when the TM processes the branching info) and p.node->dive is set.
590  // Otherwise we got to receive the diving info here.
591  if (p.node->dive == BCP_UnknownDivingStatus) {
592  // We got to receive the diving information by hand
593  p.msg_buf.clear();
594  p.msg_env->receive(p.get_parent() /*tree_manager*/,
595  BCP_Msg_DivingInfo, buf, -1);
597  }
598 
599  // BCP_lp_unpack_diving_info() sets p.node->index to the new index if
600  // diving is to be done, or to -1 if diving is not allowed.
601  if (p.node->index == -1) {
602  keep = -1;
603  // At this point brobj cannot be empty.
604  // We must reset the child to be kept, too.
605  brobj->keep_no_child();
606  }
607  return keep;
608 }
609 
610 //#############################################################################
int BCP_lp_send_node_description(BCP_lp_prob &p, BCP_presolved_lp_brobj *brobj, BCP_message_tag msgtag)
This class describes changes in the core of the problem.
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.
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_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
BCP_storage_t cut_change
Definition: BCP_lp_node.hpp:31
BCP_lp_node * node
Description he current search tree node.
Definition: BCP_lp.hpp:168
Nonexistent diving status.
void BCP_lp_unpack_diving_info(BCP_lp_prob &p, BCP_buffer &buf)
The data stored is with respect to the original description of the base problem (as was given by the ...
Definition: BCP_enum.hpp:94
BCP_lp_parent * parent
Description of the parent of the current node.
Definition: BCP_lp.hpp:170
virtual void receive(const int source, const BCP_message_tag tag, BCP_buffer &buf, const double timeout)=0
Blocking receive with timeout.
void clear()
Delete every entry.
char param(BCP_lp_par::chr_params key) const
Definition: BCP_lp.hpp:275
static void BCP_lp_pack_noncore_vars(BCP_lp_prob &p, BCP_vec< int > &deleted_pos)
Print out a message when the default version of an overridable method is executed.
BCP_var_set vars
double quality
Abstract base class that defines members common to all types of cuts.
Definition: BCP_cut.hpp:29
BCP_node_storage_in_tm tm_storage
void pack(BCP_buffer &buf) const
Pack the core change into the buffer.
static int BCP_lp_pack_branching_info(BCP_lp_prob &p, BCP_presolved_lp_brobj *brobj)
static void BCP_lp_pack_core(BCP_lp_prob &p)
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
void pack(BCP_buffer &buf) const
BCP_diving_status dive
BCP_storage_t warmstart
Definition: BCP_lp_node.hpp:33
iterator begin()
Return an iterator to the beginning of the object.
Definition: BCP_vector.hpp:99
double ub() const
Return the upper bound on the cut.
Definition: BCP_cut.hpp:84
BCP_warmstart * BCP_lp_convert_CoinWarmStart(BCP_lp_prob &p, CoinWarmStart *&ws)
NO OLD DOC.
Definition: BCP_lp.hpp:102
BCP_vec< int > _new_objs
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.
Do not use any warmstart information.
Definition: BCP_enum.hpp:235
TM sends diving information.
Warmstarting information for the LP solver.
void push_back(const_reference x)
Append x to the end of the vector.
static char * j
Definition: OSdtoa.cpp:3622
This class is the internal representation of a branching object.
Definition: BCP_branch.hpp:31
The data stored is an explicit listing of values.
Definition: BCP_enum.hpp:88
size_t varnum() const
Return the number of variables in the core.
BCP_cut_set cuts
double lb() const
Return the lower bound on the cut.
Definition: BCP_cut.hpp:82
Whether to send back the description of fathomed search tree nodes to the Tree Manager.
BCP_storage_t _storage
Specifies how warmstart information should be stored in the TM.
virtual void pack_warmstart(const BCP_warmstart *ws, BCP_buffer &buf, bool report_if_default=false)
Pack warmstarting information.
Definition: BCP_USER.hpp:63
BCP_obj_status stat
double ub() const
Return the upper bound.
Definition: BCP_var.hpp:91
BCP_vec< BCP_user_data * > & user_data()
Return a reference to the user data vector.
BCP_warmstart * warmstart
int pack_size() const
NO OLD DOC.
Definition: BCP_lp_node.hpp:92
void keep_no_child()
Fill up obj with the lower bound on each child.
int pack_size() const
Return the buffer size needed to pack the data in the core change.
OsiSolverInterface * lp_solver
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:137
CoinWarmStart * warmstartRoot
Description of the warmstart info from the end of the root node.
Definition: BCP_lp.hpp:174
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
The warmstart information at the end of the root.
double objval() const
Use the warmstart info from the end of the parent in the children.
Definition: BCP_enum.hpp:240
BCP_obj_status status() const
Return the status of the cut.
Definition: BCP_cut.hpp:91
int get_parent() const
Definition: BCP_process.hpp:25
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
static void BCP_lp_pack_warmstart(BCP_lp_prob &p, BCP_vec< int > &del_vars, BCP_vec< int > &del_cuts)
BCP_problem_core_change core_as_change
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:56
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
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
In addition to the node description, branching information is sent as well so that the children of th...
Use the warmstart info from the end of the root in all search tree nodes.
Definition: BCP_enum.hpp:238
void pack_cut(const BCP_cut &cut)
Definition: BCP_lp.cpp:174
Abstract base class that defines members common to all types of variables.
Definition: BCP_var.hpp:28
virtual BCP_warmstart * as_change(const BCP_warmstart *const old_ws, const BCP_vec< int > &del_vars, const BCP_vec< int > &del_cuts, const double petol, const double detol) const =0
Return a pointer to a warmstart info describing the currently stored data as a change with respect to...
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
A presolved branching object candidate.
BCP_storage_t var_change
Definition: BCP_lp_node.hpp:29
int bcpind() const
Return the internal index of the variable.
Definition: BCP_var.hpp:93
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
BCP_obj_status status() const
Return the status of the variable.
Definition: BCP_var.hpp:98
double true_lower_bound
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
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
BCP_vec< int > _del_change_pos
void swap(BCP_problem_core_change &other)
Swap the contents of the current core change with that of other.
int deleted_num() const
BCP_problem_core * core
Definition: BCP_lp.hpp:153
double lb() const
Return the lower bound.
Definition: BCP_var.hpp:89
BCP_vec< BCP_child_action > & action()
Return a reference to the actions to be taken.
void pack(BCP_buffer &buf) const
Pack the internal branching object into the buffer.
Definition: BCP_branch.cpp:38
BCP_message_environment * msg_env
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:139
BCP_user_data * user_data
Data the user wants to pass along with the search tree node.
static void BCP_lp_pack_user_data(BCP_lp_prob &p)
static void BCP_lp_pack_noncore_cuts(BCP_lp_prob &p, BCP_vec< int > &deleted_pos)
iterator entry(const int i)
Return an iterator to the i-th entry.
Definition: BCP_vector.hpp:109
BCP_problem_core_change * core_as_change
Definition: BCP_lp.hpp:155
virtual void pack_user_data(const BCP_user_data *ud, BCP_buffer &buf)
Pack an user data.
Definition: BCP_USER.hpp:119
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.
BCP_buffer msg_buf
Definition: BCP_lp.hpp:239
real c
void append(const BCP_vec< T > &x)
Append the entries in x to the end of the vector.
Definition: BCP_vector.hpp:169
BCP_user_pack * packer
A class that holds the methods about how to pack things.
Definition: BCP_lp.hpp:133