Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
GreedyBestFS.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 <functional>
11#include <alib/vector>
12#include <alib/pair>
13#include <alib/set>
14#include <alib/map>
15
18
19namespace graph {
20
21namespace shortest_path {
22
24// ---------------------------------------------------------------------------------------------------------------------
25
26 public:
27
46 template<
47 typename TGraph,
48 typename TNode,
49 typename F1 = std::function<typename TGraph::edge_type::weight_type(const TNode &)>,
50 typename F2 = std::function<void(const TNode &, const typename TGraph::edge_type::weight_type &)>>
51 static
52 ext::pair<ext::vector<TNode>, typename TGraph::edge_type::weight_type>
53 findPath(const TGraph &graph,
54 const TNode &start,
55 const TNode &goal,
56 F1 f_heuristic,
57 F2 f_user = [](const TNode &,
58 const typename TGraph::edge_type::weight_type &) {});
59
60 template<
61 typename TGraph,
62 typename TNode,
63 typename F1 = std::function<typename TGraph::edge_type::weight_type(const TNode &, const TNode &)>
64 >
65 static
66 ext::pair<ext::vector<TNode>, typename TGraph::edge_type::weight_type>
68 const TNode &start,
69 const TNode &goal,
70 F1 f_heuristic) {
71 return findPath(graph, start, goal, [&](const TNode &n) { return f_heuristic(goal, n); });
72 }
73
74// =====================================================================================================================
75
76 private:
77
78 template<typename TNode, typename TWeight>
79 struct Data {
80 ext::set<ext::pair<TWeight, TNode>> queue; // priority queue
81 ext::map<TNode, TWeight> g; // G score
82 ext::map<TNode, TNode> p; // parents
83 };
84
85// ---------------------------------------------------------------------------------------------------------------------
86
87 template<typename FEdges, typename TNode, typename TWeight, typename F1, typename F2, typename F3>
88 static bool relaxation(FEdges successor_edges,
89 Data<TNode, TWeight> &data,
90 F1 f_heuristic,
91 F2 f_user,
92 F3 f_stop);
93
94// ---------------------------------------------------------------------------------------------------------------------
95
96 template<typename TNode, typename TWeight, typename F>
97 inline static void init(GreedyBestFS::Data<TNode, TWeight> &data, const TNode &start, F f_heuristic);
98
99// ---------------------------------------------------------------------------------------------------------------------
100
101};
102
103// =====================================================================================================================
104
105template<typename TGraph, typename TNode, typename F1, typename F2>
106ext::pair<ext::vector<TNode>, typename TGraph::edge_type::weight_type>
108 const TNode &start,
109 const TNode &goal,
110 F1 f_heuristic,
111 F2 f_user) {
112 using weight_type = typename TGraph::edge_type::weight_type;
113
114 Data<TNode, weight_type> data;
115
116 // Init search
117 init(data, start, f_heuristic);
118
119 while (!data.queue.empty()) {
120 bool stop = relaxation([&](const auto &node) -> auto { return graph.successorEdges(node); },
121 data,
122 f_heuristic,
123 f_user,
124 [&goal](const TNode &n) -> bool { return goal == n; });
125
126 if (stop) {
127 break;
128 }
129 }
130
131 return common::ReconstructPath::reconstructWeightedPath(data.p, data.g, start, goal);
132}
133
134// ---------------------------------------------------------------------------------------------------------------------
135
136template<typename FEdges, typename TNode, typename TWeight, typename F1, typename F2, typename F3>
137bool
138GreedyBestFS::relaxation(FEdges successor_edges,
139 GreedyBestFS::Data<TNode, TWeight> &data,
140 F1 f_heuristic,
141 F2 f_user,
142 F3 f_stop) {
143 TNode n = data.queue.begin()->second;
144 data.queue.erase(data.queue.begin());
145
146 // Run user's function
147 f_user(n, data.g[n]);
148
149 // Stop if reach the goal
150 if (f_stop(n)) {
151 return true;
152 }
153
154 for (const auto &s_edge: successor_edges(n)) {
155 const TNode &s = common::SupportFunction::other(s_edge, n); // successor
156
157 // Check for negative edge
158 if (s_edge.weight() < 0) {
159 throw std::out_of_range("GreedyBestFS: Detect negative weight on edge in graph.");
160 }
161
162 // Calculate new G score
163 TWeight gscore = data.g.at(n) + s_edge.weight();
164
165 // Search if the node s was already visited
166 auto search_g = data.g.find(s);
167
168 // If not or the G score can be improve do relaxation
169 if (search_g == data.g.end() || data.g.at(s) > gscore) {
170 data.g[s] = gscore;
171 data.p.insert_or_assign(s, n);
172 if (search_g == data.g.end()) {
173 data.queue.insert(ext::make_pair(f_heuristic(s), s));
174 }
175 }
176 }
177
178 return false;
179}
180
181// ---------------------------------------------------------------------------------------------------------------------
182
183template<typename TNode, typename TWeight, typename F>
184void GreedyBestFS::init(GreedyBestFS::Data<TNode, TWeight> &data, const TNode &start, F f_heuristic) {
185 data.g[start] = 0;
186 data.p.insert_or_assign(start, start);
187 data.queue.insert(ext::make_pair(f_heuristic(start), start));
188}
189
190// ---------------------------------------------------------------------------------------------------------------------
191
192} // namespace shortest_path
193
194} // namespace graph
195
Class extending the map class from the standard library. Original reason is to allow printing of the ...
Definition: map.hpp:48
Class extending the pair class from the standard library. Original reason is to allow printing of the...
Definition: pair.hpp:43
Definition: set.hpp:44
static ext::pair< ext::vector< TNode >, TWeight > reconstructWeightedPath(const ext::map< TNode, TNode > &p, const ext::map< TNode, TWeight > &g, const TNode &start, const TNode &goal)
Definition: ReconstructPath.hpp:132
static TNode const & other(const TEdge &e, const TNode &n)
Definition: GreedyBestFS.hpp:23
static ext::pair< ext::vector< TNode >, typename TGraph::edge_type::weight_type > findPath(const TGraph &graph, const TNode &start, const TNode &goal, F1 f_heuristic, F2 f_user=[](const TNode &, const typename TGraph::edge_type::weight_type &) {})
Definition: GreedyBestFS.hpp:107
static ext::pair< ext::vector< TNode >, typename TGraph::edge_type::weight_type > findPathRegistration(const TGraph &graph, const TNode &start, const TNode &goal, F1 f_heuristic)
Definition: GreedyBestFS.hpp:67
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
Definition: Node.cpp:11