Skip to content

Commit fc98f3b

Browse files
authored
Add docstrings for random matrix ensembles (#89)
* add /test Project.toml * add doctests.jl test file and /docs folder * add doctests for random matrix ensembles * switch jldoctest to @example
1 parent c76044d commit fc98f3b

File tree

13 files changed

+236
-45
lines changed

13 files changed

+236
-45
lines changed

Project.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ GSL = "92c85e6c-cbff-5e0c-80f7-495c94daaecd"
1010
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1111
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1212
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
13-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1413

1514
[compat]
1615
Combinatorics = "0.7.0, 1"
@@ -19,3 +18,9 @@ FastGaussQuadrature = "0.3, 0.4, 0.5, 1"
1918
GSL = "0.4, 1"
2019
SpecialFunctions = "0.7, 1, 2"
2120
julia = "1.6"
21+
22+
[extras]
23+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
24+
25+
[targets]
26+
test = ["Test"]

docs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build/
2+
site/

docs/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[deps]
2+
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
RandomMatrices = "2576dda1-a324-5b11-aa66-c48ed7e3c618"

docs/make.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
push!(LOAD_PATH,"../src/")
2+
3+
using Documenter
4+
using RandomMatrices
5+
6+
DocMeta.setdocmeta!(RandomMatrices, :DocTestSetup, :(using RandomMatrices, Random); recursive=true)
7+
8+
function main()
9+
10+
makedocs(
11+
doctest = false,
12+
clean = true,
13+
sitename = "RandomMatrices.jl",
14+
format = Documenter.HTML(
15+
assets=["assets/init.js"]
16+
),
17+
modules = [RandomMatrices],
18+
checkdocs = :exports,
19+
warnonly = false,
20+
authors = "Andrew Kille",
21+
pages = [
22+
"RandomMatrices.jl" => "index.md",
23+
"Full API" => "API.md"
24+
]
25+
)
26+
end
27+
28+
main()

docs/src/API.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# [Full API](@id Full-API)
2+
3+
```@raw html
4+
<style>
5+
.content table td {
6+
padding-top: 0 !important;
7+
padding-bottom: 0 !important;
8+
}
9+
</style>
10+
```
11+
12+
## Autogenerated API list
13+
14+
```@autodocs
15+
Modules = [RandomMatrices]
16+
Private = false
17+
```

docs/src/index.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# RandomMatrices.jl
2+
3+
```@meta
4+
DocTestSetup = quote
5+
using RandomMatrices
6+
end
7+
```

src/GaussianEnsembles.jl

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,21 @@ export GaussianHermite, GaussianLaguerre, GaussianJacobi,
2424
#####################
2525

2626
"""
27-
GaussianHermite{β} represents a Gaussian Hermite ensemble with parameter β.
27+
GaussianHermite(β::Int) <: ContinuousMatrixDistribution
2828
29-
Wigner{β} is a synonym.
29+
Represents a Gaussian Hermite ensemble with Dyson index `β`.
3030
31-
Example of usage:
31+
`Wigner(β)` is a synonym.
3232
33-
β = 2 #β = 1, 2, 4 generates real, complex and quaternionic matrices respectively.
34-
d = Wigner{β} #same as GaussianHermite{β}
33+
## Examples
3534
36-
n = 20 #Generate square matrices of this size
37-
38-
S = rand(d, n) #Generate a 20x20 symmetric Wigner matrix
39-
T = tridrand(d, n) #Generate the symmetric tridiagonal form
40-
v = eigvalrand(d, n) #Generate a sample of eigenvalues
35+
```@example
36+
julia> rand(Wigner(2), 3)
37+
3×3 LinearAlgebra.Hermitian{ComplexF64, Matrix{ComplexF64}}:
38+
0.383322+0.0im -0.0452508+0.491032im -0.313208-0.330435im
39+
-0.0452508-0.491032im -0.264521+0.0im -0.131337+0.0904235im
40+
-0.313208+0.330435im -0.131337-0.0904235im -0.481758+0.0im
41+
```
4142
"""
4243
struct GaussianHermite{β} <: ContinuousMatrixDistribution end
4344
GaussianHermite(β) = GaussianHermite{β}()
@@ -47,6 +48,13 @@ Synonym for GaussianHermite{β}
4748
"""
4849
const Wigner{β} = GaussianHermite{β}
4950

51+
"""
52+
rand(d::Wigner, n::Int)
53+
54+
Generates an `n × n` matrix randomly sampled from the Gaussian-Hermite ensemble (also known as the Wigner ensemble).
55+
56+
The Dyson index `β` is restricted to `β = 1,2` or `4`, for real, complex, and quaternionic fields, respectively.
57+
"""
5058
rand(d::Type{Wigner{β}}, dims...) where {β} = rand(d(), dims...)
5159

5260
function rand(d::Wigner{1}, n::Int)
@@ -82,12 +90,15 @@ function rand(d::Wigner{β}, dims::Int...) where {β}
8290
end
8391

8492
"""
85-
Generates a nxn symmetric tridiagonal Wigner matrix
93+
tridand(d::Wigner, n::Int)
94+
95+
Generates an `n × n` symmetric tridiagonal matrix from the Gaussian-Hermite ensemble (also known as the Wigner ensemble).
8696
87-
Unlike for `rand(Wigner{β}, n)`, which is restricted to β=1,2 or 4,
88-
`trirand(Wigner{β}, n)` will generate a
97+
Unlike for `rand(Wigner(β), n)`, which is restricted to `β = 1,2` or `4`,
98+
the call `trirand(Wigner(β), n)` will generate a tridiagonal Wigner matrix for any positive
99+
value of `β`, including infinity.
89100
90-
The β=∞ case is defined in Edelman, Persson and Sutton, 2012
101+
The `β == ∞` case is defined in Edelman, Persson and Sutton, 2012.
91102
"""
92103
function tridrand(d::Wigner{β}, n::Int) where {β}
93104
χ(df::Real) = rand(Distributions.Chi(df))
@@ -146,16 +157,37 @@ end
146157
# Laguerre ensemble #
147158
#####################
148159

160+
"""
161+
GaussianLaguerre(β::Real, a::Real)` <: ContinuousMatrixDistribution
162+
163+
Represents a Gaussian-Laguerre ensemble with Dyson index `β` and `a` parameter
164+
used to control the density of eigenvalues near `λ = 0`.
165+
166+
`Wishart(β, a)` is a synonym.
167+
168+
## Fields
169+
- `beta`: Dyson index
170+
- `a`: Parameter used for weighting the joint probability density function of the ensemble
171+
172+
## References:
173+
- Edelman and Rao, 2005
174+
"""
149175
mutable struct GaussianLaguerre <: ContinuousMatrixDistribution
150176
beta::Real
151177
a::Real
152178
end
153179
const Wishart = GaussianLaguerre
154180

155-
156-
#Generates a NxN Hermitian Wishart matrix
157181
#TODO Check - the eigenvalue distribution looks funky
158182
#TODO The appropriate matrix size should be calculated from a and one matrix dimension
183+
"""
184+
rand(d::GaussianLaguerre, dims::Tuple)
185+
186+
Generate a random matrix sampled from the Gaussian Laguerre ensemble (also known as the Wishart ensemble)
187+
with parameters defined in `d` and dimensions given by `dims`.
188+
189+
The Dyson index `β` is restricted to `β = 1,2` or `4`, for real, complex, and quaternionic fields, respectively.
190+
"""
159191
function rand(d::GaussianLaguerre, dims::Dim2)
160192
n = 2.0*a/d.beta
161193
if d.beta == 1 #real
@@ -172,15 +204,23 @@ function rand(d::GaussianLaguerre, dims::Dim2)
172204
return (A * A') / dims[1]
173205
end
174206

175-
#Generates a NxN bidiagonal Wishart matrix
207+
"""
208+
bidrand(d::GaussianLaguerre, n::Int)
209+
210+
Generate an `n × n` bidiagonal matrix sampled from the Gaussian Laguerre ensemble (also known as the Wishart ensemble).
211+
"""
176212
function bidrand(d::GaussianLaguerre, m::Integer)
177213
if d.a <= d.beta*(m-1)/2.0
178214
error("Given your choice of m and beta, a must be at least $(d.beta*(m-1)/2.0) (You said a = $(d.a))")
179215
end
180216
Bidiagonal([chi(2*d.a-i*d.beta) for i=0:m-1], [chi(d.beta*i) for i=m-1:-1:1], true)
181217
end
182218

183-
#Generates a NxN tridiagonal Wishart matrix
219+
"""
220+
tridrand(d::GaussianLaguerre, n::Int)
221+
222+
Generate an `n × n` tridiagonal matrix sampled from the Gaussian Laguerre ensemble (also known as the Wishart ensemble).
223+
"""
184224
function tridrand(d::GaussianLaguerre, m::Integer)
185225
B = bidrand(d, m)
186226
L = B * B'
@@ -218,14 +258,35 @@ end
218258
# Jacobi ensemble #
219259
###################
220260

221-
#Generates a NxN self-dual MANOVA matrix
261+
"""
262+
GaussianJacobi(β::Real, a::Real, a::Real)` <: ContinuousMatrixDistribution
263+
264+
Represents a Gaussian-Jacobi ensemble with Dyson index `β`, while
265+
`a`and `b` are parameters used to weight the joint probability density function of the ensemble.
266+
267+
`MANOVA(β, a, b)` is a synonym.
268+
269+
## Fields
270+
- `beta`: Dyson index
271+
- `a`: Parameter used for shaping the joint probability density function near `λ = 0`
272+
- `b`: Parameter used for shaping the joint probability density function near `λ = 1`
273+
274+
## References:
275+
- Edelman and Rao, 2005
276+
"""
222277
mutable struct GaussianJacobi <: ContinuousMatrixDistribution
223278
beta::Real
224279
a::Real
225280
b::Real
226281
end
227282
const MANOVA = GaussianJacobi
228283

284+
"""
285+
rand(d::GaussianJacobi, n::Int)
286+
287+
Generate an `n × n` random matrix sampled from the Gaussian-Jacobi ensemble (also known as the MANOVA ensemble)
288+
with parameters defined in `d`.
289+
"""
229290
function rand(d::GaussianJacobi, m::Integer)
230291
w1 = Wishart(m, int(2.0*d.a/d.beta), d.beta)
231292
w2 = Wishart(m, int(2.0*d.b/d.beta), d.beta)

src/Ginibre.jl

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,42 @@
11
export rand, Ginibre
22
import Base.rand
33

4-
#Samples a matrix from the Ginibre ensemble
5-
#This ensemble lives in GL(N, F), the set of all invertible N x N matrices
6-
#over the field F
7-
#For beta=1,2,4, F=R, C, H respectively
4+
"""
5+
Ginibre(β::Int, N::Int) <: ContinuousMatrixDistribution
6+
7+
Represents a Ginibre ensemble with Dyson index `β` living in `GL(N, F)`, the set
8+
of all invertible `N × N` matrices over the field `F`.
9+
10+
## Fields
11+
- `beta`: Dyson index
12+
- `N`: Matrix dimension over the field `F`.
13+
14+
## Examples
15+
16+
```@example
17+
julia> rand(Ginibre(2, 3))
18+
3×3 Matrix{ComplexF64}:
19+
0.781329+2.00346im 0.0595122+0.488652im -0.323494-0.35966im
20+
1.11089+0.935174im -0.384457+1.71419im 0.114358-0.360676im
21+
1.54119+0.362003im -0.693623-2.50141im -1.42383-1.06341im
22+
```
23+
24+
## References:
25+
- Edelman and Rao, 2005
26+
"""
827
struct Ginibre <: ContinuousMatrixDistribution
928
beta::Float64
1029
N::Integer
1130
end
1231

32+
"""
33+
rand(W::Ginibre)
34+
35+
Samples a matrix from the Ginibre ensemble.
36+
37+
For `β = 1,2,4`, generates matrices randomly sampled from the real, complex, and quaternion
38+
Ginibre ensemble, respectively.
39+
"""
1340
function rand(W::Ginibre)
1441
beta, n = W.beta, W.N
1542
if beta==1

src/Haar.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,30 @@ end
6464
data(P::Ptr{gsl_permutation}) = [convert(Int64, x)+1 for x in
6565
pointer_to_array(permutation_data(P), (convert(Int64, permutation_size(P)) ,))]
6666

67+
"""
68+
Haar(β::Int) <: ContinuousMatrixDistribution
6769
70+
Represents a Haar measure with Dyson index `β`, in which values of `β = 1,2` or `4`
71+
correspond to matrices are distributed with uniform Haar measure over the
72+
classical orthogonal, unitary and symplectic groups `O(n)`, `U(n)` and
73+
`Sp(n)~USp(2n)` respectively.
74+
75+
## Fields
76+
- `beta`: Dyson index
77+
78+
## Examples
79+
80+
```@example
81+
julia> rand(Haar(2), 3)
82+
3×3 Matrix{ComplexF64}:
83+
-0.275126-0.112754im -0.217139-0.293544im 0.299633-0.829756im
84+
0.48675-0.575106im 0.226526-0.445825im -0.406164-0.131472im
85+
-0.245835-0.532433im 0.375591+0.689594im -0.0243468-0.197175im
86+
```
87+
88+
## References:
89+
- Edelman and Rao, 2005
90+
"""
6891
mutable struct Haar <: ContinuousMatrixDistribution
6992
beta::Real
7093
end

src/HaarMeasure.jl

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
1-
# Computes samples of real or complex Haar matrices of size nxn
2-
#
3-
# For beta=1,2,4, generates random orthogonal, unitary and symplectic matrices
4-
# of uniform Haar measure.
5-
# These matrices are distributed with uniform Haar measure over the
6-
# classical orthogonal, unitary and symplectic groups O(N), U(N) and
7-
# Sp(N)~USp(2N) respectively.
8-
#
9-
# The last parameter specifies whether or not the piecewise correction
10-
# is applied to ensure that it truly of Haar measure
11-
# This addresses an inconsistency in the Householder reflections as
12-
# implemented in most versions of LAPACK
13-
# Method 0: No correction
14-
# Method 1: Multiply rows by uniform random phases
15-
# Method 2: Multiply rows by phases of diag(R)
16-
# References:
17-
# Edelman and Rao, 2005
18-
# Mezzadri, 2006, math-ph/0609050
191
#TODO implement O(n^2) method
20-
#By default, always do piecewise correction
21-
#For most applications where you use the HaarMatrix as a similarity transform
22-
#it doesn't matter, but better safe than sorry... let the user choose else
2+
"""
3+
rand(W::Haar, n::Int)
4+
5+
Computes samples of real or complex Haar matrices of size `n`×`n`.
6+
7+
For `beta = 1,2,4`, generates random orthogonal, unitary and symplectic matrices
8+
of uniform Haar measure.
9+
These matrices are distributed with uniform Haar measure over the
10+
classical orthogonal, unitary and symplectic groups `O(n)`, `U(n)` and
11+
`Sp(n)~USp(2n)` respectively.
12+
13+
rand(W::Haar, n::Int, doCorrection::Int = 1)
14+
15+
The additional argument `doCorrection` specifies whether or not the piecewise correction
16+
is applied to ensure that it is truly of Haar measure.
17+
This addresses an inconsistency in the Householder reflections as
18+
implemented in most versions of LAPACK.
19+
- Method 0: No correction
20+
- Method 1: Multiply rows by uniform random phases
21+
- Method 2: Multiply rows by phases of diag(R)
22+
23+
## References:
24+
- Edelman and Rao, 2005
25+
- Mezzadri, 2006, math-ph/0609050
26+
"""
2327
function rand(W::Haar, n::Int, doCorrection::Int=1)
2428
beta = W.beta
2529
M=rand(Ginibre(beta,n))

test/Project.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[deps]
2+
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
4+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
5+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

test/doctests.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using Documenter
2+
using RandomMatrices
3+
using Test
4+
5+
@testset "Doctests" begin
6+
DocMeta.setdocmeta!(RandomMatrices, :DocTestSetup, :(using RandomMatrices, Random); recursive=true)
7+
doctest(RandomMatrices)
8+
end

0 commit comments

Comments
 (0)