The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
Did the dependence structure change between two periods? The likelihood-ratio statistic is Box’s M, and its null distribution has traditionally been handled by asymptotic approximations that are poor exactly where the question is interesting: small samples and moderate dimension.
The statistic vanishes when nothing differs, and it is invariant to a common change of basis:
cov_M(XA, XA)
#> [1] 0
A <- matrix(c(2, 0.3, -1, 0.1, 1.4, 0.2, 0, 0.5, 1), 3, 3)
c(original = cov_M(XA, XB), transformed = cov_M(XA %*% A, XB %*% A))
#> original transformed
#> 35.19953 35.19953That invariance is the point. Because the null law does not depend on the unknown common covariance, it can be calibrated once at the identity and used at every covariance, with no nuisance parameter to estimate.
cov_pexact evaluates the null tail by inverting the
exact characteristic function, so the test is exact rather than
approximate. It agrees with simulation from the covariance-free null,
which is an independent route:
set.seed(3)
null <- cov_null(p = 3, nA = 40, nB = 40, B = 20000, seed = 5L)
q <- unname(quantile(null, c(0.5, 0.9)))
rbind(simulated_tail = c(0.5, 0.1),
exact_tail = vapply(q, function(m) cov_pexact(m, 39, 39, 3), 0))
#> [,1] [,2]
#> simulated_tail 0.5000000 0.10000000
#> exact_tail 0.5013875 0.09727948Applied to the data above, the scale change in one coordinate is detected:
and two samples from the same law are not:
The same machinery gives a log-domain differential network, \(D = \log \mathrm{cov}(X_B) - \log \mathrm{cov}(X_A)\). It is symmetric, antisymmetric under swapping the samples, and inversion-invariant, so it says the same thing whether you think in covariances or precisions:
D <- cov_logdiff(XA, XB)
round(D, 4)
#> [,1] [,2] [,3]
#> [1,] 0.3851 0.0774 -0.0867
#> [2,] 0.0774 1.2499 0.1094
#> [3,] -0.0867 0.1094 -0.9849
c(antisymmetry = max(abs(D + cov_logdiff(XB, XA))), symmetry = max(abs(D - t(D))))
#> antisymmetry symmetry
#> 0.000000e+00 1.387779e-17A max-type statistic in the style of Cai, Liu and Xia is also provided for the sparse alternative:
Everything above runs in a shared C back-end with its own random number generator, so results do not depend on R’s RNG state, and the same sources are bound from Python.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.