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 <Dijkstra.H>
68#include <Bellman_Ford.H>
69#include <tpl_graph.H>
70#include <tpl_dynList.H>
71#include <ah-errors.H>
72#include <limits>
73#include <type_traits>
74
75namespace Aleph
76{
77
119template <class GT,
120 class Distance = Dft_Dist<GT>,
121 template <class, class> class Ait = Arc_Iterator,
122 template <class, class> class NAit = Node_Arc_Iterator,
123 class SA = Dft_Show_Arc<GT>>
125{
126public:
127 using Node = typename GT::Node;
128 using Arc = typename GT::Arc;
130
131private:
132 const GT* orig_graph = nullptr;
139 bool initialized = false;
140
142 {
144
145 static_assert(std::is_convertible_v<typename GT::Arc_Type, Distance_Type>,
146 "Reweighted_Dist requires arc info convertible to Distance_Type");
147
149 {
150 return static_cast<Distance_Type>(arc->get_info());
151 }
152 };
153
155 {
157 }
158
160 {
161 if constexpr (std::is_integral_v<Distance_Type>)
162 {
164 a < std::numeric_limits<Distance_Type>::min() + b)
165 << "Integer underflow in distance subtraction: " << a << " - " << b;
166
168 a > std::numeric_limits<Distance_Type>::max() + b)
169 << "Integer overflow in distance subtraction: " << a << " - " << b;
170 }
171
172 return a - b;
173 }
174
181 {
182 GT& g = graph_copy.get_graph();
183
184 for (Ait<GT, SA> it(g, sa); it.has_curr(); it.next())
185 {
186 auto arc = it.get_curr();
187 auto u = g.get_src_node(arc);
188 auto v = g.get_tgt_node(arc);
189
190 Distance_Type w = dist(arc);
191 if (auto* orig = copy_to_orig_arc.search(arc))
192 w = dist(orig->second);
193
194 Distance_Type hu = h.find(u);
195 Distance_Type hv = h.find(v);
197
198 // Store reweighted value in the arc
199 arc->get_info() = w_prime;
200 }
201 }
202
204 {
207
208 graph_copy.for_each_mapping([this](Node* orig_node, Node* copy_node) {
210 });
211
213 GT& copy_g = graph_copy.get_graph();
214
215 for (typename GT::Arc_Iterator it(copy_g); it.has_curr(); it.next_ne())
216 {
217 Arc* copy_arc = it.get_curr();
218 Node* csrc = copy_g.get_src_node(copy_arc);
219 Node* ctgt = copy_g.get_tgt_node(copy_arc);
220 buckets[std::make_pair(csrc, ctgt)].append(copy_arc);
221 }
222
223 for (typename GT::Arc_Iterator it(orig); it.has_curr(); it.next_ne())
224 {
225 Arc* orig_arc = it.get_curr();
226 Node* osrc = const_cast<GT&>(orig).get_src_node(orig_arc);
227 Node* otgt = const_cast<GT&>(orig).get_tgt_node(orig_arc);
228
229 Node* csrc = graph_copy.get_copy(osrc);
230 Node* ctgt = graph_copy.get_copy(otgt);
231
232 auto* bucket = buckets.search(std::make_pair(csrc, ctgt));
233 ah_domain_error_if(bucket == nullptr or bucket->second.is_empty())
234 << "Arc mapping mismatch between original and copied graph";
235
236 Arc* copy_arc = bucket->second.remove_first();
238 }
239
241 << "Arc mapping mismatch between original and copied graph";
242 }
243
245 {
247 << "Original graph not available";
248
250
251 if (copy_path.is_empty())
252 return orig_path;
253
254 auto it = copy_path.get_it();
255 auto* node_pair = copy_to_orig_node.search(it.get_current_node());
256 ah_domain_error_if(node_pair == nullptr)
257 << "Node not found in mapping";
258
259 orig_path.init(node_pair->second);
260
261 for (; it.has_curr() and it.has_current_arc(); it.next())
262 {
263 auto* arc_pair = copy_to_orig_arc.search(it.get_current_arc());
264 ah_domain_error_if(arc_pair == nullptr)
265 << "Arc not found in mapping";
266
267 orig_path.append(arc_pair->second);
268 }
269
270 return orig_path;
271 }
272
273public:
287 explicit Johnson(const GT& g, Distance d = Distance(), SA __sa = SA())
288 : orig_graph(&g), graph_copy(g), dist(d), sa(__sa)
289 {
290 GT& gc = graph_copy.get_graph();
291
293
294 // Compute node potentials using Bellman-Ford
295 // This will throw domain_error if negative cycle exists
297 h = bf.compute_nodes_weights();
298
299 // Reweight all arcs
301
302 initialized = true;
303 }
304
306 Johnson() = default;
307
312
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 {
362 ah_domain_error_if(!initialized) << "Johnson not initialized";
363 ah_domain_error_if(src == nullptr or tgt == nullptr) << "Source or target node is null";
364
365 // Get corresponding nodes in the copy
366 Node* csrc = graph_copy.get_copy(src);
367 Node* ctgt = graph_copy.get_copy(tgt);
368
369 GT& gc = graph_copy.get_graph();
370
371 // Run Dijkstra from csrc on reweighted graph
373 dijkstra.paint_min_paths_tree(gc, csrc);
374
376 return Path<GT>(*orig_graph);
377
378 // Get path in copy graph
380 dijkstra.get_min_path(ctgt, copy_path);
381
383 }
384
392 {
393 ah_domain_error_if(!initialized) << "Johnson not initialized";
394
396 GT& gc = graph_copy.get_graph();
397
398 // For each node as source
399 graph_copy.for_each_mapping([&](Node* orig_src, Node* copy_src) {
400 // Run Dijkstra from copy_src
402 dijkstra.paint_min_paths_tree(gc, copy_src);
403
405
406 // Get distance to all targets
407 graph_copy.for_each_mapping([&](Node* orig_tgt, Node* copy_tgt) {
409 {
410 result.insert(std::make_pair(orig_src, orig_tgt),
411 std::numeric_limits<Distance_Type>::infinity());
412 return;
413 }
414
415 Path<GT> path(gc);
416 Distance_Type d_prime = dijkstra.get_min_path(copy_tgt, path);
418 Distance_Type d = d_prime - hs + ht;
419 result.insert(std::make_pair(orig_src, orig_tgt), d);
420 });
421 });
422
423 return result;
424 }
425
436 {
437 ah_domain_error_if(!initialized) << "Johnson not initialized";
438 Node* copy_node = graph_copy.get_copy(node);
439 return h.find(copy_node);
440 }
441
448 GT& get_reweighted_graph() noexcept { return graph_copy.get_graph(); }
449
452 const GT& get_reweighted_graph() const noexcept { return graph_copy.get_graph(); }
453
459 Node* get_copy_node(Node* orig) const { return graph_copy.get_copy(orig); }
460};
461
462} // namespace Aleph
463
464#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:463
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
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:101
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
Generic key-value map implemented on top of a binary search tree.
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:3881
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
Johnson's algorithm for all-pairs shortest paths.
Definition Johnson.H:125
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:154
GraphCopyWithMapping< GT > graph_copy
Copy of graph with node mapping.
Definition Johnson.H:133
DynMapTree< std::pair< Node *, Node * >, Distance_Type > compute_all_pairs_distances()
Compute the shortest distance for all pairs.
Definition Johnson.H:391
GT & get_reweighted_graph() noexcept
Get access to the internal reweighted graph.
Definition Johnson.H:448
bool initialized
Definition Johnson.H:139
DynMapTree< Node *, Node * > copy_to_orig_node
Definition Johnson.H:134
bool is_initialized() const noexcept
Check if the algorithm has been initialized.
Definition Johnson.H:311
Distance_Type get_distance(Node *src, Node *tgt)
Get the shortest distance from source to target.
Definition Johnson.H:320
Distance_Type get_potential(Node *node) const
Get the node potential (h value) for a node.
Definition Johnson.H:435
const GT * orig_graph
Definition Johnson.H:132
typename GT::Arc Arc
Definition Johnson.H:128
static Distance_Type checked_sub(const Distance_Type &a, const Distance_Type &b)
Definition Johnson.H:159
Johnson(const GT &g, Distance d=Distance(), SA __sa=SA())
Construct a Johnson's all-pairs shortest paths executor.
Definition Johnson.H:287
typename Distance::Distance_Type Distance_Type
Definition Johnson.H:129
Johnson()=default
Default constructor (uninitialized state)
typename GT::Node Node
Definition Johnson.H:127
Path< GT > map_copy_path_to_original(const Path< GT > &copy_path) const
Definition Johnson.H:244
Node * get_copy_node(Node *orig) const
Get the copy of a node in the reweighted graph.
Definition Johnson.H:459
void reweight_arcs()
Reweight all arcs using node potentials.
Definition Johnson.H:180
void build_reverse_mappings(const GT &orig)
Definition Johnson.H:203
const GT & get_reweighted_graph() const noexcept
Get const access to the internal reweighted graph.
Definition Johnson.H:452
Distance dist
Definition Johnson.H:137
DynMapTree< Arc *, Arc * > copy_to_orig_arc
Definition Johnson.H:135
DynMapTree< Node *, Distance_Type > h
Node potentials from Bellman-Ford.
Definition Johnson.H:136
Graph_Arc< int > Arc
The node class type.
Definition tpl_graph.H:433
Path on a graph.
Definition tpl_graph.H:2669
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not 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
DynList< T > maps(const C &c, Op op)
Classic map operation.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1164
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
typename Johnson::Distance_Type Distance_Type
Definition Johnson.H:143
Distance_Type operator()(Arc *arc) const
Definition Johnson.H:148
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1119
Distance accessor.
Alias for htlist.H (DynList implementation).
Generic graph and digraph implementations.