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