Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
shortest_path_common.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
48#ifndef SHORTEST_PATH_COMMON_H
49#define SHORTEST_PATH_COMMON_H
50
51#include <limits>
52#include <type_traits>
53#include <ah-errors.H>
54#include <tpl_graph.H>
55#include <tpl_find_path.H>
56
57namespace Aleph
58{
59
60// =============================================================================
61// Cookie Access Macros (internal use)
62// =============================================================================
63
64// These macros provide unified access to node/arc cookies across algorithms
65
67#define SP_NODE_INFO(p) (static_cast<typename Shortest_Path_Base::Node_Info*>(NODE_COOKIE(p)))
68
70#define SP_TREE_NODE_INFO(p) (static_cast<typename Shortest_Path_Base::Tree_Node_Info*>(NODE_COOKIE(p)))
71
73#define SP_ACC(p) (SP_NODE_INFO(p)->dist)
74
76#define SP_HEAPNODE(p) (SP_NODE_INFO(p)->heap_node)
77
79#define SP_PARENT(p) (SP_NODE_INFO(p)->ret_node)
80
82#define SP_TREENODE(p) (SP_TREE_NODE_INFO(p)->tree_node)
83
85#define SP_ARC_INFO(p) (static_cast<typename Shortest_Path_Base::Arc_Info*>(ARC_COOKIE(p)))
86
88#define SP_TREE_ARC_INFO(p) (static_cast<typename Shortest_Path_Base::Tree_Arc_Info*>(ARC_COOKIE(p)))
89
91#define SP_POT(p) (SP_ARC_INFO(p)->pot)
92
94#define SP_TREEARC(p) (SP_TREE_ARC_INFO(p)->tree_arc)
95
97#define SP_ARC_DIST(p) (Distance()(p))
98
99
100// =============================================================================
101// Overflow-Checked Arithmetic
102// =============================================================================
103
105namespace shortest_path_detail
106{
107
119template <typename T>
120[[nodiscard]] inline T checked_add(const T& a, const T& b)
121{
122 if constexpr (std::is_integral_v<T>)
123 {
124 ah_overflow_error_if(b > 0 and a > std::numeric_limits<T>::max() - b)
125 << "Integer overflow in distance addition: " << a << " + " << b;
126
127 ah_overflow_error_if(b < 0 and a < std::numeric_limits<T>::min() - b)
128 << "Integer underflow in distance addition: " << a << " + " << b;
129 }
130
131 return a + b;
132}
133
134} // namespace shortest_path_detail
135
136
137// =============================================================================
138// Base Class for Shortest Path Algorithms
139// =============================================================================
140
159template <class GT,
160 class Distance,
161 template <typename, class> class Itor,
162 class SA,
163 template <class, class, class> class HeapT>
165{
166public:
167 // =========================================================================
168 // Cookie Structures
169 // =========================================================================
170
177 struct Arc_Info
178 {
180 };
181
186 struct Tree_Arc_Info : public Arc_Info
187 {
188 typename GT::Arc* tree_arc = nullptr;
189 };
190
197 {
199 void* heap_node = nullptr;
200 void* ret_node = nullptr;
201 };
202
207 struct Tree_Node_Info : public Node_Info
208 {
209 typename GT::Node* tree_node = nullptr;
210 };
211
212 // =========================================================================
213 // Heap Access Functor
214 // =========================================================================
215
218 {
219 void*& operator()(typename GT::Node* p) const noexcept
220 {
221 return SP_HEAPNODE(p);
222 }
223 };
224
225 // =========================================================================
226 // Get Potential Functor
227 // =========================================================================
228
231 {
232 Get_Potential_Arc() = default;
233
235
237 operator()(typename GT::Arc* a) const noexcept
238 {
239 return SP_POT(a);
240 }
241 };
242
243 // =========================================================================
244 // Initialize Functors
245 // =========================================================================
246
249 {
250 void operator()(const GT& g, typename GT::Node* p) const
251 {
253 NODE_COOKIE(p) = new Node_Info;
254 }
255 };
256
259 {
260 void operator()(const GT& g, typename GT::Arc* a) const
261 {
263 ARC_COOKIE(a) = new Arc_Info;
264 SP_POT(a) = 0;
265 }
266 };
267
270 {
271 void operator()(const GT& g, typename GT::Node* p) const
272 {
275 }
276 };
277
280 {
281 void operator()(const GT& g, typename GT::Arc* a) const
282 {
284 ARC_COOKIE(a) = new Tree_Arc_Info;
285 SP_POT(a) = 0;
286 SP_TREEARC(a) = nullptr;
287 }
288 };
289
290 // =========================================================================
291 // Destroy Functors
292 // =========================================================================
293
296 {
297 void operator()(const GT&, typename GT::Node* p) const noexcept
298 {
299 void* tmp = SP_PARENT(p);
300 delete SP_NODE_INFO(p);
301 NODE_COOKIE(p) = tmp;
302 }
303 };
304
307 {
308 void operator()(const GT&, typename GT::Arc* ga) const noexcept
309 {
310 delete SP_ARC_INFO(ga);
311 }
312 };
313
316 {
317 void operator()(const GT&, typename GT::Node* p) const noexcept
318 {
319 auto aux = SP_TREE_NODE_INFO(p);
320 auto tp = SP_TREENODE(p);
321 if (tp != nullptr)
322 {
323 NODE_COOKIE(p) = NODE_COOKIE(tp) = nullptr;
324 GT::map_nodes(p, tp);
325 }
326 else
327 NODE_COOKIE(p) = nullptr;
328
329 delete aux;
330 }
331 };
332
335 {
336 void operator()(const GT&, typename GT::Arc* ga) const noexcept
337 {
338 auto aux = SP_TREE_ARC_INFO(ga);
339 typename GT::Arc* ta = SP_TREEARC(ga);
340 if (ta != nullptr)
341 {
344 }
345
346 delete aux;
347 }
348 };
349
350 // =========================================================================
351 // Type Aliases
352 // =========================================================================
353
355
356protected:
357 // =========================================================================
358 // Member Variables
359 // =========================================================================
360
364 bool painted = false;
365 GT* ptr_g = nullptr;
366 typename GT::Node* s = nullptr;
367
368 // =========================================================================
369 // Protected Methods
370 // =========================================================================
371
379 template <class IN, class IA>
380 void init(const GT& g, typename GT::Node* start)
381 {
382 heap.empty();
383
384 ptr_g = &const_cast<GT&>(g);
385 s = start;
386
389 }
390
396 template <class DN, class DA>
397 void uninit()
398 {
399 // Clear heap first to avoid use-after-free when heap destructor
400 // tries to compare arcs whose cookies have been freed
401 heap.empty();
402
403 Operate_On_Nodes<GT, DN>()(*ptr_g);
405 }
406
416 const typename Distance::Distance_Type& b) const
417 {
419 }
420
421public:
422 // =========================================================================
423 // Constructors
424 // =========================================================================
425
432 : sa(__sa), get_pot(dist), heap(get_pot, Heap_Info()),
434 {
435 // empty
436 }
437
438 // =========================================================================
439 // State Getters
440 // =========================================================================
441
445 [[nodiscard]] bool has_computation() const noexcept { return ptr_g != nullptr; }
446
451
455 [[nodiscard]] typename GT::Node* get_start_node() const noexcept { return s; }
456
461
462 // =========================================================================
463 // Distance Calculation
464 // =========================================================================
465
480 get_distance(typename GT::Node* node)
481 {
482 ah_domain_error_if(not painted) << "Graph has not been painted";
483 ah_domain_error_if(node == nullptr) << "node cannot be null";
484
485 if (node == s)
486 return 0;
487
489 << "node is not reachable from start";
490
491 typename Distance::Distance_Type total = 0;
492
493 for (auto curr = node; curr != s;)
494 {
495 auto parent = static_cast<typename GT::Node*>(NODE_COOKIE(curr));
496 if (parent == nullptr)
497 break;
498
499 for (Itor<GT, SA> it(parent, sa); it.has_curr(); it.next_ne())
500 {
501 auto arc = it.get_current_arc_ne();
502 auto tgt = it.get_tgt_node();
503 if (tgt == curr and IS_ARC_VISITED(arc, Aleph::Spanning_Tree))
504 {
505 total += Distance()(arc);
506 break;
507 }
508 }
509 curr = parent;
510 }
511
512 return total;
513 }
514
515 // =========================================================================
516 // Path Extraction from Painted Graph
517 // =========================================================================
518
531 get_min_path(typename GT::Node* end, Path<GT>& path)
532 {
533 ah_domain_error_if(ptr_g == nullptr) << "Min path has not been computed";
534 ah_domain_error_if(not painted) << "Graph has not been painted";
535
536 return Aleph::get_min_path<GT, Distance>(s, end, path);
537 }
538
539 // =========================================================================
540 // Copy Painted Tree
541 // =========================================================================
542
544 struct Total
545 {
547
549
551 {
552 dist += Distance()(a);
553 return true;
554 }
555 };
556
567 {
568 ah_domain_error_if(not painted) << "Graph has not been painted";
569
571 Paint_Filt paint_filter;
572 (Copy_Graph<GT, Dft_Show_Node<GT>, Paint_Filt>(paint_filter))(tree, g);
573
574 return paint_filter.dist;
575 }
576
585 get_min_path(const GT& tree, typename GT::Node* end, Path<GT>& path)
586 {
587 ah_domain_error_if(ptr_g == nullptr) << "Min path has not been computed";
588
589 auto ts = mapped_node<GT>(s);
590 auto te = mapped_node<GT>(end);
591
592 Path<GT> tree_path(tree);
594
595 // Build path in original graph
596 path.empty();
597 path.init(s);
598
599 for (auto it = tree_path.get_it(); it.has_curr(); it.next())
600 {
601 auto tree_node = it.get_curr();
602 if (tree_node != ts) // Skip start node (already added via init)
603 path.append(mapped_node<GT>(tree_node));
604 }
605
606 // Sum arc weights from the tree path
608 tree_path.for_each_arc([&total_dist](typename GT::Arc* a)
609 {
610 total_dist += Distance()(a);
611 });
612
613 return total_dist;
614 }
615};
616
617
618// Cleanup macros (they are redefined in derived classes with appropriate types)
619#undef SP_NODE_INFO
620#undef SP_TREE_NODE_INFO
621#undef SP_ACC
622#undef SP_HEAPNODE
623#undef SP_PARENT
624#undef SP_TREENODE
625#undef SP_ARC_INFO
626#undef SP_TREE_ARC_INFO
627#undef SP_POT
628#undef SP_TREEARC
629#undef SP_ARC_DIST
630
631} // namespace Aleph
632
633#endif // SHORTEST_PATH_COMMON_H
Exception handling system with formatted messages for Aleph-w.
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
WeightedDigraph::Arc Arc
Filtered copy of graphs.
Definition tpl_graph.H:3716
_Graph_Node Node
The graph type.
Definition tpl_graph.H:432
_Graph_Arc Arc
The node class type.
Definition tpl_graph.H:433
Path on a graph.
Definition tpl_graph.H:2669
void empty()
Clean the path: all the nodes and arc are removed.
Definition tpl_graph.H:2819
void init(Node *start_node)
Set the first node of a path.
Definition tpl_graph.H:2767
void append(Arc *arc)
Append an arc to the path.
Definition tpl_graph.H:2865
Base class providing common infrastructure for shortest path algorithms.
Shortest_Path_Base(Distance dist=Distance(), SA __sa=SA())
Default constructor.
Distance::Distance_Type get_min_path(typename GT::Node *end, Path< GT > &path)
Extracts a shortest path to end from a previously painted graph.
Get_Potential_Arc get_pot
Potential accessor.
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.
Distance::Distance_Type get_min_path(const GT &tree, typename GT::Node *end, Path< GT > &path)
Extracts path from tree to end node.
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.
void uninit()
Cleanup algorithm state.
GT * ptr_g
Pointer to the graph.
bool painted
Whether graph has been painted.
HeapT< GT, Get_Potential_Arc, Heap_Info > Heap
void init(const GT &g, typename GT::Node *start)
Initialize algorithm state.
static void map_arcs(A1 *p, A2 *q) noexcept
Map the arcs through their cookies.
Definition graph-dry.H:1026
void reset_bit(Node *node, int bit) const noexcept
Reset the bit of node (to zero)
Definition graph-dry.H:801
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
Definition graph-dry.H:995
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
#define ARC_COOKIE(p)
Return the arc cookie
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
#define NODE_COOKIE(p)
Return the node cookie
#define IS_ARC_VISITED(p, bit)
Determine whether the bit field is or not set to one.
@ Spanning_Tree
Definition aleph-graph.H:79
T checked_add(const T &a, const T &b)
Safely add two distance values with overflow checking.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
DynList< T > maps(const C &c, Op op)
Classic map operation.
#define SP_TREE_ARC_INFO(p)
Convert arc cookie to Tree_Arc_Info pointer.
#define SP_TREE_NODE_INFO(p)
Convert node cookie to Tree_Node_Info pointer.
#define SP_ARC_INFO(p)
Convert arc cookie to Arc_Info pointer.
#define SP_PARENT(p)
Access parent pointer from node cookie.
#define SP_POT(p)
Access arc potential from arc cookie.
#define SP_TREEARC(p)
Access tree arc mapping from arc cookie.
#define SP_NODE_INFO(p)
Convert node cookie to Node_Info pointer.
#define SP_HEAPNODE(p)
Access heap node handle from node cookie.
#define SP_TREENODE(p)
Access tree node mapping from node cookie.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Filter of painter arcs with that are set the Spanning_Tree control bit.
Definition tpl_graph.H:3803
Information stored in arc cookies for painting version.
Distance::Distance_Type pot
Arc potential (priority)
Arc cleanup for painting version.
void operator()(const GT &, typename GT::Arc *ga) const noexcept
Node cleanup for painting version.
void operator()(const GT &, typename GT::Node *p) const noexcept
Arc cleanup and mapping for tree-building version.
void operator()(const GT &, typename GT::Arc *ga) const noexcept
Node cleanup and mapping for tree-building version.
void operator()(const GT &, typename GT::Node *p) const noexcept
Functor to get arc potential for heap ordering.
Distance::Distance_Type operator()(typename GT::Arc *a) const noexcept
Functor to access heap node handle from node cookie.
void *& operator()(typename GT::Node *p) const noexcept
Arc initialization for painting version.
void operator()(const GT &g, typename GT::Arc *a) const
Node initialization for painting version.
void operator()(const GT &g, typename GT::Node *p) const
Arc initialization for tree-building version.
void operator()(const GT &g, typename GT::Arc *a) const
Node initialization for tree-building version.
void operator()(const GT &g, typename GT::Node *p) const
Information stored in node cookies for painting version.
Distance::Distance_Type dist
Accumulated distance from start.
void * heap_node
Handle in priority queue.
void * ret_node
Parent node (for backtracking)
Distance totalizer class for path copying.
Extended arc info with tree arc mapping.
GT::Arc * tree_arc
Corresponding arc in spanning tree.
Extended node info with tree node mapping.
GT::Node * tree_node
Corresponding node in spanning tree.
Distance accessor.
Path finding algorithms in graphs.
Generic graph and digraph implementations.