Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Floyd_Warshall.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
95# ifndef FLOYD_WARSHALL_H
96# define FLOYD_WARSHALL_H
97
98# include <type_traits>
99# include <sstream>
100# include <iostream>
101# include <limits>
102# include <ahFunction.H>
103# include <ahSort.H>
104# include <tpl_indexArc.H>
105# include <tpl_dynMat.H>
106# include <tpl_graph.H>
107# include <tpl_graph_utils.H>
108# include <ah-errors.H>
109
110namespace Aleph
111{
147 template <class GT,
148 class Distance = Dft_Dist<GT>,
149 class SA = Dft_Show_Arc<GT>>
151 {
152 typedef typename GT::Node Node;
153 typedef typename GT::Arc Arc;
155
157 GT & g;
158 const long n;
160 bool negative_cycle = false;
164
165 public:
172
182
192 {
193 return dist;
194 }
195
214
229
246
253 Node * select_node(long i) const noexcept { return nodes(i); }
254
256
263 long index_node(Node *p) const
264 {
265 ah_invalid_argument_if(p == nullptr) << "Node pointer cannot be null";
266 auto i = binary_search(nodes, p);
268 << "Floyd_All_Shortest_Paths::index_node() node not found";
269 return i;
270 }
271
272 public:
286 : g(const_cast<GT &>(__g)), n(g.get_num_nodes()),
288 path_mat(n, n), dist(n, n), sa(__sa)
289 {
290 ah_invalid_argument_if(n <= 0) << "Graph must contain at least one node";
291
292 long i = 0;
293 nodes.reserve(n);
294 for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
295 nodes.access(i++) = it.get_curr();
296 in_place_sort(nodes); // sort by node pointer value
297
298 dist.allocate();
299 path_mat.allocate(); { // initialize matrices
301
302 for (long i = 0; i < n; ++i)
303 for (long j = 0; j < n; ++j)
304 path_mat(i, j) = -1;
305
306 for (long i = 0; i < n; ++i)
307 {
308 Node *src = nodes(i);
309 for (long j = 0; j < n; ++j)
310 {
311 if (i == j)
312 {
313 dist(i, j) = 0;
314 path_mat(i, j) = j;
315 continue;
316 }
317
318 Node *tgt = nodes(j);
319 Arc *arc = arcs.search_directed(src, tgt);
320 if (arc == nullptr)
321 {
322 dist(i, j) = Inf;
323 continue;
324 }
325
326 dist(i, j) = Distance()(arc);
327 path_mat(i, j) = j;
328 }
329 }
330 }
331
332 for (long k = 0; k < n; ++k)
333 for (long i = 0; i < n; ++i)
334 {
335 const Distance_Type & dik = dist(i, k);
336 for (long j = 0; j < n; ++j)
337 {
338 const Distance_Type & dij = dist(i, j);
339 if (dik == Inf)
340 continue;
341
342 const Distance_Type & dkj = dist(k, j);
343 if (dkj == Inf)
344 continue;
345
346 // Calculate new distance through intermediate node k.
347 // Important: avoid undefined behavior on signed overflow
348 // (e.g. Inf - negative) and handle negative weights safely.
349 bool can_add = true;
350 if constexpr (std::numeric_limits<Distance_Type>::is_integer)
351 {
352 if constexpr (std::numeric_limits<Distance_Type>::is_signed)
353 {
354 const Distance_Type maxv = std::numeric_limits<Distance_Type>::max();
355 const Distance_Type minv = std::numeric_limits<Distance_Type>::lowest();
356 if (dkj > 0)
357 can_add = (dik <= maxv - dkj);
358 else if (dkj < 0)
359 can_add = (dik >= minv - dkj);
360 }
361 else
362 {
364 }
365 }
366
367 if (!can_add)
368 continue;
369
370 const Distance_Type new_dist = dik + dkj;
371 if (new_dist < dij)
372 {
373 dist(i, j) = new_dist;
374 path_mat(i, j) = path_mat(i, k);
375 }
376 }
377 }
378
379 // Check for negative cycles on the diagonal
380 for (long idx = 0; idx < n; ++idx)
381 if (dist(idx, idx) < 0)
382 {
383 negative_cycle = true;
384 break;
385 }
386 }
387
396
403 std::string entry(const Distance_Type & e) const
404 {
405 if (e == Inf)
406 return "Inf";
407
408 std::stringstream ss;
409 ss << e;
410 return ss.str();
411 }
412
422 {
423 const Distance_Type Inf = std::numeric_limits<Distance_Type>::max();
424 const int n = dist.rows();
425 for (int i = 0; i < n; ++i)
426 {
427 for (int j = 0; j < n; ++j)
428 if (dist.access(i, j) == Inf)
429 std::cout << "inf ";
430 else
431 std::cout << dist.access(i, j) << " ";
432 std::cout << '\n';
433 }
434 std::cout << '\n';
435 }
436
448 Path<GT> get_min_path(const long src_idx, const long tgt_idx) const
449 {
451 << "Source index out of range";
453 << "Target index out of range";
454
455 if (dist(src_idx, tgt_idx) == Inf)
456 return Path<GT>(g);
457
458 auto src = nodes(src_idx);
459 Path<GT> path(g, src);
460
461 if (src_idx == tgt_idx)
462 return path;
463
464 long i = src_idx;
465 while (true)
466 {
467 const auto & k = path_mat(i, tgt_idx);
468 auto p = nodes(k);
469 path.append_directed(p);
470 if (k == tgt_idx)
471 break;
472 i = k;
473 }
474
475 return path;
476 }
477
490 typename GT::Node *tgt) const
491 {
492 return get_min_path(index_node(src), index_node(tgt));
493 }
494 };
495} // end namespace Aleph
496
497# endif // FLOYD_WARSHALL_H
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:639
Standard functor implementations and comparison objects.
High-level sorting functions for Aleph containers.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
Default distance accessor for arc weights.
size_t size() const noexcept
Return the current dimension of array.
T & access(const size_t i) const noexcept
Fast access without checking allocation and bound_min_clock checking.
void reserve(const size_t l, const size_t r)
Allocate a range of entries.
Dynamic matrix with sparse storage.
Definition tpl_dynMat.H:120
void allocate()
Pre-allocate memory for the entire matrix.
Definition tpl_dynMat.H:249
constexpr size_t rows() const noexcept
Get the number of rows.
Definition tpl_dynMat.H:413
T & access(const size_t i, const size_t j)
Direct access to an allocated entry.
Definition tpl_dynMat.H:514
Compute the all-pairs shortest path distance matrix and the path reconstruction matrix for a graph g ...
DynMatrix< Distance_Type > dist
DynArray< Node * > get_nodes() const
Get an owning copy of the graph nodes array.
DynArray< Node * > get_nodes_copy() const
Get an owning copy of the graph nodes array.
Path< GT > get_min_path(const long src_idx, const long tgt_idx) const
Reconstruct the shortest path between two nodes by matrix indices.
const DynMatrix< Distance_Type > & get_dist_mat() const noexcept
Get the distance matrix.
Node * select_node(long i) const noexcept
Get the graph node at a given matrix index.
constexpr bool has_negative_cycle() const noexcept
Check if the graph contains a negative cycle.
std::string entry(const Distance_Type &e) const
Convert a distance value to string representation.
Path< GT > get_min_path(typename GT::Node *src, typename GT::Node *tgt) const
Reconstruct the shortest path between two nodes.
Distance::Distance_Type Distance_Type
const DynArray< Node * > & get_nodes_ref() const noexcept
Get the array of graph nodes as a constant reference.
Floyd_All_Shortest_Paths(const GT &g, SA &&sa=SA())
Construct Floyd-Warshall solver with rvalue arc filter.
Floyd_All_Shortest_Paths(const GT &__g, SA &__sa)
Construct Floyd-Warshall solver for all-pairs shortest paths.
const DynMatrix< long > & get_path_mat() const noexcept
Get the path reconstruction matrix.
long index_node(Node *p) const
Return the adjacency-matrix index corresponding to node p.
static void print(const DynMatrix< Distance_Type > &dist)
Print a distance matrix to standard output.
Index for fast arc lookup by its endpoint nodes.
Path on a graph.
Definition tpl_graph.H:2669
void append_directed(Node *p)
Append a node to a directed path.
Definition tpl_graph.H:2944
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4110
DynArray< Graph::Arc * > arcs
Definition graphpic.C:408
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
DynArray< T > & in_place_sort(DynArray< T > &c, Cmp cmp=Cmp())
Sorts a DynArray in place.
Definition ahSort.H:321
bool binary_search(Itor beg, Itor end, const T &value)
Binary search for a value.
Definition ahAlgo.H:1284
STL namespace.
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Distance accessor.
static int * k
Dynamic matrix with lazy allocation.
Generic graph and digraph implementations.
Utility algorithms and operations for graphs.
Arc indexing for fast lookup by endpoint nodes.