Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
IDDFS.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 <queue>
13#include <limits>
14#include <alib/set>
15#include <alib/map>
16
18
19namespace graph {
20
21namespace traverse {
22
23class IDDFS {
24// ---------------------------------------------------------------------------------------------------------------------
25
26 public:
27
39 template<
40 typename TGraph,
41 typename TNode,
42 typename F = std::function<bool(const TNode &, const size_t &)>>
43 static
44 void
45 run(const TGraph &graph,
46 const TNode &start,
47 unsigned long max_depth = std::numeric_limits<unsigned long>::max(),
48 F f_user = [](const TNode &, const size_t &) -> bool { return false; });
49
50// ---------------------------------------------------------------------------------------------------------------------
51
65 template<
66 typename TGraph,
67 typename TNode,
68 typename F = std::function<void(const TNode &, const size_t &)>>
69 static
71 findPath(const TGraph &graph,
72 const TNode &start,
73 const TNode &goal,
74 unsigned long max_depth = std::numeric_limits<unsigned long>::max(),
75 F f_user = [](const TNode &, const size_t &) {});
76
77 template<typename TGraph, typename TNode>
78 static
81 const TNode &start,
82 const TNode &goal) {
83 return findPath(graph, start, goal);
84
85 }
86
87// ---------------------------------------------------------------------------------------------------------------------
88
103 template<
104 typename TGraph,
105 typename TNode,
106 typename F = std::function<void(const TNode &, const size_t &)>>
107 static
109 findPathBidirectional(const TGraph &graph,
110 const TNode &start,
111 const TNode &goal,
112 unsigned long max_depth = std::numeric_limits<unsigned long>::max(),
113 F f_user = [](const TNode &, const size_t &) {});
114
115 template<typename TGraph, typename TNode>
116 static
119 const TNode &start,
120 const TNode &goal) {
121 return findPath(graph, start, goal);
122
123 }
124
125// =====================================================================================================================
126
127 private:
128
129// ---------------------------------------------------------------------------------------------------------------------
130
131 template<typename TNode>
132 struct Data {
133 ext::vector<TNode> path; // current path
134 ext::set<TNode> path_set; // current path set for quick search
135 ext::set<TNode> v; // visited
136 };
137
138// ---------------------------------------------------------------------------------------------------------------------
139
140 template<typename TGraph, typename TNode, typename F1, typename F2>
141 static
143 implNormal(const TGraph &graph,
144 const TNode &start,
145 unsigned long max_depth,
146 F1 f_user,
147 F2 f_stop);
148
149// ---------------------------------------------------------------------------------------------------------------------
150
151 template<typename FSucc, typename TNode, typename F1, typename F2>
152 static
153 bool
154 expansion(FSucc successors,
155 IDDFS::Data<TNode> &data,
156 const TNode &n,
157 bool save_nodes,
158 unsigned long max_depth,
159 F1 f_user,
160 F2 f_stop);
161
162// ---------------------------------------------------------------------------------------------------------------------
163
164 template<typename TGraph, typename TNode, typename F1, typename F2>
165 static
167 implBidirectional(const TGraph &graph,
168 const TNode &start,
169 const TNode &goal,
170 unsigned long max_depth,
171 F1 f_user,
172 F2 f_stop);
173
174// ---------------------------------------------------------------------------------------------------------------------
175
176 template<typename FSucc, typename TNode, typename F1, typename F2>
177 static
179 backward_expansion(FSucc successors,
180 const IDDFS::Data<TNode> &forward_data,
181 IDDFS::Data<TNode> &backward_data,
182 const TNode &node,
183 unsigned long max_depth,
184 F1 f_user,
185 F2 f_stop);
186
187// ---------------------------------------------------------------------------------------------------------------------
188
189 template<typename TGraph, typename TNode>
190 static
192 constructPath(const TGraph &graph,
193 const TNode &start,
194 const TNode &goal,
195 TNode intersection,
196 unsigned long max_forward_depth,
197 unsigned long max_backward_depth);
198
199// ---------------------------------------------------------------------------------------------------------------------
200
201 template<typename TNode>
202 inline static void init(IDDFS::Data<TNode> &data, const TNode &start);
203
204// ---------------------------------------------------------------------------------------------------------------------
205
206};
207
208// =====================================================================================================================
209
210template<typename TGraph, typename TNode, typename F>
211void IDDFS::run(const TGraph &graph, const TNode &start, unsigned long max_depth, F f_user) {
212 implNormal(graph, start, max_depth, f_user, [](const TNode &) -> bool { return false; });
213}
214
215// ---------------------------------------------------------------------------------------------------------------------
216
217template<typename TGraph, typename TNode, typename F>
219 const TNode &start,
220 const TNode &goal,
221 unsigned long max_depth,
222 F f_user) {
223 return implNormal(graph, start, max_depth,
224 [&](const TNode &n, const auto &d) -> bool {
225 f_user(n, d);
226 return false;
227 },
228 [&goal](const TNode &n) -> bool { return goal == n; });
229}
230
231// ---------------------------------------------------------------------------------------------------------------------
232
233template<typename TGraph, typename TNode, typename F>
235 const TNode &start,
236 const TNode &goal,
237 unsigned long max_depth,
238 F f_user) {
239 return implBidirectional(graph, start, goal, max_depth,
240 [&](const TNode &n, const auto &d) -> bool {
241 f_user(n, d);
242 return false;
243 },
244 [](const TNode &) -> bool { return false; });
245}
246
247// =====================================================================================================================
248
249// ---------------------------------------------------------------------------------------------------------------------
250
251template<typename TGraph, typename TNode, typename F1, typename F2>
252ext::vector<TNode> IDDFS::implNormal(const TGraph &graph,
253 const TNode &start,
254 unsigned long max_depth,
255 F1 f_user,
256 F2 f_stop) {
257 for (unsigned long i = 1; i < max_depth; ++i) {
258 Data<TNode> data;
259
260 // Init search
261 init(data, start);
262
263 bool stop =
264 expansion([&](const TNode &node) { return graph.successors(node); }, data, start, false, i, f_user, f_stop);
265
266 if (stop) {
267 return data.path;
268 }
269 }
270
271 return ext::vector<TNode>();
272}
273
274// ---------------------------------------------------------------------------------------------------------------------
275
276template<typename FSucc, typename TNode, typename F1, typename F2>
277bool IDDFS::expansion(FSucc successors,
278 IDDFS::Data<TNode> &data,
279 const TNode &n,
280 bool save_nodes,
281 unsigned long max_depth,
282 F1 f_user,
283 F2 f_stop) {
284 if (max_depth == 0) return false; // Continue with search
285 else if (save_nodes && max_depth == 1) {
286 data.v.insert(n); // Remember only the deepest nodes
287 }
288
289 // Run user's function
290 if (f_user(n, data.path.size())) {
291 return true; // Stop algorithm
292 }
293
294 // Stop if reach the goal
295 if (f_stop(n)) {
296 return true; // Stop algorithm
297 }
298
299 for (const auto &s : successors(n)) {
300
301 // Check if node is not in path
302 if (data.path_set.find(s) != data.path_set.end()) {
303 continue;
304 }
305
306 data.path.push_back(s); // Insert current node
307 data.path_set.insert(s);
308 bool stop = expansion(successors, data, s, save_nodes, max_depth - 1, f_user, f_stop);
309
310 if (stop) {
311 return true; // Stop algorithm
312 }
313
314 data.path.pop_back(); // Remove current node
315 data.path_set.erase(data.path_set.find(s));
316 }
317
318 return false; // Continue with search
319}
320
321// ---------------------------------------------------------------------------------------------------------------------
322
323template<typename TGraph, typename TNode, typename F1, typename F2>
324ext::vector<TNode> IDDFS::implBidirectional(const TGraph &graph,
325 const TNode &start,
326 const TNode &goal,
327 unsigned long max_depth,
328 F1 f_user,
329 F2 f_stop) {
330 for (unsigned long i = 1; i < max_depth; ++i) {
331 // -------------------------------
332 // Forward search
333 Data<TNode> forward_data;
334
335 // Init forward search
336 init(forward_data, start);
337
338 expansion([&](const TNode &n) { return graph.successors(n); }, forward_data, start, true, i, f_user, f_stop);
339
340 // -------------------------------
341 // Backward search
342
343 ext::set<TNode> intersection;
344
345 Data<TNode> backward_data;
346
347 // Init backward search
348 init(backward_data, goal);
349
350 intersection = backward_expansion([&](const TNode &node) { return graph.predecessors(node); },
351 forward_data,
352 backward_data,
353 goal,
354 i,
355 f_user,
356 f_stop); // even run
357
358 // If there is a intersection, then we can construct path
359 if (!intersection.empty()) {
360 return constructPath(graph, start, goal, *intersection.begin(), i, i);
361 }
362
363 // Init backward search
364 init(backward_data, goal);
365
366 intersection = backward_expansion([&](const TNode &node) { return graph.predecessors(node); },
367 forward_data,
368 backward_data,
369 goal,
370 i + 1,
371 f_user,
372 f_stop); // odd run
373
374 // If there is a intersection, then we can reconstruct path
375 if (!intersection.empty()) {
376 return constructPath(graph, start, goal, *intersection.begin(), i, i + 1);
377 }
378 }
379
380 return ext::vector<TNode>();
381}
382
383// ---------------------------------------------------------------------------------------------------------------------
384
385template<typename FSucc, typename TNode, typename F1, typename F2>
386ext::set<TNode> IDDFS::backward_expansion(FSucc successors,
387 const IDDFS::Data<TNode> &forward_data,
388 IDDFS::Data<TNode> &backward_data,
389 const TNode &node,
390 unsigned long max_depth,
391 F1 f_user,
392 F2 f_stop) {
393 expansion(successors, backward_data, node, true, max_depth, f_user, f_stop);
394
395 // Check for intersection
396 ext::set<TNode> intersection;
397 std::set_intersection(forward_data.v.begin(), forward_data.v.end(),
398 backward_data.v.begin(), backward_data.v.end(),
399 std::inserter(intersection, intersection.begin()));
400
401 return intersection;
402}
403
404// ---------------------------------------------------------------------------------------------------------------------
405
406template<typename TGraph, typename TNode>
407ext::vector<TNode> IDDFS::constructPath(const TGraph &graph,
408 const TNode &start,
409 const TNode &goal,
410 TNode intersection,
411 unsigned long max_forward_depth,
412 unsigned long max_backward_depth) {
413 Data<TNode> forward_data;
414 Data<TNode> backward_data;
415 init(forward_data, start);
416 init(backward_data, goal);
417
418 // Re-run forward search
419 expansion([&](const TNode &node) { return graph.successors(node); },
420 forward_data,
421 start,
422 false,
423 max_forward_depth,
424 [](const TNode &, const size_t &) -> bool { return false; },
425 [&](const TNode &n) -> bool { return n == intersection; }
426 );
427
428 // Re-run backward search
429 expansion([&](const TNode &node) { return graph.predecessors(node); },
430 backward_data,
431 goal,
432 false,
433 max_backward_depth,
434 [](const TNode &, const size_t &) -> bool { return false; },
435 [&](const TNode &n) -> bool { return n == intersection; }
436 );
437
438 return common::ReconstructPath::joinPath(forward_data.path, backward_data.path);
439}
440
441// ---------------------------------------------------------------------------------------------------------------------
442
443template<typename TNode>
444void IDDFS::init(IDDFS::Data<TNode> &data, const TNode &start) {
445 // Make sure that data are wiped
446 data.path.clear();
447 data.v.clear();
448
449 data.path.push_back(start);
450 data.path_set.insert(start);
451}
452
453// ---------------------------------------------------------------------------------------------------------------------
454
455} // namespace traverse
456
457} // namespace graph
458
Definition: set.hpp:44
auto begin() &
Inherited behavior of begin for non-const instance.
Definition: set.hpp:99
Class extending the vector class from the standard library. Original reason is to allow printing of t...
Definition: vector.hpp:45
static ext::vector< TNode > joinPath(ext::vector< TNode > &forward_path, const ext::vector< TNode > &backward_path)
Definition: ReconstructPath.hpp:163
Definition: IDDFS.hpp:23
static ext::vector< TNode > findPath(const TGraph &graph, const TNode &start, const TNode &goal, unsigned long max_depth=std::numeric_limits< unsigned long >::max(), F f_user=[](const TNode &, const size_t &) {})
Definition: IDDFS.hpp:218
static ext::vector< TNode > findPathBidirectionalRegistration(const TGraph &graph, const TNode &start, const TNode &goal)
Definition: IDDFS.hpp:118
static ext::vector< TNode > findPathRegistration(const TGraph &graph, const TNode &start, const TNode &goal)
Definition: IDDFS.hpp:80
static void run(const TGraph &graph, const TNode &start, unsigned long max_depth=std::numeric_limits< unsigned long >::max(), F f_user=[](const TNode &, const size_t &) -> bool { return false;})
Definition: IDDFS.hpp:211
static ext::vector< TNode > findPathBidirectional(const TGraph &graph, const TNode &start, const TNode &goal, unsigned long max_depth=std::numeric_limits< unsigned long >::max(), F f_user=[](const TNode &, const size_t &) {})
Definition: IDDFS.hpp:234
int i
Definition: AllEpsilonClosure.h:118
constexpr const T & max(const T &a)
Root case of maximum computation. The maximum from one value is the value itself.
Definition: algorithm.hpp:278
Definition: ReconstructPath.hpp:14
void start(measurements::stealth_string name, measurements::Type type)
Definition: measurements.cpp:14
Definition: Node.cpp:11