BCP_tm_trimming.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_tm.hpp"
5 #include "BCP_tm_functions.hpp"
6 
7 static int BCP_tm_trim_tree(BCP_tm_prob& p, BCP_tm_node* node,
8  const bool between_phases);
9 
10 //#############################################################################
11 // For now we'll trim the tree only between phases when nothing is processed.
12 // Reason: It's kinda ugly to cut off a subtree when several of its nodes
13 // might be processed. Nevertheless, this should be done sooner or later.
14 //
15 // *THINK*
16 //#############################################################################
17 
18 void BCP_tm_trim_tree_wrapper(BCP_tm_prob& p, const bool between_phases)
19 {
20  BCP_tree& tree = p.search_tree;
21  BCP_tm_node* root = tree.root();
22  tree.enumerate_leaves(root, p.ub() - p.granularity());
23  const int trimmed =
24  BCP_tm_trim_tree(p, root, true /* called between phases */);
26  printf("\
27 TM: before starting the new phase, \n\
28  %i nodes were trimmed from the tree.\n", trimmed);
29  }
30 
33  BCP_tm_node * node;
34 
35  // clean up the next phase nodes
36  nodep = p.next_phase_nodes.begin();
37  lastnodep = p.next_phase_nodes.end();
38  while (nodep != lastnodep) {
39  if ((*nodep)->index() == -1) {
40  *nodep = *--lastnodep;
42  } else {
43  ++nodep;
44  }
45  }
46 
47  // FIXME: Why is this block necessary?
48  // clean up the list of candidates
49  if (! p.candidate_list.empty()) {
51  while (! p.candidate_list.empty()) {
52  CoinTreeNode* coinnode = p.candidate_list.top();
53  node = dynamic_cast<BCP_tm_node*>(coinnode);
54  if (node->index() != -1)
55  cands.push_back(node);
56  p.candidate_list.pop();
57  }
58  lastnodep = cands.end();
59  for (nodep = cands.begin(); nodep != lastnodep; ++nodep)
60  p.candidate_list.push(*nodep);
61  }
62 
63  // clean up the tree
64  nodep = p.search_tree.begin();
65  lastnodep = p.search_tree.end();
66  while (nodep != lastnodep) {
67  node = *nodep;
68  if (node->index() == -1) {
69  // The search tree node is in a subtree that is trimmed
70 #ifdef BCP_DEBUG
71  if (node->lp != -1 || node->cg != -1 || node->vg != -1)
72  throw BCP_fatal_error("\
73 TM: At least on of lp/cg/vg of a trimmed node is non-0.\n");
74 #endif
75  if (node->cp != -1 && node->child_num() == 0) {
76  BCP_vec< std::pair<int, int> >::iterator proc =
78 #ifdef BCP_DEBUG
79  if (proc == p.leaves_per_cp.end())
80  throw BCP_fatal_error("\
81 TM: non-existing CP is assigned to a leaf.\n");
82 #endif
83  --proc->second;
84  }
85  if (node->vp != -1 && node->child_num() == 0) {
86  BCP_vec< std::pair<int, int> >::iterator proc =
88 #ifdef BCP_DEBUG
89  if (proc == p.leaves_per_vp.end())
90  throw BCP_fatal_error("\
91 TM: non-existing VP is assigned to a leaf.\n");
92 #endif
93  --proc->second;
94  }
95  delete node;
96  *nodep = 0;
97  }
98  ++nodep;
99  }
100 
101 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
102  // scan through the CP and VP list to mark the free ones
103  BCP_vec< std::pair<int, int> >::iterator proc;
104  BCP_vec< std::pair<int, int> >::iterator lastproc;
105 
106  lastproc = p.leaves_per_cp.end();
107  for (proc = p.leaves_per_cp.begin(); proc != lastproc; ++proc)
108  if (proc->second == 0)
109  p.slaves.cp->set_proc_free(proc->first);
110 
111  lastproc = p.leaves_per_vp.end();
112  for (proc = p.leaves_per_vp.begin(); proc != lastproc; ++proc)
113  if (proc->second == 0)
114  p.slaves.vp->set_proc_free(proc->first);
115 #endif
116 }
117 
118 //#############################################################################
119 // We will trim very conservatively
120 
122  const bool between_phases)
123 {
124  bool trim = true;
125  int trimmed = 0;
126 
127  if (node->_processed_leaf_num > 0) {
128  // if there is a node currently processed in the subtree then don't
129  // trim here
130  trim = false;
131  } else if (node->child_num() == 0) {
132  // if this is a leaf then there is no point in trimming
133  trim = false;
134  } else if (node->_leaf_num - node->_pruned_leaf_num <= 2) {
135  // if there are no more than 2 nodes further down that have to be taken
136  // care of then don't trim
137  trim = false;
138  } else if (node->getTrueLB() < p.ub() - p.granularity()) {
139  // don't trim if the gap at this node is not below the granularity
140  trim = false;
141  }
142 
143  if (trim) {
144  trimmed = node->mark_descendants_for_deletion();
145  if (node->cp != -1) {
146  BCP_vec< std::pair<int, int> >::iterator proc =
148 #ifdef BCP_DEBUG
149  if (proc == p.leaves_per_cp.end())
150  throw BCP_fatal_error("\
151 TM: An internal node is assigned to a non-existing CP.\n");
152 #endif
153  ++proc->second;
154  }
155  if (node->vp != -1) {
156  BCP_vec< std::pair<int, int> >::iterator proc =
158 #ifdef BCP_DEBUG
159  if (proc == p.leaves_per_vp.end())
160  throw BCP_fatal_error("\
161 TM: An internal node is assigned to a non-existing VP.\n");
162 #endif
163  ++proc->second;
164  }
165  } else {
166  // try to trim at the children
169  node->_children.end();
170  for (child = node->_children.begin(); child != lastchild; ++child)
171  trimmed += BCP_tm_trim_tree(p, *child, between_phases);
172  }
173 
174  return trimmed;
175 }
176 
177 //#############################################################################
178 // This routine will delete a node (which must be a leaf)
179 
181 {
183  return;
184 
185  if (node->child_num() == 0) {
186  BCP_tm_node* parent = node->parent();
187  p.search_tree.remove(node->index());
188  delete node;
189 
190  if (parent) {
191  parent->remove_child(node);
192  BCP_tm_remove_explored(p, parent);
193  }
194  }
195 }
196 
197 //#############################################################################
BCP_tree search_tree
Definition: BCP_tm.hpp:239
int _pruned_leaf_num
Definition: BCP_tm_node.hpp:93
Print the number of nodes trimmed between phases.
void remove(int index)
Return the worst true lower bound in the search tree.
double granularity() const
Definition: BCP_tm.hpp:313
BCP_vec< BCP_tm_node * > _children
Definition: BCP_tm_node.hpp:87
void enumerate_leaves(BCP_tm_node *node, const double obj_limit)
Return the worst true lower bound in the search tree.
double ub() const
Definition: BCP_tm.hpp:321
BCP_vec< std::pair< int, int > > leaves_per_cp
Definition: BCP_tm.hpp:259
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
BCP_vec< BCP_tm_node * >::iterator end()
NO OLD DOC.
BCP_tm_node * parent()
int index() const
void push_back(const_reference x)
Append x to the end of the vector.
BCP_vec< BCP_tm_node * >::iterator begin()
int child_num() const
void pop_back()
Delete the last entry.
BCP_vec< std::pair< int, int > > leaves_per_vp
Definition: BCP_tm.hpp:261
NO OLD DOC.
Definition: BCP_tm.hpp:136
void BCP_tm_trim_tree_wrapper(BCP_tm_prob &p, const bool between_phases)
int mark_descendants_for_deletion()
Definition: BCP_tm_node.cpp:61
int _processed_leaf_num
Definition: BCP_tm_node.hpp:91
BCP_tm_node * root()
void remove_child(BCP_tm_node *node)
Definition: BCP_tm_node.cpp:79
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
Indicates whether that part of the tree that&#39;s completely explored should be freed as soon as possibl...
iterator end()
Return an iterator to the end of the object.
Definition: BCP_vector.hpp:104
The class BCP_vec serves the same purpose as the vector class in the standard template library...
Definition: BCP_vector.hpp:24
void BCP_tm_remove_explored(BCP_tm_prob &p, BCP_tm_node *node)
static int BCP_tm_trim_tree(BCP_tm_prob &p, BCP_tm_node *node, const bool between_phases)
BCP_vec< std::pair< int, int > >::iterator BCP_tm_identify_process(BCP_vec< std::pair< int, int > > &proclist, int proc)
char param(BCP_tm_par::chr_params key) const
Definition: BCP_tm.hpp:298