BCP_tm_msgproc.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 
5 #include "BCP_math.hpp"
6 #include "BCP_node_change.hpp"
7 #include "BCP_tm.hpp"
8 #include "BCP_lp.hpp"
9 #include "BCP_tm_functions.hpp"
10 #include "BCP_problem_core.hpp"
11 #include "BCP_solution.hpp"
12 #include "BCP_tm_user.hpp"
13 
14 static void
16 
17 //#############################################################################
18 
20 {
21  p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
23 }
24 
25 //#############################################################################
26 
28 {
29  p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
31 }
32 
33 //#############################################################################
34 
36 {
38 
39  if (p.param(BCP_tm_par::LpProcessNum) > 0) {
40  const bool debug = p.param(BCP_tm_par::DebugLpProcesses) != 0;
41  const int num = p.param(BCP_tm_par::LpProcessNum);
43  p.lp_procs.insert(p.lp_procs.end(), num, -1);
44  bool success = machines.size() == 0 ?
45  p.msg_env->start_processes(exe, num, debug, &p.lp_procs[0]) :
46  p.msg_env->start_processes(exe, num, machines, debug, &p.lp_procs[0]);
47  if (! success) {
48  throw BCP_fatal_error("Failed to start up the LP processes\n");
49  }
50  p.lp_scheduler.add_free_ids(p.lp_procs.size(), &p.lp_procs[0]);
51  }
52 
53 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
54  if (p.param(BCP_tm_par::CgProcessNum) > 0) {
55  const bool debug = p.param(BCP_tm_par::DebugCgProcesses) != 0;
56  const int num = p.param(BCP_tm_par::CgProcessNum);
58  if (machines.size() == 0) {
59  p.slaves.cg= p.msg_env->start_processes(exe, num, debug);
60  } else {
61  p.slaves.cg= p.msg_env->start_processes(exe, num, machines, debug);
62  }
63  p.slaves.all->add_procs(p.slaves.cg->procs().begin(),
64  p.slaves.cg->procs().end());
65  }
66 
67  if (p.param(BCP_tm_par::VgProcessNum) > 0) {
68  const bool debug = p.param(BCP_tm_par::DebugVgProcesses) != 0;
69  const int num = p.param(BCP_tm_par::VgProcessNum);
71  if (machines.size() == 0) {
72  p.slaves.vg= p.msg_env->start_processes(exe, num, debug);
73  } else {
74  p.slaves.vg= p.msg_env->start_processes(exe, num, machines, debug);
75  }
76  p.slaves.all->add_procs(p.slaves.vg->procs().begin(),
77  p.slaves.vg->procs().end());
78  }
79 
80  if (p.param(BCP_tm_par::CpProcessNum) > 0) {
81  const bool debug = p.param(BCP_tm_par::DebugCpProcesses) != 0;
82  const int num = p.param(BCP_tm_par::CpProcessNum);
84  if (machines.size() == 0) {
85  p.slaves.cp= p.msg_env->start_processes(exe, num, debug);
86  } else {
87  p.slaves.cp= p.msg_env->start_processes(exe, num, machines, debug);
88  }
89  p.slaves.all->add_procs(p.slaves.cp->procs().begin(),
90  p.slaves.cp->procs().end());
91  }
92 
93  if (p.param(BCP_tm_par::VpProcessNum) > 0) {
94  const bool debug = p.param(BCP_tm_par::DebugVpProcesses) != 0;
95  const int num = p.param(BCP_tm_par::VpProcessNum);
97  if (machines.size() == 0) {
98  p.slaves.vp= p.msg_env->start_processes(exe, num, debug);
99  } else {
100  p.slaves.vp= p.msg_env->start_processes(exe, num, machines, debug);
101  }
102  p.slaves.all->add_procs(p.slaves.vp->procs().begin(),
103  p.slaves.vp->procs().end());
104  }
105 #endif
106 }
107 
108 //#############################################################################
109 
111 {
112  p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
114 }
115 
116 //#############################################################################
117 
118 template <typename T> void
120  BCP_process_t ptype,
122  int num, const int* pids)
123 {
124  if (num == 0) {
125  return;
126  }
127 
128  p.msg_buf.clear();
129  p.msg_buf.pack(ptype);
130  p.msg_buf.pack(p.ub());
131  p.msg_env->multicast(num, pids, BCP_Msg_ProcessType, p.msg_buf);
132 
133  p.msg_buf.clear();
134  par.pack(p.msg_buf);
135  const double wallclockInit = CoinWallclockTime(-1);
136  p.msg_buf.pack(wallclockInit);
137  p.msg_buf.pack(p.start_time);
139 
140  p.msg_buf.clear();
141  p.core->pack(p.msg_buf);
143 
144  p.msg_buf.clear();
145  p.user->pack_module_data(p.msg_buf, ptype);
147 }
148 
149 //-----------------------------------------------------------------------------
150 
151 template <typename T> void
153  BCP_process_t ptype,
155  const std::vector<int>& pids)
156 {
157  BCP_tm_initialize_process_type(p, ptype, par, pids.size(), &pids[0]);
158 }
159 
160 //#############################################################################
161 
162 void
164  int num, const int* pids)
165 {
166  switch (ptype) {
167  case BCP_ProcessType_LP:
169  num, pids);
170  break;
171  case BCP_ProcessType_TS:
173  num, pids);
174  break;
175 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
176  case BCP_ProcessType_CP:
177 // BCP_tm_initialize_process_type(p, BCP_ProcessType_CP, p.slave_pars.cp,
178 // procs ? *procs : p.slaves.cp->procs());
179  break;
180  case BCP_ProcessType_VP:
181 // BCP_tm_initialize_process_type(p, BCP_ProcessType_VP, p.slave_pars.vp,
182 // procs ? *procs : p.slaves.vp->procs());
183  break;
184  case BCP_ProcessType_CG:
186  procs ? *procs : p.slaves.cg->procs());
187  break;
188  case BCP_ProcessType_VG:
190  procs ? *procs : p.slaves.vg->procs());
191  break;
192 #endif
193  default:
194  throw BCP_fatal_error("Trying to notify bad process type\n");
195  }
196 }
197 
198 //-----------------------------------------------------------------------------
199 
200 void
202  const std::vector<int>& pids)
203 {
204  BCP_tm_notify_process_type(p, ptype, pids.size(), &pids[0]);
205 }
206 
207 //#############################################################################
208 
209 void
211 {
213 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
214  BCP_tm_notify_process_type(p, BCP_ProcessType_CG, &p.slaves.cg->procs());
215  BCP_tm_notify_process_type(p, BCP_ProcessType_VG, &p.slaves.vg->procs());
216  BCP_tm_notify_process_type(p, BCP_ProcessType_CP, &p.slaves.cp->procs());
217  BCP_tm_notify_process_type(p, BCP_ProcessType_VP, &p.slaves.vp->procs());
218 #endif
219 }
220 
221 //#############################################################################
222 
223 void
225 {
226  p.msg_buf.clear();
227  p.msg_buf.pack(p.ub());
228  p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
230 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
231 #endif
232 }
233 
234 //#############################################################################
235 
236 void
238 {
240  p.msg_buf.clear();
241  p.packer->pack_warmstart(ws, p.msg_buf);
242  p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
244 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
245 #endif
246  delete ws;
247 }
248 
249 //#############################################################################
250 
251 void
253 {
254  int sender = p.msg_buf.sender();
255  int branchNum;
256  p.msg_buf.unpack(branchNum);
257  int * pids = new int[branchNum];
258  int numIds = p.lp_scheduler.request_sb_ids(branchNum, pids);
259  p.msg_buf.clear();
260  p.msg_buf.pack(pids, numIds);
261  p.msg_env->send(sender, BCP_Msg_ProcessList, p.msg_buf);
262  delete[] pids;
263 }
264 
265 //#############################################################################
266 // This function returns T/F depending on whether an LP process was freed up
267 // or not.
268 
269 void
271 {
272  BCP_tm_node* node;
273  int sender;
274  int id;
275  std::map<int, BCP_tm_node_to_send*>::iterator index__node;
276  BCP_tm_node_to_send* node_to_send;
277 
278  // msg_counter counts the number of incoming messages. Every so often
279  // (always when there's no message in the buffer) we check that every
280  // processor is alive and well. If any has died then appropriate process
281  // list gets shrunk, tree nodes put back on the list, etc.
282  // Of course, this makes sense only if the computing environment in NOT
283  // serial.
284  static int msg_count = 0;
285  // static const int test_frequency = 1;
286 
287  ++msg_count;
288 
289  switch (msg_buf.msgtag()){
290  case BCP_Msg_User:
292  break;
293 
294  case BCP_Msg_NoMessage:
295  msg_count = 0;
296  break;
297 
298  case BCP_Msg_UpperBound:
299  throw BCP_fatal_error("TM: Got BCP_Msg_UpperBound message!\n");
300  break;
301 
306  break;
307 
312  break;
313 
322  } else {
324  }
325  nodes_to_free.push_back(node);
326  break;
327 
330  break;
331 
333  {
335  if (new_sol) {
336  const bool allval =
338  const bool allsol =
340  const bool betterval =
342  const bool bettersol =
344  bool better;
345  if (upper_bound > new_sol->objective_value() + 1e-6) {
346  better = true;
347  } else if (upper_bound > new_sol->objective_value() - 1e-6) {
348  better = user->replace_solution(feas_sol, new_sol);
349  } else {
350  better = false;
351  }
352 
353  if (allval || allsol || ((betterval || bettersol) && better)) {
355  printf("TM: Solution found at %.3f sec.\n",
356  CoinCpuTime() - start_time);
357  }
358  const int tree_size = search_tree.size();
359  const int tree_proc = search_tree.processed();
360  const int cand_list_size = candidate_list.size();
361  const int cand_list_ins = candidate_list.numInserted();
362  char bdstr[1000];
363 
364  if (upper_bound > BCP_DBL_MAX/10) {
365  sprintf(bdstr, "infinity");
366  } else {
367  sprintf(bdstr, "%f", upper_bound);
368  }
369  sender = msg_buf.sender();
370  printf("TM %.3f: Sol from proc: %i val: %f (prev best: %s) tree size/procd: %i/%i cand list ins/size: %i/%i\n",
371  CoinWallclockTime() - start_time, sender,
372  new_sol->objective_value(), bdstr,
373  tree_size, tree_proc,
374  cand_list_ins, cand_list_size);
375  if (allsol || (bettersol && better)) {
377  }
378  }
379  if (better) {
381  ub(new_sol->objective_value());
382  delete feas_sol;
383  feas_sol = new_sol;
384  BCP_tm_broadcast_ub(*this);
385  } else {
386  delete new_sol;
387  }
388  }
389  }
390  break;
391 
394  break;
395 
397  sender = msg_buf.sender();
398  lp_scheduler.release_sb_id(sender);
399  break;
400 
403  break;
404 
406  sender = msg_buf.sender();
407  msg_buf.clear();
409  next_cut_index_set_start += 10000;
412  break;
413 
415  sender = msg_buf.sender();
416  msg_buf.clear();
418  next_var_index_set_start += 10000;
421  break;
422 
424  msg_buf.unpack(id);
425  index__node = BCP_tm_node_to_send::waiting.find(id);
426  if (index__node == BCP_tm_node_to_send::waiting.end()) {
427  throw BCP_fatal_error("TM: node data from TMS for node not waiting.\n");
428  }
429  node_to_send = index__node->second;
430  if (node_to_send->receive_node_desc(msg_buf)) {
431  delete node_to_send;
432  BCP_tm_node_to_send::waiting.erase(index__node);
433  }
434  break;
435 
437  msg_buf.unpack(id);
438  index__node = BCP_tm_node_to_send::waiting.find(id);
439  if (index__node == BCP_tm_node_to_send::waiting.end()) {
440  throw BCP_fatal_error("TM: var list from TMS for node not waiting.\n");
441  }
442  node_to_send = index__node->second;
443  if (node_to_send->receive_vars(msg_buf)) {
444  delete node_to_send;
445  BCP_tm_node_to_send::waiting.erase(index__node);
446  }
447  break;
448 
450  msg_buf.unpack(id);
451  index__node = BCP_tm_node_to_send::waiting.find(id);
452  if (index__node == BCP_tm_node_to_send::waiting.end()) {
453  throw BCP_fatal_error("TM: cut list from TMS for node not waiting.\n");
454  }
455  node_to_send = index__node->second;
456  if (node_to_send->receive_cuts(msg_buf)) {
457  delete node_to_send;
458  BCP_tm_node_to_send::waiting.erase(index__node);
459  }
460  break;
461 
465  sender = msg_buf.sender();
466  msg_buf.unpack(id); // just reuse an int variable...
467  ts_space[msg_buf.sender()] = id;
468  break;
469 
471  throw BCP_fatal_error("\
472 Unexpected BCP_Msg_LpStatistics message in BCP_tm_prob::process_message.\n");
473 
475  // *FIXME-NOW* : what to do when something has died?
476  break;
477 
480  break;
481 
482  case BCP_CONFIG_CHANGE:
484  break;
485 
486  default:
487  throw BCP_fatal_error("\
488 Unknown message in BCP_tm_prob::process_message.\n");
489  }
490  msg_buf.clear();
491 
492  const double t = CoinCpuTime() - start_time;
493  const bool time_is_over = t > param(BCP_tm_par::MaxRunTime);
494 
495  /* FIXME: for now we disable testing the machine... */
496 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
498  msg_count % test_frequency == 0) {
499  // run the machine testing while it returns false (i.e., it did not
500  // check out, it had to delete something)
501  while (! BCP_tm_test_machine(*this));
502  if (slaves.lp->procs().size() == 0)
503  throw BCP_fatal_error("TM: No LP process left to compute with.\n");
504  }
505 #endif
506 
507  if (time_is_over) {
508  const double lb = search_tree.true_lower_bound(search_tree.root());
510  throw BCP_fatal_error("\
511 TM: Time has ran out.\n\
512 TM: Best lower bound in this phase: %f\n", lb);
513  }
514 }
515 
516 //#############################################################################
517 
518 /* FIXME: for now we disable testing the machine... */
519 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
520 bool
522 {
523  BCP_vec<int>::const_iterator dead_process_i =
524  p.msg_env->alive(*p.slaves.all);
525 
526  if (dead_process_i == p.slaves.all->procs().end())
527  // everything is fine
528  return true;
529 
530  int dead_pid = *dead_process_i;
531  bool continue_testing = true;
532  // Oops, something has died, must write it off.
533 
534  if (continue_testing) {
535  printf("TM: Removing dead LP (pid: %i).\n", dead_pid);
536  BCP_tm_remove_lp(p, dead_pid);
537  continue_testing = false;
538  }
539 
540 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
541  int i;
542  if (continue_testing && p.slaves.cg) {
543  i = p.slaves.cg->index_of_proc(dead_process);
544  if (i >= 0) {
545  printf("TM: CG #%i is dead. Removing the LP/CG/VG/triplet.\n", i);
546  BCP_tm_remove_cg(p, i);
547  continue_testing = false;
548  }
549  }
550 
551  if (continue_testing && p.slaves.vg) {
552  i = p.slaves.vg->index_of_proc(dead_process);
553  if (i >= 0) {
554  printf("TM: VG #%i is dead. Removing the LP/CG/VG/triplet.\n", i);
555  BCP_tm_remove_vg(p, i);
556  continue_testing = false;
557  }
558  }
559 #endif
560 
561  p.slaves.all->delete_proc(dead_pid);
562 
563  return false;
564 }
565 #endif
566 
567 //#############################################################################
568 
570 {
571 /* FIXME: we don't have pools anyway... */
572 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
573  if (node->cp != -1) {
574  BCP_vec< std::pair<int, int> >::iterator proc =
576 #ifdef BCP_DEBUG
577  if (proc == p.leaves_per_cp.end())
578  throw BCP_fatal_error("\
579 TM: non-existing CP was assigned to a just pruned node.\n");
580 #endif
581  if (--proc->second == 0)
582  p.slaves.cp->set_proc_free(proc->first);
583  }
584  if (node->vp != -1) {
585  BCP_vec< std::pair<int, int> >::iterator proc =
587 #ifdef BCP_DEBUG
588  if (proc == p.leaves_per_vp.end())
589  throw BCP_fatal_error("\
590 TM: non-existing VP was assigned to a just pruned node.\n");
591 #endif
592  if (--proc->second == 0)
593  p.slaves.vp->set_proc_free(proc->first);
594  }
595 #endif
596 }
597 
598 //#############################################################################
599 
600 /* FIXME: for now we disable testing the machine... */
601 void
602 BCP_tm_remove_lp(BCP_tm_prob& p, const int dead_pid)
603 {
604  printf("For now we can't remove dead processes...\n");
605  abort();
606 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
607  BCP_tm_node* node = p.active_nodes[dead_pid];
608  if (node) {
609  if (node->lp != dead_pid)
610  throw BCP_fatal_error("TM: messed up active nodes... :-(.\n");
611  // Got to put back the search tree node onto the candidate list.
612  // fix the CP/VP fields
613  if (node->cp != -1) {
614  BCP_vec< std::pair<int, int> >::iterator proc =
616  if (proc == p.leaves_per_cp.end()) {
617  node->cp = -1;
618  }
619  }
620  if (node->vp != -1) {
621  BCP_vec< std::pair<int, int> >::iterator proc =
623  if (proc == p.leaves_per_vp.end()) {
624  node->vp = -1;
625  }
626  }
627  p.active_nodes.erase(dead_pid);
628 
629  node->lp = node->cg = node->vg = -1;
630  node->status = BCP_CandidateNode;
631  p.candidate_list.push(node, false);
632  }
633 
634 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
635  int proc;
636  if (p.slaves.cg) {
637  proc = p.slaves.cg->procs()[index];
638  p.slaves.cg->delete_proc(index);
639  p.slaves.all->delete_proc(p.slaves.all->index_of_proc(proc));
640  }
641  if (p.slaves.vg) {
642  proc = p.slaves.vg->procs()[index];
643  p.slaves.vg->delete_proc(index);
644  p.slaves.all->delete_proc(p.slaves.all->index_of_proc(proc));
645  }
646 #endif
647 
648  p.slaves.lp->delete_proc(dead_pid);
649  p.slaves.all->delete_proc(dead_pid);
650 #endif
651 }
652 
653 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
654 void
655 BCP_tm_remove_cg(BCP_tm_prob& p, const int index)
656 {
657  // for now this just removes the lp
658  BCP_tm_remove_lp(p, index);
659 }
660 
661 void
662 BCP_tm_remove_vg(BCP_tm_prob& p, const int index)
663 {
664  // for now this just removes the lp
665  BCP_tm_remove_lp(p, index);
666 }
667 #endif
668 
669 //#############################################################################
670 
671 void
673 {
674  abort();
675  // BROKEN: multistage is BROKEN
676 #if 0
677  // only a BCP_named_pricing_list is sent over, unpack it.
678  BCP_tm_node* root = p.search_tree.root();
679 
680  p.flags.root_pricing_unpacked = true;
681 
682  BCP_tm_free_procs_of_node(p, root);
683  p.active_nodes.erase(root->lp);
684 #endif
685 }
686 
687 //#############################################################################
688 
689 void
691 {
693 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
694  if (node->cg != -1)
695  p.slaves.cg->set_proc_free(node->cg);
696  if (node->vg != -1)
697  p.slaves.vg->set_proc_free(node->vg);
698 #endif
699  // node's pointers are 0'd out (not deleted!)
700  node->lp = node->cg = node->vg = -1;
701 }
702 
703 //#############################################################################
704 
705 static void
707 {
708  /* FIXME: Do not allow config change for now */
709 #if 0
710  int i;
711  int sender = buf.sender();
712 
713  int lp_num = 0;
714  buf.unpack(lp_num);
715  BCP_vec<BCP_string> lp(lp_num, "");
716  for (i = 0; i < lp_num; ++i)
717  buf.unpack(lp[i]);
718 
719  int cg_num = 0;
720  buf.unpack(cg_num);
721  BCP_vec<BCP_string> cg(cg_num, "");
722  for (i = 0; i < cg_num; ++i)
723  buf.unpack(cg[i]);
724 
725  int vg_num = 0;
726  buf.unpack(vg_num);
727  BCP_vec<BCP_string> vg(vg_num, "");
728  for (i = 0; i < vg_num; ++i)
729  buf.unpack(vg[i]);
730 
731  int cp_num = 0;
732  buf.unpack(cp_num);
733  BCP_vec<BCP_string> cp(cp_num, "");
734  for (i = 0; i < cp_num; ++i)
735  buf.unpack(cp[i]);
736 
737  int vp_num = 0;
738  buf.unpack(vp_num);
739  BCP_vec<BCP_string> vp(vp_num, "");
740  for (i = 0; i < vp_num; ++i)
741  buf.unpack(vp[i]);
742 
743  // Check that everything works out fine
744 
745 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
746  // At least for now cg_num/vg_num must be the same as lp_num or must be 0
747  if (p.slaves.cg->size() > 0) {
748  if (cg_num != lp_num) {
749  printf("\
750 BCP: config change: CG's are running thus the number of new CG's must be\
751  the same as the number of new LP's. Not changing anything.\n");
752  p.msg_env->send(sender, BCP_CONFIG_ERROR);
753  return;
754  }
755  } else {
756  if (cg_num != 0) {
757  printf("\
758 BCP: config change: CG's are not running thus no new CG's can be started.\
759  Not changing anything.\n");
760  p.msg_env->send(sender, BCP_CONFIG_ERROR);
761  return;
762  }
763  }
764  if (p.slaves.vg->size() > 0) {
765  if (vg_num != lp_num) {
766  printf("\
767 BCP: config change: VG's are running thus the number of new VG's must be\
768  the same as the number of new LP's. Not changing anything.\n");
769  p.msg_env->send(sender, BCP_CONFIG_ERROR);
770  return;
771  }
772  } else {
773  if (vg_num != 0) {
774  printf("\
775 BCP: config change: VG's are not running thus no new VG's can be started.\
776  Not changing anything.\n");
777  p.msg_env->send(sender, BCP_CONFIG_ERROR);
778  return;
779  }
780  }
781 #endif
782 
783  // Spawn the jobs
785  if (lp_num > 0) {
786  const bool debug = p.param(BCP_tm_par::DebugLpProcesses) != 0;
787  BCP_proc_array* new_lps =
788  p.msg_env->start_processes(exe, lp_num, lp, debug);
789  p.slaves.lp->add_procs(new_lps->procs().begin(),
790  new_lps->procs().end());
791  BCP_tm_notify_process_type(p, BCP_ProcessType_LP, &new_lps->procs());
792  }
793 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
794  if (cg_num > 0) {
795  const bool debug = p.param(BCP_tm_par::DebugCgProcesses) != 0;
796  BCP_proc_array* new_cgs =
797  p.msg_env->start_processes(exe, cg_num, cg, debug);
798  p.slaves.cg->add_procs(new_cgs->procs().begin(),
799  new_cgs->procs().end());
800  BCP_tm_notify_process_type(p, BCP_ProcessType_CG, &new_cgs->procs());
801  }
802  if (vg_num > 0) {
803  const bool debug = p.param(BCP_tm_par::DebugVgProcesses) != 0;
804  BCP_proc_array* new_vgs =
805  p.msg_env->start_processes(exe, vg_num, vg, debug);
806  p.slaves.vg->add_procs(new_vgs->procs().begin(),
807  new_vgs->procs().end());
808  BCP_tm_notify_process_type(p, BCP_ProcessType_VG, &new_vgs->procs());
809  }
810  if (cp_num > 0) {
811  const bool debug = p.param(BCP_tm_par::DebugCpProcesses) != 0;
812  BCP_proc_array* new_cps =
813  p.msg_env->start_processes(exe, cp_num, cp, debug);
814  p.slaves.cp->add_procs(new_cps->procs().begin(),
815  new_cps->procs().end());
816  BCP_tm_notify_process_type(p, BCP_ProcessType_CP, &new_cps->procs());
817  }
818  if (vp_num > 0) {
819  const bool debug = p.param(BCP_tm_par::DebugVpProcesses) != 0;
820  BCP_proc_array* new_vps =
821  p.msg_env->start_processes(exe, vp_num, vp, debug);
822  p.slaves.vp->add_procs(new_vps->procs().begin(),
823  new_vps->procs().end());
824  BCP_tm_notify_process_type(p, BCP_ProcessType_VP, &new_vps->procs());
825  }
826 #endif
827 
828  // Signal back that everything is OK.
829  p.msg_env->send(sender, BCP_CONFIG_OK);
830 #endif
831 }
BCP_tree search_tree
Definition: BCP_tm.hpp:239
BCP_buffer msg_buf
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:183
virtual void display_feasible_solution(const BCP_solution *sol)
Display a feasible solution.
void BCP_tm_notify_about_new_phase(BCP_tm_prob &p)
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.
virtual bool start_processes(const BCP_string &exe, const int proc_num, const bool debug, int *ids)=0
Spawn proc_num processes, all with the same executable.
Invoke the user-written &quot;display_feasible_solution&quot; function if a better integral feasible solution i...
BCP_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
BCP has finished.
BCP_parameter_set< BCP_vg_par > vg
Definition: BCP_tm.hpp:67
int next_cut_index_set_start
Definition: BCP_tm.hpp:229
BCP_parameter_set< BCP_cg_par > cg
Definition: BCP_tm.hpp:65
void BCP_tm_notify_process_type(BCP_tm_prob &p, BCP_process_t ptype, int num, const int *pids)
Used to indicate that there is no message in the buffer of a process.
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
Definition: BCP_buffer.hpp:186
virtual double objective_value() const =0
The method returning the objective value of the solution.
virtual void pack_module_data(BCP_buffer &buf, BCP_process_t ptype)
Pack the initial information (info that the user wants to send over) for the process specified by the...
Definition: BCP_tm_user.cpp:52
std::map< int, BCP_tm_node * > active_nodes
A map from the process ids to the nodes (what they work on)
Definition: BCP_tm.hpp:241
virtual void change_candidate_heap(CoinSearchTreeManager &candidates, const bool new_solution)
double start_time
Definition: BCP_tm.hpp:203
Request a list of process ids the LP can use to do distributed strong branching.
void BCP_tm_unpack_priced_root(BCP_tm_prob &p, BCP_buffer &buf)
The message contains the statistics the LP process collected.
Request an index set for variables to be genarated.
BCP_tm_node_status status
Definition: BCP_tm_node.hpp:78
BCP_process_t
This enumerative constant describes the various process types.
double ub() const
Definition: BCP_tm.hpp:321
Request an index set for cuts to be generated.
BCP_vec< std::pair< int, int > > leaves_per_cp
Definition: BCP_tm.hpp:259
static void BCP_tm_change_config(BCP_tm_prob &p, BCP_buffer &buf)
BCP_tm_node * BCP_tm_unpack_node_no_branching_info(BCP_tm_prob &p, BCP_buffer &buf)
size_t size() const
The TM sends the description of the core formulation to the slave process.
int processed() const
The lower bound corresponding to the node is above the upper bound.
int sender() const
Return a const pointer to the process id of the sender of the message in the buffer.
Definition: BCP_buffer.hpp:93
The number of Variable Generator processes that should be spawned.
The TM sends the process type to the process (LP, Cut Generator, etc.)
CoinSearchTreeManager candidate_list
Definition: BCP_tm.hpp:243
Print the time (and the solution value and solution if the above paramters are set appropriately) whe...
BCP_solution * feas_sol
Definition: BCP_tm.hpp:163
BCP_problem_core * core
Definition: BCP_tm.hpp:208
BCP_vec< BCP_tm_node * > next_phase_nodes
a vector of nodes to be processed in the next phase
Definition: BCP_tm.hpp:250
This class is a very simple impelementation of a constant length string.
Definition: BCP_string.hpp:13
virtual BCP_warmstart * unpack_warmstart(BCP_buffer &buf, bool report_if_default=false)
Unpack warmstarting information.
Definition: BCP_USER.hpp:74
void add_free_ids(int numIds, const int *ids)
Pass in a list of freeIds_ to add.
Definition: BCP_process.cpp:67
virtual BCP_solution * unpack_feasible_solution(BCP_buffer &buf)
Unpack a MIP feasible solution that was packed by the BCP_lp_user::pack_feasible_solution() method...
Definition: BCP_tm_user.cpp:57
void BCP_tm_stop_processes(BCP_tm_prob &p)
Warmstarting information for the LP solver.
Indicates whether message passing is serial (all processes are on the same processor) or not...
void push_back(const_reference x)
Append x to the end of the vector.
virtual void process_message()
void BCP_tm_start_processes(BCP_tm_prob &p)
void BCP_tm_remove_vg(BCP_tm_prob &p, const int index)
void BCP_tm_remove_lp(BCP_tm_prob &p, const int index)
This is the class serves as a holder for a set of parameters.
Invoke the user-written &quot;display_feasible_solution&quot; function if any* feasible solution is found...
Maximum allowed running time.
int request_sb_ids(int numIds, int *ids)
Request for a number of id&#39;s to do some strong branching.
Definition: BCP_process.cpp:85
#define BCP_DBL_MAX
Definition: BCP_math.hpp:6
void fint fint fint real fint real real real real real real real real real * e
void BCP_tm_unpack_node_with_branching_info(BCP_tm_prob &p, BCP_buffer &buf)
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_vec< BCP_tm_node * > nodes_to_free
Definition: BCP_tm.hpp:252
Print the value of the integer solution when a solution better than the current best solution is foun...
void fint fint fint real fint real real real real real real real real real fint real fint * lp
The number of Cut Generator processes that should be spawned.
fint end
int next_var_index_set_start
Definition: BCP_tm.hpp:231
An LP process (that is used as a strong branching node) indicates that it&#39;s finished.
BCP_vec< std::pair< int, int > > leaves_per_vp
Definition: BCP_tm.hpp:261
The node is discarded (fathomed).
void pack(BCP_buffer &buf) const
Pack the contents of the core description into the buffer.
NO OLD DOC.
Definition: BCP_tm.hpp:136
The TM sends the appropriate parameters to the slave process.
The warmstart information at the end of the root.
bool receive_cuts(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
void release_sb_id(int id)
Gives back to scheduler an id used for strong branching.
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...
The TM sends the initial user packed information to the slave process.
TM warns an LP process that the second phase will start.
void BCP_tm_free_procs_of_node(BCP_tm_prob &p, BCP_tm_node *node)
void BCP_tm_idle_processes(BCP_tm_prob &p)
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
BCP_message_tag msgtag() const
Return the message tag of the message in the buffer.
Definition: BCP_buffer.hpp:90
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real * ws
The lower bound corresponding to the node is above the upper bound.
In addition to the node description, branching information is sent as well so that the children of th...
BCP_tm_node * root()
bool root_pricing_unpacked
Set to true if the result of root pricing is already unpacked.
Definition: BCP_tm.hpp:78
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
double true_lower_bound(const BCP_tm_node *node) const
Return the worst true lower bound in the search tree.
BCP_message_environment * msg_env
A class that holds the methods about how to pack things.
Definition: BCP_tm.hpp:156
BCP_user_pack * packer
A class that holds the methods about how to pack things.
Definition: BCP_tm.hpp:153
Indicates whether to debug Cut Pool processes or not.
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
iterator end()
Return an iterator to the end of the object.
Definition: BCP_vector.hpp:104
Send index set for cuts to be generated in the future.
std::vector< int > lp_procs
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:186
void BCP_tm_notify_processes(BCP_tm_prob &p)
Print the value of any integer feasible solution found.
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
static std::map< int, BCP_tm_node_to_send * > waiting
void BCP_tm_broadcast_ub(BCP_tm_prob &p)
void BCP_tm_initialize_process_type(BCP_tm_prob &p, BCP_process_t ptype, BCP_parameter_set< T > &par, int num, const int *pids)
bool receive_vars(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
BCP_scheduler lp_scheduler
members to measure how long it took to process the root node.
Definition: BCP_tm.hpp:188
BCP_parameter_set< BCP_lp_par > lp
Definition: BCP_tm.hpp:61
BCP_tm_user * user
A class that holds the methods about how to pack things.
Definition: BCP_tm.hpp:151
Used by the user to send a message to the user portion of the other process.
Any process to TM: a process has died.
double upper_bound
Definition: BCP_tm.hpp:201
BCP_tm_flags flags
Definition: BCP_tm.hpp:177
Send index set for variables to be generated in the future.
Indicates whether to debug Cut Generator processes or not.
The number of Variable Pool processes that should be spawned.
BCP_slave_params slave_pars
Definition: BCP_tm.hpp:170
virtual bool replace_solution(const BCP_solution *old_sol, const BCP_solution *new_sol)
Decide whether to replace old_sol with new_sol.
Definition: BCP_tm_user.cpp:88
std::map< int, int > ts_space
Definition: BCP_tm.hpp:235
Any process to TM or TM to any process: a new upper bound found.
Send a list of process ids the LP can use to do distributed strong branching.
virtual bool alive(const int pid)=0
Test if the process given by the argument is alive or not.
bool receive_node_desc(BCP_buffer &buf)
return true if has everything to send the thing off to the LP.
void BCP_tm_provide_SB_processes(BCP_tm_prob &p)
Indicates whether to debug Variable Pool processes or not.
void release_node_id(int id)
Give back an id to scheduler used for processing a node.
static char * t
Definition: OSdtoa.cpp:3645
void BCP_tm_modify_pool_counters(BCP_tm_prob &p, BCP_tm_node *node)
void pack(BCP_buffer &buf)
Pack the parameter set into the buffer.
BCP_vec< std::pair< int, int > >::iterator BCP_tm_identify_process(BCP_vec< std::pair< int, int > > &proclist, int proc)
The name of the executable that&#39;s running (and that should be spawned on the other processors...
Indicates whether to debug Variable Generator processes or not.
char param(BCP_tm_par::chr_params key) const
Definition: BCP_tm.hpp:298
BCP_parameter_set< BCP_ts_par > ts
Definition: BCP_tm.hpp:59
The node is infeasible.
The number of Cut Pool processes that should be spawned.
Indicates whether to debug LP processes or not.
The message contains a new MIP feasible solution.
void BCP_tm_remove_cg(BCP_tm_prob &p, const int index)
virtual void multicast(int num, const int *targets, const BCP_message_tag tag)=0
Send an empty message (message tag only) to all the processes in the process array.
bool BCP_tm_test_machine(BCP_tm_prob &p)
This is the abstract base class for a solution to a Mixed Integer Programming problem.
void BCP_tm_rebroadcast_root_warmstart(BCP_tm_prob &p)
The number of LP processes that should be spawned.