BCP_tm_functions.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 #include <cstdio>
4 #include "BCP_os.hpp"
5 #include "BCP_error.hpp"
6 #include "BCP_node_change.hpp"
7 #include "BCP_enum_tm.hpp"
8 #include "BCP_tm.hpp"
9 #include "BCP_tm_functions.hpp"
10 
12 
13 //#############################################################################
14 
16 BCP_tm_identify_process(BCP_vec< std::pair<int,int> >& proclist, int proc)
17 {
18  BCP_vec< std::pair<int,int> >::iterator proci = proclist.begin();
19  BCP_vec< std::pair<int,int> >::iterator lastproci = proclist.end();
20  while (proci != lastproci) {
21  if (proci->first == proc)
22  break;
23  ++proci;
24  }
25  return proci;
26 }
27 
28 //#############################################################################
29 
30 bool
32 {
33  int lp = -1;
34  int cg = -1;
35  int vg = -1;
36  int cp = -1;
37  int vp = -1;
38  bool so_far_so_good = true;
39 
40  if (so_far_so_good) {
42  if (lp == -1)
43  return false;
44  if (! p.msg_env->alive(lp)) {
45  BCP_tm_remove_lp(p, lp);
46  return false;
47  }
48  }
49 
50 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
51  if (so_far_so_good && p.slaves.cg) {
52  cg = p.slaves.cg->get_free_proc();
53  if (cg == -1)
54  return false;
55  if (! p.msg_env->alive(cg)) {
56  BCP_tm_remove_cg(p, p.slaves.cg->index_of_proc(cg));
57  so_far_so_good = false;
58  }
59  }
60 
61  if (so_far_so_good && p.slaves.vg) {
62  vg = p.slaves.vg->get_free_proc();
63  if (vg == -1)
64  return false;
65  if (! p.msg_env->alive(vg)) {
66  BCP_tm_remove_vg(p, p.slaves.vg->index_of_proc(vg));
67  so_far_so_good = false;
68  }
69  }
70 
71  if (so_far_so_good && p.slaves.cp) {
72  while (true) {
73  cp = p.slaves.cp->get_free_proc();
74  if (cp == -1)
75  break;
76  if (p.msg_env->alive(cp))
77  break;
78  // *FIXME*
79  throw BCP_fatal_error("TM: A CP has died. Aborting...\n");
80  }
81  if (cp == -1) {
82  // if there is no free CP, just keep the old one
83  if (node->cp != -1 && ! p.msg_env->alive(node->cp)) {
84  // *FIXME*
85  throw BCP_fatal_error("TM: A CP has died. Aborting...\n");
86  }
87  } else {
88  if (node->cp != -1 && ! p.msg_env->alive(node->cp)) {
89  // *FIXME*
90  throw BCP_fatal_error("TM: A CP has died. Aborting...\n");
91  }
92  }
93  }
94 
95  if (so_far_so_good && p.slaves.vp) {
96  while (true) {
97  vp = p.slaves.vp->get_free_proc();
98  if (vp == -1)
99  break;
100  if (p.msg_env->alive(vp))
101  break;
102  // *FIXME*
103  throw BCP_fatal_error("TM: A VP has died. Aborting...\n");
104  }
105  if (vp == -1) {
106  // if there is no free VP, just keep the old one
107  if (node->vp != -1 && ! p.msg_env->alive(node->vp)) {
108  // *FIXME*
109  throw BCP_fatal_error("TM: A VP has died. Aborting...\n");
110  }
111  } else {
112  if (node->vp != -1 && ! p.msg_env->alive(node->vp)) {
113  // *FIXME*
114  throw BCP_fatal_error("TM: A VP has died. Aborting...\n");
115  }
116  }
117  }
118 #endif
119 
120  if (! so_far_so_good)
121  return BCP_tm_assign_processes(p, node);
122 
123  node->lp = lp;
124  node->cg = cg;
125  node->vg = vg;
126  if (cp != -1) {
127  // *LATER* : copy the old CP over to the free one and let node have
128  // this new CP.
129  node->cp = cp;
130  }
131  if (vp != -1) {
132  // *LATER* : copy the old VP over to the free one and let node have
133  // this new VP.
134  node->vp = vp;
135  }
136 
137  return true;
138 }
139 
140 //#############################################################################
141 
143 {
144  for (int i = p.nodes_to_free.size() - 1; i >= 0; --i) {
147  }
148  p.nodes_to_free.clear();
149 }
150 
151 //#############################################################################
152 
153 static inline BCP_node_start_result
155 {
156  BCP_tm_node* next_node;
157 
158  while (true){
159  if (p.candidate_list.empty()) {
161  return BCP_NodeStart_NoNode;
162  }
163  next_node = dynamic_cast<BCP_tm_node*>(p.candidate_list.top());
164  p.candidate_list.pop();
165 
166  // if no UB yet or lb is lower than UB then go ahead
167  if (! p.has_ub())
168  break;
169 
170  bool process_this = true;
171 
172  if (next_node->getTrueLB() > p.ub() - p.granularity())
173  process_this = false;
174  if (next_node->getTrueLB() >
176  process_this = false;
177  if (next_node->getTrueLB() >
179  process_this = false;
180 
181  if (process_this)
182  break;
183 
184  // ok, so we do have an UB and true lb is "higher" than the UB.
186  // nothing is left to price or in this phase we just fathom the
187  // over-the-bound nodes. in either case this node can be pruned
188  // right here.
189  next_node->status = BCP_PrunedNode_OverUB;
191  printf("TM: Pruning NODE %i LEVEL %i instead of sending it.\n",
192  next_node->index(), next_node->getDepth());
193  p.nodes_to_free.push_back(next_node);
195  continue;
196  }
198  // the node would be sent back from the LP right away. save the
199  // trouble and don't even send it out
200  p.next_phase_nodes.push_back(next_node);
201  next_node->status = BCP_NextPhaseNode_OverUB;
203  printf("\
204 TM: Moving NODE %i LEVEL %i into the next phase list \n\
205  instead of sending it.\n",
206  next_node->index(), next_node->getDepth());
207  continue;
208  }
209  // must be BCP_GenerateColumns
210  // all right, we want to send it out anyway for pricing
211  break;
212  }
213 
214  // assign processes to the node and send it off
215  if (! BCP_tm_assign_processes(p, next_node)) {
216  // couldn't find free processes
217  p.candidate_list.push(next_node, false);
219  return BCP_NodeStart_Error;
220  }
221 
222  p.active_nodes[next_node->lp] = next_node;
223  next_node->status = BCP_ActiveNode;
226  }
227  BCP_tm_node_to_send* node_to_send =
228  new BCP_tm_node_to_send(p, next_node, BCP_Msg_ActiveNodeData);
229  if (node_to_send->send()) {
230  delete node_to_send;
231  }
232 
233 #ifdef BCP__DUMP_PROCINFO
234 #if (BCP__DUMP_PROCINFO == 1)
235  dump_procinfo(p, "start_one_node()");
236 #endif
237 #endif
238 
239  return BCP_NodeStart_OK;
240 }
241 
242 #ifdef BCP__DUMP_PROCINFO
243 #if (BCP__DUMP_PROCINFO == 1)
244 void dump_procinfo(BCP_tm_prob& p, const char* str)
245 {
246  printf("TM: ***** dump_procinfo from %s *********\n", str);
247  printf("TM: ********** Active nodes *********\n");
248  for (int i = 0; i < p.slaves.lp->size(); ++i) {
249  if (p.active_nodes[i])
250  printf("TM: %i, %i, %i\n",
251  i, p.active_nodes[i]->index(), p.active_nodes[i]->lp);
252  else
253  printf("TM: %i, %i, %i\n",
254  i, -1, -1);
255 
256  }
257  printf("TM: ********** All nodes *********\n");
258  for (int i = 0; i < p.search_tree.size(); ++i) {
259  printf("TM: %i, %i\n", i, p.search_tree[i]->lp);
260  }
261 }
262 #endif
263 #endif
264 
265 //#############################################################################
266 
268 {
269  while (p.lp_scheduler.has_free_node_id()) {
270  switch (BCP_tm_start_one_node(p)){
272  return BCP_NodeStart_NoNode;
273  case BCP_NodeStart_Error:
274  if (p.lp_scheduler.has_free_node_id()) {
275  throw BCP_fatal_error("\
276 TM: couldn't start new node but there's a free LP ?!\n");
277  }
278  break;
279  case BCP_NodeStart_OK:
280  break;
281  }
282  }
284  return BCP_NodeStart_OK;
285 }
286 
287 //#############################################################################
288 
290 {
291  /* FIXME: must walk through the siblings... */
292 #if 0
293  CoinSearchTreeBase& candidates = *p.candidate_list.getTree();
294  const int n = candidates.size();
295  const std::vector<CoinTreeNode*>& nodes = candidates.getNodes();
296  for (int i = 0; i < n; ++i) {
297  printf("%5i", dynamic_cast<BCP_tm_node*>(nodes[i])->index());
298  }
299  printf("\n");
300 #endif
301 }
302 
303 //#############################################################################
304 
306 {
308 
310  int i;
315  char treestat = tmpar.entry(BCP_tm_par::TmVerb_FinalStatistics);
316  char bestsol = tmpar.entry(BCP_tm_par::TmVerb_BestFeasibleSolution);
318  if (tmpar.entry(static_cast<BCP_tm_par::chr_params>(i)) == 2) {
319  tmpar.set_entry(static_cast<BCP_tm_par::chr_params>(i), true);
320  } else {
321  tmpar.set_entry(static_cast<BCP_tm_par::chr_params>(i), false);
322  }
323  }
325  if (lppar.entry(static_cast<BCP_lp_par::chr_params>(i)) == 2) {
326  lppar.set_entry(static_cast<BCP_lp_par::chr_params>(i), true);
327  } else {
328  lppar.set_entry(static_cast<BCP_lp_par::chr_params>(i), false);
329  }
330  }
332  if (cgpar.entry(static_cast<BCP_cg_par::chr_params>(i)) == 2) {
333  cgpar.set_entry(static_cast<BCP_cg_par::chr_params>(i), true);
334  } else {
335  cgpar.set_entry(static_cast<BCP_cg_par::chr_params>(i), false);
336  }
337  }
338  /*
339  for (i = BCP_vg_par::VgVerb_First+1; i < BCP_vg_par::VgVerb_Last; ++i){
340  vgpar.set_entry(static_cast<BCP_vg_par::chr_params>(i), false);
341  }
342  */
347  } else {
349  }
352  } else {
354  }
357  } else {
359  }
362  } else {
364  }
365  }
366  if (p.param(BCP_tm_par::MaxHeapSize) == 0) {
367  long fm = BCP_free_mem();
368  fm = fm == -1 ? 192 * (1<<20) /* 192M */ : fm;
371  }
372 }
373 
374 //#############################################################################
375 // A little bit of sanity check
376 
378 {
379 }
380 
BCP_tree search_tree
Definition: BCP_tm.hpp:239
Just a marker for the first CgVerb.
BCP_parameter_set< BCP_vg_par > vg
Definition: BCP_tm.hpp:67
BCP_parameter_set< BCP_cg_par > cg
Definition: BCP_tm.hpp:65
Just a marker for the first LpVerb.
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
void clear()
Delete every entry.
Print out a message when the default version of an overridable method is executed.
Print out a message when the default version of an overridable method is executed.
Do not generate columns, but send back the node to the Tree Manager for processing in the next phase...
Definition: BCP_enum.hpp:70
double granularity() const
Definition: BCP_tm.hpp:313
Print information about nodes that are pruned by bound in the tree manager.
bool has_free_node_id() const
Decide if there is an id that can be returned for processin a node.
Definition: BCP_process.hpp:91
Print out a message when the default version of an overridable method is executed.
BCP_tm_node_status status
Definition: BCP_tm_node.hpp:78
void BCP_tm_list_candidates(BCP_tm_prob &p)
double ub() const
Definition: BCP_tm.hpp:321
char entry(const chr_params key) const
TM sends the description of a new search tree node.
size_t size() const
iterator begin()
Return an iterator to the beginning of the object.
Definition: BCP_vector.hpp:99
CoinSearchTreeManager candidate_list
Definition: BCP_tm.hpp:243
BCP_vec< BCP_tm_node * > next_phase_nodes
a vector of nodes to be processed in the next phase
Definition: BCP_tm.hpp:250
The maximum size of the memory heap the TS can use.
Indicates whether message passing is serial (all processes are on the same processor) or not...
Just a marker for the last TmVerb.
int index() const
void push_back(const_reference x)
Append x to the end of the vector.
void BCP_tm_remove_vg(BCP_tm_prob &p, const int index)
static BCP_node_start_result BCP_tm_start_one_node(BCP_tm_prob &p)
void BCP_tm_remove_lp(BCP_tm_prob &p, const int index)
??? Values: Default:
bool BCP_tm_assign_processes(BCP_tm_prob &p, BCP_tm_node *node)
BCP_vec< BCP_tm_node * > nodes_to_free
Definition: BCP_tm.hpp:252
BCP_node_start_result BCP_tm_start_new_nodes(BCP_tm_prob &p)
void fint fint fint real fint real real real real real real real real real fint real fint * lp
void set_entry(const chr_params key, const char val)
NO OLD DOC.
Definition: BCP_tm.hpp:136
int request_node_id()
Request an id for processing nodes.
BCP_node_start_result
This enumerative constant describes ...
Definition: BCP_enum_tm.hpp:19
BCP_parameter_set< BCP_tm_par > par
Definition: BCP_tm.hpp:168
Print out a message when the default version of an overridable method is executed.
Verbosity flags for the tree manager.
void BCP_sanity_checks(BCP_tm_prob &p)
void BCP_print_memusage(BCP_tm_prob &p)
bool has_ub() const
Definition: BCP_tm.hpp:319
Just a marker for the last LpVerb.
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
The maximum size of the memory heap the TM can use.
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
Invoke &quot;display_feasible_solution&quot; user routine for the best feasible solution after the entire tree ...
The class BCP_vec serves the same purpose as the vector class in the standard template library...
Definition: BCP_vector.hpp:24
Do fathom the node.
Definition: BCP_enum.hpp:67
void BCP_tm_remove_explored(BCP_tm_prob &p, BCP_tm_node *node)
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
Print statistics: running time, tree size, best solution value.
Just a marker for the last CgVerb.
BCP_slave_params slave_pars
Definition: BCP_tm.hpp:170
A flag that instructs BCP to be (almost) absolutely silent.
virtual bool alive(const int pid)=0
Test if the process given by the argument is alive or not.
BCP_column_generation current_phase_colgen
Definition: BCP_tm.hpp:216
static void BCP_tm_free_nodes(BCP_tm_prob &p)
void BCP_tm_modify_pool_counters(BCP_tm_prob &p, BCP_tm_node *node)
void fint * n
BCP_vec< std::pair< int, int > >::iterator BCP_tm_identify_process(BCP_vec< std::pair< int, int > > &proclist, int proc)
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
BCP_parameter_set< BCP_ts_par > ts
Definition: BCP_tm.hpp:59
static long BCP_free_mem()
Definition: BCP_os.hpp:38
void BCP_tm_remove_cg(BCP_tm_prob &p, const int index)
void BCP_check_parameters(BCP_tm_prob &p)