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 <ah-graph-concepts.H>
99
100# include <type_traits>
101# include <sstream>
102# include <iostream>
103# include <limits>
104# include <ahFunction.H>
105# include <ahSort.H>
106# include <tpl_indexArc.H>
107# include <tpl_dynMat.H>
108# include <tpl_graph.H>
109# include <tpl_graph_utils.H>
110# include <ah-errors.H>
111
112namespace Aleph
113{
149 template <AlephGraph GT,
153 {
154 typedef typename GT::Node Node;
155 typedef typename GT::Arc Arc;
157
159 GT & g;
160 const long n;
162 bool negative_cycle = false;
165 SA & sa;
166
167 public:
174
184
194 {
195 return dist;
196 }
197
216
231
248
255 Node * select_node(long i) const noexcept { return nodes(i); }
256
258
265 long index_node(Node *p) const
266 {
267 ah_invalid_argument_if(p == nullptr) << "Node pointer cannot be null";
268 auto i = binary_search(nodes, p);
270 << "Floyd_All_Shortest_Paths::index_node() node not found";
271 return i;
272 }
273
274 public:
288 : g(const_cast<GT &>(__g)), n(g.get_num_nodes()),
290 path_mat(n, n), dist(n, n), sa(__sa)
291 {
292 ah_invalid_argument_if(n <= 0) << "Graph must contain at least one node";
293
294 long i = 0;
295 nodes.reserve(n);
296 for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
297 nodes.access(i++) = it.get_curr();
298 in_place_sort(nodes); // sort by node pointer value
299
300 dist.allocate();
301 path_mat.allocate(); { // initialize matrices
303
304 for (long i = 0; i < n; ++i)
305 for (long j = 0; j < n; ++j)
306 path_mat(i, j) = -1;
307
308 for (long i = 0; i < n; ++i)
309 {
310 Node *src = nodes(i);
311 for (long j = 0; j < n; ++j)
312 {
313 if (i == j)
314 {
315 dist(i, j) = 0;
316 path_mat(i, j) = j;
317 continue;
318 }
319
320 Node *tgt = nodes(j);
321 Arc *arc = arcs.search_directed(src, tgt);
322 if (arc == nullptr)
323 {
324 dist(i, j) = Inf;
325 continue;
326 }
327
328 dist(i, j) = Distance()(arc);
329 path_mat(i, j) = j;
330 }
331 }
332 }
333
334 for (long k = 0; k < n; ++k)
335 for (long i = 0; i < n; ++i)
336 {
337 const Distance_Type & dik = dist(i, k);
338 for (long j = 0; j < n; ++j)
339 {
340 const Distance_Type & dij = dist(i, j);
341 if (dik == Inf)
342 continue;
343
344 const Distance_Type & dkj = dist(k, j);
345 if (dkj == Inf)
346 continue;
347
348 // Calculate new distance through intermediate node k.
349 // Important: avoid undefined behavior on signed overflow
350 // (e.g. Inf - negative) and handle negative weights safely.
351 bool can_add = true;
352 if constexpr (std::numeric_limits<Distance_Type>::is_integer)
353 {
354 if constexpr (std::numeric_limits<Distance_Type>::is_signed)
355 {
356 const Distance_Type maxv = std::numeric_limits<Distance_Type>::max();
357 const Distance_Type minv = std::numeric_limits<Distance_Type>::lowest();
358 if (dkj > 0)
359 can_add = (dik <= maxv - dkj);
360 else if (dkj < 0)
361 can_add = (dik >= minv - dkj);
362 }
363 else
364 {
366 }
367 }
368
369 if (!can_add)
370 continue;
371
372 const Distance_Type new_dist = dik + dkj;
373 if (new_dist < dij)
374 {
375 dist(i, j) = new_dist;
376 path_mat(i, j) = path_mat(i, k);
377 }
378 }
379 }
380
381 // Check for negative cycles on the diagonal
382 for (long idx = 0; idx < n; ++idx)
383 if (dist(idx, idx) < 0)
384 {
385 negative_cycle = true;
386 break;
387 }
388 }
389
396 Floyd_All_Shortest_Paths(const GT & g, SA && sa = SA())
398
405 std::string entry(const Distance_Type & e) const
406 {
407 if (e == Inf)
408 return "Inf";
409
410 std::stringstream ss;
411 ss << e;
412 return ss.str();
413 }
414
424 {
425 const Distance_Type Inf = std::numeric_limits<Distance_Type>::max();
426 const int n = dist.rows();
427 for (int i = 0; i < n; ++i)
428 {
429 for (int j = 0; j < n; ++j)
430 if (dist.access(i, j) == Inf)
431 std::cout << "inf ";
432 else
433 std::cout << dist.access(i, j) << " ";
434 std::cout << '\n';
435 }
436 std::cout << '\n';
437 }
438
450 Path<GT> get_min_path(const long src_idx, const long tgt_idx) const
451 {
453 << "Source index out of range";
455 << "Target index out of range";
456
457 if (dist(src_idx, tgt_idx) == Inf)
458 return Path<GT>(g);
459
460 auto src = nodes(src_idx);
461 Path<GT> path(g, src);
462
463 if (src_idx == tgt_idx)
464 return path;
465
466 long i = src_idx;
467 while (true)
468 {
469 const auto & k = path_mat(i, tgt_idx);
470 auto p = nodes(k);
471 path.append_directed(p);
472 if (k == tgt_idx)
473 break;
474 i = k;
475 }
476
477 return path;
478 }
479
492 typename GT::Node *tgt) const
493 {
494 return get_min_path(index_node(src), index_node(tgt));
495 }
496 };
497} // end namespace Aleph
498
499# 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:584
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:644
C++20 concepts for the protocol shared by graph algorithms.
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:2772
void append_directed(Node *p)
Append a node to a directed path.
Definition tpl_graph.H:3047
__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:4121
DynArray< Graph::Arc * > arcs
Definition graphpic.C:408
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
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynArray< T > & in_place_sort(DynArray< T > &c, Cmp cmp=Cmp())
Sorts a DynArray in place.
Definition ahSort.H:328
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:1001
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.