Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Johnson.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
64#ifndef JOHNSON_H
65#define JOHNSON_H
66
67# include <ah-graph-concepts.H>
68
69#include <Dijkstra.H>
70#include <Bellman_Ford.H>
71#include <tpl_graph.H>
72#include <tpl_dynList.H>
73#include <ah-errors.H>
74#include <limits>
75#include <type_traits>
76
77namespace Aleph
78{
79
121template <AlephGraph GT,
123 template <class, class> class Ait = Arc_Iterator,
124 template <class, class> class NAit = Node_Arc_Iterator,
127{
128public:
129 using Node = typename GT::Node;
130 using Arc = typename GT::Arc;
132
133private:
134 const GT* orig_graph = nullptr;
140 SA sa;
141 bool initialized = false;
142
144 {
146
148 {
149 return static_cast<Distance_Type>(arc->get_info());
150 }
151 };
152
154 {
156 }
157
159 {
160 if constexpr (std::is_integral_v<Distance_Type>)
161 {
163 a < std::numeric_limits<Distance_Type>::min() + b)
164 << "Integer underflow in distance subtraction: " << a << " - " << b;
165
167 a > std::numeric_limits<Distance_Type>::max() + b)
168 << "Integer overflow in distance subtraction: " << a << " - " << b;
169 }
170
171 return a - b;
172 }
173
180 {
181 GT& g = graph_copy.get_graph();
182
183 for (Ait<GT, SA> it(g, sa); it.has_curr(); it.next())
184 {
185 auto arc = it.get_curr();
186 auto u = g.get_src_node(arc);
187 auto v = g.get_tgt_node(arc);
188
189 Distance_Type w = dist(arc);
190 if (auto* orig = copy_to_orig_arc.search(arc))
191 w = dist(orig->second);
192
193 Distance_Type hu = h.find(u);
194 Distance_Type hv = h.find(v);
196
197 // Store reweighted value in the arc
198 arc->get_info() = w_prime;
199 }
200 }
201
203 {
206
207 graph_copy.for_each_mapping([this](Node* orig_node, Node* copy_node) {
209 });
210
212 GT& copy_g = graph_copy.get_graph();
213
214 for (typename GT::Arc_Iterator it(copy_g); it.has_curr(); it.next_ne())
215 {
216 Arc* copy_arc = it.get_curr();
218 Node* ctgt = copy_g.get_tgt_node(copy_arc);
219 buckets[std::make_pair(csrc, ctgt)].append(copy_arc);
220 }
221
222 for (typename GT::Arc_Iterator it(orig); it.has_curr(); it.next_ne())
223 {
224 Arc* orig_arc = it.get_curr();
225 Node* osrc = const_cast<GT&>(orig).get_src_node(orig_arc);
226 Node* otgt = const_cast<GT&>(orig).get_tgt_node(orig_arc);
227
228 Node* csrc = graph_copy.get_copy(osrc);
229 Node* ctgt = graph_copy.get_copy(otgt);
230
231 auto* bucket = buckets.search(std::make_pair(csrc, ctgt));
232 ah_domain_error_if(bucket == nullptr or bucket->second.is_empty())
233 << "Arc mapping mismatch between original and copied graph";
234
235 Arc* copy_arc = bucket->second.remove_first();
237 }
238
240 << "Arc mapping mismatch between original and copied graph";
241 }
242
244 {
246 << "Original graph not available";
247
249
250 if (copy_path.is_empty())
251 return orig_path;
252
253 auto it = copy_path.get_it();
254 auto* node_pair = copy_to_orig_node.search(it.get_current_node());
255 ah_domain_error_if(node_pair == nullptr)
256 << "Node not found in mapping";
257
258 orig_path.init(node_pair->second);
259
260 for (; it.has_curr() and it.has_current_arc(); it.next())
261 {
262 auto* arc_pair = copy_to_orig_arc.search(it.get_current_arc());
263 ah_domain_error_if(arc_pair == nullptr)
264 << "Arc not found in mapping";
265
266 orig_path.append(arc_pair->second);
267 }
268
269 return orig_path;
270 }
271
272public:
286 explicit Johnson(const GT& g, Distance d = Distance(), SA __sa = SA())
287 : orig_graph(&g), graph_copy(g), dist(d), sa(__sa)
288 {
289 GT& gc = graph_copy.get_graph();
290
292
293 // Compute node potentials using Bellman-Ford
294 // This will throw domain_error if negative cycle exists
296 h = bf.compute_nodes_weights();
297
298 // Reweight all arcs
300
301 initialized = true;
302 }
303
305 Johnson() = default;
306
311
320 requires std::is_convertible_v<typename GT::Arc_Type, Distance_Type>
321 {
322 ah_domain_error_if(!initialized) << "Johnson not initialized";
323 ah_domain_error_if(src == nullptr or tgt == nullptr) << "Source or target node is null";
324
325 // Same node - distance is 0
326 if (src == tgt)
327 return Distance_Type(0);
328
329 // Get corresponding nodes in the copy
330 Node* csrc = graph_copy.get_copy(src);
331 Node* ctgt = graph_copy.get_copy(tgt);
332
333 GT& gc = graph_copy.get_graph();
334
335 // Run Dijkstra from csrc on reweighted graph
337 dijkstra.paint_min_paths_tree(gc, csrc);
338
340 return std::numeric_limits<Distance_Type>::infinity();
341
342 // Get reweighted distance (may throw if unreachable)
343 Path<GT> path(gc);
344 Distance_Type d_prime = dijkstra.get_min_path(ctgt, path);
345
346 // Adjust back: d(s,t) = d'(s,t) - h(s) + h(t)
349
350 return d_prime - hs + ht;
351 }
352
361 requires std::is_convertible_v<typename GT::Arc_Type, Distance_Type>
362 {
363 ah_domain_error_if(!initialized) << "Johnson not initialized";
364 ah_domain_error_if(src == nullptr or tgt == nullptr) << "Source or target node is null";
365
366 // Get corresponding nodes in the copy
367 Node* csrc = graph_copy.get_copy(src);
368 Node* ctgt = graph_copy.get_copy(tgt);
369
370 GT& gc = graph_copy.get_graph();
371
372 // Run Dijkstra from csrc on reweighted graph
374 dijkstra.paint_min_paths_tree(gc, csrc);
375
377 return Path<GT>(*orig_graph);
378
379 // Get path in copy graph
381 dijkstra.get_min_path(ctgt, copy_path);
382
384 }
385
393 requires std::is_convertible_v<typename GT::Arc_Type, Distance_Type>
394 {
395 ah_domain_error_if(!initialized) << "Johnson not initialized";
396
398 GT& gc = graph_copy.get_graph();
399
400 // For each node as source
401 graph_copy.for_each_mapping([&](Node* orig_src, Node* copy_src) {
402 // Run Dijkstra from copy_src
404 dijkstra.paint_min_paths_tree(gc, copy_src);
405
407
408 // Get distance to all targets
409 graph_copy.for_each_mapping([&](Node* orig_tgt, Node* copy_tgt) {
411 {
412 result.insert(std::make_pair(orig_src, orig_tgt),
413 std::numeric_limits<Distance_Type>::infinity());
414 return;
415 }
416
417 Path<GT> path(gc);
418 Distance_Type d_prime = dijkstra.get_min_path(copy_tgt, path);
420 Distance_Type d = d_prime - hs + ht;
421 result.insert(std::make_pair(orig_src, orig_tgt), d);
422 });
423 });
424
425 return result;
426 }
427
438 {
439 ah_domain_error_if(!initialized) << "Johnson not initialized";
440 Node* copy_node = graph_copy.get_copy(node);
441 return h.find(copy_node);
442 }
443
450 GT& get_reweighted_graph() noexcept { return graph_copy.get_graph(); }
451
454 const GT& get_reweighted_graph() const noexcept { return graph_copy.get_graph(); }
455
461 Node* get_copy_node(Node* orig) const { return graph_copy.get_copy(orig); }
462};
463
464} // namespace Aleph
465
466#endif // JOHNSON_H
Bellman-Ford algorithm for single-source shortest paths.
Dijkstra's shortest path algorithm.
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.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
long double w
Definition btreepic.C:153
Bellman-Ford algorithm for shortest paths with negative weights.
Default distance accessor for arc weights.
Spanning tree calculation of all shortest paths from a given node according to Dijkstra's algorithm.
Definition Dijkstra.H:103
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
Generic key-value map implemented on top of a binary search tree.
Pair * append(const Key &key, const Data &data)
Pair * search(const Key &key) const noexcept
Collect all keys.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair.
Data & find(const Key &key)
Find the value associated with key.
const size_t & size() const
Returns the cardinality of the set.
void empty()
remove all elements from the set
Graph copy with explicit node mapping.
Definition tpl_graph.H:3991
Johnson's algorithm for all-pairs shortest paths.
Definition Johnson.H:127
Path< GT > find_path(Node *src, Node *tgt)
Find the shortest path from source to target.
Definition Johnson.H:360
static Distance_Type checked_add(const Distance_Type &a, const Distance_Type &b)
Definition Johnson.H:153
GraphCopyWithMapping< GT > graph_copy
Copy of graph with node mapping.
Definition Johnson.H:135
GT & get_reweighted_graph() noexcept
Get access to the internal reweighted graph.
Definition Johnson.H:450
bool initialized
Definition Johnson.H:141
DynMapTree< Node *, Node * > copy_to_orig_node
Definition Johnson.H:136
bool is_initialized() const noexcept
Check if the algorithm has been initialized.
Definition Johnson.H:310
DynMapTree< std::pair< Node *, Node * >, Distance_Type > compute_all_pairs_distances()
Compute the shortest distance for all pairs.
Definition Johnson.H:392
Distance_Type get_potential(Node *node) const
Get the node potential (h value) for a node.
Definition Johnson.H:437
const GT * orig_graph
Definition Johnson.H:134
typename GT::Arc Arc
Definition Johnson.H:130
static Distance_Type checked_sub(const Distance_Type &a, const Distance_Type &b)
Definition Johnson.H:158
Johnson(const GT &g, Distance d=Distance(), SA __sa=SA())
Construct a Johnson's all-pairs shortest paths executor.
Definition Johnson.H:286
typename Distance::Distance_Type Distance_Type
Definition Johnson.H:131
Johnson()=default
Default constructor (uninitialized state)
typename GT::Node Node
Definition Johnson.H:129
Path< GT > map_copy_path_to_original(const Path< GT > &copy_path) const
Definition Johnson.H:243
Node * get_copy_node(Node *orig) const
Get the copy of a node in the reweighted graph.
Definition Johnson.H:461
Distance_Type get_distance(Node *src, Node *tgt)
Get the shortest distance from source to target.
Definition Johnson.H:319
void reweight_arcs()
Reweight all arcs using node potentials.
Definition Johnson.H:179
void build_reverse_mappings(const GT &orig)
Definition Johnson.H:202
const GT & get_reweighted_graph() const noexcept
Get const access to the internal reweighted graph.
Definition Johnson.H:454
Distance dist
Definition Johnson.H:139
DynMapTree< Arc *, Arc * > copy_to_orig_arc
Definition Johnson.H:137
DynMapTree< Node *, Distance_Type > h
Node potentials from Bellman-Ford.
Definition Johnson.H:138
Path on a graph.
Definition tpl_graph.H:2772
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:779
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:785
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
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
@ 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.
STL namespace.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1165
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1001
typename Johnson::Distance_Type Distance_Type
Definition Johnson.H:145
Distance_Type operator()(Arc *arc) const
Definition Johnson.H:147
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1120
Distance accessor.
Alias for htlist.H (DynList implementation).
Generic graph and digraph implementations.