Nothing
# Test suite for the GFT package.
#
# The golden values were generated from the independently verified Python
# implementation (NumPy/SciPy, double precision) and are shared with the
# Julia test suite, so a passing run constitutes a cross-language
# verification of the solver.
test_that("golden values from Python implementation", {
# Case 1: Toeplitz rho = 0.9, n = 5
z1 <- c(1.153290016506162, 0.5558856623939625, 0.35800387580539283,
0.27329448930908706, 1.0109967961569906, 0.5069766634781976,
0.358003875805393, 1.0109967961569903, 0.5558856623939642,
1.1532900165061641)
x1 <- c(-1.0295579541972146, -1.511633306658801, -1.5605423055745682,
-1.5116333066588024, -1.0295579541972182)
r <- inv_gft(z1, tol = 1e-15)
expect_true(r$converged)
expect_lt(max(abs(r$x - x1)), 1e-11)
# forward map round-trip
C <- 0.9^abs(outer(1:5, 1:5, "-"))
expect_lt(max(abs(gft(C) - z1)), 1e-12)
expect_lt(max(abs(r$C - C)), 1e-11)
# Case 2: equicorrelation rho = 0.99, n = 4 (repeated eigenvalues)
z2 <- c(1.4959840701717646, 1.4959840701718055, 1.4959840701718055,
1.4959840701717937, 1.4959840701717941, 1.495984070171792)
x2 <- c(-3.1091861158162764, -3.1091861158162533, -3.10918611581629,
-3.109186115816293)
r <- inv_gft(z2, tol = 1e-15)
expect_true(r$converged)
expect_lt(max(abs(r$x - x2)), 1e-10)
# Case 3: fixed z, n = 3, with the reconstructed C
z3 <- c(0.5, -1.25, 2.0)
x3 <- c(-0.4468779844556956, -1.1593398688810534, -1.7913253190785425)
C3 <- matrix(c(1.0, -0.19502680396870392, -0.6143366326910233,
-0.19502680396870378, 1.000000000000004,
0.8717792808904407,
-0.6143366326910232, 0.871779280890441,
1.0000000000000056), 3, 3)
r <- inv_gft(z3, tol = 1e-15)
expect_lt(max(abs(r$x - x3)), 1e-11)
expect_lt(max(abs(r$C - C3)), 1e-11)
})
test_that("round trips, all solvers", {
set.seed(1)
for (n in c(10, 50)) {
X <- matrix(rnorm(n * 2 * n), n, 2 * n)
S <- X %*% t(X)
Dh <- 1 / sqrt(diag(S))
C <- S * outer(Dh, Dh)
C <- (C + t(C)) / 2
z <- gft(C)
for (solver in list(inv_gft, inv_gft_fp, inv_gft_broyden,
inv_gft_newton)) {
r <- solver(z)
expect_true(r$converged)
expect_lt(max(abs(diag(r$C) - 1)), 1e-12)
expect_lt(max(abs(r$C - C)), 1e-10)
}
}
})
test_that("extreme z (log-domain robustness)", {
set.seed(2)
z <- 8 * rnorm(40 * 39 / 2) # spectra spanning ~200 log-units
r <- inv_gft(z)
expect_true(r$converged)
expect_lt(max(abs(diag(r$C) - 1)), 1e-12)
rfp <- inv_gft_fp(z, maxit = 20000)
expect_true(rfp$converged)
expect_lt(max(abs(r$x - rfp$x)), 1e-8)
})
test_that("near-singular one-factor", {
set.seed(3)
n <- 100
b <- 0.995 + 0.0049 * runif(n)
C <- outer(b, b)
diag(C) <- 1
z <- gft(C)
r <- inv_gft(z)
expect_true(r$converged)
expect_lt(r$eighs, 30)
expect_lt(max(abs(r$C - C)), 1e-9)
})
test_that("gradient, Hessian-vector products, exact Hessian", {
set.seed(4)
n <- 12
A0 <- matrix(rnorm(n * n), n, n)
A0 <- (A0 + t(A0)) / 2
diag(A0) <- 0
x <- rnorm(n)
A <- A0
diag(A) <- x
F <- eigen(A, symmetric = TRUE)
lam <- F$values
Q <- F$vectors
f <- function(x) {
A <- A0
diag(A) <- x
sum(exp(eigen(A, symmetric = TRUE, only.values = TRUE)$values)) -
sum(x)
}
g <- exp(GFT:::.logdiagexp(lam, Q)) - 1
eps <- 1e-6
for (i in seq_len(n)) {
e <- numeric(n)
e[i] <- eps
expect_lt(abs((f(x + e) - f(x - e)) / (2 * eps) - g[i]), 1e-6)
}
L <- GFT:::.loewner_exp(lam)
H <- GFT:::.hessian(lam, Q, L)
v <- rnorm(n)
expect_lt(max(abs(GFT:::.hess_vec(lam, Q, L, v) - H %*% v)), 1e-10)
# Proposition 1: H*1 = d, lmin(E) I <= H <= D
E <- GFT:::.expA(lam, Q)
d <- diag(E)
expect_lt(max(abs(H %*% rep(1, n) - d)), 1e-8 * max(d))
eigmin <- function(M)
min(eigen((M + t(M)) / 2, symmetric = TRUE,
only.values = TRUE)$values)
expect_gt(eigmin(diag(d) - H), -1e-8 * max(d))
expect_gt(eigmin(H - exp(min(lam)) * diag(n)), -1e-10)
})
test_that("repeated eigenvalues in divided differences", {
lam <- c(1.0, 1.0, 2.0, 2.0 + 1e-15)
L <- GFT:::.loewner_exp(lam)
expect_equal(L[1, 2], exp(1))
expect_equal(L[3, 4], exp(2), tolerance = 1e-12)
expect_true(isSymmetric(round(L, 10)))
})
test_that("vecl and unvecl", {
M <- matrix(1:16, 4, 4)
z <- vecl(M)
expect_equal(z, c(2, 3, 4, 7, 8, 12)) # column-major below-diagonal
A <- unvecl(z)
expect_equal(vecl(A), z)
expect_equal(A, t(A))
expect_equal(diag(A), numeric(4))
expect_error(unvecl(1:2), "n\\(n-1\\)/2")
})
test_that("input validation", {
expect_error(gft(matrix(1, 2, 3)), "square")
expect_error(gft(diag(c(1, -1))), "positive definite")
expect_error(inv_gft(c(0.1, 0.2), x0 = 1), "n\\(n-1\\)/2")
expect_error(inv_gft(c(0.1, 0.2, 0.3), x0 = 1), "x0")
})
test_that("warm start and print method", {
C <- 0.5^abs(outer(1:6, 1:6, "-"))
z <- gft(C)
r0 <- inv_gft(z)
r1 <- inv_gft(z, x0 = r0$x)
expect_true(r1$converged)
expect_lte(r1$eighs, r0$eighs)
expect_output(print(r0), "Inverse GFT result")
expect_output(print(r0), "converged")
})
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.