Skip to content

Commit

Permalink
Merge pull request #76 from stdgraph/idx_adj_list
Browse files Browse the repository at this point in the history
Idx adj list
  • Loading branch information
pratzl committed Nov 16, 2023
2 parents e483a5b + 75b14a9 commit ace0598
Show file tree
Hide file tree
Showing 15 changed files with 989 additions and 280 deletions.
70 changes: 67 additions & 3 deletions example/CppCon2022/rr_adaptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// https://www.reddit.com/r/cpp/comments/4yp7fv/c17_structured_bindings_convert_struct_to_a_tuple/
// https://gist.github.com/utilForever/1a058050b8af3ef46b58bcfa01d5375d

#define EDGES_CPO 1

template <class T, class... TArgs>
decltype(void(T{std::declval<TArgs>()...}), std::true_type{}) test_is_braces_constructible(int);

Expand Down Expand Up @@ -39,10 +41,42 @@ auto to_tuple(T&& object) noexcept {
return std::make_tuple();
}
}

template <class T>
using to_tuple_t = decltype(to_tuple(std::declval<T>()));


template <class T>
constexpr auto& to_tuple_value(T&& object, const int param) noexcept {
using type = std::decay_t<T>;
if constexpr (is_braces_constructible<type, any_type, any_type, any_type, any_type>{}) {
auto&& [p1, p2, p3, p4] = object;
switch (param) {
case 0: return p1;
case 1: return p2;
case 2: return p3;
case 3: return p4;
}
} else if constexpr (is_braces_constructible<type, any_type, any_type, any_type>{}) {
auto&& [p1, p2, p3] = object;
switch (param) {
case 0: return p1;
case 1: return p2;
case 2: return p3;
}
} else if constexpr (is_braces_constructible<type, any_type, any_type>{}) {
auto&& [p1, p2] = object;
switch (param) {
case 0: return p1;
case 1: return p2;
}
} else if constexpr (is_braces_constructible<type, any_type>{}) {
auto&& [p1] = object;
return p1;
} else {
return std::make_tuple();
}
}

//template <class C>
//concept has_push_back = requires(C& container, std::ranges::range_reference_t<C> val) {
// { container.push_back(val) };
Expand Down Expand Up @@ -123,18 +157,30 @@ class rr_adaptor {
}

private: // tag_invoke definitions
#if VERTICES_CPO
friend constexpr vertices_range& vertices(graph_type& g) { return g.vertices_; }
friend constexpr const vertices_range& vertices(const graph_type& g) { return g.vertices_; }
#else
friend constexpr vertices_range& tag_invoke(std::graph::tag_invoke::vertices_fn_t, graph_type& g) {
return g.vertices_;
}
friend constexpr const vertices_range& tag_invoke(std::graph::tag_invoke::vertices_fn_t, const graph_type& g) {
return g.vertices_;
}
#endif

friend vertex_id_type vertex_id(const graph_type& g, std::ranges::iterator_t<vertices_range> ui) {
return static_cast<vertex_id_type>(ui -
std::ranges::begin(g.vertices_)); // overriden to assure correct type returned
}

#if EDGES_CPO
friend constexpr edges_range& edges(graph_type& g, vertex_type& u) { return u; }
friend constexpr const edges_range& edges(const graph_type& g, const vertex_type& u) { return u; }

friend constexpr edges_range& edges(graph_type& g, const vertex_id_type uid) { return g.vertices_[uid]; }
friend constexpr const edges_range& edges(const graph_type& g, const vertex_id_type uid) { return g.vertices_[uid]; }
#else
friend constexpr edges_range& tag_invoke(std::graph::tag_invoke::edges_fn_t, graph_type& g, vertex_type& u) {
return u;
}
Expand All @@ -151,6 +197,7 @@ class rr_adaptor {
tag_invoke(std::graph::tag_invoke::edges_fn_t, const graph_type& g, const vertex_id_type uid) {
return g.vertices_[uid];
}
#endif

friend constexpr vertex_id_type target_id(const graph_type& g, const edge_type& uv) noexcept {
return get<0>(to_tuple(uv));
Expand All @@ -166,11 +213,11 @@ class rr_adaptor {
}

// edge_value(g,uv)
friend constexpr edge_value_type& edge_value(graph_type& g, edge_type& uv) {
friend constexpr edge_value_type edge_value(graph_type& g, edge_type& uv) {
auto t = to_tuple(uv);
return get<1>(t);
}
friend constexpr const edge_value_type& edge_value(const graph_type& g, const edge_type& uv) {
friend constexpr const edge_value_type edge_value(const graph_type& g, const edge_type& uv) {
auto t = to_tuple(uv);
return get<1>(t);
}
Expand Down Expand Up @@ -354,18 +401,34 @@ class rr_adaptor2 {
}

private:
#if VERTICES_CPO
friend constexpr vertices_range& vertices(graph_type& g) { return g.vertices_; }
friend constexpr const vertices_range& vertices(const graph_type& g) { return g.vertices_; }
#else
friend constexpr vertices_range& tag_invoke(std::graph::tag_invoke::vertices_fn_t, graph_type& g) {
return g.vertices_;
}
friend constexpr const vertices_range& tag_invoke(std::graph::tag_invoke::vertices_fn_t, const graph_type& g) {
return g.vertices_;
}
#endif

friend vertex_id_type vertex_id(const graph_type& g, std::ranges::iterator_t<vertices_range> ui) {
return static_cast<vertex_id_type>(ui -
std::ranges::begin(g.vertices_)); // overriden to assure correct type returned
}

#if EDGES_CPO
friend constexpr edges_range& edges(graph_type& g, vertex_type& u) { return get<0>(to_tuple(u)); }
friend constexpr const edges_range& edges(const graph_type& g, const vertex_type& u) { return get<0>(to_tuple(u)); }

friend constexpr edges_range& edges(graph_type& g, const vertex_id_type uid) {
return get<0>(to_tuple(g.vertices_[uid]));
}
friend constexpr const edges_range& edges(const graph_type& g, const vertex_id_type uid) {
return get<0>(to_tuple(g.vertices_[uid]));
}
#else
friend constexpr edges_range& tag_invoke(std::graph::tag_invoke::edges_fn_t, graph_type& g, vertex_type& u) {
return get<0>(to_tuple(u));
}
Expand All @@ -382,6 +445,7 @@ class rr_adaptor2 {
tag_invoke(std::graph::tag_invoke::edges_fn_t, const graph_type& g, const vertex_id_type uid) {
return get<0>(to_tuple(g.vertices_[uid]));
}
#endif

friend constexpr vertex_id_type target_id(const graph_type& g, const edge_type& uv) noexcept {
return get<0>(to_tuple(uv));
Expand Down
61 changes: 54 additions & 7 deletions include/graph/container/compressed_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class csr_row_values<EV, void, GV, VId, EIndex, Alloc> {
using value_type = void;
using size_type = size_t; //VId;

public: // Properties
public: // Properties
[[nodiscard]] constexpr size_type size() const noexcept { return 0; }
[[nodiscard]] constexpr bool empty() const noexcept { return true; }
[[nodiscard]] constexpr size_type capacity() const noexcept { return 0; }
Expand Down Expand Up @@ -342,7 +342,7 @@ class csr_col_values<void, VV, GV, VId, EIndex, Alloc> {
using value_type = void;
using size_type = size_t; //VId;

public: // Properties
public: // Properties
[[nodiscard]] constexpr size_type size() const noexcept { return 0; }
[[nodiscard]] constexpr bool empty() const noexcept { return true; }
[[nodiscard]] constexpr size_type capacity() const noexcept { return 0; }
Expand Down Expand Up @@ -481,7 +481,7 @@ class compressed_graph_base
}

public:
public: // Operations
public: // Operations
void reserve_vertices(size_type count) {
row_index_.reserve(count + 1); // +1 for terminating row
row_values_base::reserve(count);
Expand Down Expand Up @@ -739,28 +739,74 @@ class compressed_graph_base
//row_values_type row_value_; // row_value_[r] holds the value for row_index_[r], for VV!=void

private: // tag_invoke properties
#if VERTICES_CPO
friend constexpr vertices_type vertices(compressed_graph_base& g) {
if (g.row_index_.empty())
return vertices_type(g.row_index_); // really empty
else
return vertices_type(g.row_index_.begin(), g.row_index_.end() - 1); // don't include terminating row
}
friend constexpr const_vertices_type vertices(const compressed_graph_base& g) {
if (g.row_index_.empty())
return const_vertices_type(g.row_index_); // really empty
else
return const_vertices_type(g.row_index_.begin(), g.row_index_.end() - 1); // don't include terminating row
}
#else
friend constexpr vertices_type tag_invoke(::std::graph::tag_invoke::vertices_fn_t, compressed_graph_base& g) {
if (g.row_index_.empty())
return vertices_type(g.row_index_); // really empty
return vertices_type(g.row_index_); // really empty
else
return vertices_type(g.row_index_.begin(), g.row_index_.end() - 1); // don't include terminating row
}
friend constexpr const_vertices_type tag_invoke(::std::graph::tag_invoke::vertices_fn_t,
const compressed_graph_base& g) {
if (g.row_index_.empty())
return const_vertices_type(g.row_index_); // really empty
return const_vertices_type(g.row_index_); // really empty
else
return const_vertices_type(g.row_index_.begin(), g.row_index_.end() - 1); // don't include terminating row
}
#endif

friend vertex_id_type vertex_id(const compressed_graph_base& g, const_iterator ui) {
return static_cast<vertex_id_type>(ui - g.row_index_.begin());
}

#if EDGES_CPO
friend constexpr edges_type edges(graph_type& g, vertex_type& u) {
static_assert(ranges::contiguous_range<row_index_vector>, "row_index_ must be a contiguous range to get next row");
vertex_type* u2 = &u + 1;
assert(static_cast<size_t>(u2 - &u) < g.row_index_.size()); // in row_index_ bounds?
assert(static_cast<size_t>(u.index) <= g.col_index_.size() &&
static_cast<size_t>(u2->index) <= g.col_index_.size()); // in col_index_ bounds?
return edges_type(g.col_index_.begin() + u.index, g.col_index_.begin() + u2->index);
}
friend constexpr const_edges_type edges(const graph_type& g, const vertex_type& u) {
static_assert(ranges::contiguous_range<row_index_vector>, "row_index_ must be a contiguous range to get next row");
const vertex_type* u2 = &u + 1;
assert(static_cast<size_t>(u2 - &u) < g.row_index_.size()); // in row_index_ bounds?
assert(static_cast<size_t>(u.index) <= g.col_index_.size() &&
static_cast<size_t>(u2->index) <= g.col_index_.size()); // in col_index_ bounds?
return const_edges_type(g.col_index_.begin() + u.index, g.col_index_.begin() + u2->index);
}

friend constexpr edges_type edges(graph_type& g, const vertex_id_type uid) {
assert(static_cast<size_t>(uid + 1) < g.row_index_.size()); // in row_index_ bounds?
assert(static_cast<size_t>(g.row_index_[uid + 1].index) <= g.col_index_.size()); // in col_index_ bounds?
return edges_type(g.col_index_.begin() + g.row_index_[uid].index,
g.col_index_.begin() + g.row_index_[uid + 1].index);
}
friend constexpr const_edges_type edges(const graph_type& g, const vertex_id_type uid) {
assert(static_cast<size_t>(uid + 1) < g.row_index_.size()); // in row_index_ bounds?
assert(static_cast<size_t>(g.row_index_[uid + 1].index) <= g.col_index_.size()); // in col_index_ bounds?
return const_edges_type(g.col_index_.begin() + g.row_index_[uid].index,
g.col_index_.begin() + g.row_index_[uid + 1].index);
}
#else
friend constexpr edges_type tag_invoke(::std::graph::tag_invoke::edges_fn_t, graph_type& g, vertex_type& u) {
static_assert(ranges::contiguous_range<row_index_vector>, "row_index_ must be a contiguous range to get next row");
vertex_type* u2 = &u + 1;
assert(static_cast<size_t>(u2 - &u) < g.row_index_.size()); // in row_index_ bounds?
assert(static_cast<size_t>(u2 - &u) < g.row_index_.size()); // in row_index_ bounds?
assert(static_cast<size_t>(u.index) <= g.col_index_.size() &&
static_cast<size_t>(u2->index) <= g.col_index_.size()); // in col_index_ bounds?
return edges_type(g.col_index_.begin() + u.index, g.col_index_.begin() + u2->index);
Expand All @@ -769,7 +815,7 @@ class compressed_graph_base
tag_invoke(::std::graph::tag_invoke::edges_fn_t, const graph_type& g, const vertex_type& u) {
static_assert(ranges::contiguous_range<row_index_vector>, "row_index_ must be a contiguous range to get next row");
const vertex_type* u2 = &u + 1;
assert(static_cast<size_t>(u2 - &u) < g.row_index_.size()); // in row_index_ bounds?
assert(static_cast<size_t>(u2 - &u) < g.row_index_.size()); // in row_index_ bounds?
assert(static_cast<size_t>(u.index) <= g.col_index_.size() &&
static_cast<size_t>(u2->index) <= g.col_index_.size()); // in col_index_ bounds?
return const_edges_type(g.col_index_.begin() + u.index, g.col_index_.begin() + u2->index);
Expand All @@ -789,6 +835,7 @@ class compressed_graph_base
return const_edges_type(g.col_index_.begin() + g.row_index_[uid].index,
g.col_index_.begin() + g.row_index_[uid + 1].index);
}
#endif


// target_id(g,uv), target(g,uv)
Expand Down
23 changes: 21 additions & 2 deletions include/graph/container/dynamic_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,13 +679,18 @@ class dynamic_vertex_base {
edges_type edges_;

private: // tag_invoke properties
#if EDGES_CPO
friend constexpr edges_type& edges(graph_type& g, vertex_type& u) { return u.edges_; }
friend constexpr const edges_type& edges(const graph_type& g, const vertex_type& u) { return u.edges_; }
#else
friend constexpr edges_type& tag_invoke(::std::graph::tag_invoke::edges_fn_t, graph_type& g, vertex_type& u) {
return u.edges_;
}
friend constexpr const edges_type&
tag_invoke(::std::graph::tag_invoke::edges_fn_t, const graph_type& g, const vertex_type& u) {
return u.edges_;
}
#endif

friend constexpr typename edges_type::iterator
find_vertex_edge(graph_type& g, vertex_id_type uid, vertex_id_type vid) {
Expand Down Expand Up @@ -1212,7 +1217,7 @@ class dynamic_graph_base {
constexpr typename vertices_type::value_type& operator[](size_type i) noexcept { return vertices_[i]; }
constexpr const typename vertices_type::value_type& operator[](size_type i) const noexcept { return vertices_[i]; }

public: // Operations
public: // Operations
void reserve_vertices(size_type count) {
if constexpr (reservable<vertices_type>) // reserve if we can; otherwise ignored
vertices_.reserve(count);
Expand All @@ -1233,18 +1238,31 @@ class dynamic_graph_base {
vertices_type vertices_;

private: // tag_invoke properties
#if VERTICES_CPO
friend constexpr vertices_type& vertices(dynamic_graph_base& g) { return g.vertices_; }
friend constexpr const vertices_type& vertices(const dynamic_graph_base& g) { return g.vertices_; }
#else
friend constexpr vertices_type& tag_invoke(::std::graph::tag_invoke::vertices_fn_t, dynamic_graph_base& g) {
return g.vertices_;
}
friend constexpr const vertices_type& tag_invoke(::std::graph::tag_invoke::vertices_fn_t,
const dynamic_graph_base& g) {
return g.vertices_;
}
#endif

friend vertex_id_type vertex_id(const dynamic_graph_base& g, typename vertices_type::const_iterator ui) {
return static_cast<vertex_id_type>(ui - g.vertices_.begin());
}

#if EDGES_CPO
friend constexpr edges_type& edges(graph_type& g, const vertex_id_type uid) { //
return g.vertices_[uid].edges();
}
friend constexpr const edges_type& edges(const graph_type& g, const vertex_id_type uid) {
return g.vertices_[uid].edges();
}
#else
friend constexpr edges_type&
tag_invoke(::std::graph::tag_invoke::edges_fn_t, graph_type& g, const vertex_id_type uid) {
return g.vertices_[uid].edges();
Expand All @@ -1253,6 +1271,7 @@ class dynamic_graph_base {
tag_invoke(::std::graph::tag_invoke::edges_fn_t, const graph_type& g, const vertex_id_type uid) {
return g.vertices_[uid].edges();
}
#endif
};

/**
Expand Down Expand Up @@ -1612,7 +1631,7 @@ class dynamic_graph : public dynamic_graph_base<EV, VV, GV, VId, Sourced, Traits
private:
value_type value_; ///< Graph value

private: // tag_invoke properties
private: // tag_invoke properties
friend constexpr value_type& graph_value(graph_type& g) { return g.value_; }
friend constexpr const value_type& graph_value(const graph_type& g) { return g.value_; }
};
Expand Down
4 changes: 4 additions & 0 deletions include/graph/container/utility_edgelist.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,13 @@ class utility_edgelist {
bool is_directed() { return directed_; }

private:
#if EDGES_CPO
friend constexpr storage_type& edges(utility_edgelist& el) { return el.storage_; }
#else
friend constexpr storage_type& tag_invoke(::std::graph::edgelist::tag_invoke::edges_fn_t, utility_edgelist& el) {
return el.storage_;
}
#endif

friend constexpr VSourceId& source_id(utility_edgelist& el, value_type& e) { return std::get<0>(e); }

Expand Down
Loading

0 comments on commit ace0598

Please sign in to comment.