@@ -20,12 +20,28 @@ limitations under the License.
2020
2121#include " iterator_concepts.hpp"
2222
23+ /* *
24+ * @file graph_traits.hpp
25+ * @brief Type traits and concepts for graph structures in OneStopParallel.
26+ *
27+ * This file defines the core requirements for types used by graph implementations in the library,
28+ * specifically for computational DAGs. It provides mechanisms
29+ * to extract types for vertex indices, edge descriptors, and weights,
30+ * ensuring that graph implementations conform to the expected interfaces.
31+ */
32+
2333namespace osp {
2434
25- #define DEFINE_TYPE_MEMBER_TEST (test_name, member_name ) \
26- template <typename T, typename = void > \
27- struct test_name : std::false_type {}; \
28- template <typename T> \
35+ /* *
36+ * @brief Macro to define a trait that checks for the existence of a specific type member.
37+ *
38+ * Creates a struct `test_name<T>` inheriting from `std::true_type` if `T::member_name` exists,
39+ * otherwise inherits from `std::false_type`.
40+ */
41+ #define DEFINE_TYPE_MEMBER_TEST (test_name, member_name ) \
42+ template <typename T, typename = void > \
43+ struct test_name : std::false_type {}; \
44+ template <typename T> \
2945 struct test_name <T, std::void_t <typename T::member_name>> : std::true_type {};
3046
3147DEFINE_TYPE_MEMBER_TEST (has_vertex_idx_tmember, vertex_idx)
@@ -36,17 +52,33 @@ DEFINE_TYPE_MEMBER_TEST(has_vertex_mem_weight_tmember, vertex_mem_weight_type)
3652DEFINE_TYPE_MEMBER_TEST (has_vertex_type_tmember, vertex_type_type)
3753DEFINE_TYPE_MEMBER_TEST (has_edge_comm_weight_tmember, edge_comm_weight_type)
3854
39- // Every directed graph must have a vertex_idx type
55+ /* *
56+ * @brief Core traits for any directed graph type.
57+ *
58+ * Requires that the graph type `T` defines a `vertex_idx` type member.
59+ *
60+ * @tparam T The graph type.
61+ */
4062template <typename T>
4163struct directed_graph_traits {
4264 static_assert (has_vertex_idx_tmember<T>::value, " graph must have vertex_idx" );
4365 using vertex_idx = typename T::vertex_idx;
4466};
4567
46- // Macro to extract the vertex_idx type from the graph
68+ /* *
69+ * @brief Alias to easily access the vertex index type of a graph.
70+ */
4771template <typename T>
4872using vertex_idx_t = typename directed_graph_traits<T>::vertex_idx;
4973
74+ /* *
75+ * @brief A default edge descriptor for directed graphs.
76+ *
77+ * This struct is used when the graph type does not provide its own edge descriptor.
78+ * It simply holds the source and target vertex indices.
79+ *
80+ * @tparam Graph_t The graph type.
81+ */
5082template <typename Graph_t>
5183struct directed_edge {
5284
@@ -65,6 +97,11 @@ struct directed_edge {
6597 directed_edge (vertex_idx_t <Graph_t> src, vertex_idx_t <Graph_t> tgt) : source(src), target(tgt) {}
6698};
6799
100+ /* *
101+ * @brief Helper struct to extract the edge descriptor type of a directed graph.
102+ *
103+ * If the graph defines `directed_edge_descriptor`, it is extracted; otherwise, `directed_edge` is used as a default implementation.
104+ */
68105template <typename T, bool has_edge>
69106struct directed_graph_edge_desc_traits_helper {
70107 using directed_edge_descriptor = directed_edge<T>;
@@ -84,6 +121,16 @@ struct directed_graph_edge_desc_traits {
84121template <typename T>
85122using edge_desc_t = typename directed_graph_edge_desc_traits<T>::directed_edge_descriptor;
86123
124+ /* *
125+ * @brief Traits for computational Directed Acyclic Graphs (DAGs).
126+ *
127+ * Computational DAGs extend basic graphs by adding requirements for weight types:
128+ * - `vertex_work_weight_type`: Represents computational cost of a task.
129+ * - `vertex_comm_weight_type`: Represents data size/communication cost.
130+ * - `vertex_mem_weight_type`: Represents memory usage of a task.
131+ *
132+ * @tparam T The computational DAG type.
133+ */
87134template <typename T>
88135struct computational_dag_traits {
89136 static_assert (has_vertex_work_weight_tmember<T>::value, " cdag must have vertex work weight type" );
@@ -104,6 +151,11 @@ using v_commw_t = typename computational_dag_traits<T>::vertex_comm_weight_type;
104151template <typename T>
105152using v_memw_t = typename computational_dag_traits<T>::vertex_mem_weight_type;
106153
154+ /* *
155+ * @brief Traits to extract the vertex type of a computational DAG, if defined.
156+ *
157+ * If the DAG defines `vertex_type_type`, it is extracted; otherwise, `void` is used.
158+ */
107159template <typename T, typename = void >
108160struct computational_dag_typed_vertices_traits {
109161 using vertex_type_type = void ;
@@ -117,6 +169,11 @@ struct computational_dag_typed_vertices_traits<T, std::void_t<typename T::vertex
117169template <typename T>
118170using v_type_t = typename computational_dag_typed_vertices_traits<T>::vertex_type_type;
119171
172+ /* *
173+ * @brief Traits to extract the edge communication weight type of a computational DAG, if defined.
174+ *
175+ * If the DAG defines `edge_comm_weight_type`, it is extracted; otherwise, `void` is used.
176+ */
120177template <typename T, typename = void >
121178struct computational_dag_edge_desc_traits {
122179 using edge_comm_weight_type = void ;
@@ -130,6 +187,14 @@ struct computational_dag_edge_desc_traits<T, std::void_t<typename T::edge_comm_w
130187template <typename T>
131188using e_commw_t = typename computational_dag_edge_desc_traits<T>::edge_comm_weight_type;
132189
190+ // -----------------------------------------------------------------------------
191+ // Property Traits
192+ // -----------------------------------------------------------------------------
193+
194+ /* *
195+ * @brief Check if a graph guarantees vertices are stored/iterated in topological order.
196+ * It allows a graph implementation to notify algorithms that vertices are stored/iterated in topological order which can be used to optimize the algorithm.
197+ */
133198template <typename T, typename = void >
134199struct has_vertices_in_top_order_trait : std::false_type {};
135200
@@ -140,6 +205,9 @@ struct has_vertices_in_top_order_trait<T, std::void_t<decltype(T::vertices_in_to
140205template <typename T>
141206inline constexpr bool has_vertices_in_top_order_v = has_vertices_in_top_order_trait<T>::value;
142207
208+ /* *
209+ * @brief Check if a graph guarantees children of a vertex are stored/iterated in vertex index order.
210+ */
143211template <typename T, typename = void >
144212struct has_children_in_vertex_order_trait : std::false_type {};
145213
@@ -150,6 +218,9 @@ struct has_children_in_vertex_order_trait<T, std::void_t<decltype(T::children_in
150218template <typename T>
151219inline constexpr bool has_children_in_vertex_order_v = has_children_in_vertex_order_trait<T>::value;
152220
221+ /* *
222+ * @brief Check if a graph guarantees parents of a vertex are stored/iterated in vertex index order.
223+ */
153224template <typename T, typename = void >
154225struct has_parents_in_vertex_order_trait : std::false_type {};
155226
@@ -162,6 +233,11 @@ inline constexpr bool has_parents_in_vertex_order_v = has_parents_in_vertex_orde
162233
163234} // namespace osp
164235
236+ /* *
237+ * @brief Specialization of std::hash for osp::directed_edge.
238+ *
239+ * This specialization provides a hash function for osp::directed_edge, which is used in hash-based containers like std::unordered_set and std::unordered_map.
240+ */
165241template <typename Graph_t>
166242struct std ::hash<osp::directed_edge<Graph_t>> {
167243 std::size_t operator ()(const osp::directed_edge<Graph_t> &p) const noexcept {
0 commit comments