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 <sstream>
99# include <iostream>
100# include <limits>
101# include <ahFunction.H>
102# include <ahSort.H>
103# include <tpl_indexArc.H>
104# include <tpl_dynMat.H>
105# include <tpl_graph.H>
106# include <tpl_graph_utils.H>
107# include <ah-errors.H>
108
109namespace Aleph
110{
146 template <class GT,
147 class Distance = Dft_Dist<GT>,
148 class SA = Dft_Show_Arc<GT>>
150 {
151 typedef typename GT::Node Node;
152 typedef typename GT::Arc Arc;
154
156 GT & g;
157 const long n;
159 bool negative_cycle = false;
163
164 public:
171
181
191 {
192 return dist;
193 }
194
203
210 Node * select_node(long i) const noexcept { return nodes(i); }
211
213
220 long index_node(Node *p) const
221 {
222 ah_invalid_argument_if(p == nullptr) << "Node pointer cannot be null";
223 auto i = binary_search(nodes, p);
225 << "Floyd_All_Shortest_Paths::index_node() node not found";
226 return i;
227 }
228
229 public:
243 : g(const_cast<GT &>(__g)), n(g.get_num_nodes()),
245 path_mat(n, n), dist(n, n), sa(__sa)
246 {
247 ah_invalid_argument_if(n <= 0) << "Graph must contain at least one node";
248
249 long i = 0;
250 nodes.reserve(n);
251 for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
252 nodes.access(i++) = it.get_curr();
253 in_place_sort(nodes); // sort by node pointer value
254
255 dist.allocate();
256 path_mat.allocate(); { // initialize matrices
258
259 for (long i = 0; i < n; ++i)
260 for (long j = 0; j < n; ++j)
261 path_mat(i, j) = -1;
262
263 for (long i = 0; i < n; ++i)
264 {
265 Node *src = nodes(i);
266 for (long j = 0; j < n; ++j)
267 {
268 if (i == j)
269 {
270 dist(i, j) = 0;
271 path_mat(i, j) = j;
272 continue;
273 }
274
275 Node *tgt = nodes(j);
276 Arc *arc = arcs.search_directed(src, tgt);
277 if (arc == nullptr)
278 {
279 dist(i, j) = Inf;
280 continue;
281 }
282
283 dist(i, j) = Distance()(arc);
284 path_mat(i, j) = j;
285 }
286 }
287 }
288
289 for (long k = 0; k < n; ++k)
290 for (long i = 0; i < n; ++i)
291 {
292 const Distance_Type & dik = dist(i, k);
293 for (long j = 0; j < n; ++j)
294 {
295 const Distance_Type & dij = dist(i, j);
296 if (dik == Inf)
297 continue;
298
299 const Distance_Type & dkj = dist(k, j);
300 if (dkj == Inf)
301 continue;
302
303 // Calculate new distance through intermediate node k.
304 // Important: avoid undefined behavior on signed overflow
305 // (e.g. Inf - negative) and handle negative weights safely.
306 bool can_add = true;
307 if constexpr (std::numeric_limits<Distance_Type>::is_integer)
308 {
309 if constexpr (std::numeric_limits<Distance_Type>::is_signed)
310 {
311 const Distance_Type maxv = std::numeric_limits<Distance_Type>::max();
312 const Distance_Type minv = std::numeric_limits<Distance_Type>::lowest();
313 if (dkj > 0)
314 can_add = (dik <= maxv - dkj);
315 else if (dkj < 0)
316 can_add = (dik >= minv - dkj);
317 }
318 else
319 {
321 }
322 }
323
324 if (!can_add)
325 continue;
326
327 const Distance_Type new_dist = dik + dkj;
328 if (new_dist < dij)
329 {
330 dist(i, j) = new_dist;
331 path_mat(i, j) = path_mat(i, k);
332 }
333 }
334 }
335
336 // Check for negative cycles on the diagonal
337 for (long idx = 0; idx < n; ++idx)
338 if (dist(idx, idx) < 0)
339 {
340 negative_cycle = true;
341 break;
342 }
343 }
344
353
360 std::string entry(const Distance_Type & e) const
361 {
362 if (e == Inf)
363 return "Inf";
364
365 std::stringstream ss;
366 ss << e;
367 return ss.str();
368 }
369
379 {
380 const Distance_Type Inf = std::numeric_limits<Distance_Type>::max();
381 const int n = dist.rows();
382 for (int i = 0; i < n; ++i)
383 {
384 for (int j = 0; j < n; ++j)
385 if (dist.access(i, j) == Inf)
386 std::cout << "inf ";
387 else
388 std::cout << dist.access(i, j) << " ";
389 std::cout << '\n';
390 }
391 std::cout << '\n';
392 }
393
405 Path<GT> get_min_path(const long src_idx, const long tgt_idx) const
406 {
408 << "Source index out of range";
410 << "Target index out of range";
411
412 if (dist(src_idx, tgt_idx) == Inf)
413 return Path<GT>(g);
414
415 auto src = nodes(src_idx);
416 Path<GT> path(g, src);
417
418 if (src_idx == tgt_idx)
419 return path;
420
421 long i = src_idx;
422 while (true)
423 {
424 const auto & k = path_mat(i, tgt_idx);
425 auto p = nodes(k);
426 path.append_directed(p);
427 if (k == tgt_idx)
428 break;
429 i = k;
430 }
431
432 return path;
433 }
434
447 typename GT::Node *tgt) const
448 {
449 return get_min_path(index_node(src), index_node(tgt));
450 }
451 };
452} // end namespace Aleph
453
454# 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.
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
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
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.
DynArray< Node * > get_nodes() const noexcept
Get the array of graph nodes.
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:2937
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
__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
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
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Distance accessor.
Dynamic matrix with lazy allocation.
Generic graph and digraph implementations.
Utility algorithms and operations for graphs.
Arc indexing for fast lookup by endpoint nodes.