79#include <initializer_list>
96template <
typename Cost_Type =
double>
99 static_assert(std::is_signed_v<std::remove_cv_t<Cost_Type>>
or
100 std::is_floating_point_v<std::remove_cv_t<Cost_Type>>,
101 "Cost_Type must be signed or floating-point to avoid "
102 "underflow when negating costs");
121 pairs.
append(std::make_pair(i,
static_cast<size_t>(j)));
140template <
typename Cost_Type =
double>
144 static_assert(std::is_signed_v<std::remove_cv_t<Cost_Type>>
or
145 std::is_floating_point_v<std::remove_cv_t<Cost_Type>>,
146 "Cost_Type must be signed or floating-point to avoid "
147 "underflow when negating costs");
162 const long n =
static_cast<long>(
n_);
163 const auto sz =
static_cast<size_t>(n + 1);
172 const Cost_Type Inf = std::numeric_limits<Cost_Type>::max() / 2;
175 for (
long i = 1; i <= n; ++i)
195 const long i0 = p(
j0);
199 for (
long j = 1; j <= n; ++j)
206 cost.
read(
static_cast<size_t>(
i0 - 1),
static_cast<size_t>(j - 1)) - u(
i0) - v(j);
222 for (
long j = 0; j <= n; ++j)
232 }
while (p(
j0) != 0);
249 for (
long j = 1; j <= n; ++j)
251 const long row = p(j) - 1;
252 const long col = j - 1;
277 <<
"Hungarian_Assignment: cost matrix must not be empty";
279 if constexpr (std::is_floating_point_v<Cost_Type>)
283 <<
"Hungarian_Assignment: cost[" << i <<
"][" << j <<
"] is not finite";
318 <<
"Hungarian_Assignment: cost matrix must not be empty";
323 <<
"Hungarian_Assignment: cost matrix must not have zero columns";
333 <<
"Hungarian_Assignment: all rows must have the same length";
335 for (
const auto &val :
row)
337 if constexpr (std::is_floating_point_v<Cost_Type>)
339 <<
"Hungarian_Assignment: non-finite cost value at row " << i;
381 pairs.
append(std::make_pair(i,
static_cast<size_t>(j)));
469template <
typename Cost_Type>
472 static_assert(std::is_signed_v<std::remove_cv_t<Cost_Type>>
or
473 std::is_floating_point_v<std::remove_cv_t<Cost_Type>>,
474 "Cost_Type must be signed or floating-point to avoid "
475 "underflow when negating costs");
483 result.
row_to_col = std::move(
ha).extract_row_assignments();
484 result.
col_to_row = std::move(
ha).extract_col_assignments();
507template <
typename Cost_Type>
510 static_assert(std::is_signed_v<std::remove_cv_t<Cost_Type>>
or
511 std::is_floating_point_v<std::remove_cv_t<Cost_Type>>,
512 "Cost_Type must be signed or floating-point to avoid "
513 "underflow when negating costs");
517 using Common = std::common_type_t<Cost_Type, long long>;
519 std::conditional_t<std::is_floating_point_v<Common>,
Common, std::make_signed_t<Common>>;
525 for (
size_t i = 0; i <
rows; ++i)
526 for (
size_t j = 0; j <
cols; ++j)
528 if constexpr (std::is_integral_v<Promoted>
and std::is_signed_v<Promoted>)
532 <<
"Cannot negate minimum integer value";
543 result.
row_to_col = std::move(inner.row_to_col);
544 result.
col_to_row = std::move(inner.col_to_row);
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.
Doubly-linked list (defined in tpl_dynList.H).
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.
Implementation of the Hungarian (Munkres) algorithm.
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.
Array< long > extract_col_assignments() &&noexcept
Move out the column-to-row assignment array.
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.
Array< long > extract_row_assignments() &&noexcept
Move out the row-to-column assignment array.
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).
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.
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
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.