Nothing
# tests/testthat/test-assignment-lapmod.R
# Tests for LAPMOD sparse LAP solver
test_that("lapmod solves simple 3x3 problem correctly", {
cost <- matrix(c(4, 2, 5,
3, 3, 6,
7, 5, 4), nrow = 3, byrow = TRUE)
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
expect_equal(result$method_used, "lapmod")
expect_equal(length(result$match), 3)
expect_true(all(result$match >= 1 & result$match <= 3))
expect_equal(length(unique(result$match)), 3) # All different columns
# Check cost is correct (should be 9: row1->col2 (2) + row2->col1 (3) + row3->col3 (4))
expect_equal(result$total_cost, 9)
})
test_that("lapmod handles rectangular matrix (n < m)", {
cost <- matrix(c(1, 2, 3, 4,
5, 1, 2, 3,
4, 5, 1, 2), nrow = 3, byrow = TRUE)
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
expect_equal(length(result$match), 3)
expect_true(all(result$match >= 1 & result$match <= 4))
expect_equal(length(unique(result$match)), 3)
# Optimal: row1->col1 (1) + row2->col2 (1) + row3->col3 (1) = 3
expect_equal(result$total_cost, 3)
})
test_that("lapmod handles NA (forbidden) entries", {
cost <- matrix(c(NA, 2, 5,
3, NA, 6,
7, 5, NA), nrow = 3, byrow = TRUE)
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
# Should avoid diagonal (NA entries)
expect_true(result$match[1] != 1)
expect_true(result$match[2] != 2)
expect_true(result$match[3] != 3)
})
test_that("lapmod handles Inf (forbidden) entries", {
cost <- matrix(c(Inf, 2, 5,
3, Inf, 6,
7, 5, Inf), nrow = 3, byrow = TRUE)
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
# Should avoid diagonal (Inf entries)
expect_true(result$match[1] != 1)
expect_true(result$match[2] != 2)
expect_true(result$match[3] != 3)
})
test_that("lapmod handles sparse matrix (many NA entries)", {
# Create a 10x10 matrix with ~70% NA
set.seed(42)
n <- 10
cost <- matrix(NA_real_, nrow = n, ncol = n)
# Fill in ~30% of entries
for (i in 1:n) {
# Ensure each row has at least 2-3 options
cols <- sample(1:n, 3)
for (j in cols) {
cost[i, j] <- runif(1, 1, 10)
}
}
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
expect_equal(length(result$match), n)
expect_equal(length(unique(result$match)), n)
# Verify no NA was chosen
for (i in 1:n) {
expect_false(is.na(cost[i, result$match[i]]))
}
})
test_that("lapmod maximization works", {
cost <- matrix(c(4, 2, 5,
3, 3, 6,
7, 5, 4), nrow = 3, byrow = TRUE)
min_result <- assignment(cost, maximize = FALSE, method = "lapmod")
max_result <- assignment(cost, maximize = TRUE, method = "lapmod")
expect_lt(min_result$total_cost, max_result$total_cost)
# Max should be 18: row1->col3 (5) + row2->col3 (6)... wait need unique
# Max should be: row1->col3 (5) + row2->col2 (3)... let me check
# Actually: row3->col1 (7) + row2->col3 (6) + row1->col2 (2) = 15? No...
# row3->col1 (7) + row2->col3 (6) + row1->col3 can't both have col3
# Maximum unique: row1->col3 (5) + row2->col3 can't...
# Let's just check it's bigger
expect_true(max_result$total_cost >= min_result$total_cost)
})
test_that("lapmod gives same result as JV for dense matrix", {
set.seed(123)
n <- 20
cost <- matrix(runif(n * n, 1, 100), nrow = n)
jv_result <- assignment(cost, method = "jv")
lapmod_result <- assignment(cost, method = "lapmod")
expect_equal(lapmod_result$total_cost, jv_result$total_cost, tolerance = 1e-9)
})
test_that("lapmod gives same result as JV for rectangular matrix", {
set.seed(456)
n <- 15
m <- 25
cost <- matrix(runif(n * m, 1, 100), nrow = n, ncol = m)
jv_result <- assignment(cost, method = "jv")
lapmod_result <- assignment(cost, method = "lapmod")
expect_equal(lapmod_result$total_cost, jv_result$total_cost, tolerance = 1e-9)
})
test_that("lapmod handles single row/column", {
# Single row
cost1 <- matrix(c(3, 1, 4), nrow = 1)
result1 <- assignment(cost1, method = "lapmod")
expect_equal(result1$match[1], 2) # Column with minimum cost
expect_equal(result1$total_cost, 1)
# Single column (will be transposed)
# 3x1 matrix: rows compete for 1 column
# Row 2 (cost 1) wins
cost2 <- matrix(c(3, 1, 4), ncol = 1)
result2 <- assignment(cost2, method = "lapmod")
expect_equal(result2$match[2], 1) # Row 2 gets column 1
expect_equal(result2$total_cost, 1)
})
test_that("lapmod errors on infeasible problem", {
# Row with all NA
cost <- matrix(c(NA, NA, NA,
1, 2, 3,
4, 5, 6), nrow = 3, byrow = TRUE)
expect_error(assignment(cost, method = "lapmod"), "Infeasible")
})
test_that("lapmod handles negative costs", {
cost <- matrix(c(-4, -2, -5,
-3, -3, -6,
-7, -5, -4), nrow = 3, byrow = TRUE)
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
# Minimum with negatives: most negative wins
# row3->col1 (-7) + row2->col3 (-6) + row1->col2 (-2) = -15? Let's check
# Or: row3->col1 (-7) + row2->col3 (-6) + row1->col3 can't
# Valid: row1->col3 (-5) + row2->col3 can't...
# row1->col1 (-4) + row2->col2 (-3) + row3->col3 (-4) = -11
# row1->col2 (-2) + row2->col1 (-3) + row3->col3 (-4) = -9
# row1->col2 (-2) + row2->col3 (-6) + row3->col1 (-7) = -15
expect_equal(result$total_cost, -15)
})
test_that("lapmod handles mixed positive/negative costs", {
cost <- matrix(c(1, -2, 3,
-1, 2, -3,
2, -1, 1), nrow = 3, byrow = TRUE)
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
# Verify against JV
jv_result <- assignment(cost, method = "jv")
expect_equal(result$total_cost, jv_result$total_cost, tolerance = 1e-9)
})
test_that("lapmod is selected by auto for large sparse problems", {
set.seed(789)
n <- 150
cost <- matrix(NA_real_, nrow = n, ncol = n)
# Fill ~30% of entries
for (i in 1:n) {
cols <- sample(1:n, ceiling(n * 0.3))
for (j in cols) {
cost[i, j] <- runif(1, 1, 10)
}
}
result <- assignment(cost, method = "auto")
expect_equal(result$method_used, "lapmod")
})
test_that("lapmod handles 2x2 correctly", {
cost <- matrix(c(1, 2,
3, 4), nrow = 2, byrow = TRUE)
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
# Optimal: row1->col1 (1) + row2->col2 (4) = 5
# Or: row1->col2 (2) + row2->col1 (3) = 5
expect_equal(result$total_cost, 5)
})
test_that("lapmod handles ties correctly", {
cost <- matrix(c(1, 1, 1,
1, 1, 1,
1, 1, 1), nrow = 3, byrow = TRUE)
result <- assignment(cost, method = "lapmod")
expect_equal(result$status, "optimal")
expect_equal(result$total_cost, 3)
expect_equal(length(unique(result$match)), 3) # All different columns
})
test_that("lapmod benchmark: faster than JV on sparse problems", {
skip_if_not_installed("bench")
set.seed(999)
n <- 500
cost <- matrix(NA_real_, nrow = n, ncol = n)
# Fill ~20% of entries (very sparse)
for (i in 1:n) {
cols <- sample(1:n, ceiling(n * 0.2))
for (j in cols) {
cost[i, j] <- runif(1, 1, 100)
}
}
# Just verify it runs - actual benchmarking is optional
lapmod_result <- assignment(cost, method = "lapmod")
expect_equal(lapmod_result$status, "optimal")
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.