Skip to content
Merged
2 changes: 1 addition & 1 deletion example/CppCon2022/rr_adaptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class rr_adaptor {
template <std::ranges::forward_range ERng, class EProj = std::identity>
rr_adaptor(VVR& vertex_values, //
const ERng& erng, //
const EProj& eproj = EProj(), // EProj(ERng::value_type&) -> edge_descriptor<VId,true[,val]>
const EProj& eproj = EProj(), // EProj(ERng::value_type&) -> edge_info<VId,true[,val]>
bool dup_edges = false)
: vertex_values_(vertex_values) {
vertex_id_type max_vid = max_vertex_id(erng, eproj);
Expand Down
18 changes: 9 additions & 9 deletions include/graph/algorithm/common_shortest_paths.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,49 +82,49 @@ constexpr void init_shortest_paths(Distances& distances, Predecessors& predecess
// Vertex visitor concepts
template <class G, class Visitor>
concept has_on_initialize_vertex = // For exposition only
requires(Visitor& v, vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
requires(Visitor& v, vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
{ v.on_initialize_vertex(vdesc) };
};
template <class G, class Visitor>
concept has_on_discover_vertex = // For exposition only
requires(Visitor& v, vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
requires(Visitor& v, vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
{ v.on_discover_vertex(vdesc) };
};
template <class G, class Visitor>
concept has_on_examine_vertex = // For exposition only
requires(Visitor& v, vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
requires(Visitor& v, vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
{ v.on_examine_vertex(vdesc) };
};
template <class G, class Visitor>
concept has_on_finish_vertex = // For exposition only
requires(Visitor& v, vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
requires(Visitor& v, vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void> vdesc) {
{ v.on_finish_vertex(vdesc) };
};

// Edge visitor concepts
template <class G, class Visitor>
concept has_on_examine_edge = // For exposition only
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
{ v.on_examine_edge(edesc) };
};
template <class G, class Visitor>
concept has_on_edge_relaxed = // For exposition only
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
{ v.on_edge_relaxed(edesc) };
};
template <class G, class Visitor>
concept has_on_edge_not_relaxed = // For exposition only
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
{ v.on_edge_not_relaxed(edesc) };
};
template <class G, class Visitor>
concept has_on_edge_minimized = // For exposition only
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
{ v.on_edge_minimized(edesc) };
};
template <class G, class Visitor>
concept has_on_edge_not_minimized = // For exposition only
requires(Visitor& v, edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
requires(Visitor& v, edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void> edesc) {
{ v.on_edge_not_minimized(edesc) };
};

Expand Down
87 changes: 73 additions & 14 deletions include/graph/algorithm/dijkstra_clrs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,26 @@ concept edge_weight_function2 = // e.g. weight(uv)
basic_edge_weight_function2<G, WF, Distance, less<range_value_t<Distance>>, plus<range_value_t<Distance>>>;


class null_range_type : public std::vector<size_t> {
class _null_range_type : public std::vector<size_t> {
using T = size_t;
using Allocator = std::allocator<T>;
using Base = std::vector<T, Allocator>;

public:
null_range_type() noexcept(noexcept(Allocator())) = default;
explicit null_range_type(const Allocator& alloc) noexcept {}
null_range_type(Base::size_type count, const T& value, const Allocator& alloc = Allocator()) {}
explicit null_range_type(Base::size_type count, const Allocator& alloc = Allocator()) {}
_null_range_type() noexcept(noexcept(Allocator())) = default;
explicit _null_range_type(const Allocator& alloc) noexcept {}
_null_range_type(Base::size_type count, const T& value, const Allocator& alloc = Allocator()) {}
explicit _null_range_type(Base::size_type count, const Allocator& alloc = Allocator()) {}
template <class InputIt>
null_range_type(InputIt first, InputIt last, const Allocator& alloc = Allocator()) {}
null_range_type(const null_range_type& other) : Base() {}
null_range_type(const null_range_type& other, const Allocator& alloc) {}
null_range_type(null_range_type&& other) noexcept {}
null_range_type(null_range_type&& other, const Allocator& alloc) {}
null_range_type(std::initializer_list<T> init, const Allocator& alloc = Allocator()) {}
_null_range_type(InputIt first, InputIt last, const Allocator& alloc = Allocator()) {}
_null_range_type(const _null_range_type& other) : Base() {}
_null_range_type(const _null_range_type& other, const Allocator& alloc) {}
_null_range_type(_null_range_type&& other) noexcept {}
_null_range_type(_null_range_type&& other, const Allocator& alloc) {}
_null_range_type(std::initializer_list<T> init, const Allocator& alloc = Allocator()) {}
};

inline static null_range_type null_predecessors;
inline static _null_range_type null_predecessors;


template <class... Ts>
Expand Down Expand Up @@ -80,6 +80,9 @@ constexpr auto print_types(Ts...) {
* The edge weight function must not throw an exception.
* The edge weight function must not modify the graph, the edge, or the vertex (nor any of their associated data).
*/

#if 1 // not using Identifiers (original)

template <adjacency_list G,
random_access_range Distance,
random_access_range Predecessor,
Expand All @@ -101,7 +104,7 @@ void dijkstra_clrs(

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

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

std::ranges::fill(distance, std::numeric_limits<weight_type>::max());
Expand Down Expand Up @@ -129,12 +132,68 @@ void dijkstra_clrs(
//weight_type w = weight(uv);
if (distance[uid] + w < distance[vid]) {
distance[vid] = distance[uid] + w;
if constexpr (!is_same_v<Predecessor, null_range_type>)
if constexpr (!is_same_v<Predecessor, _null_range_type>)
predecessor[vid] = uid;
Q.push({vid, distance[vid]});
}
}
}
}

#else // using Identifiers

template <adjacency_list G,
random_access_range Distance,
random_access_range Predecessor,
class WF = function<range_value_t<Distance>(edge_identifier_t<G>)>>
requires random_access_range<vertex_range_t<G>> && //
integral<vertex_id_t<G>> && //
is_arithmetic_v<range_value_t<Distance>> && //
convertible_to<vertex_id_t<G>, range_value_t<Predecessor>> && //
edge_weight_function<G, WF>
void dijkstra_clrs(
G&& g, // graph
vertex_identifier_t<G> seed, // starting vertex_id
Distance& distance, // out: distance[uid] of uid from seed
Predecessor& predecessor, // out: predecessor[uid] of uid in path
WF&& weight = [](edge_identifier_t<G> uv) { return range_value_t<Distance>(1); }) // default weight(uv) -> 1
{
using id_type = vertex_id_t<G>;
using weight_type = invoke_result_t<WF, edge_identifer_t<G>>;
const id_type seed_id = vertex_id(g, seed);

size_t N(num_vertices(g));
assert(seed_id < N && seed_id >= 0);

std::ranges::fill(distance, std::numeric_limits<weight_type>::max());
distance[seed_id] = 0;

struct weighted_vertex {
id_type vertex_id = id_type();
weight_type weight = weight_type();
};

using q_compare = decltype([](const weighted_vertex& a, const weighted_vertex& b) { return a.weight > b.weight; });
std::priority_queue<weighted_vertex, std::vector<weighted_vertex>, q_compare> Q;

Q.push({seed_id, distance[seed_id]});

while (!Q.empty()) {
auto uid = Q.top().vertex_id;
Q.pop();

for (auto&& [v_identifier, uv_identifier, w] : views::incidence(g, find_vertex(g, uid), weight)) {
id_type vid = vertex_id(v_identifier);
if (distance[uid] + w < distance[vid]) {
distance[vid] = distance[uid] + w;
if constexpr (!is_same_v<Predecessor, _null_range_type>)
predecessor[vid] = uid;
Q.push({vid, distance[vid]});
}
}
}
}

#endif // Identifiers

} // namespace graph
6 changes: 3 additions & 3 deletions include/graph/algorithm/experimental/co_cmn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ concept edge_weight_function = // e.g. weight(uv)
is_arithmetic_v<invoke_result_t<WF, edge_reference_t<G>>> &&
basic_edge_weight_function<G, WF, DistanceValue, less<DistanceValue>, plus<DistanceValue>>;

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

Expand Down
4 changes: 2 additions & 2 deletions include/graph/algorithm/experimental/visitor_dijkstra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ class dijkstra_visitor_base {
// Types
public:
using graph_type = G;
using vertex_desc_type = vertex_descriptor<vertex_id_t<G>, vertex_reference_t<G>, void>;
using sourced_edge_desc_type = edge_descriptor<vertex_id_t<G>, true, edge_reference_t<G>, void>;
using vertex_desc_type = vertex_info<vertex_id_t<G>, vertex_reference_t<G>, void>;
using sourced_edge_desc_type = edge_info<vertex_id_t<G>, true, edge_reference_t<G>, void>;

// Visitor Functions
public:
Expand Down
10 changes: 5 additions & 5 deletions include/graph/algorithm/mst.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ void kruskal(IELR&& e, // graph
OELR&& t, // tree
CompareOp compare // edge value comparitor
) {
using edge_descriptor = range_value_t<IELR>;
using VId = remove_const_t<typename edge_descriptor::source_id_type>;
using EV = edge_descriptor::value_type;
using edge_info = range_value_t<IELR>;
using VId = remove_const_t<typename edge_info::source_id_type>;
using EV = edge_info::value_type;

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

VId N = 0;
auto outer_compare = [&](auto&& i, auto&& j) {
Expand Down
2 changes: 1 addition & 1 deletion include/graph/container/compressed_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ class compressed_graph<EV, VV, void, VId, EIndex, Alloc>
const Alloc& alloc = Alloc())
: base_type(erng, vrng, eprojection, vprojection, partition_start_ids, alloc) {}

// initializer list using edge_descriptor<VId,true,void,EV>
// initializer list using edge_info<VId,true,void,EV>
constexpr compressed_graph(const std::initializer_list<copyable_edge_t<VId, EV>>& ilist, const Alloc& alloc = Alloc())
: base_type(ilist, alloc) {}
};
Expand Down
Loading
Loading