|
| 1 | +# Customization Points |
| 2 | + |
| 3 | +The algorithms and views in this library operate on graph representations via _Customization Point Objects_ (CPO). |
| 4 | +A user-defined graph representation `G` is adapted for use with this library by making sure that the necessary CPOs are _valid_ for `G`. |
| 5 | + |
| 6 | +A CPO is a function object, so it can be passed as an argument to functions. |
| 7 | + |
| 8 | +Each customization point specifies individually what it takes to make it valid. |
| 9 | +A customization point can be made valid in a number of ways. |
| 10 | +For each customization point we provide an ordered list of ways in which it can be made valid. |
| 11 | +The order in this list matters: the match for validity is performed in order, |
| 12 | +and if a given customization is determined to be valid, the subsequent ways, even if they would be valid, are ignored. |
| 13 | + |
| 14 | +Often, the last item from the list serves the purpose of a "fallback" or "default" customization. |
| 15 | + |
| 16 | +If none of the customization ways is valid for a given type, or set of types, the customization point is considered _invalid_ for this set of types. |
| 17 | +The property or being valid or invalid can be statically tested in the program via SFINAE (like `enable_if`) tricks or `requires`-expressions. |
| 18 | + |
| 19 | +All the customization points in this library are defined in namespace `::graph` and brought into the program code via including header `<graph/graph.hpp>`. |
| 20 | + |
| 21 | + |
| 22 | +## The list of customization points |
| 23 | + |
| 24 | +We use the following notation to represent the customization points: |
| 25 | + |
| 26 | + |
| 27 | +| Symbol | Type | Meaning | |
| 28 | +|--------|--------------------------------|------------------------------------------| |
| 29 | +| `G` | | the type of the graph representation | |
| 30 | +| `g` | `G` | the graph representation | |
| 31 | +| `u` | `graph::vertex_reference_t<G>` | vertex in `g` | |
| 32 | +| `ui` | `graph::vertex_iterator_t<G>` | iterator to a vertex in `g` | |
| 33 | +| `uid` | `graph::vertex_id_t<G>` | _id_ of a vertex in `g` (often an index) | |
| 34 | +| `uv` | `graph::edge_reference_t<G>` | an edge in `g` | |
| 35 | + |
| 36 | + |
| 37 | +### `vertices` |
| 38 | + |
| 39 | +The CPO `vertices(g)` is used to obtain the range of all vertices, in form of a `std::ranges::random_access_range`, from the graph-representing object `g`. |
| 40 | +We also use its return type to determine the type of the vertex: `vertex_t<G>`. |
| 41 | + |
| 42 | +#### Customization |
| 43 | + |
| 44 | + 1. Returns `g.vertices()`, if such member function exists and returns a `std::move_constructible` type. |
| 45 | + 2. Returns `vertices(g)`, if such function is ADL-discoverable and returns a `std::move_constructible` type. |
| 46 | + 3. Returns `g`, if it is a `std::ranges::random_access_range`. |
| 47 | + |
| 48 | + |
| 49 | +### `vertex_id` |
| 50 | + |
| 51 | +The CPO `vertex_id(g, ui)` is used obtain the _id_ of the vertex, given the iterator. <br> |
| 52 | +We also use its return type to determine the type of the vertex id: `vertex_id_t<G>`. |
| 53 | + |
| 54 | +#### Customization |
| 55 | + |
| 56 | + 1. Returns `ui->vertex_id(g)`, if this expression is valid and its type is `std::move_constructible`. |
| 57 | + 2. Returns `vertex_id(g, ui)`, if this expression is valid and its type is `std::move_constructible`. |
| 58 | + 3. Returns <code>static_cast<<em>vertex-id-t</em><G>>(ui - begin(vertices(g)))</code>, |
| 59 | + if `std::ranges::random_access_range<vertex_range_t<G>>` is `true`, where <code><em>vertex-id-t</em></code> is defined as: |
| 60 | + |
| 61 | + * `I`, when the type of `G` matches pattern `ranges::forward_list<ranges::forward_list<I>>` and `I` is `std::integral`, |
| 62 | + * `I0`, when the type of `G` matches pattern <code>ranges::forward_list<ranges::forward_list<<em>tuple-like</em><I0, ...>>></code> and `I0` is `std::integral`, |
| 63 | + * `std::size_t` otherwise. |
| 64 | + |
| 65 | + |
| 66 | +### `find_vertex` |
| 67 | + |
| 68 | +TODO `find_vertex(g, uid)` |
| 69 | + |
| 70 | + |
| 71 | +### `edges(g, u)` |
| 72 | + |
| 73 | +The CPO `edges(g, u)` is used to obtain the sequence of outgoing edges for a vertex |
| 74 | +denoted by reference `u`. <br> |
| 75 | +We also use its return type to determine the type of the edge type: `edge_t<G>`. |
| 76 | + |
| 77 | +#### Customization |
| 78 | + |
| 79 | + 1. Returns `u.edges(g)`, if this expression is valid and its type is `std::move_constructible`. |
| 80 | + 2. Returns `edges(g, u)`, if this expression is valid and its type is `std::move_constructible`. |
| 81 | + 3. `u`, if `G` is a user-defined type and type `vertex_t<G>` is `std::ranges::forward_range; |
| 82 | + |
| 83 | + |
| 84 | +### `edges(g, uid)` |
| 85 | + |
| 86 | +The CPO `edges(g, uid)` is used to obtain the sequence of outgoing edges for a vertex |
| 87 | +denoted by _id_ `uid`. |
| 88 | + |
| 89 | +#### Customization |
| 90 | + |
| 91 | + 1. Returns `edges(g, uid)`, if this expression is valid and its type is `std::move_constructible`. |
| 92 | + 2. Returns `*find_vertex(g, uid)`, if |
| 93 | + * `vertex_t<G>` is `std::ranges::forward_range`, and |
| 94 | + * expression `find_vertex(g, uid)` is valid and its type is `std::move_constructible`. |
| 95 | + |
| 96 | + |
| 97 | +### `num_edges(g)` |
| 98 | + |
| 99 | +TODO |
| 100 | + |
| 101 | + |
| 102 | +### `target_id(g, uv)` |
| 103 | + |
| 104 | +The CPO `target_id(g, uv)` is used to obtain the _id_ of the target vertex of edge `uv`. |
| 105 | + |
| 106 | +#### Customization |
| 107 | + |
| 108 | + 1. Returns `uv.target_id(g)`, if this expression is valid and its type is `std::move_constructible`. |
| 109 | + 2. Returns `target_id(g, uv)`, if this expression is valid and its type is `std::move_constructible`. |
| 110 | + 3. Returns `uv`, if |
| 111 | + * `G` is `std::ranges::forward_range`, and |
| 112 | + * `std::ranges::range_value_t<G>` is `std::ranges::forward_range`, and |
| 113 | + * `std::ranges::range_value_t<std::ranges::range_value_t<G>>` is `std::integral`. |
| 114 | + 4. Returns `get<0>(uv)`, if |
| 115 | + * `G` is `std::ranges::forward_range`, and |
| 116 | + * `std::ranges::range_value_t<G>` is `std::ranges::forward_range`, and |
| 117 | + * `std::ranges::range_value_t<std::ranges::range_value_t<G>>` is <code><em>tuple-like</em></code>, and |
| 118 | + * `std::tuple_element_t<0, std::ranges::range_value_t<std::ranges::range_value_t<G>>>` is `std::integral`. |
| 119 | + |
| 120 | + |
| 121 | +### `target_id(e)` |
| 122 | + |
| 123 | +### `source_id(g, uv)` |
| 124 | + |
| 125 | +### `source_id(e)` |
| 126 | + |
| 127 | + |
| 128 | +### `target(g, uv)` |
| 129 | + |
| 130 | +CPO `target(g, uv)` is used to access the target vertex of a given edge `uv`. |
| 131 | + |
| 132 | +#### Customization |
| 133 | + |
| 134 | + 1. Returns `target(g, uv)`, if this expression is valid and its type is `std::move_constructible`. |
| 135 | + 2. Returns `*find_vertex(g, target_id(g, uv))`, if |
| 136 | + |
| 137 | + * `vertex_range_t<G>` is a `std::ranges::random_access_range`, and |
| 138 | + * `find_vertex(g, uid)` is valid and its type is `std::move_constructible`, and |
| 139 | + * `target_id(g, uv)` is valid and its type is `std::integral`. |
| 140 | + |
| 141 | + |
| 142 | +### `source(g, uv)` |
| 143 | + |
| 144 | +### `find_vertex_edge(g, u, vid)` |
| 145 | + |
| 146 | +### `find_vertex_edge(g, uid, vid)` |
| 147 | + |
| 148 | +### `contains_edge(g, uid, vid)` |
| 149 | + |
| 150 | +### `partition_id(g, u)` |
| 151 | + |
| 152 | +### `partition_id(g, uid)` |
| 153 | + |
| 154 | +### `num_vertices(g, pid)` |
| 155 | + |
| 156 | +### `num_vertices(g)` |
| 157 | + |
| 158 | +### `degree(g, u)` |
| 159 | + |
| 160 | +### `degree(g, uid)` |
| 161 | + |
| 162 | +### `vertex_value(g, u)` |
| 163 | + |
| 164 | +### `edge_value(g, uv)` |
| 165 | + |
| 166 | +### `edge_value(e)` |
| 167 | + |
| 168 | +### `graph_value(g)` |
| 169 | + |
| 170 | +### `num_partitions(g)` |
| 171 | + |
| 172 | +### `has_edge(g)` |
| 173 | + |
0 commit comments