Skip to content

Commit 38cca6e

Browse files
committed
Test Semicircle law
Add missing imports and exports Make a lot of the Semicircle methods more type stable Also modernize code - 4 space indents, use of iseven(),
1 parent 1f72265 commit 38cca6e

File tree

4 files changed

+102
-56
lines changed

4 files changed

+102
-56
lines changed

src/RandomMatrices.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@ using GSL
66
using ODE
77

88
import Base: isinf, rand
9-
import Distributions: ContinuousMatrixDistribution, Chi, cdf, pdf
9+
import Distributions: ContinuousUnivariateDistribution,
10+
ContinuousMatrixDistribution,
11+
Beta, Chi,
12+
cdf, pdf, entropy, insupport, mean, median, modes, kurtosis, skewness, std, var, moment
1013

1114
export bidrand, #Generate random bidiagonal matrix
1215
tridrand, #Generate random tridiagonal matrix
1316
sprand, #Generate random sparse matrix
1417
eigvalrand, #Generate random set of eigenvalues
1518
eigvaljpdf, #Eigenvalue joint probability density
16-
pdf,
17-
cdf
19+
cumulant, freecumulant, cf, mgf,
20+
cdf, pdf, entropy, insupport, mean, median, modes, kurtosis, skewness, std, var, moment
1821

1922
typealias Dim2 Tuple{Int, Int} #Dimensions of a rectangular matrix
2023

src/densities/Semicircle.jl

Lines changed: 65 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,51 @@
1-
#Wigner semicircle distribution
2-
3-
import Distributions
4-
import Distributions: ContinuousUnivariateDistribution
5-
61
export Semicircle
72

8-
immutable Semicircle <: ContinuousUnivariateDistribution
9-
mean::Float64
10-
radius::Float64
11-
Semicircle(mu, r) = r > 0 ? new(float64(mu), float64(r)) :
12-
error("radius r must be positive") #Constructor
13-
end
3+
"""
4+
Wigner semicircle distribution
145
15-
#Standardized distribution - mean 0, variance 1
16-
Semicircle(mu) = Semicircle(mu, 2.0)
17-
Semicircle() = Semicircle(0.0, 2.0)
6+
By default, creates a standardized distribution
7+
with mean 0 and variance 1 (radius 2)
8+
"""
9+
immutable Semicircle{T<:Real} <: ContinuousUnivariateDistribution
10+
mean::T
11+
radius::T
12+
end
13+
Semicircle{T<:Real}::T=0.0, r::T=2.0) = r > 0 ? Semicircle{T}(μ, r) :
14+
throw(ArgumentError("radius r must be positive, got $r"))
1815

1916
# Distribution function methods
2017
###############################
2118

2219
# cumulative distribution function
23-
function cdf(X::Semicircle, x::Real)
24-
r, a = X.mean, X.radius
25-
insupport(x) ? 0.5 + (x-a)/(pi*r^2) * sqrt(r^2 - (x-a)^2) + 1/pi * asin((x-a)/r) : (x>a ? 1.0 : 0.0)
20+
function cdf{T<:Real}(d::Semicircle{T}, x::T)
21+
r, a = d.mean, d.radius
22+
if insupport(d, x)
23+
return 0.5 + (x-a)/*r^2) * (r^2 - (x-a)^2) + asin((x-a)/r)/π
24+
elseif x a
25+
return one(T)
26+
else
27+
return zero(T)
28+
end
2629
end
2730

2831
# probability density function
29-
function pdf(X::Semicircle, x::Real)
30-
r, a = X.mean, X.radius
31-
insupport(x) ? 2/(pi*r^2) * sqrt(r^2 - (x-a)^2) : 0.0
32+
function pdf{T<:Real}(d::Semicircle{T}, x::T)
33+
r, a = d.mean, d.radius
34+
if insupport(d, x)
35+
return 2/*r^2) * (r^2 - (x-a)^2)
36+
else
37+
return zero(T)
38+
end
3239
end
3340

3441
# predicate is x in the support of the distribution?
35-
insupport(X::Semicircle, x::Real)=abs(x)<=X.radius
36-
42+
insupport{T<:Real}(d::Semicircle{T}, x::T)=abs(x)<d.radius
3743

3844
#Entropy methods
3945
################
4046

4147
# entropy of distribution in nats
42-
entropy(X::Semicircle)=log(pi*X.radius) - 0.5
48+
entropy(X::Semicircle)=log(π*X.radius) - 0.5
4349

4450
#Measures of central tendency methods
4551
#####################################
@@ -51,13 +57,13 @@ mean(X::Semicircle)=X.mean
5157
median(X::Semicircle)=X.mean
5258

5359
# mode(s) of distribution as vector
54-
modes(X::Semicircle)=[X.mean]
60+
modes{T}(X::Semicircle{T})=T[X.mean]
5561

5662
# kurtosis of the distribution
57-
kurtosis(X::Semicircle)=2
63+
kurtosis{T}(X::Semicircle{T})=T(2)
5864

5965
# skewness of the distribution
60-
skewness(X::Semicircle)=0
66+
skewness{T}(X::Semicircle{T})=T(0)
6167

6268
# standard deviation of distribution
6369
std(X::Semicircle)=X.radius/2
@@ -66,51 +72,57 @@ std(X::Semicircle)=X.radius/2
6672
var(X::Semicircle)=std(X)^2
6773

6874
# moment of distribution
69-
function moment(X::Semicircle, order::Integer)
75+
function moment{T<:Real}(X::Semicircle{T}, order::Integer)
7076
a, r = X.mean, X.radius
7177
if X.mean != 0
72-
a^n*hypergeom([(1-n)/2, -n/2], 2, (r/a)^2)
78+
return a^n*hypergeom([(1-n)/2, -n/2], 2, (r/a)^2)
79+
elseif iseven(order)
80+
return (0.5*r)^(2order) * T(catalannum(order÷2))
7381
else
74-
order%2 ? (0.5*r)^(2n) * catalan(div(order,2)) : 0
82+
return zero(T)
7583
end
7684
end
7785

7886
# cumulant of distribution
79-
function cumulant(X::Semicircle, order::Integer)
80-
if X.mean != 0 error("not supported") end
81-
if order%2
82-
order==0 ? 1 : (0.5*r)^(2n) * lassalle(order/2)
83-
else
84-
0
85-
end
87+
function cumulant{T<:Real}(d::Semicircle{T}, order::Integer)
88+
if d.mean != 0
89+
throw(ArgumentError("Non-central Semicircle not supported"))
90+
end
91+
92+
if order==0
93+
return one(T)
94+
elseif iseven(order)
95+
return (0.5*d.radius)^(2order) * T(lassallenum(order÷2))
96+
else
97+
return zero(T)
98+
end
8699
end
87100

88101
# free cumulant of distribution
89-
function freecumulant(X::Semicircle, order::Integer)
90-
if order == 0
91-
return 1
92-
elseif order == 1
93-
return mean(X)
94-
elseif order == 2
95-
return var(X)
96-
else
97-
return 0
98-
end
102+
function freecumulant{T<:Real}(d::Semicircle{T}, order::Int)
103+
if order == 0
104+
return one(T)
105+
elseif order == 1
106+
return mean(X)
107+
elseif order == 2
108+
return var(X)
109+
else
110+
return zero(T)
111+
end
99112
end
100113

101-
102114
#Generating function methods
103115
############################
104116

105117
# characteristic function
106-
function cf(X::Semicircle, t::Real)
107-
r = t * X.mean
118+
function cf(d::Semicircle, t::Real)
119+
r = t / d.mean
108120
2 * besselj(1, r)/r
109121
end
110122

111123
# moment generating function
112-
function mgf(X::Semicircle, t::Real)
113-
r = t * X.mean
124+
function mgf(d::Semicircle, t::Real)
125+
r = t * d.mean
114126
2 * besseli(1, r)/r
115127
end
116128

@@ -120,6 +132,6 @@ end
120132
# random sampler
121133
# Use relationship with beta distribution
122134
function rand(X::Semicircle)
123-
Y = rand(Beta(1.5, 1.5))
124-
X.mean + 2 * X.radius * Y - X.radius
135+
Y = rand(Beta(1.5, 1.5))
136+
X.mean + 2 * X.radius * Y - X.radius
125137
end

test/densities/Semicircle.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using RandomMatrices
2+
using Base.Test
3+
4+
let
5+
d = Semicircle()
6+
@test cdf(d, 2.0) == 1.0
7+
@test cdf(d, -2.0) == 0.0
8+
@test pdf(d, 2.0) == 0.0
9+
@test pdf(d, -2.0) == 0.0
10+
11+
@test entropy(d) == log(2π) - 0.5
12+
@test mean(d) == median(d) == skewness(d) == 0
13+
@test modes(d) == [0]
14+
@test std(d) == var(d) == 1
15+
@test kurtosis(d) == 2
16+
17+
@test isfinite(rand(d))
18+
@test moment(d, 4) == 2
19+
@test cumulant(d, 4) == 1
20+
@test moment(d, 5) == cumulant(d, 5) == freecumulant(d, 5) == 0
21+
22+
@test cf(d, 1.0) == 0.0
23+
24+
#XXX Throws AmosException - ???
25+
#@show mgf(d, 1.0)
26+
27+
x = rand(d)
28+
@test insupport(d, x)
29+
end
30+

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ include("FormalPowerSeries.jl")
77
include("Haar.jl")
88
include("StochasticProcess.jl")
99

10+
include("densities/Semicircle.jl")
1011
include("densities/TracyWidom.jl")
1112

0 commit comments

Comments
 (0)