Commit a8481771 authored by Tiago Peixoto's avatar Tiago Peixoto

Add 'target' parameter to shortest_distances()

parent e5a1861d
......@@ -34,8 +34,9 @@ class bfs_max_visitor:
public boost::bfs_visitor<null_visitor>
{
public:
bfs_max_visitor(DistMap dist_map, PredMap pred, size_t max_dist)
: _dist_map(dist_map), _pred(pred), _max_dist(max_dist), _dist(0) {}
bfs_max_visitor(DistMap dist_map, PredMap pred, size_t max_dist, size_t target)
: _dist_map(dist_map), _pred(pred), _max_dist(max_dist), _target(target),
_dist(0) {}
template <class Graph>
void tree_edge(typename graph_traits<Graph>::edge_descriptor e,
......@@ -54,12 +55,16 @@ public:
if (dist > _max_dist)
throw stop_search();
_dist_map[v] = dist;
if (v == _target)
throw stop_search();
}
private:
DistMap _dist_map;
PredMap _pred;
size_t _max_dist;
size_t _target;
size_t _dist;
};
......@@ -69,12 +74,12 @@ class djk_max_visitor:
{
public:
djk_max_visitor(DistMap dist_map,
typename property_traits<DistMap>::value_type max_dist)
: _dist_map(dist_map), _max_dist(max_dist) {}
typename property_traits<DistMap>::value_type max_dist, size_t target)
: _dist_map(dist_map), _max_dist(max_dist), _target(target) {}
template <class Graph>
void examine_vertex(typename graph_traits<Graph>::vertex_descriptor u,
Graph&)
void discover_vertex(typename graph_traits<Graph>::vertex_descriptor u,
Graph&)
{
if (_dist_map[u] > _max_dist)
{
......@@ -82,36 +87,28 @@ public:
_dist_map[u] = numeric_limits<d_type>::max();
throw stop_search();
}
if (u == _target)
throw stop_search();
}
private:
DistMap _dist_map;
typename property_traits<DistMap>::value_type _max_dist;
size_t _target;
};
struct do_bfs_search
{
template <class Graph, class VertexIndexMap, class DistMap, class PredMap>
void operator()(const Graph& g, size_t source, VertexIndexMap vertex_index,
DistMap dist_map, PredMap pred_map, long double max_dist)
const
void operator()(const Graph& g, size_t source, size_t target,
VertexIndexMap vertex_index, DistMap dist_map,
PredMap pred_map, long double max_dist) const
{
typedef typename property_traits<DistMap>::value_type dist_t;
dist_t max_d = (max_dist > 0) ?
max_dist : numeric_limits<dist_t>::max();
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(dynamic)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
dist_map[v] = numeric_limits<dist_t>::max();
}
dist_map[vertex(source,g)] = 0;
pred_map[vertex(source, g)] = vertex(source, g);
unchecked_vector_property_map<boost::default_color_type, VertexIndexMap>
color_map(vertex_index, num_vertices(g));
......@@ -119,7 +116,7 @@ struct do_bfs_search
{
breadth_first_search(g, vertex(source, g),
visitor(bfs_max_visitor<DistMap, PredMap>
(dist_map, pred_map, max_d)).
(dist_map, pred_map, max_d, target)).
vertex_index_map(vertex_index).
color_map(color_map));
}
......@@ -131,9 +128,9 @@ struct do_djk_search
{
template <class Graph, class VertexIndexMap, class DistMap, class PredMap,
class WeightMap>
void operator()(const Graph& g, size_t source, VertexIndexMap vertex_index,
DistMap dist_map, PredMap pred_map, WeightMap weight,
long double max_dist) const
void operator()(const Graph& g, size_t source, size_t target,
VertexIndexMap vertex_index, DistMap dist_map,
PredMap pred_map, WeightMap weight, long double max_dist) const
{
typedef typename property_traits<DistMap>::value_type dist_t;
dist_t max_d = (max_dist > 0) ?
......@@ -147,13 +144,13 @@ struct do_djk_search
vertex_index_map(vertex_index).
predecessor_map(pred_map).
visitor(djk_max_visitor<DistMap>
(dist_map, max_d)));
(dist_map, max_d, target)));
}
catch (stop_search&) {}
}
};
void get_dists(GraphInterface& gi, size_t source, boost::any dist_map,
void get_dists(GraphInterface& gi, size_t source, int tgt, boost::any dist_map,
boost::any weight, boost::any pred_map, long double max_dist)
{
typedef property_map_type
......@@ -161,10 +158,12 @@ void get_dists(GraphInterface& gi, size_t source, boost::any dist_map,
pred_map_t pmap = any_cast<pred_map_t>(pred_map);
size_t target = tgt < 0 ? graph_traits<GraphInterface::multigraph_t>::null_vertex() : tgt;
if (weight.empty())
{
run_action<>()
(gi, bind<void>(do_bfs_search(), _1, source, gi.GetVertexIndex(),
(gi, bind<void>(do_bfs_search(), _1, source, target, gi.GetVertexIndex(),
_2, pmap.get_unchecked(num_vertices(gi.GetGraph())),
max_dist),
writable_vertex_scalar_properties(),
......@@ -174,7 +173,7 @@ void get_dists(GraphInterface& gi, size_t source, boost::any dist_map,
else
{
run_action<>()
(gi, bind<void>(do_djk_search(), _1, source, gi.GetVertexIndex(),
(gi, bind<void>(do_djk_search(), _1, source, target, gi.GetVertexIndex(),
_2, pmap.get_unchecked(num_vertices(gi.GetGraph())),
_3, max_dist),
writable_vertex_scalar_properties(),
......
......@@ -1006,12 +1006,13 @@ def kcore_decomposition(g, deg="out", vprop=None):
return vprop
def shortest_distance(g, source=None, weights=None, max_dist=None,
def shortest_distance(g, source=None, target=None, weights=None, max_dist=None,
directed=None, dense=False, dist_map=None,
pred_map=False):
"""
Calculate the distance of all vertices from a given source, or the all pairs
shortest paths, if the source is not specified.
Calculate the distance from a source to a target vertex, or to of all
vertices from a given source, or the all pairs shortest paths, if the source
is not specified.
Parameters
----------
......@@ -1020,6 +1021,9 @@ def shortest_distance(g, source=None, weights=None, max_dist=None,
source : :class:`~graph_tool.Vertex` (optional, default: None)
Source vertex of the search. If unspecified, the all pairs shortest
distances are computed.
target : :class:`~graph_tool.Vertex` (optional, default: None)
Target vertex of the search. If unspecified, the distance to all
vertices from the source will be computed.
weights : :class:`~graph_tool.PropertyMap` (optional, default: None)
The edge weights. If provided, the minimum spanning tree will minimize
the edge weights.
......@@ -1147,10 +1151,15 @@ def shortest_distance(g, source=None, weights=None, max_dist=None,
g.stash_filter(directed=True)
g.set_directed(directed)
if target is None:
target = -1
try:
if source is not None:
pmap = g.copy_property(g.vertex_index, value_type="int64_t")
libgraph_tool_topology.get_dists(g._Graph__graph, int(source),
libgraph_tool_topology.get_dists(g._Graph__graph,
int(source),
int(target),
_prop("v", g, dist_map),
_prop("e", g, weights),
_prop("v", g, pmap),
......@@ -1163,6 +1172,10 @@ def shortest_distance(g, source=None, weights=None, max_dist=None,
finally:
if directed is not None:
g.pop_filter(directed=True)
if source is not None and target != -1:
dist_map = dist_map[target]
if source is not None and pred_map:
return dist_map, pmap
else:
......@@ -1233,10 +1246,11 @@ def shortest_path(g, source, target, weights=None, pred_map=None):
"""
if pred_map is None:
pred_map = shortest_distance(g, source, weights=weights,
pred_map = shortest_distance(g, source, target,
weights=weights,
pred_map=True)[1]
if pred_map[target] == int(target): # no path to source
if pred_map[target] == int(target): # no path to target
return [], []
vlist = [target]
......
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