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 <ahFunction.H>
48#include <ah-errors.H>
49#include <archeap.H>
50#include <tpl_find_path.H>
51#include <tpl_agraph.H>
53
54namespace Aleph
55{
56
94template <class GT,
95 class Distance = Dft_Dist<GT>,
96 template <typename, class> class Itor = Node_Arc_Iterator,
97 class SA = Dft_Show_Arc<GT>,
98 template <class, class, class> class HeapT = ArcHeap>
100 : public Shortest_Path_Base<GT, Distance, Itor, SA, HeapT>
101{
103
104 // Import types from base class
117
118 // Local cookie access macros
119#define DNassert(p) (static_cast<Node_Info*>(NODE_COOKIE(p)))
120#define TREENODE(p) (static_cast<Tree_Node_Info*>(NODE_COOKIE(p))->tree_node)
121#define ACC(p) (DNassert(p)->dist)
122#define HEAPNODE(p) (DNassert(p)->heap_node)
123#define PARENT(p) (DNassert(p)->ret_node)
124#define DAassert(p) (static_cast<Arc_Info*>(ARC_COOKIE(p)))
125#define ARC_DIST(p) (Distance()(p))
126#define TREEARC(p) (static_cast<Tree_Arc_Info*>(ARC_COOKIE(p))->tree_arc)
127#define POT(p) (DAassert(p)->pot)
128
129 // Import member variables from base
130 using Base::sa;
131 using Base::heap;
132 using Base::painted;
133 using Base::ptr_g;
134 using Base::s;
135
136public:
143 : Base(dist, __sa)
144 {
145 // empty
146 }
147
148 // Import public methods from base
150 using Base::is_painted;
152 using Base::get_graph;
153 using Base::get_distance;
154 using Base::get_min_path;
156
169 typename GT::Node*
170 compute_min_paths_tree(const GT& g, typename GT::Node* start, GT& tree)
171 {
172 ah_domain_error_if(start == nullptr) << "start node cannot be null";
173 ah_domain_error_if(g.get_num_nodes() == 0) << "graph is empty";
174
176
177 clear_graph(tree);
178
179 NODE_BITS(start).set_bit(Aleph::Spanning_Tree, true);
180 ACC(start) = 0;
181 auto ret = TREENODE(start) = tree.insert_node(start->get_info());
182 NODE_COOKIE(TREENODE(start)) = start;
183
184 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
185 {
186 auto arc = it.get_current_arc_ne();
187 POT(arc) = ARC_DIST(arc);
188 heap.put_arc(arc, it.get_tgt_node());
189 }
190
191 const auto& n = g.get_num_nodes();
192
193 while (tree.get_num_nodes() < n and not heap.is_empty())
194 {
195 auto garc = heap.get_min_arc();
197 continue;
198
199 auto gsrc = g.get_src_node(garc);
200 auto gtgt = g.get_tgt_node(garc);
201
204 continue;
205
206 ARC_BITS(garc).set_bit(Aleph::Spanning_Tree, true);
207
209 std::swap(gsrc, gtgt);
210
211 NODE_BITS(gtgt).set_bit(Aleph::Spanning_Tree, true);
212
213 auto ttgt = tree.insert_node(gtgt->get_info());
214 TREENODE(gtgt) = ttgt;
215 auto tsrc = TREENODE(gsrc);
216
217 auto tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
218 TREEARC(garc) = tarc;
219
220 ACC(gtgt) = this->checked_add(ACC(gsrc), ARC_DIST(garc));
221 const auto& acc = ACC(gtgt);
222
223 for (Itor<GT, SA> it(gtgt, sa); it.has_curr(); it.next_ne())
224 {
225 auto arc = it.get_current_arc_ne();
227 continue;
228
229 auto tgt = it.get_tgt_node();
231 continue;
232
233 POT(arc) = this->checked_add(acc, ARC_DIST(arc));
234 heap.put_arc(arc, tgt);
235 }
236 }
237
239
240 return ret;
241 }
242
255 typename GT::Node* start,
256 typename GT::Node* end,
257 GT& tree)
258 {
259 ah_domain_error_if(start == nullptr) << "start node cannot be null";
260 ah_domain_error_if(end == nullptr) << "end node cannot be null";
261 ah_domain_error_if(g.get_num_nodes() == 0) << "graph is empty";
262
264 clear_graph(tree);
265
266 NODE_BITS(start).set_bit(Aleph::Spanning_Tree, true);
267 ACC(start) = 0;
268 TREENODE(start) = tree.insert_node(start->get_info());
269 NODE_COOKIE(TREENODE(start)) = start;
270
271 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
272 {
273 auto arc = it.get_current_arc_ne();
274 POT(arc) = ARC_DIST(arc);
275 heap.put_arc(arc, it.get_tgt_node());
276 }
277
278 const auto& n = g.get_num_nodes();
279
280 while (tree.get_num_nodes() < n and not heap.is_empty())
281 {
282 auto garc = heap.get_min_arc();
284 continue;
285
286 auto gsrc = g.get_src_node(garc);
287 auto gtgt = g.get_tgt_node(garc);
288
291 continue;
292
293 ARC_BITS(garc).set_bit(Aleph::Spanning_Tree, true);
294
296 std::swap(gsrc, gtgt);
297
298 auto ttgt = tree.insert_node(gtgt->get_info());
299 TREENODE(gtgt) = ttgt;
300 NODE_BITS(gtgt).set_bit(Aleph::Spanning_Tree, true);
301
302 auto tarc = tree.insert_arc(TREENODE(gsrc), TREENODE(gtgt), garc->get_info());
303 TREEARC(garc) = tarc;
304
305 if (gtgt == end)
306 break;
307
308 ACC(gtgt) = this->checked_add(ACC(gsrc), ARC_DIST(garc));
309 const auto& acc = ACC(gtgt);
310
311 for (Itor<GT, SA> it(gtgt, sa); it.has_curr(); it.next_ne())
312 {
313 auto arc = it.get_current_arc_ne();
315 continue;
316
317 auto tgt = it.get_tgt_node();
319 continue;
320
321 POT(arc) = this->checked_add(acc, ARC_DIST(arc));
322 heap.put_arc(arc, tgt);
323 }
324 }
325
327 }
328
340 typename GT::Node* start,
341 typename GT::Node* end)
342 {
343 ah_domain_error_if(start == nullptr) << "start node cannot be null";
344 ah_domain_error_if(end == nullptr) << "end node cannot be null";
345 ah_domain_error_if(g.get_num_nodes() == 0) << "graph is empty";
346
347 bool ret_val = false;
348 this->template init<Initialize_Node, Initialize_Arc>(g, start);
349
350 NODE_BITS(start).set_bit(Aleph::Spanning_Tree, true);
351 ACC(start) = 0;
352
353 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
354 {
355 auto arc = it.get_current_arc_ne();
356 POT(arc) = ARC_DIST(arc);
357 heap.put_arc(arc, it.get_tgt_node());
358 }
359
360 const auto& n = g.get_num_nodes();
361 size_t tn = 1;
362
363 while (tn < n and not heap.is_empty())
364 {
365 auto garc = heap.get_min_arc();
367 continue;
368
369 auto src = g.get_src_node(garc);
370 auto tgt = g.get_tgt_node(garc);
371
374 continue;
375
376 ARC_BITS(garc).set_bit(Aleph::Spanning_Tree, true);
377
379 std::swap(src, tgt);
380
381 NODE_BITS(tgt).set_bit(Aleph::Spanning_Tree, true);
382 PARENT(tgt) = src;
383
384 ++tn;
385
386 if (tgt == end)
387 {
388 ret_val = true;
389 break;
390 }
391
392 ACC(tgt) = this->checked_add(ACC(src), ARC_DIST(garc));
393 const auto& acc = ACC(tgt);
394
395 for (Itor<GT, SA> it(tgt, sa); it.has_curr(); it.next_ne())
396 {
397 auto a = it.get_current_arc_ne();
399 continue;
400
401 auto t = it.get_tgt_node();
403 continue;
404
405 POT(a) = this->checked_add(acc, ARC_DIST(a));
406 heap.put_arc(a, t);
407 }
408 }
409
410 this->template uninit<Destroy_Node, Destroy_Arc>();
411 painted = true;
412
413 return ret_val;
414 }
415
424 void paint_min_paths_tree(const GT& g, typename GT::Node* start)
425 {
426 ah_domain_error_if(start == nullptr) << "start node cannot be null";
427 ah_domain_error_if(g.get_num_nodes() == 0) << "graph is empty";
428
429 this->template init<Initialize_Node, Initialize_Arc>(g, start);
430
431 NODE_BITS(start).set_bit(Aleph::Spanning_Tree, true);
432 ACC(start) = 0;
433
434 for (Itor<GT, SA> it(start, sa); it.has_curr(); it.next_ne())
435 {
436 auto arc = it.get_current_arc_ne();
437 POT(arc) = ARC_DIST(arc);
438 heap.put_arc(arc, it.get_tgt_node());
439 }
440
441 const auto& n = g.get_num_nodes();
442 size_t tn = 1;
443
444 while (tn < n and not heap.is_empty())
445 {
446 auto garc = heap.get_min_arc();
448 continue;
449
450 auto src = g.get_src_node(garc);
451 auto tgt = g.get_tgt_node(garc);
452
455 continue;
456
457 ARC_BITS(garc).set_bit(Aleph::Spanning_Tree, true);
458
460 std::swap(src, tgt);
461
462 NODE_BITS(tgt).set_bit(Aleph::Spanning_Tree, true);
463 PARENT(tgt) = src;
464
465 ++tn;
466
467 ACC(tgt) = this->checked_add(ACC(src), ARC_DIST(garc));
468 const auto& acc = ACC(tgt);
469
470 for (Itor<GT, SA> it(tgt, sa); it.has_curr(); it.next_ne())
471 {
472 auto a = it.get_current_arc_ne();
474 continue;
475
476 auto t = it.get_tgt_node();
478 continue;
479
480 POT(a) = this->checked_add(acc, ARC_DIST(a));
481 heap.put_arc(a, t);
482 }
483 }
484
485 this->template uninit<Destroy_Node, Destroy_Arc>();
486 painted = true;
487 }
488
503 typename GT::Node* start, typename GT::Node* end,
505 {
506 min_path.empty();
507 if (paint_partial_min_paths_tree(g, start, end))
508 return this->get_min_path(end, min_path);
509
510 return std::numeric_limits<typename Distance::Distance_Type>::max();
511 }
512
521 void operator()(const GT& g, typename GT::Node* s, GT& tree)
522 {
523 compute_min_paths_tree(g, s, tree);
524 }
525
528 typename GT::Node* s,
529 typename GT::Node* e,
530 Path<GT>& path)
531 {
532 return find_min_path(g, s, e, path);
533 }
534
535#undef DNassert
536#undef PARENT
537#undef TREENODE
538#undef ACC
539#undef HEAPNODE
540#undef DAassert
541#undef ARC_DIST
542#undef TREEARC
543#undef POT
544};
545
546} // end namespace Aleph
547
548#endif // DIJKSTRA_H
#define PARENT(p)
Definition Dijkstra.H:123
#define TREENODE(p)
Definition Dijkstra.H:120
#define POT(p)
Definition Dijkstra.H:127
#define ACC(p)
Definition Dijkstra.H:121
#define ARC_DIST(p)
Definition Dijkstra.H:125
#define TREEARC(p)
Definition Dijkstra.H:126
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:522
Standard functor implementations and comparison objects.
Arc heap for graph algorithms.
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:101
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:521
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:424
Distance::Distance_Type operator()(const GT &g, typename GT::Node *s, typename GT::Node *e, Path< GT > &path)
Definition Dijkstra.H:527
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:170
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:502
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:254
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:339
Dijkstra_Min_Paths(Distance dist=Distance(), SA __sa=SA())
Constructor.
Definition Dijkstra.H:142
void empty() noexcept
empty the list
Definition htlist.H:1689
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
Path on a graph.
Definition tpl_graph.H:2669
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:494
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
#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:3549
#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
DynList< T > maps(const C &c, Op op)
Classic map operation.
Common utilities and base class for shortest path algorithms.
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1119
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.