| assignment | R Documentation |
Solve the linear assignment problem (minimum- or maximum-cost matching)
using several algorithms. Forbidden edges can be marked as NA or Inf.
assignment(
cost,
maximize = FALSE,
method = c("auto", "jv", "hungarian", "munkres", "auction", "auction_gs",
"auction_scaled", "sap", "ssp", "sap_dense", "csflow", "hk01", "bruteforce",
"ssap_bucket", "cycle_cancel", "gabow_tarjan", "lapmod", "csa", "ramshaw_tarjan",
"push_relabel", "network_simplex"),
auction_eps = NULL,
eps = NULL,
memory_mode = "auto",
certify = NULL,
cardinality = c("complete", "maximum", "fixed"),
n_matches = NULL,
unmatched_penalty = NULL
)
cost |
Numeric matrix; rows = tasks, columns = agents. |
maximize |
Logical; if |
method |
Character string indicating the algorithm to use. Options: General-purpose solvers:
Auction-based solvers:
Specialized solvers:
Advanced solvers:
One-dimensional problems have their own entry point,
Under
Sparsity and aspect ratio used to divert the choice to Naming a method skips the pass. Rectangular problems are transposed internally so the solver always sees at least as many columns as rows, and the assignment is mapped back afterwards. |
auction_eps |
Optional numeric epsilon for the 'Auction'/'Auction-GS' methods.
If |
eps |
Deprecated. Use |
memory_mode |
One of "auto" (default), "dense", "lazy" or "implicit".
|
certify |
Logical; whether to attach a checked |
cardinality |
How many pairs to produce.
All three are solved exactly by the same solver: the two non-complete modes append dummy columns priced so that the solver's own optimum is the requested objective. |
n_matches |
Integer; the number of pairs to produce. Required when
|
unmatched_penalty |
Numeric; the cost charged for leaving one row
unmatched, under |
method = "auto" selects an algorithm based on problem size and the costs:
Very small (n <= 8 and m <= 8): "bruteforce" — exact enumeration
Binary/constant costs: "hk01" — specialized for 0/1 costs
Otherwise: "jv"
explain_dispatch() reports which rule fired and why. The other solvers are
available by naming them explicitly.
An object of class lap_solve_result, a list with elements:
match — integer vector of length min(nrow(cost), ncol(cost))
giving the assigned column for each row (0 if unassigned).
total_cost — numeric scalar, the objective value.
status — character scalar drawn from solver_status_values(),
computed from what the solver terminated on. "optimal" means the
solver reached its own optimality condition with every row matched;
it is not a checked proof. Use verify_assignment() for that.
method_used — character scalar, the algorithm actually used.
dispatch — list recording how method was chosen: the rule that
fired under "auto", the condition that triggered it, and whether
the method was named explicitly. See explain_dispatch().
certificate — an assignment_certificate, present when one was
checked. See certify.
Under memory_mode = "implicit" the result also carries u and v, the
duals the last restricted master produced, and search: the columns the
first round gave each row (seed_width), the pairs the candidate set ended
up holding (candidate_edges) out of possible_edges, the pairs a cost was
computed for (edges_evaluated), the round count, and rounds, one row per
round of what the master held, what priced out and what each step cost.
"gabow_tarjan" is a bit-scaling algorithm and runs on integer costs. The
conversion is part of the method, so the rule it follows and what it claims
afterwards are both properties of the solve rather than of the caller's
preparation.
Finite costs are shifted so the smallest is zero, multiplied by a scale
factor s, and rounded to the nearest integer. s is set so that
K * s * (max - min) stays at or below 10^13, where K is n + 1 on a
square problem and 2 * min(n, m) + 1 on a rectangular one. K is the
separation the algorithm needs between the optimum and a 1-optimal matching,
and the bound holds every scaled cost clear of the sentinel that marks a
forbidden pair while keeping the path sums the solver forms inside 64-bit
arithmetic. Forbidden pairs take the sentinel and take part in neither the
range nor the conversion.
A matrix whose finite entries are each within 1e-9 of an integer is taken
as an integer matrix: s is one, the shift is an integer, and every cost
reaches the solver as the integer nearest to it. Where those entries are
integers the conversion is exact and the optimum is the optimum of the
instance as supplied; where they are merely near one, each cost moves by at
most 1e-9, so the matching returned costs at most 2 * min(n, m) * 1e-9
more than that optimum. Such a matrix is refused when its range exceeds
1.25 * 10^14 / K, since a scale of one is the only one available and no
choice brings the instance inside the bound; the error names the limit and
points at "jv" or "auction".
Costs that are not integers are solved on the rounded instance. Rounding
moves each cost by at most 1 / (2 * s), so the matching returned costs at
most min(n, m) * K * (max - min) / 10^13 more than the optimum of the
matrix as supplied. On a square problem that is about
n^2 * (max - min) / 10^13, which is 10^-7 of the range at n = 1000 and
10^-5 of it at n = 10000. Duals are divided by s and shifted back, so
they belong to the original matrix; whether the matching is optimal for that
matrix and not only for the rounded one is a question
verify_assignment() answers rather than one this bound settles.
lap_solve() — Tidy interface returning tibbles
lap_solve_kbest() — Find k-best assignments ('Murty' algorithm)
assignment_duals() — Extract dual variables for sensitivity analysis
bottleneck_assignment() — Minimize maximum edge cost (minimax)
sinkhorn() — Entropy-regularized optimal transport
cost <- matrix(c(4,2,5, 3,3,6, 7,5,4), nrow = 3, byrow = TRUE)
res <- assignment(cost)
res$match; res$total_cost
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.