Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Expanded the Cython-friendly comment, linked Boost ticket, removed tr…
Browse files Browse the repository at this point in the history
…ailing whitespaces
  • Loading branch information
Michele Borassi committed Jun 18, 2015
1 parent f3a1c07 commit 51a183a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 47 deletions.
6 changes: 3 additions & 3 deletions src/sage/graphs/base/boost_graph.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ cdef extern from "boost_interface.cpp":
int num_edges()
result_ec edge_connectivity()
pass

ctypedef BoostGraph[vecS, vecS, undirectedS, vecS] BoostVecGraph
ctypedef BoostGraph[vecS, vecS, bidirectionalS, vecS] BoostVecDiGraph

ctypedef fused BoostVecGenGraph:
BoostVecGraph
BoostVecDiGraph

ctypedef fused BoostGenGraph:
BoostVecGraph
BoostVecDiGraph
Expand Down
74 changes: 35 additions & 39 deletions src/sage/graphs/base/boost_graph.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
# http://www.gnu.org/licenses/
#*****************************************************************************
r"""
Boost Graphs
Interface to run Boost algorithms
Wrapper for a Boost graphs. The Boost graphs must be created with cdef, and
they cannot be shared by different Python functions, because they cannot be
converted to Python objects.
Expand All @@ -19,19 +19,15 @@ raises an error. Furthermore, no variable can have a generic type, apart from
the arguments of a generic function.
All the input functions use pointers, because otherwise we might have problems
with ``delete()`` routines.
with ``delete()``.
**Basic Boost Graph operations:**
.. csv-table::
:class: contentstable
:widths: 30, 70
:delim: |
:meth:`~add_vertex` | Adds a vertex to the graph.
:meth:`~add_edge` | Adds an edge to the graph.
:meth:`~num_verts` | Returns the number of vertices.
:meth:`~num_edges` | Returns the number of edges.
:meth:`~edge_connectivity` | Returns the edge connectivity of the graph.
"""
Expand All @@ -46,7 +42,7 @@ include "sage/ext/interrupt.pxi"
cdef boost_graph_from_sage_graph(BoostGenGraph *g, g_sage):
r"""
Initializes the Boost graph ``g`` to be equal to g_sage.
The Boost output graph must be generated elsewhere, because Cython does not
allow to instantiate a generic graph. However, ``g`` must be empty,
otherwise an error is raised.
Expand All @@ -57,84 +53,84 @@ cdef boost_graph_from_sage_graph(BoostGenGraph *g, g_sage):

if g.num_verts() > 0:
raise ValueError("The Boost graph in input must be empty")

N = g_sage.num_verts()
vertex_to_int = {v:i for i,v in enumerate(g_sage.vertices())}

for i in range(N):
g.add_vertex()

for u,v in g_sage.edge_iterator(labels=None):
g.add_edge(vertex_to_int[u], vertex_to_int[v])

cdef edge_connectivity(BoostVecGenGraph *g):
r"""
Computes the edge connectivity of the input Boost graph.
The adjacency lists of the input graph should be vectors, because the Boost
edge connectivity algorithm requires this kind of input. The output is a
The adjacency lists of the input graph should be vectors, because the Boost
edge connectivity algorithm requires this kind of input. The output is a
pair ``[ec,edges]``, where ``ec`` is the edge connectivity, ``edges`` is the
list of edges in a minimum cut. It is based on the function
``edge_connectivity`` in file ``boost_interface``, which outputs a vector,
list of edges in a minimum cut. It is based on the function
``edge_connectivity`` in file ``boost_interface``, which outputs a vector,
having in position 0 the edge connectivity, followed by a list of arcs.
WARNING: this function is a backend, which should not be called by the
WARNING: this function is a backend, which should not be called by the
standard user. We suggest to use the method
:meth:`edge_connectivity <sage.graphs.generic_graph.GenericGraph>`
:meth:`edge_connectivity <sage.graphs.generic_graph.GenericGraph>`
instead.
"""
result = g[0].edge_connectivity()

cdef int ec = result.ec

edges = []

for i in range(0, result.edges.size(), 2):
edges.append([result.edges[i], result.edges[i+1]])

return[ec, edges]

cpdef boost_edge_connectivity(g):
r"""
Computes the edge connectivity of the input graph, using the Boost
Computes the edge connectivity of the input graph, using the Boost
algorithm.
The output is a pair ``[ec,edges]``, where ``ec`` is the edge connectivity,
``edges`` is the list of edges in a minimum cut.
WARNING: this function is a backend, which should not be called by the
The output is a pair ``[ec,edges]``, where ``ec`` is the edge connectivity,
``edges`` is the list of edges in a minimum cut.
WARNING: this function is a backend, which should not be called by the
standard user. We suggest to use the method
:meth:`edge_connectivity <sage.graphs.generic_graph.GenericGraph.edge_connectivity>`
:meth:`edge_connectivity <sage.graphs.generic_graph.GenericGraph.edge_connectivity>`
instead.
EXAMPLES:
Computing the edge connectivity of a clique::
sage: from sage.graphs.base.boost_graph import boost_edge_connectivity
sage: g = graphs.CompleteGraph(5)
sage: boost_edge_connectivity(g)
[4, [[0, 1], [0, 2], [0, 3], [0, 4]]]
"""
sig_on()
# These variables are automatically deleted when the function terminates.
cdef BoostVecGraph g_boost_und
cdef BoostVecGraph g_boost_und
cdef BoostVecDiGraph g_boost_dir

if isinstance(g, Graph):
boost_graph_from_sage_graph(&g_boost_und, g)
sig_off()
return edge_connectivity(&g_boost_und)

elif isinstance(g, DiGraph):
boost_graph_from_sage_graph(&g_boost_dir, g)
print ("The directed edge connectivity algorithm implemented in the "
"Boost graph library is not reliable. The result could be "
"wrong.")
sig_off()
return edge_connectivity(&g_boost_dir)

else:
sig_off()
raise ValueError("The input must be a Sage graph.")
Expand Down
13 changes: 9 additions & 4 deletions src/sage/graphs/base/boost_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ class BoostGraph
/*
* This generic class wraps a Boost graph, in order to make it Cython-friendly.
*
* In particular, it allows to "keep together" the Boost graph and the vector
* *vertices: these two variables are generic, and Cython is not able to deal
* with them properly, since it does not support generic classes.
*
* Vertices are numbers from 0 to n-1, where n is the total number of vertices:
* this class takes care of the relation between number i and the corresponding
* Boost vertex descriptor (which might be any object, depending on the value of
* VertexListS).
* In particular, (*vertices)[i] contains the Boost vertex corresponding to number
* i, while to transform a Boost vertex v into a number we use vertex properties,
* and the syntax is (*graph)[v].
* VertexListS). In particular, (*vertices)[i] contains the Boost vertex
* corresponding to number i, while to transform a Boost vertex v into a number
* we use vertex properties, and the syntax is (*graph)[v].
*/
{
typedef typename boost::adjacency_list<OutEdgeListS, VertexListS, DirectedS,
Expand Down Expand Up @@ -65,6 +68,8 @@ class BoostGraph
(*vertices).push_back(boost::add_vertex((*vertices).size(), *graph));
}



void add_edge(int u, int v) {
boost::add_edge((*vertices)[u], (*vertices)[v], *graph);
}
Expand Down
4 changes: 3 additions & 1 deletion src/sage/graphs/generic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -8274,7 +8274,9 @@ def edge_connectivity(self,
graph library is not reliable. The result could be wrong.
[1, [[0, 1]], [{0}, {1, 2, 3, 4, 5, 6, 7, 8, 9}]]

However, Boost algorithm still contains bugs if the input is directed::
However, the Boost algorithm is not reliable if the input is directed
(see https://svn.boost.org/trac/boost/ticket/11406 for
more information)::

sage: g = digraphs.Path(3)
sage: g.edge_connectivity()
Expand Down

0 comments on commit 51a183a

Please sign in to comment.