87# ifndef BELLMAN_FORD_H
88# define BELLMAN_FORD_H
90# include <type_traits>
205 if constexpr (std::is_integral_v<Distance_Type>)
209 <<
"Integer overflow in distance addition: " << a <<
" + " << b;
213 <<
"Integer underflow in distance addition: " << a <<
" + " << b;
232 typename GT::Node_Iterator it(
g);
233 for (
int i = 0; it.has_curr(); ++i, it.next_ne())
235 auto p = it.get_curr();
262 typename GT::Node_Iterator it(
g);
263 for (
size_t i = 0; it.has_curr(); ++i, it.next())
267 auto p = it.get_curr();
271 ptr->idx =
static_cast<int>(i);
286 template <
class Info_Type>
289 for (
typename GT::Node_Iterator it(
g); it.has_curr(); it.next())
291 auto p = it.get_curr();
322 for (
typename GT::Node_Iterator it(
g); it.has_curr(); it.next_ne())
324 auto node = it.get_curr();
338 auto arc =
ait.get_curr();
398 for (
typename GT::Node_Iterator it(
g); it.has_curr(); it.next_ne())
430 const size_t & n =
g.
vsize();
434 for (
size_t i = 0; i < n - 1; ++i)
437 auto arc = it.get_curr();
443 auto tgt = it.get_tgt_node_ne();
449 const auto & index =
idx(tgt);
480 auto arc = it.get_curr();
492 const auto & index =
idx(tgt);
503 const size_t n =
g.
vsize();
504 for (
size_t i = 0; i < n; ++i)
527 bool negative_cycle =
false;
530 auto arc = it.get_curr();
542 negative_cycle =
true;
543 const auto & index =
idx(tgt);
548 return negative_cycle;
556 auto arc = it.get_curr();
578 const size_t n =
g.
vsize();
579 for (
size_t i = 0; i < n; ++i)
605 <<
"start node cannot be null";
614 if (
not negative_cycle)
619 return negative_cycle;
637 <<
"start node cannot be null";
669 if (
not negative_cycle)
674 return negative_cycle;
688 bool released =
false;
704 if (
dummy !=
nullptr)
710 void release() { released =
true; }
720 for (
typename GT::Node_Iterator it(
g); it.has_curr(); it.next_ne())
722 auto p = it.get_curr();
735 template <
class Info_Type>
752 <<
"start node cannot be null";
761 return negative_cycle;
783 bool released =
false;
796 void release() { released =
true; }
816 for (
typename GT::Node_Iterator it(aux); it.has_curr(); it.next_ne())
818 auto p = it.get_curr();
826 for (
typename GT::Node_Iterator it(aux); it.has_curr(); it.next_ne())
834 ret.append_directed(
static_cast<Node *
>(table.
find(it.get_current_node_ne())));
856 <<
"start node cannot be null";
862 if (
not negative_cycle)
870 WARNING(
"Serious inconsistency. Bellman-Ford algorithm has detected\n"
871 "a negative cycle, but Tarjan algorithm executed on partial\n"
872 "graph has not found such cycle\n\n"
873 "Be very careful, this is provably a bug");
943 std::tuple<Path<GT>,
size_t>
947 <<
"start node cannot be null";
977 return std::make_tuple(std::forward<
Path<GT>>(
ret), i);
991 WARNING(
"Serious inconsistency. Bellman-Ford algorithm has detected\n"
992 "a negative cycle, but Tarjan algorithm executed on partial\n"
993 "graph has not found such cycle\n\n"
994 "Be very careful, this provably is a bug");
998 return std::make_tuple(std::forward<
Path<GT>>(
ret), i);
1011 <<
"start node cannot be null";
1026 if (src == sentinel)
1042 WARNING(
"Serious inconsistency. Bellman-Ford algorithm has detected\n"
1043 "a negative cycle, but Tarjan algorithm executed on partial\n"
1044 "graph has not found such cycle\n\n"
1045 "Be very careful, this provably is a bug");
1112 <<
"Spanning tree has not been painted";
1130 <<
"Graph has not been previously painted";
1133 <<
"node cannot be null";
1141 <<
"Node is not reachable from start node";
1154 if (
auto arc = it.get_curr();
g.
get_tgt_node(arc) == curr &&
1177 <<
"Spanning tree has not been painted";
1182 for (
typename GT::Node_Iterator it(
g); it.has_curr(); it.next_ne())
1184 auto gp = it.get_curr();
1189 for (
typename GT::Node_Iterator it(
g); it.has_curr(); it.next_ne())
1191 auto gtgt = it.get_curr();
1193 if (
gsrc ==
nullptr)
1200 auto a =
ait.get_curr();
1208 <<
"Arc not found between nodes in spanning tree";
1278 if (
dummy !=
nullptr)
1297 if (src == sentinel)
1312 if (
not negative_cycle)
1313 for (
auto it =
g.
get_node_it(); it.has_curr(); it.next_ne())
1315 auto p = it.get_curr();
1372 test_negative_cycle(path);
1379 test_negative_cycle(path);
1397 test_negative_cycle(s, path);
1402 SA && sa =
SA())
const
1405 test_negative_cycle(s, path);
1420 search_negative_cycle(s);
1428 search_negative_cycle(s);
1441 search_negative_cycle();
1449 search_negative_cycle();
Tarjan's algorithm for strongly connected components.
Exception handling system with formatted messages for Aleph-w.
#define ah_logic_error_unless(C)
Throws std::logic_error if condition does NOT hold.
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
#define WARNING(format, args...)
Print a warning message (no-op when MESSAGES is not defined).
RAII guard for exception-safe resource cleanup.
Bellman-Ford algorithm for shortest paths with negative weights.
Distance_Type get_distance(typename GT::Node *node)
Get the accumulated distance to a node from a previously painted tree.
DynArray< Arc * > extract_min_spanning_tree()
Extract the shortest paths tree in a compressed form.
void init_with_indexes(Node *start)
Initialize node cookies with predecessor tracking for path reconstruction.
bool has_computation() const noexcept
Check if a shortest-path tree has been computed or painted.
void uninit()
Release the memory associated with the node cookies.
void relax_arcs() noexcept
Relax all arcs n-1 times (standard Bellman-Ford).
void init_simple(Node *start)
Initialize node cookies for simple mode (without predecessor tracking).
bool faster_paint_spanning_tree(Node *start)
Faster shortest paths tree painting from a start node.
void remove_dummy_node(Node *p)
Remove a dummy node and clean up its cookie.
void link_cookies_and_free(typename GT::Node *start) noexcept
Free node cookies and set up predecessor pointers for path reconstruction.
DynArray< typename GT::Arc * > arcs
DynMapTree< Node *, Distance_Type > compute_nodes_weights()
Returns a mapping with the shortest distances to each node obtained after executing the Bellman-Ford ...
bool test_negative_cycle(typename GT::Node *s, Path< GT > &cycle)
Test for negative cycle and return it if found.
bool last_relax_and_prepare_check_negative_cycle() noexcept
Perform one more relaxation pass and check for negative cycle.
static GT::Node * get_from_queue(DynListQueue< typename GT::Node * > &q)
Remove a node from the queue and clear its in-queue flag.
bool paint_spanning_tree(Node *start)
Paint the shortest paths tree from a start node.
Path< GT > search_negative_cycle(Node *start)
Searches a negative cycle using the faster version of Bellman-Ford algorithm (SPFA variant).
Path< GT > search_negative_cycle()
Path< GT > test_negative_cycle()
Searches and returns a negative cycle (if it exists).
void paint_tree() noexcept
Paint the spanning tree nodes and arcs with the Spanning_Tree bit.
std::tuple< Path< GT >, size_t > search_negative_cycle(double it_factor, const size_t step)
void clear() noexcept
Clear the painted state and reset internal data structures.
bool is_painted() const noexcept
Check if a shortest-path tree has been painted.
bool has_negative_cycle()
Test if a negative cycle exists anywhere in the graph.
bool has_negative_cycle(Node *start)
Test if a negative cycle exists starting from a specific node.
void relax_arcs(typename GT::Node *src, DynListQueue< typename GT::Node * > &q)
Relax outgoing arcs from a source node (SPFA variant).
static void put_in_queue(DynListQueue< typename GT::Node * > &q, typename GT::Node *p)
Insert a node into the queue if not already present (SPFA optimization).
static Distance_Type & accum(Node *p) noexcept
Node * create_dummy_node()
Create a dummy node connected to all nodes with zero-weight edges.
bool check_painted_arcs() noexcept
Check that painted arcs form a valid spanning tree structure.
Distance_Type get_min_path(typename GT::Node *end, Path< GT > &path)
Extract the shortest path to a node from a previously painted tree.
bool test_negative_cycle(Path< GT > &cycle)
Test for negative cycle anywhere in the graph.
static int & idx(Node *p) noexcept
Bellman_Ford(GT &__g, Distance d=Distance(), SA __sa=SA())
Construct a Bellman-Ford executor.
const GT & get_graph() const noexcept
Get reference to the graph.
Node * get_start_node() const noexcept
Get the start node of the last computation.
Path< GT > test_negative_cycle(Node *start)
Search a negative cycle on all possible paths starting from start node.
std::tuple< Path< GT >, size_t > search_negative_cycle(Node *start, double it_factor, const size_t step)
Searches a negative cycle using the faster version of Bellman-Ford algorithm and iteratively searchin...
Distance_Type checked_add(const Distance_Type &a, const Distance_Type &b) const
Path< GT > search_negative_cycle_on_partial_graph()
Build spanning tree from arcs and search for cycle using Tarjan's algorithm.
void build_tree(GT &tree, bool with_map=true)
Extract from the graph a previously painted shortest paths tree.
Distance::Distance_Type Distance_Type
bool last_relax_and_test_negative_cycle() noexcept
Perform one more relaxation pass to detect (but not prepare) negative cycle.
RAII guard that saves and restores graph cookies.
Default distance accessor for arc weights.
void cut(const size_t new_dim=0)
Cut the array to a new dimension; that is, it reduces the dimension of array and frees the remaining ...
T & touch(const size_t i)
Touch the entry i.
void reserve(const size_t l, const size_t r)
Allocate a range of entries.
Dynamic queue of elements of generic type T based on single linked list.
T & put(const T &data)
The type of element.
T get()
Remove the oldest item of the queue.
bool is_empty() const noexcept
Return true if this is empty.
T & insert(const T &item)
Insert a new item by copy.
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.
constexpr bool is_empty() const noexcept
Return true if list is empty.
RAII guard for graph algorithm initialization.
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
virtual void remove_node(Node *node) noexcept
Remove a node from the graph and free its memory.
typename Node::Node_Type Node_Type
The arc class type.
virtual void remove_arc(Arc *arc) noexcept
Remove an arc from the graph and free it.
Graph_Node< int > Node
The graph type.
Graph_Arc< int > Arc
The node class type.
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Filtered iterator for outcoming arcs of a node.
Iterator on nodes and arcs of a path.
bool has_current_node() const noexcept
Return true if the iterator has a current node.
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
void reset_arcs() const
Reset all the arcs of graph (the control bits, the state, the counter and the cookie)
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
static void map_arcs(A1 *p, A2 *q) noexcept
Map the arcs through their cookies.
void reset_bit(Node *node, int bit) const noexcept
Reset the bit of node (to zero)
constexpr size_t vsize() const noexcept
auto get_node_it() const noexcept
Obtains an iterator to the nodes of graph.
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
RAII guards for graph node/arc cookies.
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)
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
#define ARC_BITS(p)
Return the control bits of arc p.
#define NODE_COOKIE(p)
Return the node cookie
void clear_graph(GT &g) noexcept
Clean a graph: all its nodes and arcs are removed and freed.
#define IS_ARC_VISITED(p, bit)
Determine whether the bit field is or not set to one.
#define NODE_BITS(p)
Get the control bits of a node.
Main namespace for Aleph-w library functions.
DynList< T > maps(const C &c, Op op)
Classic map operation.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Filtered iterator on all the arcs of a graph.
Detects if a negative cycle exists and eventually computes it.
bool operator()(GT &g, Path< GT > &path, Distance &d, SA &sa) const
Invokes the detection and calculation of a negative cycle.
Default filter for filtered iterators on arcs.
Filtered iterator of adjacent arcs of a node.
static void set_zero(Arc *a)
TestDigraph::Arc * add_arc(TestDigraph &g, TestDigraph::Node *src, TestDigraph::Node *tgt, int value=0)
Dynamic queue implementation based on linked lists.
Dynamic set implementations based on balanced binary search trees.
Utility algorithms and operations for graphs.