Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Dijkstra.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
44#ifndef DIJKSTRA_H
45#define DIJKSTRA_H
46
47# include <ah-graph-concepts.H>
48
49#include <ahFunction.H>
50#include <ah-errors.H>
51#include <archeap.H>
52#include <tpl_find_path.H>
53#include <tpl_agraph.H>
55
56namespace Aleph
57{
58
96template <AlephGraph GT,
98 template <typename, class> class Itor = Node_Arc_Iterator,
100 template <class, class, class> class HeapT = ArcHeap>
102 : public Shortest_Path_Base<GT, Distance, Itor, SA, HeapT>
103{
105
106 // Import types from base class
119
120 // Local cookie access macros
121#define DNassert(p) (static_cast<Node_Info*>(NODE_COOKIE(p)))
122#define TREENODE(p) (static_cast<Tree_Node_Info*>(NODE_COOKIE(p))->tree_node)
123#define ACC(p) (DNassert(p)->dist)
124#define HEAPNODE(p) (DNassert(p)->heap_node)
125#define PARENT(p) (DNassert(p)->ret_node)
126#define DAassert(p) (static_cast<Arc_Info*>(ARC_COOKIE(p)))
127#define ARC_DIST(p) (Distance()(p))
128#define TREEARC(p) (static_cast<Tree_Arc_Info*>(ARC_COOKIE(p))->tree_arc)
129#define POT(p) (DAassert(p)->pot)
130
131 // Import member variables from base
132 using Base::sa;
133 using Base::heap;
134 using Base::painted;
135 using Base::ptr_g;
136 using Base::s;
137
138public:
145 : Base(dist, __sa)
146 {
147 // empty
148 }
149
150 // Import public methods from base
152 using Base::is_painted;
154 using Base::get_graph;
155 using Base::get_distance;
156 using Base::get_min_path;
158
171 typename GT::Node*
172 compute_min_paths_tree(const GT& g, typename GT::Node* start, GT& tree)
173 {
174 ah_domain_error_if(start == nullptr) << "start node cannot be null";
175 ah_domain_error_if(g.get_num_nodes() == 0) << "graph is empty";
176
178
179 clear_graph(tree);
180
181 NODE_BITS(start).set_bit(Aleph::Spanning_Tree, true);
182 ACC(start) = 0;
183 auto ret = TREENODE(start) = tree.insert_node(start->get_info());
184 NODE_COOKIE(TREENODE(start)) = start;
185
186 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
187 {
188 auto arc = it.get_current_arc_ne();
189 POT(arc) = ARC_DIST(arc);
190 heap.put_arc(arc, it.get_tgt_node());
191 }
192
193 const auto& n = g.get_num_nodes();
194
195 while (tree.get_num_nodes() < n and not heap.is_empty())
196 {
197 auto garc = heap.get_min_arc();
199 continue;
200
201 auto gsrc = g.get_src_node(garc);
202 auto gtgt = g.get_tgt_node(garc);
203
206 continue;
207
208 ARC_BITS(garc).set_bit(Aleph::Spanning_Tree, true);
209
211 std::swap(gsrc, gtgt);
212
213 NODE_BITS(gtgt).set_bit(Aleph::Spanning_Tree, true);
214
215 auto ttgt = tree.insert_node(gtgt->get_info());
216 TREENODE(gtgt) = ttgt;
217 auto tsrc = TREENODE(gsrc);
218
219 auto tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
220 TREEARC(garc) = tarc;
221
222 ACC(gtgt) = this->checked_add(ACC(gsrc), ARC_DIST(garc));
223 const auto& acc = ACC(gtgt);
224
225 for (Itor<GT, SA> it(gtgt, sa); it.has_curr(); it.next_ne())
226 {
227 auto arc = it.get_current_arc_ne();
229 continue;
230
231 auto tgt = it.get_tgt_node();
233 continue;
234
235 POT(arc) = this->checked_add(acc, ARC_DIST(arc));
236 heap.put_arc(arc, tgt);
237 }
238 }
239
241
242 return ret;
243 }
244
257 typename GT::Node* start,
258 typename GT::Node* end,
259 GT& tree)
260 {
261 ah_domain_error_if(start == nullptr) << "start node cannot be null";
262 ah_domain_error_if(end == nullptr) << "end node cannot be null";
263 ah_domain_error_if(g.get_num_nodes() == 0) << "graph is empty";
264
266 clear_graph(tree);
267
268 NODE_BITS(start).set_bit(Aleph::Spanning_Tree, true);
269 ACC(start) = 0;
270 TREENODE(start) = tree.insert_node(start->get_info());
271 NODE_COOKIE(TREENODE(start)) = start;
272
273 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
274 {
275 auto arc = it.get_current_arc_ne();
276 POT(arc) = ARC_DIST(arc);
277 heap.put_arc(arc, it.get_tgt_node());
278 }
279
280 const auto& n = g.get_num_nodes();
281
282 while (tree.get_num_nodes() < n and not heap.is_empty())
283 {
284 auto garc = heap.get_min_arc();
286 continue;
287
288 auto gsrc = g.get_src_node(garc);
289 auto gtgt = g.get_tgt_node(garc);
290
293 continue;
294
295 ARC_BITS(garc).set_bit(Aleph::Spanning_Tree, true);
296
298 std::swap(gsrc, gtgt);
299
300 auto ttgt = tree.insert_node(gtgt->get_info());
301 TREENODE(gtgt) = ttgt;
302 NODE_BITS(gtgt).set_bit(Aleph::Spanning_Tree, true);
303
304 auto tarc = tree.insert_arc(TREENODE(gsrc), TREENODE(gtgt), garc->get_info());
305 TREEARC(garc) = tarc;
306
307 if (gtgt == end)
308 break;
309
310 ACC(gtgt) = this->checked_add(ACC(gsrc), ARC_DIST(garc));
311 const auto& acc = ACC(gtgt);
312
313 for (Itor<GT, SA> it(gtgt, sa); it.has_curr(); it.next_ne())
314 {
315 auto arc = it.get_current_arc_ne();
317 continue;
318
319 auto tgt = it.get_tgt_node();
321 continue;
322
323 POT(arc) = this->checked_add(acc, ARC_DIST(arc));
324 heap.put_arc(arc, tgt);
325 }
326 }
327
329 }
330
342 typename GT::Node* start,
343 typename GT::Node* end)
344 {
345 ah_domain_error_if(start == nullptr) << "start node cannot be null";
346 ah_domain_error_if(end == nullptr) << "end node cannot be null";
347 ah_domain_error_if(g.get_num_nodes() == 0) << "graph is empty";
348
349 bool ret_val = false;
350 this->template init<Initialize_Node, Initialize_Arc>(g, start);
351
352 NODE_BITS(start).set_bit(Aleph::Spanning_Tree, true);
353 ACC(start) = 0;
354
355 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
356 {
357 auto arc = it.get_current_arc_ne();
358 POT(arc) = ARC_DIST(arc);
359 heap.put_arc(arc, it.get_tgt_node());
360 }
361
362 const auto& n = g.get_num_nodes();
363 size_t tn = 1;
364
365 while (tn < n and not heap.is_empty())
366 {
367 auto garc = heap.get_min_arc();
369 continue;
370
371 auto src = g.get_src_node(garc);
372 auto tgt = g.get_tgt_node(garc);
373
376 continue;
377
378 ARC_BITS(garc).set_bit(Aleph::Spanning_Tree, true);
379
381 std::swap(src, tgt);
382
383 NODE_BITS(tgt).set_bit(Aleph::Spanning_Tree, true);
384 PARENT(tgt) = src;
385
386 ++tn;
387
388 if (tgt == end)
389 {
390 ret_val = true;
391 break;
392 }
393
394 ACC(tgt) = this->checked_add(ACC(src), ARC_DIST(garc));
395 const auto& acc = ACC(tgt);
396
397 for (Itor<GT, SA> it(tgt, sa); it.has_curr(); it.next_ne())
398 {
399 auto a = it.get_current_arc_ne();
401 continue;
402
403 auto t = it.get_tgt_node();
405 continue;
406
407 POT(a) = this->checked_add(acc, ARC_DIST(a));
408 heap.put_arc(a, t);
409 }
410 }
411
412 this->template uninit<Destroy_Node, Destroy_Arc>();
413 painted = true;
414
415 return ret_val;
416 }
417
426 void paint_min_paths_tree(const GT& g, typename GT::Node* start)
427 {
428 ah_domain_error_if(start == nullptr) << "start node cannot be null";
429 ah_domain_error_if(g.get_num_nodes() == 0) << "graph is empty";
430
431 this->template init<Initialize_Node, Initialize_Arc>(g, start);
432
433 NODE_BITS(start).set_bit(Aleph::Spanning_Tree, true);
434 ACC(start) = 0;
435
436 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
437 {
438 auto arc = it.get_current_arc_ne();
439 POT(arc) = ARC_DIST(arc);
440 heap.put_arc(arc, it.get_tgt_node());
441 }
442
443 const auto& n = g.get_num_nodes();
444 size_t tn = 1;
445
446 while (tn < n and not heap.is_empty())
447 {
448 auto garc = heap.get_min_arc();
450 continue;
451
452 auto src = g.get_src_node(garc);
453 auto tgt = g.get_tgt_node(garc);
454
457 continue;
458
459 ARC_BITS(garc).set_bit(Aleph::Spanning_Tree, true);
460
462 std::swap(src, tgt);
463
464 NODE_BITS(tgt).set_bit(Aleph::Spanning_Tree, true);
465 PARENT(tgt) = src;
466
467 ++tn;
468
469 ACC(tgt) = this->checked_add(ACC(src), ARC_DIST(garc));
470 const auto& acc = ACC(tgt);
471
472 for (Itor<GT, SA> it(tgt, sa); it.has_curr(); it.next_ne())
473 {
474 auto a = it.get_current_arc_ne();
476 continue;
477
478 auto t = it.get_tgt_node();
480 continue;
481
482 POT(a) = this->checked_add(acc, ARC_DIST(a));
483 heap.put_arc(a, t);
484 }
485 }
486
487 this->template uninit<Destroy_Node, Destroy_Arc>();
488 painted = true;
489 }
490
505 typename GT::Node* start, typename GT::Node* end,
507 {
508 min_path.empty();
509 if (paint_partial_min_paths_tree(g, start, end))
510 return this->get_min_path(end, min_path);
511
512 return std::numeric_limits<typename Distance::Distance_Type>::max();
513 }
514
523 void operator()(const GT& g, typename GT::Node* s, GT& tree)
524 {
525 compute_min_paths_tree(g, s, tree);
526 }
527
530 typename GT::Node* s,
531 typename GT::Node* e,
532 Path<GT>& path)
533 {
534 return find_min_path(g, s, e, path);
535 }
536
537#undef DNassert
538#undef PARENT
539#undef TREENODE
540#undef ACC
541#undef HEAPNODE
542#undef DAassert
543#undef ARC_DIST
544#undef TREEARC
545#undef POT
546};
547
548} // end namespace Aleph
549
550#endif // DIJKSTRA_H
#define PARENT(p)
Definition Dijkstra.H:125
#define TREENODE(p)
Definition Dijkstra.H:122
#define POT(p)
Definition Dijkstra.H:129
#define ACC(p)
Definition Dijkstra.H:123
#define ARC_DIST(p)
Definition Dijkstra.H:127
#define TREEARC(p)
Definition Dijkstra.H:128
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
C++20 concepts for the protocol shared by graph algorithms.
Standard functor implementations and comparison objects.
Arc heap for graph algorithms.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
Default distance accessor for arc weights.
Spanning tree calculation of all shortest paths from a given node according to Dijkstra's algorithm.
Definition Dijkstra.H:103
void operator()(const GT &g, typename GT::Node *s, GT &tree)
Computes the spanning tree of all shortest paths from a given node according to Dijkstra's algorithm.
Definition Dijkstra.H:523
Distance::Distance_Type get_min_path(typename GT::Node *end, Path< GT > &path)
Extracts a shortest path to end from a previously painted graph.
void paint_min_paths_tree(const GT &g, typename GT::Node *start)
Paints on graph g the spanning tree of all shortest paths starting from start.
Definition Dijkstra.H:426
Distance::Distance_Type operator()(const GT &g, typename GT::Node *s, typename GT::Node *e, Path< GT > &path)
Definition Dijkstra.H:529
GT::Node * compute_min_paths_tree(const GT &g, typename GT::Node *start, GT &tree)
Computes the spanning tree of all shortest paths from the start node.
Definition Dijkstra.H:172
bool painted
Whether graph has been painted.
Distance::Distance_Type find_min_path(const GT &g, typename GT::Node *start, typename GT::Node *end, Path< GT > &min_path)
Computes the shortest path between start and end by painting the graph.
Definition Dijkstra.H:504
void compute_partial_min_paths_tree(const GT &g, typename GT::Node *start, typename GT::Node *end, GT &tree)
Computes the partial spanning tree of all shortest paths from start that contains the path from start...
Definition Dijkstra.H:256
bool paint_partial_min_paths_tree(const GT &g, typename GT::Node *start, typename GT::Node *end)
Paints on graph g the partial shortest paths tree starting from start and stopping when the end node ...
Definition Dijkstra.H:341
Dijkstra_Min_Paths(Distance dist=Distance(), SA __sa=SA())
Constructor.
Definition Dijkstra.H:144
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:525
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:605
Path on a graph.
Definition tpl_graph.H:2772
Base class providing common infrastructure for shortest path algorithms.
Distance::Distance_Type get_min_path(typename GT::Node *end, Path< GT > &path)
Extracts a shortest path to end from a previously painted graph.
Distance::Distance_Type copy_painted_min_paths_tree(GT &g, GT &tree)
Extracts the painted shortest paths tree and puts it in tree.
bool is_painted() const noexcept
Check if the graph has been painted.
bool has_computation() const noexcept
Check if a computation has been performed.
Distance::Distance_Type checked_add(const typename Distance::Distance_Type &a, const typename Distance::Distance_Type &b) const
Checked addition to prevent integer overflow.
GT * get_graph() const noexcept
Get the graph of the last computation.
Distance::Distance_Type get_distance(typename GT::Node *node)
Gets the accumulated distance to a node after painting.
GT::Node * get_start_node() const noexcept
Get the start node of the last computation.
GT * ptr_g
Pointer to the graph.
bool painted
Whether graph has been painted.
NodeInfo & get_info() noexcept
Return a modifiable reference to the data contained in the node.
Definition graph-dry.H:536
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:779
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:737
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:785
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
#define ARC_BITS(p)
Return the control bits of arc p.
#define NODE_COOKIE(p)
Return the node cookie
void clear_graph(GT &g) noexcept
Clean a graph: all its nodes and arcs are removed and freed.
Definition tpl_graph.H:3659
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
#define IS_ARC_VISITED(p, bit)
Determine whether the bit field is or not set to one.
#define NODE_BITS(p)
Get the control bits of a node.
@ Spanning_Tree
Definition aleph-graph.H:79
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
Common utilities and base class for shortest path algorithms.
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1001
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1120
Information stored in arc cookies for painting version.
Arc cleanup for painting version.
Node cleanup for painting version.
Arc cleanup and mapping for tree-building version.
Node cleanup and mapping for tree-building version.
Arc initialization for painting version.
Node initialization for painting version.
Arc initialization for tree-building version.
Node initialization for tree-building version.
Information stored in node cookies for painting version.
Extended arc info with tree arc mapping.
Extended node info with tree node mapping.
Distance accessor.
Array-based graph implementation.
Path finding algorithms in graphs.