tests/testthat/test-arguments.R

## Argument handling and optimizer plumbing that used to fail silently.

test_that("AdMit warns about unknown control components", {
  expect_warning(
    AdMit(KERNEL = GelmanMeng, mu0 = c(0.0, 0.1),
          control = list(Ns = 5e3, Np = 5e2, Hmax = 2, Hmaxx = 99)),
    "unknown names in 'control': Hmaxx")
})

test_that("AdMit does not warn about valid control components", {
  expect_no_warning(
    AdMit(KERNEL = GelmanMeng, mu0 = c(0.0, 0.1),
          control = list(Ns = 5e3, Np = 5e2, Hmax = 2, CVtol = 0.2, df = 5)))
})

test_that("AdMitIS warns about arguments used by neither KERNEL nor G", {
  set.seed(501)
  fit <- AdMit(KERNEL = GelmanMeng, mu0 = c(0.0, 0.1),
               control = list(Ns = 5e3, Np = 5e2, Hmax = 2))

  expect_warning(AdMitIS(N = 1e3, KERNEL = GelmanMeng, mit = fit$mit, notanarg = 1),
                 "used by neither 'KERNEL' nor 'G'")
  ## arguments that do belong to KERNEL or to G must not warn
  expect_no_warning(AdMitIS(N = 1e3, KERNEL = GelmanMeng, mit = fit$mit, A = 2))
  expect_no_warning(AdMitIS(N = 1e3, KERNEL = GelmanMeng, mit = fit$mit,
                            G = function(theta, shift) theta - shift, shift = 1))
})

test_that("AdMitIS routes abbreviated argument names to the right function", {
  ## the dispatch used to select from '...' by the *matched formal* name, so an
  ## abbreviated name resolved to a name absent from the supplied arguments
  Scaled <- function(x, scaling = 1, log = TRUE) {
    if (is.vector(x)) x <- matrix(x, nrow = 1)
    r <- -0.5 * scaling * (x[,1]^2 + x[,2]^2)
    if (!log) r <- exp(r)
    as.vector(r)
  }
  set.seed(502)
  fit <- AdMit(KERNEL = Scaled, mu0 = c(0.1, 0.1), scaling = 4,
               control = list(Ns = 5e3, Np = 5e2, Hmax = 2))

  set.seed(503)
  full <- AdMitIS(N = 5e3, KERNEL = Scaled, mit = fit$mit, scaling = 4)
  set.seed(503)
  abbr <- AdMitIS(N = 5e3, KERNEL = Scaled, mit = fit$mit, scal = 4)
  expect_equal(abbr$ghat, full$ghat)

  ## same for an abbreviated formal of G
  G.shift <- function(theta, shiftvalue) theta - shiftvalue
  set.seed(504)
  a <- AdMitIS(N = 5e3, KERNEL = Scaled, mit = fit$mit, scaling = 4,
               G = G.shift, shiftvalue = 1)
  set.seed(504)
  b <- AdMitIS(N = 5e3, KERNEL = Scaled, mit = fit$mit, scaling = 4,
               G = G.shift, shift = 1)
  expect_equal(a$ghat, b$ghat)
})

test_that("the gradient belongs to the point it is asked about", {
  ## The gradient handed to the optimizer used to be whatever the last
  ## *objective* evaluation left behind, so asking for g(B) right after f(A)
  ## returned the gradient at A. That is silent and only bites when the
  ## optimizer breaks the f-then-g-at-the-same-point pattern, so it has to be
  ## tested on the evaluator itself rather than through the optimizer.
  set.seed(505)
  Np <- 40L; H <- 3L
  lnK <- matrix(rnorm(Np * H), Np, H)
  lnD <- matrix(rnorm(Np * H * H, -1, 0.5), Np, H * H)

  lnfgrad <- get("fn.lnfgrad", envir = asNamespace("AdMit"))
  lambdaA <- c(0.7, -0.4)
  lambdaB <- c(-0.2, 1.1)

  ## reference: an evaluator that has only ever seen lambdaB
  ref <- lnfgrad(lnK, lnD)
  ref$f(lambdaB)
  gB <- ref$g(lambdaB)

  ## the same gradient, requested straight after an objective call elsewhere
  obj <- lnfgrad(lnK, lnD)
  obj$f(lambdaA)
  expect_equal(obj$g(lambdaB), gB)

  ## and with no objective call at all beforehand
  expect_equal(lnfgrad(lnK, lnD)$g(lambdaB), gB)

  ## the gradient is the actual derivative of the objective at that point
  num <- vapply(seq_along(lambdaB), function(j) {
    h <- 1e-6
    lp <- lm <- lambdaB
    lp[j] <- lambdaB[j] + h
    lm[j] <- lambdaB[j] - h
    (ref$f(lp) - ref$f(lm)) / (2 * h)
  }, numeric(1))
  expect_equal(gB, num, tolerance = 1e-6)
})

test_that("fn.optp returns a valid probability vector and is deterministic", {
  set.seed(506)
  Np <- 40L; H <- 3L
  lnK <- matrix(rnorm(Np * H), Np, H)
  lnD <- matrix(rnorm(Np * H * H, -1, 0.5), Np, H * H)
  ctl <- list(trace = 0, iter.max = 5e2, rel.tol = 1e-8, weightNC = 0.1)

  optp <- get("fn.optp", envir = asNamespace("AdMit"))
  out <- optp(c(0.5, 0.5), lnK, lnD, ctl)

  expect_length(out$p, H)
  expect_equal(sum(out$p), 1)
  expect_true(all(out$p > 0))
  expect_equal(optp(c(0.5, 0.5), lnK, lnD, ctl)$p, out$p)
})

test_that("fn.wIS centres every candidate on the highest-weight draw", {
  set.seed(507)
  theta <- matrix(rnorm(200), 100, 2)
  w <- runif(100)
  wIS <- get("fn.wIS", envir = asNamespace("AdMit"))
  out <- wIS(theta, w, list(percent = c(.05, .15, .3), scale = c(1, .25, 4)))

  expect_equal(out$mu, theta[which.max(w), ], ignore_attr = TRUE)
  expect_identical(dim(out$Sigma), c(9L, 4L)) ## 3 percentages x 3 scalings
  ## the scalings are applied to a common scale matrix, in order
  expect_equal(out$Sigma[2, ], 0.25 * out$Sigma[1, ])
  expect_equal(out$Sigma[3, ], 4 * out$Sigma[1, ])
})

Try the AdMit package in your browser

Any scripts or data that you put into this service are public.

AdMit documentation built on Aug. 21, 2026, 5:14 p.m.