1#ifndef ALGORITHMS_PRIORITY_QUEUES_H
2#define ALGORITHMS_PRIORITY_QUEUES_H
4#include "downward/utils/collections.h"
28namespace priority_queues {
29template <
typename Key,
typename Value>
32 typedef std::pair<Key, Value> Entry;
35 virtual ~AbstractQueue() {}
37 virtual void push(
const Key& key,
const Value& value) = 0;
38 virtual Entry pop() = 0;
39 virtual bool empty()
const = 0;
40 virtual void clear() = 0;
42 virtual AbstractQueue<Key, Value>* convert_if_necessary(
const Key&)
65 virtual void add_virtual_pushes(
int num_extra_pushes) = 0;
68template <
typename Key,
typename Value>
69class HeapQueue :
public AbstractQueue<Key, Value> {
70 typedef typename AbstractQueue<Key, Value>::Entry Entry;
73 bool operator()(
const Entry& lhs,
const Entry& rhs)
const
75 return lhs.first > rhs.first;
80 :
public std::priority_queue<Entry, std::vector<Entry>, compare_func> {
83 friend class HeapQueue;
91 virtual ~HeapQueue() {}
93 virtual void push(
const Key& key,
const Value& value)
95 heap.push(std::make_pair(key, value));
100 assert(!heap.empty());
101 Entry result = heap.top();
106 virtual bool empty()
const {
return heap.empty(); }
108 virtual void clear() { heap.c.clear(); }
110 static HeapQueue<Key, Value>*
111 create_from_sorted_entries_destructively(std::vector<Entry>& entries)
115 HeapQueue<Key, Value>* result =
new HeapQueue<Key, Value>;
116 result->heap.c.swap(entries);
121 virtual void add_virtual_pushes(
int ) {}
124template <
typename Value>
125class BucketQueue :
public AbstractQueue<int, Value> {
126 static const int MIN_BUCKETS_BEFORE_SWITCH = 100;
127 static const bool DEBUG =
false;
129 typedef typename AbstractQueue<int, Value>::Entry Entry;
131 typedef std::vector<Value> Bucket;
132 std::vector<Bucket> buckets;
133 mutable int current_bucket_no;
137 void update_current_bucket_no()
const
139 int num_buckets = buckets.size();
140 while (current_bucket_no < num_buckets &&
141 buckets[current_bucket_no].empty())
145 void extract_sorted_entries(std::vector<Entry>& result)
149 assert(result.empty());
150 result.reserve(num_entries);
151 for (
int key = current_bucket_no; num_entries != 0; ++key) {
152 Bucket& bucket = buckets[key];
153 for (
size_t i = 0; i < bucket.size(); ++i)
154 result.push_back(std::make_pair(key, bucket[i]));
155 num_entries -= bucket.size();
157 bucket.swap(empty_bucket);
159 current_bucket_no = 0;
164 : current_bucket_no(0)
170 virtual ~BucketQueue() {}
172 virtual void push(
const int& key,
const Value& value)
176 assert(num_pushes > 0);
177 int num_buckets = buckets.size();
178 if (key >= num_buckets)
179 buckets.resize(key + 1);
180 else if (key < current_bucket_no)
181 current_bucket_no = key;
182 buckets[key].push_back(value);
187 assert(num_entries > 0);
189 update_current_bucket_no();
190 Bucket& current_bucket = buckets[current_bucket_no];
191 Value top_element = current_bucket.back();
192 current_bucket.pop_back();
193 return std::make_pair(current_bucket_no, top_element);
196 virtual bool empty()
const {
return num_entries == 0; }
200 for (
int i = current_bucket_no; num_entries != 0; ++i) {
201 assert(utils::in_bounds(i, buckets));
202 int bucket_size = buckets[i].size();
203 assert(bucket_size <= num_entries);
204 num_entries -= bucket_size;
207 current_bucket_no = 0;
208 assert(num_entries == 0);
212 virtual AbstractQueue<int, Value>* convert_if_necessary(
const int& key)
214 if (key >= MIN_BUCKETS_BEFORE_SWITCH && key > num_pushes) {
216 std::cout <<
"Switch from bucket-based to heap-based queue "
217 <<
"at key = " << key
218 <<
", num_pushes = " << num_pushes << std::endl;
220 std::vector<Entry> entries;
221 extract_sorted_entries(entries);
222 return HeapQueue<int, Value>::
223 create_from_sorted_entries_destructively(entries);
228 virtual void add_virtual_pushes(
int num_extra_pushes)
230 num_pushes += num_extra_pushes;
234template <
typename Value>
236 AbstractQueue<int, Value>* wrapped_queue;
238 AdaptiveQueue& operator=(
const AdaptiveQueue<Value>&);
239 AdaptiveQueue(
const AdaptiveQueue<Value>&);
242 typedef std::pair<int, Value> Entry;
245 : wrapped_queue(new BucketQueue<Value>)
249 ~AdaptiveQueue() {
delete wrapped_queue; }
251 void push(
int key,
const Value& value)
253 AbstractQueue<int, Value>* q = wrapped_queue->convert_if_necessary(key);
254 if (q != wrapped_queue) {
255 delete wrapped_queue;
258 wrapped_queue->push(key, value);
261 Entry pop() {
return wrapped_queue->pop(); }
263 bool empty()
const {
return wrapped_queue->empty(); }
265 void clear() { wrapped_queue->clear(); }
267 void add_virtual_pushes(
int num_extra_pushes)
269 wrapped_queue->add_virtual_pushes(num_extra_pushes);