Skip to content

Commit

Permalink
factorize d_ary_heap and updatable_d_ary_heap + fixed range-v3 versio…
Browse files Browse the repository at this point in the history
…n to 0.12.0
  • Loading branch information
fhamonic committed Sep 19, 2024
1 parent 7580d44 commit 55ad801
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 236 deletions.
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MelonConan(ConanFile):
generators = "CMakeToolchain", "CMakeDeps"

def requirements(self):
self.requires("range-v3/[>=0.11.0]", transitive_headers=True)
self.requires("range-v3/0.12.0", transitive_headers=True)
self.requires("fmt/[>=10.0.0]", transitive_headers=True)
self.test_requires("gtest/[>=1.10.0 <cci]")

Expand Down
43 changes: 25 additions & 18 deletions include/melon/algorithm/bidirectional_dijkstra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ template <typename _Graph, typename _ValueType>
struct bidirectional_dijkstra_default_traits {
using semiring = shortest_path_semiring<_ValueType>;
using heap =
d_ary_heap<2, std::pair<vertex_t<_Graph>, _ValueType>,
views::get_map<1>, typename semiring::less_t,
views::get_map<0>, vertex_map_t<_Graph, std::size_t>>;
updatable_d_ary_heap<2, std::pair<vertex_t<_Graph>, _ValueType>,
typename semiring::less_t,
vertex_map_t<_Graph, std::size_t>,
views::get_map<1>, views::get_map<0>>;

static constexpr bool store_path = true;
};
Expand All @@ -52,11 +53,15 @@ class bidirectional_dijkstra {
private:
using vertex = vertex_t<_Graph>;
using arc = arc_t<_Graph>;
using value_t = mapped_value_t<_LengthMap, vertex>;
using length_type = mapped_value_t<_LengthMap, vertex>;

using heap = _Traits::heap;
enum vertex_status : char { PRE_HEAP = 0, IN_HEAP = 1, POST_HEAP = 2 };

static_assert(std::is_same_v<typename heap::value_type,
std::pair<vertex, length_type>>,
"bidirectional_dijkstra requires heap entries type.");

using optional_arc = std::optional<arc>;
struct no_forward_pred_arcs_map {};
using forward_pred_arcs_map =
Expand Down Expand Up @@ -88,8 +93,10 @@ class bidirectional_dijkstra {
[[nodiscard]] constexpr bidirectional_dijkstra(_G && g, _M && l)
: _graph(views::graph_all(std::forward<_G>(g)))
, _length_map(views::mapping_all(std::forward<_M>(l)))
, _forward_heap(create_vertex_map<std::size_t>(_graph))
, _reverse_heap(create_vertex_map<std::size_t>(_graph))
, _forward_heap(typename _Traits::semiring::less_t(),
create_vertex_map<std::size_t>(_graph))
, _reverse_heap(typename _Traits::semiring::less_t(),
create_vertex_map<std::size_t>(_graph))
, _vertex_status_map(_graph.template create_vertex_map<
std::pair<vertex_status, vertex_status>>(
std::make_pair(PRE_HEAP, PRE_HEAP)))
Expand All @@ -114,7 +121,7 @@ class bidirectional_dijkstra {
}
bidirectional_dijkstra & add_source(
const vertex & s,
const value_t dist = _Traits::semiring::zero) noexcept {
const length_type dist = _Traits::semiring::zero) noexcept {
assert(_vertex_status_map[s].first == PRE_HEAP);
_forward_heap.push(std::make_pair(s, dist));
_vertex_status_map[s].first = IN_HEAP;
Expand All @@ -123,7 +130,7 @@ class bidirectional_dijkstra {
}
bidirectional_dijkstra & add_target(
const vertex & t,
const value_t dist = _Traits::semiring::zero) noexcept {
const length_type dist = _Traits::semiring::zero) noexcept {
assert(_vertex_status_map[t].second == PRE_HEAP);
_reverse_heap.push(std::make_pair(t, dist));
_vertex_status_map[t].second = IN_HEAP;
Expand All @@ -132,8 +139,8 @@ class bidirectional_dijkstra {
}

public:
constexpr value_t run() noexcept {
value_t st_dist = _Traits::semiring::infty;
constexpr length_type run() noexcept {
length_type st_dist = _Traits::semiring::infty;
while(!_forward_heap.empty() && !_reverse_heap.empty()) {
const auto && [u1, u1_dist] = _forward_heap.top();
const auto && [u2, u2_dist] = _reverse_heap.top();
Expand All @@ -152,13 +159,13 @@ class bidirectional_dijkstra {
auto [w_forward_status, w_reverse_status] =
_vertex_status_map[w];
if(w_forward_status == IN_HEAP) {
const value_t new_w_dist =
const length_type new_w_dist =
_Traits::semiring::plus(u1_dist, _length_map[a]);
if(_Traits::semiring::less(new_w_dist,
_forward_heap.priority(w))) {
_forward_heap.promote(w, new_w_dist);
if(w_reverse_status == IN_HEAP) {
const value_t new_st_dist =
const length_type new_st_dist =
new_w_dist + _reverse_heap.priority(w);
if(_Traits::semiring::less(new_st_dist,
st_dist)) {
Expand All @@ -170,12 +177,12 @@ class bidirectional_dijkstra {
_forward_pred_arcs_map[w].emplace(a);
}
} else if(w_forward_status == PRE_HEAP) {
const value_t new_w_dist =
const length_type new_w_dist =
_Traits::semiring::plus(u1_dist, _length_map[a]);
_forward_heap.push(std::make_pair(w, new_w_dist));
_vertex_status_map[w].first = IN_HEAP;
if(w_reverse_status == IN_HEAP) {
const value_t new_st_dist =
const length_type new_st_dist =
new_w_dist + _reverse_heap.priority(w);
if(_Traits::semiring::less(new_st_dist, st_dist)) {
st_dist = new_st_dist;
Expand All @@ -198,13 +205,13 @@ class bidirectional_dijkstra {
auto [w_forward_status, w_reverse_status] =
_vertex_status_map[w];
if(w_reverse_status == IN_HEAP) {
const value_t new_w_dist =
const length_type new_w_dist =
_Traits::semiring::plus(u2_dist, _length_map[a]);
if(_Traits::semiring::less(new_w_dist,
_reverse_heap.priority(w))) {
_reverse_heap.promote(w, new_w_dist);
if(w_forward_status == IN_HEAP) {
const value_t new_st_dist =
const length_type new_st_dist =
new_w_dist + _forward_heap.priority(w);
if(_Traits::semiring::less(new_st_dist,
st_dist)) {
Expand All @@ -216,12 +223,12 @@ class bidirectional_dijkstra {
_reverse_pred_arcs_map[w].emplace(a);
}
} else if(w_reverse_status == PRE_HEAP) {
const value_t new_w_dist =
const length_type new_w_dist =
_Traits::semiring::plus(u2_dist, _length_map[a]);
_reverse_heap.push(std::make_pair(w, new_w_dist));
_vertex_status_map[w].second = IN_HEAP;
if(w_forward_status == IN_HEAP) {
const value_t new_st_dist =
const length_type new_st_dist =
new_w_dist + _forward_heap.priority(w);
if(_Traits::semiring::less(new_st_dist, st_dist)) {
st_dist = new_st_dist;
Expand Down
45 changes: 25 additions & 20 deletions include/melon/algorithm/competing_dijkstras.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,19 @@ template <outward_incidence_graph _Graph, typename _ValueType>
struct competing_dijkstras_default_traits {
using semiring = shortest_path_semiring<_ValueType>;
using entry = std::pair<_ValueType, bool>;
static bool compare_entries(const entry & e1, const entry & e2) {
if(e1.first == e2.first) {
return e1.second && !e2.second;
}
return semiring::less(e1.first, e2.first);
}
struct entry_cmp {
[[nodiscard]] constexpr bool operator()(
const auto & e1, const auto & e2) const noexcept {
return compare_entries(e1, e2);
[[nodiscard]] constexpr bool operator()(const entry & e1,
const entry & e2) const {
if(e1.first == e2.first) {
return e1.second && !e2.second;
}
return semiring::less(e1.first, e2.first);
}
};
using heap = d_ary_heap<2, std::pair<vertex_t<_Graph>, entry>,
views::get_map<1>, entry_cmp, views::get_map<0>,
vertex_map_t<_Graph, std::size_t>>;
using heap =
updatable_d_ary_heap<2, std::pair<vertex_t<_Graph>, entry>, entry_cmp,
vertex_map_t<_Graph, std::size_t>,
views::get_map<1>, views::get_map<0>>;

static constexpr bool store_distances = false;
static constexpr bool store_paths = false;
Expand All @@ -63,11 +61,16 @@ class competing_dijkstras {
private:
using vertex = vertex_t<_Graph>;
using arc = arc_t<_Graph>;
using value_t = mapped_value_t<BLM, arc_t<_Graph>>;
using length_type = mapped_value_t<BLM, arc_t<_Graph>>;
using entry_t = typename _Traits::entry;
using entry_cmp = typename _Traits::entry_cmp;
using heap = typename _Traits::heap;

static_assert(
std::is_same_v<typename _Traits::heap::value_type,
std::pair<vertex, std::pair<length_type, bool>>>,
"competing_dijkstras requires matching value_type with heap.");

private:
_Graph _graph;
BLM _blue_length_map;
Expand All @@ -76,6 +79,7 @@ class competing_dijkstras {
vertex_map_t<_Graph, vertex_status> _vertex_status_map;
heap _heap;
std::size_t _nb_blue_candidates;
[[no_unique_address]] entry_cmp _entry_cmp;

public:
template <typename _G, typename _BLM, typename _RLM>
Expand All @@ -84,7 +88,7 @@ class competing_dijkstras {
, _blue_length_map(views::mapping_all(std::forward<_BLM>(l1)))
, _red_length_map(views::mapping_all(std::forward<_RLM>(l2)))
, _vertex_status_map(create_vertex_map<vertex_status>(_graph, PRE_HEAP))
, _heap(create_vertex_map<std::size_t>(_graph), entry_cmp{})
, _heap(_entry_cmp, create_vertex_map<std::size_t>(_graph))
, _nb_blue_candidates(0) {}

template <typename... _Args>
Expand Down Expand Up @@ -115,7 +119,7 @@ class competing_dijkstras {

competing_dijkstras & add_blue_source(
const vertex & s,
const value_t dist_v = _Traits::semiring::zero) noexcept {
const length_type dist_v = _Traits::semiring::zero) noexcept {
assert(_vertex_status_map[s] != IN_HEAP);
_heap.push(std::make_pair(s, entry_t{dist_v, true}));
++_nb_blue_candidates;
Expand All @@ -128,7 +132,7 @@ class competing_dijkstras {
}
competing_dijkstras & add_red_source(
const vertex & s,
const value_t dist_v = _Traits::semiring::zero) noexcept {
const length_type dist_v = _Traits::semiring::zero) noexcept {
assert(_vertex_status_map[s] != IN_HEAP);
_heap.push(std::make_pair(s, entry_t{dist_v, false}));
_vertex_status_map[s] = IN_HEAP;
Expand All @@ -140,12 +144,12 @@ class competing_dijkstras {
}

void relax_blue_vertex(const vertex & w,
const value_t new_dist_v) noexcept {
const length_type new_dist_v) noexcept {
const entry_t new_dist = {new_dist_v, true};
auto && w_status = _vertex_status_map[w];
if(w_status == IN_HEAP) {
const entry_t old_dist = _heap.priority(w);
if(_Traits::compare_entries(new_dist, old_dist)) {
if(_entry_cmp(new_dist, old_dist)) {
if(!old_dist.second) {
++_nb_blue_candidates;
}
Expand All @@ -158,12 +162,13 @@ class competing_dijkstras {
}
}

void relax_red_vertex(const vertex & w, const value_t new_dist_v) noexcept {
void relax_red_vertex(const vertex & w,
const length_type new_dist_v) noexcept {
const entry_t new_dist = {new_dist_v, false};
auto && w_status = _vertex_status_map[w];
if(w_status == IN_HEAP) {
const entry_t old_dist = _heap.priority(w);
if(_Traits::compare_entries(new_dist, old_dist)) {
if(_entry_cmp(new_dist, old_dist)) {
if(old_dist.second) {
--_nb_blue_candidates;
}
Expand Down
29 changes: 16 additions & 13 deletions include/melon/algorithm/dijkstra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ template <typename _Graph, typename _ValueType>
struct dijkstra_default_traits {
using semiring = shortest_path_semiring<_ValueType>;
using heap =
d_ary_heap<2, std::pair<vertex_t<_Graph>, _ValueType>,
views::get_map<1>, typename semiring::less_t,
views::get_map<0>, vertex_map_t<_Graph, std::size_t>>;
updatable_d_ary_heap<2, std::pair<vertex_t<_Graph>, _ValueType>,
typename semiring::less_t,
vertex_map_t<_Graph, std::size_t>,
views::get_map<1>, views::get_map<0>>;

static constexpr bool store_distances = false;
static constexpr bool store_paths = false;
Expand All @@ -52,16 +53,17 @@ class dijkstra {
private:
using vertex = vertex_t<_Graph>;
using arc = arc_t<_Graph>;
using value_t = mapped_value_t<_LengthMap, arc_t<_Graph>>;
using traversal_entry = std::pair<vertex, value_t>;

static_assert(
std::is_same_v<traversal_entry, typename _Traits::heap::entry>,
"traversal_entry != heap_entry");
using length_type = mapped_value_t<_LengthMap, arc_t<_Graph>>;
using traversal_entry = std::pair<vertex, length_type>;

using heap = _Traits::heap;
enum vertex_status : char { PRE_HEAP = 0, IN_HEAP = 1, POST_HEAP = 2 };

static_assert(std::is_same_v<typename heap::value_type,
std::pair<vertex, length_type>>,
"dijkstras requires heap entries type.");

private:
_Graph _graph;
_LengthMap _length_map;
Expand All @@ -81,7 +83,8 @@ class dijkstra {
[[nodiscard]] constexpr dijkstra(_G && g, _M && l)
: _graph(views::graph_all(std::forward<_G>(g)))
, _length_map(views::mapping_all(std::forward<_M>(l)))
, _heap(create_vertex_map<std::size_t>(_graph))
, _heap(typename _Traits::semiring::less_t(),
create_vertex_map<std::size_t>(_graph))
, _vertex_status_map(create_vertex_map<vertex_status>(_graph, PRE_HEAP))
, _pred_vertices_map(_graph)
, _pred_arcs_map(_graph)
Expand Down Expand Up @@ -110,7 +113,7 @@ class dijkstra {
}
constexpr dijkstra & add_source(
const vertex & s,
const value_t & dist = _Traits::semiring::zero) noexcept {
const length_type & dist = _Traits::semiring::zero) noexcept {
assert(_vertex_status_map[s] != IN_HEAP);
_heap.push(std::make_pair(s, dist));
_vertex_status_map[s] = IN_HEAP;
Expand Down Expand Up @@ -144,7 +147,7 @@ class dijkstra {
const vertex & w = melon::arc_target(_graph, a);
const vertex_status & w_status = _vertex_status_map[w];
if(w_status == IN_HEAP) {
const value_t new_dist =
const length_type new_dist =
_Traits::semiring::plus(st_dist, _length_map[a]);
if(_Traits::semiring::less(new_dist, _heap.priority(w))) {
_heap.promote(w, new_dist);
Expand Down Expand Up @@ -198,14 +201,14 @@ class dijkstra {
else
return _pred_vertices_map[u];
}
[[nodiscard]] constexpr value_t current_dist(
[[nodiscard]] constexpr length_type current_dist(
const vertex & u) const noexcept
requires(_Traits::store_distances)
{
assert(reached(u) && !visited(u));
return _heap.priority(u);
}
[[nodiscard]] constexpr value_t dist(const vertex & u) const noexcept
[[nodiscard]] constexpr length_type dist(const vertex & u) const noexcept
requires(_Traits::store_distances)
{
assert(visited(u));
Expand Down
Loading

0 comments on commit 55ad801

Please sign in to comment.