14#ifndef OR_TOOLS_UTIL_MONOID_OPERATION_TREE_H_
15#define OR_TOOLS_UTIL_MONOID_OPERATION_TREE_H_
21#include "absl/strings/str_format.h"
66 const T&
result()
const {
return *result_; }
69 void Reset(
int argument_index);
72 void Set(
int argument_index,
const T& argument);
79 return nodes_[PositionOfLeaf(argument_index)];
83 template <
class Diver>
92 static int ComputeLeafOffset(
int size);
96 static int ComputeNumberOfNodes(
int leaf_offset);
100 void ComputeAbove(
int position);
103 void Compute(
int position);
106 int PositionOfLeaf(
int index)
const {
return leaf_offset_ +
index; }
109 bool IsLeaf(
int position)
const {
return position >= leaf_offset_; }
112 int ArgumentIndexOfLeafPosition(
int position)
const {
113 DCHECK(IsLeaf(position));
114 return position - leaf_offset_;
117 template <
class Diver>
118 void DiveInTree(
int position, Diver* diver)
const;
120 static int father(
int pos) {
return (pos - 1) >> 1; }
121 static int left(
int pos) {
return (pos << 1) + 1; }
122 static int right(
int pos) {
return (pos + 1) << 1; }
129 const int leaf_offset_;
132 const int num_nodes_;
135 std::vector<T> nodes_;
146int MonoidOperationTree<T>::ComputeLeafOffset(
int size) {
147 int smallest_pow_two_not_less_than_size = 1;
148 while (smallest_pow_two_not_less_than_size <
size) {
149 smallest_pow_two_not_less_than_size <<= 1;
151 return std::max(1, smallest_pow_two_not_less_than_size - 1);
155int MonoidOperationTree<T>::ComputeNumberOfNodes(
int leaf_offset) {
157 DCHECK_EQ(0, (leaf_offset) & (leaf_offset + 1));
158 const int num_leaves = leaf_offset + 1;
159 const int num_nodes = leaf_offset + num_leaves;
160 DCHECK_GE(num_nodes, 3);
167 leaf_offset_(ComputeLeafOffset(
size)),
168 num_nodes_(ComputeNumberOfNodes(leaf_offset_)),
169 nodes_(num_nodes_, T()),
170 result_(&(nodes_[0])) {}
174 const int size = nodes_.size();
175 nodes_.assign(
size, T());
180 Set(argument_index, T());
185 CHECK_LT(argument_index, size_);
186 const int position = leaf_offset_ + argument_index;
187 nodes_[position] = argument;
188 ComputeAbove(position);
193 int pos = father(position);
202void MonoidOperationTree<T>::Compute(
int position) {
203 const T& left_child = nodes_[left(position)];
212 for (
int i = 0; i < num_nodes_; ++i) {
213 if (((i + 1) & i) == 0) {
215 absl::StrAppendFormat(&out,
"-------------- Layer %d ---------------\n",
219 absl::StrAppendFormat(&out,
"Position %d: %s\n", i,
220 nodes_[i].DebugString());
226template <
class Diver>
229 if (IsLeaf(position)) {
230 const int index = ArgumentIndexOfLeafPosition(position);
231 const T& argument = nodes_[position];
232 diver->OnArgumentReached(
index, argument);
234 const T& current = nodes_[position];
235 const T& left_child = nodes_[left(position)];
237 if (diver->ChooseGoLeft(current, left_child,
right_child)) {
239 DiveInTree(left(position), diver);
241 diver->OnComeBackFromLeft(current, left_child,
right_child);
244 DiveInTree(right(position), diver);
246 diver->OnComeBackFromRight(current, left_child,
right_child);
const T & GetOperand(int argument_index) const
Returns the leaf node corresponding to the given argument index.
MonoidOperationTree(const MonoidOperationTree &)=delete
This type is neither copyable nor movable.
void Reset(int argument_index)
Resets the argument of given index.
void Set(int argument_index, const T &argument)
Sets the argument of given index.
void Clear()
Resets all arguments.
MonoidOperationTree & operator=(const MonoidOperationTree &)=delete
std::string DebugString() const
MonoidOperationTree(int size)
Constructs a MonoidOperationTree able to store 'size' operands.
void DiveInTree(Diver *const diver) const
Dive down a branch of the operation tree, and then come back up.
const T & result() const
Returns the root of the tree, containing the result of the operation.
In SWIG mode, we don't want anything besides these top-level includes.