Nothing
# Test file for Gauss-Seidel Auction Algorithm
# Save as: tests/testthat/test-assignment-auction-gs.R
test_that("auction_gs works on small square matrix", {
set.seed(42)
n <- 5
M <- matrix(runif(n*n), n, n)
# Compare with other methods
a_gs <- assignment(M, method = "auction_gs")
a_jv <- assignment(M, method = "jv")
expect_true(is.list(a_gs))
expect_true("match" %in% names(a_gs))
expect_true("total_cost" %in% names(a_gs))
expect_equal(length(a_gs$match), n)
# Should get same (or very close) cost as JV
expect_equal(a_gs$total_cost, a_jv$total_cost, tolerance = 1e-6)
})
test_that("auction_gs handles rectangular n < m", {
set.seed(43)
n <- 4; m <- 7
M <- matrix(runif(n*m), n, m)
a_gs <- assignment(M, method = "auction_gs")
a_ssp <- assignment(M, method = "ssp")
expect_equal(length(a_gs$match), n)
expect_true(all(a_gs$match >= 1 & a_gs$match <= m))
expect_equal(a_gs$total_cost, a_ssp$total_cost, tolerance = 1e-6)
})
test_that("auction_gs handles rectangular n > m (auto-transpose)", {
set.seed(44)
n <- 8; m <- 4
M <- matrix(runif(n*m), n, m)
# This should work with auto-transpose
a_gs <- assignment(M, method = "auction_gs")
a_ssp <- assignment(M, method = "ssp")
expect_equal(length(a_gs$match), n)
# When n > m, only m rows can be matched, rest will be 0 (unmatched)
matched <- a_gs$match[a_gs$match > 0]
expect_true(all(matched >= 1 & matched <= m))
expect_equal(sum(a_gs$match > 0), m) # Exactly m assignments
expect_equal(a_gs$total_cost, a_ssp$total_cost, tolerance = 1e-6)
})
test_that("auction_gs handles NA values", {
set.seed(45)
n <- 5; m <- 7
M <- matrix(runif(n*m), n, m)
# Set some entries to NA (forbidden)
M[1, 1:3] <- NA
M[2, c(2,4,6)] <- NA
M[5, 1] <- NA
a_gs <- assignment(M, method = "auction_gs")
a_ssp <- assignment(M, method = "ssp")
# Check that no NA cells were chosen
for (i in 1:n) {
j <- a_gs$match[i]
expect_false(is.na(M[i, j]))
}
expect_equal(a_gs$total_cost, a_ssp$total_cost, tolerance = 1e-6)
})
test_that("auction_gs handles Inf values", {
set.seed(46)
n <- 4; m <- 6
M <- matrix(runif(n*m), n, m)
# Set some entries to Inf (forbidden)
M[1, c(1,3,5)] <- Inf
M[3, 2:4] <- Inf
a_gs <- assignment(M, method = "auction_gs")
# Check that no Inf cells were chosen
for (i in 1:n) {
j <- a_gs$match[i]
expect_true(is.finite(M[i, j]))
}
})
test_that("auction_gs errors when row has no valid assignments", {
M <- matrix(c(
1, 2, 3,
4, 5, 6,
NA, NA, NA
), nrow = 3, byrow = TRUE)
expect_error(assignment(M, method = "auction_gs"), "Infeasible")
})
test_that("auction_gs maximization works", {
set.seed(47)
n <- 5
M <- matrix(runif(n*n), n, n)
a_max <- assignment(M, maximize = TRUE, method = "auction_gs")
a_min <- assignment(-M, maximize = FALSE, method = "auction_gs")
expect_equal(a_max$total_cost, -a_min$total_cost, tolerance = 1e-6)
})
test_that("auction_gs with custom epsilon", {
set.seed(48)
n <- 4
M <- matrix(runif(n*n), n, n)
# Try different epsilon values
a1 <- assignment(M, method = "auction_gs", auction_eps = 1e-6)
a2 <- assignment(M, method = "auction_gs", auction_eps = 1e-9)
a3 <- assignment(M, method = "auction_gs", auction_eps = 1e-12)
# All should give valid assignments
expect_true(all(a1$match >= 1 & a1$match <= n))
expect_true(all(a2$match >= 1 & a2$match <= n))
expect_true(all(a3$match >= 1 & a3$match <= n))
# Smaller epsilon should give more accurate results
expect_lte(abs(a3$total_cost - a2$total_cost), abs(a2$total_cost - a1$total_cost))
})
test_that("auction_gs returns bid count diagnostic", {
set.seed(49)
n <- 6
M <- matrix(runif(n*n), n, n)
result <- lap_solve_auction_gs(M, maximize = FALSE, eps = 1e-6)
expect_true("bids" %in% names(result))
expect_true(is.numeric(result$bids))
expect_true(result$bids > 0)
expect_true(result$bids <= 200000000) # Should be well below iteration guard
})
test_that("auction_gs compares favorably with standard auction", {
set.seed(50)
n <- 10
M <- matrix(runif(n*n), n, n)
result_gs <- lap_solve_auction_gs(M, maximize = FALSE, eps = 1e-8)
result_std <- lap_solve_auction(M, maximize = FALSE, eps = 1e-8)
# Should get same cost (within tolerance)
expect_equal(result_gs$total_cost, result_std$total_cost, tolerance = 1e-6)
# GS often makes fewer bids (though not guaranteed)
# Just check that both terminated successfully
expect_true("bids" %in% names(result_gs))
})
test_that("auction_gs works on larger problems", {
testthat::skip_on_cran()
set.seed(51)
n <- 100; m <- 150
M <- matrix(runif(n*m), n, m)
# Add some NA entries
na_idx <- sample.int(length(M), size = as.integer(0.1 * length(M)))
M[na_idx] <- NA
# Ensure each row has at least one valid entry
for (i in 1:n) {
if (all(is.na(M[i,]))) {
j <- sample.int(m, 1)
M[i, j] <- runif(1)
}
}
a_gs <- assignment(M, method = "auction_gs")
expect_equal(length(a_gs$match), n)
expect_true(all(a_gs$match >= 1 & a_gs$match <= m))
expect_true(all(!is.na(M[cbind(1:n, a_gs$match)])))
})
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.