Skip to content

Commit 0eece7b

Browse files
authored
Merge pull request #136 from stdgraph/identifier
Identifier
2 parents c43b457 + 4bba09b commit 0eece7b

28 files changed

+1661
-264
lines changed

example/CppCon2022/rr_adaptor.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class rr_adaptor {
113113
template <std::ranges::forward_range ERng, class EProj = std::identity>
114114
rr_adaptor(VVR& vertex_values, //
115115
const ERng& erng, //
116-
const EProj& eproj = EProj(), // EProj(ERng::value_type&) -> edge_descriptor<VId,true[,val]>
116+
const EProj& eproj = EProj(), // EProj(ERng::value_type&) -> edge_info<VId,true[,val]>
117117
bool dup_edges = false)
118118
: vertex_values_(vertex_values) {
119119
vertex_id_type max_vid = max_vertex_id(erng, eproj);

include/graph/algorithm/common_shortest_paths.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,49 +82,49 @@ constexpr void init_shortest_paths(Distances& distances, Predecessors& predecess
8282
// Vertex visitor concepts
8383
template <class G, class Visitor>
8484
concept has_on_initialize_vertex = // For exposition only
85-
requires(Visitor& v, vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
85+
requires(Visitor& v, vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
8686
{ v.on_initialize_vertex(vdesc) };
8787
};
8888
template <class G, class Visitor>
8989
concept has_on_discover_vertex = // For exposition only
90-
requires(Visitor& v, vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
90+
requires(Visitor& v, vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
9191
{ v.on_discover_vertex(vdesc) };
9292
};
9393
template <class G, class Visitor>
9494
concept has_on_examine_vertex = // For exposition only
95-
requires(Visitor& v, vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
95+
requires(Visitor& v, vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
9696
{ v.on_examine_vertex(vdesc) };
9797
};
9898
template <class G, class Visitor>
9999
concept has_on_finish_vertex = // For exposition only
100-
requires(Visitor& v, vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
100+
requires(Visitor& v, vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
101101
{ v.on_finish_vertex(vdesc) };
102102
};
103103

104104
// Edge visitor concepts
105105
template <class G, class Visitor>
106106
concept has_on_examine_edge = // For exposition only
107-
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
107+
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
108108
{ v.on_examine_edge(edesc) };
109109
};
110110
template <class G, class Visitor>
111111
concept has_on_edge_relaxed = // For exposition only
112-
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
112+
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
113113
{ v.on_edge_relaxed(edesc) };
114114
};
115115
template <class G, class Visitor>
116116
concept has_on_edge_not_relaxed = // For exposition only
117-
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
117+
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
118118
{ v.on_edge_not_relaxed(edesc) };
119119
};
120120
template <class G, class Visitor>
121121
concept has_on_edge_minimized = // For exposition only
122-
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
122+
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
123123
{ v.on_edge_minimized(edesc) };
124124
};
125125
template <class G, class Visitor>
126126
concept has_on_edge_not_minimized = // For exposition only
127-
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
127+
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
128128
{ v.on_edge_not_minimized(edesc) };
129129
};
130130

include/graph/algorithm/dijkstra_clrs.hpp

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,26 @@ concept edge_weight_function2 = // e.g. weight(uv)
2828
basic_edge_weight_function2<G, WF, Distance, less<range_value_t<Distance>>, plus<range_value_t<Distance>>>;
2929

3030

31-
class null_range_type : public std::vector<size_t> {
31+
class _null_range_type : public std::vector<size_t> {
3232
using T = size_t;
3333
using Allocator = std::allocator<T>;
3434
using Base = std::vector<T, Allocator>;
3535

3636
public:
37-
null_range_type() noexcept(noexcept(Allocator())) = default;
38-
explicit null_range_type(const Allocator& alloc) noexcept {}
39-
null_range_type(Base::size_type count, const T& value, const Allocator& alloc = Allocator()) {}
40-
explicit null_range_type(Base::size_type count, const Allocator& alloc = Allocator()) {}
37+
_null_range_type() noexcept(noexcept(Allocator())) = default;
38+
explicit _null_range_type(const Allocator& alloc) noexcept {}
39+
_null_range_type(Base::size_type count, const T& value, const Allocator& alloc = Allocator()) {}
40+
explicit _null_range_type(Base::size_type count, const Allocator& alloc = Allocator()) {}
4141
template <class InputIt>
42-
null_range_type(InputIt first, InputIt last, const Allocator& alloc = Allocator()) {}
43-
null_range_type(const null_range_type& other) : Base() {}
44-
null_range_type(const null_range_type& other, const Allocator& alloc) {}
45-
null_range_type(null_range_type&& other) noexcept {}
46-
null_range_type(null_range_type&& other, const Allocator& alloc) {}
47-
null_range_type(std::initializer_list<T> init, const Allocator& alloc = Allocator()) {}
42+
_null_range_type(InputIt first, InputIt last, const Allocator& alloc = Allocator()) {}
43+
_null_range_type(const _null_range_type& other) : Base() {}
44+
_null_range_type(const _null_range_type& other, const Allocator& alloc) {}
45+
_null_range_type(_null_range_type&& other) noexcept {}
46+
_null_range_type(_null_range_type&& other, const Allocator& alloc) {}
47+
_null_range_type(std::initializer_list<T> init, const Allocator& alloc = Allocator()) {}
4848
};
4949

50-
inline static null_range_type null_predecessors;
50+
inline static _null_range_type null_predecessors;
5151

5252

5353
template <class... Ts>
@@ -80,6 +80,9 @@ constexpr auto print_types(Ts...) {
8080
* The edge weight function must not throw an exception.
8181
* The edge weight function must not modify the graph, the edge, or the vertex (nor any of their associated data).
8282
*/
83+
84+
#if 1 // not using Identifiers (original)
85+
8386
template <adjacency_list G,
8487
random_access_range Distance,
8588
random_access_range Predecessor,
@@ -101,7 +104,7 @@ void dijkstra_clrs(
101104

102105
// Remark(Andrew): Do we want to allow null distance? What about if both are null? Still run algorithm at all?
103106

104-
size_t N(size(vertices(g))); // Question(Andrew): Do we want a num_vertices(g) CPO?
107+
size_t N(num_vertices(g));
105108
assert(seed < N && seed >= 0);
106109

107110
std::ranges::fill(distance, std::numeric_limits<weight_type>::max());
@@ -129,12 +132,68 @@ void dijkstra_clrs(
129132
//weight_type w = weight(uv);
130133
if (distance[uid] + w < distance[vid]) {
131134
distance[vid] = distance[uid] + w;
132-
if constexpr (!is_same_v<Predecessor, null_range_type>)
135+
if constexpr (!is_same_v<Predecessor, _null_range_type>)
136+
predecessor[vid] = uid;
137+
Q.push({vid, distance[vid]});
138+
}
139+
}
140+
}
141+
}
142+
143+
#else // using Identifiers
144+
145+
template <adjacency_list G,
146+
random_access_range Distance,
147+
random_access_range Predecessor,
148+
class WF = function<range_value_t<Distance>(edge_identifier_t<G>)>>
149+
requires random_access_range<vertex_range_t<G>> && //
150+
integral<vertex_id_t<G>> && //
151+
is_arithmetic_v<range_value_t<Distance>> && //
152+
convertible_to<vertex_id_t<G>, range_value_t<Predecessor>> && //
153+
edge_weight_function<G, WF>
154+
void dijkstra_clrs(
155+
G&& g, // graph
156+
vertex_identifier_t<G> seed, // starting vertex_id
157+
Distance& distance, // out: distance[uid] of uid from seed
158+
Predecessor& predecessor, // out: predecessor[uid] of uid in path
159+
WF&& weight = [](edge_identifier_t<G> uv) { return range_value_t<Distance>(1); }) // default weight(uv) -> 1
160+
{
161+
using id_type = vertex_id_t<G>;
162+
using weight_type = invoke_result_t<WF, edge_identifer_t<G>>;
163+
const id_type seed_id = vertex_id(g, seed);
164+
165+
size_t N(num_vertices(g));
166+
assert(seed_id < N && seed_id >= 0);
167+
168+
std::ranges::fill(distance, std::numeric_limits<weight_type>::max());
169+
distance[seed_id] = 0;
170+
171+
struct weighted_vertex {
172+
id_type vertex_id = id_type();
173+
weight_type weight = weight_type();
174+
};
175+
176+
using q_compare = decltype([](const weighted_vertex& a, const weighted_vertex& b) { return a.weight > b.weight; });
177+
std::priority_queue<weighted_vertex, std::vector<weighted_vertex>, q_compare> Q;
178+
179+
Q.push({seed_id, distance[seed_id]});
180+
181+
while (!Q.empty()) {
182+
auto uid = Q.top().vertex_id;
183+
Q.pop();
184+
185+
for (auto&& [v_identifier, uv_identifier, w] : views::incidence(g, find_vertex(g, uid), weight)) {
186+
id_type vid = vertex_id(v_identifier);
187+
if (distance[uid] + w < distance[vid]) {
188+
distance[vid] = distance[uid] + w;
189+
if constexpr (!is_same_v<Predecessor, _null_range_type>)
133190
predecessor[vid] = uid;
134191
Q.push({vid, distance[vid]});
135192
}
136193
}
137194
}
138195
}
139196
197+
#endif // Identifiers
198+
140199
} // namespace graph

include/graph/algorithm/experimental/co_cmn.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ concept edge_weight_function = // e.g. weight(uv)
2020
is_arithmetic_v<invoke_result_t<WF, edge_reference_t<G>>> &&
2121
basic_edge_weight_function<G, WF, DistanceValue, less<DistanceValue>, plus<DistanceValue>>;
2222

23-
// These types comprise the bfs value type, made up of bfs_events and variant<vertex_descriptor, edge_descriptor>.
23+
// These types comprise the bfs value type, made up of bfs_events and variant<vertex_info, edge_info>.
2424
// monostate is used to indicate that the value is not set and to make it default-constructible.
2525
template <class G, class VValue = void>
26-
using bfs_vertex_value_t = vertex_descriptor<vertex_id_t<G>, reference_wrapper<vertex_t<G>>, VValue>;
26+
using bfs_vertex_value_t = vertex_info<vertex_id_t<G>, reference_wrapper<vertex_t<G>>, VValue>;
2727
template <class G>
28-
using bfs_edge_value_t = edge_descriptor<vertex_id_t<G>, true, reference_wrapper<edge_t<G>>, void>;
28+
using bfs_edge_value_t = edge_info<vertex_id_t<G>, true, reference_wrapper<edge_t<G>>, void>;
2929
template <class G, class VValue = void>
3030
using bfs_variant_value_t = std::variant<std::monostate, bfs_vertex_value_t<G, VValue>, bfs_edge_value_t<G>>;
3131

include/graph/algorithm/experimental/visitor_dijkstra.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ class dijkstra_visitor_base {
6464
// Types
6565
public:
6666
using graph_type = G;
67-
using vertex_desc_type = vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void>;
68-
using sourced_edge_desc_type = edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void>;
67+
using vertex_desc_type = vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void>;
68+
using sourced_edge_desc_type = edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void>;
6969

7070
// Visitor Functions
7171
public:

include/graph/algorithm/mst.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,9 @@ void kruskal(IELR&& e, // graph
167167
OELR&& t, // tree
168168
CompareOp compare // edge value comparitor
169169
) {
170-
using edge_descriptor = range_value_t<IELR>;
171-
using VId = remove_const_t<typename edge_descriptor::source_id_type>;
172-
using EV = edge_descriptor::value_type;
170+
using edge_info = range_value_t<IELR>;
171+
using VId = remove_const_t<typename edge_info::source_id_type>;
172+
using EV = edge_info::value_type;
173173

174174
std::vector<tuple<VId, VId, EV>> e_copy;
175175
std::ranges::transform(e, back_inserter(e_copy),
@@ -241,8 +241,8 @@ void inplace_kruskal(IELR&& e, // graph
241241
OELR&& t, // tree
242242
CompareOp compare // edge value comparitor
243243
) {
244-
using edge_descriptor = range_value_t<IELR>;
245-
using VId = remove_const_t<typename edge_descriptor::source_id_type>;
244+
using edge_info = range_value_t<IELR>;
245+
using VId = remove_const_t<typename edge_info::source_id_type>;
246246

247247
VId N = 0;
248248
auto outer_compare = [&](auto&& i, auto&& j) {

include/graph/container/compressed_graph.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ class compressed_graph<EV, VV, void, VId, EIndex, Alloc>
11061106
const Alloc& alloc = Alloc())
11071107
: base_type(erng, vrng, eprojection, vprojection, partition_start_ids, alloc) {}
11081108

1109-
// initializer list using edge_descriptor<VId,true,void,EV>
1109+
// initializer list using edge_info<VId,true,void,EV>
11101110
constexpr compressed_graph(const std::initializer_list<copyable_edge_t<VId, EV>>& ilist, const Alloc& alloc = Alloc())
11111111
: base_type(ilist, alloc) {}
11121112
};

0 commit comments

Comments
 (0)