Commit 50559493 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Add 'edges' parameter to all_shortest_paths()

This fixes issue #622
parent 1f67a67f
......@@ -550,8 +550,9 @@ void do_get_all_preds(GraphInterface& gi, boost::any adist, boost::any apred,
}
template <class Pred, class Yield>
void get_all_shortest_paths(size_t s, size_t t, Pred pred, Yield& yield)
template <class Graph, class Pred, class Yield>
void get_all_shortest_paths(GraphInterface& gi, Graph& g, size_t s, size_t t,
Pred pred, bool edges, Yield& yield)
{
vector<size_t> path;
vector<pair<size_t, size_t>> stack = {{t, 0}};
......@@ -561,10 +562,30 @@ void get_all_shortest_paths(size_t s, size_t t, Pred pred, Yield& yield)
std::tie(v, i) = stack.back();
if (v == s)
{
path.clear();
for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter)
path.push_back(iter->first);
yield(wrap_vector_owned<size_t>(path));
if (!edges)
{
path.clear();
for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter)
path.push_back(iter->first);
yield(wrap_vector_owned<size_t>(path));
}
else
{
auto gp = retrieve_graph_view<Graph>(gi, g);
boost::python::list opath;
auto s = graph_traits<Graph>::null_vertex();
for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter)
{
auto t = iter->first;
if (s != graph_traits<Graph>::null_vertex())
{
auto e = edge(s, t, g).first;
opath.append(PythonEdge<Graph>(gp, e));
}
s = t;
}
yield(opath);
}
}
if (pred[v].size() > i)
{
......@@ -580,14 +601,14 @@ void get_all_shortest_paths(size_t s, size_t t, Pred pred, Yield& yield)
};
python::object do_get_all_shortest_paths(GraphInterface& gi, size_t s, size_t t,
boost::any apred)
boost::any apred, bool edges)
{
#ifdef HAVE_BOOST_COROUTINE
auto dispatch = [&](auto& yield)
{
run_action<>()
(gi, [&](auto&, auto pred)
{get_all_shortest_paths(s, t, pred, yield);},
(gi, [&](auto& g, auto pred)
{get_all_shortest_paths(gi, g, s, t, pred, edges, yield);},
vertex_scalar_vector_properties())(apred);
};
return python::object(CoroGenerator(dispatch));
......
......@@ -2182,7 +2182,7 @@ def all_predecessors(g, dist_map, pred_map, weights=None, epsilon=1e-8):
return preds
def all_shortest_paths(g, source, target, dist_map=None, pred_map=None,
all_preds_map=None, epsilon=1e-8, **kwargs):
all_preds_map=None, epsilon=1e-8, edges=False, **kwargs):
"""Return an iterator over all shortest paths from `source` to `target`.
Parameters
......@@ -2207,6 +2207,8 @@ def all_shortest_paths(g, source, target, dist_map=None, pred_map=None,
epsilon : ``float`` (optional, default: ``1e-8``)
Maximum relative difference between distances to be considered "equal",
in case floating-point weights are used.
edges : ``bool`` (optional, default: ``False``)
If ``True``, the returned iterator is over edge descriptors.
**kwargs : Keyword parameter list
The remaining parameters will be passed to
:func:`~graph_tool.topology.shortest_path`.
......@@ -2215,7 +2217,8 @@ def all_shortest_paths(g, source, target, dist_map=None, pred_map=None,
-------
path_iterator : iterator over a sequence of integers
Iterator over sequences of vertices from `source` to `target` in the
shortest path.
shortest path. If ``edges == True``, the iterator is over sequences of
edge descriptors (:class:`~graph_tool.Edge`).
Notes
-----
......@@ -2254,7 +2257,8 @@ def all_shortest_paths(g, source, target, dist_map=None, pred_map=None,
libgraph_tool_topology.get_all_shortest_paths(g._Graph__graph,
int(source),
int(target),
_prop("v", g, all_preds_map))
_prop("v", g, all_preds_map),
edges)
for p in path_iterator:
yield p
......
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