Commit 4026fb2a authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Implement get_graph() method in Edge and Vertex classes

This also makes all Edge classes inherit from the same base class of the
same name.

This fixes tickets #94 and #95
parent 70b50865
......@@ -43,7 +43,7 @@ struct get_vertex_iterator
python::object get_vertices(python::object g)
{
GraphInterface& gi = python::extract<GraphInterface&>(g());
GraphInterface& gi = python::extract<GraphInterface&>(g().attr("_Graph__graph"));
python::object iter;
run_action<>()(gi, bind<void>(get_vertex_iterator(), _1,
ref(g),
......@@ -86,7 +86,7 @@ struct get_vertex_hard
python::object get_vertex(python::object g, size_t i)
{
GraphInterface& gi = python::extract<GraphInterface&>(g());
GraphInterface& gi = python::extract<GraphInterface&>(g().attr("_Graph__graph"));
python::object v;
if (gi.IsVertexFilterActive())
run_action<>()(gi,
......@@ -111,7 +111,7 @@ struct get_edge_iterator
python::object get_edges(python::object g)
{
GraphInterface& gi = python::extract<GraphInterface&>(g());
GraphInterface& gi = python::extract<GraphInterface&>(g().attr("_Graph__graph"));
python::object iter;
run_action<>()(gi,
bind<void>(get_edge_iterator(), _1, ref(g), ref(iter)))();
......@@ -120,7 +120,7 @@ python::object get_edges(python::object g)
python::object add_vertex(python::object g)
{
GraphInterface& gi = python::extract<GraphInterface&>(g());
GraphInterface& gi = python::extract<GraphInterface&>(g().attr("_Graph__graph"));
return python::object(PythonVertex(g, add_vertex(gi.GetGraph())));
}
......@@ -188,7 +188,7 @@ python::object add_edge(python::object g, const python::object& s,
PythonVertex& tgt = python::extract<PythonVertex&>(t);
src.CheckValid();
tgt.CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(g());
GraphInterface& gi = python::extract<GraphInterface&>(g().attr("_Graph__graph"));
python::object new_e;
run_action<>()(gi, bind<void>(add_new_edge(), _1, ref(g), ref(gi), src, tgt,
gi.GetEdgeIndex(), ref(new_e)))();
......@@ -308,8 +308,7 @@ struct export_python_interface
void operator()(const Graph*, set<string>& v_iterators) const
{
using namespace boost::python;
class_<PythonEdge<Graph> >
class_<PythonEdge<Graph>, bases<EdgeBase> >
("Edge", no_init)
.def("source", &PythonEdge<Graph>::GetSource,
"Return the source vertex.")
......@@ -317,6 +316,8 @@ struct export_python_interface
"Return the target vertex.")
.def("is_valid", &PythonEdge<Graph>::IsValid,
"Return whether the edge is valid.")
.def("get_graph", &PythonEdge<Graph>::GetGraph,
"Return the graph to which the edge belongs.")
.def(python::self == python::self)
.def(python::self != python::self)
.def("__str__", &PythonEdge<Graph>::GetString)
......@@ -401,11 +402,14 @@ void export_python_interface()
"Return an iterator over the in-edges.")
.def("is_valid", &PythonVertex::IsValid,
"Return whether the vertex is valid.")
.def("get_graph", &PythonVertex::GetGraph,
"Return the graph to which the vertex belongs.")
.def(python::self == python::self)
.def(python::self != python::self)
.def("__str__", &PythonVertex::GetString)
.def("__int__", &PythonVertex::GetIndex)
.def("__hash__", &PythonVertex::GetHash);
class_<EdgeBase>("EdgeBase", no_init);
set<string> v_iterators;
typedef mpl::transform<graph_tool::detail::all_graph_views,
......
......@@ -84,7 +84,7 @@ public:
{
if (_g().ptr() == Py_None)
return false;
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
return _valid &&
(_v != graph_traits<GraphInterface::multigraph_t>::null_vertex()) &&
(_v < num_vertices(gi._state->_mg));
......@@ -102,6 +102,11 @@ public:
lexical_cast<string>(_v));
}
python::object GetGraph() const
{
return _g();
}
GraphInterface::vertex_t GetDescriptor() const
{
return _v;
......@@ -122,7 +127,7 @@ public:
size_t GetInDegree() const
{
CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
size_t in_deg;
run_action<>()(gi, bind<void>(get_degree<in_degreeS>(),
_1, _v,
......@@ -133,7 +138,7 @@ public:
size_t GetOutDegree() const
{
CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
size_t out_deg;
run_action<>()(gi, bind<void>(get_degree<out_degreeS>(), _1, _v,
ref(out_deg)))();
......@@ -161,7 +166,7 @@ public:
OutEdges() const
{
CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
python::object iter;
run_action<>()(gi, bind<void>(get_out_edges(), _1,
ref(_g), _v, ref(iter)))();
......@@ -187,7 +192,7 @@ public:
InEdges() const
{
CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
python::object iter;
run_action<>()(gi, bind<void>(get_in_edges(), _1, ref(_g), _v,
ref(iter)))();
......@@ -208,7 +213,7 @@ public:
size_t GetIndex() const
{
CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
return gi._vertex_index[_v];
}
......@@ -234,8 +239,10 @@ private:
// below are classes related to the PythonEdge type
class EdgeBase {}; // useful to unite all edge types
template <class Graph>
class PythonEdge
class PythonEdge : public EdgeBase
{
public:
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
......@@ -249,7 +256,7 @@ public:
{
if (_g().ptr() == Py_None)
return false;
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
GraphInterface::edge_t e(_e);
return (_valid &&
PythonVertex(_g, source(e, gi._state->_mg)).IsValid() &&
......@@ -267,6 +274,11 @@ public:
throw ValueException("invalid edge descriptor");
}
python::object GetGraph() const
{
return _g();
}
GraphInterface::edge_t GetDescriptor() const
{
return _e;
......@@ -287,7 +299,7 @@ public:
python::object GetSource() const
{
CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
python::object v;
run_action<>()(gi, bind<void>(get_source(), _1, ref(_g), ref(_e),
ref(v)))();
......@@ -309,7 +321,7 @@ public:
python::object GetTarget() const
{
CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
python::object v;
run_action<>()(gi, bind<void>(get_target(), _1, ref(_g), ref(_e),
ref(v)))();
......@@ -326,7 +338,7 @@ public:
size_t GetHash() const
{
CheckValid();
GraphInterface& gi = python::extract<GraphInterface&>(_g());
GraphInterface& gi = python::extract<GraphInterface&>(_g().attr("_Graph__graph"));
return hash<size_t>()(gi._edge_index[_e]);
}
......
......@@ -782,7 +782,7 @@ class PropertyDict(dict):
# The main graph interface
################################################################################
from libgraph_tool_core import Vertex, Edge, Vector_bool, Vector_int32_t, \
from libgraph_tool_core import Vertex, EdgeBase, Vector_bool, Vector_int32_t, \
Vector_int64_t, Vector_double, Vector_long_double, Vector_string, \
new_vertex_property, new_edge_property, new_graph_property
......@@ -934,7 +934,7 @@ class Graph(object):
>>> assert(vlist == vlist2)
"""
return libcore.get_vertices(weakref.ref(self.__graph))
return libcore.get_vertices(weakref.ref(self))
def vertex(self, i, use_index=True):
"""Return the vertex with index ``i``. If ``use_index=False``, the
......@@ -943,7 +943,7 @@ class Graph(object):
if use_index:
self.stash_filter(vertex=True)
try:
v = libcore.get_vertex(weakref.ref(self.__graph), int(i))
v = libcore.get_vertex(weakref.ref(self), int(i))
finally:
if use_index:
self.pop_filter(vertex=True)
......@@ -983,7 +983,7 @@ class Graph(object):
ordering.
"""
return libcore.get_edges(weakref.ref(self.__graph))
return libcore.get_edges(weakref.ref(self))
def add_vertex(self, n=1):
"""Add a vertex to the graph, and return it. If ``n > 1``, ``n``
......@@ -992,7 +992,7 @@ class Graph(object):
vlist = []
vfilt = self.get_vertex_filter()
for i in xrange(n):
v = libcore.add_vertex(weakref.ref(self.__graph))
v = libcore.add_vertex(weakref.ref(self))
if vfilt[0] is not None:
vfilt[0][v] = not vfilt[1]
vlist.append(v)
......@@ -1031,7 +1031,7 @@ class Graph(object):
"""Add a new edge from ``source`` to ``target`` to the graph, and return
it."""
self.__check_perms("add_edge")
e = libcore.add_edge(weakref.ref(self.__graph), source, target)
e = libcore.add_edge(weakref.ref(self), source, target)
efilt = self.get_edge_filter()
if efilt[0] is not None:
efilt[0][e] = not efilt[1]
......@@ -1040,7 +1040,7 @@ class Graph(object):
def remove_edge(self, edge):
"""Remove an edge from the graph."""
self.__check_perms("del_edge")
return libcore.remove_edge(self.__graph, edge)
return libcore.remove_edge(self, edge)
def remove_edge_if(self, predicate):
"""Remove all edges from the graph, for which ``predicate(e)`` evaluates
......@@ -1570,7 +1570,7 @@ def value_types():
# Vertex and Edge Types
# =====================
from libgraph_tool_core import Vertex, Edge
from libgraph_tool_core import Vertex, Edge, EdgeBase
Vertex.__doc__ = """Vertex descriptor.
......@@ -1644,6 +1644,7 @@ def _edge_repr(self):
# There are several edge classes... me must cycle through them all to modify
# them.
def init_edge_classes():
for directed in [True, False]:
for e_reversed in [True, False]:
......@@ -1668,9 +1669,17 @@ def init_edge_classes():
init_edge_classes()
# Add convenience function to vector classes
# some shenanigans to make it seem there is only a single edge class
EdgeBase.__doc__ = Edge.__doc__
EdgeBase.source = Edge.source
EdgeBase.target = Edge.target
EdgeBase.is_valid = Edge.is_valid
EdgeBase.get_graph = Edge.get_graph
Edge = EdgeBase
Edge.__name__ = "Edge"
# Add convenience function to vector classes
def _get_array_view(self):
return self.get_array()[:]
......
......@@ -321,7 +321,7 @@ def bfs_search(g, source, visitor=BFSVisitor()):
try:
libgraph_tool_search.bfs_search(g._Graph__graph,
weakref.ref(g._Graph__graph),
weakref.ref(g),
int(source), visitor)
except StopSearch:
pass
......@@ -556,7 +556,7 @@ def dfs_search(g, source, visitor=DFSVisitor()):
try:
libgraph_tool_search.dfs_search(g._Graph__graph,
weakref.ref(g._Graph__graph),
weakref.ref(g),
int(source), visitor)
except StopSearch:
pass
......@@ -832,7 +832,7 @@ def dijkstra_search(g, source, weight, visitor=DijkstraVisitor(), dist_map=None,
try:
libgraph_tool_search.dijkstra_search(g._Graph__graph,
weakref.ref(g._Graph__graph),
weakref.ref(g),
int(source),
_prop("v", g, dist_map),
_prop("v", g, pred_map),
......@@ -1078,7 +1078,7 @@ def bellman_ford_search(g, source, weight, visitor=BellmanFordVisitor(),
try:
minimized = \
libgraph_tool_search.bellman_ford_search(g._Graph__graph,
weakref.ref(g._Graph__graph),
weakref.ref(g),
int(source),
_prop("v", g, dist_map),
_prop("v", g, pred_map),
......@@ -1508,7 +1508,7 @@ def astar_search(g, source, weight, visitor=AStarVisitor(),
"add_edge": False})
libgraph_tool_search.astar_search(g._Graph__graph,
weakref.ref(g._Graph__graph),
weakref.ref(g),
int(source), _prop("v", g, dist_map),
_prop("v", g, pred_map),
_prop("e", g, weight), visitor,
......@@ -1522,7 +1522,7 @@ def astar_search(g, source, weight, visitor=AStarVisitor(),
" dist_map.")
g._Graph__perms.update({"del_vertex": False})
libgraph_tool_search.astar_search_implicit\
(g._Graph__graph, weakref.ref(g._Graph__graph), int(source),
(g._Graph__graph, weakref.ref(g), int(source),
_prop("v", g, dist_map), _prop("v", g, pred_map),
_prop("v", g, cost_map), _prop("e", g, weight), visitor,
compare, combine, zero, infinity, h)
......
......@@ -53,7 +53,7 @@ def find_vertex(g, prop, match):
"out" or "total", representing a degree type."""
val = _convert(prop, match)
ret = libgraph_tool_util.\
find_vertex_range(weakref.ref(g._Graph__graph), _degree(g, prop),
find_vertex_range(weakref.ref(g), _degree(g, prop),
(val, val))
return ret
......@@ -63,7 +63,7 @@ def find_vertex_range(g, prop, range):
parameter prop can be either a :class:`~graph_tool.PropertyMap` or string
with value"in", "out" or "total", representing a degree type."""
ret = libgraph_tool_util.\
find_vertex_range(weakref.ref(g._Graph__graph), _degree(g, prop),
find_vertex_range(weakref.ref(g), _degree(g, prop),
(_convert(prop, range[0]), _convert(prop, range[1])))
return ret
......@@ -73,7 +73,7 @@ def find_edge(g, prop, match):
must be a :class:`~graph_tool.PropertyMap`."""
val = _convert(prop, match)
ret = libgraph_tool_util.\
find_edge_range(weakref.ref(g._Graph__graph), _prop("e", g, prop),
find_edge_range(weakref.ref(g), _prop("e", g, prop),
(val, val))
return ret
......@@ -82,6 +82,6 @@ def find_edge_range(g, prop, range):
"""Find all vertices `e` for which `range[0] <= prop[e] <= range[1]`. The
parameter prop can be either a :class:`~graph_tool.PropertyMap`."""
ret = libgraph_tool_util.\
find_edge_range(weakref.ref(g._Graph__graph), _prop("e", g, prop),
find_edge_range(weakref.ref(g), _prop("e", g, prop),
(_convert(prop, range[0]), _convert(prop, range[1])))
return ret
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment