graph/doc/python.html
Douglas Gregor 34bc3a8786 doc/*: Document Python bindings
src/python/basic_graph.cpp src/python/basic_graph.hpp:
  - Add ability to record the names of vertices input via the adjacency list
    reader.

example/python/breadth_first_search.py: Building a better example


[SVN r28350]
2005-04-20 23:45:55 +00:00

661 lines
26 KiB
HTML

<html>
<head>
<title>Boost Graph Library: Python Bindings (Experimental)</title>
<script language="JavaScript" type="text/JavaScript">
<!--
function address(host, user) {
var atchar = '@';
var thingy = user+atchar+host;
thingy = '<a hre' + 'f=' + "mai" + "lto:" + thingy + '>' + user+atchar+host + '</a>';
document.write(thingy);
}
//-->
</script>
</head>
<body BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<img SRC="../../../boost.png"
ALT="C++ Boost" width="277" height="86">
<h1><img src="figs/python.gif" alt="(Python)"/>Boost Graph Library: Python Bindings (<b>Experimental</b>)</h1>
<p>The Boost Graph Library offers a wealth of graph algorithms and
data types for C++. These algorithms are flexible and efficient,
but the mechanisms employed to achieve this goal can result in
long compile times that slow the development cycle.</p>
<p>The Python bindings are build using the <a
href="../../python/doc">Boost.Python</a> library. The bindings are
meant to strike a balance of usability, flexibility, and
efficiency, making it possible to rapidly develop useful systems
using the BGL in Python.</p>
<ul>
<li><a href="#caveats">Caveats and Warnings</a></li>
<li><a href="#building">Building the Python Bindings</a></li>
<li><a href="#Goals">Goals</a></li>
<li><a href="#documentation">Documentation style</a>
<ul>
<li><a href="#graph_types">Graph types</a>
<li><a href="#types">Types</a></li>
<li><a href="#constructors">Constructors</a></li>
<li><a href="#general">General operations</a></li>
<li><a href="#vertex_list_graph">Vertex List Graph
operations</a></li>
<li><a href="#edge_list_graph">Edge List Graph
operations</a></li>
<li><a href="#mutable_graph">Mutable Graph
operations</a></li>
<li><a href="#incidence_graph">Incidence Graph
operations</a></li>
<li><a href="#vertex_property_maps">Vertex Property
Maps</a></li>
<li><a href="#edge_property_maps">Edge Property
Maps</a></li>
<li><a href="#input_output">Input/Output operations</a></li>
</li>
<li><a href="#algorithms">Algorithms</a></li>
<li><a href="#property_maps">Property Maps</a></li>
</ul>
</li>
<li><a href="#vis">A simple visualization tool</a></li>
<li><a href="#rfc">Request for comments</a></li>
</ul>
<h2><a name="caveats">Caveats and Warnings</a></h2>
<p>The Python bindings for the Graph library are experimental at
this time. The bindings may not work (but they probably do) and we
will not attempt to provide backward compatibility if the
interfaces change. If you have any ideas </p>
<h2><a name="building">Building the Python Bindings</a></h2>
<p>To build the Python bindings, change to
the <tt>libs/graph/build/python</tt> subdirectory of Boost and
then follow the <a
href="../../../more/getting_started.html#Build_Install">Boost
Build Instructions</a> to build the Python extension module. The
end result will be a dynamic library (DLL, .so, etc.) that can be
loaded into Python via "<tt>import bgl</tt>". <b>Note</b>: For
this build to succeed, the graph library must work flawlessly on
the compile, <i>including the new GraphViz parser</i>, which tends
to break many popular compilers. For instance, recent versions of
GCC are okay but Visual C++ 7.1 will crash. We're working to
resolve the situation.</p>
<h2><a name="goals">Goals</a></h2>
<p>The goal of the BGL-Python bindings is to create a set of
bindings for the majority of the BGL in Python that:
<ul>
<li>"Feel" like the BGL, but with Python syntax.</li>
<li>Allow rapid prototyping of algorithms for the BGL.</li>
<li>Allow easy porting from the BGL in Python to the BGL in
C++.</li>
<li>Permit the use of the BGL in applications for which C++ is
not particularly well suited.</li>
<li>Strike a balance between simplicity, usability, and
efficiency.</li>
</ul>
<p>Note that one goal we did not list is that the Python syntax be
perfect for Python. For instance, one might implement a graph
library in Python very differently from the way the BGL is
implemented in C++, and the Python version may be syntactically
superior. Nonetheless, having a strong syntactic correlation
between the BGL in C++ and the BGL in Python is important for this
project.</p>
<h2><a name="example1">A First Example</a></h2>
<p>Our <a
href="../example/python/biconnected_components.py">first
example</a> illustrates the use of BGL graphs, graph
algorithms, and property maps from Python. The initial
step is to load the BGL-Python bindings:</p>
<pre>
from bgl import *
</pre>
<p>Next, we load a GraphViz file containing the description of a
sample graph. The <tt>Graph</tt> type is an undirected
graph; <tt>file_kind</tt> is an enumerator with only two
potential values: <tt>adjlist</tt>, for an adjacency-list
representation, or <tt>graphviz</tt>, for a GraphViz file.</p>
<pre>
g = Graph("biconnected_components.dot", file_kind.graphviz)
</pre>
<p>Assuming no exceptions have been thrown, we will have an
undirected graph loaded. We can immediately
call <tt>biconnected_components</tt> to compute the biconnected
components within the graph:</p>
<pre>
art_points = biconnected_components(g, g.get_edge_int_map("label"))
</pre>
<p>There are several interesting parts of the preceeding line. We
call the <a
href="biconnected_components.html"><tt>biconnected_components</tt></a>
algorithm with two parameters. The first is just the graph
itself. The second parameter is a property map from edges to an
integer value, which will be stored in the graph under the name
"label". Finally, the return value
of <tt>biconnected_components</tt> is a Python list containing the
articulation points of the graph.</p>
<p>Other kinds of property maps are available. In this case, we
create two property maps attaching strings to the vertices of the
graph. We then iterate over all vertices of the graph to set
default values for each vertex property.</p>
<pre>
v_color = g.get_vertex_string_map("fillcolor")
v_style = g.get_vertex_string_map("style")
for v in g.vertices:
v_color[v] = "white"
v_style[v] = "filled"
</pre>
<p>Lastly, we mark all of the articulation points red and write
out the result in GraphViz format.</p>
<pre>
for v in art_points:
v_color[v] = "red"
g.write_graphviz("biconnected_components_out.dot")
</pre>
<h2><a name="documentation">Documentation style</a></h2> <p>The
Python bindings for the Boost Graph Library retain essentially the
same syntax. Because of this, there is no separate documentation
for the BGL in Python: each BGL component (algorithms, data
structures, etc.) available in Python will be marked with the
Python symbol <img src="figs/python_ico.gif"
alt="(Python)">. Unless an explicit <b>Python</b> section (or
field) is present, the Python versions have precisely the same
semantics as the C++ version.</p>
<h3><a name="graph_types"/>Graph types</h3>
<p>The C++ Boost Graph Library provides several graph types that
permit the generation of a huge number of specific graph types. In
Python, the BGL only exposes two general-purpose graph
types: <tt>Graph</tt> and <tt>Digraph</tt>, for undirected and
directed graphs, respectively. Both graph types are part of
the <tt>bgl</tt> extension module for Python. These graph types
are one-size-fits-most, offering stable vertex and edge
descriptors and a core set of operations from the <a
href="adjacency_list.html"><tt>adjacency_list</tt></a> class
template. The following sections briefly describe the operations
that can be performed on both the <tt>Graph</tt>
and <tt>Digraph</tt> Python graph types, although the
documentation uses <tt>Graph</tt> in the description.</p>
<p>Unlike the C++ graph types in the BGL, the Python graph types
use object-oriented syntax. For
instance, <tt>num_vertices(g)</tt> retrieves the number of
vertices in graph <tt>g</tt> in C++, whereas the Python
equivalent is <tt>g.num_vertices()</tt>. All of the graph
operations described in the following text are methods of the
graph type.</p>
<h4><a name="types"/>Types</h4>
<pre>Graph.Vertex</pre>
<blockquote>
The type of a vertex descriptor in the graph <tt>Graph</tt> that will
be used to refer to vertices in the graph. Note that there may be
several Python objects that refer to the same vertex, which can be
compared with <tt>==</tt> and <tt>!=</tt> correctly.<br>
<b>Bug</b>: Vertex descriptors do not work properly when used in a
Python <tt>dict</tt>.
</blockquote>
<pre>Graph.Edge</pre>
<blockquote>
The type of a edge descriptor in the graph <tt>Graph</tt> that will
be used to refer to edges in the graph. Note that there may be
several Python objects that refer to the same edge, which can be
compared with <tt>==</tt> and <tt>!=</tt> correctly.<br>
<b>Bug</b>: Edge descriptors do not work properly when used in a
Python <tt>dict</tt>.
</blockquote>
<h4><a name="constructors"/>Constructors</h4>
<pre>Graph()</pre>
<blockquote>
Constructs an empty graph.
</blockquote>
<pre>Graph(edges, name_map = "")</pre>
<blockquote>
Constructs a graph from a list of edges. <tt>edges</tt> should be a
Python sequence, the elements of which should be 2-tuples containing
the source and target of the edge. The sources and targets can be of
any type that has a less-than operator defined, e.g., strings or
integers. If a non-empty string is provided for <tt>name_map</tt>,
a <tt>vertex_object_map</tt> will be created that maps from the
vertices that are created to the name used in the list of edges.
</blockquote>
<pre>Graph(filename, kind)</pre>
<blockquote>
Constructs a graph from an external file using one of the Boost Graph
Library's graph parsers. <tt>filename</tt> is a string containing the
file name. <tt>kind</tt> is an value of type <tt>bgl.file_kind</tt>,
which has one of the following values:
<ul>
<li><tt>bgl.file_kind.adjlist</tt>: Reads an adjacency-list
representation into the graph. In the file, each line represents a
single edge. On that line will be the source and target of the edge,
separated by one or more spaces.</li>
<li><tt>bgl.file_kind.graphviz</tt>: Reads a <a
href="http://www.graphviz.org">GraphViz</a> DOT file into the
graph. The DOT file must represent a graph that is directed (for
a <tt>Digraph</tt>) or undirected (for a <tt>Graph</tt>). See <a
href="#read_graphviz"><tt>read_graphviz</tt></a> for additional details.</li>
</ul>
</blockquote>
<pre>Graph(generator, seed)</pre>
<blockquote>
Constructs a graph using the random generator <tt>generator</tt> and
random seed value <tt>seed</tt> (an integer). The <tt>generator</tt>
parameter may be one of three things:
<ul>
<li><tt>bgl.<a href="erdos_renyi_generator.html">ErdosRenyi</a>(n, p)</tt>: Generates a graph
with <tt>n</tt> vertices and a probability <i>0 &lt;= <tt>p</tt> &gt;=
1</i> of having an edge between any two vertices <tt>u</tt>
and <tt>v</tt>.</li>
<li><tt>bgl.<a href="small_world_generator.html">SmallWorld</a>(n, k, p)</tt>: Generates a small-world graph
with <tt>n</tt> vertices, each of which is connected to
its <tt>k</tt> nearest neighbors (assuming one places the vertices
in a circle). With probability <tt>p</tt>, each edge in the graph is
randomly rewired.</li>
<li><tt>bgl.<a href="plod_generator.html">PowerLawOutDegree</a>(n, alpha, beta)</tt>: Generates a
scale-free graph using the Power Law Out Degree model
with <tt>n</tt> vertices. Each vertex has degree <i>beta *
x<sup>-alpha</sup></i>, where <i>x</i> is a random value between 0
and <i>n-1</i>. The value of <i>beta</i> controls the y-intercept of the
curve, so that increasing <i>beta</i> increases the average degree of
vertices. The value of <i>alpha</i> controls how steeply the curve drops
off, with larger values indicating a steeper curve. The web graph,
for instance, has <i>alpha ~ 2.72</i>.</li>
</ul>
</blockquote>
<h4><a name="general"/>General operations</h4>
<pre>is_directed()</pre>
<blockquote>
Returns <tt>True</tt> if the edges in the graph are
directed, <tt>False</tt> otherwise.
</blockquote>
<h4><a name="vertex_list_graph"/>Vertex List Graph operations</h4>
<pre>num_vertices()</pre>
<blockquote>
Returns the number of vertices in the graph.
</blockquote>
<pre>vertices</pre>
<blockquote>
Returns a sequence containing all vertices in the graph. This
sequence has a Python iterator, such that the following Python code
prints the names of all vertices in graph <tt>g</tt>:
<pre>
for v in g.vertices:
print name[v]
</pre>
</blockquote>
<h4><a name="edge_list_graph"/>Edge List Graph operations</h4>
<pre>num_edges()</pre>
<blockquote>
Returns the number of edges in the graph.
</blockquote>
<pre>edges</pre>
<blockquote>
Returns a sequence containing all edges in the graph. This
sequence has a Python iterator, such that the following Python code
prints the weights of all edges in graph <tt>g</tt>:
<pre>
for e in g.edges:
print weight[e]
</pre>
</blockquote>
<h4><a name="mutable_graph"/>Mutable Graph operations</h4>
<pre>add_vertex()</pre>
<blockquote>
Adds a new vertex to the graph and returns the descriptor of the new
vertex. Default values for all property maps attached to the graph
will be provided for this vertex.
</blockquote>
<pre>clear_vertex(v)</pre>
<blockquote>
Removes all of the incoming and outgoing edges to the
vertex <tt>v</tt>. The properties for each of the edges removed will
be removed from the property maps attached to the graph.
</blockquote>
<pre>remove_vertex(v)</pre>
<blockquote>
Removes the vertex <tt>v</tt> from the graph. Before invoking this
function, there must be no edges attached to this vertex (either
incoming or outgoing), which can be ensured by a call
to <tt>clear_vertex(v)</tt>. Properties associated with this vertex
will be removed from the property maps attached to the graph. Once
this call completes, the vertex descriptor <tt>v</tt> is considered
invalid and cannot be used again.
</blockquote>
<pre>add_edge(u, v)</pre>
<blockquote>
Add an edge <i>(u, v)</i> to the graph and returns the descriptor for
the new edge. Default values for all property maps attached to the graph
will be provided for this edge.
</blockquote>
<pre>remove_edge(e)</pre>
<blockquote>
Remove the edge <tt>e</tt> from the graph. The properties
for <tt>e</tt> will be be removed from the property maps attached to
the graph. Once this operation completes, the edge
descriptor <tt>e</tt> is considered invalid and cannot be used again.
</blockquote>
<h4><a name="incidence_graph"/>Incidence Graph operations</h4>
<pre>source(e)</pre>
<blockquote>
Returns the source of the edge <tt>e</tt>.
</blockquote>
<pre>target(e)</pre>
<blockquote>
Returns the target of the edge <tt>e</tt>.
</blockquote>
<pre>out_edges(u)</pre>
<blockquote>
Returns a sequence containing all edges outgoing
from <tt>u</tt>. This sequence has an iterator, so that the following
Python code prints the weights of all edges outgoing from
vertex <tt>u</tt> in graph <tt>g</tt>:
<pre>
for e in g.out_edges(u):
print weight[e]
</pre>
For each edge <tt>e</tt>, <tt>g.source(e) == u</tt>.
</blockquote>
<pre>out_degree(u)</pre>
<blockquote>
Returns the number of edges outgoing from vertex <tt>u</tt>.
</blockquote>
<pre>in_edges(v)</pre>
<blockquote>
Returns a sequence containing all edges incoming
to <tt>v</tt>. This sequence has an iterator, so that the following
Python code prints the weights of all edges incoming to
vertex <tt>v</tt> in graph <tt>g</tt>:
<pre>
for e in g.in_edges(u):
print weight[e]
</pre>
For each edge <tt>e</tt>, <tt>g.target(e) == v</tt>. For undirected
graphs, the <tt>in_edges</tt> will be equivalent to
the <tt>out_edges</tt>, except that the source and target will be
swapped.
</blockquote>
<pre>in_degree(u)</pre>
<blockquote>
Returns the number of edges incoming to vertex <tt>u</tt>. For
undirected graphs, <tt>g.in_degree(u) == g.in_degree(v)</tt>.
</blockquote>
<pre>adjacent_vertices(u)</pre>
<blockquote>
Returns a sequence containing all vertices adjacent to
<tt>u</tt>. This sequence has an iterator, so that the following
Python code prints the names of all vertices adjacent to
vertex <tt>u</tt> in graph <tt>g</tt>:
<pre>
for v in g.adjacent_vertices(u):
print name[v]
</pre>
The sequence of adjacent vertices for vertex <tt>u</tt> corresponds to
the targets of the outgoing edges of <tt>u</tt>.
</blockquote>
<h4><a name="vertex_property_maps"/>Vertex property maps</h4>
<pre>has_vertex_map(name)</pre>
<blockquote>
Returns <tt>True</tt> if the graph contains a vertex property map
with the name <tt>name</tt>.
</blockquote>
<pre>get_vertex_index_map()</pre>
<blockquote>
Returns a property map that maps vertex descriptors to indices in the
range <i>[0, <tt>g.num_vertices()</tt>)</i>.
</blockquote>
<pre>get_vertex_color_map()</pre>
<blockquote>
Returns a property map that maps vertex descriptors to values of the
Python type <tt>bgl.Color</tt>, which is an enumeration containing
the values <tt>white</tt>, <tt>gray</tt>, and <tt>black</tt>. If a
property map of this name already exists, its values are converted to
colors. Otherwise, a new map is created.
</blockquote>
<pre>get_vertex_double_map()</pre>
<blockquote>
Returns a property map that maps vertex descriptors to <tt>double</tt>
values. If a property map of this name already exists, its values are
converted to <tt>double</tt>s. Otherwise, a new map is created.
</blockquote>
<pre>get_vertex_int_map()</pre>
<blockquote>
Returns a property map that maps vertex descriptors to <tt>int</tt>
values. If a property map of this name already exists, its values are
converted to <tt>int</tt>s. Otherwise, a new map is created.
</blockquote>
<pre>get_vertex_string_map()</pre>
<blockquote>
Returns a property map that maps vertex descriptors to <tt>string</tt>
values. If a property map of this name already exists, its values are
converted to <tt>string</tt>s. Otherwise, a new map is created.
</blockquote>
<pre>get_vertex_object_map()</pre>
<blockquote>
Returns a property map that maps vertex descriptors to
Python <tt>object</tt>s. If a property map of this name already
exists, its values are converted to <tt>object</tt>s. Otherwise, a new
map is created.
</blockquote>
<pre>get_vertex_point_map()</pre>
<blockquote>
Returns a property map that maps vertex descriptors to values of the
Python type <tt>bgl.Point2D</tt>, which is an class
containing <tt>x</tt> and <tt>y</tt> attributes
storing <tt>double</tt> values. If a property map of this name already
exists, its values are converted to 2-D points. Otherwise, a new map
is created.<br>
<b>Bug</b>: Writing just the <tt>x</tt> or <tt>y</tt> attributes of
a <tt>bgl.Point2D</tt> object does not work at this time. However,
you can create a new <tt>bgl.Point2D</tt> object and assign it into
the property map.
</blockquote>
<h4><a name="edge_property_maps"/>Edge property maps</h4>
<pre>has_edge_map(name)</pre>
<blockquote>
Returns <tt>True</tt> if the graph contains a edge property map
with the name <tt>name</tt>.
</blockquote>
<pre>get_edge_index_map()</pre>
<blockquote>
Returns a property map that maps edge descriptors to indices in the
range <i>[0, <tt>g.num_edges()</tt>)</i>.
</blockquote>
<pre>get_edge_color_map()</pre>
<blockquote>
Returns a property map that maps edge descriptors to values of the
Python type <tt>bgl.Color</tt>, which is an enumeration containing
the values <tt>white</tt>, <tt>gray</tt>, and <tt>black</tt>. If a
property map of this name already exists, its values are converted to
colors. Otherwise, a new map is created.
</blockquote>
<pre>get_edge_double_map()</pre>
<blockquote>
Returns a property map that maps edge descriptors to <tt>double</tt>
values. If a property map of this name already exists, its values are
converted to <tt>double</tt>s. Otherwise, a new map is created.
</blockquote>
<pre>get_edge_int_map()</pre>
<blockquote>
Returns a property map that maps edge descriptors to <tt>int</tt>
values. If a property map of this name already exists, its values are
converted to <tt>int</tt>s. Otherwise, a new map is created.
</blockquote>
<pre>get_edge_string_map()</pre>
<blockquote>
Returns a property map that maps edge descriptors to <tt>string</tt>
values. If a property map of this name already exists, its values are
converted to <tt>string</tt>s. Otherwise, a new map is created.
</blockquote>
<pre>get_edge_object_map()</pre>
<blockquote>
Returns a property map that maps edge descriptors to
Python <tt>object</tt>s. If a property map of this name already
exists, its values are converted to <tt>object</tt>s. Otherwise, a new
map is created.
</blockquote>
<h4><a name="input_output"/>Input/Output operations</h4>
<a name="read_graphviz"/><pre>read_graphviz(filename, node_id = "node_id")</pre>
<blockquote>
Reads a <a href="http://www.graphviz.org">GraphViz</a> file
named <tt>filename</tt>into the graph, which is assumed to be
empty. The operation will create a <tt>vertex_string_map</tt>
named <tt>node_id</tt> that maps from vertex descriptors to the node
identifiers in the GraphViz file. All vertex and edge attributes
stored in the file will be loaded into <tt>vertex_string_map</tt>
and <tt>edge_string_map</tt> property maps, respectively. An exception
will be thrown if parsing of the GraphViz file fails.
</blockquote>
<pre>write_graphviz(filename, node_id = None)</pre>
<blockquote>
Writes the graph into a file named <tt>filename</tt> in <a
href="http://www.graphviz.org">GraphViz</a> format. All vertex and
edge attributes stored in the graph's property maps will be written to
the file. If <tt>node_id</tt> is provided, the vertex identifiers in
the GraphViz output will correspond with the names provided in the
vertex property map <tt>node_id</tt>. Otherwise, integer indices will
be used to identify nodes in the output file.
</blockquote>
<h3><a name="algorithms"/>Algorithms</h3>
<p>All algorithms available in Python operate only on the Python
graph types supplied by the BGL-Python bindings and are not
generic in the same sense as their C++ counterparts. However,
unless marked otherwise, their parameters are still customizable
from Python. See, for instance, <a
href="breadth_first_search.html"><tt>breadth_first_search</tt></a>,
which can still be provided with a customized queue and visitor
from within Python. </p>
<p>All algorithms are in the <tt>bgl</tt> extension module, at the
top level, and have the same names as in C++.</p>
<p>The parameters of BGL functions exposed to Python have the same
general data types, order, and names as in C++. If the BGL
function takes named parameters, then the names of the parameters
can be used for keyword arguments in Python. For instance:</p>
<pre>
// C++
betweenness_centrality(g, weight_map(weight).centrality_map(centrality));
# Python
bgl.betweenness_centrality(g, weight_map = weight, centrality_map = centrality);
</pre>
<p>Unless otherwise specified, all parameters documented in C++
are available in Python. If there are any differences, the
parameter documentation will contain a <b>Python</b> line
describing those differences. If the default in Python differs
from the C++ default, the parameter documentation will contain
a <b>Python default</b> line. Finally, if the algorithm's
behavior is radically different in Python, the algorithm will
contain a "Python" section. Although not available now, we would
like to rewrite the C++ examples in Python and add a "Python
Example" for each algorithm with inline examples.</p>
<h3><a name="property_maps"/>Property Maps</h3>
<p>Property maps in Python allow the same <tt>[]</tt> operator
syntax as Python dictionaries. For instance, if we have a property
map <tt>rank</tt> mapping vertices to integers, we can increment
the rank of vertex <tt>v</tt> with the following Python code:</p>
<pre>
rank[v] = rank[v] + 1
</pre>
<p>However, unlike Python dictionaries one cannot enumerate the
keys or values in a property map. Instead, you must enumerate the
vertex or edges in the graph to index into the Python property
map. This restriction follows from the C++ formulation of
property maps, which do not allow such iteration.</p>
<h2><a name="vis"/>A simple visualization tool</a></h2>
<p>The program <tt>vis.py</tt>, in the <tt>examples/python</tt>
subdirectory, is a simple Graph visualization tool written in
Python using the BGL bindings. It can load graphs, perform graph
layout, run a few graph algorithms on graphs, etc. At present, it
is not a useful program <i>per se</i> but merely an example of
what can be achieved (quickly!) using the BGL-Python bindings. To
use this program you will need to install <a
href="http://www.wxpython.org/">wxPython</a>.
<h2><a name="rfc"/>Request for comments</a></h2>
<p><b>We want YOU</b> to send it comments, questions, bug reports,
or suggestions for the BGL-Python bindings. They are experimental,
used primarily in-house for rapid prototyping of graph systems. If
you have any ideas, please post them to the <a
href="http://lists.boost.org/mailman/listinfo.cgi/boost-users">Boost-Users</a>
or <a
href="http://lists.boost.org/mailman/listinfo.cgi/boost">Boost
Developers</a> mailing lists, or e-mail me directly at <script
language="Javascript">address("cs.indiana.edu",
"dgregor")</script>.</p>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy; 2005</TD><TD>
<A HREF="../../../people/doug_gregor.html">Doug Gregor</A>, Indiana University (<script language="Javascript">address("cs.indiana.edu", "dgregor")</script>)<br>
<A HREF=http://www.osl.iu.edu/~lums>Andrew Lumsdaine</A>,
Indiana University (<script language="Javascript">address("osl.iu.edu", "lums")</script>)
</TD></TR></TABLE>
</body>
</html>