Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
JarnikPrim.hpp
Go to the documentation of this file.
1
6// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
7
8#pragma once
9
10#include <alib/pair>
11#include <alib/set>
12#include <alib/map>
13
15
16namespace graph {
17
18namespace spanning_tree {
19
21// ---------------------------------------------------------------------------------------------------------------------
22 public:
23
24 template<typename TGraph, typename TNode>
25 static
26 TGraph
27 findSpanningTree(const TGraph &graph, const TNode &start);
28
29// =====================================================================================================================
30
31 private:
32
33 template<typename TNode, typename TWeight>
34 struct Data {
35 ext::set<ext::pair<TWeight, TNode>> queue; // priority queue
36 ext::map<TNode, TWeight> g; // distances (aka G score)
37 ext::map<TNode, TNode> p; // parents
38 };
39
40// ---------------------------------------------------------------------------------------------------------------------
41
42 template<typename TNode, typename TWeight>
43 inline static void init(JarnikPrim::Data<TNode, TWeight> &data, const TNode &start);
44
45};
46
47// =====================================================================================================================
48
49template<typename TGraph, typename TNode>
50TGraph JarnikPrim::findSpanningTree(const TGraph &graph, const TNode &start) {
51 using weight_type = typename TGraph::edge_type::weight_type;
52
53 TGraph res;
54 Data<TNode, weight_type> data;
55
56 // Init search
57 init(data, start);
58
59 while (!data.queue.empty()) {
60 TNode n = data.queue.begin()->second;
61 data.queue.erase(data.queue.begin());
62
63 // If not already in spanning tree add it
64 auto search = data.p.find(n);
65 if (search != data.p.end()) {
66 res.addEdge(search->second, n, data.g.at(n));
67 }
68
69 for (const auto &s_edge: graph.successorEdges(n)) {
70 const TNode &s = common::SupportFunction::other(s_edge, n); // successor
71
72 // Calculate new G score
73 weight_type gscore = s_edge.weight();
74
75 // Search if the node s was already visited
76 auto search_d = data.g.find(s);
77
78 // If not or the distance can be improve do relaxation
79 if (search_d == data.g.end() || search_d->second > gscore) {
80 // Search if the node s is in OPEN
81 auto search_q = data.queue.find(ext::make_pair(search_d->second, s));
82 if (search_q != data.queue.end()) {
83 // Erase node from priority queue
84 data.queue.erase(search_q);
85 }
86
87 data.g[s] = gscore;
88 data.p.insert_or_assign(s, n);
89 data.queue.insert(ext::make_pair(data.g[s], s));
90 }
91 }
92 }
93
94 return res;
95}
96
97// ---------------------------------------------------------------------------------------------------------------------
98
99template<typename TNode, typename TWeight>
100void JarnikPrim::init(JarnikPrim::Data<TNode, TWeight> &data, const TNode &start) {
101 data.g[start] = 0;
102 data.p.insert_or_assign(start, start);
103 data.queue.insert(ext::make_pair(data.g[start], start));
104}
105
106// ---------------------------------------------------------------------------------------------------------------------
107
108} // namespace spanning_tree
109
110} // namespace graph
111
Class extending the map class from the standard library. Original reason is to allow printing of the ...
Definition: map.hpp:48
Definition: set.hpp:44
static TNode const & other(const TEdge &e, const TNode &n)
Definition: JarnikPrim.hpp:20
static TGraph findSpanningTree(const TGraph &graph, const TNode &start)
Definition: JarnikPrim.hpp:50
return res
Definition: MinimizeByPartitioning.h:145
constexpr auto make_pair(T1 &&x, T2 &&y)
Definition: pair.hpp:79
Definition: ReconstructPath.hpp:14
void start(measurements::stealth_string name, measurements::Type type)
Definition: measurements.cpp:14