Nothing
# Tests to push coverage above 90%
# Targets: network_simplex, cycle_cancel, gabow_tarjan edge cases
# ---------- network_simplex coverage ----------
test_that("network_simplex handles various matrix sizes", {
skip_on_cran()
# Square matrices of different sizes
for (n in c(2, 3, 5, 7)) {
set.seed(n * 42)
cost <- matrix(sample(1:100, n * n, replace = TRUE), n, n)
result <- assignment(cost, method = "network_simplex")
expect_equal(length(result$match), n)
expect_true(all(result$match >= 1 & result$match <= n))
expect_true(result$total_cost > 0)
}
})
test_that("network_simplex handles rectangular matrices (more cols)", {
skip_on_cran()
# More columns than rows (valid case)
cost <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3)
result <- assignment(cost, method = "network_simplex")
expect_equal(length(result$match), 2)
expect_true(all(result$match >= 1 & result$match <= 3))
})
test_that("network_simplex handles more rows than cols", {
skip_on_cran()
# More rows than columns - infeasible case
cost <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3, ncol = 2)
# Should either handle gracefully or error
result <- tryCatch(
assignment(cost, method = "network_simplex"),
error = function(e) list(error = TRUE, msg = e$message)
)
# Either returns infeasible or handles via transposition
expect_true(!is.null(result))
})
test_that("network_simplex handles uniform costs", {
skip_on_cran()
cost <- matrix(5, nrow = 4, ncol = 4)
result <- assignment(cost, method = "network_simplex")
expect_equal(length(result$match), 4)
expect_equal(result$total_cost, 20) # 4 * 5
})
test_that("network_simplex handles zero diagonal", {
skip_on_cran()
cost <- matrix(10, nrow = 3, ncol = 3)
diag(cost) <- 0
result <- assignment(cost, method = "network_simplex")
expect_equal(result$total_cost, 0) # Should use diagonal
})
# ---------- cycle_cancel coverage ----------
test_that("cycle_cancel handles various sizes", {
skip_on_cran()
for (n in c(2, 3, 4, 5, 6)) {
set.seed(n * 100)
cost <- matrix(runif(n * n, 1, 100), n, n)
result <- assignment(cost, method = "cycle_cancel")
expect_equal(length(result$match), n)
expect_true(result$total_cost > 0)
}
})
test_that("cycle_cancel handles rectangular (more cols)", {
skip_on_cran()
cost <- matrix(c(1, 5, 3, 2, 4, 6), nrow = 2, ncol = 3)
result <- assignment(cost, method = "cycle_cancel")
expect_equal(length(result$match), 2)
expect_true(all(result$match >= 1 & result$match <= 3))
})
test_that("cycle_cancel handles rectangular (more rows)", {
skip_on_cran()
# This triggers the transpose path
cost <- matrix(c(1, 5, 3, 2, 4, 6), nrow = 3, ncol = 2)
result <- assignment(cost, method = "cycle_cancel")
# After transpose, we get n=2 assignments
expect_equal(length(result$match), 3)
})
test_that("cycle_cancel handles maximize", {
skip_on_cran()
cost <- matrix(c(1, 10, 8, 2), nrow = 2, ncol = 2)
result <- assignment(cost, method = "cycle_cancel", maximize = TRUE)
expect_true(result$total_cost >= 10) # Should get high cost
})
test_that("cycle_cancel handles sparse costs with Inf", {
skip_on_cran()
cost <- matrix(c(1, Inf, Inf, 2, 3, Inf, Inf, 4, 5), nrow = 3, ncol = 3)
result <- tryCatch(
assignment(cost, method = "cycle_cancel"),
error = function(e) list(error = TRUE)
)
expect_true(!is.null(result))
})
# ---------- gabow_tarjan edge cases ----------
test_that("gabow_tarjan handles various sizes", {
skip_on_cran()
for (n in c(2, 3, 4, 5, 6, 8)) {
set.seed(n * 77)
cost <- matrix(sample(1:50, n * n, replace = TRUE), n, n)
result <- assignment(cost, method = "gabow_tarjan")
expect_equal(length(result$match), n)
expect_true(all(sort(result$match) == 1:n))
}
})
test_that("gabow_tarjan handles negative costs", {
skip_on_cran()
cost <- matrix(c(-5, -1, -2, -10), nrow = 2, ncol = 2)
result <- assignment(cost, method = "gabow_tarjan")
expect_true(result$total_cost < 0)
})
test_that("gabow_tarjan handles uniform costs", {
skip_on_cran()
cost <- matrix(7, nrow = 3, ncol = 3)
result <- assignment(cost, method = "gabow_tarjan")
expect_equal(result$total_cost, 21) # 3 * 7
})
test_that("gabow_tarjan handles rectangular", {
skip_on_cran()
# More columns than rows
cost <- matrix(c(1, 5, 3, 2, 4, 6), nrow = 2, ncol = 3)
result <- assignment(cost, method = "gabow_tarjan")
expect_equal(length(result$match), 2)
})
test_that("gabow_tarjan with forbidden edges", {
skip_on_cran()
# Diagonal forbidden
cost <- matrix(c(Inf, 1, 2, 3, Inf, 4, 5, 6, Inf), nrow = 3, ncol = 3)
result <- assignment(cost, method = "gabow_tarjan")
# Should find assignment avoiding diagonal
expect_equal(length(result$match), 3)
for (i in 1:3) {
expect_false(result$match[i] == i) # Not on diagonal
}
})
# ---------- Additional solver coverage ----------
test_that("csflow handles various sizes", {
skip_on_cran()
for (n in c(2, 3, 4, 6)) {
set.seed(n * 55)
cost <- matrix(sample(1:100, n * n, replace = TRUE), n, n)
result <- assignment(cost, method = "csflow")
expect_equal(length(result$match), n)
}
})
test_that("ssp handles various sizes", {
skip_on_cran()
for (n in c(2, 3, 4, 5)) {
set.seed(n * 66)
cost <- matrix(sample(1:50, n * n, replace = TRUE), n, n)
result <- assignment(cost, method = "ssp")
expect_equal(length(result$match), n)
}
})
test_that("orlin handles various sizes", {
skip_on_cran()
for (n in c(3, 4, 5, 6)) {
set.seed(n * 88)
cost <- matrix(sample(1:80, n * n, replace = TRUE), n, n)
result <- assignment(cost, method = "orlin")
expect_equal(length(result$match), n)
}
})
test_that("push_relabel handles various sizes", {
skip_on_cran()
for (n in c(2, 3, 4, 5)) {
set.seed(n * 99)
cost <- matrix(sample(1:60, n * n, replace = TRUE), n, n)
result <- assignment(cost, method = "push_relabel")
expect_equal(length(result$match), n)
}
})
# ---------- lap_utils coverage ----------
test_that("lap_solve with all methods succeeds", {
skip_on_cran()
cost <- matrix(c(5, 2, 3, 7, 1, 8, 4, 6, 9), nrow = 3, ncol = 3)
methods <- c("hungarian", "jv", "auction", "ssp", "csflow",
"network_simplex", "cycle_cancel", "gabow_tarjan")
for (method in methods) {
result <- tryCatch(
lap_solve(cost, method = method),
error = function(e) NULL
)
if (!is.null(result)) {
expect_equal(nrow(result), 3)
}
}
})
# ---------- morph_pixel coverage ----------
test_that("pixel_morph with color_walk mode", {
skip_on_cran()
skip_if_not_installed("magick")
skip_if_not_installed("png")
imgA <- system.file("extdata/icons/circleA_40.png", package = "couplr")
imgB <- system.file("extdata/icons/circleB_40.png", package = "couplr")
skip_if(!nzchar(imgA), "Test images not found")
skip_if(!nzchar(imgB), "Test images not found")
# Test color_walk mode (for images larger than exact threshold)
result <- tryCatch(
pixel_morph_animate(imgA, imgB, mode = "color_walk",
n_frames = 3, show = FALSE, upscale = 1),
error = function(e) NULL
)
# Should produce frames
if (!is.null(result)) {
expect_true(inherits(result, "magick-image") || is.list(result))
}
})
# ---------- matching_core edge cases ----------
test_that("match_couples with blocking", {
skip_on_cran()
set.seed(42)
n <- 8
left <- data.frame(id = 1:n, x = rnorm(n), group = rep(c("A", "B"), each = n/2))
right <- data.frame(id = 1:n, x = rnorm(n), group = rep(c("A", "B"), each = n/2))
# Create block IDs for exact matching within groups
blocks <- matchmaker(left, right, block_type = "group", block_by = "group")
# Match within blocks
result <- match_couples(left, right, vars = "x",
block_id = blocks$block_id)
expect_true(nrow(result$pairs) > 0)
})
test_that("match_couples with max_distance constraint", {
skip_on_cran()
set.seed(42)
n <- 10
# Create overlapping distributions with some variation
left <- data.frame(id = 1:n, x = rnorm(n, 0, 1))
right <- data.frame(id = 1:n, x = rnorm(n, 0.5, 1))
# Moderate max_distance should work
result <- match_couples(left, right, vars = "x",
max_distance = 3, auto_scale = TRUE)
# Should match
expect_true(nrow(result$pairs) > 0)
})
test_that("greedy_couples with all strategies", {
skip_on_cran()
set.seed(42)
n <- 15
left <- data.frame(id = 1:n, x = rnorm(n), y = rnorm(n))
right <- data.frame(id = 1:n, x = rnorm(n), y = rnorm(n))
strategies <- c("sorted", "row_best", "pq")
for (strat in strategies) {
result <- greedy_couples(left, right, vars = c("x", "y"),
strategy = strat)
expect_equal(nrow(result$pairs), n)
}
})
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.