19#include "absl/log/check.h"
25template <
typename IntegerType>
28template <
typename IntegerType>
29typename ThetaLambdaTree<IntegerType>::TreeNode
30ThetaLambdaTree<IntegerType>::ComposeTreeNodes(
const TreeNode& left,
31 const TreeNode& right) {
32 return {std::max(right.envelope, left.envelope + right.sum_of_energy_min),
33 std::max(right.envelope_opt,
34 right.sum_of_energy_min +
35 std::max(left.envelope_opt,
36 left.envelope + right.max_of_energy_delta)),
37 left.sum_of_energy_min + right.sum_of_energy_min,
38 std::max(right.max_of_energy_delta, left.max_of_energy_delta)};
41template <
typename IntegerType>
44 leaf_nodes_have_delayed_operations_ =
false;
49 num_events_ = num_events;
50 num_leaves_ = std::max(2, num_events + (num_events & 1));
52 const int num_nodes = 2 * num_leaves_;
55 IntegerType{0}, IntegerType{0}});
61 for (power_of_two_ = 2; power_of_two_ < num_leaves_; power_of_two_ <<= 1) {
65template <
typename IntegerType>
66int ThetaLambdaTree<IntegerType>::GetLeafFromEvent(
int event)
const {
68 DCHECK_LT(event, num_events_);
72 const int r = power_of_two_ + event;
73 return r < 2 * num_leaves_ ? r : r - num_leaves_;
76template <
typename IntegerType>
77int ThetaLambdaTree<IntegerType>::GetEventFromLeaf(
int leaf)
const {
78 DCHECK_GE(leaf, num_leaves_);
79 DCHECK_LT(leaf, 2 * num_leaves_);
80 const int r = leaf - power_of_two_;
81 return r >= 0 ? r : r + num_leaves_;
84template <
typename IntegerType>
87 leaf_nodes_have_delayed_operations_ =
false;
90 const int last_internal_node = tree_.size() / 2 - 1;
91 for (
int node = last_internal_node; node >= 1; --node) {
92 const int right = 2 * node + 1;
93 const int left = 2 * node;
94 tree_[node] = ComposeTreeNodes(tree_[left], tree_[right]);
98template <
typename IntegerType>
100 int event, IntegerType initial_envelope, IntegerType energy_min,
101 IntegerType energy_max) {
103 leaf_nodes_have_delayed_operations_ =
true;
105 DCHECK_LE(0, energy_min);
106 DCHECK_LE(energy_min, energy_max);
107 const int node = GetLeafFromEvent(event);
108 tree_[node] = {initial_envelope + energy_min, initial_envelope + energy_max,
109 energy_min, energy_max - energy_min};
112template <
typename IntegerType>
114 int event, IntegerType initial_envelope, IntegerType energy_min,
115 IntegerType energy_max) {
116 DCHECK(!leaf_nodes_have_delayed_operations_);
117 DCHECK_LE(0, energy_min);
118 DCHECK_LE(energy_min, energy_max);
119 const int node = GetLeafFromEvent(event);
120 tree_[node] = {initial_envelope + energy_min, initial_envelope + energy_max,
121 energy_min, energy_max - energy_min};
125template <
typename IntegerType>
127 int event, IntegerType initial_envelope_opt, IntegerType energy_max) {
128 DCHECK(!leaf_nodes_have_delayed_operations_);
129 DCHECK_LE(0, energy_max);
130 const int node = GetLeafFromEvent(event);
132 initial_envelope_opt + energy_max, IntegerType{0}, energy_max};
136template <
typename IntegerType>
138 int event, IntegerType initial_envelope_opt, IntegerType energy_max) {
140 leaf_nodes_have_delayed_operations_ =
true;
142 DCHECK_LE(0, energy_max);
143 const int node = GetLeafFromEvent(event);
145 initial_envelope_opt + energy_max, IntegerType{0}, energy_max};
148template <
typename IntegerType>
150 DCHECK(!leaf_nodes_have_delayed_operations_);
151 const int node = GetLeafFromEvent(event);
158template <
typename IntegerType>
161 leaf_nodes_have_delayed_operations_ =
true;
163 const int node = GetLeafFromEvent(event);
169template <
typename IntegerType>
171 DCHECK(!leaf_nodes_have_delayed_operations_);
172 return tree_[1].envelope;
174template <
typename IntegerType>
176 DCHECK(!leaf_nodes_have_delayed_operations_);
177 return tree_[1].envelope_opt;
180template <
typename IntegerType>
182 IntegerType target_envelope)
const {
183 DCHECK(!leaf_nodes_have_delayed_operations_);
184 DCHECK_LT(target_envelope, tree_[1].envelope);
186 return GetEventFromLeaf(
187 GetMaxLeafWithEnvelopeGreaterThan(1, target_envelope, &unused));
190template <
typename IntegerType>
192 IntegerType target_envelope,
int* critical_event,
int* optional_event,
193 IntegerType* available_energy)
const {
194 DCHECK(!leaf_nodes_have_delayed_operations_);
197 GetLeavesWithOptionalEnvelopeGreaterThan(target_envelope, &critical_leaf,
198 &optional_leaf, available_energy);
199 *critical_event = GetEventFromLeaf(critical_leaf);
200 *optional_event = GetEventFromLeaf(optional_leaf);
203template <
typename IntegerType>
205 DCHECK(!leaf_nodes_have_delayed_operations_);
206 const int leaf = GetLeafFromEvent(event);
207 IntegerType envelope = tree_[leaf].envelope;
208 for (
int node = leaf; node > 1; node >>= 1) {
209 const int right = node | 1;
210 if (node != right) envelope += tree_[right].sum_of_energy_min;
215template <
typename IntegerType>
216void ThetaLambdaTree<IntegerType>::RefreshNode(
int node) {
217 TreeNode* tree = tree_.data();
219 const int right = node | 1;
220 const int left = right ^ 1;
222 tree[node] = ComposeTreeNodes(tree[left], tree[right]);
226template <
typename IntegerType>
227int ThetaLambdaTree<IntegerType>::GetMaxLeafWithEnvelopeGreaterThan(
228 int node, IntegerType target_envelope, IntegerType* extra)
const {
229 DCHECK(!leaf_nodes_have_delayed_operations_);
230 DCHECK_LT(target_envelope, tree_[node].envelope);
231 while (node < num_leaves_) {
232 const int left = node << 1;
233 const int right = left | 1;
234 DCHECK_LT(right, tree_.size());
236 if (target_envelope < tree_[right].envelope) {
239 target_envelope -= tree_[right].sum_of_energy_min;
243 *extra = tree_[node].envelope - target_envelope;
247template <
typename IntegerType>
248int ThetaLambdaTree<IntegerType>::GetLeafWithMaxEnergyDelta(
int node)
const {
249 DCHECK(!leaf_nodes_have_delayed_operations_);
250 const IntegerType delta_node = tree_[node].max_of_energy_delta;
251 while (node < num_leaves_) {
252 const int left = node << 1;
253 const int right = left | 1;
254 DCHECK_LT(right, tree_.size());
255 if (tree_[right].max_of_energy_delta == delta_node) {
258 DCHECK_EQ(tree_[left].max_of_energy_delta, delta_node);
265template <
typename IntegerType>
266void ThetaLambdaTree<IntegerType>::GetLeavesWithOptionalEnvelopeGreaterThan(
267 IntegerType target_envelope,
int* critical_leaf,
int* optional_leaf,
268 IntegerType* available_energy)
const {
269 DCHECK(!leaf_nodes_have_delayed_operations_);
270 DCHECK_LT(target_envelope, tree_[1].envelope_opt);
272 while (node < num_leaves_) {
273 const int left = node << 1;
274 const int right = left | 1;
275 DCHECK_LT(right, tree_.size());
277 if (target_envelope < tree_[right].envelope_opt) {
280 const IntegerType opt_energy_right =
281 tree_[right].sum_of_energy_min + tree_[right].max_of_energy_delta;
282 if (target_envelope < tree_[left].envelope + opt_energy_right) {
283 *optional_leaf = GetLeafWithMaxEnergyDelta(right);
285 *critical_leaf = GetMaxLeafWithEnvelopeGreaterThan(
286 left, target_envelope - opt_energy_right, &extra);
287 *available_energy = tree_[*optional_leaf].sum_of_energy_min +
288 tree_[*optional_leaf].max_of_energy_delta - extra;
291 target_envelope -= tree_[right].sum_of_energy_min;
296 *critical_leaf = node;
297 *optional_leaf = node;
298 *available_energy = target_envelope - (tree_[node].envelope_opt -
299 tree_[node].sum_of_energy_min -
300 tree_[node].max_of_energy_delta);
void Reset(int num_events)
void DelayedRemoveEvent(int event)
Delayed version of RemoveEvent(), see RecomputeTreeForDelayedOperations().
ThetaLambdaTree()
Builds a reusable tree. Initialization is done with Reset().
void DelayedAddOrUpdateOptionalEvent(int event, IntegerType initial_envelope_opt, IntegerType energy_max)
void RecomputeTreeForDelayedOperations()
IntegerType GetOptionalEnvelope() const
IntegerType GetEnvelope() const
void RemoveEvent(int event)
Makes event absent, compute the new envelope in O(log n).
void AddOrUpdateEvent(int event, IntegerType initial_envelope, IntegerType energy_min, IntegerType energy_max)
void GetEventsWithOptionalEnvelopeGreaterThan(IntegerType target_envelope, int *critical_event, int *optional_event, IntegerType *available_energy) const
int GetMaxEventWithEnvelopeGreaterThan(IntegerType target_envelope) const
IntegerType GetEnvelopeOf(int event) const
void AddOrUpdateOptionalEvent(int event, IntegerType initial_envelope_opt, IntegerType energy_max)
void DelayedAddOrUpdateEvent(int event, IntegerType initial_envelope, IntegerType energy_min, IntegerType energy_max)
constexpr IntegerType IntegerTypeMinimumValue()
The minimal value of an envelope, for instance the envelope of the empty set.
In SWIG mode, we don't want anything besides these top-level includes.