Skip to content

Commit

Permalink
Merge pull request #9 from adknudson/add-julia-formatter
Browse files Browse the repository at this point in the history
Add JuliaFormatter
  • Loading branch information
adknudson authored Mar 23, 2024
2 parents bd08bf1 + 828714e commit 9704fdf
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 60 deletions.
8 changes: 8 additions & 0 deletions .JuliaFormatter.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
style = "blue"

whitespace_in_kwargs = false
whitespace_ops_in_indices = false
trailing_comma = false
disallow_single_arg_nesting = true

ignore = ["test"]
2 changes: 1 addition & 1 deletion .github/workflows/Downgrade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ jobs:
version: ${{ matrix.version }}
- uses: julia-actions/julia-downgrade-compat@v1
with:
skip: Pkg,TOML,Aqua,Polynomials
skip: Pkg,TOML,JuliaFormatter,Aqua,SafeTestsets,Polynomials
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
6 changes: 5 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@ Aqua = "0.8"
Distributions = "0.24.5, 0.25.57"
FastGaussQuadrature = "1"
IrrationalConstants = "0.1.1, 0.2"
JuliaFormatter = "1"
LinearAlgebra = "<0.0.1, 1"
PolynomialRoots = "1"
Polynomials = "4"
PrecompileTools = "1"
SafeTestsets = "0.1"
SharedArrays = "<0.0.1, 1"
StatsFuns = "0.9.15, 1"
Test = "1"
julia = "1.6, 1.7, 1.8, 1.9, 1.10"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45"
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "Polynomials", "Aqua"]
test = ["Test", "Polynomials", "Aqua", "JuliaFormatter", "SafeTestsets"]
3 changes: 0 additions & 3 deletions src/PearsonCorrelationMatch.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@ using PolynomialRoots: roots
using SharedArrays: SharedMatrix, sdata
using StatsFuns: normcdf, normpdf, norminvcdf


export pearson_bounds, pearson_match


include("common.jl")
include("pearson_bounds.jl")
include("pearson_match.jl")


using PrecompileTools
using Distributions: Distributions

Expand Down
47 changes: 17 additions & 30 deletions src/common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ function _generate_coefs(F, n::Int, m::Int=2n)
return a
end


"""
Equation (41) of the reference paper.
"""
Expand All @@ -36,30 +35,29 @@ function _Gn0_discrete(n::Int, A, B, a, b, invs1s2)
accu = zero(Float64)

for r in 1:M, s in 1:N
r00 = _hermite_normpdf(a[r], n-1) * _hermite_normpdf(b[s], n-1)
r10 = _hermite_normpdf(a[r+1], n-1) * _hermite_normpdf(b[s], n-1)
r01 = _hermite_normpdf(a[r], n-1) * _hermite_normpdf(b[s+1], n-1)
r11 = _hermite_normpdf(a[r+1], n-1) * _hermite_normpdf(b[s+1], n-1)
r00 = _hermite_normpdf(a[r], n - 1) * _hermite_normpdf(b[s], n - 1)
r10 = _hermite_normpdf(a[r+1], n - 1) * _hermite_normpdf(b[s], n - 1)
r01 = _hermite_normpdf(a[r], n - 1) * _hermite_normpdf(b[s+1], n - 1)
r11 = _hermite_normpdf(a[r+1], n - 1) * _hermite_normpdf(b[s+1], n - 1)

accu += A[r] * B[s] * (r11 + r00 - r01 - r10)
end

return accu * invs1s2
end


"""
Equation (49) of the reference paper.
"""
function _Gn0_mixed(n::Int, A, a, F, invs1s2, m::Int=n+4)
function _Gn0_mixed(n::Int, A, a, F, invs1s2, m::Int=n + 4)
n == 0 && return zero(Float64)

M = length(A)

accu = zero(Float64)

for r in 1:M
accu += A[r] * (_hermite_normpdf(a[r+1], n-1) - _hermite_normpdf(a[r], n-1))
accu += A[r] * (_hermite_normpdf(a[r+1], n - 1) - _hermite_normpdf(a[r], n - 1))
end

t, w = gausshermite(m)
Expand All @@ -84,7 +82,6 @@ function _Gn0_mixed(n::Int, A, a, F, invs1s2, m::Int=n+4)
return -invs1s2 * accu * S
end


"""
The "probabilist's" Hermite polynomial of degree ``k``.
"""
Expand Down Expand Up @@ -113,14 +110,12 @@ _hermite(x, n) = _hermite(convert(Float64, x), convert(Int, n))
_hermite_normpdf(x::Float64, k::Int) = isinf(x) ? zero(x) : _hermite(x, k) * normpdf(x)
_hermite_normpdf(x, k) = _hermite_normpdf(convert(Float64, x), convert(Int, k))


"""
_is_real(x::Complex)
Check if a number is real within a given tolerance.
"""
_is_real(x::Complex{T}) where T = abs(imag(x)) < sqrt(eps(T))

_is_real(x::Complex{T}) where {T} = abs(imag(x)) < sqrt(eps(T))

"""
_real_roots(coeffs)
Expand All @@ -136,7 +131,6 @@ function _real_roots(coeffs)
return unique!(xs)
end


"""
_feasible_roots(coeffs)
Expand All @@ -149,7 +143,6 @@ function _feasible_roots(coeffs)
return filter!(x -> abs(x) 1.0 + sqrt(eps()), xs)
end


"""
_nearest_root(target, roots)
Expand All @@ -170,7 +163,6 @@ function _nearest_root(target, roots)
return y
end


"""
_best_root(p, xs)
Expand All @@ -181,11 +173,10 @@ Consider the feasible roots and return a value.
"""
function _best_root(p, roots)
length(roots) == 1 && return clamp(first(roots), -1, 1)
length(roots) > 1 && return _nearest_root(p, roots)
length(roots) > 1 && return _nearest_root(p, roots)
return p < 0 ? nextfloat(-one(Float64)) : prevfloat(one(Float64))
end


"""
_idx_subsets2(d)
Expand All @@ -197,42 +188,40 @@ function _idx_subsets2(d::Int)
xs = Vector{Tuple}(undef, n)

k = 1
for i = 1:d-1
for j = i+1:d
xs[k] = (i,j)
for i in 1:d-1
for j in i+1:d
xs[k] = (i, j)
k += 1
end
end

return xs
end


"""
_symmetric!(X)
Copy the upper part of a matrix to its lower half.
"""
function _symmetric!(X::AbstractMatrix{T}) where T
function _symmetric!(X::AbstractMatrix{T}) where {T}
m, n = size(X)
m == n || throw(DimensionMismatch("Input matrix must be square"))

for i = 1:n-1
for j = i+1:n
@inbounds X[j,i] = X[i,j]
for i in 1:n-1
for j in i+1:n
@inbounds X[j, i] = X[i, j]
end
end

return X
end


"""
_set_diag1!(X)
Set the diagonal elements of a square matrix to `1`.
"""
function _set_diag1!(X::AbstractMatrix{T}) where T
function _set_diag1!(X::AbstractMatrix{T}) where {T}
m, n = size(X)
m == n || throw(DimensionMismatch("Input matrix must be square"))

Expand All @@ -243,20 +232,18 @@ function _set_diag1!(X::AbstractMatrix{T}) where T
return X
end


"""
_project_psd(X, ϵ)
Project `X` onto the set of PSD matrixes.
"""
function _project_psd!(X, ϵ)
λ, P = eigen(Symmetric(X), sortby=x->-x)
λ, P = eigen(Symmetric(X); sortby=x -> -x)
replace!(x -> max(x, ϵ), λ)
X .= P * Diagonal(λ) * P'
return X
end


"""
_cov2cor!(X)
Expand Down
13 changes: 6 additions & 7 deletions src/pearson_bounds.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,15 @@ function pearson_bounds(d1::UD, d2::UD, n=32)
c2 = inv(s1 * s2)
kab = a .* factorial.(k) .* b

pl = c1 * c2 + c2 * sum((-1).^k .* kab)
pl = c1 * c2 + c2 * sum((-1) .^ k .* kab)
pu = c1 * c2 + c2 * sum(kab)

pl = clamp(pl, -1, 1)
pu = clamp(pu, -1, 1)

return (lower = Float64(pl), upper = Float64(pu))
return (lower=Float64(pl), upper=Float64(pu))
end


"""
pearson_bounds(margins::AbstractVector{<:UnivariateDistribution}, n::Int)
Expand Down Expand Up @@ -75,10 +74,10 @@ function pearson_bounds(margins::AbstractVector{<:UD}, n=32)
lower = SharedMatrix{Float64}(d, d)
upper = SharedMatrix{Float64}(d, d)

Base.Threads.@threads for (i,j) in _idx_subsets2(d)
Base.Threads.@threads for (i, j) in _idx_subsets2(d)
l, u = pearson_bounds(margins[i], margins[j], n)
@inbounds lower[i,j] = l
@inbounds upper[i,j] = u
@inbounds lower[i, j] = l
@inbounds upper[i, j] = u
end

L, U = sdata(lower), sdata(upper)
Expand All @@ -89,5 +88,5 @@ function pearson_bounds(margins::AbstractVector{<:UD}, n=32)
_symmetric!(U)
_set_diag1!(U)

(lower = L, upper = U)
return (lower=L, upper=U)
end
20 changes: 7 additions & 13 deletions src/pearson_match.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ function pearson_match(p::Real, d1::UD, d2::UD, n=21)
return _pearson_match(Float64(p), d1, d2, Int(n))
end



function _pearson_match(p::Float64, d1::CUD, d2::CUD, n::Int)
m1 = mean(d1)
m2 = mean(d2)
Expand All @@ -44,7 +42,6 @@ function _pearson_match(p::Float64, d1::CUD, d2::CUD, n::Int)
return _best_root(p, xs)
end


function _pearson_match(p::Float64, d1::DUD, d2::DUD, n::Int)
max1 = maximum(d1)
max2 = maximum(d2)
Expand All @@ -66,17 +63,16 @@ function _pearson_match(p::Float64, d1::DUD, d2::DUD, n::Int)

c2 = inv(s1 * s2)

coef = zeros(Float64, n+1)
coef = zeros(Float64, n + 1)
for k in 1:n
@inbounds coef[k + 1] = _Gn0_discrete(k, A, B, a, b, c2) / factorial(big(k))
@inbounds coef[k+1] = _Gn0_discrete(k, A, B, a, b, c2) / factorial(big(k))
end
coef[1] = -p

xs = _feasible_roots(coef)
return _best_root(p, xs)
end


function _pearson_match(p::Float64, d1::DUD, d2::CUD, n::Int)
s1 = std(d1)
s2 = std(d2)
Expand All @@ -89,7 +85,7 @@ function _pearson_match(p::Float64, d1::DUD, d2::CUD, n::Int)

c2 = inv(s1 * s2)

coef = zeros(Float64, n+1)
coef = zeros(Float64, n + 1)
for k in 1:n
@inbounds coef[k+1] = _Gn0_mixed(k, A, a, d2, c2) / factorial(big(k))
end
Expand All @@ -99,13 +95,10 @@ function _pearson_match(p::Float64, d1::DUD, d2::CUD, n::Int)
return _best_root(p, xs)
end


function _pearson_match(p::Float64, d1::CUD, d2::DUD, n::Int)
return _pearson_match(p, d2, d1, n)
end



"""
pearson_match(rho::AbstractMatrix{<:Real}, margins::AbstractVector{<:UnivariateDistribution}, n::Int)
Expand All @@ -132,16 +125,17 @@ julia> pearson_match(rho, margins)
0.612753 0.418761 1.0
```
"""
function pearson_match(rho::AbstractMatrix{T}, margins::AbstractVector{<:UD}, n=21) where {T<:Real}
function pearson_match(rho::AbstractMatrix{<:Real}, margins::AbstractVector{<:UD}, n=21)
d = length(margins)
r, s = size(rho)
(r == s == d) || throw(DimensionMismatch("The number of margins must be the same size as the correlation matrix."))
(r == s == d) ||
throw(DimensionMismatch("The number of margins must be the same size as the correlation matrix."))

R = SharedMatrix{Float64}(d, d)

# Calculate the pearson matching pairs
Base.Threads.@threads for (i, j) in _idx_subsets2(d)
@inbounds R[i, j] = pearson_match(rho[i,j], margins[i], margins[j], n)
@inbounds R[i, j] = pearson_match(rho[i, j], margins[i], margins[j], n)
end

S = sdata(R)
Expand Down
8 changes: 8 additions & 0 deletions test/format_check.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Test
using PearsonCorrelationMatch
using JuliaFormatter

if VERSION >= v"1.6"
print("Testing code formatting...")
@test JuliaFormatter.format(PearsonCorrelationMatch; verbose=false, overwrite=false)
end
11 changes: 6 additions & 5 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Test
using SafeTestsets

include("qa.jl")
include("internals.jl")
include("matching.jl")
include("bounds.jl")
@safetestset "Quality Assurance" include("qa.jl")
@safetestset "Formatting" include("format_check.jl")
@safetestset "Utilities" include("internals.jl")
@safetestset "Pearson Matching" include("matching.jl")
@safetestset "Pearson Bounds" include("bounds.jl")

0 comments on commit 9704fdf

Please sign in to comment.