63# ifndef MIN_MEAN_CYCLE_H
64# define MIN_MEAN_CYCLE_H
69# include <type_traits>
86 template <
class GT,
typename Cost_Type>
90 long double minimum_mean = std::numeric_limits<long double>::infinity();
110 long double minimum_mean = std::numeric_limits<long double>::infinity();
114 namespace min_mean_cycle_detail
116 template <
class GT,
typename Cost_Type>
125 template <
class GT,
class Distance,
class SA>
131 static_assert(std::is_arithmetic_v<Cost_Type>,
132 "Karp minimum mean cycle requires arithmetic arc costs");
136 Arc * arc = it.get_curr_ne();
139 if constexpr (std::is_floating_point_v<Cost_Type>)
141 <<
"Karp minimum mean cycle requires finite arc weights";
146 template <
typename Cost_Type>
149 if constexpr (std::is_floating_point_v<Cost_Type>)
194 <<
"karp_minimum_mean_cycle(): graph must be directed";
204 n > std::numeric_limits<size_t>::max() - 1
205 or (n + 1) > std::numeric_limits<size_t>::max() / n)
206 <<
"karp_minimum_mean_cycle(): DP table size overflow";
216 Node * node = it.get_curr_ne();
218 node_to_idx.
insert(node, idx);
223 for (
size_t i = 0; i < n; ++i)
228 Arc * arc = it.get_curr_ne();
232 const size_t src_idx = node_to_idx.
find(src);
238 const Cost_Type inf = std::numeric_limits<Cost_Type>::max();
245 const auto state_of = [n](
const size_t k,
const size_t v)
250 for (
size_t v = 0; v < n; ++v)
253 for (
size_t k = 1;
k <= n; ++
k)
254 for (
size_t v = 0; v < n; ++v)
271 "Karp minimum mean cycle accumulation became non-finite");
288 const long double ld_inf = std::numeric_limits<long double>::infinity();
293 for (
size_t v = 0; v < n; ++v)
302 for (
size_t k = 0;
k < n; ++
k)
308 const long double num =
static_cast<long double>(
dnv)
309 -
static_cast<long double>(
dkv);
310 const long double den =
static_cast<long double>(n -
k);
311 const long double ratio = num /
den;
323 result.has_cycle =
true;
333 if (
not result.has_cycle)
348 for (
size_t k = n;
k > 0; --
k)
354 if (
pred < 0
or arc ==
nullptr)
358 curr =
static_cast<size_t>(
pred);
375 const size_t invalid_pos = std::numeric_limits<size_t>::max();
384 for (
size_t i = 0; i <
walk_nodes.size(); ++i)
388 <<
"karp_minimum_mean_cycle(): invalid witness node index";
390 const size_t j = first_pos[
node_idx];
397 const size_t len = i - j;
402 for (
size_t p = j; p < i; ++p)
408 "Karp minimum mean cycle witness accumulation became non-finite");
412 /
static_cast<long double>(len);
460 <<
"karp_minimum_mean_cycle_value(): graph must be directed";
470 n > std::numeric_limits<size_t>::max() - 1
471 or (n + 1) > std::numeric_limits<size_t>::max() / n)
472 <<
"karp_minimum_mean_cycle_value(): DP table size overflow";
478 node_to_idx.
insert(it.get_curr_ne(), idx);
483 for (
size_t i = 0; i < n; ++i)
488 Arc * arc = it.get_curr_ne();
491 const size_t src_idx = node_to_idx.
find(src);
496 const Cost_Type inf = std::numeric_limits<Cost_Type>::max();
500 const auto state_of = [n](
const size_t k,
const size_t v)
505 for (
size_t v = 0; v < n; ++v)
508 for (
size_t k = 1;
k <= n; ++
k)
509 for (
size_t v = 0; v < n; ++v)
525 "Karp minimum mean cycle accumulation became non-finite");
536 const long double ld_inf = std::numeric_limits<long double>::infinity();
539 for (
size_t v = 0; v < n; ++v)
547 for (
size_t k = 0;
k < n; ++
k)
553 const long double num =
static_cast<long double>(
dnv)
554 -
static_cast<long double>(
dkv);
555 const long double den =
static_cast<long double>(n -
k);
556 const long double ratio = num /
den;
592 g, std::move(distance), std::move(sa));
609 g, std::move(distance), std::move(sa));
Exception handling system with formatted messages for Aleph-w.
#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 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
bool has_curr() const noexcept
Check if there is a current valid item.
Simple dynamic array with automatic resizing and functional operations.
void reserve(size_t cap)
Reserves cap cells into the array.
Default distance accessor for arc weights.
Dynamic singly linked list with functional programming support.
Generic key-value map implemented on top of a binary search tree.
Pair * append(const Key &key, const Data &data)
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair.
Data & find(const Key &key)
Find the value associated with key.
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
Functor wrapper for value-only minimum mean cycle.
Min_Mean_Cycle_Value_Result operator()(const GT &g) const
Karp_Minimum_Mean_Cycle_Value(Distance distance=Distance(), SA sa=SA())
Functor wrapper for Karp minimum mean cycle.
Min_Mean_Cycle_Result< GT, typename Distance::Distance_Type > operator()(const GT &g) const
Karp_Minimum_Mean_Cycle(Distance distance=Distance(), SA sa=SA())
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.
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)
DynArray< Graph::Node * > nodes
Min_Mean_Cycle_Value_Result minimum_mean_cycle_value(const GT &g, Distance distance=Distance(), SA sa=SA())
Alias for karp_minimum_mean_cycle_value().
Min_Mean_Cycle_Result< GT, typename Distance::Distance_Type > minimum_mean_cycle(const GT &g, Distance distance=Distance(), SA sa=SA())
Alias for karp_minimum_mean_cycle().
Min_Mean_Cycle_Value_Result karp_minimum_mean_cycle_value(const GT &g, Distance distance=Distance(), SA sa=SA())
Compute only the minimum mean value (without witness walk).
Min_Mean_Cycle_Result< GT, typename Distance::Distance_Type > karp_minimum_mean_cycle(const GT &g, Distance distance=Distance(), SA sa=SA())
Compute minimum mean cycle by Karp's algorithm.
Singly linked list implementations with head-tail access.
Freq_Node * pred
Predecessor node in level-order traversal.
void validate_weights(const GT &g, Distance distance, SA sa)
void validate_finite_accumulator(const Cost_Type &value, const char *context)
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.
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.
Common utilities and base class for shortest path algorithms.
Filtered iterator on all the arcs of a graph.
Iterator on the items of an array.
Default filter for filtered iterators on arcs.
Result of minimum mean cycle computation.
size_t cycle_length
Number of arcs in witness cycle.
Cost_Type cycle_total_cost
Weight sum of witness cycle.
GT::Node * witness_node
Vertex used in Karp witness extraction.
bool has_cycle
True if at least one directed cycle exists.
DynList< typename GT::Node * > cycle_nodes
Closed witness walk (first node repeated at end).
DynList< typename GT::Arc * > cycle_arcs
Witness arcs aligned with cycle_nodes.
Lightweight minimum-mean-cycle value result.
bool has_cycle
True if at least one directed cycle exists.
Dynamic array container with automatic resizing.
Dynamic key-value map based on balanced binary search trees.