Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redundant computation for Affine measures #163

Open
cscherrer opened this issue Oct 2, 2021 · 0 comments
Open

Redundant computation for Affine measures #163

cscherrer opened this issue Oct 2, 2021 · 0 comments
Assignees

Comments

@cscherrer
Copy link
Collaborator

Say we have a measure like

julia> d = MvNormal((σ=[3;4;;],))
Affine{(,),PowerMeasure{typeof(identity), Normal{(), Tuple{}}, 1, Tuple{Base.OneTo{Int64}}},Tuple{Matrix{Int64}}}(AffineTransform{(:σ,),Tuple{Matrix{Int64}}}((σ = [3; 4;;],)), Normal() ^ 1)

Then this works just fine:

julia> x = rand(d)
2-element Vector{Float64}:
 -3.212402995915957
 -4.283203994554609

julia> logdensity(d,x)
-0.5733073893427674

But there's a problem. Along the way, this requires calculating

z = d.σ \ x

and the base measure is left as

julia> basemeasure(d)
0.398942 * Affine{(,),PowerMeasure{typeof(identity), Lebesgue{ℝ}, 1, Tuple{Base.OneTo{Int64}}},Tuple{Matrix{Int64}}}(AffineTransform{(:σ,),Tuple{Matrix{Int64}}}((σ = [3; 4;;],)), Lebesgue(ℝ) ^ 1)

So computing the logdensity with respect to other measures will typically require more repetitions of the z = d.σ \ x code, which is very inefficient.

Adding some @show statements in logpdf makes this clear:

julia> logpdf(d, [0,0])
d = Affine{(,),PowerMeasure{typeof(identity), Normal{(), Tuple{}}, 1, Tuple{Base.OneTo{Int64}}},Tuple{Matrix{Int64}}}(AffineTransform{(:σ,),Tuple{Matrix{Int64}}}((σ = [3; 4;;],)), Normal() ^ 1)
z = [-0.0]

d = 0.398942 * Affine{(,),PowerMeasure{typeof(identity), Lebesgue{ℝ}, 1, Tuple{Base.OneTo{Int64}}},Tuple{Matrix{Int64}}}(AffineTransform{(:σ,),Tuple{Matrix{Int64}}}((σ = [3; 4;;],)), Lebesgue(ℝ) ^ 1)
z = [-0.0]

d = Affine{(,),PowerMeasure{typeof(identity), Lebesgue{ℝ}, 1, Tuple{Base.OneTo{Int64}}},Tuple{Matrix{Int64}}}(AffineTransform{(:σ,),Tuple{Matrix{Int64}}}((σ = [3; 4;;],)), Lebesgue(ℝ) ^ 1)
z = [-0.0]

d = 0.2 * Lebesgue(ℝ) ^ 1
d = Lebesgue(ℝ) ^ 1
-2.528376445638773

Each z = ... is the result of solving the same linear system, three times.

I got a start on fixing this, by adding a MapsTo combinator:

struct MapsTo{X,Y}
    x::X
    y::Y
end

export , mapsto

mapsto(x,y) = x  y

(x::X, y::Y) where {X,Y} = MapsTo{X,Y}(x,y)

Base.first(t::MapsTo) = t.x
Base.last(t::MapsTo) = t.y

Base.Pair(t::MapsTo) = t.x => t.y

Base.show(io::IO, t::MapsTo) = print(t.x, "", t.y)

It's pretty easy to make this work with logpdf, but for a more generic logdensity I think it will take some restructuring. We might need a LogdensityComputation struct that's just for internal use, and holds things we know so far about the result.

@cscherrer cscherrer self-assigned this Oct 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant