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 <ah-graph-concepts.H>
52
53#include <limits>
54#include <type_traits>
55#include <ah-errors.H>
56#include <tpl_graph.H>
57#include <tpl_find_path.H>
58
59namespace Aleph
60{
61
62// =============================================================================
63// Cookie Access Macros (internal use)
64// =============================================================================
65
66// These macros provide unified access to node/arc cookies across algorithms
67
69#define SP_NODE_INFO(p) (static_cast<typename Shortest_Path_Base::Node_Info*>(NODE_COOKIE(p)))
70
72#define SP_TREE_NODE_INFO(p) (static_cast<typename Shortest_Path_Base::Tree_Node_Info*>(NODE_COOKIE(p)))
73
75#define SP_ACC(p) (SP_NODE_INFO(p)->dist)
76
78#define SP_HEAPNODE(p) (SP_NODE_INFO(p)->heap_node)
79
81#define SP_PARENT(p) (SP_NODE_INFO(p)->ret_node)
82
84#define SP_TREENODE(p) (SP_TREE_NODE_INFO(p)->tree_node)
85
87#define SP_ARC_INFO(p) (static_cast<typename Shortest_Path_Base::Arc_Info*>(ARC_COOKIE(p)))
88
90#define SP_TREE_ARC_INFO(p) (static_cast<typename Shortest_Path_Base::Tree_Arc_Info*>(ARC_COOKIE(p)))
91
93#define SP_POT(p) (SP_ARC_INFO(p)->pot)
94
96#define SP_TREEARC(p) (SP_TREE_ARC_INFO(p)->tree_arc)
97
99#define SP_ARC_DIST(p) (Distance()(p))
100
101
102// =============================================================================
103// Overflow-Checked Arithmetic
104// =============================================================================
105
107namespace shortest_path_detail
108{
109
121template <typename T>
122[[nodiscard]] inline T checked_add(const T& a, const T& b)
123{
124 if constexpr (std::is_integral_v<T>)
125 {
126 ah_overflow_error_if(b > 0 and a > std::numeric_limits<T>::max() - b)
127 << "Integer overflow in distance addition: " << a << " + " << b;
128
129 ah_overflow_error_if(b < 0 and a < std::numeric_limits<T>::min() - b)
130 << "Integer underflow in distance addition: " << a << " + " << b;
131 }
132
133 return a + b;
134}
135
136} // namespace shortest_path_detail
137
138
139// =============================================================================
140// Base Class for Shortest Path Algorithms
141// =============================================================================
142
161template <AlephGraph GT,
163 template <typename, class> class Itor,
164 ArcFilter<GT> SA,
165 template <class, class, class> class HeapT>
167{
168public:
169 // =========================================================================
170 // Cookie Structures
171 // =========================================================================
172
179 struct Arc_Info
180 {
182 };
183
188 struct Tree_Arc_Info : public Arc_Info
189 {
190 typename GT::Arc* tree_arc = nullptr;
191 };
192
199 {
201 void* heap_node = nullptr;
202 void* ret_node = nullptr;
203 };
204
209 struct Tree_Node_Info : public Node_Info
210 {
211 typename GT::Node* tree_node = nullptr;
212 };
213
214 // =========================================================================
215 // Heap Access Functor
216 // =========================================================================
217
220 {
221 void*& operator()(typename GT::Node* p) const noexcept
222 {
223 return SP_HEAPNODE(p);
224 }
225 };
226
227 // =========================================================================
228 // Get Potential Functor
229 // =========================================================================
230
233 {
234 Get_Potential_Arc() = default;
235
237
239 operator()(typename GT::Arc* a) const noexcept
240 {
241 return SP_POT(a);
242 }
243 };
244
245 // =========================================================================
246 // Initialize Functors
247 // =========================================================================
248
251 {
252 void operator()(const GT& g, typename GT::Node* p) const
253 {
255 NODE_COOKIE(p) = new Node_Info;
256 }
257 };
258
261 {
262 void operator()(const GT& g, typename GT::Arc* a) const
263 {
265 ARC_COOKIE(a) = new Arc_Info;
266 SP_POT(a) = 0;
267 }
268 };
269
272 {
273 void operator()(const GT& g, typename GT::Node* p) const
274 {
277 }
278 };
279
282 {
283 void operator()(const GT& g, typename GT::Arc* a) const
284 {
286 ARC_COOKIE(a) = new Tree_Arc_Info;
287 SP_POT(a) = 0;
288 SP_TREEARC(a) = nullptr;
289 }
290 };
291
292 // =========================================================================
293 // Destroy Functors
294 // =========================================================================
295
298 {
299 void operator()(const GT&, typename GT::Node* p) const noexcept
300 {
301 void* tmp = SP_PARENT(p);
302 delete SP_NODE_INFO(p);
303 NODE_COOKIE(p) = tmp;
304 }
305 };
306
309 {
310 void operator()(const GT&, typename GT::Arc* ga) const noexcept
311 {
312 delete SP_ARC_INFO(ga);
313 }
314 };
315
318 {
319 void operator()(const GT&, typename GT::Node* p) const noexcept
320 {
321 auto aux = SP_TREE_NODE_INFO(p);
322 auto tp = SP_TREENODE(p);
323 if (tp != nullptr)
324 {
325 NODE_COOKIE(p) = NODE_COOKIE(tp) = nullptr;
326 GT::map_nodes(p, tp);
327 }
328 else
329 NODE_COOKIE(p) = nullptr;
330
331 delete aux;
332 }
333 };
334
337 {
338 void operator()(const GT&, typename GT::Arc* ga) const noexcept
339 {
340 auto aux = SP_TREE_ARC_INFO(ga);
341 typename GT::Arc* ta = SP_TREEARC(ga);
342 if (ta != nullptr)
343 {
346 }
347
348 delete aux;
349 }
350 };
351
352 // =========================================================================
353 // Type Aliases
354 // =========================================================================
355
357
358protected:
359 // =========================================================================
360 // Member Variables
361 // =========================================================================
362
363 SA sa;
366 bool painted = false;
367 GT* ptr_g = nullptr;
368 typename GT::Node* s = nullptr;
369
370 // =========================================================================
371 // Protected Methods
372 // =========================================================================
373
381 template <class IN, class IA>
382 void init(const GT& g, typename GT::Node* start)
383 {
384 heap.empty();
385
386 ptr_g = &const_cast<GT&>(g);
387 s = start;
388
391 }
392
398 template <class DN, class DA>
399 void uninit()
400 {
401 // Clear heap first to avoid use-after-free when heap destructor
402 // tries to compare arcs whose cookies have been freed
403 heap.empty();
404
405 Operate_On_Nodes<GT, DN>()(*ptr_g);
407 }
408
418 const typename Distance::Distance_Type& b) const
419 {
421 }
422
423public:
424 // =========================================================================
425 // Constructors
426 // =========================================================================
427
434 : sa(__sa), get_pot(dist), heap(get_pot, Heap_Info()),
435 painted(false), ptr_g(nullptr), s(nullptr)
436 {
437 // empty
438 }
439
440 // =========================================================================
441 // State Getters
442 // =========================================================================
443
447 [[nodiscard]] bool has_computation() const noexcept { return ptr_g != nullptr; }
448
453
457 [[nodiscard]] typename GT::Node* get_start_node() const noexcept { return s; }
458
463
464 // =========================================================================
465 // Distance Calculation
466 // =========================================================================
467
482 get_distance(typename GT::Node* node)
483 {
484 ah_domain_error_if(not painted) << "Graph has not been painted";
485 ah_domain_error_if(node == nullptr) << "node cannot be null";
486
487 if (node == s)
488 return 0;
489
491 << "node is not reachable from start";
492
493 typename Distance::Distance_Type total = 0;
494
495 for (auto curr = node; curr != s;)
496 {
497 auto parent = static_cast<typename GT::Node*>(NODE_COOKIE(curr));
498 if (parent == nullptr)
499 break;
500
501 for (Itor<GT, SA> it(parent, sa); it.has_curr(); it.next_ne())
502 {
503 auto arc = it.get_current_arc_ne();
504 auto tgt = it.get_tgt_node();
505 if (tgt == curr and IS_ARC_VISITED(arc, Aleph::Spanning_Tree))
506 {
507 total += Distance()(arc);
508 break;
509 }
510 }
511 curr = parent;
512 }
513
514 return total;
515 }
516
517 // =========================================================================
518 // Path Extraction from Painted Graph
519 // =========================================================================
520
533 get_min_path(typename GT::Node* end, Path<GT>& path)
534 {
535 ah_domain_error_if(ptr_g == nullptr) << "Min path has not been computed";
536 ah_domain_error_if(not painted) << "Graph has not been painted";
537
538 return Aleph::get_min_path<GT, Distance>(s, end, path);
539 }
540
541 // =========================================================================
542 // Copy Painted Tree
543 // =========================================================================
544
546 struct Total
547 {
549
551
553 {
554 dist += Distance()(a);
555 return true;
556 }
557 };
558
569 {
570 ah_domain_error_if(not painted) << "Graph has not been painted";
571
573 Paint_Filt paint_filter;
574 (Copy_Graph<GT, Dft_Show_Node<GT>, Paint_Filt>(paint_filter))(tree, g);
575
576 return paint_filter.dist;
577 }
578
587 get_min_path(const GT& tree, typename GT::Node* end, Path<GT>& path)
588 {
589 ah_domain_error_if(ptr_g == nullptr) << "Min path has not been computed";
590
591 auto ts = mapped_node<GT>(s);
592 auto te = mapped_node<GT>(end);
593
594 Path<GT> tree_path(tree);
596
597 // Build path in original graph
598 path.empty();
599 path.init(s);
600
601 for (auto it = tree_path.get_it(); it.has_curr(); it.next())
602 {
603 auto tree_node = it.get_curr();
604 if (tree_node != ts) // Skip start node (already added via init)
605 path.append(mapped_node<GT>(tree_node));
606 }
607
608 // Sum arc weights from the tree path
610 tree_path.for_each_arc([&total_dist](typename GT::Arc* a)
611 {
612 total_dist += Distance()(a);
613 });
614
615 return total_dist;
616 }
617};
618
619
620// Cleanup macros (they are redefined in derived classes with appropriate types)
621#undef SP_NODE_INFO
622#undef SP_TREE_NODE_INFO
623#undef SP_ACC
624#undef SP_HEAPNODE
625#undef SP_PARENT
626#undef SP_TREENODE
627#undef SP_ARC_INFO
628#undef SP_TREE_ARC_INFO
629#undef SP_POT
630#undef SP_TREEARC
631#undef SP_ARC_DIST
632
633} // namespace Aleph
634
635#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:468
#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.
WeightedDigraph::Arc Arc
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
Filtered copy of graphs.
Definition tpl_graph.H:3826
Path on a graph.
Definition tpl_graph.H:2772
void empty()
Clean the path: all the nodes and arc are removed.
Definition tpl_graph.H:2922
void init(Node *start_node)
Set the first node of a path.
Definition tpl_graph.H:2870
void append(Arc *arc)
Append an arc to the path.
Definition tpl_graph.H:2975
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:1074
void reset_bit(Node *node, int bit) const noexcept
Reset the bit of node (to zero)
Definition graph-dry.H:849
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
Definition graph-dry.H:1043
#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
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.
@ 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
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
#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.
Filter of painter arcs with that are set the Spanning_Tree control bit.
Definition tpl_graph.H:3913
Distance::Distance_Type dist
Accumulative distance from the first seen arc until the last seen.
Definition tpl_graph.H:3915
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.