93# include <type_traits>
95# include <initializer_list>
113 template <
typename Cost_Type =
double>
116 static_assert(std::is_signed_v<std::remove_cv_t<Cost_Type>>
or
117 std::is_floating_point_v<std::remove_cv_t<Cost_Type>>,
118 "Cost_Type must be signed or floating-point to avoid "
119 "underflow when negating costs");
138 pairs.
append(std::make_pair(i,
static_cast<size_t>(j)));
174 template <
typename Cost_Type =
double>
177 static_assert(std::is_signed_v<std::remove_cv_t<Cost_Type>>
or
178 std::is_floating_point_v<std::remove_cv_t<Cost_Type>>,
179 "Cost_Type must be signed or floating-point to avoid "
180 "underflow when negating costs");
195 const long n =
static_cast<long>(
n_);
196 const auto sz =
static_cast<size_t>(n + 1);
205 const Cost_Type Inf = std::numeric_limits<Cost_Type>::max() / 2;
208 for (
long i = 1; i <= n; ++i)
228 const long i0 = p(
j0);
232 for (
long j = 1; j <= n; ++j)
239 static_cast<size_t>(j - 1)) - u(
i0) - v(j);
255 for (
long j = 0; j <= n; ++j)
284 for (
long j = 1; j <= n; ++j)
286 const long row = p(j) - 1;
287 const long col = j - 1;
312 <<
"Hungarian_Assignment: cost matrix must not be empty";
347 "Hungarian_Assignment: cost matrix must not be empty";
357 for (
const auto & row:
rows)
360 <<
"Hungarian_Assignment: all rows must have the same length";
362 for (
const auto & val: row)
387 <<
"Hungarian_Assignment::get_assignment: row " << row
404 pairs.
append(std::make_pair(i,
static_cast<size_t>(j)));
459 template <
typename Cost_Type>
463 static_assert(std::is_signed_v<std::remove_cv_t<Cost_Type>>
or
464 std::is_floating_point_v<std::remove_cv_t<Cost_Type>>,
465 "Cost_Type must be signed or floating-point to avoid "
466 "underflow when negating costs");
497 template <
typename Cost_Type>
501 static_assert(std::is_signed_v<std::remove_cv_t<Cost_Type>>
or
502 std::is_floating_point_v<std::remove_cv_t<Cost_Type>>,
503 "Cost_Type must be signed or floating-point to avoid "
504 "underflow when negating costs");
508 using Common = std::common_type_t<Cost_Type, long long>;
509 using Promoted = std::conditional_t<std::is_floating_point_v<Common>,
511 std::make_signed_t<Common>>;
513 const size_t rows = cost.
rows();
514 const size_t cols = cost.
cols();
517 for (
size_t i = 0; i < rows; ++i)
518 for (
size_t j = 0; j < cols; ++j)
520 if constexpr (std::is_signed_v<Promoted>)
524 <<
"Cannot negate minimum integer value";
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Standard functor implementations and comparison objects.
Simple dynamic array with automatic resizing and functional operations.
Dynamic singly linked list with functional programming support.
T & append(const T &item)
Dynamic matrix with sparse storage.
const T & read(const size_t i, const size_t j) const
Read the entry at position (i, j).
constexpr size_t cols() const noexcept
Get the number of columns.
void allocate()
Pre-allocate memory for the entire matrix.
constexpr size_t rows() const noexcept
Get the number of rows.
Hungarian (Munkres) algorithm for optimal assignment.
DynList< std::pair< size_t, size_t > > get_assignments() const
Get all assignment pairs.
long get_assignment(const size_t row) const
Get the column assigned to a given row.
const Array< long > & get_row_assignments() const noexcept
Get the row-to-column assignment array.
Array< long > col_to_row_
Hungarian_Assignment(std::initializer_list< std::initializer_list< Cost_Type > > rows)
Construct and solve from an initializer list of rows.
const Array< long > & get_col_assignments() const noexcept
Get the column-to-row assignment array.
size_t cols() const noexcept
Get the original number of columns.
Array< long > row_to_col_
size_t dimension() const noexcept
Get the padded square dimension.
size_t rows() const noexcept
Get the original number of rows.
void solve(const DynMatrix< Cost_Type > &cost)
Core algorithm: shortest augmenting paths with dual variables.
Hungarian_Assignment(const DynMatrix< Cost_Type > &cost)
Construct and solve from a DynMatrix cost matrix.
Cost_Type get_total_cost() const noexcept
Get the optimal total cost.
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_j0_function > > j0(const __gmp_expr< T, U > &expr)
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_j1_function > > j1(const __gmp_expr< T, U > &expr)
Hungarian_Result< Cost_Type > hungarian_max_assignment(const DynMatrix< Cost_Type > &cost)
Compute maximum-profit assignment (free function).
Hungarian_Result< Cost_Type > hungarian_assignment(const DynMatrix< Cost_Type > &cost)
Compute minimum-cost assignment (free function).
Singly linked list implementations with head-tail access.
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.
Result of the Hungarian assignment algorithm.
Array< long > col_to_row
column j is assigned to row col_to_row[j]
Cost_Type total_cost
Optimal total cost.
Array< long > row_to_col
row i is assigned to column row_to_col[i]
DynList< std::pair< size_t, size_t > > get_pairs() const
Get the assignment pairs, excluding dummy entries.
size_t orig_rows
Original number of rows.
size_t orig_cols
Original number of columns.
Dynamic array container with automatic resizing.
Dynamic matrix with lazy allocation.