# tests/testthat/test-assignment-orlin.R # Tests for Orlin-Ahuja algorithm via assignment() interface test_that("orlin method works via assignment()", { cost <- matrix(c(4, 2, 5, 3, 3, 6, 7, 5, 4), nrow = 3, byrow = TRUE) result <- assignment(cost, method = "orlin") expect_equal(result$status, "optimal") expect_equal(result$method_used, "orlin") expect_equal(length(result$match), 3) expect_true(all(result$match > 0)) # All assigned expect_equal(length(unique(result$match)), 3) # All different }) test_that("orlin matches JV on small problems", { set.seed(123) for (n in c(3, 5, 8)) { cost <- matrix(runif(n * n, 1, 100), nrow = n) orlin_result <- assignment(cost, method = "orlin") jv_result <- assignment(cost, method = "jv") expect_equal(orlin_result$total_cost, jv_result$total_cost, tolerance = 1e-6, label = paste("n =", n)) } }) test_that("orlin handles rectangular matrices", { # 3x5 matrix (more columns than rows) cost <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), nrow = 3, byrow = TRUE) result <- assignment(cost, method = "orlin") expect_equal(length(result$match), 3) expect_true(all(result$match > 0)) expect_equal(length(unique(result$match)), 3) }) test_that("orlin handles transposed matrices (rows > cols)", { # 5x3 matrix (auto-transposed internally) cost <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), nrow = 5, byrow = TRUE) result <- assignment(cost, method = "orlin") # Result should have 5 entries (one per row), but only 3 can be matched expect_equal(length(result$match), 5) matched <- sum(result$match > 0) expect_equal(matched, 3) # Can only match 3 }) test_that("orlin handles maximize = TRUE", { cost <- matrix(c(10, 5, 8, 20, 3, 15, 7, 12, 6), nrow = 3, byrow = TRUE) min_result <- assignment(cost, method = "orlin", maximize = FALSE) max_result <- assignment(cost, method = "orlin", maximize = TRUE) expect_gt(max_result$total_cost, min_result$total_cost) }) test_that("orlin handles forbidden edges (Inf)", { cost <- matrix(c(1, Inf, 3, 4, 5, Inf, Inf, 8, 9), nrow = 3, byrow = TRUE) result <- assignment(cost, method = "orlin") expect_equal(result$status, "optimal") # Check no forbidden edges were assigned for (i in 1:3) { j <- result$match[i] if (j > 0) { expect_true(is.finite(cost[i, j])) } } }) test_that("orlin handles NA as forbidden", { cost <- matrix(c(1, NA, 3, 4, 5, NA, NA, 8, 9), nrow = 3, byrow = TRUE) result <- assignment(cost, method = "orlin") expect_equal(result$status, "optimal") }) test_that("orlin scales to medium problems", { skip_on_cran() set.seed(42) n <- 50 cost <- matrix(runif(n * n, 1, 100), nrow = n) result <- assignment(cost, method = "orlin") jv_result <- assignment(cost, method = "jv") expect_equal(result$total_cost, jv_result$total_cost, tolerance = 1e-4) })