@@ -30,18 +30,47 @@ template <typename Graph>
3030class subgraph;
3131----
3232
33- The `subgraph` class wraps an `adjacency_list` and maintains a tree of
34- subgraphs. The root graph owns all vertices and edges. Child subgraphs hold
35- subsets of the root's vertices, and their edge sets are _induced_: any edge in
36- the root whose both endpoints are in the child automatically appears in the
37- child.
38-
39- Each subgraph uses _local_ descriptors (0-based within that subgraph). Use
40- `local_to_global()` and `global_to_local()` to convert between local and root
41- descriptors.
42-
43- Adding an edge to a child subgraph also adds it to all ancestor subgraphs.
44- Adding a vertex to a child subgraph also adds it to all ancestors.
33+ `subgraph` represents parts of a single graph as independent graphs, without
34+ copying the data and without the parts drifting out of sync with the whole. All
35+ vertices and edges are stored once, in the root graph. Each subgraph is a
36+ lightweight view onto a subset of that storage which still behaves like a full
37+ graph, so it can be passed to any BGL algorithm.
38+
39+ [TIP]
40+ ====
41+ Consider a national road network: intersections are vertices and roads are
42+ edges. An analysis might focus on one city, then one district within that city,
43+ then compare against the whole country. Rather than three separate copies kept
44+ consistent by hand, `subgraph` keeps one dataset and offers lightweight views
45+ onto its parts. The country is the root, a city is a child subgraph, and a
46+ district is a child of that city. Each view behaves like a normal graph and can
47+ be handed to an algorithm such as `dijkstra_shortest_paths` exactly like any
48+ other BGL graph.
49+ ====
50+
51+ These views nest into a tree. The _root_ subgraph holds the entire graph and
52+ owns all of its vertices and edges. Each _child_ is a subset of its parent's
53+ vertices, and a child may in turn have children of its own. A child's edges are
54+ _induced_: an edge belongs to a child exactly when both of its endpoints do, so
55+ only vertices are ever added to a child, never edges directly.
56+
57+ Because the storage is shared rather than copied, the levels stay linked in both
58+ directions. A property set at one level, such as an edge weight or a vertex
59+ color, is visible from every level. Adding a vertex or edge to a child also adds
60+ it to every ancestor up to the root, so an edit made while working on one part
61+ keeps the whole hierarchy consistent.
62+
63+ Each subgraph numbers its own vertices and edges 0-based, as required by the
64+ many algorithms that assume a contiguous index space. A descriptor is therefore
65+ meaningful only within one subgraph. `local_to_global()` and `global_to_local()`
66+ translate a descriptor between a subgraph's local numbering and the root's.
67+
68+ Choosing among the graph views:
69+
70+ * `filtered_graph` for a read-only view that hides some vertices or edges.
71+ * `copy_graph` for an independent copy that does not stay linked to the original.
72+ * `subgraph` when mutability, per-region local numbering, and a parent/child
73+ hierarchy over shared storage are all needed.
4574
4675== Template Parameters
4776
@@ -102,16 +131,39 @@ edge_descriptor global_to_local(edge_descriptor e_global) const;
102131
103132Convert between local (subgraph-relative) and global (root) descriptors.
104133
134+ WARNING: These conversions have a precondition. The element must belong to this
135+ subgraph. Passing a vertex or edge that is not in the subgraph is a precondition
136+ violation (checked with `BOOST_ASSERT` in debug builds, undefined behaviour
137+ otherwise). On the root subgraph the conversion is the identity, so any element
138+ is accepted. To convert an element that might not be present, test membership
139+ first with `find_vertex()` or `find_edge()`.
140+
105141'''
106142
107143[source,cpp]
108144----
109145std::pair<vertex_descriptor, bool>
110146find_vertex(vertex_descriptor u_global) const;
147+
148+ std::pair<edge_descriptor, bool>
149+ find_edge(edge_descriptor e_global) const;
111150----
112151
113- Returns `(local_descriptor, true)` if the global vertex is in this subgraph,
114- `(_, false)` otherwise.
152+ Membership queries that never assert. `find_vertex` returns
153+ `(local_descriptor, true)` if the global vertex is in this subgraph, and
154+ `(null_vertex(), false)` otherwise. `find_edge` behaves the same way for edges,
155+ returning a default-constructed `edge_descriptor` in the not-found case. These
156+ are the safe form of `global_to_local`, for the case where the element is not
157+ known in advance to be in the subgraph.
158+
159+ [NOTE]
160+ ====
161+ *Descriptor identity and stability.* For an element that is present, the
162+ conversions round-trip: `global_to_local(local_to_global(x)) == x`, and the
163+ edge index is preserved. Properties live in the root's storage and are shared
164+ across the whole tree, so the same logical element carries the same property
165+ value no matter which subgraph's descriptor reaches it.
166+ ====
115167
116168=== Hierarchy Navigation
117169
0 commit comments