Replies: 1 comment
-
I think that the map-like adjacency list representation could work without introducing new graph concepts. I think that algorithms could operate both on both index-based and map-like adjacency lists using a single concept Pull request #173 demonstrates how this would work for Dijkstra's shortest paths. It could be achieved via one building-block customization point + a building block concept for interoperating with containers such as CPO: template <typename Cont, typename UID>
auto* vertex_record(Cont& cont, UID uid); Were:
Helper alias: template <typename Cont, typename G>
using record_t = decltype(*vertex_record(std::declval<Cont&>(), std::declval<vertex_id_t<G>>())); CPO default implementations: template <std::ranges::random_access_range Cont, typename G>
requires std::sized_integral<vertex_id_t<G>>
auto* vertex_record(Cont& cont, vertex_id_t<G> uid)
{
if (0 <= uid && uid < cont.size())
return cont[uid];
else
return nullptr;
} template <MapLike Cont, typename G>
requires std::regular<vertex_id_t<G>>
auto* vertex_record(Cont& cont, vertex_id_t<G> uid)
{
return cont[uid];
} Helper concept: template <typename Cont, typename G>
concept record_for = requires(Cont& cont, vertex_id_t<G>& id)
{
{ vertex_record(cont, id) } -> std::regular;
/*
requires requires(G g) // semantic requirements
{
// for (vertex_iterator_t<G> it : vertices(g))
// assert(vertex_record(cont, vertex_id(g, it)) != nullptr);
};
*/
}; The declaration of the Dijkstra's algorithm: template <adjacency_list G,
input_range Sources,
record_for<G> Distances,
record_for<G> Predecessors,
class WF = function<record_t<Distances, G>(edge_reference_t<G>)>,
class Visitor = empty_visitor,
class Compare = less<record_t<Distances, G>>,
class Combine = plus<record_t<Distances, G>>>
requires convertible_to<range_value_t<Sources>, vertex_id_t<G>> &&
convertible_to<vertex_id_t<G>, record_t<Predecessors, G>> &&
basic_edge_weight_function<G, WF, record_t<Distances, G>, Compare, Combine>
constexpr void dijkstra_shortest_paths(
G&& g,
const Sources& sources,
Distances& distances,
Predecessors& predecessor,
WF&& weight = [](edge_reference_t<G> uv) { return record_t<Distances, G>(1); },
Visitor&& visitor = empty_visitor(),
Compare&& compare = less<record_t<Distances, G>>(),
Combine&& combine = plus<record_t<Distances, G>>()); |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
First of all, your use case is very valuable, and for one, it deserves to be described in the graph papers.
I acknowledge the need to have an adjacency list with a map-like vertex look-up. But it is still not clear to me what you want to do about this adjacency list representation in the graph-v2 library.
You say:
So, you want to write your own algorithm, you have your own graph representation. What do you need this library for then?
You say:
So it looks like you consider an option that graph-v2 algorithms (such as
dijkstra_shortest_paths
) would support your graph representation. In that case, I note that the algorithm requires not only traversing the graph, but also recording the visited nodes in the output parameter, such aspredecessor
. So concept (non-index
)adjacency_list
is not enough: you would also need to have a concept for recording a visited node in the collection of nodes.Anyway, my general observation is that this library should have either of the two answers to the question of supporting non-index adjacency lists:
But, in my opinion, it would be wrong to have a half-measure solution, such as having concept
adjacency_list
but no prove or no signal that the library would be able to do anything with non-index adjacency lists.Beta Was this translation helpful? Give feedback.
All reactions