| |
| |
| |
|
|
| using FunctionalGPs: Interval |
| using LinearAlgebra |
| using SparseArrays |
| using GaussianMarkovRandomFields: GMRF, ConstrainedGMRF, precision_matrix |
|
|
| export midpoint |
|
|
| """ |
| midpoint(interv::Interval) |
| |
| Compute the midpoint of an interval. |
| """ |
| midpoint(interv::Interval) = 0.5 * (interv[1] + interv[2]) |
|
|
| |
| |
| |
|
|
| export dense_std, dense_var, dense_cov, is_dense_gmrf |
|
|
| """ |
| is_dense_gmrf(gmrf::GMRF) |
| |
| Check if a GMRF has a dense (non-sparse) precision matrix. |
| """ |
| is_dense_gmrf(gmrf::GMRF) = !(precision_matrix(gmrf) isa SparseMatrixCSC) |
|
|
| """ |
| dense_var(gmrf::GMRF) |
| dense_var(gmrf::ConstrainedGMRF) |
| |
| Compute variance of a GMRF by computing the diagonal of Q⁻¹ via Cholesky. |
| |
| For a Cholesky factorization Q = LLᵀ, we have Q⁻¹ = L⁻ᵀL⁻¹. |
| The diagonal elements are: Σᵢᵢ = ||L⁻ᵀeᵢ||² = Σⱼ (L⁻¹)ᵢⱼ² |
| |
| This is O(n³) for the factorization plus O(n²) for extracting the diagonal. |
| """ |
| function dense_var(gmrf::GMRF) |
| Q = precision_matrix(gmrf) |
| F = cholesky(Symmetric(Matrix(Q))) |
| Linv = inv(F.L) |
| |
| return vec(sum(Linv .^ 2, dims=1)) |
| end |
|
|
| |
| |
| |
| function dense_var(gmrf::ConstrainedGMRF) |
| |
| σ_base = dense_var(gmrf.base_gmrf) |
|
|
| |
| B_T = gmrf.L_c.L \ gmrf.A_tilde_T' |
|
|
| |
| B_squared_rowsums = vec(sum(abs2, B_T, dims=1)) |
|
|
| |
| σ_constrained = σ_base - B_squared_rowsums |
|
|
| |
| σ_constrained .= max.(σ_constrained, zero(eltype(σ_constrained))) |
|
|
| return σ_constrained |
| end |
|
|
| """ |
| dense_std(gmrf::GMRF) |
| dense_std(gmrf::ConstrainedGMRF) |
| |
| Compute standard deviation of a GMRF. See [`dense_var`](@ref) for details. |
| """ |
| dense_std(gmrf::GMRF) = sqrt.(dense_var(gmrf)) |
| dense_std(gmrf::ConstrainedGMRF) = sqrt.(dense_var(gmrf)) |
|
|
| """ |
| dense_cov(gmrf::GMRF) |
| |
| Compute full covariance matrix of a GMRF via Cholesky inversion. |
| |
| Warning: This is O(n³) in time and O(n²) in memory. |
| Only use for small-to-moderate sized problems. |
| """ |
| function dense_cov(gmrf::GMRF) |
| Q = precision_matrix(gmrf) |
| F = cholesky(Symmetric(Matrix(Q))) |
| return Matrix(inv(F)) |
| end |
|
|