14#ifndef OR_TOOLS_UTIL_FIXED_SHAPE_BINARY_TREE_H_
15#define OR_TOOLS_UTIL_FIXED_SHAPE_BINARY_TREE_H_
20#include "absl/log/check.h"
21#include "absl/numeric/bits.h"
54 : largest_leaf_index_(num_leaves - 1) {
55 max_depth_ = absl::bit_width(
56 static_cast<unsigned int>(2 * largest_leaf_index_.value() + 1));
57 leave_start_index_ = 1 << (max_depth_ - 1);
64 return leave_start_index_ - 1;
69 bool IsLeaf(TreeNodeIndex node)
const {
return node >= leave_start_index_; }
71 TreeNodeIndex
Root()
const {
return TreeNodeIndex(1); }
74 return TreeNodeIndex(leave_start_index_);
78 return leave_start_index_ + largest_leaf_index_.value();
83 return TreeNodeIndex(node.value() << 1);
88 return TreeNodeIndex(node.value() << 1) + TreeNodeIndex(1);
91 TreeNodeIndex
Parent(TreeNodeIndex node)
const {
92 DCHECK_NE(node,
Root());
93 return TreeNodeIndex(node.value() >> 1);
96 TreeNodeIndex
Sibling(TreeNodeIndex node)
const {
97 DCHECK_NE(node,
Root());
98 return TreeNodeIndex(node.value() ^ 1);
102 const LeafIndex ret = LeafIndex((node - leave_start_index_).value());
103 if (ret > largest_leaf_index_) {
104 return LeafIndex(-1);
110 int Depth(TreeNodeIndex node)
const {
111 return absl::bit_width(
static_cast<unsigned int>(node.value())) - 1;
116 std::pair<LeafIndex, LeafIndex>
GetInterval(TreeNodeIndex node)
const {
118 const LeafIndex leaf_value =
LeafValue(node);
119 return {leaf_value, leaf_value};
121 const int depth =
Depth(node);
122 const int pos = node.value() - (1 << depth);
123 const int min = pos << (max_depth_ - depth - 1);
124 if (min > largest_leaf_index_) {
125 return {LeafIndex(-1), LeafIndex(-1)};
127 const int max = ((pos + 1) << (max_depth_ - depth - 1)) - 1;
128 return {LeafIndex(min),
129 LeafIndex(std::min(max, largest_leaf_index_.value()))};
143 LeafIndex last_leaf)
const {
144 DCHECK_LE(first_leaf, last_leaf);
145 DCHECK_GE(first_leaf, 0);
146 DCHECK_LE(last_leaf, largest_leaf_index_);
148 if (last_leaf == largest_leaf_index_) {
152 last_leaf = (1 << (max_depth_ - 1)) - 1;
154 if (first_leaf == last_leaf) {
165 const int power_of_two_div =
166 absl::countr_zero(
static_cast<unsigned int>(first_leaf.value()));
167 const int log2_size = absl::bit_width(
static_cast<unsigned int>(
168 last_leaf.value() - first_leaf.value() + 1)) -
170 const int height = std::min(log2_size, power_of_two_div);
171 const int pos = first_leaf.value() >> height;
172 const int depth = max_depth_ - height - 1;
174 start = (1 << depth) + pos;
187 LeafIndex last_leaf)
const {
188 DCHECK_LT(first_leaf, last_leaf);
189 DCHECK_GE(first_leaf, 0);
190 DCHECK_LE(last_leaf, largest_leaf_index_);
192 if (first_leaf == last_leaf) {
203 const int log2_size = absl::bit_width(
static_cast<unsigned int>(
204 last_leaf.value() - first_leaf.value() + 1)) -
206 const int power_of_two_div =
207 absl::countr_zero(
static_cast<unsigned int>(last_leaf.value() + 1));
208 const int height = std::min(log2_size, power_of_two_div);
209 const int pos = last_leaf.value() >> height;
210 const int depth = max_depth_ - height - 1;
211 TreeNodeIndex int_end;
212 int_end = (1 << depth) + pos;
218 template <
typename TypeWithPushBack>
220 TypeWithPushBack* result)
const {
221 DCHECK_LE(first_leaf, last_leaf);
222 TreeNodeIndex prev(0);
224 if (current ==
Root()) {
225 result->push_back(current);
230 if (min >= first_leaf && max <= last_leaf) {
231 result->push_back(current);
232 if (max == last_leaf) {
236 current =
Parent(current);
239 if (prev == TreeNodeIndex(0)) {
241 current =
Parent(current);
242 }
else if (prev !=
Root() && current ==
Parent(prev)) {
250 current =
Parent(current);
256 current =
Parent(current);
258 DCHECK_EQ(prev,
Parent(current));
266 TreeNodeIndex
GetLeaf(LeafIndex value)
const {
267 return leave_start_index_ + value.value();
271 TreeNodeIndex leave_start_index_;
272 LeafIndex largest_leaf_index_;
TreeNodeIndex GetNodeEndOfRange(LeafIndex first_leaf, LeafIndex last_leaf) const
int Depth(TreeNodeIndex node) const
Zero for the root.
TreeNodeIndex FirstLeafNode() const
TreeNodeIndex Parent(TreeNodeIndex node) const
void PartitionIntervalIntoNodes(LeafIndex first_leaf, LeafIndex last_leaf, TypeWithPushBack *result) const
TreeNodeIndex GetLeaf(LeafIndex value) const
TreeNodeIndex Sibling(TreeNodeIndex node) const
bool IsLeaf(TreeNodeIndex node) const
TreeNodeIndex Root() const
TreeNodeIndex RightChild(TreeNodeIndex node) const
TreeNodeIndex GetNodeStartOfRange(LeafIndex first_leaf, LeafIndex last_leaf) const
FixedShapeBinaryTree(LeafIndex num_leaves)
TreeNodeIndex HighestIntermediateNodeIndex() const
If you want to use a different storage for intermediate nodes and leaves.
TreeNodeIndex LeftChild(TreeNodeIndex node) const
std::pair< LeafIndex, LeafIndex > GetInterval(TreeNodeIndex node) const
LeafIndex LeafValue(TreeNodeIndex node) const
TreeNodeIndex HighestNodeIndex() const
TreeNodeIndex LastLeafNode() const
In SWIG mode, we don't want anything besides these top-level includes.
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)