osrm-backend/unit_tests/util/query_heap.cpp

180 lines
4.5 KiB
C++
Raw Normal View History

2017-05-02 07:12:28 -04:00
#include "util/query_heap.hpp"
2016-01-02 11:13:44 -05:00
#include "util/typedefs.hpp"
2014-06-12 19:00:46 -04:00
#include <boost/mpl/list.hpp>
2016-05-27 15:05:04 -04:00
#include <boost/test/unit_test.hpp>
2014-06-12 19:00:46 -04:00
#include <algorithm>
#include <limits>
2014-06-12 19:00:46 -04:00
#include <random>
#include <vector>
2014-06-12 19:00:46 -04:00
BOOST_AUTO_TEST_SUITE(binary_heap)
2016-01-05 10:51:13 -05:00
using namespace osrm;
using namespace osrm::util;
2014-06-12 19:00:46 -04:00
struct TestData
{
unsigned value;
};
using TestNodeID = NodeID;
using TestKey = int;
using TestWeight = int;
using storage_types =
boost::mpl::list<ArrayStorage<TestNodeID, TestKey>, UnorderedMapStorage<TestNodeID, TestKey>>;
2014-06-12 19:00:46 -04:00
template <unsigned NUM_ELEM> struct RandomDataFixture
2014-06-12 19:00:46 -04:00
{
RandomDataFixture()
{
for (unsigned i = 0; i < NUM_ELEM; i++)
{
data.push_back(TestData{i * 3});
weights.push_back((i + 1) * 100);
2014-06-12 19:00:46 -04:00
ids.push_back(i);
order.push_back(i);
}
// Choosen by a fair W20 dice roll
std::mt19937 g(15);
std::shuffle(order.begin(), order.end(), g);
}
std::vector<TestData> data;
2014-06-12 19:00:46 -04:00
std::vector<TestWeight> weights;
std::vector<TestNodeID> ids;
std::vector<unsigned> order;
2014-06-12 19:00:46 -04:00
};
constexpr unsigned NUM_NODES = 100;
BOOST_FIXTURE_TEST_CASE_TEMPLATE(insert_test, T, storage_types, RandomDataFixture<NUM_NODES>)
{
2017-05-02 07:12:28 -04:00
QueryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(NUM_NODES);
2014-06-12 19:00:46 -04:00
TestWeight min_weight = std::numeric_limits<TestWeight>::max();
TestNodeID min_id;
for (unsigned idx : order)
{
BOOST_CHECK(!heap.WasInserted(ids[idx]));
heap.Insert(ids[idx], weights[idx], data[idx]);
BOOST_CHECK(heap.WasInserted(ids[idx]));
if (weights[idx] < min_weight)
{
min_weight = weights[idx];
min_id = ids[idx];
}
BOOST_CHECK_EQUAL(min_id, heap.Min());
}
for (auto id : ids)
{
const auto &d = heap.GetData(id);
2014-06-12 19:00:46 -04:00
BOOST_CHECK_EQUAL(d.value, data[id].value);
const auto &w = heap.GetKey(id);
2014-06-12 19:00:46 -04:00
BOOST_CHECK_EQUAL(w, weights[id]);
}
}
BOOST_FIXTURE_TEST_CASE_TEMPLATE(delete_min_test, T, storage_types, RandomDataFixture<NUM_NODES>)
{
2017-05-02 07:12:28 -04:00
QueryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(NUM_NODES);
2014-06-12 19:00:46 -04:00
for (unsigned idx : order)
{
heap.Insert(ids[idx], weights[idx], data[idx]);
}
for (auto id : ids)
{
BOOST_CHECK(!heap.WasRemoved(id));
BOOST_CHECK_EQUAL(heap.Min(), id);
BOOST_CHECK_EQUAL(id, heap.DeleteMin());
if (id + 1 < NUM_NODES)
BOOST_CHECK_EQUAL(heap.Min(), id + 1);
2014-06-12 19:00:46 -04:00
BOOST_CHECK(heap.WasRemoved(id));
}
}
BOOST_FIXTURE_TEST_CASE_TEMPLATE(delete_all_test, T, storage_types, RandomDataFixture<NUM_NODES>)
{
2017-05-02 07:12:28 -04:00
QueryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(NUM_NODES);
2014-06-12 19:00:46 -04:00
for (unsigned idx : order)
{
heap.Insert(ids[idx], weights[idx], data[idx]);
}
heap.DeleteAll();
BOOST_CHECK(heap.Empty());
}
2024-08-22 16:16:23 -04:00
BOOST_FIXTURE_TEST_CASE_TEMPLATE(smoke_test, T, storage_types, RandomDataFixture<NUM_NODES>)
{
QueryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(NUM_NODES);
for (unsigned idx : order)
{
heap.Insert(ids[idx], weights[idx], data[idx]);
}
while (!heap.Empty())
{
auto old_weight = heap.MinKey();
auto node = heap.GetHeapNodeIfWasInserted(heap.Min());
BOOST_CHECK(old_weight == node->weight);
BOOST_CHECK(node);
node->weight = node->weight - 1;
heap.DecreaseKey(*node);
BOOST_CHECK(heap.MinKey() == node->weight);
heap.DeleteMin();
}
}
2014-06-12 19:00:46 -04:00
BOOST_FIXTURE_TEST_CASE_TEMPLATE(decrease_key_test, T, storage_types, RandomDataFixture<10>)
{
2017-05-02 07:12:28 -04:00
QueryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(10);
2014-06-12 19:00:46 -04:00
for (unsigned idx : order)
{
heap.Insert(ids[idx], weights[idx], data[idx]);
}
std::vector<TestNodeID> rids(ids);
std::reverse(rids.begin(), rids.end());
for (auto id : rids)
{
TestNodeID min_id = heap.Min();
TestWeight min_weight = heap.GetKey(min_id);
// decrease weight until we reach min weight
while (weights[id] > min_weight)
{
heap.DecreaseKey(id, weights[id]);
BOOST_CHECK_EQUAL(heap.Min(), min_id);
BOOST_CHECK_EQUAL(heap.MinKey(), min_weight);
2014-06-12 19:00:46 -04:00
weights[id]--;
}
// make weight smaller than min
weights[id] -= 2;
heap.DecreaseKey(id, weights[id]);
BOOST_CHECK_EQUAL(heap.Min(), id);
BOOST_CHECK_EQUAL(heap.MinKey(), weights[id]);
2014-06-12 19:00:46 -04:00
}
}
BOOST_AUTO_TEST_SUITE_END()