From 631d35bcc2a13e86a8f751d57181e2eb82a23eb7 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 19 Apr 2005 17:01:07 +0000 Subject: [PATCH] Started documenting Python bindings libs/graph/src/python/basic_graph.cpp, libs/graph/src/python/basic_graph.hpp: - Allow one to build a graph from anything that looks like a Python list or tuple. [SVN r28324] --- doc/BFSVisitor.html | 23 ++++- doc/BellmanFordVisitor.html | 24 ++++- doc/DFSVisitor.html | 24 ++++- doc/DijkstraVisitor.html | 25 ++++- doc/breadth_first_search.html | 36 +++++-- doc/breadth_first_visit.html | 25 +++-- doc/figs/python.gif | Bin 0 -> 344 bytes doc/figs/python_ico.gif | Bin 0 -> 125 bytes doc/python.html | 125 +++++++++++++++++++++++++ doc/table_of_contents.html | 12 +-- example/python/breadth_first_search.py | 14 +++ src/python/basic_graph.cpp | 29 +++++- src/python/basic_graph.hpp | 1 + 13 files changed, 314 insertions(+), 24 deletions(-) create mode 100644 doc/figs/python.gif create mode 100644 doc/figs/python_ico.gif create mode 100644 doc/python.html create mode 100644 example/python/breadth_first_search.py diff --git a/doc/BFSVisitor.html b/doc/BFSVisitor.html index 699555ed..8b17cc8f 100644 --- a/doc/BFSVisitor.html +++ b/doc/BFSVisitor.html @@ -19,7 +19,7 @@
-

BFS Visitor Concept

+

(Python)BFS Visitor Concept

This concept defines the visitor interface for breadth_first_search(). @@ -180,6 +180,27 @@ search tree and all of the adjacent vertices have been discovered
  • bfs_visitor +

    Python

    +To implement a model of the BFSVisitor concept in Python, +create a new class that derives from the BFSVisitor type of +the graph, which will be +named GraphType.BFSVisitor. The events and syntax are +the same as with visitors in C++. Here is an example for the +Python bgl.Graph graph type: + +
    +class count_tree_edges_bfs_visitor(bgl.Graph.BFSVisitor):
    +  def __init__(self, name_map):
    +    bgl.Graph.BFSVisitor.__init__(self)
    +    self.name_map = name_map
    +
    +  def tree_edge(self, e, g):
    +    (u, v) = (g.source(e), g.target(e))
    +    print "Tree edge ",
    +    print self.name_map[u],
    +    print " -> ",
    +    print self.name_map[v]
    +

    See also

    diff --git a/doc/BellmanFordVisitor.html b/doc/BellmanFordVisitor.html index f59c1e5c..58958e87 100644 --- a/doc/BellmanFordVisitor.html +++ b/doc/BellmanFordVisitor.html @@ -19,7 +19,7 @@
    -

    Bellman Ford Visitor Concept

    +

    (Python)Bellman Ford Visitor Concept

    This concept defines the visitor interface for bellman_ford_shortest_paths(). @@ -156,6 +156,28 @@ when there is a negative cycle in the graph.
  • bellman_visitor +

    Python

    + +To implement a model of the BellmanFordVisitor concept in Python, +create a new class that derives from the BellmanFordVisitor type of +the graph, which will be +named GraphType.BellmanFordVisitor. The events and syntax are +the same as with visitors in C++. Here is an example for the +Python bgl.Graph graph type: + +
    +class count_tree_edges_bellman_ford_visitor(bgl.Graph.BellmanFordVisitor):
    +  def __init__(self, name_map):
    +    bgl.Graph.BellmanFordVisitor.__init__(self)
    +    self.name_map = name_map
    +
    +  def edge_relaxed(self, e, g):
    +    (u, v) = (g.source(e), g.target(e))
    +    print "Relaxed edge ",
    +    print self.name_map[u],
    +    print " -> ",
    +    print self.name_map[v]
    +


    diff --git a/doc/DFSVisitor.html b/doc/DFSVisitor.html index 5765ef57..031777db 100644 --- a/doc/DFSVisitor.html +++ b/doc/DFSVisitor.html @@ -19,7 +19,7 @@
    -

    DFS Visitor Concept

    +

    (Python)DFS Visitor Concept

    This concept defines the visitor interface for depth_first_search(). @@ -174,6 +174,28 @@ all the out-edges of u have been examined.
  • dfs_visitor +

    Python

    + +To implement a model of the DFSVisitor concept in Python, +create a new class that derives from the DFSVisitor type of +the graph, which will be +named GraphType.DFSVisitor. The events and syntax are +the same as with visitors in C++. Here is an example for the +Python bgl.Graph graph type: + +
    +class count_tree_edges_dfs_visitor(bgl.Graph.DFSVisitor):
    +  def __init__(self, name_map):
    +    bgl.Graph.DFSVisitor.__init__(self)
    +    self.name_map = name_map
    +
    +  def tree_edge(self, e, g):
    +    (u, v) = (g.source(e), g.target(e))
    +    print "Tree edge ",
    +    print self.name_map[u],
    +    print " -> ",
    +    print self.name_map[v]
    +


    diff --git a/doc/DijkstraVisitor.html b/doc/DijkstraVisitor.html index 4801cb17..994ef140 100644 --- a/doc/DijkstraVisitor.html +++ b/doc/DijkstraVisitor.html @@ -19,7 +19,7 @@
    -

    Dijkstra Visitor Concept

    +

    (Python)Dijkstra Visitor Concept

    This concept defines the visitor interface for dijkstra_shortest_paths() @@ -184,6 +184,29 @@ search tree and all of the adjacent vertices have been discovered
  • dijkstra_visitor +

    Python

    + +To implement a model of the DijkstraVisitor concept in Python, +create a new class that derives from the DijkstraVisitor type of +the graph, which will be +named GraphType.DijkstraVisitor. The events and syntax are +the same as with visitors in C++. Here is an example for the +Python bgl.Graph graph type: + +
    +class count_tree_edges_dijkstra_visitor(bgl.Graph.DijkstraVisitor):
    +  def __init__(self, name_map):
    +    bgl.Graph.DijkstraVisitor.__init__(self)
    +    self.name_map = name_map
    +
    +  def edge_relaxed(self, e, g):
    +    (u, v) = (g.source(e), g.target(e))
    +    print "Relaxed edge ",
    +    print self.name_map[u],
    +    print " -> ",
    +    print self.name_map[v]
    +
    +

    diff --git a/doc/breadth_first_search.html b/doc/breadth_first_search.html index 194a07fa..cbef3c6f 100644 --- a/doc/breadth_first_search.html +++ b/doc/breadth_first_search.html @@ -19,7 +19,7 @@
    -

    +

    (Python) breadth_first_search

    @@ -157,12 +157,16 @@ IN: Graph& g
    A directed or undirected graph. The graph type must be a model of Vertex List Graph - and Incidence Graph. + and Incidence Graph.
    + + Python: The parameter is named graph.
    IN: vertex_descriptor s
    - The source vertex where the search is started. + The source vertex where the search is started.
    + + Python: The parameter is named root_vertex.
    @@ -174,7 +178,11 @@ IN: visitor(BFSVisitor vis) event-points specified by the BFS Visitor concept. The visitor object is passed by value [1].
    Default: - bfs_visitor<null_visitor> + bfs_visitor<null_visitor>
    + + Python: The parameter should be an object that derives from + the BFSVisitor type of the graph. + UTIL/OUT: color_map(ColorMap color) @@ -198,7 +206,10 @@ UTIL/OUT: color_map(ColorMap color) iterator_property_map created from a std::vector of default_color_type of size num_vertices(g) and using the i_map for the index - map. + map.
    + + Python: The color map must be a vertex_color_map for + the graph. IN: vertex_index_map(VertexIndexMap i_map) @@ -212,7 +223,9 @@ IN: vertex_index_map(VertexIndexMap i_map) vertex descriptor type of the graph needs to be usable as the key type of the map.
    - Default: get(vertex_index, g) + Default: get(vertex_index, g)
    + + Python: Unsupported parameter. UTIL: buffer(Buffer& Q) @@ -225,7 +238,11 @@ UTIL: buffer(Buffer& Q) using a priority queue. The type Buffer must be a model of Buffer.
    The value_type of the buffer must be the vertex_descriptor type for the graph.
    - Default: boost::queue + Default: boost::queue
    + + Python: The buffer must derive from the Buffer type for the graph. + @@ -294,6 +311,11 @@ class used has VertexList and EdgeList set to listS.

    +

    Python example

    + +

    TBD... + +

    See Also

    bfs_visitor and diff --git a/doc/breadth_first_visit.html b/doc/breadth_first_visit.html index 37f7625f..481ab38f 100644 --- a/doc/breadth_first_visit.html +++ b/doc/breadth_first_visit.html @@ -19,7 +19,7 @@
    -

    +

    (Python) breadth_first_visit

    @@ -60,12 +60,16 @@ only reaches a small portion of the graph. IN: IncidenceGraph& g
    A directed or undirected graph. The graph type must - be a model of Incidence Graph. + be a model of Incidence Graph.
    + + Python: The parameter is named graph.
    IN: vertex_descriptor s
    - The source vertex where the search is started. + The source vertex where the search is started.
    + + Python: The parameter is named root_vertex.
    @@ -77,7 +81,10 @@ IN: visitor(BFSVisitor vis) event-points specified by the BFS Visitor concept. The visitor object is passed by value [1].
    Default: - bfs_visitor<null_visitor> + bfs_visitor<null_visitor>
    + + Python: The parameter should be an object that derives from + the BFSVisitor type of the graph. UTIL/OUT: color_map(ColorMap color) @@ -88,7 +95,10 @@ UTIL/OUT: color_map(ColorMap color) Property Map and its key type must be the graph's vertex descriptor type and the value type of the color map must model ColorValue.
    - Default: get(vertex_color, g) + Default: get(vertex_color, g)
    + + Python: The color map must be a vertex_color_map for + the graph. UTIL: buffer(Buffer& Q) @@ -100,7 +110,10 @@ UTIL: buffer(Buffer& Q) For example Dijkstra's algorithm can be implemented using a priority queue. The type Buffer must be a model of Buffer.
    - Default: boost::queue + Default: boost::queue
    + + Python: The buffer must derive from the Buffer type for the graph. diff --git a/doc/figs/python.gif b/doc/figs/python.gif new file mode 100644 index 0000000000000000000000000000000000000000..51f4ecac0db5dc92a44a585d31ded9f5bde699fc GIT binary patch literal 344 zcmZ?wbhEHbRA5kGXkh?>1_lO(28ISO)c|H4IB?*=ode5GePH;{@c%yp1Bd{z{)0JS zg(&J98X689IPf2&?mrq({K>+|z#z|{1F{KZCj;x%2kL$D3{%uru6x75bC`R6?%G*9 zEN|EB)M=16xVD*9(p_ca4J);HlV@5SB2J5g0`->7ez+udMupDfZ>JuA>B$M%Et+lk zO{}|Hw4x?9&Uv}0MP*&FUVejGK|?`~4nt+XWm9EOZp7YNS&AvSK>WqzF)0b@0xE{HGQx69tgEau$ Cyqtjm literal 0 HcmV?d00001 diff --git a/doc/figs/python_ico.gif b/doc/figs/python_ico.gif new file mode 100644 index 0000000000000000000000000000000000000000..58271edec49353382f935ada2de138a1f5b35d9a GIT binary patch literal 125 zcmZ?wbhEHbkRpTr)(n(XGB|3S*0q@@xZ12U Wv}a*whMKW&_^dmklF}*+4AuY`b0;GJ literal 0 HcmV?d00001 diff --git a/doc/python.html b/doc/python.html new file mode 100644 index 00000000..1a2bce5b --- /dev/null +++ b/doc/python.html @@ -0,0 +1,125 @@ + + + Boost Graph Library: Python Bindings (Experimental) + + + + C++ Boost +

    Boost Graph Library: Python Bindings (Experimental)

    +

    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.

    + +

    The Python bindings are build using the Boost.Python 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.

    + +

    Caveats and Warnings

    +

    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

    + +

    Building the Python Bindings

    +

    To build the Python bindings, change to + the libs/graph/build/python subdirectory of Boost and + then follow the Boost + Build Instructions to build the Python extension module. The + end result will be a dynamic library (DLL, .so, etc.) that can be + loaded into Python via "import bgl". Note: For + this build to succeed, the graph library must work flawlessly on + the compile, including the new GraphViz parser, 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.

    + +

    A First Example

    +

    Our first + example illustrates the use of BGL graphs, graph + algorithms, and property maps from Python. The initial + step is to load the BGL-Python bindings:

    +
    +from bgl import *
    +    
    + +

    Next, we load a GraphViz file containing the description of a + sample graph. The Graph type is an undirected + graph; file_kind is an enumerator with only two + potential values: adjlist, for an adjacency-list + representation, or graphviz, for a GraphViz file.

    + +
    +g = Graph("biconnected_components.dot", file_kind.graphviz)
    +    
    + +

    Assuming no exceptions have been thrown, we will have an + undirected graph loaded. We can immediately + call biconnected_components to compute the biconnected + components within the graph:

    + +
    +art_points = biconnected_components(g, g.get_edge_int_map("label"))
    +    
    + +

    There are several interesting parts of the preceeding line. We + call the biconnected_components + 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 biconnected_components is a Python list containing the + articulation points of the graph.

    + +

    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.

    + +
    +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"
    +    
    + +

    Lastly, we mark all of the articulation points red and write + out the result in GraphViz format.

    + +
    +for v in art_points:
    +  v_color[v] = "red"
    +
    +g.write_graphviz("biconnected_components_out.dot")
    +    
    + +

    Documentation style

    +

    + +


    +

    + +
    Copyright © 2005 + Doug Gregor, Indiana University ()
    + Andrew Lumsdaine, + Indiana University () +
    + + diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 3e8b9178..ddbd2334 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -69,10 +69,10 @@
  • The Property Map Library (technically not part of the graph library, but used a lot here)
  • Visitor Concepts
      -
    1. BFS Visitor -
    2. DFS Visitor -
    3. Dijkstra Visitor -
    4. Bellman Ford Visitor +
    5. (Python)BFS Visitor +
    6. (Python)DFS Visitor +
    7. (Python)Dijkstra Visitor +
    8. (Python)Bellman Ford Visitor
    9. A* Visitor
    10. Event Visitor
    @@ -126,8 +126,8 @@
  • bgl_named_params
  • Core Algorithm Patterns
      -
    1. breadth_first_search -
    2. breadth_first_visit +
    3. (Python)breadth_first_search +
    4. (Python)breadth_first_visit
    5. depth_first_search
    6. depth_first_visit diff --git a/example/python/breadth_first_search.py b/example/python/breadth_first_search.py new file mode 100644 index 00000000..18179ad5 --- /dev/null +++ b/example/python/breadth_first_search.py @@ -0,0 +1,14 @@ +from bgl import * + +class bfs_print_discover_visitor(Graph.BFSVisitor): + def discover_vertex(self, u, g): + print "Discovered vertex ", + print u + +g = Graph((("r", "s"), ("r", "v"), ("s", "w"), ("w", "r"), ("w", "t"), ("w", "x"), ("x", "t"), ("t", "u"), ("x", "y"), ("u", "y"))) + +iter = g.vertices.__iter__() +iter.next() +s = iter.next() +breadth_first_search(g, s, visitor=bfs_print_discover_visitor()) + diff --git a/src/python/basic_graph.cpp b/src/python/basic_graph.cpp index 4079255b..69461105 100644 --- a/src/python/basic_graph.cpp +++ b/src/python/basic_graph.cpp @@ -113,6 +113,31 @@ basic_graph::basic_graph() : inherited(), dp(build_string_property_maps(this)) { } +template +basic_graph::basic_graph(::boost::python::object l) + : inherited() +{ + using boost::python::object; + std::map verts; + int len = ::boost::python::extract(l.attr("__len__")()); + + for (int i = 0; i < len; ++i) { + vertex_descriptor u, v; + object up = l[i][0]; + object vp = l[i][1]; + + typename std::map::iterator pos; + pos = verts.find(up); + if (pos == verts.end()) u = verts[up] = add_vertex(); + else u = pos->second; + pos = verts.find(vp); + if (pos == verts.end()) v = verts[vp] = add_vertex(); + else v = pos->second; + + add_edge(u, v); + } +} + template basic_graph::basic_graph(const std::string& filename, graph_file_kind kind) @@ -527,13 +552,14 @@ template void export_in_graph(); template void export_basic_graph(const char* name) { + using boost::python::arg; using boost::python::class_; using boost::python::init; using boost::python::object; using boost::python::range; using boost::python::scope; using boost::python::self; - using boost::python::arg; + using boost::python::tuple; typedef basic_graph Graph; typedef typename Graph::Vertex Vertex; @@ -545,6 +571,7 @@ void export_basic_graph(const char* name) scope s( class_ >(name) // Constructors + .def(init()) .def(init()) .def(init( (arg("generator"), arg("seed") = 1))) diff --git a/src/python/basic_graph.hpp b/src/python/basic_graph.hpp index 16bd4ce7..06b8192f 100644 --- a/src/python/basic_graph.hpp +++ b/src/python/basic_graph.hpp @@ -228,6 +228,7 @@ class basic_graph adjacency_iterator; basic_graph(); + basic_graph(::boost::python::object); basic_graph(const std::string& filename, graph_file_kind kind); basic_graph(erdos_renyi, int seed); basic_graph(power_law_out_degree, int seed);