BCP_tm_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 "CoinTime.hpp"
4 #include "BCP_message.hpp"
5 
6 #include "BCP_enum_branch.hpp"
7 #include "BCP_node_change.hpp"
8 #include "BCP_warmstart.hpp"
9 #include "BCP_var.hpp"
10 #include "BCP_cut.hpp"
11 
12 #include "BCP_tm.hpp"
13 #include "BCP_tm_user.hpp"
14 #include "BCP_USER.hpp"
15 #include "BCP_message_tag.hpp"
16 
17 //XXX
18 #include "BCP_tm_functions.hpp"
19 
20 #ifndef BCP_DEBUG_PRINT
21 #define BCP_DEBUG_PRINT 0
22 #endif
23 
24 //#############################################################################
25 
26 std::map<int, BCP_tm_node_to_send*> BCP_tm_node_to_send::waiting;
27 
28 //#############################################################################
29 
31  const BCP_tm_node* node_to_send,
32  const BCP_message_tag tag) :
33  p(prob),
34  msgtag(tag),
35  ID(node_to_send->_index),
36  node(node_to_send),
37  root_path(NULL),
38  child_index(NULL),
39  node_data_on_root_path(NULL),
40  explicit_core_level(-1),
41  explicit_var_level(-1),
42  explicit_cut_level(-1),
43  explicit_ws_level(-1),
44  explicit_all_level(-1),
45  missing_desc_num(-1),
46  missing_var_num(-1),
47  missing_cut_num(-1)
48 {
49  level = node->getDepth();
50  const BCP_tm_node* n = node;
51 
52  root_path = new const BCP_tm_node*[level + 1];
53  child_index = new int[level];;
55 
56  // the path to the root
57  int i = level;
58  while (explicit_core_level < 0 || explicit_var_level < 0 ||
60  assert(i >= 0);
61  root_path[i] = n;
62  // some stuff is on other processes
63  if (n->_locally_stored) {
65  } else {
66  node_data_on_root_path[i]._desc = NULL;
67  node_data_on_root_path[i]._user = NULL;
68  }
69 
73  }
77  }
81  }
85  }
86  --i;
87  n = n->parent();
88  }
89  for (i = explicit_all_level + 1; i <= level; i++) {
90  child_index[i-1] = root_path[i]->birth_index();
91  }
93 }
94 
95 //#############################################################################
96 
98 {
99  delete[] root_path;
100  delete[] child_index;
101  delete[] node_data_on_root_path;
102 }
103 
104 //#############################################################################
105 
106 bool
108 {
110  int cnt, lclLevel, index;
111  buf.unpack(cnt);
112  missing_desc_num -= cnt;
113  bool has_user_data = false;
114  while (--cnt >= 0) {
115  buf.unpack(lclLevel).unpack(index);
116  assert(root_path[lclLevel]->_index == index);
117  node_data_on_root_path[lclLevel]._desc =
118  new BCP_node_change(p.packer, def, buf);
119  buf.unpack(has_user_data);
120  node_data_on_root_path[lclLevel]._user =
121  has_user_data ? p.packer->unpack_user_data(buf) : 0;
122  }
123  assert(missing_desc_num >= 0);
124  if (missing_desc_num == 0) {
125  return send();
126  }
127  return false;
128 }
129 
130 //#############################################################################
131 
132 bool
134 {
135  int cnt, pos, index;
136  buf.unpack(cnt);
137  missing_var_num -= cnt;
138  while (--cnt >= 0) {
139  buf.unpack(pos).unpack(index);
140  vars[pos] = p.packer->unpack_var_algo(buf);
141  assert(var_set._new_objs[pos] == vars[pos]->bcpind());
142  }
143  assert(missing_var_num >= 0);
144  if (missing_var_num == 0 && missing_cut_num == 0) {
145  return send();
146  }
147  return false;
148 }
149 
150 //#############################################################################
151 
152 bool
154 {
155  int cnt, pos, index;
156  buf.unpack(cnt);
157  missing_cut_num -= cnt;
158  while (--cnt >= 0) {
159  buf.unpack(pos).unpack(index);
160  cuts[pos] = p.packer->unpack_cut_algo(buf);
161  assert(cut_set._new_objs[pos] == cuts[pos]->bcpind());
162  }
163  assert(missing_cut_num >= 0);
164  if (missing_var_num == 0 && missing_cut_num == 0) {
165  return send();
166  }
167  return false;
168 }
169 
170 //#############################################################################
171 
172 bool
174 {
175  int i;
176 
177  if (missing_desc_num < 0) {
178  missing_desc_num = 0;
179  // collect what needs od be asked for
180  std::map< int, BCP_vec<int> > tms_nodelevel;
181  for (i = explicit_all_level; i <= level; i++) {
182  if (node_data_on_root_path[i]._desc.IsNull()) {
183  tms_nodelevel[root_path[i]->_data_location].push_back(i);
185  }
186  }
187  BCP_buffer& buf = p.msg_buf;
188  std::map< int, BCP_vec<int> >::const_iterator tms;
189  BCP_vec<int> indices;
190  for (tms = tms_nodelevel.begin(); tms != tms_nodelevel.end(); ++tms) {
191  buf.clear();
192  buf.pack(ID);
193  const BCP_vec<int>& nodelevel = tms->second;
194  indices.clear();
195  const int size = nodelevel.size();
196  indices.reserve(size);
197  for (i = 0; i < size; ++i) {
198  indices.unchecked_push_back(root_path[nodelevel[i]]->_index);
199  }
200  buf.pack(nodelevel);
201  buf.pack(indices);
202  p.msg_env->send(tms->first, BCP_Msg_NodeListRequest, buf);
203  }
204  }
205 
206  if (missing_desc_num > 0) {
207  return false;
208  }
209 
210 #if 0
211  // FIXME--DELETE (used to test Bonmin code)
212  for (i = 0; i <= level; ++i) {
213  assert(node_data_on_root_path[level]._desc.IsValid());
214  assert(node_data_on_root_path[level]._user.IsValid());
215  }
216 #endif
217 
218  // OK, we have all the descriptions. Now if we haven't done so yet (which
219  // is indicated by missing_var_num (and missing_cut_num) being negative)
220  // we need to create the explicit parent description and the current node
221  // description (vars/cuts will be present only with their bcpind). Also,
222  // we need to create the full list of variables for the node itself (and
223  // not for the parent).
224  if (missing_var_num < 0) {
225  missing_var_num = 0;
226  missing_cut_num = 0;
227  std::map< int, BCP_vec<int> > tms_pos;
228  std::map< int, BCP_vec<int> >::const_iterator tms;
229  std::map<int, int>::iterator remote;
230  std::map<int, Coin::SmartPtr<BCP_var> >::iterator localvar;
231  std::map<int, Coin::SmartPtr<BCP_cut> >::iterator localcut;
232  BCP_buffer& buf = p.msg_buf;
233  BCP_vec<int> indices;
234 
236  for (i = explicit_var_level; i < level; ++i) {
237  var_set.update(node_data_on_root_path[i]._desc->var_change);
238  }
239  // FIXME: can it be BCP_Storage_NoData ???
241  }
242  BCP_obj_set_change node_var_set = var_set;
243  node_var_set.update(node_data_on_root_path[level]._desc->var_change);
244  BCP_vec<int>& var_inds = node_var_set._new_objs;
245  const int varnum = var_inds.size();
246  vars.reserve(varnum);
247  // check whether we have all the vars
248  for (i = 0; i < varnum; ++i) {
249  remote = p.vars_remote.find(var_inds[i]);
250  if (remote != p.vars_remote.end()) {
251  tms_pos[remote->second].push_back(i);
253  ++missing_var_num;
254  continue;
255  }
256  localvar = p.vars_local.find(var_inds[i]);
257  if (localvar != p.vars_local.end()) {
258  // FIXME: cloning could be avoided by using smart pointers
259  vars.unchecked_push_back(localvar->second);
260  continue;
261  }
262  throw BCP_fatal_error("\
263 TM: var in node description is neither local nor remote.\n");
264  }
265  for (tms = tms_pos.begin(); tms != tms_pos.end(); ++tms) {
266  buf.clear();
267  buf.pack(ID);
268  const BCP_vec<int>& pos = tms->second;
269  const int num = pos.size();
270  indices.clear();
271  indices.reserve(num);
272  for (i = 0; i < num; ++i) {
273  indices.unchecked_push_back(var_inds[pos[i]]);
274  }
275  buf.pack(pos);
276  buf.pack(indices);
277  p.msg_env->send(tms->first, BCP_Msg_VarListRequest, buf);
278  }
279 
281  for (i = explicit_cut_level; i < level; ++i) {
282  cut_set.update(node_data_on_root_path[i]._desc->cut_change);
283  }
284  // FIXME: can it be BCP_Storage_NoData ???
286  }
287  BCP_obj_set_change node_cut_set = cut_set;
288  node_cut_set.update(node_data_on_root_path[level]._desc->cut_change);
289  BCP_vec<int>& cut_inds = node_cut_set._new_objs;
290  const int cutnum = cut_inds.size();
291  cuts.reserve(cutnum);
292  // check whether we have all the cuts
293  tms_pos.clear();
294  for (i = 0; i < cutnum; ++i) {
295  remote =p.cuts_remote.find(cut_inds[i]);
296  if (remote != p.cuts_remote.end()) {
297  tms_pos[remote->second].push_back(i);
299  ++missing_cut_num;
300  continue;
301  }
302  localcut = p.cuts_local.find(cut_inds[i]);
303  if (localcut != p.cuts_local.end()) {
304  // FIXME: cloning could be avoided by using smart pointers
305  cuts.unchecked_push_back(localcut->second);
306  continue;
307  }
308  throw BCP_fatal_error("\
309 TM: cut in node description is neither local nor remote.\n");
310  }
311  for (tms = tms_pos.begin(); tms != tms_pos.end(); ++tms) {
312  buf.clear();
313  buf.pack(ID);
314  const BCP_vec<int>& pos = tms->second;
315  const int num = pos.size();
316  indices.clear();
317  indices.reserve(num);
318  for (i = 0; i < num; ++i) {
319  indices.unchecked_push_back(cut_inds[pos[i]]);
320  }
321  buf.pack(pos);
322  buf.pack(indices);
323  p.msg_env->send(tms->first, BCP_Msg_CutListRequest, buf);
324  }
325  }
326 
327  if (missing_var_num > 0 || missing_cut_num > 0) {
328  return false;
329  }
330 
331  //=========================================================================
332  // Great! Now we have everything. Start to pack it up.
334  // The user will override at most one...
337  false /*before processing*/);
338 
339  BCP_diving_status dive =
340  (rand() < p.param(BCP_tm_par::UnconditionalDiveProbability)*RAND_MAX) ?
342 
343  // start with book-keeping data
344  BCP_buffer& buf = p.msg_buf;
345  buf.clear();
346  buf.pack(p.current_phase_colgen).pack(node->index()).pack(level).
347  pack(node->getQuality()).pack(node->getTrueLB()).pack(dive);
348 
349  // pack the process information
350  buf.pack(node->cg).pack(node->cp).pack(node->vg).pack(node->vp);
351 
352  // pack how things are stored in node. this will influence what do we pack
353  // in the parent, too.
354  buf.pack(node->_core_storage).
355  pack(node->_var_storage).
356  pack(node->_cut_storage).
357  pack(node->_ws_storage);
358 
359  // Now pack the parent if there's one
360  if (level > 0) {
361  p.msg_buf.pack(node->parent()->index());
362  // start with the core
365  for (i = explicit_core_level; i < level; ++i) {
366  core.update(*p.core_as_change,
367  node_data_on_root_path[i]._desc->core_change);
368  }
370  core.pack(p.msg_buf);
371  }
372 
373  // next the variabless
375  var_set.pack(buf);
376  }
377 
378  // now the cuts
380  cut_set.pack(buf);
381  }
382 
383  // finally warmstart
385  BCP_warmstart* warmstart =
386  node_data_on_root_path[explicit_ws_level]._desc->warmstart->clone();
387  for (i = explicit_ws_level + 1; i < level; ++i) {
388  warmstart->update(node_data_on_root_path[i]._desc->warmstart);
389  }
390  p.packer->pack_warmstart(warmstart, p.msg_buf, def);
391  delete warmstart;
392  }
393  }
394 
395  // finally pack the changes in this node
396  node_data_on_root_path[level]._desc->pack(p.packer, def, buf);
397 
398  // Now pack the full list of vars/cuts of the node
399  int cnt = vars.size();
400  buf.pack(cnt);
401  for (i = 0; i < cnt; ++i) {
402  p.pack_var(*vars[i]);
403  }
404  cnt = cuts.size();
405  buf.pack(cnt);
406  for (i = 0; i < cnt; ++i) {
407  p.pack_cut(*cuts[i]);
408  }
409 
410  const BCP_user_data* ud = node_data_on_root_path[level]._user.GetRawPtr();
411  bool has_user_data = ud != 0;
412  buf.pack(has_user_data);
413  if (has_user_data) {
414  p.packer->pack_user_data(ud, buf);
415  }
416 
417 #if (BCP_DEBUG_PRINT != 0)
418  // const char* compName = p.candidate_list.getTree()->compName();
419  printf("TM %.3lf: Sending to proc %i node: %i quality: %lf pref: %s\n",
420  CoinWallclockTime()-p.start_time,
421  node->lp, node->_index, node->getQuality(),
422  node->getPreferred().str().c_str());
423 
424 #endif
425 
426  p.msg_env->send(node->lp, msgtag, buf);
427  if (node->_index == 0) {
428  p.root_node_sent_ = CoinGetTimeOfDay();
429  }
430 
431 #ifdef BCP__DUMP_PROCINFO
432 #if (BCP__DUMP_PROCINFO == 1)
433  dump_procinfo(p, "BCP_tm_send_node()");
434 #endif
435 #endif
436  return true;
437 }
BCP_tree search_tree
Definition: BCP_tm.hpp:239
This class describes changes in the core of the problem.
BCP_buffer msg_buf
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:183
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 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
virtual void update(const BCP_warmstart *const change)=0
Update the current data with the one in the argument.
BCP_obj_set_change cut_set
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
Definition: BCP_buffer.hpp:186
int missing_cut_num
-1/nonneg unset/value : how many cut is missing
std::map< int, int > cuts_remote
Definition: BCP_tm.hpp:226
pos
position where the operator should be printed when printing the expression
void clear()
Delete every entry.
Print out a message when the default version of an overridable method is executed.
double start_time
Definition: BCP_tm.hpp:203
std::map< int, Coin::SmartPtr< BCP_cut > > cuts_local
Definition: BCP_tm.hpp:224
BCP_obj_set_change var_set
The explicit description of the vars/cuts of the parent as a BCP_obj_set_change and the vars/cuts the...
void update(const BCP_obj_set_change &objs_change)
virtual BCP_cut_algo * unpack_cut_algo(BCP_buffer &buf)
Unpack an algorithmic cut.
Definition: BCP_USER.hpp:109
void pack(BCP_buffer &buf) const
Pack the core change into the buffer.
virtual BCP_user_data * unpack_user_data(BCP_buffer &buf)
Unpack an user data.
Definition: BCP_USER.hpp:126
void pack(BCP_buffer &buf) const
int * child_index
at each level the index of the child in the parent&#39;s list
BCP_vec< int > _new_objs
void reserve(const size_t n)
Reallocate the object to make space for n entries.
Warmstarting information for the LP solver.
BCP_tm_node * parent()
const BCP_tm_node ** root_path
the path to the root.
int index() const
The data stored is an explicit listing of values.
Definition: BCP_enum.hpp:88
BCP_storage_t _storage
const int ID
An identifier of this object.
virtual void pack_warmstart(const BCP_warmstart *ws, BCP_buffer &buf, bool report_if_default=false)
Pack warmstarting information.
Definition: BCP_USER.hpp:63
std::map< int, Coin::SmartPtr< BCP_var > > vars_local
Definition: BCP_tm.hpp:220
void make_wrtcore_if_shorter(const BCP_problem_core_change &orig_core)
Replace the current explicitly stored core change with one stored with respect to the explicitly stor...
Coin::SmartPtr< BCP_node_change > _desc
Definition: BCP_tm_node.hpp:53
BCP_diving_status
This enumerative constant describes the diving status of the search tree node processed by the LP pro...
The probability with which the LP process is directed to dive.
BCP_vec< Coin::SmartPtr< BCP_cut > > cuts
NO OLD DOC.
Definition: BCP_tm.hpp:136
BCP_tm_node_data _data
bool receive_cuts(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
BCP_tm_node_to_send(BCP_tm_prob &p, const BCP_tm_node *node, const BCP_message_tag tag)
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
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
void pack_cut(const BCP_cut &cut)
Definition: BCP_tm.cpp:169
BCP_vec< Coin::SmartPtr< BCP_var > > vars
The list of vars/cuts of the node when the changes of the node are applied to var_set and cut_set...
After branching the LP process is free to decide whether it keeps a child to dive into...
std::map< int, int > vars_remote
Definition: BCP_tm.hpp:222
Coin::SmartPtr< BCP_user_data > _user
Definition: BCP_tm_node.hpp:54
BCP_message_tag msgtag
the message tag to be used when finally the node is sent off
const BCP_tm_node * node
int birth_index() const
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
BCP_message_environment * msg_env
A class that holds the methods about how to pack things.
Definition: BCP_tm.hpp:156
void pack_var(const BCP_var &var)
Definition: BCP_tm.cpp:83
BCP_user_pack * packer
A class that holds the methods about how to pack things.
Definition: BCP_tm.hpp:153
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
virtual BCP_var_algo * unpack_var_algo(BCP_buffer &buf)
Unpack an algorithmic variable.
Definition: BCP_USER.hpp:93
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
int level
the level of node to be sent
static std::map< int, BCP_tm_node_to_send * > waiting
void unchecked_push_back(const_reference x)
Append x to the end of the vector.
bool receive_vars(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
BCP_tm_user * user
A class that holds the methods about how to pack things.
Definition: BCP_tm.hpp:151
int missing_desc_num
-1/nonneg unset/value : how many desc is missing
BCP_problem_core_change * core_as_change
Definition: BCP_tm.hpp:210
BCP_tm_node_data * node_data_on_root_path
the node data on each level (well, up to the point where we have encountered an explicit description ...
void update(const BCP_problem_core_change &expl_core, const BCP_problem_core_change &core_change)
Update the current change according to core_change.
int missing_var_num
-1/nonneg unset/value : how many var is missing
virtual void display_node_information(BCP_tree &search_tree, const BCP_tm_node &node)
Display user information just before a new node is sent to the LP or diving into a node is acknowledg...
bool receive_node_desc(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
After branching the LP process must inquire of the Tree Manager whether it can dive into one of the c...
BCP_column_generation current_phase_colgen
Definition: BCP_tm.hpp:216
virtual void pack_user_data(const BCP_user_data *ud, BCP_buffer &buf)
Pack an user data.
Definition: BCP_USER.hpp:119
void fint * n
bool send()
return true or false depending on whether the node was really sent out or it&#39;s still waiting for some...
char param(BCP_tm_par::chr_params key) const
Definition: BCP_tm.hpp:298
int explicit_core_level
where the various pieces start to be explicit (or wrt.
double root_node_sent_
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:191