PGROUTING  3.2
pgr_dagShortestPath.hpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 
3 Copyright (c) 2015 pgRouting developers
5 
6 Copyright (c) 2018 Sourabh Garg
8 
9 ------
10 
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 
25  ********************************************************************PGR-GNU*/
26 
27 #ifndef INCLUDE_DAGSHORTESTPATH_PGR_DAGSHORTESTPATH_HPP_
28 #define INCLUDE_DAGSHORTESTPATH_PGR_DAGSHORTESTPATH_HPP_
29 #pragma once
30 
31 #include <boost/config.hpp>
32 #include <boost/graph/dijkstra_shortest_paths.hpp>
33 #include <boost/graph/adjacency_list.hpp>
34 #include <boost/graph/dag_shortest_paths.hpp>
35 #include <deque>
36 #include <set>
37 #include <vector>
38 #include <algorithm>
39 #include <sstream>
40 #include <functional>
41 #include <limits>
42 #include <map>
43 
47 
48 template < class G >
49 class Pgr_dag {
50  public:
51  typedef typename G::V V;
52  typedef typename G::E E;
53 
54 
57  G &graph,
58  int64_t start_vertex,
59  int64_t end_vertex,
60  bool only_cost = false) {
61  clear();
62 
63  // adjust predecessors and distances vectors
64  predecessors.resize(graph.num_vertices());
65  distances.resize(
66  graph.num_vertices(),
67  std::numeric_limits<double>::infinity());
68 
69 
70  if (!graph.has_vertex(start_vertex)
71  || !graph.has_vertex(end_vertex)) {
72  return Path(start_vertex, end_vertex);
73  }
74 
75  // get the graphs source and target
76  auto v_source(graph.get_V(start_vertex));
77  auto v_target(graph.get_V(end_vertex));
78 
79  // perform the algorithm
80  dag_1_to_1(graph, v_source, v_target);
81 
82  // get the results
83  return Path(
84  graph,
85  v_source, v_target,
87  only_cost, true);
88  }
89 
90 
92  std::deque<Path> dag(
93  G &graph,
94  int64_t start_vertex,
95  const std::vector< int64_t > &end_vertex,
96  bool only_cost) {
97  // adjust predecessors and distances vectors
98  clear();
99  size_t n_goals = (std::numeric_limits<size_t>::max)();
100  predecessors.resize(graph.num_vertices());
101  distances.resize(
102  graph.num_vertices(),
103  std::numeric_limits<double>::infinity());
104 
105 
106  // get the graphs source and target
107  if (!graph.has_vertex(start_vertex))
108  return std::deque<Path>();
109  auto v_source(graph.get_V(start_vertex));
110 
111  std::set< V > s_v_targets;
112  for (const auto &vertex : end_vertex) {
113  if (graph.has_vertex(vertex)) {
114  s_v_targets.insert(graph.get_V(vertex));
115  }
116  }
117 
118  std::vector< V > v_targets(s_v_targets.begin(), s_v_targets.end());
119  // perform the algorithm
120  dag_1_to_many(graph, v_source, v_targets, n_goals);
121 
122  std::deque< Path > paths;
123  // get the results // route id are the targets
124  paths = get_paths(graph, v_source, v_targets, only_cost);
125 
126  std::stable_sort(paths.begin(), paths.end(),
127  [](const Path &e1, const Path &e2)->bool {
128  return e1.end_id() < e2.end_id();
129  });
130 
131  return paths;
132  }
133 
134  // preparation for many to 1
135  std::deque<Path> dag(
136  G &graph,
137  const std::vector < int64_t > &start_vertex,
138  int64_t end_vertex,
139  bool only_cost) {
140  std::deque<Path> paths;
141 
142  for (const auto &start : start_vertex) {
143  paths.push_back(
144  dag(graph, start, end_vertex, only_cost));
145  }
146 
147  std::stable_sort(paths.begin(), paths.end(),
148  [](const Path &e1, const Path &e2)->bool {
149  return e1.start_id() < e2.start_id();
150  });
151  return paths;
152  }
153 
154 
155  // preparation for many to many
156  std::deque<Path> dag(
157  G &graph,
158  const std::vector< int64_t > &start_vertex,
159  const std::vector< int64_t > &end_vertex,
160  bool only_cost) {
161  // a call to 1 to many is faster for each of the sources
162  std::deque<Path> paths;
163 
164  for (const auto &start : start_vertex) {
165  auto r_paths = dag(
166  graph,
167  start, end_vertex,
168  only_cost);
169  paths.insert(paths.begin(), r_paths.begin(), r_paths.end());
170  }
171 
172  std::sort(paths.begin(), paths.end(),
173  [](const Path &e1, const Path &e2)->bool {
174  return e1.end_id() < e2.end_id();
175  });
176  std::stable_sort(paths.begin(), paths.end(),
177  [](const Path &e1, const Path &e2)->bool {
178  return e1.start_id() < e2.start_id();
179  });
180  return paths;
181  }
182 
183  // preparation for parallel arrays
184  std::deque<Path> dag(
185  G &graph,
186  const std::vector<pgr_combination_t> &combinations,
187  bool only_cost) {
188  std::deque<Path> paths;
189 
190  // group targets per distinct source
191  std::map< int64_t, std::vector<int64_t> > vertex_map;
192  for (const pgr_combination_t &comb : combinations) {
193  std::map< int64_t, std::vector<int64_t> >::iterator it = vertex_map.find(comb.source);
194  if (it != vertex_map.end()) {
195  it->second.push_back(comb.target);
196  } else {
197  std::vector<int64_t > targets{comb.target};
198  vertex_map[comb.source] = targets;
199  }
200  }
201 
202  for (const auto &start_ends : vertex_map) {
203  auto result_paths = dag(
204  graph,
205  start_ends.first,
206  start_ends.second,
207  only_cost);
208  paths.insert(
209  paths.end(),
210  std::make_move_iterator(result_paths.begin()),
211  std::make_move_iterator(result_paths.end()));
212  }
213 
214  return paths;
215  }
216 
218 
219  private:
222  G &graph,
223  V source,
224  V target) {
225  /* abort in case of an interruption occurs (e.g. the query is being cancelled) */
226  CHECK_FOR_INTERRUPTS();
227  try {
228  boost::dag_shortest_paths(graph.graph, source,
229  boost::predecessor_map(&predecessors[0])
230  .weight_map(get(&G::G_T_E::cost, graph.graph))
231  .distance_map(&distances[0])
232  .visitor(dijkstra_one_goal_visitor(target)));
233  } catch(found_goals &) {
234  return true;
235  } catch (boost::exception const& ex) {
236  (void)ex;
237  throw;
238  } catch (std::exception &e) {
239  (void)e;
240  throw;
241  } catch (...) {
242  throw;
243  }
244  return true;
245  }
246 
249  G &graph,
250  V source,
251  const std::vector< V > &targets,
252  size_t n_goals = (std::numeric_limits<size_t>::max)()) {
253  /* abort in case of an interruption occurs (e.g. the query is being cancelled) */
254  CHECK_FOR_INTERRUPTS();
255  try {
256  boost::dag_shortest_paths(graph.graph, source,
257  boost::predecessor_map(&predecessors[0])
258  .weight_map(get(&G::G_T_E::cost, graph.graph))
259  .distance_map(&distances[0])
260  .distance_inf(std::numeric_limits<double>::infinity())
261  .visitor(dijkstra_many_goal_visitor(targets, n_goals)));
262  } catch(found_goals &) {
263  return true;
264  } catch (boost::exception const& ex) {
265  (void)ex;
266  throw;
267  } catch (std::exception &e) {
268  (void)e;
269  throw;
270  } catch (...) {
271  throw;
272  }
273  return true;
274  }
275 
276 
277  void clear() {
278  predecessors.clear();
279  distances.clear();
280  nodesInDistance.clear();
281  }
282 
283 
284 
285 
286  // used when multiple goals
287  std::deque<Path> get_paths(
288  const G &graph,
289  V source,
290  std::vector< V > &targets,
291  bool only_cost) const {
292  std::deque<Path> paths;
293  for (const auto target : targets) {
294  paths.push_back(Path(
295  graph,
296  source, target,
298  only_cost, true));
299  }
300  return paths;
301  }
302 
303 
304 
306 
307  struct found_goals{};
308  std::vector< V > predecessors;
309  std::vector< double > distances;
310  std::deque< V > nodesInDistance;
311  std::ostringstream log;
313 
314 
316 
317 
319  class dijkstra_one_goal_visitor : public boost::default_dijkstra_visitor {
320  public:
321  explicit dijkstra_one_goal_visitor(V goal) : m_goal(goal) {}
322  template <class B_G>
323  void examine_vertex(V &u, B_G &) {
324  if (u == m_goal) throw found_goals();
325  }
326  private:
328  };
329 
331  class dijkstra_many_goal_visitor : public boost::default_dijkstra_visitor {
332  public:
334  const std::vector< V > &goals,
335  size_t n_goals) :
336  m_goals(goals.begin(), goals.end()),
337  m_n_goals(n_goals) {}
338  template <class B_G>
339  void examine_vertex(V u, B_G &) {
340  auto s_it = m_goals.find(u);
341  if (s_it == m_goals.end()) return;
342 
343  // found one more goal
344  m_goals.erase(s_it);
345 
346  // all goals found
347  if (m_goals.size() == 0) throw found_goals();
348 
349  // number of requested goals found
350  --m_n_goals;
351  if (m_n_goals == 0) throw found_goals();
352  }
353 
354  private:
355  std::set< V > m_goals;
356  size_t m_n_goals;
357  };
358 };
359 
360 #endif // INCLUDE_DAGSHORTESTPATH_PGR_DAGSHORTESTPATH_HPP_
interruption.h
Pgr_dag::clear
void clear()
Definition: pgr_dagShortestPath.hpp:277
Path
Definition: basePath_SSEC.hpp:47
Pgr_dag::dag
Path dag(G &graph, int64_t start_vertex, int64_t end_vertex, bool only_cost=false)
Dijkstra 1 to 1.
Definition: pgr_dagShortestPath.hpp:56
pgr_base_graph.hpp
Pgr_dag::E
G::E E
Definition: pgr_dagShortestPath.hpp:52
Pgr_dag::dag
std::deque< Path > dag(G &graph, int64_t start_vertex, const std::vector< int64_t > &end_vertex, bool only_cost)
Dijkstra 1 to many.
Definition: pgr_dagShortestPath.hpp:92
Pgr_dag::dag
std::deque< Path > dag(G &graph, const std::vector< int64_t > &start_vertex, int64_t end_vertex, bool only_cost)
Definition: pgr_dagShortestPath.hpp:135
Pgr_dag::dag_1_to_many
bool dag_1_to_many(G &graph, V source, const std::vector< V > &targets, size_t n_goals=(std::numeric_limits< size_t >::max)())
Dijkstra 1 source to many targets.
Definition: pgr_dagShortestPath.hpp:248
Pgr_dag::dijkstra_many_goal_visitor::examine_vertex
void examine_vertex(V u, B_G &)
Definition: pgr_dagShortestPath.hpp:339
Pgr_dag::log
std::ostringstream log
Definition: pgr_dagShortestPath.hpp:311
Pgr_dag::dag_1_to_1
bool dag_1_to_1(G &graph, V source, V target)
Call to Dijkstra 1 source to 1 target.
Definition: pgr_dagShortestPath.hpp:221
Pgr_dag::distances
std::vector< double > distances
Definition: pgr_dagShortestPath.hpp:309
Pgr_dag::dijkstra_many_goal_visitor::dijkstra_many_goal_visitor
dijkstra_many_goal_visitor(const std::vector< V > &goals, size_t n_goals)
Definition: pgr_dagShortestPath.hpp:333
Pgr_dag::get_paths
std::deque< Path > get_paths(const G &graph, V source, std::vector< V > &targets, bool only_cost) const
Definition: pgr_dagShortestPath.hpp:287
Pgr_dag::dijkstra_one_goal_visitor
class for stopping when 1 target is found
Definition: pgr_dagShortestPath.hpp:319
pgrouting::alphashape::E
boost::graph_traits< BG >::edge_descriptor E
Definition: pgr_alphaShape.h:57
pgr_combination_t
Definition: pgr_combination_t.h:43
Pgr_dag::dijkstra_many_goal_visitor::m_n_goals
size_t m_n_goals
Definition: pgr_dagShortestPath.hpp:356
Pgr_dag::dijkstra_many_goal_visitor::m_goals
std::set< V > m_goals
Definition: pgr_dagShortestPath.hpp:355
Pgr_dag::nodesInDistance
std::deque< V > nodesInDistance
Definition: pgr_dagShortestPath.hpp:310
Pgr_dag::dag
std::deque< Path > dag(G &graph, const std::vector< int64_t > &start_vertex, const std::vector< int64_t > &end_vertex, bool only_cost)
Definition: pgr_dagShortestPath.hpp:156
Pgr_dag::predecessors
std::vector< V > predecessors
Definition: pgr_dagShortestPath.hpp:308
Pgr_dag::dijkstra_one_goal_visitor::examine_vertex
void examine_vertex(V &u, B_G &)
Definition: pgr_dagShortestPath.hpp:323
Pgr_dag::V
G::V V
Definition: pgr_dagShortestPath.hpp:51
Pgr_dag::dijkstra_one_goal_visitor::m_goal
V m_goal
Definition: pgr_dagShortestPath.hpp:327
Pgr_dag::dijkstra_one_goal_visitor::dijkstra_one_goal_visitor
dijkstra_one_goal_visitor(V goal)
Definition: pgr_dagShortestPath.hpp:321
Pgr_dag::dijkstra_many_goal_visitor
class for stopping when all targets are found
Definition: pgr_dagShortestPath.hpp:331
pgrouting::alphashape::G
graph::Pgr_base_graph< BG, XY_vertex, Basic_edge > G
Definition: pgr_alphaShape.h:56
Pgr_dag::dag
std::deque< Path > dag(G &graph, const std::vector< pgr_combination_t > &combinations, bool only_cost)
Definition: pgr_dagShortestPath.hpp:184
Pgr_dag::found_goals
Definition: pgr_dagShortestPath.hpp:307
pgrouting::alphashape::V
boost::graph_traits< BG >::vertex_descriptor V
Definition: pgr_alphaShape.h:58
Pgr_dag
Definition: pgr_dagShortestPath.hpp:49
basePath_SSEC.hpp