zenna / Omega.jl

Causal, Higher-Order, Probabilistic Programming
MIT License
164 stars 17 forks source link

Interventions can't refer to themselves -- stackoverflow #144

Closed zenna closed 3 years ago

zenna commented 3 years ago

I think, but am not certain this should be well defined

julia> a = 1 ~ Normal(0, 1)
[1]@Normal{Float64}(μ=0.0, σ=1.0)

julia> b = 2 ~ Normal(0, 1)
[2]@Normal{Float64}(μ=0.0, σ=1.0)

julia> c = a +ₚ b
+ₚ([1]@Normal{Float64}(μ=0.0, σ=1.0), [2]@Normal{Float64}(μ=0.0, σ=1.0))

julia> randsample(c)
-0.036156683650858154

julia> c_ = c |ᵈ (a => (a +ₚ 10.0))
OmegaCore.Interventions.Intervened{PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Member{Normal{Float64}, Vector{Int64}}}, typeof(+)}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}(+ₚ([1]@Normal{Float64}(μ=0.0, σ=1.0), [2]@Normal{Float64}(μ=0.0, σ=1.0)), Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}([1]@Normal{Float64}(μ=0.0, σ=1.0), +ₚ([1]@Normal{Float64}(μ=0.0, σ=1.0), 10.0)))

julia> randsample(c_)
ERROR: StackOverflowError:
Stacktrace:
     [1] fieldnames
       @ ./reflection.jl:173 [inlined]
     [2] ==(s1::Normal{Float64}, s2::Normal{Float64}; kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
       @ Distributions ~/.julia/packages/Distributions/7Ifyw/src/common.jl:78
     [3] ==
       @ ~/.julia/packages/Distributions/7Ifyw/src/common.jl:77 [inlined]
     [4] ==
       @ ~/repos/OmegaCore.jl/src/var/member.jl:16 [inlined]
     [5] passintervene(traits::Trait{Union{OmegaCore.Tagging.Err, OmegaCore.Tagging.Intervene, OmegaCore.Tagging.Rng}}, i::Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}, x::Member{Normal{Float64}, Vector{Int64}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Interventions ~/repos/OmegaCore.jl/src/interventions/intervenepass.jl:10
     [6] (::Member{Normal{Float64}, Vector{Int64}})(traits::Trait{Union{OmegaCore.Tagging.Err, OmegaCore.Tagging.Intervene, OmegaCore.Tagging.Rng}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Interventions ~/repos/OmegaCore.jl/src/interventions/intervenepass.jl:69
     [7] (::Member{Normal{Float64}, Vector{Int64}})(ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Var ~/repos/OmegaCore.jl/src/var/dispatch.jl:17
     [8] liftapply(#unused#::OmegaCore.Var.Lift, f::Member{Normal{Float64}, Vector{Int64}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Var ~/repos/OmegaCore.jl/src/var/pointwise.jl:76
     [9] liftapply(f::Member{Normal{Float64}, Vector{Int64}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Var ~/repos/OmegaCore.jl/src/var/pointwise.jl:73
    [10] recurse
       @ ~/repos/OmegaCore.jl/src/var/pointwise.jl:87 [inlined]
    [11] ctxapply
       @ ~/repos/OmegaCore.jl/src/var/dispatch.jl:23 [inlined]
    [12] passintervene
       @ ~/repos/OmegaCore.jl/src/interventions/intervenepass.jl:66 [inlined]
    [13] (::PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)})(traits::Trait{Union{OmegaCore.Tagging.Err, OmegaCore.Tagging.Intervene, OmegaCore.Tagging.Rng}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Interventions ~/repos/OmegaCore.jl/src/interventions/intervenepass.jl:69
    [14] (::PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)})(ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Var ~/repos/OmegaCore.jl/src/var/dispatch.jl:17
    [15] passintervene(traits::Trait{Union{OmegaCore.Tagging.Err, OmegaCore.Tagging.Intervene, OmegaCore.Tagging.Rng}}, i::Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}, x::Member{Normal{Float64}, Vector{Int64}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Interventions ~/repos/OmegaCore.jl/src/interventions/intervenepass.jl:11
--- the last 10 lines are repeated 9995 more times ---
 [99966] (::Member{Normal{Float64}, Vector{Int64}})(traits::Trait{Union{OmegaCore.Tagging.Err, OmegaCore.Tagging.Intervene, OmegaCore.Tagging.Rng}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Interventions ~/repos/OmegaCore.jl/src/interventions/intervenepass.jl:69
 [99967] (::Member{Normal{Float64}, Vector{Int64}})(ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Var ~/repos/OmegaCore.jl/src/var/dispatch.jl:17
 [99968] liftapply(#unused#::OmegaCore.Var.Lift, f::Member{Normal{Float64}, Vector{Int64}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Var ~/repos/OmegaCore.jl/src/var/pointwise.jl:76
 [99969] liftapply(f::Member{Normal{Float64}, Vector{Int64}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Var ~/repos/OmegaCore.jl/src/var/pointwise.jl:73
 [99970] recurse
       @ ~/repos/OmegaCore.jl/src/var/pointwise.jl:87 [inlined]
 [99971] ctxapply
       @ ~/repos/OmegaCore.jl/src/var/dispatch.jl:23 [inlined]
 [99972] passintervene
       @ ~/repos/OmegaCore.jl/src/interventions/intervenepass.jl:66 [inlined]
 [99973] (::PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)})(traits::Trait{Union{OmegaCore.Tagging.Err, OmegaCore.Tagging.Intervene, OmegaCore.Tagging.Rng}}, ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Interventions ~/repos/OmegaCore.jl/src/interventions/intervenepass.jl:69
 [99974] (::PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)})(ω::LazyΩ{NamedTuple{(:rng, :err, :intervene), Tuple{Random._GLOBAL_RNG, OmegaCore.Util.Box{Bool}, Intervention{Member{Normal{Float64}, Vector{Int64}}, PwVar{Tuple{Member{Normal{Float64}, Vector{Int64}}, Float64}, typeof(+)}}}}, Dict{Any, Any}})
       @ OmegaCore.Var ~/repos/OmegaCore.jl/src/var/dispatch.jl:17
zenna commented 3 years ago

The problem, presumably, is that when we evaluate (a => (a +ₚ 10.0)), the a in a +ₚ 10.0 will be evaluated with the intervention again, leading to infinite regress!

We don't want to say evaluate a with no interventions, because there may be some other important interventions at play We might want to say evaluate but remove this particular intervention?

Alternatively:

Perhaps c |ᵈ (a => (a +ₚ 10.0)) should first evaluate (a +ₚ 10.0) and then x