Skip to content

Relax numerical precision for covariance matrix symmetry check#74

Merged
gbradburd merged 2 commits intogbradburd:masterfrom
chriscrsmith:precision
May 2, 2026
Merged

Relax numerical precision for covariance matrix symmetry check#74
gbradburd merged 2 commits intogbradburd:masterfrom
chriscrsmith:precision

Conversation

@chriscrsmith
Copy link
Copy Markdown
Contributor

Behavior:
The cross validation function sometimes gives an error (below) when checking for symmetry of the covariance matrices from each CV fold. The error seems more common for large genotype inputs (and for randomly generated allele frequencies).

Error message:

Error in check.data.partitions.covmats(args) : 
you must specify symmetric matrices for the "data" elements of the data partitions list

Example:

set.seed(123)
m=1000
n=10
locs = matrix(runif(2*n), nrow=n)
dists = distm(locs, fun = distHaversine)
freqs = matrix(runif(m*n), nrow=n)
x.validation(train.prop = 0.9,
                     n.reps = 8,
                     K = 1:6,
                     freqs = freqs,
                     data.partitions = NULL,
                     geoDist = dists,
                     coords = locs,
                     prefix = "temp",
                     n.iter = 1e3,
                     make.figs = TRUE,
                     save.files = FALSE,
                     parallel = FALSE,
                     n.nodes = NULL)

The offending values can be as close as:
-0.0039732048102367745
-0.0039732048102368300

Fix:
isSymmetric() takes a tolerance argument with default 100 * .Machine$double.eps (= 2.220446e-16). I replaced this with 1e-10 which seems plenty precise and works for several iterations of the above example.

Don't know if it would also be good to copy the upper triangle onto the lower triangle of each covariance matrix?

@petrelharp
Copy link
Copy Markdown
Collaborator

Hi, Chris! Let's see; these covariance matrices are getting produced in calc.covariance, I think. And that is a function that certainly should produce a symmetric matrix, except for floating-point error. So I think changing that function to do

	return((allelic.covariance + t(allelic.covariance))/2)

would fix this up? Then, I think we'll only get non-symmetric matrices if the user passes them in, in which case maybe the tolerance doesn't need to be updated, actually. What do you think?

@chriscrsmith
Copy link
Copy Markdown
Contributor Author

Hey Peter!

Ah so the user can input a covariance matrix. I had wondered why the symmetry check was necessary.

I like your fix. included it in recent commit, deleted the tol=1e-10.

@gbradburd gbradburd merged commit 9dde30b into gbradburd:master May 2, 2026
5 checks passed
@gbradburd
Copy link
Copy Markdown
Owner

thanks Chris for the question and Peter for the elegant solution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants