14 #ifndef OR_TOOLS_GLOP_PRICING_H_
15 #define OR_TOOLS_GLOP_PRICING_H_
20 #include "absl/random/bit_gen_ref.h"
21 #include "absl/random/random.h"
58 template <
typename Index>
96 std::string
StatString()
const {
return stats_.StatString(); }
107 absl::BitGenRef random_;
108 std::vector<Index> equivalent_choices_;
137 const double operator<(
const HeapElement& other)
const {
138 return value > other.value;
142 std::vector<HeapElement> tops_;
145 struct QueryStats :
public StatsGroup {
148 get_maximum(
"get_maximum", this),
149 heap_size_on_hit(
"heap_size_on_hit", this),
150 random_choices(
"random_choices", this) {}
151 TimeDistribution get_maximum;
152 IntegerDistribution heap_size_on_hit;
153 IntegerDistribution random_choices;
158 template <
typename Index>
163 is_candidate_.ClearAndResize(n);
166 template <
typename Index>
168 is_candidate_.Clear(position);
171 template <
typename Index>
178 template <
typename Index>
182 DCHECK(tops_.empty());
183 is_candidate_.Set(position);
184 values_[position] =
value;
187 template <
typename Index>
191 is_candidate_.Set(position);
192 values_[position] =
value;
193 if (
value >= threshold_) UpdateTopK(position,
value);
196 template <
typename Index>
198 if (equivalent_choices_.empty())
return best;
199 equivalent_choices_.push_back(best);
200 stats_.random_choices.Add(equivalent_choices_.size());
202 return equivalent_choices_[std::uniform_int_distribution<int>(
203 0, equivalent_choices_.size() - 1)(random_)];
206 template <
typename Index>
210 Index best_position(-1);
211 equivalent_choices_.clear();
221 if (!tops_.empty()) {
223 for (
const HeapElement e : tops_) {
225 if (!is_candidate_[e.index])
continue;
226 if (values_[e.index] != e.value)
continue;
228 tops_[new_size++] = e;
229 if (e.value >= best_value) {
230 if (e.value == best_value) {
231 equivalent_choices_.push_back(e.index);
234 equivalent_choices_.clear();
235 best_value = e.value;
236 best_position = e.index;
239 tops_.resize(new_size);
241 stats_.heap_size_on_hit.Add(new_size);
242 return RandomizeIfManyChoices(best_position);
248 DCHECK(tops_.empty());
249 for (
const Index position : is_candidate_) {
254 if (
value < threshold_)
continue;
255 UpdateTopK(position,
value);
257 if (
value >= best_value) {
258 if (
value == best_value) {
259 equivalent_choices_.push_back(position);
262 equivalent_choices_.clear();
264 best_position = position;
268 return RandomizeIfManyChoices(best_position);
271 template <
typename Index>
275 DCHECK_GE(
value, threshold_);
281 constexpr
int k = 31;
282 static_assert(((k + 1) & k) == 0,
"k + 1 should be a power of 2.");
285 if (tops_.size() < k) {
286 tops_.emplace_back(position,
value);
287 if (tops_.size() == k) {
288 std::make_heap(tops_.begin(), tops_.end());
289 threshold_ = tops_[0].value;
304 if (absl::Bernoulli(random_, 0.5)) {
305 tops_[0].index = position;
314 std::pop_heap(tops_.begin(), tops_.end());
315 tops_.back() = HeapElement(position,
value);
316 std::push_heap(tops_.begin(), tops_.end());
317 threshold_ = tops_[0].value;
325 DCHECK_EQ(tops_.size(), k);
326 constexpr
int limit = k / 2;
328 const int left_child = 2 * i + 1;
330 const Fractional l_value = tops_[left_child].value;
332 if (l_value > r_value) {
333 if (
value <= r_value)
break;
337 if (
value <= l_value)
break;
338 tops_[i] = tops_[left_child];
342 tops_[i] = HeapElement(position,
value);
343 threshold_ = tops_[0].value;
344 DCHECK(std::is_heap(tops_.begin(), tops_.end()));
StatsGroup(absl::string_view 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
constexpr double kInfinity
bool IsFinite(Fractional value)
Collection of objects used to extend the Constraint Solver library.
#define SCOPED_TIME_STAT(stats)