Skip to content

Commit

Permalink
Don't miss smallest eigenvalue
Browse files Browse the repository at this point in the history
  • Loading branch information
ms609 committed Aug 14, 2024
1 parent b5536df commit e584265
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 4 deletions.
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# TreeDist 2.8.0.9000 (development)

- `SpectralEigens()` survives values of nEig larger than the input
- `SpectralEigens()` returns correct eigenvalues (smallest was overlooked)
- `SpectralEigens()` handles values of nEig larger than the input

# TreeDist 2.8.0 (2024-07-25)

Expand Down
9 changes: 6 additions & 3 deletions R/spectral_clustering.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#' @family tree space functions
#' @export
SpectralEigens <- function(D, nn = 10L, nEig = 2L) {
if (nEig < 1) {
stop("nEig must be positive")
}

MutualKnnGraph <- function(D, nn) {
D <- as.matrix(D)
Expand All @@ -32,13 +35,13 @@ SpectralEigens <- function(D, nn = 10L, nEig = 2L) {
# intialize the knn matrix
knn_mat <- matrix(FALSE, nrow = dims[[1]], ncol = dims[[2]])

# find the 10 nearest neighbors for each point
# find the 10 nearest neighbours for each point
for (i in seq_len(nrow(D))) {
neighbor_index <- order(D[i, ])[2:(nn + 1)]
knn_mat[i, ][neighbor_index] <- TRUE
}

# Now we note that i,j are neighbors iff K[i,j] = 1 or K[j,i] = 1
# Now we note that i,j are neighbours iff K[i,j] = 1 or K[j, i] = 1
knn_mat <- knn_mat | t(knn_mat) # find mutual knn

# Return:
Expand All @@ -64,7 +67,7 @@ SpectralEigens <- function(D, nn = 10L, nEig = 2L) {

if (nL > nEig) {
# Return the eigenvectors of the n_eig smallest eigenvalues:
ei[["vectors"]][, nL - rev(seq_len(nEig))]
ei[["vectors"]][, nL - (0:(nEig - 1))]
} else {
ei[["vectors"]]
}
Expand Down
11 changes: 11 additions & 0 deletions tests/testthat/test-spectral_clustering.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
d <- dist(c(1:20, 60:41))

test_that("Spectral clustering fails gracefully", {
expect_error(SpectralEigens(d, nEig = 0), "nEig must be.*positive")
})

test_that("Spectral clustering works", {
allEig <- SpectralEigens(d, nEig = Inf)
expect_equal(dim(allEig), c(40, 40))
expect_equal(SpectralEigens(d, nEig = 2), allEig[, 40:39])
})

0 comments on commit e584265

Please sign in to comment.