adaptors ok

This commit is contained in:
Arnaud Becheler
2026-04-16 05:28:51 +02:00
parent 3d1dcb3b4d
commit f9ec2bd17a
17 changed files with 949 additions and 2112 deletions
@@ -0,0 +1,36 @@
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <functional>
#include <iostream>
struct Road {
int weight;
};
int main() {
using namespace boost;
using Graph = adjacency_list<vecS, vecS, directedS, no_property, Road>;
using Edge = graph_traits<Graph>::edge_descriptor;
Graph g(4);
add_edge(0, 1, Road{5}, g);
add_edge(0, 2, Road{0}, g);
add_edge(1, 3, Road{3}, g);
add_edge(2, 3, Road{0}, g);
// Keep only edges with positive weight
auto filter = [&g](Edge e) { return g[e].weight > 0; };
filtered_graph<Graph, std::function<bool(Edge)>> fg(g, filter);
std::cout << "Original: " << num_edges(g) << " edges\n";
for (auto ei = edges(g).first; ei != edges(g).second; ++ei) {
std::cout << " " << source(*ei, g) << " -> " << target(*ei, g)
<< " (weight=" << g[*ei].weight << ")\n";
}
std::cout << "Filtered (weight > 0):\n";
for (auto ei = edges(fg).first; ei != edges(fg).second; ++ei) {
std::cout << " " << source(*ei, fg) << " -> " << target(*ei, fg)
<< " (weight=" << fg[*ei].weight << ")\n";
}
}
@@ -0,0 +1,24 @@
#include <boost/graph/grid_graph.hpp>
#include <boost/array.hpp>
#include <iostream>
int main() {
using namespace boost;
using Graph = grid_graph<3>;
using Vertex = graph_traits<Graph>::vertex_descriptor;
// 3x3x3 cube (no wrapping)
boost::array<std::size_t, 3> lengths = {{ 3, 3, 3 }};
Graph g(lengths);
std::cout << num_vertices(g) << " vertices, "
<< num_edges(g) << " edges\n";
// Corner vertex: 3 neighbors. Center vertex: 6 neighbors.
Vertex corner = vertex(0, g);
Vertex center = {{ 1, 1, 1 }};
std::cout << "corner (" << corner[0] << "," << corner[1] << ","
<< corner[2] << ") degree=" << out_degree(corner, g) << "\n";
std::cout << "center (" << center[0] << "," << center[1] << ","
<< center[2] << ") degree=" << out_degree(center, g) << "\n";
}
@@ -0,0 +1,29 @@
#include <boost/graph/grid_graph.hpp>
#include <boost/array.hpp>
#include <iostream>
int main() {
using namespace boost;
using Graph = grid_graph<2>;
using Vertex = graph_traits<Graph>::vertex_descriptor;
// 4x3 cylinder: dimension 0 wraps, dimension 1 does not
boost::array<std::size_t, 2> lengths = {{ 4, 3 }};
boost::array<bool, 2> wrap = {{ true, false }};
Graph g(lengths, wrap);
std::cout << num_vertices(g) << " vertices, "
<< num_edges(g) << " edges\n";
// Navigate: wrapping in dimension 0
Vertex corner = vertex(0, g);
Vertex wrapped = g.previous(corner, 0); // wraps to (3,0)
std::cout << "\nFrom (" << corner[0] << "," << corner[1] << "):\n";
std::cout << " previous in dim 0 (wraps) = ("
<< wrapped[0] << "," << wrapped[1] << ")\n";
// Navigate: no wrapping in dimension 1
Vertex same = g.previous(corner, 1); // stays at (0,0)
std::cout << " previous in dim 1 (stops) = ("
<< same[0] << "," << same[1] << ")\n";
}
@@ -0,0 +1,23 @@
#include <boost/graph/grid_graph.hpp>
#include <boost/array.hpp>
#include <iostream>
int main() {
using namespace boost;
using Graph = grid_graph<2>;
using Vertex = graph_traits<Graph>::vertex_descriptor;
// 3x3 torus (all dimensions wrap)
boost::array<std::size_t, 2> lengths = {{ 3, 3 }};
Graph g(lengths, true);
std::cout << num_vertices(g) << " vertices, "
<< num_edges(g) << " edges\n";
// Every vertex has exactly 4 neighbors on a torus
for (auto vi = vertices(g).first; vi != vertices(g).second; ++vi) {
Vertex v = *vi;
std::cout << "(" << v[0] << "," << v[1] << ") degree="
<< out_degree(v, g) << "\n";
}
}
@@ -0,0 +1,23 @@
#include <boost/graph/grid_graph.hpp>
#include <boost/array.hpp>
#include <iostream>
int main() {
using namespace boost;
using Graph = grid_graph<2>;
using Vertex = graph_traits<Graph>::vertex_descriptor;
// 3x3 flat grid (no wrapping)
boost::array<std::size_t, 2> lengths = {{ 3, 3 }};
Graph g(lengths);
std::cout << num_vertices(g) << " vertices, "
<< num_edges(g) << " edges\n";
// Corner vertex has 2 neighbors, edge vertex has 3, center has 4
for (auto vi = vertices(g).first; vi != vertices(g).second; ++vi) {
Vertex v = *vi;
std::cout << "(" << v[0] << "," << v[1] << ") degree="
<< out_degree(v, g) << "\n";
}
}
@@ -0,0 +1,21 @@
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/reverse_graph.hpp>
#include <boost/graph/graph_utility.hpp>
#include <iostream>
int main() {
using namespace boost;
using Graph = adjacency_list<vecS, vecS, bidirectionalS>;
Graph g(4);
add_edge(0, 1, g);
add_edge(1, 2, g);
add_edge(2, 3, g);
add_edge(3, 0, g);
std::cout << "Original:\n";
print_graph(g);
std::cout << "\nReversed:\n";
print_graph(make_reverse_graph(g));
}
@@ -0,0 +1,37 @@
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/subgraph.hpp>
#include <iostream>
int main() {
using namespace boost;
// subgraph requires edge_index_t as an internal property tag
using Graph = subgraph<adjacency_list<vecS, vecS, directedS,
no_property, property<edge_index_t, int>>>;
// Root graph: 5 vertices, 6 edges
Graph root(5);
add_edge(0, 1, root);
add_edge(1, 2, root);
add_edge(2, 3, root);
add_edge(3, 4, root);
add_edge(4, 0, root);
add_edge(1, 3, root);
// Create a subgraph containing vertices {1, 2, 3}
Graph& sub = root.create_subgraph();
add_vertex(1, sub); // global vertex 1
add_vertex(2, sub); // global vertex 2
add_vertex(3, sub); // global vertex 3
std::cout << "Root: " << num_vertices(root) << " vertices, "
<< num_edges(root) << " edges\n";
std::cout << "Subgraph: " << num_vertices(sub) << " vertices, "
<< num_edges(sub) << " edges\n\n";
std::cout << "Subgraph edges (local descriptors):\n";
for (auto ei = edges(sub).first; ei != edges(sub).second; ++ei) {
auto s = sub.local_to_global(source(*ei, sub));
auto t = sub.local_to_global(target(*ei, sub));
std::cout << " " << s << " -> " << t << "\n";
}
}
+15 -14
View File
@@ -3,24 +3,25 @@
#include <iostream>
#include <sstream>
struct City { std::string name; };
struct Road { int weight; };
int main() {
using namespace boost;
using Graph = adjacency_list<vecS, vecS, directedS,
property<vertex_name_t, std::string>,
property<edge_weight_t, int>>;
using Graph = adjacency_list<vecS, vecS, directedS, City, Road>;
// --- Write ---
Graph g(3);
add_edge(0, 1, {10}, g);
add_edge(1, 2, {20}, g);
add_edge(0, 2, {30}, g);
put(vertex_name, g, 0, "Paris");
put(vertex_name, g, 1, "Lyon");
put(vertex_name, g, 2, "Marseille");
g[0].name = "Paris";
g[1].name = "Lyon";
g[2].name = "Marseille";
add_edge(0, 1, Road{10}, g);
add_edge(1, 2, Road{20}, g);
add_edge(0, 2, Road{30}, g);
dynamic_properties dp;
dp.property("name", get(vertex_name, g));
dp.property("weight", get(edge_weight, g));
dp.property("name", get(&City::name, g));
dp.property("weight", get(&Road::weight, g));
std::ostringstream xml;
write_graphml(xml, g, dp, true);
@@ -29,8 +30,8 @@ int main() {
// --- Read back ---
Graph g2;
dynamic_properties dp2;
dp2.property("name", get(vertex_name, g2));
dp2.property("weight", get(edge_weight, g2));
dp2.property("name", get(&City::name, g2));
dp2.property("weight", get(&Road::weight, g2));
std::istringstream in(xml.str());
read_graphml(in, g2, dp2);
@@ -39,6 +40,6 @@ int main() {
std::cout << num_vertices(g2) << " vertices, "
<< num_edges(g2) << " edges\n";
for (auto v : make_iterator_range(vertices(g2))) {
std::cout << " " << get(vertex_name, g2, v) << "\n";
std::cout << " " << g2[v].name << "\n";
}
}
+14 -13
View File
@@ -3,24 +3,25 @@
#include <iostream>
#include <sstream>
struct City { std::string name; };
struct Road { double weight; };
int main() {
using namespace boost;
using Graph = adjacency_list<vecS, vecS, directedS,
property<vertex_name_t, std::string>,
property<edge_weight_t, double>>;
using Graph = adjacency_list<vecS, vecS, directedS, City, Road>;
// --- Write ---
Graph g(3);
add_edge(0, 1, {1.5}, g);
add_edge(1, 2, {2.5}, g);
add_edge(0, 2, {4.0}, g);
put(vertex_name, g, 0, "A");
put(vertex_name, g, 1, "B");
put(vertex_name, g, 2, "C");
g[0].name = "A";
g[1].name = "B";
g[2].name = "C";
add_edge(0, 1, Road{1.5}, g);
add_edge(1, 2, Road{2.5}, g);
add_edge(0, 2, Road{4.0}, g);
dynamic_properties dp;
dp.property("node_id", get(vertex_name, g));
dp.property("weight", get(edge_weight, g));
dp.property("node_id", get(&City::name, g));
dp.property("weight", get(&Road::weight, g));
std::ostringstream dot;
write_graphviz_dp(dot, g, dp, "node_id");
@@ -29,8 +30,8 @@ int main() {
// --- Read back ---
Graph g2;
dynamic_properties dp2;
dp2.property("node_id", get(vertex_name, g2));
dp2.property("weight", get(edge_weight, g2));
dp2.property("node_id", get(&City::name, g2));
dp2.property("weight", get(&Road::weight, g2));
std::istringstream in(dot.str());
read_graphviz(in, g2, dp2, "node_id");
+4 -4
View File
@@ -170,11 +170,11 @@
** xref:io/graphml.adoc[GraphML]
** xref:io/dimacs.adoc[DIMACS]
* Graph Adaptors
** xref:adaptors/subgraph.adoc[subgraph]
** xref:adaptors/edge_list.adoc[Edge List]
** xref:adaptors/reverse_graph.adoc[Reverse Graph]
** xref:adaptors/overview.adoc[Overview]
** xref:adaptors/filtered_graph.adoc[Filtered Graph]
** xref:adaptors/stanford_graph.adoc[Stanford GraphBase]
** xref:adaptors/reverse_graph.adoc[Reverse Graph]
** xref:adaptors/subgraph.adoc[Subgraph]
** xref:adaptors/edge_list.adoc[Edge List]
** xref:adaptors/grid_graph.adoc[Grid Graph]
* Traits and Iterators
** xref:traits/graph_traits.adoc[Graph Traits]
+75 -124
View File
@@ -1,157 +1,108 @@
[#sec:edge-list-class]
= Edge List Class
= Edge List
....
Turns a pair of edge iterators into an EdgeListGraph. Minimal adaptor providing
only `edges()`, `source()`, and `target()`.
edge_list<EdgeIterator, ValueType, DiffType>
....
*Defined in:* `<boost/graph/edge_list.hpp>` +
*Models:* EdgeListGraph only
The `edge_list` class is an adaptor that turns a pair of edge
iterators into a class that models `EdgeListGraph`. The `value_type`
of the edge iterator must be a `std::pair` (or at least have `first` and
`second` members). The `first_type` and `second_type` of the
pair must be the same and they will be used for the graph's
`vertex_descriptor`. The `ValueType` and `DiffType` template
parameters are only needed if your compiler does not support partial
specialization. Otherwise they default to the correct types.
WARNING: `edge_list` does not model VertexListGraph, IncidenceGraph, or
AdjacencyGraph. Most BGL algorithms (BFS, DFS, Dijkstra, etc.) cannot be used
with it. It works with algorithms that only need edge iteration, such as
`bellman_ford_shortest_paths` and `kruskal_minimum_spanning_tree`.
==== Example
Applying the Bellman-Ford shortest paths algorithm to an
`edge_list`.
== Example
[source,cpp]
----
enum { u, v, x, y, z, N };
char name[] = { 'u', 'v', 'x', 'y', 'z' };
enum { u, v, x, y, z, N };
char name[] = { 'u', 'v', 'x', 'y', 'z' };
using E = std::pair<int, int>;
E edges[] = { E(u,y), E(u,x), E(u,v),
E(v,u),
E(x,y), E(x,v),
E(y,v), E(y,z),
E(z,u), E(z,x) };
typedef std::pair<int,int> E;
E edges[] = { E(u,y), E(u,x), E(u,v),
E(v,u),
E(x,y), E(x,v),
E(y,v), E(y,z),
E(z,u), E(z,x) };
int weight[] = { -4, 8, 5,
-2,
9, -3,
7, 2,
6, 7 };
typedef boost::edge_list<E*> Graph;
Graph g(edges, edges + sizeof(edges) / sizeof(E));
std::vector<int> distance(N, std::numeric_limits<short>::max());
std::vector<int> parent(N,-1);
distance[z] = 0;
parent[z] = z;
bool r = boost::bellman_ford_shortest_paths(g, int(N), weight,
distance.begin(),
parent.begin());
if (r)
for (int i = 0; i < N; ++i)
std::cout << name[i] << ": " << distance[i]
<< " " << name[parent[i]] << std::endl;
else
std::cout << "negative cycle" << std::endl;
boost::edge_list<E*> g(edges, edges + 10);
----
The output is the distance from the root and the parent of each vertex
in the shortest paths tree.
== Synopsis
....
[source,cpp]
----
template <typename EdgeIterator,
typename ValueType = std::iterator_traits<EdgeIterator>::value_type,
typename DiffType = std::iterator_traits<EdgeIterator>::difference_type>
class edge_list;
----
u: 2 v
v: 4 x
x: 7 z
y: -2 u
z: 0 z
....
The `value_type` of the edge iterator must be a `std::pair` (or have `first`
and `second` members). Both members must be the same type, used as vertex
descriptors. The `ValueType` and `DiffType` parameters are only needed for
compilers without partial specialization support.
==== Where Defined
== Template Parameters
link:../../../boost/graph/edge_list.hpp[`boost/graph/edge_list.hpp`]
==== Template Parameters
[width="100%",cols="50%,50%",options="header",]
[cols="1,3,1",options="header"]
|===
|Parameter |Description
|`EdgeIterator` |Must be model of
http://www.boost.org/sgi/stl/InputIterator.html[InputIterator] who's
`value_type` must be a pair of vertex descriptors.
| Parameter | Description | Default
|`ValueType` |The `value_type` of the `EdgeIterator`. +
Default:
`std::iterator_traits<EdgeIterator>::value_type`
| `EdgeIterator`
| Must model InputIterator. `value_type` must be a pair of vertex descriptors.
|
|`DiffType` |The `difference_type` of the `EdgeIterator`. +
Default:
`std::iterator_traits<EdgeIterator>::difference_type`
| `ValueType`
| The `value_type` of `EdgeIterator`.
| `std::iterator_traits<EdgeIterator>::value_type`
| `DiffType`
| The `difference_type` of `EdgeIterator`.
| `std::iterator_traits<EdgeIterator>::difference_type`
|===
==== Model of
== Member Functions
xref:concepts/EdgeListGraph.adoc[EdgeListGraph]
[source,cpp]
----
edge_list(EdgeIterator first, EdgeIterator last);
----
==== Associated Types
Create a graph from the edge range `[first, last)`.
'''''
== Non-Member Functions
`boost::graph_traits<edge_list>::vertex_descriptor` +
+
The type for the vertex descriptors associated with the `edge_list`.
This will be the same type as
`std::iterator_traits<EdgeIterator>::value_type::first_type`.
[source,cpp]
----
std::pair<edge_iterator, edge_iterator>
edges(const edge_list& g);
----
'''''
Returns an iterator-range for the edge set.
` boost::graph_traits<edge_list>::edge_descriptor ` +
+
The type for the edge descriptors associated with the `edge_list`.
'''
'''''
[source,cpp]
----
vertex_descriptor source(edge_descriptor e, const edge_list& g);
vertex_descriptor target(edge_descriptor e, const edge_list& g);
----
` boost::graph_traits<edge_list>::edge_iterator ` +
+
The type for the iterators returned by `edges()`. The iterator category
of the `edge_iterator` will be the same as that of the
`EdgeIterator`.
Returns the source/target vertex of edge `e`.
'''''
== Associated Types
==== Member Functions
[cols="1,3",options="header"]
|===
| Type | Description
'''''
| `vertex_descriptor`
| Same as `std::iterator_traits<EdgeIterator>::value_type::first_type`.
` edge_list(EdgeIterator first, EdgeIterator last) ` +
+
Creates a graph object with `n` vertices and with the edges specified in
the edge list given by the range `[first,last)`.
| `edge_descriptor`
| Internal edge descriptor type.
'''''
==== Non-Member Functions
'''''
` std::pair<edge_iterator, edge_iterator>` +
`edges(const edge_list& g) ` +
+
Returns an iterator-range providing access to the edge set of graph `g`.
'''''
` vertex_descriptor` +
`source(edge_descriptor e, const edge_list& g) ` +
+
Returns the source vertex of edge `e`.
'''''
` vertex_descriptor` +
`target(edge_descriptor e, const edge_list& g) ` +
+
Returns the target vertex of edge `e`.
| `edge_iterator`
| Same iterator category as `EdgeIterator`.
|===
@@ -1,522 +1,299 @@
[#sec:filtered-graph-class]
= Filtered Graph
....
A view of a graph that hides vertices and/or edges based on predicate functions.
filtered_graph<Graph, EdgePredicate, VertexPredicate>
....
*Defined in:* `<boost/graph/filtered_graph.hpp>` +
*Models:* same concepts as the underlying graph (VertexListGraph, EdgeListGraph,
IncidenceGraph, BidirectionalGraph, PropertyGraph, etc.)
The `filtered_graph` class template is an adaptor that creates a
filtered view of a graph. The predicate function objects determine which
edges and vertices of the original graph will show up in the filtered
graph. If the edge predicate returns `true` for an edge then it shows up
in the filtered graph, and if the predicate returns `false` then the
edge does not appear in the filtered graph. Likewise for vertices. The
`filtered_graph` class does not create a copy of the original graph,
but uses a reference to the original graph. The lifetime of the original
graph must extend past any use of the filtered graph. The filtered graph
does not change the structure of the original graph, though vertex and
edge properties of the original graph can be changed through property
maps of the filtered graph. Vertex and edge descriptors of the filtered
graph are the same as, and interchangeable with, the vertex and edge
descriptors of the original graph.
WARNING: `num_vertices()` and `num_edges()` return counts from the _underlying_
graph, not the filtered view. This means
`std::distance(vertices(fg).first, vertices(fg).second) != num_vertices(fg)`.
This is by design: computing filtered counts would be O(V) instead of O(1), and
the vertex/edge indices would no longer fall in the range `[0, num_vertices(g))`
which many algorithms assume. Some algorithms (e.g. `vf2_sub_graph_iso`) have
been specifically patched to use `std::distance` instead of `num_vertices`.
The <<num_vertices,`num_vertices`>> and
<<num_edges,`num_edges`>> functions do not filter before
returning results, so they return the number of vertices or edges in the
underlying graph, unfiltered <<2,[2>>].
==== Example
In this example we will filter a graph's edges based on edge weight. We
will keep all edges with positive edge weight. First, we create a
predicate function object.
== Example
[source,cpp]
----
template <typename EdgeWeightMap>
struct positive_edge_weight {
positive_edge_weight() { }
positive_edge_weight(EdgeWeightMap weight) : m_weight(weight) { }
template <typename Edge>
bool operator()(const Edge& e) const {
return 0 < get(m_weight, e);
}
EdgeWeightMap m_weight;
};
include::example$adaptors/filtered_graph.cpp[]
----
Now we create a graph and print out the filtered graph.
[source,cpp]
----
int main()
{
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS,
no_property, property<edge_weight_t, int> > Graph;
typedef property_map<Graph, edge_weight_t>::type EdgeWeightMap;
enum { A, B, C, D, E, N };
const char* name = "ABCDE";
Graph g(N);
add_edge(A, B, 2, g);
add_edge(A, C, 0, g);
add_edge(C, D, 1, g);
add_edge(C, E, 0, g);
add_edge(D, B, 3, g);
add_edge(E, C, 0, g);
positive_edge_weight<EdgeWeightMap> filter(get(edge_weight, g));
filtered_graph<Graph, positive_edge_weight<EdgeWeightMap> >
fg(g, filter);
std::cout << "filtered edge set: ";
print_edges(fg, name);
std::cout << "filtered out-edges:" << std::endl;
print_graph(fg, name);
return 0;
}
----
The output is:
Expected output:
....
filtered edge set: (A,B) (C,D) (D,B)
filtered out-edges:
A --> B
B -->
C --> D
D --> B
E -->
Original: 4 edges
0 -> 1 (weight=5)
0 -> 2 (weight=0)
1 -> 3 (weight=3)
2 -> 3 (weight=0)
Filtered (weight > 0):
0 -> 1 (weight=5)
1 -> 3 (weight=3)
....
==== Template Parameters
[cols=",,",options="header",]
|===
|Parameter |Description |Default
|`Graph` |The underlying graph type. | 
|`EdgePredicate` |A function object that selects which edges from the
original graph will appear in the filtered graph. The function object
must model http://www.boost.org/sgi/stl/Predicate.html[Predicate]. The
argument type for the function object must be the edge descriptor type
of the graph. Also, the predicate must be
http://www.boost.org/sgi/stl/DefaultConstructible.html[Default
Constructible] <<1,[1>>]. | 
|`VertexPredicate` |A function object that selects which vertices from
the original graph will appear in the filtered graph. The function
object must model
http://www.boost.org/sgi/stl/Predicate.html[Predicate]. The argument
type for the function object must be the vertex descriptor type of the
graph. Also, the predicate must be
http://www.boost.org/sgi/stl/DefaultConstructible.html[Default
Constructible] <<1,[1>>]. |`keep_all`
|===
==== Model of
This depends on the underlying graph type. If the underlying `Graph`
type models xref:concepts/VertexAndEdgeListGraph.adoc[VertexAndEdgeListGraph]
and xref:concepts/PropertyGraph.adoc[PropertyGraph] then so does the filtered
graph. If the underlying `Graph` type models fewer or smaller concepts
than these, then so does the filtered graph.
==== Where Defined
link:../../../boost/graph/filtered_graph.hpp[`boost/graph/filtered_graph.hpp`]
=== Associated Types
'''''
`graph_traits<filtered_graph>::vertex_descriptor` +
+
The type for the vertex descriptors associated with the
`filtered_graph`, which is the same type as the
`vertex_descriptor` for the original `Graph`.
'''''
`graph_traits<filtered_graph>::edge_descriptor` +
+
+
The type for the edge descriptors associated with the
`filtered_graph`, which is the same type as the
`edge_descriptor` for the original `Graph`.
'''''
`graph_traits<filtered_graph>::vertex_iterator` +
+
+
The type for the iterators returned by `vertices()`, which is:
== Synopsis
[source,cpp]
----
filter_iterator<VertexPredicate, graph_traits<Graph>::vertex_iterator>
template <typename Graph,
typename EdgePredicate,
typename VertexPredicate = keep_all>
class filtered_graph;
----
The iterator is a model of
link:../../utility/MultiPassInputIterator.html[MultiPassInputIterator].
'''''
`graph_traits<filtered_graph>::edge_iterator` +
+
The type for the iterators returned by `edges()`, which is:
[source,cpp]
----
filter_iterator<EdgePredicate, graph_traits<Graph>::edge_iterator>
----
The iterator is a model of
link:../../utility/MultiPassInputIterator.html[MultiPassInputIterator].
'''''
`graph_traits<filtered_graph>::out_edge_iterator` +
+
The type for the iterators returned by `out_edges()`, which is:
[source,cpp]
----
filter_iterator<EdgePredicate, graph_traits<Graph>::out_edge_iterator>
----
The iterator is a model of
link:../../utility/MultiPassInputIterator.html[MultiPassInputIterator].
'''''
`graph_traits<filtered_graph>::adjacency_iterator` +
+
The type for the iterators returned by `adjacent_vertices()`. The
`adjacency_iterator` models the same iterator concept as
`out_edge_iterator`.
'''''
`graph_traits<filtered_graph>::directed_category` +
+
+
Provides information about whether the graph is directed
(`directed_tag`) or undirected (`undirected_tag`).
'''''
`graph_traits<filtered_graph>::edge_parallel_category` +
+
+
This describes whether the graph class allows the insertion of parallel
edges (edges with the same source and target). The two tags are
`allow_parallel_edge_tag` and
`disallow_parallel_edge_tag`.
'''''
`graph_traits<filtered_graph>::vertices_size_type` +
+
The type used for dealing with the number of vertices in the graph.
'''''
`graph_traits<filtered_graph>::edges_size_type` +
+
The type used for dealing with the number of edges in the graph.
'''''
`graph_traits<filtered_graph>::degree_size_type` +
+
The type used for dealing with the number of edges incident to a vertex
in the graph.
'''''
`property_map<filtered_graph, Property>::type` +
and +
`property_map<filtered_graph, Property>::const_type` +
+
The property map type for vertex or edge properties in the graph. The
same property maps from the adapted graph are available in the filtered
The `filtered_graph` does not copy the original graph. It holds a reference to
it. The lifetime of the original graph must extend past any use of the filtered
graph.
'''''
Vertex and edge descriptors of the filtered graph are the same as, and
interchangeable with, the descriptors of the original graph. Property maps from
the original graph are available through the filtered graph.
=== Member Functions
== Template Parameters
'''''
[cols="1,3,1",options="header"]
|===
| Parameter | Description | Default
....
| `Graph`
| The underlying graph type.
|
filtered_graph(Graph& g, EdgePredicate ep, VertexPredicate vp)
....
| `EdgePredicate`
| Function object selecting which edges appear. Must model Predicate (argument
type: edge descriptor). Must be Default Constructible.
|
Create a filtered graph based on the graph _g_ and the edge filter _ep_
and vertex filter _vp_.
| `VertexPredicate`
| Function object selecting which vertices appear. Must model Predicate
(argument type: vertex descriptor). Must be Default Constructible.
| `keep_all`
|===
'''''
NOTE: Predicates must be Default Constructible because they are stored by-value
in filter iterators, and the C++ Standard requires iterators to be Default
Constructible.
....
== Member Functions
filtered_graph(Graph& g, EdgePredicate ep)
....
=== Constructors
Create a filtered graph based on the graph _g_ and the edge filter _ep_.
All vertices from the original graph are retained.
[source,cpp]
----
filtered_graph(Graph& g, EdgePredicate ep, VertexPredicate vp);
----
'''''
Create a filtered view of `g` with both edge and vertex filters.
filtered_graph(const filtered_graph& x)
'''
This creates a filtered graph for the same underlying graph as _x_.
Anotherwords, this is a shallow copy.
[source,cpp]
----
filtered_graph(Graph& g, EdgePredicate ep);
----
'''''
Create a filtered view of `g` with an edge filter only. All vertices are
retained.
....
== Non-Member Functions
filtered_graph& operator=(const filtered_graph& x)
....
This creates a filtered graph for the same underlying graph as _x_.
Anotherwords, this is a shallow copy.
'''''
=== Non-Member Functions
===== Structure Access
'''''
=== Structure Access
[source,cpp]
----
std::pair<vertex_iterator, vertex_iterator>
vertices(const filtered_graph& g)
vertices(const filtered_graph& g);
----
Returns an iterator-range providing access to the vertex set of graph
`g`.
Returns an iterator-range for the filtered vertex set.
'''''
'''
[source,cpp]
----
std::pair<edge_iterator, edge_iterator>
edges(const filtered_graph& g)
edges(const filtered_graph& g);
----
Returns an iterator-range providing access to the edge set of graph
`g`.
Returns an iterator-range for the filtered edge set.
'''''
[source,cpp]
----
std::pair<adjacency_iterator, adjacency_iterator>
adjacent_vertices(vertex_descriptor u, const filtered_graph& g)
----
Returns an iterator-range providing access to the vertices adjacent to
vertex `u` in graph `g`.
'''''
'''
[source,cpp]
----
std::pair<out_edge_iterator, out_edge_iterator>
out_edges(vertex_descriptor u, const filtered_graph& g)
out_edges(vertex_descriptor u, const filtered_graph& g);
----
Returns an iterator-range providing access to the out-edges of vertex
`u` in graph `g`. If the graph is undirected, this iterator-range
provides access to all edges incident on vertex `u`. For both directed
and undirected graphs, for an out-edge `e`, `source(e, g) == u` and
`target(e, g) == v` where `v` is a vertex adjacent to `u`.
Returns an iterator-range for the filtered out-edges of vertex `u`.
'''''
'''
[source,cpp]
----
std::pair<in_edge_iterator, in_edge_iterator>
in_edges(vertex_descriptor v, const filtered_graph& g)
in_edges(vertex_descriptor v, const filtered_graph& g);
----
Returns an iterator-range providing access to the in-edges of vertex
`v` in graph `g`. For an in-edge `e`, `target(e, g) == v` and
`source(e, g) == u` for some vertex `u` that is adjacent to `v`,
whether the graph is directed or undirected.
Returns an iterator-range for the filtered in-edges of vertex `v`.
Requires the underlying graph to model BidirectionalGraph.
'''''
'''
[source,cpp]
----
vertex_descriptor
source(edge_descriptor e, const filtered_graph& g)
std::pair<adjacency_iterator, adjacency_iterator>
adjacent_vertices(vertex_descriptor u, const filtered_graph& g);
----
Returns the source vertex of edge `e`.
Returns an iterator-range for the vertices adjacent to `u` through filtered
edges.
'''''
'''
[source,cpp]
----
vertex_descriptor
target(edge_descriptor e, const filtered_graph& g)
vertex_descriptor source(edge_descriptor e, const filtered_graph& g);
vertex_descriptor target(edge_descriptor e, const filtered_graph& g);
----
Returns the target vertex of edge `e`.
Returns the source/target vertex of edge `e`.
'''''
'''
[source,cpp]
----
degree_size_type
out_degree(vertex_descriptor u, const filtered_graph& g)
degree_size_type out_degree(vertex_descriptor u, const filtered_graph& g);
degree_size_type in_degree(vertex_descriptor u, const filtered_graph& g);
----
Returns the number of edges leaving vertex `u`.
Returns the filtered out-degree/in-degree of vertex `u`.
'''''
'''
[source,cpp]
----
degree_size_type
in_degree(vertex_descriptor u, const filtered_graph& g)
vertices_size_type num_vertices(const filtered_graph& g);
edges_size_type num_edges(const filtered_graph& g);
----
Returns the number of edges entering vertex `u`.
Returns the number of vertices/edges in the _underlying_ graph (not the
filtered count).
'''''
[[num_vertices]]
[source,cpp]
----
vertices_size_type
num_vertices(const filtered_graph& g)
----
Returns the number of vertices in the underlying graph <<2,[2]>>.
'''''
[[num_edges]]
[source,cpp]
----
edges_size_type
num_edges(const filtered_graph& g)
----
Returns the number of edges in the underlying graph <<2,[2]>>.
'''''
'''
[source,cpp]
----
std::pair<edge_descriptor, bool>
edge(vertex_descriptor u, vertex_descriptor v,
const filtered_graph& g)
edge(vertex_descriptor u, vertex_descriptor v, const filtered_graph& g);
----
Returns the edge connecting vertex `u` to vertex `v` in graph `g`.
Returns the edge connecting `u` to `v`, if it exists and passes the filter.
'''''
'''
[source,cpp]
----
template <typename G, typename EP, typename VP>
std::pair<out_edge_iterator, out_edge_iterator>
edge_range(vertex_descriptor u, vertex_descriptor v,
const filtered_graph& g)
const filtered_graph& g);
----
Returns a pair of out-edge iterators that give the range for all the
parallel edges from `u` to `v`. This function only works when the
underlying graph supports `edge_range`, which requires that it sorts
its out edges according to target vertex and allows parallel edges. The
`adjacency_list` class with `OutEdgeList=multisetS` is an example of
such a graph.
Returns all parallel edges from `u` to `v`. Only works when the underlying
graph sorts out-edges by target (e.g. `adjacency_list` with
`OutEdgeList=multisetS`).
'''''
===== Property Map Access
'''''
=== Property Map Access
[source,cpp]
----
template <typename PropertyTag>
property_map<filtered_graph, PropertyTag>::type
get(PropertyTag, filtered_graph& g)
get(PropertyTag, filtered_graph& g);
template <typename PropertyTag>
property_map<filtered_graph, PropertyTag>::const_type
get(PropertyTag, const filtered_graph& g)
get(PropertyTag, const filtered_graph& g);
----
Returns the property map object for the vertex property specified by
`PropertyTag`. The `PropertyTag` must match one of the properties
specified in the graph's `VertexProperty` template argument.
Returns the property map for the given tag. The same property maps from the
underlying graph are accessible through the filtered graph.
'''''
'''
[source,cpp]
----
template <typename PropertyTag, typename X>
typename property_traits<property_map<filtered_graph, PropertyTag>::const_type>::value_type
get(PropertyTag, const filtered_graph& g, X x)
auto get(PropertyTag, const filtered_graph& g, X x);
----
This returns the property value for `x`, where `x` is either a vertex
or edge descriptor.
Returns the property value for vertex or edge `x`.
'''''
'''
[source,cpp]
----
template <typename PropertyTag, typename X, typename Value>
void
put(PropertyTag, const filtered_graph& g, X x, const Value& value)
void put(PropertyTag, const filtered_graph& g, X x, const Value& value);
----
This sets the property value for `x` to `value`. `x` is either a
vertex or edge descriptor. `Value` must be convertible to
`typename property_traits<property_map<filtered_graph, PropertyTag>::type>::value_type`
Sets the property value for vertex or edge `x`. This modifies the property in
the underlying graph.
'''''
== Associated Types
==== See Also
[cols="1,3",options="header"]
|===
| Type | Description
xref:helpers/property_map.adoc[`property_map`],
xref:traits/graph_traits.adoc[`graph_traits`]
| `vertex_descriptor`
| Same as the underlying graph.
==== Notes
| `edge_descriptor`
| Same as the underlying graph.
[[1]][1] The reason for requiring
http://www.boost.org/sgi/stl/DefaultConstructible.html[Default
Constructible] in the `EdgePredicate` and `VertexPredicate` types is
that these predicates are stored by-value (for performance reasons) in
the filter iterator adaptor, and iterators are required to be Default
Constructible by the C++ Standard.
| `vertex_iterator`
| `filter_iterator<VertexPredicate, graph_traits<Graph>::vertex_iterator>`
[[2]][2] It would be nicer to return the number of vertices (or edges)
remaining after the filter has been applied, but this has two problems.
The first is that it would take longer to calculate, and the second is
that it would interact badly with the underlying vertex/edge index
mappings. The index mapping would no longer fall in the range
`[0,num_vertices(g))` (resp. `[0, num_edges(g))`) which is assumed in
many of the algorithms.
| `edge_iterator`
| `filter_iterator<EdgePredicate, graph_traits<Graph>::edge_iterator>`
| `out_edge_iterator`
| `filter_iterator<EdgePredicate, graph_traits<Graph>::out_edge_iterator>`
| `adjacency_iterator`
| Models the same iterator concept as `out_edge_iterator`.
| `directed_category`
| `directed_tag` or `undirected_tag` (from underlying graph).
| `edge_parallel_category`
| `allow_parallel_edge_tag` or `disallow_parallel_edge_tag` (from underlying graph).
| `vertices_size_type`, `edges_size_type`, `degree_size_type`
| Size types from the underlying graph.
|===
== Helper Predicates
The header provides several ready-made predicates:
[cols="1,3"]
|===
| Predicate | Description
| `keep_all`
| Keeps all elements (the default vertex predicate).
| `is_residual_edge<ResCapMap>`
| Keeps edges with positive residual capacity. Useful for max-flow.
| `is_in_subset<Set>`
| Keeps vertices that are in the given set.
| `is_not_in_subset<Set>`
| Keeps vertices that are not in the given set.
|===
+180 -236
View File
@@ -1,276 +1,220 @@
= `grid_graph`
= Grid Graph
* <<overview,Overview>>
* <<creating,Creating a Grid Graph>>
* <<indexing,Indexing>>
* <<member,Grid Graph Member Functions>>
A multi-dimensional, rectangular grid of vertices with user-defined dimension
lengths and optional wrapping per dimension.
==== Overview
*Defined in:* `<boost/graph/grid_graph.hpp>` +
*Models:* IncidenceGraph, AdjacencyGraph, VertexListGraph, EdgeListGraph,
BidirectionalGraph, AdjacencyMatrix
A `grid_graph` represents a multi-dimensional, rectangular grid of
vertices with user-defined dimension lengths and wrapping.
NOTE: `grid_graph` does not support bundled properties. To associate data with
grid cells (e.g. terrain costs), maintain an external container indexed by the
grid's vertex index: `std::vector<double> cost(num_vertices(g));`
`grid_graph` models:
== Flat grid
* xref:concepts/IncidenceGraph.adoc[Incidence Graph]
* xref:concepts/AdjacencyGraph.adoc[Adjacency Graph]
* xref:concepts/VertexListGraph.adoc[Vertex List Graph]
* xref:concepts/EdgeListGraph.adoc[Edge List Graph]
* xref:concepts/BidirectionalGraph.adoc[Bidirectional Graph]
* xref:concepts/AdjacencyMatrix.adoc[Adjacency Matrix]
The simplest case: a rectangular grid with no wrapping. Corner vertices have
fewer neighbors than interior vertices.
Defined in
link:../../../boost/graph/grid_graph.hpp[`boost/graph/grid_graph.hpp`]
with all functions in the `boost` namespace. A simple examples of
creating and iterating over a grid_graph is available here
link:../../../libs/graph/example/grid_graph_example.cpp[`libs/graph/example/grid_graph_example.cpp`].
An example of adding properties to a grid_graph is also available
link:../../../libs/graph/example/grid_graph_properties.cpp[`libs/graph/example/grid_graph_properties.cpp`]
image::figs/grid_graph_unwrapped.png[3x3 unwrapped grid]
===== Template Parameters
[source,code]
[source,cpp]
----
include::example$adaptors/grid_graph_unwrapped.cpp[]
----
Expected output:
....
9 vertices, 24 edges
(0,0) degree=2
(1,0) degree=3
(2,0) degree=2
(0,1) degree=3
(1,1) degree=4
(2,1) degree=3
(0,2) degree=2
(1,2) degree=3
(2,2) degree=2
....
== Torus (all dimensions wrap)
Pass `true` as the second constructor argument to wrap all dimensions. Every
vertex now has the same degree.
image::figs/grid_graph_wrapped.png[3x3 wrapped grid (torus)]
[source,cpp]
----
include::example$adaptors/grid_graph_torus.cpp[]
----
Expected output:
....
9 vertices, 36 edges
(0,0) degree=4
(1,0) degree=4
(2,0) degree=4
(0,1) degree=4
(1,1) degree=4
(2,1) degree=4
(0,2) degree=4
(1,2) degree=4
(2,2) degree=4
....
== Cylinder (mixed wrapping)
Pass a `boost::array<bool, Dimensions>` to control wrapping per dimension.
Here dimension 0 wraps (cylinder) but dimension 1 does not.
[source,cpp]
----
include::example$adaptors/grid_graph_cylinder.cpp[]
----
Expected output:
....
12 vertices, 40 edges
From (0,0):
previous in dim 0 (wraps) = (3,0)
previous in dim 1 (stops) = (0,0)
....
== Higher dimensions
The `Dimensions` template parameter is a compile-time constant. A 3D grid
works the same way.
[source,cpp]
----
include::example$adaptors/grid_graph_3d.cpp[]
----
Expected output:
....
27 vertices, 108 edges
corner (0,0,0) degree=3
center (1,1,1) degree=6
....
'''
== Synopsis
[source,cpp]
----
template <std::size_t Dimensions,
typename VertexIndex = std::size_t,
typename EdgeIndex = VertexIndex>
class grid_graph;
class grid_graph;
----
* `Dimensions` - Number of dimensions in the graph
* `VertexIndex` - Type used for vertex indices, defaults to
`std::size_t`
* `EdgeIndex` - Type used for edge indices, defaults to the same type as
`VertexIndex`
== Template Parameters
[[creating]]
==== Creating a Grid Graph
[cols="1,3,1",options="header"]
|===
| Parameter | Description | Default
The constructor to `grid_graph` has several overloads to aid in
configuring each dimension:
| `Dimensions`
| Number of dimensions (compile-time constant).
|
[source,code]
| `VertexIndex`
| Integer type for vertex indices.
| `std::size_t`
| `EdgeIndex`
| Integer type for edge indices.
| same as `VertexIndex`
|===
== Constructors
[source,cpp]
----
grid_graph(boost::array<VertexIndex, Dimensions> lengths);
----
// Defines a grid_graph that does not wrap.
grid_graph<...>(boost:array<VertexIndex, Dimensions> dimension_lengths);
Create an unwrapped grid with the given dimension lengths.
// Defines a grid_graph where all dimensions are either wrapped or unwrapped.
grid_graph<...>(boost:array<VertexIndex, Dimensions> dimension_lengths,
bool wrap_all_dimensions);
'''
// Defines a grid_graph where the wrapping for each dimension is specified individually.
grid_graph<...>(boost:array<VertexIndex, Dimensions> dimension_lengths,
boost:array<bool, Dimensions> wrap_dimension);
[source,cpp]
----
grid_graph(boost::array<VertexIndex, Dimensions> lengths,
bool wrap_all);
----
===== Example
Create a grid where all dimensions wrap (`true`) or none wrap (`false`).
[source,code]
'''
[source,cpp]
----
grid_graph(boost::array<VertexIndex, Dimensions> lengths,
boost::array<bool, Dimensions> wrap_per_dim);
----
// Define dimension lengths, a 3x3 in this case
boost::array<std::size_t, 2> lengths = { { 3, 3 } };
Create a grid with per-dimension wrapping control.
// Create a 3x3 two-dimensional, unwrapped grid graph (Figure 1)
grid_graph<2> graph(lengths);
== Member Functions
// Create a 3x3 two-dimensional, wrapped grid graph (Figure 2)
grid_graph<2> graph(lengths, true);
[source,cpp]
----
image:figs/grid_graph_unwrapped.png[figs/grid_graph_unwrapped] +
_*Figure 1:* A 3x3 two-dimensional, unwrapped grid graph_
image:figs/grid_graph_wrapped.png[figs/grid_graph_wrapped] +
_*Figure 2:* A 3x3 two-dimensional, wrapped grid graph_
==== Indexing
The `grid_graph` supports addressing vertices and edges by index.
The following functions allow you to convert between vertices, edges,
and their associated indices:
[source,code]
----
typedef grid_graph<...> Graph;
typedef graph_traits<Graph> Traits;
// Get the vertex associated with vertex_index
Traits::vertex_descriptor
vertex(Traits::vertices_size_type vertex_index,
const Graph& graph);
// Get the index associated with vertex
Traits::vertices_size_type
get(boost::vertex_index_t,
const Graph& graph,
Traits::vertex_descriptor vertex);
// Get the edge associated with edge_index
Traits::edge_descriptor
edge_at(Traits::edges_size_type edge_index,
const Graph& graph);
// Get the index associated with edge
Traits::edges_size_type
get(boost::edge_index_t,
const Graph& graph,
Traits::edge_descriptor edge);
// Get the out-edge associated with vertex and out_edge_index
Traits::edge_descriptor
out_edge_at(Traits::vertex_descriptor vertex,
Traits::degree_size_type out_edge_index,
const Graph& graph);
// Get the out-edge associated with vertex and in_edge_index
Traits::edge_descriptor
in_edge_at(Traits::vertex_descriptor vertex,
Traits::degree_size_type in_edge_index,
const Graph& graph);
----
===== Example
[source,code]
----
typedef grid_graph<2> Graph;
typedef graph_traits<Graph> Traits;
// Create a 3x3, unwrapped grid_graph (Figure 3)
boost::array<std::size_t, 2> lengths = { { 3, 3 } };
Graph graph(lengths);
// Do a round-trip test of the vertex index functions
for (Traits::vertices_size_type v_index = 0;
v_index < num_vertices(graph); ++v_index) {
// The two indices should always be equal
std::cout << "Index of vertex " << v_index << " is " <<
get(boost::vertex_index, graph, vertex(v_index, graph)) << std::endl;
}
// Do a round-trip test of the edge index functions
for (Traits::edges_size_type e_index = 0;
e_index < num_edges(graph); ++e_index) {
// The two indices should always be equal
std::cout << "Index of edge " << e_index << " is " <<
get(boost::edge_index, graph, edge_at(e_index, graph)) << std::endl;
}
----
image:figs/grid_graph_indexed.png[figs/grid_graph_indexed] +
_*Figure 3:* 3x3 unwrapped grid_graph with vertex and edge indices
shown._
[[member]]
==== Member Functions
There are several `grid_graph` specific member functions available:
[source,code]
----
typedef grid_graph<...> Graph;
typedef graph_traits<Graph> Traits;
// Returns the number of dimensions
std::size_t dimensions();
// Returns the length of a dimension
Traits::vertices_size_type length(std::size_t dimension);
// Returns true if the dimension wraps, false if not
bool wrapped(std::size_t dimension);
// Returns the "next" vertex in a dimension at a given distance. If the dimension
// is unwrapped, next will stop at the last vertex in the dimension.
Traits::vertex_descriptor next(Traits::vertex_descriptor vertex,
std::size_t dimension,
Traits::vertices_size_type distance = 1);
// Returns the "previous" vertex in a dimension at a given distance. If the
// dimension is unwrapped, previous will stop at the beginning vertex in the dimension.
Traits::vertex_descriptor previous(Traits::vertex_descriptor vertex,
std::size_t dimension,
Traits::vertices_size_type distance = 1);
----
===== Example
Returns the number of dimensions.
[source,code]
'''
[source,cpp]
----
VertexIndex length(std::size_t dim);
----
typedef grid_graph<3> Graph;
typedef graph_traits<Graph> Traits;
Returns the length of dimension `dim`.
// Define a 3x5x7 grid_graph where the second dimension doesn't wrap
boost::array<std::size_t, 3> lengths = { { 3, 5, 7 } };
boost::array<bool, 3> wrapped = { { true, false, true } };
Graph graph(lengths, wrapped);
'''
// Print number of dimensions
std::cout << graph.dimensions() << std::endl; // prints "3"
// Print dimension lengths (same order as in the lengths array)
std::cout << graph.length(0) << "x" << graph.length(1) <<
"x" << graph.length(2) << std::endl; // prints "3x5x7"
// Print dimension wrapping (W = wrapped, U = unwrapped)
std::cout << graph.wrapped(0) ? "W" : "U" << ", " <<
graph.wrapped(1) ? "W" : "U" << ", " <<
graph.wrapped(2) ? "W" : "U" << std::endl; // prints "W, U, W"
// Define a simple function to print vertices
void print_vertex(Traits::vertex_descriptor vertex_to_print) {
std::cout << "(" << vertex_to_print[0] << ", " << vertex_to_print[1] <<
", " << vertex_to_print[2] << ")" << std::endl;
}
// Start with the first vertex in the graph
Traits::vertex_descriptor first_vertex = vertex(0, graph);
print_vertex(first_vertex); // prints "(0, 0, 0)"
// Print the next vertex in dimension 0
print_vertex(graph.next(first_vertex, 0)); // prints "(1, 0, 0)"
// Print the next vertex in dimension 1
print_vertex(graph.next(first_vertex, 1)); // prints "(0, 1, 0)"
// Print the 5th next vertex in dimension 2
print_vertex(graph.next(first_vertex, 2, 5)); // prints "(0, 0, 5)"
// Print the previous vertex in dimension 0 (wraps)
print_vertex(graph.previous(first_vertex, 0)); // prints "(2, 0, 0)"
// Print the previous vertex in dimension 1 (doesn't wrap, so it's the same)
print_vertex(graph.previous(first_vertex, 1)); // prints "(0, 0, 0)"
// Print the 20th previous vertex in dimension 2 (wraps around twice)
print_vertex(graph.previous(first_vertex, 2, 20)); // prints "(0, 0, 1)"
[source,cpp]
----
bool wrapped(std::size_t dim);
----
'''''
Returns whether dimension `dim` wraps.
Copyright © 2009 Trustees of Indiana University
'''
[source,cpp]
----
vertex_descriptor next(vertex_descriptor v, std::size_t dim,
vertices_size_type distance = 1);
vertex_descriptor previous(vertex_descriptor v, std::size_t dim,
vertices_size_type distance = 1);
----
Move along a dimension. In an unwrapped dimension, `next` stops at the last
vertex and `previous` stops at the first. In a wrapped dimension, movement
wraps around.
== Indexing
Vertices and edges can be addressed by integer index:
[source,cpp]
----
vertex_descriptor vertex(vertices_size_type idx, const grid_graph& g);
edges_size_type get(edge_index_t, const grid_graph& g, edge_descriptor e);
edge_descriptor edge_at(edges_size_type idx, const grid_graph& g);
----
The vertex descriptor is a `boost::array<VertexIndex, Dimensions>` that can
be indexed by dimension: `v[0]` is the position in dimension 0, `v[1]` in
dimension 1, etc.
@@ -0,0 +1,41 @@
= Graph Adaptors
A graph adaptor wraps an existing graph and presents a different view of it
without copying. The original graph's data and structure are reused. Adaptors
are lightweight (typically O(1) to construct) and composable.
[cols="1,3"]
|===
| Adaptor | What it does
| xref:adaptors/filtered_graph.adoc[filtered_graph]
| Hides vertices and/or edges based on predicate functions.
| xref:adaptors/reverse_graph.adoc[reverse_graph]
| Reverses all edge directions (graph transposition). O(1).
| xref:adaptors/subgraph.adoc[subgraph]
| Selects a subset of vertices; all edges between them are included
automatically. Supports parent/child nesting.
| xref:adaptors/edge_list.adoc[edge_list]
| Turns raw data (an array of `std::pair`, a CSV file parsed into pairs, etc.)
into a graph that algorithms like `bellman_ford_shortest_paths` can consume
directly. Useful when you have edge data but do not want to build a full
`adjacency_list`.
| xref:adaptors/grid_graph.adoc[grid_graph]
| N-dimensional rectangular grid with optional wrapping per dimension.
Not an adaptor in the strict sense (it generates its own structure), but
it follows the same zero-copy philosophy.
|===
Adaptors model the same graph concepts as their underlying graph. A
`filtered_graph` over a BidirectionalGraph is itself a BidirectionalGraph.
A `reverse_graph` over a BidirectionalGraph is a BidirectionalGraph.
Vertex and edge descriptors from an adaptor are typically the same type as
descriptors from the underlying graph, so they can be used interchangeably.
The exception is `subgraph`, which uses local descriptors that must be
converted with `local_to_global()` and `global_to_local()`.
+104 -348
View File
@@ -1,432 +1,188 @@
= Reverse Graph Adaptor
= Reverse Graph
....
A view of a graph with all edges reversed (transposed). Construction is O(1).
reverse_graph<BidirectionalGraph, GraphReference>
....
*Defined in:* `<boost/graph/reverse_graph.hpp>` +
*Models:* BidirectionalGraph, VertexListGraph, PropertyGraph (depending on
underlying graph)
The `reverse_graph` adaptor flips the in-edges and out-edges of a
xref:concepts/BidirectionalGraph.adoc[BidirectionalGraph], effectively
transposing the graph. The construction of the `reverse_graph` is
constant time, providing a highly efficient way to obtain a transposed
view of a graph.
==== Example
The example from
link:../example/reverse_graph.cpp[`example/reverse_graph.cpp`].
== Example
[source,cpp]
----
int
main()
{
typedef boost::adjacency_list<
boost::vecS, boost::vecS, boost::bidirectionalS,
> Graph;
Graph G(5);
boost::add_edge(0, 2, G);
boost::add_edge(1, 1, G);
boost::add_edge(1, 3, G);
boost::add_edge(1, 4, G);
boost::add_edge(2, 1, G);
boost::add_edge(2, 3, G);
boost::add_edge(2, 4, G);
boost::add_edge(3, 1, G);
boost::add_edge(3, 4, G);
boost::add_edge(4, 0, G);
boost::add_edge(4, 1, G);
std::cout << "original graph:" << std::endl;
boost::print_graph(G, boost::get(boost::vertex_index, G));
std::cout << std::endl << "reversed graph:" << std::endl;
boost::print_graph(boost::make_reverse_graph(G),
boost::get(boost::vertex_index, G));
return 0;
}
include::example$adaptors/reverse_graph.cpp[]
----
The output is:
Expected output:
....
Original:
0 --> 1
1 --> 2
2 --> 3
3 --> 0
original graph:
0 --> 2
1 --> 1 3 4
2 --> 1 3 4
3 --> 1 4
4 --> 0 1
reversed graph:
0 --> 4
1 --> 1 2 3 4
2 --> 0
3 --> 1 2
4 --> 1 2 3
Reversed:
0 --> 3
1 --> 0
2 --> 1
3 --> 2
....
==== Template Parameters
[cols=",,",options="header",]
|===
|Parameter |Description |Default
|`BidirectionalGraph` |The graph type to be adapted. | 
|`GraphReference` |This type should be `const BidirectionalGraph&` if
you want to create a const reverse graph, or `BidirectionalGraph&` if
you want to create a non-const reverse graph.
|`const BidirectionalGraph&`
|===
==== Model of
xref:concepts/BidirectionalGraph.adoc[BidirectionalGraph] and optionally
xref:concepts/VertexListGraph.adoc[VertexListGraph] and
xref:concepts/PropertyGraph.adoc[PropertyGraph]
==== Where Defined
link:../../../boost/graph/reverse_graph.hpp[`boost/graph/reverse_graph.hpp`]
=== Associated Types
'''''
`graph_traits<reverse_graph>::vertex_descriptor` +
+
The type for the vertex descriptors associated with the
`reverse_graph`.
'''''
`graph_traits<reverse_graph>::edge_descriptor` +
+
The type for the edge descriptors associated with the
`reverse_graph`.
'''''
`graph_traits<reverse_graph>::vertex_iterator` +
+
The type for the iterators returned by `vertices()`.
'''''
`graph_traits<reverse_graph>::edge_iterator` +
+
The type for the iterators returned by `edges()`.
'''''
`graph_traits<reverse_graph>::out_edge_iterator` +
+
The type for the iterators returned by `out_edges()`.
'''''
`graph_traits<reverse_graph>::adjacency_iterator` +
+
The type for the iterators returned by `adjacent_vertices()`.
'''''
`graph_traits<reverse_graph>::directed_category` +
+
Provides information about whether the graph is directed
(`directed_tag`) or undirected (`undirected_tag`).
'''''
`graph_traits<reverse_graph>::edge_parallel_category` +
+
This describes whether the graph class allows the insertion of parallel
edges (edges with the same source and target). The two tags are
`allow_parallel_edge-_tag` and
`disallow_parallel_edge_tag`. The `setS` and `hash_setS`
variants disallow parallel edges while the others allow parallel edges.
'''''
`graph_traits<reverse_graph>::vertices_size_type` +
+
The type used for dealing with the number of vertices in the graph.
'''''
`graph_traits<reverse_graph>::edges_size_type` +
+
The type used for dealing with the number of edges in the graph.
'''''
`graph_traits<reverse_graph>::degree_size_type` +
+
The type used for dealing with the number of edges incident to a vertex
in the graph.
'''''
`property_map<reverse_graph, PropertyTag>::type` +
and +
`property_map<reverse_graph, PropertyTag>::const_type` +
+
The property map type for vertex or edge properties in the graph. The
specific property is specified by the `PropertyTag` template argument,
and must match one of the properties specified in the `VertexProperty`
or `EdgeProperty` for the graph.
'''''
`property_map<reverse_graph, edge_underlying_t>::type` +
and +
`property_map<reverse_graph, edge_underlying_t>::const_type` +
+
An edge property type mapping from edge descriptors in the
`reverse_graph` to edge descriptors in the underlying
`BidirectionalGraph` object.
'''''
=== Member Functions
'''''
....
reverse_graph(BidirectionalGraph& g)
....
Constructor. Create a reversed (transposed) view of the graph `g`.
'''''
=== Non-Member Functions
'''''
== Synopsis
[source,cpp]
----
template <typename BidirectionalGraph>
reverse_graph<BidirectionalGraph, BidirectionalGraph&>
make_reverse_graph(BidirectionalGraph& g);
template <typename BidirectionalGraph,
typename GraphRef = const BidirectionalGraph&>
class reverse_graph;
template <typename BidirectionalGraph>
reverse_graph<BidirectionalGraph, const BidirectionalGraph&>
make_reverse_graph(const BidirectionalGraph& g)
make_reverse_graph(const BidirectionalGraph& g);
template <typename BidirectionalGraph>
reverse_graph<BidirectionalGraph, BidirectionalGraph&>
make_reverse_graph(BidirectionalGraph& g);
----
Helper function for creating a `reverse_graph`.
The `reverse_graph` does not copy the original graph. It holds a reference and
swaps the meaning of `out_edges` and `in_edges`. This makes `source()` and
`target()` return the opposite of what they return on the original graph.
'''''
The `GraphRef` parameter controls const-ness: `const BidirectionalGraph&`
(default) gives a read-only view, `BidirectionalGraph&` gives a mutable view.
== Template Parameters
[cols="1,3,1",options="header"]
|===
| Parameter | Description | Default
| `BidirectionalGraph`
| The underlying graph type. Must model BidirectionalGraph.
|
| `GraphRef`
| Reference type to the underlying graph. Use `const BidirectionalGraph&` for a
read-only view, `BidirectionalGraph&` for a mutable view.
| `const BidirectionalGraph&`
|===
== Non-Member Functions
=== Structure Access
[source,cpp]
----
std::pair<vertex_iterator, vertex_iterator>
vertices(const reverse_graph& g)
vertices(const reverse_graph& g);
----
Returns an iterator-range providing access to the vertex set of graph
`g`.
Same vertices as the underlying graph.
'''''
'''
[source,cpp]
----
std::pair<out_edge_iterator, out_edge_iterator>
out_edges(vertex_descriptor v, const reverse_graph& g)
vertex_descriptor vertex(vertices_size_type n, const reverse_graph& g);
----
Returns an iterator-range providing access to the out-edges of vertex
`v` in graph `g`. These out-edges correspond to the in-edges of the
adapted graph.
Returns the nth vertex.
'''''
[source,cpp]
----
std::pair<in_edge_iterator, in_edge_iterator>
in_edges(vertex_descriptor v, const reverse_graph& g)
----
Returns an iterator-range providing access to the in-edges of vertex
`v` in graph `g`. These in-edges correspond to the out edges of the
adapted graph.
'''''
'''
[source,cpp]
----
std::pair<adjacency_iterator, adjacency_iterator>
adjacent_vertices(vertex_descriptor v, const reverse_graph& g)
adjacent_vertices(vertex_descriptor v, const reverse_graph& g);
----
Returns an iterator-range providing access to the adjacent vertices of
vertex `v` in graph `g`.
Returns the vertices adjacent to `v` through reversed edges.
'''''
'''
[source,cpp]
----
vertex_descriptor
source(edge_descriptor e, const reverse_graph& g)
std::pair<out_edge_iterator, out_edge_iterator>
out_edges(vertex_descriptor v, const reverse_graph& g);
----
Returns the source vertex of edge `e`.
Returns the in-edges of `v` in the underlying graph (as out-edges of the
reversed view).
'''''
'''
[source,cpp]
----
vertex_descriptor
target(edge_descriptor e, const reverse_graph& g)
std::pair<in_edge_iterator, in_edge_iterator>
in_edges(vertex_descriptor v, const reverse_graph& g);
----
Returns the target vertex of edge `e`.
Returns the out-edges of `v` in the underlying graph (as in-edges of the
reversed view).
'''''
'''
[source,cpp]
----
degree_size_type
out_degree(vertex_descriptor u, const reverse_graph& g)
vertex_descriptor source(edge_descriptor e, const reverse_graph& g);
vertex_descriptor target(edge_descriptor e, const reverse_graph& g);
----
Returns the number of edges leaving vertex `u`.
Reversed: `source()` returns the target of the underlying edge, and vice versa.
'''''
'''
[source,cpp]
----
degree_size_type
in_degree(vertex_descriptor u, const reverse_graph& g)
degree_size_type out_degree(vertex_descriptor u, const reverse_graph& g);
degree_size_type in_degree(vertex_descriptor u, const reverse_graph& g);
vertices_size_type num_vertices(const reverse_graph& g);
edges_size_type num_edges(const reverse_graph& g);
----
Returns the number of edges entering vertex `u`. This operation is only
available if `bidirectionalS` was specified for the `Directed` template
parameter.
Degree and count functions. `out_degree` returns the in-degree of the
underlying graph, and vice versa.
'''''
=== Property Map Access
[source,cpp]
----
vertices_size_type
num_vertices(const reverse_graph& g)
----
Returns the number of vertices in the graph `g`.
'''''
[source,cpp]
----
vertex_descriptor
vertex(vertices_size_type n, const reverse_graph& g)
----
Returns the nth vertex in the graph's vertex list.
'''''
[source,cpp]
----
std::pair<edge_descriptor, bool>
edge(vertex_descriptor u, vertex_descriptor v,
const reverse_graph& g)
----
Returns the edge connecting vertex `u` to vertex `v` in graph `g`.
'''''
Property maps from the underlying graph are accessible through the reversed
view. Additionally, the `edge_underlying_t` property maps reversed edge
descriptors back to the underlying edge descriptors.
[source,cpp]
----
template <typename PropertyTag>
property_map<reverse_graph, PropertyTag>::type
get(PropertyTag, reverse_graph& g)
get(PropertyTag, reverse_graph& g);
template <typename PropertyTag>
property_map<reverse_graph, PropertyTag>::const_type
get(PropertyTag, const reverse_graph& g)
get(PropertyTag, const reverse_graph& g);
----
Returns the property map object for the vertex property specified by
`PropertyTag`. The `PropertyTag` must match one of the properties
specified in the graph's `VertexProperty` template argument.
== Associated Types
'''''
[cols="1,3",options="header"]
|===
| Type | Description
[source,cpp]
----
property_map<reverse_graph, edge_underlying_t>::const_type
get(edge_underlying_t, const reverse_graph& g)
----
| `vertex_descriptor`
| Same as the underlying graph.
Returns a property map object that converts from edge descriptors in the
`reverse_graph` to edge descriptors in the underlying
`BidirectionalGraph` object.
| `edge_descriptor`
| Same as the underlying graph.
'''''
| `out_edge_iterator`
| Corresponds to `in_edge_iterator` of the underlying graph.
[source,cpp]
----
template <typename PropertyTag, typename X>
typename property_traits<property_map<reverse_graph, PropertyTag>::const_type>::value_type
get(PropertyTag, const reverse_graph& g, X x)
----
| `in_edge_iterator`
| Corresponds to `out_edge_iterator` of the underlying graph.
This returns the property value for `x`, which is either a vertex or
edge descriptor.
| `directed_category`
| From the underlying graph.
'''''
[source,cpp]
----
typename graph_traits<BidirectionalGraph>::edge_descriptor
get(edge_underlying_t, const reverse_graph& g, edge_descriptor e)
----
This returns the underlying edge descriptor for the edge `e` in the
`reverse_graph`.
'''''
[source,cpp]
----
template <typename PropertyTag, typename X, typename Value>
void
put(PropertyTag, const reverse_graph& g, X x, const Value& value)
----
This sets the property value for `x` to `value`. `x` is either a
vertex or edge descriptor. `Value` must be convertible to
`typename property_traits<property_map<reverse_graph, PropertyTag>::type>::value_type`
'''''
[source,cpp]
----
template <typename GraphProperties, typename GraphPropertyTag>
typename property_value<GraphProperties, GraphPropertyTag>::type&
get_property(reverse_graph& g, GraphPropertyTag)
----
Return the property specified by `GraphPropertyTag` that is attached to
the graph object `g`. The `property_value` traits class is defined in
link:../../../boost/pending/property.hpp[`boost/pending/property.hpp`].
'''''
[source,cpp]
----
template <typename GraphProperties, typename GraphPropertyTag>
const typename property_value<GraphProperties, GraphPropertyTag>::type&
get_property(const reverse_graph& g, GraphPropertyTag)
----
Return the property specified by `GraphPropertyTag` that is attached to
the graph object `g`. The `property_value` traits class is defined in
link:../../../boost/pending/property.hpp[`boost/pending/property.hpp`].
| `edge_parallel_category`
| From the underlying graph.
|===
@@ -1,248 +0,0 @@
= Using SGB Graphs in BGL
The Boost Graph Library (BGL) header,
link:../../../boost/graph/stanford_graph.hpp[`<boost/graph/stanford_graph.hpp>`],
adapts a Stanford GraphBase (SGB) `Graph` pointer into a BGL-compatible
xref:concepts/VertexListGraph.adoc[VertexListGraph].  Note that a graph adaptor
*class* is _not_ used; SGB's `Graph*` itself becomes a model of
VertexListGraph.  The VertexListGraph concept is fulfilled by defining
the appropriate non-member functions for `Graph*`.
[#sec:SGB]
=== The Stanford GraphBase
"The http://www-cs-staff.stanford.edu/~knuth/sgb.html[Stanford
GraphBase] (SGB) is a collection of datasets and computer programs that
generate and examine a wide variety of graphs and networks."  The SGB
was developed and published by
http://www-cs-staff.stanford.edu/~knuth[Donald E. Knuth] in 1993.  The
fully documented source code is available for anonymous ftp from
ftp://labrea.stanford.edu/pub/sgb/sgb.tar.gz[Stanford University] and in
the book "The Stanford GraphBase, A Platform for Combinatorial
Computing," published jointly by ACM Press and Addison-Wesley Publishing
Company in 1993.  (This book contains several chapters with additional
information not available in the electronic distribution.)
[#sec:CWEB]
==== Prerequisites
The source code of SGB is written in accordance with the rules of the
http://www-cs-staff.stanford.edu/~knuth/lp.html[Literate Programming]
paradigm, so you need to make sure that your computer supports the
http://www-cs-staff.stanford.edu/~knuth/cweb.html[CWEB] system.  The
CWEB sources are available for anonymous ftp from
ftp://labrea.stanford.edu/pub/cweb/cweb.tar.gz[Stanford University]. 
Bootstrapping CWEB on Unix systems is elementary and documented in the
CWEB distribution; pre-compiled binary executables of the CWEB tools for
Win32 systems are available from
http://www.literateprogramming.com[www.literateprogramming.com].
[#sec:SGB:Installation]
==== Installing the SGB
After you have acquired the <<sec:SGB,SGB sources>> and have
installed a working <<sec:CWEB,CWEB system>> (at least the "ctangle"
processor is required), you're almost set for compiling the SGB
sources.  SGB is written in "old-style C," but the Boost Graph Library
expects to handle "modern C" and C++.  Fortunately, the SGB
distribution comes with an appropriate set of patches that convert all
the sources from "KR-C" to "ANSI-C," thus allowing for smooth
integration of the Stanford GraphBase in the Boost Graph Library.
* *Unix*: After extracting the SGB archive, but prior to invoking
"`make tests`" and "`make install`," you should say
"`ln -s PROTOTYPES/*.ch .`" in the root directory where you
extracted the SGB files (or you can simply copy the change files next to
the proper source files).  The Unix `Makefile` coming with SGB
conveniently looks for "change files" matching the SGB source files and
automatically applies them with the "ctangle" processor.  The resulting
C files will smoothly run through the compiler.
* *Win32*: The "MSVC" subdirectory of the SGB distribution contains a
complete set of "Developer Studio Projects" (and a single "Workspace"),
applicable with Microsoft Developer Studio 6.  The installation process
is documented in the accompanying file `README.MSVC`.  The "MSVC"
contribution has been updated to make use of the "PROTOTYPES" as well,
so you don't need to worry about that.
[#sec:UsingSGB]
==== Using the SGB
After you have run <<sec:SGB:Installation,the installation process>>
of the SGB, you can use the BGL graph interface with the SGB
`Graph*`,
link:../../../boost/graph/stanford_graph.hpp[`<boost/graph/stanford_graph.hpp>`],
which will be described <<sec:BGL:Interface,next>>.  All you have to
do is tell the C++ compiler where to look for the SGB
headerfiles (by default, `/usr/local/sgb/include` on Unix and the "MSVC"
subdirectory of the SGB installation on Win32) and the linker where to
find the SGB static library file (`libgb.a` on Unix and `libgb.lib` on
Win32); consult the documentation of your particular compiler about how
to do that.
[#sec:SGB:Problems]
==== Technicalities
* *Headerfile selection*: The two SGB modules `gb_graph` and
`gb_io` use the preprocessor switch `SYSV` to select either the
headerfile `<string.h>` (if `SYSV` is `++#++define`d) or the
headerfile `<strings.h>` (if `SYSV` is _not_ `++#++define`d). 
Some compilers, like `gcc`/`g++`, don't care much (`gcc`
"knows" about the "string" functions without referring to
`<string.h>`), but others, like MSVC on Win32, do (so all
"Developer Studio Projects" in the "MSVC" subdirectory of the
<<sec:SGB,SGB distribution>> appropriately define `SYSV`). You should
be careful to set (or not) `SYSV` according to the needs of your
compiler.
* *Missing include guards*: None of the SGB headerfiles uses "internal
include guards" to protect itself from multiple inclusion.  To avoid
trouble, you must _not_ `++#++include` any of the SGB headerfiles before
or after <<sec:Wrapper,the BGL wrapper>> in a compilation unit; it
will fully suffice to use the BGL interface.
* *Preprocessor macros*: The SGB headerfiles make liberal use of the
preprocessor _without_ sticking to a particular convention (like
all-uppercase names or a particular prefix).  At the time of writing,
already three of these preprocessor macros collide with the conventions
of either C++, g++, or BGL, and are fixed in
<<sec:Wrapper,the BGL wrapper>>.  We can not guarantee that no other
preprocessor-induced problems may arise (but we are willing to learn
about any such collisions).
[#sec:BGL:Interface]
=== The BGL Interface for the SGB
[#sec:Wrapper]
==== Where Defined
link:../../../boost/graph/stanford_graph.hpp[`<boost/graph/stanford_graph.hpp>`]
The main purpose of this Boost Graph Library (BGL) headerfile is to
`++#++include` all global definitions for the general stuff of the
<<sec:SGB,Stanford GraphBase>> (SGB) and its various graph generator
functions by reading all <<sec:SGB:Problems,SGB headerfiles>> as in
section 2 of the "`test_sample`" program.
On top of the SGB stuff, the BGL `stanford_graph.hpp` header adds
and defines appropriate types and functions for using the SGB graphs in
the BGL framework.  Apart from the improved interface, the
<<sec:UsingSGB,SGB (static) library>> is used "as is" in the context
of BGL.
==== Model Of
xref:concepts/VertexListGraph.adoc[Vertex List Graph] and
xref:concepts/PropertyGraph.adoc[Property Graph]. The set of property tags that
can be used with the SGB graph is described in the
<<properties,Vertex and Edge Properties>> section below.
[#sec:Example]
==== Example
The example program
link:../example/miles_span.cpp[`<example/miles_span.cpp>`]
represents the first application of the generic framework of BGL to an
SGB graph.  It uses Prim's algorithm to solve the "minimum spanning
tree" problem.  In addition, the programs
link:../../../libs/graph/example/girth.cpp[`<example/girth.cpp>`]
and
link:../example/roget_components.cpp[`<example/roget_components.cpp>`]
have been ported from the SGB.  We intend to implement more algorithms
from SGB in a generic fashion and to provide the remaining example
programs of SGB for the BGL framework.  If you would like to help, feel
free to submit your contributions!
==== Associated Types
'''''
`graph_traits<Graph++*>++::vertex_descriptor` +
+
The type for the vertex descriptors associated with the `Graph*`. We
use the type `Vertex*` as the vertex descriptor.
'''''
`graph_traits<Graph++*>++::edge_descriptor` +
+
The type for the edge descriptors associated with the `Graph*`. This
is the type `boost::sgb_edge`. In addition to supporting all the
required operations of a BGL edge descriptor, the `boost::sgb_edge`
class has the following constructor.
....
sgb_edge::sgb_edge(Arc* arc, Vertex* source)
....
'''''
`graph_traits<Graph++*>++::vertex_iterator` +
+
The type for the iterators returned by `vertices()`.
'''''
`graph_traits<Graph++*>++::out_edge_iterator` +
+
The type for the iterators returned by `out_edges()`.
'''''
`graph_traits<Graph++*>++::adjacency_iterator` +
+
The type for the iterators returned by `adjacent_vertices()`.
'''''
`graph_traits<Graph++*>++::vertices_size_type` +
+
The type used for dealing with the number of vertices in the graph.
'''''
`graph_traits<Graph++*>++::edge_size_type` +
+
The type used for dealing with the number of edges in the graph.
'''''
`graph_traits<Graph++*>++::degree_size_type` +
+
The type used for dealing with the number of edges incident to a vertex
in the graph.
'''''
`graph_traits<Graph++*>++::directed_category` +
+
Provides information about whether the graph is directed or undirected.
An SGB `Graph*` is directed so this type is `directed_tag`.
'''''
`graph_traits<Graph++*>++::traversal_category` +
+
An SGB `Graph*` provides traversal of the vertex set, out edges, and
adjacent vertices. Therefore the traversal category tag is defined as
follows:
[source,cpp]
----
struct sgb_traversal_tag :
public virtual vertex_list_graph_tag,
public virtual incidence_graph_tag,
public virtual adjacency_graph_tag { };
----
'''''
`graph_traits<Graph++*>++::edge_parallel_category` +
+
This describes whether the graph class allows the insertion of parallel
edges (edges with the same source and target).  The SGB `Graph*`
does not prevent addition of parallel edges, so this type is
`allow_parallel_edge_tag`.
'''''
==== Non-Member Functions
+157 -736
View File
@@ -1,806 +1,227 @@
[#sec:subgraph-class]
= Subgraph
....
An induced subgraph with a hierarchical parent/child structure.
subgraph<Graph>
....
*Defined in:* `<boost/graph/subgraph.hpp>` +
*Models:* VertexMutableGraph, EdgeMutableGraph (plus whatever the underlying
graph models: VertexListGraph, EdgeListGraph, BidirectionalGraph, etc.)
The subgraph class provides a mechanism for keeping track of a graph and
its subgraphs. A graph _G'_ is a _subgraph_ of a graph _G_ if the vertex
set of _G'_ is a subset of the vertex set of _G_ and if the edge set of
_G'_ is a subset of the edge set of _G_. That is, if _G'=(V',E')_ and
_G=(V,E)_, then _G'_ is a subgraph of _G_ if _V'_ is a subset of _V_ and
_E_ is a subset of _E'_. An _induced subgraph_ is a subgraph formed by
specifying a set of vertices _V'_ and then selecting all of the edges
from the original graph that connect two vertices in _V'_. So in this
case _E' = {(u,v) in E: u,v in V'}_. Figure 1 shows a graph _G~0~_
and two subgraphs _G~1~_ and _G~2~_. The edge set for _G~1~_ is _E~1~ =
{ (E,F), (C,F) }_ and the edge set for _G~2~_ is _E~2~ = { (A,B)
}_. Edges such as _(E,B)_ and _(F,D)_ that cross out of a subgraph are
not in the edge set of the subgraph.
WARNING: The underlying graph type must have both `vertex_index` and
`edge_index` internal properties. Edge indices are assigned by the subgraph
class.
[#fig:subgraph-tree]
.*Figure 1:* A graph with nested subgraphs, maintained in a tree
structure.
[cols=",",]
|===
|image:figs/subgraph.gif[figs/subgraph]
|image:figs/subgraph-tree.gif[figs/subgraph-tree]
|===
The `subgraph` class implements induced subgraphs. The main graph and
its subgraphs are maintained in a tree data structure. The main graph is
the root, and subgraphs are either children of the root or of other
subgraphs. All of the nodes in this tree, including the root graph, are
instances of the `subgraph` class. The `subgraph` implementation ensures
that each node in the tree is an induced subgraph of its parent. The
`subgraph` class implements the BGL graph interface, so each subgraph
object can be treated as a graph.
==== Example
The full source code for this example is in `example/subgraph.cpp`. To
create a graph and subgraphs, first create the root graph object. Here
we use `adjacency_list` as the underlying graph implementation. The
underlying graph type is required to have `vertex_index` and
`edge_index` internal properties, so we add an edge index property
to the adjacency list. We do not need to add a vertex index property
because that is built in to the `adjacency_list`. We will be
building the graph and subgraphs in Figure 1, so we will need a total of
six vertices.
== Example
[source,cpp]
----
typedef adjacency_list_traits< vecS, vecS, directedS > Traits;
typedef subgraph< adjacency_list< vecS, vecS, directedS,
no_property, property< edge_index_t, int > > > Graph;
const int N = 6;
Graph G0(N);
enum { A, B, C, D, E, F}; // for conveniently referring to vertices in G0
include::example$adaptors/subgraph.cpp[]
----
Next we create two empty subgraph objects, specifying `G0` as their
Expected output:
....
Root: 5 vertices, 6 edges
Subgraph: 3 vertices, 3 edges
Subgraph edges (local descriptors):
1 -> 2
1 -> 3
2 -> 3
....
== Synopsis
[source,cpp]
----
template <typename Graph>
class subgraph;
----
The `subgraph` class wraps an `adjacency_list` and maintains a tree of
subgraphs. The root graph owns all vertices and edges. Child subgraphs hold
subsets of the root's vertices, and their edge sets are _induced_: any edge in
the root whose both endpoints are in the child automatically appears in the
child.
Each subgraph uses _local_ descriptors (0-based within that subgraph). Use
`local_to_global()` and `global_to_local()` to convert between local and root
descriptors.
Adding an edge to a child subgraph also adds it to all ancestor subgraphs.
Adding a vertex to a child subgraph also adds it to all ancestors.
== Template Parameters
[cols="1,3",options="header"]
|===
| Parameter | Description
| `Graph`
| Must model VertexMutableGraph and EdgeMutableGraph. Must have internal
`vertex_index` and `edge_index` properties. With `vecS` for the vertex
container, `vertex_index` is automatic. `edge_index` must always be declared
explicitly:
`adjacency_list<vecS, vecS, directedS, no_property, property<edge_index_t, int>>`
|===
== Member Functions
=== Constructors
[source,cpp]
----
subgraph(vertices_size_type n,
const GraphProperty& p = GraphProperty());
----
Create a root graph with `n` vertices and no edges.
=== Subgraph Creation
[source,cpp]
----
subgraph& create_subgraph();
----
Create an empty child subgraph.
'''
[source,cpp]
----
template <typename VertexIterator>
subgraph& create_subgraph(VertexIterator first, VertexIterator last);
----
Create a child subgraph with the given vertices. Edges are induced from the
parent.
....
Graph& G1 = G0.create_subgraph(), G2 = G0.create_subgraph();
enum { A1, B1, C1 }; // for conveniently referring to vertices in G1
enum { A2, B2 }; // for conveniently referring to vertices in G2
....
We can add vertices from the root graph to the subgraphs using the
`add_vertex` function. Since the graph implementation is
`adjacency_list` with `VertexList=vecS`, we can use the integers (or
in this case enums) in the range _[0,6)_ as vertex descriptors.
....
add_vertex(C, G1); // global vertex C becomes local A1 for G1
add_vertex(E, G1); // global vertex E becomes local B1 for G1
add_vertex(F, G1); // global vertex F becomes local C1 for G1
add_vertex(A, G2); // global vertex A becomes local A2 for G2
add_vertex(B, G2); // global vertex B becomes local B2 for G2
....
Next we can add edges to the main graph using the usual `add_edge`
function.
....
add_edge(A, B, G0);
add_edge(B, C, G0);
add_edge(B, D, G0);
add_edge(E, B, G0);
add_edge(E, F, G0);
add_edge(F, D, G0);
....
We can also add edges to subgraphs such as `G1` using the `add_edge`
function. Each subgraph has its own vertex and edge descriptors, which
we call _local_ descriptors. We refer to root graph's vertex and edge
descriptors as the _global_ descriptors. Above, we used global vertex
descriptors to add vertices to the graph. However, most `subgraph`
functions work with local descriptors. So in the following call to
`add_edge` we add the edge `(A1,C1)` (or numerically `(0,2)`) which
is the local version (for subgraph `G1`) of the global edge `(C,F)` (or
numerically `(2,5)`). Adding an edge to a subgraph causes the edge to
also be added to all of its ancestors in the subgraph tree to ensure
that the subgraph property is maintained.
....
add_edge(A1, C1, G1); // (A1,C1) is subgraph G1 local indices
// for the global edge (C,F).
....
==== Where Defined
`boost/graph/subgraph.hpp`
==== Template Parameters
[cols=",",options="header",]
|===
|Parameter |Description
|`Graph` |A graph type modeling
xref:concepts/VertexMutableGraph.adoc[VertexMutableGraph] and
xref:concepts/EdgeMutableGraph.adoc[EdgeMutableGraph]. Also the graph must have
internal `vertex_index` and `edge_index` properties. The vertex
indices must be maintained automatically by the graph, whereas the edge
indices will be assigned by the `subgraph` class implementation.
|===
==== Model Of
`subgraph` is a model of
xref:concepts/VertexMutableGraph.adoc[VertexMutableGraph]. Also, if the `Graph`
type models xref:concepts/VertexListGraph.adoc[VertexListGraph],
xref:concepts/EdgeListGraph.adoc[EdgeListGraph] and/or
xref:concepts/BidirectionalGraph.adoc[BidirectionalGraph], then
`subgraph<Graph>` will also models these concepts.
==== Associated Types
If the graph is the root of the subgraph tree, then the vertex and edge
descriptors are both the local descriptors for the root graph, and they
are the global descriptors. If the graph is not the root, then the
descriptors are local descriptors for the subgraph. The subgraph
iterators are the same iterator types as the iterators of the underlying
`Graph` type.
'''''
=== Descriptor Conversion
[source,cpp]
----
graph_traits<subgraph>::vertex_descriptor
vertex_descriptor local_to_global(vertex_descriptor u_local) const;
vertex_descriptor global_to_local(vertex_descriptor u_global) const;
edge_descriptor local_to_global(edge_descriptor e_local) const;
edge_descriptor global_to_local(edge_descriptor e_global) const;
----
The type for the vertex descriptors. (Required by
xref:concepts/Graph.adoc[Graph].)
Convert between local (subgraph-relative) and global (root) descriptors.
'''''
'''
[source,cpp]
----
graph_traits<subgraph>::edge_descriptor
std::pair<vertex_descriptor, bool>
find_vertex(vertex_descriptor u_global) const;
----
The type for the edge descriptors. (Required by xref:concepts/Graph.adoc[Graph].)
Returns `(local_descriptor, true)` if the global vertex is in this subgraph,
`(_, false)` otherwise.
'''''
=== Hierarchy Navigation
[source,cpp]
----
graph_traits<subgraph>::vertex_iterator
subgraph& root();
bool is_root() const;
subgraph& parent();
std::pair<children_iterator, children_iterator> children() const;
----
The type for the iterators returned by `vertices`. (Required by
xref:concepts/VertexListGraph.adoc[VertexListGraph].)
Navigate the subgraph tree. `root()` returns the top-level graph. `parent()`
returns the direct parent. `children()` iterates over child subgraphs.
'''''
== Non-Member Functions
=== Structure Access
Standard graph functions: `vertices()`, `edges()`, `out_edges()`, `in_edges()`,
`adjacent_vertices()`, `source()`, `target()`, `out_degree()`, `in_degree()`,
`num_vertices()`, `num_edges()`, `edge()`. All operate on local descriptors.
=== Structure Modification
WARNING: `remove_vertex()` is not implemented. Calling it triggers an assertion
failure at runtime. If you need to hide vertices, use `filtered_graph` on top
of the subgraph.
[source,cpp]
----
graph_traits<subgraph>::edge_iterator
vertex_descriptor add_vertex(subgraph& g);
----
The type for the iterators returned by `edges`. (Required by
xref:concepts/EdgeListGraph.adoc[EdgeListGraph].)
Add a new vertex to the subgraph (and all ancestors up to root).
'''''
'''
[source,cpp]
----
graph_traits<subgraph>::out_edge_iterator
vertex_descriptor add_vertex(vertex_descriptor u_global, subgraph& g);
----
The type for the iterators returned by `out_edges`. (Required by
xref:concepts/IncidenceGraph.adoc[IncidenceGraph].)
Add an existing global vertex to this subgraph. The vertex must already exist in
the parent.
'''''
'''
[source,cpp]
----
graph_traits<subgraph>::in_edge_iterator
std::pair<edge_descriptor, bool>
add_edge(vertex_descriptor u, vertex_descriptor v, subgraph& g);
----
The `in_edge_iterator` is the iterator type returned by the
`in_edges` function. (Required by
xref:concepts/BidirectionalGraph.adoc[BidirectionalGraph].)
Add an edge between local vertices `u` and `v`. The edge is also added to all
ancestor subgraphs.
'''''
'''
[source,cpp]
----
graph_traits<subgraph>::adjacency_iterator
void remove_edge(vertex_descriptor u, vertex_descriptor v, subgraph& g);
void remove_edge(edge_descriptor e, subgraph& g);
----
The type for the iterators returned by `adjacent_vertices`.
(Required by xref:concepts/AdjacencyGraph.adoc[AdjacencyGraph].)
Remove an edge from the subgraph.
'''''
=== Property Map Access
Property maps operate on local descriptors. Changes to properties through a
subgraph are visible from all other subgraphs and the root, because all
subgraphs share the same underlying property storage.
[source,cpp]
----
graph_traits<subgraph>::directed_category
----
Provides information about whether the graph is directed
(`directed_tag`) or undirected (`undirected_tag`). (Required by
xref:concepts/Graph.adoc[Graph].)
'''''
[source,cpp]
----
graph_traits<subgraph>::edge_parallel_category
----
This describes whether the graph class allows the insertion of parallel
edges (edges with the same source and target), which depends on the
underlying `Graph` class. The two tags are
`allow_parallel_edge_tag` and
`disallow_parallel_edge_tag`. (Required by
xref:concepts/Graph.adoc[Graph].)
'''''
[source,cpp]
----
graph_traits<subgraph>::vertices_size_type
----
The type used for dealing with the number of vertices in the graph.
(Required by xref:concepts/VertexListGraph.adoc[VertexListGraph].)
'''''
[source,cpp]
----
graph_traits<subgraph>::edges_size_type
----
The type used for dealing with the number of edges in the graph.
(Required by xref:concepts/EdgeListGraph.adoc[EdgeListGraph].)
'''''
[source,cpp]
----
graph_traits<subgraph>::degree_size_type
----
The type used for dealing with the number of out-edges of a vertex.
(Required by xref:concepts/IncidenceGraph.adoc[IncidenceGraph].)
'''''
[source,cpp]
----
template <typename PropertyTag>
property_map<subgraph, PropertyTag>::type
property_map<subgraph, PropertyTag>::const_type
get(PropertyTag, subgraph& g);
----
The map type for vertex or edge properties in the graph. The specific
property is specified by the `PropertyTag` template argument, and must
match one of the properties specified in the `VertexProperty` or
`EdgeProperty` for the graph. (Required by
xref:concepts/PropertyGraph.adoc[PropertyGraph].)
'''''
....
subgraph::children_iterator
....
The iterator type for accessing the children subgraphs of the graph.
==== Member Functions
'''''
....
subgraph(vertices_size_type n, const GraphProperty& p = GraphProperty())
....
Creates the root graph object with `n` vertices and zero edges.
'''''
....
subgraph<Graph>& create_subgraph();
....
Creates an empty subgraph object whose parent is _this_ graph.
'''''
For bundled properties, use the `local()` and `global()` wrappers to
disambiguate:
[source,cpp]
----
template <typename VertexIterator>
subgraph<Graph>&
create_subgraph(VertexIterator first, VertexIterator last)
auto lvm = get(local(&Node::value), sg); // local subgraph property
auto gvm = get(global(&Node::value), sg); // root graph property
----
Creates a subgraph object with the specified vertex set. The edges of
the subgraph are induced by the vertex set. That is, every edge in the
parent graph (which is _this_ graph) that connects two vertices in the
subgraph will be added to the subgraph.
== Associated Types
'''''
[cols="1,3",options="header"]
|===
| Type | Description
[source,cpp]
----
| `vertex_descriptor`
| Local descriptor within this subgraph.
vertex_descriptor local_to_global(vertex_descriptor u_local) const
----
| `edge_descriptor`
| Local descriptor within this subgraph.
Converts a local vertex descriptor to the corresponding global vertex
descriptor.
| `children_iterator`
| Iterator for accessing child subgraphs.
'''''
[source,cpp]
----
vertex_descriptor global_to_local(vertex_descriptor u_global) const
----
Converts a global vertex descriptor to the corresponding local vertex
descriptor.
'''''
[source,cpp]
----
edge_descriptor local_to_global(edge_descriptor e_local) const
----
Converts a local edge descriptor to the corresponding global edge
descriptor.
'''''
[source,cpp]
----
edge_descriptor global_to_local(edge_descriptor u_global) const
----
Converts a global edge descriptor to the corresponding local edge
descriptor.
'''''
[source,cpp]
----
std::pair<vertex_descriptor, bool> find_vertex(vertex_descriptor u_global) const
----
If vertex _u_ is in this subgraph, the function returns the local vertex
descriptor that corresponds to the global vertex descriptor
`u_global` as the first part of the pair and `true` for the second
part of the pair. If vertex _u_ is not in the subgraph then this
function returns false in the second part of the pair.
'''''
....
subgraph& root()
....
Returns the root graph of the subgraph tree.
'''''
....
bool is_root() const
....
Return `true` if the graph is the root of the subgraph tree, and returns
`false` otherwise.
'''''
....
subgraph& parent()
....
Returns the parent graph.
'''''
[source,cpp]
----
std::pair<children_iterator, children_iterator> children() const
----
Return an iterator pair for accessing the children subgraphs.
==== Nonmember Functions
The functionality of `subgraph` depends on the `Graph` type. For
example, if `Graph` in a
xref:concepts/BidirectionalGraph.adoc[BidirectionalGraph] and supports
`in_edges`, then so does `subgraph`. Here we list all the functions
that `subgraph` could possibly support given a `Graph` type that is a
model of xref:concepts/VertexListGraph.adoc[VertexListGraph],
xref:concepts/EdgeListGraph.adoc[EdgeListGraph] and
xref:concepts/BidirectionalGraph.adoc[BidirectionalGraph]. If the `Graph` type
that you use with `subgraph` does not model these concepts and supports
fewer functions, then the `subgraph` will also support fewer functions
and some of the functions listed below will not be implemented.
'''''
[source,cpp]
----
std::pair<vertex_iterator, vertex_iterator>
vertices(const subgraph& g)
----
Returns an iterator range providing access to the vertex set of subgraph
_g_. (Required by xref:concepts/VertexListGraph.adoc[VertexListGraph].)
'''''
[source,cpp]
----
std::pair<edge_iterator, edge_iterator>
edges(const subgraph& g)
----
Returns an iterator range providing access to the edge set of subgraph
_g_. (Required by xref:concepts/EdgeListGraph.adoc[EdgeListGraph].)
'''''
[source,cpp]
----
std::pair<adjacency_iterator, adjacency_iterator>
adjacent_vertices(vertex_descriptor u_local, const subgraph& g)
----
Returns an iterator range providing access to the vertices adjacent to
vertex _u_ in subgraph _g_. (Required by
xref:concepts/AdjacencyGraph.adoc[AdjacencyGraph].)
'''''
[source,cpp]
----
std::pair<out_edge_iterator, out_edge_iterator>
out_edges(vertex_descriptor u_local, const subgraph& g)
----
Returns an iterator range providing access to the out-edges of vertex
_u_ in subgraph _g_. If the graph is undirected, this iterator range
provides access to all edge incident on vertex _u_. (Required by
xref:concepts/IncidenceGraph.adoc[IncidenceGraph].)
'''''
[source,cpp]
----
std::pair<in_edge_iterator, in_edge_iterator>
in_edges(vertex_descriptor v_local, const subgraph& g)
----
Returns an iterator range providing access to the in-edges of vertex _v_
in subgraph _g_. (Required by
xref:concepts/BidirectionalGraph.adoc[BidirectionalGraph].)
'''''
[source,cpp]
----
vertex_descriptor
source(edge_descriptor e_local, const subgraph& g)
----
Returns the source vertex of edge _e_ in subgraph _g_. (Required by
xref:concepts/IncidenceGraph.adoc[IncidenceGraph].)
'''''
[source,cpp]
----
vertex_descriptor
target(edge_descriptor e_local, const subgraph& g)
----
Returns the target vertex of edge _e_ in subgraph _g_. (Required by
xref:concepts/IncidenceGraph.adoc[IncidenceGraph].)
'''''
[source,cpp]
----
degree_size_type
out_degree(vertex_descriptor u_local, const subgraph& g)
----
Returns the number of edges leaving vertex _u_ in subgraph _g_.
(Required by xref:concepts/IncidenceGraph.adoc[IncidenceGraph].)
'''''
[source,cpp]
----
degree_size_type in_degree(vertex_descriptor u_local, const subgraph& g)
----
Returns the number of edges entering vertex _u_ in subgraph _g_.
(Required by xref:concepts/BidirectionalGraph.adoc[BidirectionalGraph].)
'''''
[source,cpp]
----
vertices_size_type num_vertices(const subgraph& g)
----
Returns the number of vertices in the subgraph _g_. (Required by
xref:concepts/VertexListGraph.adoc[VertexListGraph].)
'''''
[source,cpp]
----
edges_size_type num_edges(const subgraph& g)
----
Returns the number of edges in the subgraph _g_. (Required by
xref:concepts/EdgeListGraph.adoc[EdgeListGraph].)
'''''
[source,cpp]
----
vertex_descriptor vertex(vertices_size_type n, const subgraph& g)
----
Returns the __n__th vertex in the subgraph's vertex list.
'''''
[source,cpp]
----
std::pair<edge_descriptor, bool>
edge(vertex_descriptor u_local, vertex_descriptor v_local, const subgraph& g)
----
Returns the edge connecting vertex _u_ to vertex _v_ in subgraph _g_.
(Required by xref:concepts/AdjacencyMatrix.adoc[AdjacencyMatrix].)
'''''
[source,cpp]
----
std::pair<edge_descriptor, bool>
add_edge(vertex_descriptor u_local, vertex_descriptor v_local, subgraph& g)
----
Adds edge _(u,v)_ to the subgraph _g_ and to all of the subgraph's
ancestors in the subgraph tree. This function returns the edge
descriptor for the new edge. If the edge is already in the graph then a
duplicate will not be added and the Boolean flag will be false.
(Required by xref:concepts/EdgeMutableGraph.adoc[EdgeMutableGraph].)
'''''
[source,cpp]
----
std::pair<edge_descriptor, bool>
add_edge(vertex_descriptor u_local, vertex_descriptor v_local,
const EdgeProperty& p, subgraph& g)
----
Adds edge _(u,v)_ to the graph and attaches `p` as the value of the
edge's internal property storage. Also see the previous `add_edge`
member function for more details.
'''''
[source,cpp]
----
void remove_edge(vertex_descriptor u_local, vertex_descriptor v_local,
subgraph& g)
----
Removes the edge _(u,v)_ from the subgraph and from all of the ancestors
of `g` in the subgraph tree. (Required by
xref:concepts/EdgeMutableGraph.adoc[EdgeMutableGraph].)
'''''
[source,cpp]
----
void remove_edge(edge_descriptor e_local, subgraph& g)
----
Removes the edge `e` from the subgraph and from all of the ancestors of
`g` in the subgraph tree. (Required by
xref:concepts/EdgeMutableGraph.adoc[EdgeMutableGraph].)
'''''
....
vertex_descriptor
add_vertex(subgraph& g)
....
Adds a vertex to the subgraph and returns the vertex descriptor for the
new vertex. The vertex is also added to all ancestors of `g` in the
subgraph tree to maintain the subgraph property. (Required by
xref:concepts/VertexMutableGraph.adoc[VertexMutableGraph].)
'''''
....
vertex_descriptor
add_vertex(vertex_descriptor u_global, subgraph& g)
....
Adds the vertex _u_ from the root graph to the subgraph `g`. (Required
by xref:concepts/VertexMutableGraph.adoc[VertexMutableGraph].)
'''''
[source,cpp]
----
template <class PropertyTag>
property_map<subgraph, PropertyTag>::type
get(PropertyTag, subgraph& g)
template <class PropertyTag>
property_map<subgraph, PropertyTag>::const_type
get(PropertyTag, const subgraph& g)
----
Returns the property map object for the vertex or edge property
specified by `PropertyTag`. The `PropertyTag` must match one of the
properties specified in the graph's `PropertyTag` template argument.
Vertex and edge properties are shared by all subgraphs, so changes to a
property through a local vertex descriptor for one subgraph will change
the property for the global vertex descriptor, and therefore for all
other subgraphs. However, the key type for a subgraph's property map is
a subgraph-local vertex or edge descriptor. (Required by
xref:concepts/PropertyGraph.adoc[PropertyGraph].)
'''''
[source,cpp]
----
template <class PropertyTag, class Key>
typename property_traits<
typename property_map<subgraph, PropertyTag>::const_type
>::value_type
get(PropertyTag, const subgraph& g, Key k_local)
----
This returns the property value for the key `k_local`, which is
either a local vertex or local edge descriptor. See the above `get`
function for more information about the property maps. (Required by
xref:concepts/PropertyGraph.adoc[PropertyGraph].)
'''''
[source,cpp]
----
template <class PropertyTag, class Key, class Value>
void
put(PropertyTag, const subgraph& g, Key k_local, const Value& value)
----
This sets the property value for the key `k_local` to `value`.
`k_local` is either a local vertex or local edge descriptor. `Value`
must be convertible to
`typename property_traits<property_map<adjacency_matrix, PropertyTag>::type>::value_type`.
(Required by xref:concepts/PropertyGraph.adoc[PropertyGraph].)
'''''
[source,cpp]
----
template <class GraphProperties, class GraphPropertyTag>
typename property_value<GraphProperties, GraphPropertyTag>::type&
get_property(subgraph& g, GraphPropertyTag);
----
Return the property specified by `GraphPropertyTag` that is attached to
the subgraph object `g`. The `property_value` traits class is
defined in `boost/pending/property.hpp`.
'''''
[source,cpp]
----
template <class GraphProperties, class GraphPropertyTag>
const typename property_value<GraphProperties, GraphPropertyTag>::type&
get_property(const subgraph& g, GraphPropertyTag);
----
Return the property specified by `GraphPropertyTag` that is attached to
the subgraph object `g`. The `property_value` traits class is
defined in `boost/pending/property.hpp`.
'''''
=== Notes
The subgraph template requires the underlying graph type to supply
vertex and edge index properties. However, there is no default
constructor of any adjacency list that satisfies both of these
requirements. This is especially true of graphs using
xref:property_maps/bundled.adoc[bundled properties], or any adjacency list whose
vertex set is selected by anything other that `vecS`. However, this
problem can be overcome by embedding your bundled (or otherwise)
properties into a `property` that contains an appropriate index. For
example:
[source,cpp]
----
struct my_vertex { ... };
typedef property<vertex_index_t, std::size_t, my_vertex> vertex_prop;
struct my_edge { ... };
typedef property<edge_index_t, std::size_t, my_edge> edge_prop;
typedef adjacency_list<vecS, listS, undirectedS, vertex_prop, edge_prop> Graph;
typedef subgraph<Graph> Subgraph;
----
| All other types
| Same as the underlying `Graph` type.
|===