Skip to content

Commit 7c48711

Browse files
committed
Updates sampling to use SVD of bidiagonal matrix
1 parent 439d4b5 commit 7c48711

File tree

3 files changed

+90
-48
lines changed

3 files changed

+90
-48
lines changed

src/GaussianEnsembleDistributions.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function VandermondeDeterminant{Eigenvalue<:Number}(lambda::Vector{Eigenvalue},
2727
return Vandermonde
2828
end
2929

30+
3031
function HermiteJPDF{Eigenvalue<:Number}(lambda::Vector{Eigenvalue}, beta::Real)
3132
n = length(lambda)
3233
#Calculate normalization constant

src/GaussianEnsembleSamples.jl

Lines changed: 80 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,21 @@ export GaussianHermiteMatrix, GaussianLaguerreMatrix, GaussianJacobiMatrix,
1919
GaussianJacobiSparseMatrix,
2020
GaussianHermiteSamples, GaussianLaguerreSamples, GaussianJacobiSamples
2121

22+
23+
#########################
24+
# Convenience functions #
25+
#########################
26+
27+
#Produces a random variate of the chi distribution
28+
chi(df) = df==0? 0.0 : sqrt(rand(Chisq(df)))
29+
30+
#############################
31+
# Gaussian Wigner ensemble #
32+
# Gaussian Hermite ensemble #
33+
#############################
34+
2235
#Generates a NxN symmetric Wigner matrix
23-
#Hermite ensemble
24-
function GaussianHermiteMatrix(n :: Integer, beta :: Integer)
36+
function GaussianHermiteMatrix(n::Integer, beta::Integer)
2537
if beta == 1 #real
2638
A = randn(n, n)
2739
normalization = sqrt(2*n)
@@ -40,10 +52,24 @@ function GaussianHermiteMatrix(n :: Integer, beta :: Integer)
4052
return (A + A') / normalization
4153
end
4254

55+
#Generates a NxN tridiagonal Wigner matrix
56+
#The beta=infinity case is defined in Edelman, Persson and Sutton, 2012
57+
function GaussianHermiteTridiagonalMatrix(n::Integer, beta::Real)
58+
if beta<=0 error("beta must be positive") end
59+
if beta==Inf return SymTridiagonal(zeros(n), [sqrt(x/2) for x=n-1:-1:1]) end
60+
Hdiag = randn(n)/sqrt(n)
61+
Hsup = [chi(beta*i)/sqrt(2*n) for i=n-1:-1:1]
62+
return SymTridiagonal(Hdiag, Hsup)
63+
end
64+
65+
##############################
66+
# Gaussian Wishart ensemble #
67+
# Gaussian Laguerre ensemble #
68+
##############################
69+
4370
#Generates a NxN Hermitian Wishart matrix
44-
#Laguerre ensemble
4571
#TODO Check - the eigenvalue distribution looks funky
46-
function GaussianLaguerreMatrix(m :: Integer, n :: Integer, beta :: Integer)
72+
function GaussianLaguerreMatrix(m::Integer, n::Integer, beta::Integer)
4773
if beta == 1 #real
4874
A = randn(m, n)
4975
elseif beta == 2 #complex
@@ -58,47 +84,47 @@ function GaussianLaguerreMatrix(m :: Integer, n :: Integer, beta :: Integer)
5884
return (A * A') / m
5985
end
6086

61-
#Generates a NxN self-dual MANOVA Matrix
62-
#Jacobi ensemble
63-
function GaussianJacobiMatrix(m :: Integer, n1 :: Integer, n2 :: Integer, beta :: Integer)
64-
w1 = Wishart(m, n1, beta)
65-
w2 = Wishart(m, n2, beta)
66-
return (w1 + w2) \ w1
87+
88+
#Generates a NxN bidiagonal Wishart matrix
89+
#Laguerre ensemble
90+
function GaussianLaguerreBidiagonalMatrix(m::Integer, a::Real, beta::Real)
91+
min_a = beta*(m-1)/2
92+
a<min_a ? error(@sprintf("Given your choice of m and beta, a must be at least %f (You said a = %f)", min_a, a)) : nothing
93+
Hdiag = [chi(2*a-i*beta) for i=0:m-1]
94+
Hsub = [chi(beta*i) for i=m-1:-1:1]
95+
Bidiagonal(Hsub, Hdiag, false)/(m^0.25)
6796
end
6897

6998

70-
#A convenience function
71-
chi(df) = sqrt(rand(Chisq(df)))
99+
#Generates a NxN tridiagonal Wishart matrix
100+
#Laguerre ensemble
101+
function GaussianLaguerreTridiagonalMatrix(m::Integer, a::Real, beta::Real)
102+
B = GaussianLaguerreBidiagonalMatrix(m, a, beta)
103+
B * B'
104+
end
72105

73-
#Generates a NxN tridiagonal Wigner matrix
74-
#Hermite ensemble
75-
#The beta=infinity case is defined in Edelman, Persson and Sutton, 2012
76-
function GaussianHermiteTridiagonalMatrix(n :: Integer, beta :: FloatingPoint)
77-
if beta<=0 error("beta must be positive") end
78-
if beta==Inf return SymTridiagonal(zeros(n), [sqrt(x/2) for x=n-1:-1:1]) end
79-
Hdiag = randn(n)/sqrt(n)
80-
Hsup = [chi(beta*i)/sqrt(2*n) for i=n-1:-1:1]
81-
return SymTridiagonal(Hdiag, Hsup)
106+
107+
#Return n eigenvalues distributed according to the Hermite ensemble
108+
function GaussianHermiteSamples(n::Integer, beta::Real)
109+
eigvals(GaussianHermiteTridiagonalMatrix(n, beta))
82110
end
83111

84112

85-
#Generates a NxN tridiagonal Wishart matrix
86-
#Laguerre ensemble
87-
function GaussianLaguerreTridiagonalMatrix(m :: Integer, a :: FloatingPoint, beta :: FloatingPoint)
88-
if a <= beta*(m-1)/2.0
89-
error(@sprintf("Given your choice of m and beta, a must be at least %f (You said a = %f)", beta*(m-1)/2.0, a))
90-
end
91-
Hdiag = [chi(2*a-i*beta) for i=0:m-1]
92-
Hsub = [chi(beta*i) for i=m-1:-1:1]
93-
#Julia has no bidiagonal type... yet
94-
B = Tridiagonal(Hsub, Hdiag, zeros(m-1))
95-
L = B * B' #Currently returns a dense matrix
96-
return SymTridiagonal(diag(L)/sqrt(m), diag(L,1)/sqrt(m))
113+
############################
114+
# Gaussian MANOVA ensemble #
115+
# Jacobi ensemble #
116+
############################
117+
118+
#Generates a NxN self-dual MANOVA Matrix
119+
function GaussianJacobiMatrix(m::Integer, n1::Integer, n2::Integer, beta::Integer)
120+
w1 = Wishart(m, n1, beta)
121+
w2 = Wishart(m, n2, beta)
122+
return (w1 + w2) \ w1
97123
end
98124

99125

100126
# A helper function for Jacobi samples
101-
function SampleCSValues(n :: Integer, a :: FloatingPoint, b :: FloatingPoint, beta :: FloatingPoint)
127+
function SampleCSValues(n::Integer, a::Real, b::Real, beta::Real)
102128
if beta == Inf
103129
c=sqrt((a+[1:n])./(a+b+2*[1:n]))
104130
s=sqrt((b+[1:n])./(a+b+2*[1:n]))
@@ -114,6 +140,15 @@ function SampleCSValues(n :: Integer, a :: FloatingPoint, b :: FloatingPoint, be
114140
end
115141
return c, s, cp, sp
116142
end
143+
144+
145+
#Return n eigenvalues distributed according to the Laguerre ensemble
146+
#Compute the singular values of the bidiagonal matrix
147+
function GaussianLaguerreSamples(m::Integer, a::Real, beta::Real)
148+
svdvals(GaussianLaguerreBidiagonalMatrix(m, a, beta))
149+
end
150+
151+
117152
#Generates a 2Mx2M sparse MANOVA matrix
118153
#Jacobi ensemble
119154
#
@@ -122,7 +157,7 @@ end
122157
# and generalized singular value problems", Foundations of Computational Mathematics,
123158
# vol. 8 iss. 2 (2008), pp 259-285.
124159
#TODO check normalization
125-
function GaussianJacobiSparseMatrix(n :: Integer, a :: FloatingPoint, b :: FloatingPoint, beta :: FloatingPoint)
160+
function GaussianJacobiSparseMatrix(n::Integer, a::Real, b::Real, beta::Real)
126161
CoordI = zeros(8n-4)
127162
CoordJ = zeros(8n-4)
128163
Values = zeros(8n-4)
@@ -167,23 +202,20 @@ function GaussianJacobiSparseMatrix(n :: Integer, a :: FloatingPoint, b :: Float
167202
return sparse(CoordI, CoordJ, Values)
168203
end
169204

170-
#Return n eigenvalues distributed according to the Hermite ensemble
171-
function GaussianHermiteSamples(n :: Integer, beta :: FloatingPoint)
172-
eigvals(GaussianHermiteTridiagonalMatrix(n, beta))
173-
end
174-
175-
#Return n eigenvalues distributed according to the Laguerre ensemble
176-
function GaussianLaguerreSamples(m :: Integer, a :: FloatingPoint, beta :: FloatingPoint)
177-
eigvals(GaussianLaguerreTridiagonalMatrix(m, a, beta))
178-
end
179205

180-
#Return n eigenvalues distributed according to the Jacobi ensemble
181-
function GaussianJacobiSamples(n :: Integer, a :: FloatingPoint, b :: FloatingPoint, beta :: FloatingPoint)
206+
#Return n-dimensional bidiagonal matrix representation of the Jacobi ensemble
207+
function GaussianJacobiBidiagonalMatrix(n::Integer, a::Real, b::Real, beta::Real)
182208
#Generate just the upper left quadrant of the matrix
183209
c, s, cp, sp = SampleCSValues(n, a, b, beta)
184210
dv = [i==1 ? c[n] : c[n+1-i] * sp[n+1-i] for i=1:n]
185211
ev = [-s[n+1-i]*cp[n-i] for i=1:n-1]
186-
M = Tridiagonal(zeros(n-1), dv, ev)
187-
return svdvals(full(M)) #No SVD for tridiagonal matrices... yet
212+
Bidiagonal(dv, ev, true)
213+
end
214+
215+
216+
#Return n eigenvalues distributed according to the Jacobi ensemble
217+
function GaussianJacobiSamples(n::Integer, a::Real, b::Real, beta::Real)
218+
svdvals(GaussianJacobiBidiagonalMatrix(n, a, b))
188219
end
189220

221+

src/LargestEigenvalue.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
#Samples the largest eigenvalue of the GUE matrix
3+
function SampleTracyWidom(n::Integer)
4+
k=int(n-10*n^(1/3)-1)
5+
A=[chi(i) for i=(n-1):-1:k]
6+
B=randn(n-k+1)
7+
v=max(eigvals(SymTridiagonal(B, A)))
8+
end
9+

0 commit comments

Comments
 (0)