forked from aidenlab/EigenVector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbestEigen3.R
71 lines (63 loc) · 1.4 KB
/
bestEigen3.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
require(Matrix)
bestEigen <- function(x=x,a1=NULL,a2=NULL,tol=1.0e-6,maxiter=100) {
# set.seed(12345)
n <- nrow(x)
s1 <- colSums(x)/n
s2 <- colSums(x^2)/n
z <- s2-s1*s1
#
bad <- which(z==0)
good <- setdiff(1:n,bad)
x <- x[-bad,-bad]
for (i in 1:3) junk <- gc()
k <- nrow(x)
s1 <- colSums(x)/k
s2 <- colSums(x^2)/k
sd <- sqrt(s2-s1*s1)
x <- x %*% Diagonal(x=1/sd)
C <- s1/sd
if (is.null(a1)) a1 <- rnorm(nrow(x))
if (is.null(a2)) a2 <- rnorm(nrow(x))
xx <- t(x)
for (i in 1:3) junk <- gc()
niter <- 0
while (niter < maxiter) {
for (i in 1:10) {
a1 <- x %*% a1 - sum(C*a1)
a1 <- xx %*% a1 - sum(a1)*C
a1 <- a1/sqrt(sum(a1*a1))
}
ev1 <- a1
a1 <- x %*% a1 - sum(C*a1)
a1 <- xx %*% a1 - sum(a1)*C
lam1 <- sqrt(sum(a1*a1))
er1 <- sqrt(sum((a1 - lam1*ev1)^2))
a1 <- a1/sqrt(sum(a1*a1))
a2 <- a2 - a1*sum(a2*a1)
for (i in 1:10) {
a2 <- x %*% a2 - sum(C*a2)
a2 <- xx %*% a2 - sum(a2)*C
a2 <- a2 - a1*sum(a2*a1)
a2 <- a2/sqrt(sum(a2*a2))
}
ev2 <- a2
a2 <- x %*% a2 - sum(C*a2)
a2 <- xx %*% a2 - sum(a2)*C
lam2 <- sqrt(sum(a2*a2))
a2 <- a2/sqrt(sum(a2*a2))
if (lam1 < lam2) {
temp <- a1
a1 <- a2
a2 <- temp
temp <- lam1
lam1 <- lam2
lam2 <- temp
for (junk in 1:3) gc()
}
niter <- niter + 10
if (er1/(lam1-lam2) < tol) break
}
v <- rep(NA,n)
v[good] <- ev1
return(list(v=v,lam1=lam1,er=er1,lam2=lam2,niter=niter,a1=a1,a2=a2))
}