14#ifndef OR_TOOLS_GLOP_PRICING_H_
15#define OR_TOOLS_GLOP_PRICING_H_
17#include "absl/random/bit_gen_ref.h"
18#include "absl/random/random.h"
55template <
typename Index>
93 std::string
StatString()
const {
return stats_.StatString(); }
104 absl::BitGenRef random_;
105 std::vector<Index> equivalent_choices_;
134 const double operator<(
const HeapElement& other)
const {
135 return value > other.value;
139 std::vector<HeapElement> tops_;
142 struct QueryStats :
public StatsGroup {
145 get_maximum(
"get_maximum", this),
146 heap_size_on_hit(
"heap_size_on_hit", this),
147 random_choices(
"random_choices", this) {}
148 TimeDistribution get_maximum;
149 IntegerDistribution heap_size_on_hit;
150 IntegerDistribution random_choices;
155template <
typename Index>
160 is_candidate_.ClearAndResize(n);
163template <
typename Index>
165 is_candidate_.Clear(position);
168template <
typename Index>
175template <
typename Index>
180 is_candidate_.Set(position);
181 values_[position] =
value;
184template <
typename Index>
188 is_candidate_.Set(position);
189 values_[position] =
value;
190 if (
value >= threshold_) UpdateTopK(position,
value);
193template <
typename Index>
195 if (equivalent_choices_.empty())
return best;
196 equivalent_choices_.push_back(best);
197 stats_.random_choices.Add(equivalent_choices_.size());
199 return equivalent_choices_[std::uniform_int_distribution<int>(
200 0, equivalent_choices_.size() - 1)(random_)];
203template <
typename Index>
207 Index best_position(-1);
208 equivalent_choices_.clear();
218 if (!tops_.empty()) {
220 for (
const HeapElement e : tops_) {
222 if (!is_candidate_[e.index])
continue;
223 if (values_[e.index] != e.value)
continue;
225 tops_[new_size++] = e;
226 if (e.value >= best_value) {
227 if (e.value == best_value) {
228 equivalent_choices_.push_back(e.index);
231 equivalent_choices_.clear();
232 best_value = e.value;
233 best_position = e.index;
236 tops_.resize(new_size);
238 stats_.heap_size_on_hit.Add(new_size);
239 return RandomizeIfManyChoices(best_position);
246 for (
const Index position : is_candidate_) {
251 if (
value < threshold_)
continue;
252 UpdateTopK(position,
value);
254 if (
value >= best_value) {
255 if (
value == best_value) {
256 equivalent_choices_.push_back(position);
259 equivalent_choices_.clear();
261 best_position = position;
265 return RandomizeIfManyChoices(best_position);
268template <
typename Index>
278 constexpr int k = 31;
279 static_assert(((k + 1) & k) == 0,
"k + 1 should be a power of 2.");
282 if (tops_.size() < k) {
283 tops_.emplace_back(position,
value);
284 if (tops_.size() == k) {
285 std::make_heap(tops_.begin(), tops_.end());
286 threshold_ = tops_[0].value;
301 if (absl::Bernoulli(random_, 0.5)) {
302 tops_[0].index = position;
311 std::pop_heap(tops_.begin(), tops_.end());
312 tops_.back() = HeapElement(position,
value);
313 std::push_heap(tops_.begin(), tops_.end());
314 threshold_ = tops_[0].value;
323 constexpr int limit = k / 2;
325 const int left_child = 2 * i + 1;
327 const Fractional l_value = tops_[left_child].value;
329 if (l_value > r_value) {
330 if (
value <= r_value)
break;
334 if (
value <= l_value)
break;
335 tops_[i] = tops_[left_child];
339 tops_[i] = HeapElement(position,
value);
340 threshold_ = tops_[0].value;
341 DCHECK(std::is_heap(tops_.begin(), tops_.end()));
#define DCHECK_GE(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
StatsGroup(const std::string &name)
void AddOrUpdate(Index position, Fractional value)
void Remove(Index position)
DynamicMaximum(absl::BitGenRef random)
void DenseAddOrUpdate(Index position, Fractional value)
void ClearAndResize(Index n)
std::string StatString() const
bool IsFinite(Fractional value)
Collection of objects used to extend the Constraint Solver library.
#define SCOPED_TIME_STAT(stats)