PGROUTING  3.2
dijkstra_driver.cpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: many_to_many_dijkstra_driver.cpp
3 
4 Generated with Template by:
5 Copyright (c) 2015 pgRouting developers
7 
8 Function's developer:
9 Copyright (c) 2015 Celia Virginia Vergara Castillo
11 
12 Copyright (c) 2020 The combinations_sql signature is added by Mahmoud SAKR
13 and Esteban ZIMANYI
15 
16 ------
17 
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation; either version 2 of the License, or
21 (at your option) any later version.
22 
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
27 
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 
32  ********************************************************************PGR-GNU*/
33 
36 
37 #include <sstream>
38 #include <deque>
39 #include <vector>
40 #include <algorithm>
41 #include <limits>
42 
44 
45 #include "cpp_common/pgr_alloc.hpp"
46 #include "cpp_common/pgr_assert.h"
47 
48 namespace detail {
49 
50 void
51 post_process(std::deque<Path> &paths, bool only_cost, bool normal, size_t n_goals, bool global) {
52  paths.erase(std::remove_if(paths.begin(), paths.end(),
53  [](const Path &p) {
54  return p.size() == 0;
55  }),
56  paths.end());
57  using difference_type = std::deque<double>::difference_type;
58 
59  if (!normal) {
60  for (auto &path : paths) path.reverse();
61  }
62 
63  if (!only_cost) {
64  for (auto &p : paths) {
66  }
67  }
68 
69  if (n_goals != (std::numeric_limits<size_t>::max)()) {
70  std::sort(paths.begin(), paths.end(),
71  [](const Path &e1, const Path &e2)->bool {
72  return e1.end_id() < e2.end_id();
73  });
74  std::stable_sort(paths.begin(), paths.end(),
75  [](const Path &e1, const Path &e2)->bool {
76  return e1.start_id() < e2.start_id();
77  });
78  std::stable_sort(paths.begin(), paths.end(),
79  [](const Path &e1, const Path &e2)->bool {
80  return e1.tot_cost() < e2.tot_cost();
81  });
82  if (global && n_goals < paths.size()) {
83  paths.erase(paths.begin() + static_cast<difference_type>(n_goals), paths.end());
84  }
85  } else {
86  std::sort(paths.begin(), paths.end(),
87  [](const Path &e1, const Path &e2)->bool {
88  return e1.end_id() < e2.end_id();
89  });
90  std::stable_sort(paths.begin(), paths.end(),
91  [](const Path &e1, const Path &e2)->bool {
92  return e1.start_id() < e2.start_id();
93  });
94  }
95 }
96 
97 
98 template < class G >
99 std::deque< Path >
101  G &graph,
102  std::vector < int64_t > sources,
103  std::vector < int64_t > targets,
104  bool only_cost,
105  bool normal,
106  size_t n_goals,
107  bool global) {
108  std::sort(sources.begin(), sources.end());
109  sources.erase(
110  std::unique(sources.begin(), sources.end()),
111  sources.end());
112 
113  std::sort(targets.begin(), targets.end());
114  targets.erase(
115  std::unique(targets.begin(), targets.end()),
116  targets.end());
117 
118  pgrouting::Pgr_dijkstra< G > fn_dijkstra;
119  auto paths = fn_dijkstra.dijkstra(
120  graph,
121  sources, targets,
122  only_cost, n_goals);
123 
124  post_process(paths, only_cost, normal, n_goals, global);
125 
126  return paths;
127 }
128 
129 
130 template < class G >
131 std::deque< Path >
133  G &graph,
134  std::vector < pgr_combination_t > &combinations,
135  bool only_cost,
136  bool normal,
137  size_t n_goals,
138  bool global) {
139  pgrouting::Pgr_dijkstra< G > fn_dijkstra;
140  auto paths = fn_dijkstra.dijkstra(
141  graph,
142  combinations,
143  only_cost, n_goals);
144 
145  post_process(paths, only_cost, normal, n_goals, global);
146 
147  return paths;
148 }
149 } // namespace detail
150 
151 
152 // CREATE OR REPLACE FUNCTION pgr_dijkstra(
153 // sql text,
154 // start_vids anyarray,
155 // end_vids anyarray,
156 // directed boolean default true,
157 void
159  pgr_edge_t *data_edges,
160  size_t total_edges,
161  int64_t *start_vidsArr,
162  size_t size_start_vidsArr,
163  int64_t *end_vidsArr,
164  size_t size_end_vidsArr,
165  bool directed,
166  bool only_cost,
167  bool normal,
168  int64_t n_goals,
169  bool global,
170 
171  General_path_element_t **return_tuples,
172  size_t *return_count,
173  char ** log_msg,
174  char ** notice_msg,
175  char ** err_msg) {
176  std::ostringstream log;
177  std::ostringstream err;
178  std::ostringstream notice;
179 
180  try {
181  pgassert(total_edges != 0);
182  pgassert(!(*log_msg));
183  pgassert(!(*notice_msg));
184  pgassert(!(*err_msg));
185  pgassert(!(*return_tuples));
186  pgassert(*return_count == 0);
187 
188  graphType gType = directed? DIRECTED: UNDIRECTED;
189 
190  std::vector<int64_t>
191  start_vertices(start_vidsArr, start_vidsArr + size_start_vidsArr);
192  std::vector< int64_t >
193  end_vertices(end_vidsArr, end_vidsArr + size_end_vidsArr);
194 
195  size_t n = n_goals <= 0? (std::numeric_limits<size_t>::max)() : static_cast<size_t>(n_goals);
196 
197  std::deque< Path >paths;
198  if (directed) {
199  pgrouting::DirectedGraph digraph(gType);
200  digraph.insert_edges(data_edges, total_edges);
201  paths = detail::pgr_dijkstra(
202  digraph,
203  start_vertices, end_vertices,
204  only_cost, normal, n, global);
205  } else {
206  pgrouting::UndirectedGraph undigraph(gType);
207  undigraph.insert_edges(data_edges, total_edges);
208  paths = detail::pgr_dijkstra(
209  undigraph,
210  start_vertices, end_vertices,
211  only_cost, normal, n, global);
212  }
213 
214  size_t count(0);
215  count = count_tuples(paths);
216 
217  if (count == 0) {
218  (*return_tuples) = NULL;
219  (*return_count) = 0;
220  notice <<
221  "No paths found";
222  *log_msg = pgr_msg(notice.str().c_str());
223  return;
224  }
225 
226  (*return_tuples) = pgr_alloc(count, (*return_tuples));
227  (*return_count) = (collapse_paths(return_tuples, paths));
228 
229  *log_msg = log.str().empty()?
230  *log_msg :
231  pgr_msg(log.str().c_str());
232  *notice_msg = notice.str().empty()?
233  *notice_msg :
234  pgr_msg(notice.str().c_str());
235  } catch (AssertFailedException &except) {
236  (*return_tuples) = pgr_free(*return_tuples);
237  (*return_count) = 0;
238  err << except.what();
239  *err_msg = pgr_msg(err.str().c_str());
240  *log_msg = pgr_msg(log.str().c_str());
241  } catch (std::exception &except) {
242  (*return_tuples) = pgr_free(*return_tuples);
243  (*return_count) = 0;
244  err << except.what();
245  *err_msg = pgr_msg(err.str().c_str());
246  *log_msg = pgr_msg(log.str().c_str());
247  } catch(...) {
248  (*return_tuples) = pgr_free(*return_tuples);
249  (*return_count) = 0;
250  err << "Caught unknown exception!";
251  *err_msg = pgr_msg(err.str().c_str());
252  *log_msg = pgr_msg(log.str().c_str());
253  }
254 }
255 
256 
257 // CREATE OR REPLACE FUNCTION pgr_dijkstra(
258 // sql text,
259 // combinations sql text,
260 // directed boolean default true,
261 void
263  pgr_edge_t *data_edges,
264  size_t total_edges,
265  pgr_combination_t *combinations,
266  size_t total_combinations,
267  bool directed,
268  bool only_cost,
269  bool normal,
270  int64_t n_goals,
271  bool global,
272 
273  General_path_element_t **return_tuples,
274  size_t *return_count,
275  char ** log_msg,
276  char ** notice_msg,
277  char ** err_msg) {
278  std::ostringstream log;
279  std::ostringstream err;
280  std::ostringstream notice;
281 
282  try {
283  pgassert(total_edges != 0);
284  pgassert(total_combinations != 0);
285  pgassert(!(*log_msg));
286  pgassert(!(*notice_msg));
287  pgassert(!(*err_msg));
288  pgassert(!(*return_tuples));
289  pgassert(*return_count == 0);
290 
291  graphType gType = directed? DIRECTED: UNDIRECTED;
292 
293 
294  std::vector<pgr_combination_t>
295  combinations_vector(combinations, combinations + total_combinations);
296 
297  size_t n = n_goals <= 0? (std::numeric_limits<size_t>::max)() : static_cast<size_t>(n_goals);
298 
299  std::deque< Path >paths;
300  if (directed) {
301  pgrouting::DirectedGraph digraph(gType);
302  digraph.insert_edges(data_edges, total_edges);
303  paths = detail::pgr_dijkstra(
304  digraph,
305  combinations_vector,
306  only_cost, normal, n, global);
307  } else {
308  pgrouting::UndirectedGraph undigraph(gType);
309  undigraph.insert_edges(data_edges, total_edges);
310  paths = detail::pgr_dijkstra(
311  undigraph,
312  combinations_vector,
313  only_cost, normal, n, global);
314  }
315  combinations_vector.clear();
316  size_t count(0);
317  count = count_tuples(paths);
318 
319  if (count == 0) {
320  (*return_tuples) = NULL;
321  (*return_count) = 0;
322  notice << "No paths found";
323  *log_msg = pgr_msg(notice.str().c_str());
324  return;
325  }
326 
327  (*return_tuples) = pgr_alloc(count, (*return_tuples));
328  (*return_count) = (collapse_paths(return_tuples, paths));
329 
330  *log_msg = log.str().empty()?
331  *log_msg :
332  pgr_msg(log.str().c_str());
333  *notice_msg = notice.str().empty()?
334  *notice_msg :
335  pgr_msg(notice.str().c_str());
336  } catch (AssertFailedException &except) {
337  (*return_tuples) = pgr_free(*return_tuples);
338  (*return_count) = 0;
339  err << except.what();
340  *err_msg = pgr_msg(err.str().c_str());
341  *log_msg = pgr_msg(log.str().c_str());
342  } catch (std::exception &except) {
343  (*return_tuples) = pgr_free(*return_tuples);
344  (*return_count) = 0;
345  err << except.what();
346  *err_msg = pgr_msg(err.str().c_str());
347  *log_msg = pgr_msg(log.str().c_str());
348  } catch(...) {
349  (*return_tuples) = pgr_free(*return_tuples);
350  (*return_count) = 0;
351  err << "Caught unknown exception!";
352  *err_msg = pgr_msg(err.str().c_str());
353  *log_msg = pgr_msg(log.str().c_str());
354  }
355 }
356 
357 
Path
Definition: basePath_SSEC.hpp:47
pgr_alloc
T * pgr_alloc(std::size_t size, T *ptr)
allocates memory
Definition: pgr_alloc.hpp:66
count_tuples
size_t count_tuples(const std::deque< Path > &paths)
Definition: basePath_SSEC.cpp:387
detail::post_process
void post_process(std::deque< Path > &paths, bool only_cost, bool normal, size_t n_goals, bool global)
Definition: dijkstra_driver.cpp:51
pgr_edge_t
Definition: pgr_edge_t.h:37
pgr_msg
char * pgr_msg(const std::string &msg)
Definition: pgr_alloc.cpp:30
AssertFailedException::what
virtual const char * what() const
Definition: pgr_assert.cpp:67
pgr_combination_t.h
detail
Definition: dijkstra_driver.cpp:48
collapse_paths
size_t collapse_paths(General_path_element_t **ret_path, const std::deque< Path > &paths)
Definition: basePath_SSEC.cpp:310
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:94
do_pgr_many_to_many_dijkstra
void do_pgr_many_to_many_dijkstra(pgr_edge_t *data_edges, size_t total_edges, int64_t *start_vidsArr, size_t size_start_vidsArr, int64_t *end_vidsArr, size_t size_end_vidsArr, bool directed, bool only_cost, bool normal, int64_t n_goals, bool global, General_path_element_t **return_tuples, size_t *return_count, char **log_msg, char **notice_msg, char **err_msg)
Definition: dijkstra_driver.cpp:158
UNDIRECTED
@ UNDIRECTED
Definition: graph_enum.h:30
pgrouting::graph::Pgr_base_graph::insert_edges
void insert_edges(const T *edges, size_t count)
Inserts count edges of type T into the graph.
Definition: pgr_base_graph.hpp:357
pgr_alloc.hpp
detail::pgr_dijkstra
std::deque< Path > pgr_dijkstra(G &graph, std::vector< int64_t > sources, std::vector< int64_t > targets, bool only_cost, bool normal, size_t n_goals, bool global)
Definition: dijkstra_driver.cpp:100
pgr_combination_t
Definition: pgr_combination_t.h:43
do_pgr_combinations_dijkstra
void do_pgr_combinations_dijkstra(pgr_edge_t *data_edges, size_t total_edges, pgr_combination_t *combinations, size_t total_combinations, bool directed, bool only_cost, bool normal, int64_t n_goals, bool global, General_path_element_t **return_tuples, size_t *return_count, char **log_msg, char **notice_msg, char **err_msg)
Definition: dijkstra_driver.cpp:262
graphType
graphType
Definition: graph_enum.h:30
pgr_assert.h
An assert functionality that uses C++ throw().
pgr_dijkstra.hpp
DIRECTED
@ DIRECTED
Definition: graph_enum.h:30
General_path_element_t
Definition: general_path_element_t.h:37
pgrouting::alphashape::G
graph::Pgr_base_graph< BG, XY_vertex, Basic_edge > G
Definition: pgr_alphaShape.h:56
pgr_free
T * pgr_free(T *ptr)
Definition: pgr_alloc.hpp:77
pgrouting::graph::Pgr_base_graph
Definition: pgr_base_graph.hpp:168
dijkstra_driver.h
pgrouting::Pgr_dijkstra
Definition: pgr_dijkstra.hpp:62
AssertFailedException
Extends std::exception and is the exception that we throw if an assert fails.
Definition: pgr_assert.h:139
pgrouting::Pgr_dijkstra::dijkstra
Path dijkstra(G &graph, int64_t start_vertex, int64_t end_vertex, bool only_cost=false)
Dijkstra 1 to 1.
Definition: pgr_dijkstra.hpp:172
Path::recalculate_agg_cost
void recalculate_agg_cost()
Definition: basePath_SSEC.cpp:77