TuringLang / TuringLang/DynamicPPL.jl
Reconstructing Cholesky variables from their indices gives wrong result in VNT
Nobody has claimed this yet.
- Dominant language
- Julia
- Stars
- 286
- Forks
- 41
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 34
Description
julia> using DynamicPPL, Distributions
julia> c = rand(LKJCholesky(3, 0.5))
Cholesky{Float64, Matrix{Float64}}
L factor:
3×3 LinearAlgebra.LowerTriangular{Float64, Matrix{Float64}}:
1.0 ⋅ ⋅
-0.71428 0.69986 ⋅
0.255189 0.911365 0.322942
julia> vnt = @vnt begin
@template c
c.L[1, 1] := c.L[1, 1]
c.L[2, 1] := c.L[2, 1]
c.L[2, 2] := c.L[2, 2]
c.L[3, 1] := c.L[3, 1]
c.L[3, 2] := c.L[3, 2]
c.L[3, 3] := c.L[3, 3]
end
VarNamedTuple
└─ c => VarNamedTuple
└─ L => PartialArray size=(3, 3) data::LinearAlgebra.LowerTriangular{Float64, Matrix{Float64}}
├─ (1, 1) => 1.0
├─ (2, 1) => -0.7142799536546864
├─ (3, 1) => 0.25518913641826435
├─ (2, 2) => 0.6998600915947837
├─ (3, 2) => 0.9113653464249535
└─ (3, 3) => 0.3229422703670502
Obviously, this doesn't reconstruct the Cholesky sample c despite us passing the template to it.
When does this pathological situation occur? Easy, it's when trying to load samples back into a VNT from MCMCChains.Chains, since Cholesky samples get broken up in MCMCChains.
(with FlexiChains it doesn't break up the sample so you would get something like this and it's a-ok
julia> vnt2 = @vnt begin
c := c
end
VarNamedTuple
└─ c => Cholesky{Float64, Matrix{Float64}}([1.0 5.0e-324 0.0; -0.7142799536546864 0.6998600915947837 0.0; 0.25518913641826435 0.9113653464249535 0.3229422703670502], 'L', 0)
)
Now the above issue doesn't yet cause problems because we have this patch for VNT that calls hasvalue(..., dist) and getvalue(..., dist)
However, it is really just wrong to even create a VNT with the wrong structure. That VNT should never be allowed to exist!!! We do have enough info to re-create the correct form of c because we pass the template in, it's just that we're not using it.
There are two Correct Things to do, either of which will allow us to stop creating these wrong VNTs, and thereby remove these hasvalue / getvalue methods:
- Use the template to make a PartialCholesky thing, and then fill it in one element by one element.
- Stop using MCMCChains, and once we stop using MCMCChains, just declare this as unsupported.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/varnamedtuple.jl at lines 167-208 and trace how @vnt uses the supplied template when reconstructing Cholesky values from MCMCChains.Chains. Compare the two proposed directions—building a PartialCholesky incrementally or dropping MCMCChains support—and confirm that the resulting VNT preserves the Cholesky structure without the hasvalue/getvalue workaround.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100