/*PGR-GNU***************************************************************** File: pgr_prim.hpp Copyright (c) 2018 pgRouting developers Mail: project@pgrouting.org Copyright (c) 2018 Aditya Pratap Singh adityapratap.singh28@gmail.com ------ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ********************************************************************PGR-GNU*/ #ifndef INCLUDE_SPANNINGTREE_PGR_PRIM_HPP_ #define INCLUDE_SPANNINGTREE_PGR_PRIM_HPP_ #pragma once #include #include #include #include #include "spanningTree/pgr_mst.hpp" #include "cpp_common/interruption.h" //****************************************** namespace pgrouting { namespace functions { template class Pgr_prim : public Pgr_mst { typedef typename G::V V; typedef typename G::E E; typedef typename G::B_G B_G; public: std::vector prim(G &graph); std::vector primBFS( G &graph, std::vector roots, int64_t max_depth); std::vector primDFS( G &graph, std::vector roots, int64_t max_depth); std::vector primDD( G &graph, std::vector roots, double distance); private: // Functions void clear() { data.clear(); predecessors.clear(); distances.clear(); } void primTree( const G &graph, int64_t root_vertex); void generate_mst(const G &graph); private: // Member std::vector predecessors; std::vector distances; std::vector data; std::set m_unassigned; }; template void Pgr_prim::primTree( const G &graph, int64_t root_vertex) { clear(); predecessors.resize(graph.num_vertices()); distances.resize(graph.num_vertices()); auto v_root(graph.get_V(root_vertex)); using prim_visitor = visitors::Prim_dijkstra_visitor; /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ CHECK_FOR_INTERRUPTS(); boost::prim_minimum_spanning_tree( graph.graph, &predecessors[0], boost::distance_map(&distances[0]). weight_map(get(&G::G_T_E::cost, graph.graph)) .root_vertex(v_root) .visitor(prim_visitor(data))); for (const auto v : data) { /* * its not a tree, its a forest * - v is not on current tree */ if (std::isinf(distances[v])) continue; m_unassigned.erase(v); auto u = predecessors[v]; /* * Not a valid edge */ if (u == v) continue; auto cost = distances[u] - distances[v]; auto edge = graph.get_edge(u, v, cost); this->m_spanning_tree.edges.insert(edge); } } template void Pgr_prim::generate_mst(const G &graph) { this->clear(); size_t totalNodes = num_vertices(graph.graph); m_unassigned.clear(); for (V v = 0; v < totalNodes; ++v) { m_unassigned.insert(m_unassigned.end(), v); } while (!m_unassigned.empty()) { auto root = *m_unassigned.begin(); m_unassigned.erase(m_unassigned.begin()); primTree( graph, graph.graph[root].id); } } template std::vector Pgr_prim::prim( G &graph) { return this->mst(graph); } template std::vector Pgr_prim::primBFS( G &graph, std::vector roots, int64_t max_depth) { return this->mstBFS(graph, roots, max_depth); } template std::vector Pgr_prim::primDFS( G &graph, std::vector roots, int64_t max_depth) { return this->mstDFS(graph, roots, max_depth); } template std::vector Pgr_prim::primDD( G &graph, std::vector roots, double distance) { return this->mstDD(graph, roots, distance); } } // namespace functions } // namespace pgrouting #endif // INCLUDE_SPANNINGTREE_PGR_PRIM_HPP_