00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef OR_TOOLS_UTIL_MONOID_OPERATION_TREE_H_
00015 #define OR_TOOLS_UTIL_MONOID_OPERATION_TREE_H_
00016
00017 #include <algorithm>
00018 #include <string>
00019
00020 #include "base/logging.h"
00021 #include "base/macros.h"
00022 #include "base/scoped_ptr.h"
00023 #include "base/stringprintf.h"
00024
00025 namespace operations_research {
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 template<class T>
00057 class MonoidOperationTree {
00058 public:
00059
00060 explicit MonoidOperationTree(int size);
00061 virtual ~MonoidOperationTree() {}
00062
00063
00064 const T& result() const { return *result_; }
00065
00066
00067 void Reset(int argument_index);
00068
00069
00070 void Set(int argument_index, const T& argument);
00071
00072
00073 void Clear();
00074
00075
00076 const T& GetOperand(int argument_index) const {
00077 return nodes_[PositionOfLeaf(argument_index)];
00078 }
00079
00080
00081 template <class Diver>
00082 void DiveInTree(Diver* diver) const {
00083 DiveInTree(0, diver);
00084 }
00085
00086 string DebugString() const;
00087
00088 private:
00089
00090 static int ComputeLeafOffset(int size);
00091
00092
00093
00094 static int ComputeNumberOfNodes(int leaf_offset);
00095
00096
00097
00098 void ComputeAbove(int position);
00099
00100
00101 void Compute(int position);
00102
00103
00104 int PositionOfLeaf(int index) const { return leaf_offset_ + index; }
00105
00106
00107 bool IsLeaf(int position) const { return position >= leaf_offset_; }
00108
00109
00110 int ArgumentIndexOfLeafPosition(int position) const {
00111 DCHECK(IsLeaf(position));
00112 return position - leaf_offset_;
00113 }
00114
00115 template <class Diver>
00116 void DiveInTree(int position, Diver* diver) const;
00117
00118 static int father(int pos) { return (pos - 1) >> 1; }
00119 static int left(int pos) { return (pos << 1) + 1; }
00120 static int right(int pos) { return (pos + 1) << 1; }
00121
00122
00123
00124 const int size_;
00125
00126
00127 const int leaf_offset_;
00128
00129
00130 const int num_nodes_;
00131
00132
00133 scoped_array<T> nodes_;
00134
00135
00136 T const * result_;
00137
00138
00139 const T identity_;
00140
00141 DISALLOW_COPY_AND_ASSIGN(MonoidOperationTree);
00142 };
00143
00144
00145
00146
00147
00148 template<class T>
00149 int MonoidOperationTree<T>::ComputeLeafOffset(int size) {
00150 int smallest_pow_two_not_less_than_size = 1;
00151 while (smallest_pow_two_not_less_than_size < size) {
00152 smallest_pow_two_not_less_than_size <<= 1;
00153 }
00154 return std::max(1, smallest_pow_two_not_less_than_size - 1);
00155 }
00156
00157 template<class T>
00158 int MonoidOperationTree<T>::ComputeNumberOfNodes(int leaf_offset) {
00159
00160 DCHECK_EQ(0, (leaf_offset) & (leaf_offset+1));
00161 const int num_leaves = leaf_offset + 1;
00162 const int num_nodes = leaf_offset + num_leaves;
00163 DCHECK_GE(num_nodes, 3);
00164 return num_nodes;
00165 }
00166
00167 template<class T>
00168 MonoidOperationTree<T>::MonoidOperationTree(int size)
00169 : size_(size),
00170 leaf_offset_(ComputeLeafOffset(size)),
00171 num_nodes_(ComputeNumberOfNodes(leaf_offset_)),
00172 nodes_(new T[num_nodes_]),
00173 result_(& (nodes_[0])),
00174
00175 identity_() {
00176
00177 for (int i = 0; i < num_nodes_; ++i) {
00178 nodes_[i].Set(identity_);
00179 }
00180 }
00181
00182 template<class T>
00183 void MonoidOperationTree<T>::Clear() {
00184
00185 const int num_used_nodes = leaf_offset_ + size_;
00186 for (int i = 0; i < num_used_nodes; ++i) {
00187 nodes_[i].Set(identity_);
00188 }
00189 }
00190
00191 template<class T>
00192 void MonoidOperationTree<T>::Reset(int argument_index) {
00193 Set(argument_index, identity_);
00194 }
00195
00196 template<class T>
00197 void MonoidOperationTree<T>::Set(int argument_index, const T& argument) {
00198 CHECK_LT(argument_index, size_);
00199 const int position = leaf_offset_ + argument_index;
00200 nodes_[position].Set(argument);
00201 ComputeAbove(position);
00202 }
00203
00204 template<class T>
00205 void MonoidOperationTree<T>::ComputeAbove(int position) {
00206 int pos = father(position);
00207 while (pos > 0) {
00208 Compute(pos);
00209 pos = father(pos);
00210 }
00211 Compute(0);
00212 }
00213
00214 template<class T>
00215 void MonoidOperationTree<T>::Compute(int position) {
00216 const T& left_child = nodes_[left(position)];
00217 const T& right_child = nodes_[right(position)];
00218 nodes_[position].Compute(left_child, right_child);
00219 }
00220
00221 template<class T>
00222 string MonoidOperationTree<T>::DebugString() const {
00223 string out;
00224 int layer = 0;
00225 for (int i = 0; i < num_nodes_; ++i) {
00226 if (((i+1) & i) == 0) {
00227
00228 StringAppendF(&out, "-------------- Layer %d ---------------\n", layer);
00229 ++layer;
00230 }
00231 StringAppendF(&out, "Position %d: %s\n", i,
00232 nodes_[i].DebugString().c_str());
00233 }
00234 return out;
00235 }
00236
00237 template <class T>
00238 template <class Diver>
00239 void MonoidOperationTree<T>::DiveInTree(int position, Diver* diver) const {
00240
00241 if (IsLeaf(position)) {
00242 const int index = ArgumentIndexOfLeafPosition(position);
00243 const T& argument = nodes_[position];
00244 diver->OnArgumentReached(index, argument);
00245 } else {
00246 const T& current = nodes_[position];
00247 const T& left_child = nodes_[left(position)];
00248 const T& right_child = nodes_[right(position)];
00249 if (diver->ChooseGoLeft(current, left_child, right_child)) {
00250
00251 DiveInTree(left(position), diver);
00252
00253 diver->OnComeBackFromLeft(current, left_child, right_child);
00254 } else {
00255
00256 DiveInTree(right(position), diver);
00257
00258 diver->OnComeBackFromRight(current, left_child, right_child);
00259 }
00260 }
00261 }
00262
00263 }
00264
00265 #endif // OR_TOOLS_UTIL_MONOID_OPERATION_TREE_H_