25template <
typename IntegerType>
28template <
typename IntegerType>
31 return {
std::max(right.envelope, left.envelope + right.sum_of_energy_min),
33 right.sum_of_energy_min +
35 left.envelope + right.max_of_energy_delta)),
36 left.sum_of_energy_min + right.sum_of_energy_min,
37 std::max(right.max_of_energy_delta, left.max_of_energy_delta)};
40template <
typename IntegerType>
43 leaf_nodes_have_delayed_operations_ =
false;
48 num_events_ = num_events;
49 num_leaves_ =
std::max(2, num_events + (num_events & 1));
51 const int num_nodes = 2 * num_leaves_;
52 tree_.assign(num_nodes, TreeNode{IntegerTypeMinimumValue<IntegerType>(),
53 IntegerTypeMinimumValue<IntegerType>(),
54 IntegerType{0}, IntegerType{0}});
60 for (power_of_two_ = 2; power_of_two_ < num_leaves_; power_of_two_ <<= 1) {
64template <
typename IntegerType>
71 const int r = power_of_two_ + event;
72 return r < 2 * num_leaves_ ? r : r - num_leaves_;
75template <
typename IntegerType>
76int ThetaLambdaTree<IntegerType>::GetEventFromLeaf(
int leaf)
const {
79 const int r = leaf - power_of_two_;
80 return r >= 0 ? r : r + num_leaves_;
83template <
typename IntegerType>
86 leaf_nodes_have_delayed_operations_ =
false;
89 const int last_internal_node = tree_.size() / 2 - 1;
90 for (
int node = last_internal_node; node >= 1; --node) {
91 const int right = 2 * node + 1;
92 const int left = 2 * node;
93 tree_[node] = ComposeTreeNodes(tree_[left], tree_[right]);
97template <
typename IntegerType>
99 int event, IntegerType initial_envelope, IntegerType energy_min,
100 IntegerType energy_max) {
102 leaf_nodes_have_delayed_operations_ =
true;
106 const int node = GetLeafFromEvent(event);
107 tree_[node] = {initial_envelope + energy_min, initial_envelope + energy_max,
108 energy_min, energy_max - energy_min};
111template <
typename IntegerType>
113 int event, IntegerType initial_envelope, IntegerType energy_min,
114 IntegerType energy_max) {
115 DCHECK(!leaf_nodes_have_delayed_operations_);
118 const int node = GetLeafFromEvent(event);
119 tree_[node] = {initial_envelope + energy_min, initial_envelope + energy_max,
120 energy_min, energy_max - energy_min};
124template <
typename IntegerType>
126 int event, IntegerType initial_envelope_opt, IntegerType energy_max) {
127 DCHECK(!leaf_nodes_have_delayed_operations_);
129 const int node = GetLeafFromEvent(event);
130 tree_[node] = {IntegerTypeMinimumValue<IntegerType>(),
131 initial_envelope_opt + energy_max, IntegerType{0}, energy_max};
135template <
typename IntegerType>
137 int event, IntegerType initial_envelope_opt, IntegerType energy_max) {
139 leaf_nodes_have_delayed_operations_ =
true;
142 const int node = GetLeafFromEvent(event);
143 tree_[node] = {IntegerTypeMinimumValue<IntegerType>(),
144 initial_envelope_opt + energy_max, IntegerType{0}, energy_max};
147template <
typename IntegerType>
149 DCHECK(!leaf_nodes_have_delayed_operations_);
150 const int node = GetLeafFromEvent(event);
151 tree_[node] = {IntegerTypeMinimumValue<IntegerType>(),
152 IntegerTypeMinimumValue<IntegerType>(), IntegerType{0},
157template <
typename IntegerType>
160 leaf_nodes_have_delayed_operations_ =
true;
162 const int node = GetLeafFromEvent(event);
163 tree_[node] = {IntegerTypeMinimumValue<IntegerType>(),
164 IntegerTypeMinimumValue<IntegerType>(), IntegerType{0},
168template <
typename IntegerType>
170 DCHECK(!leaf_nodes_have_delayed_operations_);
171 return tree_[1].envelope;
173template <
typename IntegerType>
175 DCHECK(!leaf_nodes_have_delayed_operations_);
176 return tree_[1].envelope_opt;
179template <
typename IntegerType>
181 IntegerType target_envelope)
const {
182 DCHECK(!leaf_nodes_have_delayed_operations_);
183 DCHECK_LT(target_envelope, tree_[1].envelope);
185 return GetEventFromLeaf(
186 GetMaxLeafWithEnvelopeGreaterThan(1, target_envelope, &unused));
189template <
typename IntegerType>
191 IntegerType target_envelope,
int* critical_event,
int* optional_event,
192 IntegerType* available_energy)
const {
193 DCHECK(!leaf_nodes_have_delayed_operations_);
196 GetLeavesWithOptionalEnvelopeGreaterThan(target_envelope, &critical_leaf,
197 &optional_leaf, available_energy);
198 *critical_event = GetEventFromLeaf(critical_leaf);
199 *optional_event = GetEventFromLeaf(optional_leaf);
202template <
typename IntegerType>
204 DCHECK(!leaf_nodes_have_delayed_operations_);
205 const int leaf = GetLeafFromEvent(event);
206 IntegerType envelope = tree_[leaf].envelope;
207 for (
int node = leaf; node > 1; node >>= 1) {
208 const int right = node | 1;
209 if (node != right) envelope += tree_[right].sum_of_energy_min;
214template <
typename IntegerType>
217 const int right = node | 1;
218 const int left = right ^ 1;
220 tree_[node] = ComposeTreeNodes(tree_[left], tree_[right]);
224template <
typename IntegerType>
225int ThetaLambdaTree<IntegerType>::GetMaxLeafWithEnvelopeGreaterThan(
226 int node, IntegerType target_envelope, IntegerType* extra)
const {
227 DCHECK(!leaf_nodes_have_delayed_operations_);
228 DCHECK_LT(target_envelope, tree_[node].envelope);
229 while (node < num_leaves_) {
230 const int left = node << 1;
231 const int right = left | 1;
234 if (target_envelope < tree_[right].envelope) {
237 target_envelope -= tree_[right].sum_of_energy_min;
241 *extra = tree_[node].envelope - target_envelope;
245template <
typename IntegerType>
246int ThetaLambdaTree<IntegerType>::GetLeafWithMaxEnergyDelta(
int node)
const {
247 DCHECK(!leaf_nodes_have_delayed_operations_);
248 const IntegerType delta_node = tree_[node].max_of_energy_delta;
249 while (node < num_leaves_) {
250 const int left = node << 1;
251 const int right = left | 1;
253 if (tree_[right].max_of_energy_delta == delta_node) {
256 DCHECK_EQ(tree_[left].max_of_energy_delta, delta_node);
263template <
typename IntegerType>
264void ThetaLambdaTree<IntegerType>::GetLeavesWithOptionalEnvelopeGreaterThan(
265 IntegerType target_envelope,
int* critical_leaf,
int* optional_leaf,
266 IntegerType* available_energy)
const {
267 DCHECK(!leaf_nodes_have_delayed_operations_);
268 DCHECK_LT(target_envelope, tree_[1].envelope_opt);
270 while (node < num_leaves_) {
271 const int left = node << 1;
272 const int right = left | 1;
275 if (target_envelope < tree_[right].envelope_opt) {
278 const IntegerType opt_energy_right =
279 tree_[right].sum_of_energy_min + tree_[right].max_of_energy_delta;
280 if (target_envelope < tree_[left].envelope + opt_energy_right) {
281 *optional_leaf = GetLeafWithMaxEnergyDelta(right);
283 *critical_leaf = GetMaxLeafWithEnvelopeGreaterThan(
284 left, target_envelope - opt_energy_right, &extra);
285 *available_energy = tree_[*optional_leaf].sum_of_energy_min +
286 tree_[*optional_leaf].max_of_energy_delta - extra;
289 target_envelope -= tree_[right].sum_of_energy_min;
294 *critical_leaf = node;
295 *optional_leaf = node;
296 *available_energy = target_envelope - (tree_[node].envelope_opt -
297 tree_[node].sum_of_energy_min -
298 tree_[node].max_of_energy_delta);
301template class ThetaLambdaTree<IntegerValue>;
302template class ThetaLambdaTree<int64_t>;
#define DCHECK_LE(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
IntegerType GetEnvelopeOf(int event) const
void GetEventsWithOptionalEnvelopeGreaterThan(IntegerType target_envelope, int *critical_event, int *optional_event, IntegerType *available_energy) const
void RecomputeTreeForDelayedOperations()
IntegerType GetOptionalEnvelope() const
void RemoveEvent(int event)
int GetMaxEventWithEnvelopeGreaterThan(IntegerType target_envelope) const
void Reset(int num_events)
void AddOrUpdateOptionalEvent(int event, IntegerType initial_envelope_opt, IntegerType energy_max)
void DelayedAddOrUpdateEvent(int event, IntegerType initial_envelope, IntegerType energy_min, IntegerType energy_max)
void DelayedAddOrUpdateOptionalEvent(int event, IntegerType initial_envelope_opt, IntegerType energy_max)
void AddOrUpdateEvent(int event, IntegerType initial_envelope, IntegerType energy_min, IntegerType energy_max)
IntegerType GetEnvelope() const
void DelayedRemoveEvent(int event)
Collection of objects used to extend the Constraint Solver library.