64# ifndef MIN_MEAN_CYCLE_H
65# define MIN_MEAN_CYCLE_H
72# include <type_traits>
89 template <AlephGraph GT,
typename Cost_Type>
93 long double minimum_mean = std::numeric_limits<long double>::infinity();
113 long double minimum_mean = std::numeric_limits<long double>::infinity();
117 namespace min_mean_cycle_detail
119 template <AlephGraph GT,
typename Cost_Type>
128 template <AlephGraph GT, ArcDistance<GT> Distance, ArcFilter<GT> SA>
134 static_assert(std::is_arithmetic_v<Cost_Type>,
135 "Karp minimum mean cycle requires arithmetic arc costs");
139 Arc * arc = it.get_curr_ne();
142 if constexpr (std::is_floating_point_v<Cost_Type>)
144 <<
"Karp minimum mean cycle requires finite arc weights";
149 template <
typename Cost_Type>
152 if constexpr (std::is_floating_point_v<Cost_Type>)
182 template <AlephGraph
GT,
197 <<
"karp_minimum_mean_cycle(): graph must be directed";
207 n > std::numeric_limits<size_t>::max() - 1
208 or (n + 1) > std::numeric_limits<size_t>::max() / n)
209 <<
"karp_minimum_mean_cycle(): DP table size overflow";
219 Node * node = it.get_curr_ne();
221 node_to_idx.
insert(node, idx);
226 for (
size_t i = 0; i < n; ++i)
231 Arc * arc = it.get_curr_ne();
235 const size_t src_idx = node_to_idx.
find(src);
241 const Cost_Type inf = std::numeric_limits<Cost_Type>::max();
248 const auto state_of = [n](
const size_t k,
const size_t v)
253 for (
size_t v = 0; v < n; ++v)
256 for (
size_t k = 1;
k <= n; ++
k)
257 for (
size_t v = 0; v < n; ++v)
274 "Karp minimum mean cycle accumulation became non-finite");
291 const long double ld_inf = std::numeric_limits<long double>::infinity();
296 for (
size_t v = 0; v < n; ++v)
305 for (
size_t k = 0;
k < n; ++
k)
311 const long double num =
static_cast<long double>(
dnv)
312 -
static_cast<long double>(
dkv);
313 const long double den =
static_cast<long double>(n -
k);
314 const long double ratio = num /
den;
326 result.has_cycle =
true;
336 if (
not result.has_cycle)
351 for (
size_t k = n;
k > 0; --
k)
357 if (
pred < 0
or arc ==
nullptr)
361 curr =
static_cast<size_t>(
pred);
378 const size_t invalid_pos = std::numeric_limits<size_t>::max();
387 for (
size_t i = 0; i <
walk_nodes.size(); ++i)
391 <<
"karp_minimum_mean_cycle(): invalid witness node index";
393 const size_t j = first_pos[
node_idx];
400 const size_t len = i - j;
405 for (
size_t p = j; p < i; ++p)
411 "Karp minimum mean cycle witness accumulation became non-finite");
415 /
static_cast<long double>(len);
449 template <AlephGraph
GT,
463 <<
"karp_minimum_mean_cycle_value(): graph must be directed";
473 n > std::numeric_limits<size_t>::max() - 1
474 or (n + 1) > std::numeric_limits<size_t>::max() / n)
475 <<
"karp_minimum_mean_cycle_value(): DP table size overflow";
481 node_to_idx.
insert(it.get_curr_ne(), idx);
486 for (
size_t i = 0; i < n; ++i)
491 Arc * arc = it.get_curr_ne();
494 const size_t src_idx = node_to_idx.
find(src);
499 const Cost_Type inf = std::numeric_limits<Cost_Type>::max();
503 const auto state_of = [n](
const size_t k,
const size_t v)
508 for (
size_t v = 0; v < n; ++v)
511 for (
size_t k = 1;
k <= n; ++
k)
512 for (
size_t v = 0; v < n; ++v)
528 "Karp minimum mean cycle accumulation became non-finite");
539 const long double ld_inf = std::numeric_limits<long double>::infinity();
542 for (
size_t v = 0; v < n; ++v)
550 for (
size_t k = 0;
k < n; ++
k)
556 const long double num =
static_cast<long double>(
dnv)
557 -
static_cast<long double>(
dkv);
558 const long double den =
static_cast<long double>(n -
k);
559 const long double ratio = num /
den;
586 template <AlephGraph
GT,
595 g, std::move(distance), std::move(sa));
603 template <AlephGraph
GT,
612 g, std::move(distance), std::move(sa));
620 template <AlephGraph
GT,
648 template <AlephGraph
GT,
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.
C++20 concepts for the protocol shared by graph algorithms.
WeightedDigraph::Node Node
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
size_t size_t int32_t value
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.
Doubly-linked list (defined in tpl_dynList.H).
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.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
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.
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.