60# ifndef K_SHORTEST_PATHS_H
61# define K_SHORTEST_PATHS_H
66# include <type_traits>
86 template <
class GT,
typename Cost_Type>
94 namespace k_shortest_paths_detail
96 template <
class GT,
typename Cost_Type>
105 template <
class GT,
typename Cost_Type>
118 template <
class GT,
class SA>
153 template <
class GT,
class Distance>
177 <<
"Reverse_Arc_Distance: reverse arc map is null";
179 <<
"Reverse_Arc_Distance: base distance functor is null";
184 <<
"Reverse_Arc_Distance: missing reverse-to-original arc map";
191 template <
class GT,
class Distance,
class SA>
199 static_assert(std::is_arithmetic_v<Cost_Type>,
200 "K shortest paths require arithmetic arc costs");
204 Arc *arc = it.get_curr_ne();
207 if constexpr (std::is_floating_point_v<Cost_Type>)
209 <<
"K shortest paths require finite arc weights";
212 <<
"K shortest paths require non-negative arc weights";
217 template <
class GT,
typename Cost_Type>
225 template <
class GT,
typename Cost_Type>
233 for (
auto it = path.
nodes.
get_it(); it.has_curr(); it.next_ne())
236 for (
auto it = path.
arcs.
get_it(); it.has_curr(); it.next_ne())
243 template <
class GT,
typename Cost_Type>
253 if (it.has_current_arc())
261 template <
class GT,
typename Cost_Type>
273 it.has_curr(); it.next_ne())
280 path.
append(it.get_curr_ne());
287 template <
class GT,
typename Cost_Type>
298 while (
an.has_curr())
300 if (
an.get_curr_ne() !=
bn.get_curr_ne())
308 while (
aa.has_curr())
310 if (
aa.get_curr_ne() !=
ba.get_curr_ne())
320 template <
class GT,
typename Cost_Type>
342 template <
class GT,
typename Cost_Type>
346 for (
const auto & p: container)
353 template <
class GT,
typename Cost_Type>
365 template <
class GT,
typename Cost_Type>
371 return p ==
nullptr ?
nullptr : p->second;
375 template <
class GT,
typename Cost_Type>
381 return p ==
nullptr ?
nullptr : p->second;
385 template <
template <
class,
class>
class Itor,
401 Node * node = it.get_curr_ne();
407 auto &
mg =
const_cast<GT &
>(g);
417 Node * node = it.get_curr_ne();
426 if (parent ==
nullptr)
429 Arc * selected =
nullptr;
432 Arc * arc =
ait.get_current_arc_ne();
440 if (selected ==
nullptr)
448 Arc * arc =
ait.get_current_arc_ne();
449 if (
ait.get_tgt_node() != parent)
472 template <
class GT,
class Distance,
class SA>
492 Node * node = it.get_curr_ne();
504 Arc * arc = it.get_curr_ne();
509 orig_to_rev.
find(tgt),
510 orig_to_rev.
find(src),
518 Reverse_Distance::base_ptr = &distance;
525 Reverse_Distance::map_ptr =
nullptr;
526 Reverse_Distance::base_ptr =
nullptr;
557 Arc * selected =
nullptr;
564 Arc * arc =
ait.get_current_arc_ne();
568 if (selected ==
nullptr)
593 template <
class GT,
class Distance,
class SA>
602 g, target, distance, sa);
605 g, target, distance, sa);
609 template <
class GT,
typename Cost_Type>
626 while (curr != target)
633 if (
next ==
nullptr or arc ==
nullptr)
645 template <
class GT,
class Distance,
class SA>
658 if (forbidden_nodes !=
nullptr and
662 if (source == target)
666 out.nodes.append(source);
671 const_cast<GT &
>(g).reset_nodes();
672 const_cast<GT &
>(g).reset_arcs();
679 if (dist == std::numeric_limits<Cost_Type>::max()
or shortest.is_empty())
687 template <
class GT,
class Distance>
702 template <
class GT,
typename Cost_Type>
718 it.has_curr(); it.next_ne())
726 candidate.nodes.append(it.get_curr_ne());
737 template <
class GT,
typename Cost_Type>
758 it.has_curr(); it.next_ne())
766 candidate.nodes.append(it.get_curr_ne());
777 template <
class GT,
class Distance,
class SA,
typename Cost_Type>
911 if (source == target)
926 if (
not k_shortest_paths_detail::shortest_path_filtered<GT, Distance, SA>(
927 g, source, target, distance, sa,
nullptr,
935 const State & previous =
accepted.get_last();
937 k_shortest_paths_detail::make_path_snapshot<GT, Cost_Type>(previous);
946 k_shortest_paths_detail::make_path_snapshot<GT, Cost_Type>(p));
968 if (
not k_shortest_paths_detail::shortest_path_filtered<GT, Distance, SA>(
983 k_shortest_paths_detail::compute_cost_from_arcs<GT, Distance>(
995 for (
size_t i = 1; i <
candidates.size(); ++i)
1008 for (
const State & state:
accepted)
1011 item.total_cost = state.total_cost;
1081 ah_domain_error_if(source ==
nullptr) <<
"eppstein_k_shortest_paths(): source is null";
1082 ah_domain_error_if(target ==
nullptr) <<
"eppstein_k_shortest_paths(): target is null";
1086 if (source == target)
1100 const auto suffix_index =
1101 k_shortest_paths_detail::build_suffix_index<GT, Distance, SA>(
1102 g, target, distance, sa);
1105 if (
not k_shortest_paths_detail::build_suffix_state<GT, Cost_Type>(
1106 g, suffix_index, source, target, first))
1110 k_shortest_paths_detail::generate_general_deviation_candidates<GT, Distance, SA, Cost_Type>(
1116 for (
size_t i = 1; i <
candidates.size(); ++i)
1130 k_shortest_paths_detail::generate_general_deviation_candidates<GT, Distance, SA, Cost_Type>(
1134 for (
const State & state:
accepted)
1137 item.total_cost = state.total_cost;
1206 const size_t k)
const
1258 const size_t k)
const
Dijkstra's shortest path algorithm.
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
WeightedDigraph::Node Node
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
Simple dynamic array with automatic resizing and functional operations.
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
T & append(const T &data)
Append a copy of data
void reserve(size_t cap)
Reserves cap cells into the array.
RAII guard that saves and restores graph cookies.
Default distance accessor for arc weights.
Spanning tree calculation of all shortest paths from a given node according to Dijkstra's algorithm.
void append(Dlink *node) noexcept
Insert node before this.
Iterator on the items of list.
Dynamic singly linked list with functional programming support.
T & append(const T &item)
T & get_first() const
Return the first item of the list.
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.
Dynamic set backed by balanced binary search trees with automatic memory management.
Key * insert(const Key &key)
Inserts a key into the dynamic set.
bool contains(const Key &key) const
Checks if a key exists in the set.
Functor wrapper for Eppstein-style k-shortest paths API.
DynList< K_Shortest_Path_Item< GT, typename Distance::Distance_Type > > operator()(const GT &g, typename GT::Node *source, typename GT::Node *target, const size_t k) const
Compute k shortest general (loopy) paths.
Eppstein_K_Shortest_Paths(Distance distance=Distance(), SA sa=SA())
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
bool has_curr() const noexcept
constexpr bool is_empty() const noexcept
size_t size() const noexcept
Count the number of elements of the list.
Graph_Node< Node_Info > Node
The graph type.
Graph_Arc< Arc_Info > Arc
The node class type.
Filtered iterator on the nodes of a graph.
Iterator on nodes and arcs of a path.
bool has_current_node() const noexcept
Return true if the iterator has a current node.
void set_graph(const GT &__g, Node *start_node=nullptr)
Set the graph of the path.
void append(Arc *arc)
Append an arc to the path.
void append_directed(Node *p)
Append a node to a directed path.
Functor wrapper for Yen's k-shortest loopless paths algorithm.
DynList< K_Shortest_Path_Item< GT, typename Distance::Distance_Type > > operator()(const GT &g, typename GT::Node *source, typename GT::Node *target, const size_t k) const
Compute k shortest loopless paths.
Yen_K_Shortest_Paths(Distance distance=Distance(), SA sa=SA())
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.
bool is_digraph() const noexcept
Return true if the graph this is directed.
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
RAII guards for graph node/arc cookies.
DynArray< Graph::Arc * > arcs
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
#define NODE_COOKIE(p)
Return the node cookie
DynList< K_Shortest_Path_Item< GT, typename Distance::Distance_Type > > eppstein_k_shortest_paths(const GT &g, typename GT::Node *source, typename GT::Node *target, const size_t k, Distance distance=Distance(), SA sa=SA())
Compute k shortest general (loopy) paths.
#define IS_ARC_VISITED(p, bit)
Determine whether the bit field is or not set to one.
DynList< K_Shortest_Path_Item< GT, typename Distance::Distance_Type > > yen_k_shortest_paths(const GT &g, typename GT::Node *source, typename GT::Node *target, const size_t k, Distance distance=Distance(), SA sa=SA())
Compute k shortest loopless paths using Yen's algorithm.
Singly linked list implementations with head-tail access.
Path< GT > state_to_path(const GT &g, const Path_State< GT, Cost_Type > &state)
GT::Node * get_tree_next(const Suffix_Index< GT, Cost_Type > &index, typename GT::Node *node)
Suffix_Index< GT, typename Distance::Distance_Type > build_suffix_index(const GT &g, typename GT::Node *target, Distance distance, SA sa)
Path_State< GT, Cost_Type > compose_general_candidate(const Path_Snapshot< GT, Cost_Type > &base_path, const size_t spur_index, typename GT::Arc *deviation_arc, typename GT::Node *deviation_next_node, const Path_State< GT, Cost_Type > &suffix_state)
bool contains_path(const Array< Path_State< GT, Cost_Type > > &container, const Path_State< GT, Cost_Type > &candidate)
bool shortest_path_filtered(const GT &g, typename GT::Node *source, typename GT::Node *target, Distance distance, SA sa, const DynSetTree< typename GT::Node * > *forbidden_nodes, const DynSetTree< typename GT::Arc * > *forbidden_arcs, Path_State< GT, typename Distance::Distance_Type > &out)
void generate_general_deviation_candidates(const GT &g, const Path_State< GT, Cost_Type > &base_path, typename GT::Node *target, const Suffix_Index< GT, Cost_Type > &suffix_index, Distance distance, SA sa, const Array< Path_State< GT, Cost_Type > > &accepted, Array< Path_State< GT, Cost_Type > > &candidates)
bool same_path_sequence(const Path_State< GT, Cost_Type > &a, const Path_State< GT, Cost_Type > &b)
Cost_Type get_dist_to_target(const Suffix_Index< GT, Cost_Type > &index, typename GT::Node *node)
Path_State< GT, Cost_Type > compose_candidate(const Path_Snapshot< GT, Cost_Type > &base_path, const size_t spur_index, const Path_State< GT, Cost_Type > &spur_state)
bool build_suffix_state(const GT &g, const Suffix_Index< GT, Cost_Type > &index, typename GT::Node *start, typename GT::Node *target, Path_State< GT, Cost_Type > &out_suffix)
Suffix_Index< GT, typename Distance::Distance_Type > build_suffix_index_with_itor(const GT &g, typename GT::Node *target, Distance distance, SA sa)
Path_State< GT, Cost_Type > path_to_state(const Path< GT > &path, const Cost_Type total_cost)
Suffix_Index< GT, typename Distance::Distance_Type > build_suffix_index_digraph(const GT &g, typename GT::Node *target, Distance distance, SA sa)
Distance::Distance_Type compute_cost_from_arcs(const DynList< typename GT::Arc * > &arcs, Distance distance)
void validate_non_negative_weights(const GT &g, Distance distance, SA sa)
Path_Snapshot< GT, Cost_Type > make_path_snapshot(const Path_State< GT, Cost_Type > &path)
bool same_prefix_nodes(const Path_Snapshot< GT, Cost_Type > &a, const Path_Snapshot< GT, Cost_Type > &b, const size_t spur_index)
GT::Arc * get_tree_arc(const Suffix_Index< GT, Cost_Type > &index, typename GT::Node *node)
T checked_add(const T &a, const T &b)
Safely add two distance values with overflow checking.
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
Container2< typename Container1::Item_Type > filter(Container1 &container, Operation &operation)
Filter elements that satisfy operation.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
std::pair< First, Second > pair
Alias to std::pair kept for backwards compatibility.
void next()
Advance all underlying iterators (bounds-checked).
Common utilities and base class for shortest path algorithms.
Filtered iterator on all the arcs of a graph.
Default filter for filtered iterators on arcs.
A shortest-path item returned by k-shortest algorithms.
Cost_Type total_cost
Total path cost.
Path< GT > path
Path from source to target.
Filtered iterator of adjacent arcs of a node.
const DynSetTree< Arc * > * forbidden_arcs
bool operator()(Arc *arc) const
const DynSetTree< Node * > * forbidden_nodes
Array< typename GT::Arc * > arcs
Array< typename GT::Node * > nodes
DynList< typename GT::Arc * > arcs
DynList< typename GT::Node * > nodes
static thread_local const Distance * base_ptr
typename Distance::Distance_Type Distance_Type
static thread_local const DynMapTree< Arc *, Arc * > * map_ptr
Context for reverse-graph Dijkstra in build_suffix_index_digraph().
Distance_Type operator()(Arc *rev_arc) const
DynMapTree< Node *, Arc * > tree_arc
DynMapTree< Node *, Node * > tree_next
DynMapTree< Node *, Cost_Type > dist_to_target
Dynamic array container with automatic resizing.
Dynamic key-value map based on balanced binary search trees.
Dynamic set implementations based on balanced binary search trees.