Skip to content
Merged
17 changes: 11 additions & 6 deletions D3129_Views/tex/views.tex
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ \section{Data Structs (Return Types)}\label{sec:data-structs}
\end{lstlisting}

\subsection{\tcode{struct vertex_data<VId, V, VV>}}\label{vertex-view}\mbox{} \\
\tcode{vertex_data} is used to return vertex information. It is used by \tcode{vertexlist(g)}, \tcode{vertices_breadth_first_search(g,u)},
\tcode{vertex_data} is used to return vertex information. It is used by \tcode{vertexlist(g)}, \tcode{vertices_bfs(g,u)},
\tcode{vertices_dfs(g,u)} and others. The \tcode{id} member is the vertex id, the \tcode{vertex} member is the vertex descriptor,
and \tcode{value} is the result of the value function, if provided.

Expand Down Expand Up @@ -100,7 +100,7 @@ \subsection{\tcode{struct vertex_data<VId, V, VV>}}\label{vertex-view}\mbox{} \\
\subsection{\tcode{struct edge_data<VId, Sourced, E, EV>}}\label{edge-view}\mbox{} \\

\tcode{edge_data} is used to return edge information. It is used by
\tcode{incidence(g,u), edgelist(g), edges_breadth_first_search(g,u), edges_dfs(g,u)} and others.
\tcode{incidence(g,u), edgelist(g), edges_bfs(g,u), edges_dfs(g,u)} and others.
\tcode{source_id} and \tcode{target_id} are vertex ids of type \tcode{vertex_id_t<G>}.

When \tcode{Sourced=true}, the \tcode{source_id} member is included. The \tcode{target_id} member always exists.
Expand Down Expand Up @@ -163,9 +163,11 @@ \subsection{\tcode{struct neighbor_data<VId, Sourced, V, VV>}}\label{neighbor-vi
\hline
\tcode{neighbor_data<VId, true, V, VV>} & \tcode{source_id} & \tcode{target_id} & \tcode{target} & \tcode{value} \\
\tcode{neighbor_data<VId, true, V, void>} & \tcode{source_id} & \tcode{target_id} & \tcode{target} & \\
\tcode{neighbor_data<VId, true, void, VV>} & \tcode{source_id} & \tcode{target_id} & & \tcode{value} \\
\tcode{neighbor_data<VId, true, void, void>} & \tcode{source_id} & \tcode{target_id} & & \\
\tcode{neighbor_data<VId, false, V, VV>} & & \tcode{target_id} & \tcode{target} & \tcode{value} \\
\tcode{neighbor_data<VId, false, V, void>} & & \tcode{target_id} & \tcode{target} & \\
\tcode{neighbor_data<VId, false, void, VV>} & & \tcode{target_id} & & \tcode{value} \\
\tcode{neighbor_data<VId, false, void, void>} & & \tcode{target_id} & & \\
\hline
\end{tabular}}
Expand Down Expand Up @@ -387,8 +389,8 @@ \subsection{Common Types and Functions for ``Search'' }
\begin{lstlisting}
cancel_search cancel() const noexcept; // get current cancel state
void cancel(cancel_search c) noexcept; // set cancel state
std::size_t depth() const noexcept; // distance from seed to current vertex
std::size_t num_visited() const noexcept; // total vertices/edges visited so far
std::size_t depth() const noexcept; // depth of currently yielded element (seed is 0)
std::size_t num_visited() const noexcept; // elements yielded so far, including the current element
\end{lstlisting}

The \tcode{search_view} concept captures these requirements:
Expand All @@ -403,12 +405,15 @@ \subsection{Common Types and Functions for ``Search'' }

Topological sort views support \tcode{cancel()} and \tcode{num_visited()} but not \tcode{depth()} (flat ordering has no tree structure), so they do not satisfy \tcode{search_view}.

For DFS, \tcode{dfs.num_visited()} is typically close to \tcode{dfs.depth()} and is simple to calculate. Breadth-first search requires extra bookkeeping to evaluate \tcode{bfs.depth()}, which returns a different value than \tcode{bfs.num_visited()}.
For views that satisfy \tcode{search_view} (DFS and BFS), \tcode{depth()} denotes the depth of the currently yielded element measured from the seed. The seed has depth 0, and each traversed edge increases depth by 1.

\tcode{num_visited()} returns the number of elements yielded so far, \emph{including the element currently held by the loop variable}. On the first iteration it equals 1 (the seed for vertex views, the first tree edge for edge views). This makes threshold checks inside the loop body intuitive: when the loop body executes, \tcode{num_visited()} reflects the current position rather than the previous one.

The following example shows how the member functions could be used, using \tcode{dfs} for one of the depth-first search views. The same members are available on all search views that satisfy \tcode{search_view}.
\begin{lstlisting}
auto&& g = ...; // graph
auto&& dfs = vertices_dfs(g,0); // start with seed vertex\_id=0
// On first iteration: dfs.depth()==0, dfs.num\_visited()==1
for(auto&& [uid,u] : dfs) {
// No need to search deeper?
if(dfs.depth() > 3) {
Expand Down Expand Up @@ -533,7 +538,7 @@ \subsection{Topological Sort Views}

\section{Range Adaptors (Pipe Syntax)}

All view factory functions described in this paper are also available as range adaptor closure objects, enabling pipe syntax. The adaptor objects live in \tcode{namespace graph::views} and forward to the corresponding factory function. Table \ref{tab:adaptors_graph} shows the graph view adaptors and Table \ref{tab:adaptors_search} shows the search view adaptors.
All range-returning, non-\tcode{_safe} view factories listed in Tables \ref{tab:adaptors_graph} and \ref{tab:adaptors_search} are also available as range adaptor closure objects, enabling pipe syntax. The adaptor objects live in \tcode{namespace graph::views} and forward to the corresponding factory function. The \tcode{_safe} topological-sort factories return \tcode{std::expected} and are not adaptor closures. \tcode{transpose} is a graph adaptor (not a range adaptor) and remains documented separately.

\begin{table}[h!]
\begin{center}
Expand Down
11 changes: 9 additions & 2 deletions D3130_Container_Interface/src/concepts_edges.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
// For exposition only

// Shared edge floor (namespace std::graph): ids only.
template <class G, class E>
concept edge = requires(G& g, const E& e) {
concept basic_edge = requires(G& g, const E& e) {
source_id(g, e);
source(g, e);
target_id(g, e);
};

// Adjacency-list refinement (namespace std::graph::adj\_list):
// adds the source/target vertex descriptors.
template <class G, class E>
concept edge = basic_edge<G, E> && requires(G& g, const E& e) {
source(g, e);
target(g, e);
};
16 changes: 12 additions & 4 deletions D3130_Container_Interface/src/concepts_vertex_range.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// For exposition only

template <class G, class V>
concept vertex = requires(G& g, const V& u, const vertex_id_t<G>& uid) {
vertex_id(g, u);
find_vertex(g, uid);
};
concept vertex = is_vertex_descriptor_v<remove_cvref_t<V>> &&
requires(G& g, const V& u, const vertex_id_t<G>& uid) {
vertex_id(g, u);
find_vertex(g, uid);
};

template <class R, class G>
concept vertex_range = forward_range<R> &&
Expand All @@ -19,9 +20,16 @@ concept index_vertex_range =
{ vertices(g) } -> vertex_range<G>;
};

// vertex id usable as an unordered\_map key (for mapped property maps)
template <class G>
concept hashable_vertex_id = requires(const vertex_id_t<G>& uid) {
{ hash<vertex_id_t<G>>{}(uid) } -> convertible_to<size_t>;
};

template <class G>
concept mapped_vertex_range =
!index_vertex_range<G> &&
hashable_vertex_id<G> &&
requires(G& g, const vertex_id_t<G>& uid) {
{ vertices(g) } -> forward_range;
find_vertex(g, uid);
Expand Down
6 changes: 3 additions & 3 deletions D3130_Container_Interface/src/descriptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ class edge_descriptor {
static constexpr bool is_in_edge = is_same_v<EdgeDirection, in_edge_tag>;
static constexpr bool is_out_edge = is_same_v<EdgeDirection, out_edge_tag>;

// index for random-access, iterator for forward (for exposition only)
using edge_storage_type =
conditional_t<random_access_iterator<EdgeIter>, size_t, EdgeIter>;
// Edges are always backed by a physical container, so the edge is
// stored as its iterator directly (no index-only path). (for exposition only)
using edge_storage_type = EdgeIter;

constexpr edge_descriptor() = default;
constexpr edge_descriptor(edge_storage_type edge_val,
Expand Down
5 changes: 1 addition & 4 deletions D3130_Container_Interface/src/edgelist_concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ template <class EL>
concept basic_sourced_edgelist =
ranges::input_range<EL> &&
!ranges::range<ranges::range_value_t<EL>> &&
requires(EL& el, ranges::range_value_t<EL> uv) {
{ source_id(el, uv) };
{ target_id(el, uv) } -> convertible_to<decltype(source_id(el, uv))>;
};
basic_edge<EL, ranges::range_value_t<EL>>; // shared edge floor: source\_id + target\_id

template <class EL>
concept basic_sourced_index_edgelist =
Expand Down
Loading
Loading