1 /*PGR-GNU*****************************************************************
2 File: pgr_depthFirstSearch.hpp
3 
4 Copyright (c) 2020 pgRouting developers
5 Mail: project@pgrouting.org
6 
7 Copyright (c) 2020 Ashish Kumar
8 Mail: ashishkr23438@gmail.com
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 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
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 ********************************************************************PGR-GNU*/
23 
24 #ifndef INCLUDE_TRAVERSAL_PGR_DEPTHFIRSTSEARCH_HPP_
25 #define INCLUDE_TRAVERSAL_PGR_DEPTHFIRSTSEARCH_HPP_
26 #pragma once
27 
28 
29 #include <visitors/dfs_visitor.hpp>
30 #include <boost/graph/depth_first_search.hpp>
31 #include <boost/graph/undirected_dfs.hpp>
32 
33 #include <vector>
34 #include <map>
35 
36 #include "cpp_common/pgr_base_graph.hpp"
37 #include "cpp_common/interruption.h"
38 
39 
40 /** @file pgr_depthFirstSearch.hpp
41  * @brief The main file which calls the respective boost function.
42  *
43  * Contains actual implementation of the function and the calling
44  * of the respective boost function.
45  */
46 
47 
48 namespace pgrouting {
49 namespace functions {
50 
51 //*************************************************************
52 
53 template < class G >
54 class Pgr_depthFirstSearch {
55  public:
56      typedef typename G::V V;
57      typedef typename G::E E;
58 
59      /** @name DepthFirstSearch
60       * @{
61       *
62       */
63 
64      /** @brief depthFirstSearch function
65       *
66       * It does all the processing and returns the results.
67       *
68       * @param graph      the graph containing the edges
69       * @param roots      the root vertices
70       * @param max_depth  the maximum depth of traversal
71       * @param directed   whether the graph is directed or undirected
72       *
73       * @returns results, when results are found
74       *
75       * @see [boost::depth_first_search]
76       * (https://www.boost.org/libs/graph/doc/depth_first_search.html)
77       * @see [boost::undirected_dfs]
78       * (https://www.boost.org/libs/graph/doc/undirected_dfs.html)
79       */
depthFirstSearch(G & graph,std::vector<int64_t> roots,bool directed,int64_t max_depth)80      std::vector < pgr_mst_rt > depthFirstSearch(
81              G &graph,
82              std::vector < int64_t > roots,
83              bool directed,
84              int64_t max_depth) {
85          std::vector < pgr_mst_rt > results;
86 
87          for (auto root : roots) {
88              std::vector < E > visited_order;
89              results.push_back({root, 0, root, -1, 0.0, 0.0});
90 
91              if (graph.has_vertex(root)) {
92                  auto v_root(graph.get_V(root));
93 
94                  depthFirstSearch_single_vertex(graph, v_root, visited_order, directed, max_depth);
95 
96                  auto result = get_results(visited_order, root, max_depth, graph);
97                  results.insert(results.end(), result.begin(), result.end());
98              }
99          }
100 
101          return results;
102      }
103 
104      //@}
105 
106  private:
107      /** @brief Calls the Boost function
108       *
109       * Calls [boost::depth_first_search]
110       * (https://www.boost.org/libs/graph/doc/depth_first_search.html)
111       * and [boost::undirected_dfs]
112       * (https://www.boost.org/libs/graph/doc/undirected_dfs.html)
113       * for directed graphs and undirected graphs, respectively.
114       *
115       * @param graph          the graph containing the edges
116       * @param root           the root vertex
117       * @param visited_order  vector which will contain the edges of the resulting traversal
118       * @param directed       whether the graph is directed or undirected
119       *
120       * @returns bool  @b true, when results are found
121       */
depthFirstSearch_single_vertex(G & graph,V root,std::vector<E> & visited_order,bool directed,int64_t max_depth)122      bool depthFirstSearch_single_vertex(
123                  G &graph,
124                  V root,
125                  std::vector < E > &visited_order,
126                  bool directed,
127                  int64_t max_depth) {
128          using dfs_visitor = visitors::Dfs_visitor < V, E, G >;
129 
130          // Exterior property storage containers
131          std::vector < boost::default_color_type > colors(boost::num_vertices(graph.graph));
132          std::map < E, boost::default_color_type > edge_color;
133 
134          auto i_map = boost::get(boost::vertex_index, graph.graph);
135 
136          // Iterator property maps which record the color of each vertex and edge, respectively
137          auto vertex_color_map = boost::make_iterator_property_map(colors.begin(), i_map);
138          auto edge_color_map = boost::make_assoc_property_map(edge_color);
139 
140          auto vis =  dfs_visitor(root, visited_order, max_depth, colors, graph);
141 
142          /* abort in case of an interruption occurs (e.g. the query is being cancelled) */
143          CHECK_FOR_INTERRUPTS();
144 
145          try {
146              if (directed) {
147                  boost::depth_first_search(graph.graph, vis, vertex_color_map, root);
148              } else {
149                  boost::undirected_dfs(graph.graph, vis, vertex_color_map, edge_color_map, root);
150              }
151          } catch(found_goals &) {
152              {}
153          } catch (boost::exception const& ex) {
154              (void)ex;
155              throw;
156          } catch (std::exception &e) {
157              (void)e;
158              throw;
159          } catch (...) {
160              throw;
161          }
162          return true;
163      }
164 
165      /** @brief to get the results
166       *
167       * Uses the `visited_order` of vertices to get the results.
168       * Selects only those nodes in the final result whose
169       * depth is less than the `max_depth`.
170       *
171       * @param visited_order  vector which contains the edges of the resulting traversal
172       * @param root           the root vertex
173       * @param max_depth      the maximum depth of traversal
174       * @param graph          the graph containing the edges
175       *
176       * @returns `results` vector
177       */
178      template < typename T >
get_results(T visited_order,int64_t root,int64_t max_depth,const G & graph)179      std::vector < pgr_mst_rt > get_results(
180              T visited_order,
181              int64_t root,
182              int64_t max_depth,
183              const G &graph) {
184          std::vector < pgr_mst_rt > results;
185 
186          std::vector < double > agg_cost(graph.num_vertices(), 0);
187          std::vector < int64_t > depth(graph.num_vertices(), 0);
188 
189          for (const auto edge : visited_order) {
190              auto u = graph.source(edge);
191              auto v = graph.target(edge);
192 
193              agg_cost[v] = agg_cost[u] + graph[edge].cost;
194              depth[v] = depth[u] + 1;
195 
196              if (max_depth >= depth[v]) {
197                  results.push_back({
198                      root,
199                      depth[v],
200                      graph[v].id,
201                      graph[edge].id,
202                      graph[edge].cost,
203                      agg_cost[v]
204                  });
205              }
206          }
207          return results;
208      }
209 };
210 }  // namespace functions
211 }  // namespace pgrouting
212 
213 #endif  // INCLUDE_TRAVERSAL_PGR_DEPTHFIRSTSEARCH_HPP_
214