PGROUTING  3.2
pgr_mst.hpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 File: pgr_mst.hpp
3 
4 Copyright (c) 2018 Vicky Vergara
5 mail: vicky at georepublic dot de
6 
7 ------
8 
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23  ********************************************************************PGR-GNU*/
24 
25 #ifndef INCLUDE_SPANNINGTREE_PGR_MST_HPP_
26 #define INCLUDE_SPANNINGTREE_PGR_MST_HPP_
27 #pragma once
28 
32 #include <boost/graph/connected_components.hpp>
33 #include <boost/graph/filtered_graph.hpp>
34 
35 #include <set>
36 #include <utility>
37 #include <string>
38 #include <vector>
39 
42 #include "spanningTree/details.hpp"
43 
44 namespace pgrouting {
45 namespace functions {
46 
47 template <class G>
48 class Pgr_mst {
49  protected:
50  typedef typename G::B_G B_G;
51  typedef typename G::V V;
52  typedef typename G::E E;
53  typedef typename G::E_i E_i;
54 
55 
56  protected:
57  virtual void generate_mst(const G &graph) = 0;
58 
59  void clear() {
60  this->m_spanning_tree.clear();
61  this->m_components.clear();
62  this->m_tree_id.clear();
63  }
64 
65  std::vector<pgr_mst_rt>
66  no_order(const G &graph) {
67  return no_ordering(graph);
68  }
69 
70  std::vector<pgr_mst_rt>
71  dfs_order(const G &graph) {
72  return dfs_ordering(graph);
73  }
74 
75  std::vector<pgr_mst_rt>
76  bfs_order(const G &graph) {
77  return bfs_ordering(graph);
78  }
79 
80  std::vector<pgr_mst_rt> mst(const G &graph) {
81  m_suffix = "";
82  m_get_component = false;
83  m_distance = -1;
84  m_max_depth = -1;
85  m_roots.clear();
86 
87  no_neg_costs(graph);
88  this->generate_mst(graph);
89  return no_order(graph);
90  }
91 
92 
93  std::vector<pgr_mst_rt> mstBFS(
94  const G &graph,
95  std::vector<int64_t> roots,
96  int64_t max_depth) {
97  m_suffix = "BFS";
98  m_get_component = true;
99  m_distance = -1;
100  m_max_depth = max_depth;
101  m_roots = details::clean_vids(roots);
102 
103  this->generate_mst(graph);
104  return bfs_order(graph);
105  }
106 
107  std::vector<pgr_mst_rt> mstDFS(
108  const G &graph,
109  std::vector<int64_t> roots,
110  int64_t max_depth) {
111  m_suffix = "DFS";
112  m_get_component = false;
113  m_distance = -1;
114  m_max_depth = max_depth;
115  m_roots = details::clean_vids(roots);
116 
117  this->generate_mst(graph);
118  return dfs_order(graph);
119  }
120 
121  std::vector<pgr_mst_rt> mstDD(
122  const G &graph,
123  std::vector<int64_t> roots,
124  double distance) {
125  m_suffix = "DD";
126  m_get_component = false;
127  m_distance = distance;
128  m_max_depth = -1;
129  m_roots = details::clean_vids(roots);
130 
131  this->generate_mst(graph);
132  return dfs_order(graph);
133  }
134 
135  protected:
136  std::vector<int64_t> m_roots;
138  int64_t m_max_depth;
139  double m_distance;
140 
141  struct InSpanning {
142  std::set<E> edges;
143  bool operator()(E e) const { return edges.count(e); }
144  void clear() { edges.clear(); }
145  } m_spanning_tree;
146 
147 
152  std::vector<size_t> m_components;
153 
159  std::string m_suffix;
160 
166  std::vector<int64_t> m_tree_id;
167 
168  private:
169  template <typename T>
170  std::vector<pgr_mst_rt> get_results(
171  T order,
172  int64_t p_root,
173  const G &graph) {
174  std::vector<pgr_mst_rt> results;
175 
176  std::vector<double> agg_cost(graph.num_vertices(), 0);
177  std::vector<int64_t> depth(graph.num_vertices(), 0);
178  int64_t root(p_root);
179 
180  for (const auto edge : order) {
181  auto u = graph.source(edge);
182  auto v = graph.target(edge);
183  if (depth[u] == 0 && depth[v] != 0) {
184  std::swap(u, v);
185  }
186 
187  auto component = m_get_component? m_tree_id[m_components[u]] : 0;
188  if (m_suffix != "" && depth[u] == 0 && depth[v] == 0) {
189  if (!m_roots.empty() && graph[u].id != root) std::swap(u, v);
190  if (m_roots.empty() && graph[u].id != component) std::swap(u, v);
191  if (!p_root && graph[u].id > graph[v].id) std::swap(u, v);
192 
193  root = p_root? p_root: graph[u].id;
194  depth[u] = -1;
195  results.push_back({
196  root,
197  0,
198  graph[u].id,
199  -1,
200  0.0,
201  0.0 });
202  }
203 
204  agg_cost[v] = agg_cost[u] + graph[edge].cost;
205  depth[v] = depth[u] == -1? 1 : depth[u] + 1;
206 
207  if ((m_suffix == "")
208  || ((m_suffix == "BFS") && (m_max_depth >= depth[v]))
209  || ((m_suffix == "DFS") && m_max_depth >= depth[v])
210  || ((m_suffix == "DD") && m_distance >= agg_cost[v])) {
211  results.push_back({
212  root,
213  m_suffix != ""? depth[v] : 0,
214  graph[v].id,
215  graph[edge].id,
216  graph[edge].cost,
217  m_suffix != ""? agg_cost[v] : 0.0
218  });
219  }
220  }
221  return results;
222  }
223 
224 
225  void calculate_component(const G &graph) {
226  if (!m_get_component) return;
227 
228  m_components.resize(num_vertices(graph.graph));
229 
230  /*
231  * Calculate connected components
232  *
233  * Number of components of graph: num_comps components
234  */
235  auto num_comps = boost::connected_components(
236  graph.graph,
237  &m_components[0]);
238 
239  m_tree_id.resize(num_comps, 0);
240 
241  for (const auto v : boost::make_iterator_range(vertices(graph.graph))) {
242  m_tree_id[m_components[v]] =
243  (m_tree_id[m_components[v]] == 0
244  || m_tree_id[m_components[v]] >= graph[v].id) ?
245  graph[v].id : m_tree_id[m_components[v]];
246  }
247  }
248 
249  std::vector<pgr_mst_rt>
250  no_ordering(const G &graph) {
251  return get_results(m_spanning_tree.edges, 0, graph);
252  }
253 
254  std::vector<pgr_mst_rt>
255  dfs_forest(const G &graph) {
256  boost::filtered_graph<B_G, InSpanning, boost::keep_all>
257  mstGraph(graph.graph, m_spanning_tree, {});
258  std::vector<E> visited_order;
259 
260  using dfs_visitor = visitors::Edges_order_dfs_visitor<E>;
261  /* abort in case of an interruption occurs (e.g. the query is being cancelled) */
262  CHECK_FOR_INTERRUPTS();
263  try {
264  boost::depth_first_search(mstGraph, visitor(dfs_visitor(visited_order)));
265  } catch (boost::exception const& ex) {
266  (void)ex;
267  throw;
268  } catch (std::exception &e) {
269  (void)e;
270  throw;
271  } catch (...) {
272  throw;
273  }
274 
275  return get_results(visited_order, 0, graph);
276  }
277 
278 
279  std::vector<pgr_mst_rt>
280  dfs_ordering(const G &graph) {
281  boost::filtered_graph<B_G, InSpanning, boost::keep_all>
282  mstGraph(graph.graph, m_spanning_tree, {});
283 
284  if (m_roots.empty()) {
285  return dfs_forest(graph);
286  } else {
287  std::vector<pgr_mst_rt> results;
288  for (const auto root : m_roots) {
289  std::vector<E> visited_order;
290 
291  using dfs_visitor = visitors::Dfs_visitor_with_root<V, E>;
292  if (graph.has_vertex(root)) {
293  /* abort in case of an interruption occurs (e.g. the query is being cancelled) */
294  CHECK_FOR_INTERRUPTS();
295  try {
296  boost::depth_first_search(
297  mstGraph,
298  visitor(dfs_visitor(graph.get_V(root), visited_order))
299  .root_vertex(graph.get_V(root)));
300  } catch(found_goals &) {
301  {}
302  } catch (boost::exception const& ex) {
303  (void)ex;
304  throw;
305  } catch (std::exception &e) {
306  (void)e;
307  throw;
308  } catch (...) {
309  throw;
310  }
311  auto result = get_results(visited_order, root, graph);
312  results.insert(results.end(), result.begin(), result.end());
313  } else {
314  results.push_back({root, 0, root, -1, 0.0, 0.0});
315  }
316  }
317  return results;
318  }
319  }
320 
321  std::vector<pgr_mst_rt>
322  bfs_ordering(const G &graph) {
323  std::vector<pgr_mst_rt> results;
324  /*
325  * order by bfs
326  */
327  boost::filtered_graph<B_G, InSpanning, boost::keep_all>
328  mst(graph.graph, m_spanning_tree, {});
329 
330  calculate_component(graph);
331 
332  std::vector<int64_t> roots;
333  if (!m_roots.empty()) {
334  roots = m_roots;
335  } else {
336  roots = m_tree_id;
337  }
338 
339  using bfs_visitor = visitors::Edges_order_bfs_visitor<E>;
340  for (auto root : roots) {
341  std::vector<E> visited_order;
342  if (graph.has_vertex(root)) {
343  boost::breadth_first_search(mst,
344  graph.get_V(root),
345  visitor(bfs_visitor(visited_order)));
346 
347  auto tree_results = get_results(visited_order, root, graph);
348  results.insert(results.end(), tree_results.begin(), tree_results.end());
349  } else {
350  results.push_back({root, 0, root, -1, 0.0, 0.0});
351  }
352  /* abort in case of an interruption occurs (e.g. the query is being cancelled) */
353  CHECK_FOR_INTERRUPTS();
354  }
355 
356  return results;
357  }
358 
359  bool no_neg_costs(const G &graph) {
360  E_i ei, ei_end;
361  for (boost::tie(ei, ei_end) = edges(graph.graph); ei != ei_end; ++ei)
362  pgassert(graph[*ei].cost > 0);
363  return true;
364  }
365 };
366 
367 } // namespace functions
368 } // namespace pgrouting
369 
370 #endif // INCLUDE_SPANNINGTREE_PGR_MST_HPP_
pgrouting::visitors::Dfs_visitor_with_root
Definition: dfs_visitor_with_root.hpp:42
pgrouting::functions::Pgr_mst::m_roots
std::vector< int64_t > m_roots
Definition: pgr_mst.hpp:136
interruption.h
pgrouting::functions::Pgr_mst::m_spanning_tree
struct pgrouting::functions::Pgr_mst::InSpanning m_spanning_tree
pgrouting::functions::Pgr_mst::InSpanning
Definition: pgr_mst.hpp:141
pgr_base_graph.hpp
pgrouting::details::clean_vids
std::vector< int64_t > clean_vids(std::vector< int64_t > vids)
Definition: details.cpp:33
pgrouting::functions::Pgr_mst::m_max_depth
int64_t m_max_depth
Definition: pgr_mst.hpp:138
pgrouting::functions::Pgr_mst::InSpanning::clear
void clear()
Definition: pgr_mst.hpp:144
pgrouting::functions::Pgr_mst::m_get_component
bool m_get_component
Definition: pgr_mst.hpp:137
pgrouting::functions::Pgr_mst::bfs_ordering
std::vector< pgr_mst_rt > bfs_ordering(const G &graph)
Definition: pgr_mst.hpp:322
edge
Definition: trsp.h:41
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:94
pgrouting::functions::Pgr_mst::V
G::V V
Definition: pgr_mst.hpp:51
pgrouting::functions::Pgr_mst
Definition: pgr_mst.hpp:48
pgrouting::functions::Pgr_mst::get_results
std::vector< pgr_mst_rt > get_results(T order, int64_t p_root, const G &graph)
Definition: pgr_mst.hpp:170
pgrouting::functions::Pgr_mst::m_components
std::vector< size_t > m_components
m_components[v]:
Definition: pgr_mst.hpp:152
pgrouting::alphashape::E
boost::graph_traits< BG >::edge_descriptor E
Definition: pgr_alphaShape.h:57
pgrouting::functions::Pgr_mst::InSpanning::edges
std::set< E > edges
Definition: pgr_mst.hpp:142
pgrouting::functions::Pgr_mst::no_ordering
std::vector< pgr_mst_rt > no_ordering(const G &graph)
Definition: pgr_mst.hpp:250
dfs_visitor_with_root.hpp
pgrouting::functions::Pgr_mst::bfs_order
std::vector< pgr_mst_rt > bfs_order(const G &graph)
Definition: pgr_mst.hpp:76
pgrouting::functions::Pgr_mst::m_distance
double m_distance
Definition: pgr_mst.hpp:139
pgrouting::functions::Pgr_mst::E_i
G::E_i E_i
Definition: pgr_mst.hpp:53
pgrouting::functions::Pgr_mst::InSpanning::operator()
bool operator()(E e) const
Definition: pgr_mst.hpp:143
pgrouting::functions::Pgr_mst::no_neg_costs
bool no_neg_costs(const G &graph)
Definition: pgr_mst.hpp:359
pgrouting::functions::Pgr_mst::m_suffix
std::string m_suffix
Stores which function is being executed.
Definition: pgr_mst.hpp:159
pgrouting::functions::Pgr_mst::generate_mst
virtual void generate_mst(const G &graph)=0
pgrouting::functions::Pgr_mst::B_G
G::B_G B_G
Definition: pgr_mst.hpp:50
pgrouting::functions::Pgr_mst::mstBFS
std::vector< pgr_mst_rt > mstBFS(const G &graph, std::vector< int64_t > roots, int64_t max_depth)
Definition: pgr_mst.hpp:93
pgrouting::alphashape::G
graph::Pgr_base_graph< BG, XY_vertex, Basic_edge > G
Definition: pgr_alphaShape.h:56
edges_order_dfs_visitor.hpp
pgrouting::functions::Pgr_mst::clear
void clear()
Definition: pgr_mst.hpp:59
details.hpp
pgrouting::functions::Pgr_mst::m_tree_id
std::vector< int64_t > m_tree_id
m_tree_id[v]:
Definition: pgr_mst.hpp:166
pgrouting::functions::Pgr_mst::E
G::E E
Definition: pgr_mst.hpp:52
pgrouting::functions::Pgr_mst::dfs_order
std::vector< pgr_mst_rt > dfs_order(const G &graph)
Definition: pgr_mst.hpp:71
pgrouting::visitors::Edges_order_bfs_visitor
Definition: edges_order_bfs_visitor.hpp:41
pgrouting::found_goals
exception for visitor termination
Definition: found_goals.hpp:33
pgrouting::functions::Pgr_mst::dfs_ordering
std::vector< pgr_mst_rt > dfs_ordering(const G &graph)
Definition: pgr_mst.hpp:280
pgrouting::functions::Pgr_mst::mstDFS
std::vector< pgr_mst_rt > mstDFS(const G &graph, std::vector< int64_t > roots, int64_t max_depth)
Definition: pgr_mst.hpp:107
pgrouting::alphashape::V
boost::graph_traits< BG >::vertex_descriptor V
Definition: pgr_alphaShape.h:58
pgrouting::functions::Pgr_mst::calculate_component
void calculate_component(const G &graph)
Definition: pgr_mst.hpp:225
pgrouting::functions::Pgr_mst::no_order
std::vector< pgr_mst_rt > no_order(const G &graph)
Definition: pgr_mst.hpp:66
pgrouting::functions::Pgr_mst::dfs_forest
std::vector< pgr_mst_rt > dfs_forest(const G &graph)
Definition: pgr_mst.hpp:255
edges_order_bfs_visitor.hpp
pgrouting
Book keeping class for swapping orders between vehicles.
Definition: pgr_alphaShape.cpp:56
pgrouting::visitors::Edges_order_dfs_visitor
Definition: edges_order_dfs_visitor.hpp:42
pgrouting::functions::Pgr_mst::mstDD
std::vector< pgr_mst_rt > mstDD(const G &graph, std::vector< int64_t > roots, double distance)
Definition: pgr_mst.hpp:121
pgrouting::functions::Pgr_mst::mst
std::vector< pgr_mst_rt > mst(const G &graph)
Definition: pgr_mst.hpp:80