-
Notifications
You must be signed in to change notification settings - Fork 17
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
Overview of proposed ciid changes #122
Comments
A quick primer on Cassette. Mostly for @jburroni Cassette allows you to implement some (actually many) kinds of non-standard interpretations. The general approach is to first create a context, and then add new definitions to that context. using Cassette
Cassette.@context MyCtx # Creates a new context type called MyCtx In this new context I will replace # adding methods to Cassette.overdub is how to define new semantics
function Cassette.overdub(::MyCtx, ::typeof(sin), x)
println("I will now do cos instead of sin")
cos(x)
end Try it out myprogram() = sin(3)
# execute myprogram in MyCtx
Cassette.overdub(MyCtx(), myprogram) One thing it quite easily allows you to do something equivalent to adding extra state to the environment, in the operational semantics sense. This is done by adding data ('metadata') to your context. mutable struct Counter
count::Int
end
# This will intercept __every__ function call (except one's in Base that Cassette has defaults to not recurse into)
function Cassette.overdub(ctx::MyCtx, f, args...)
ctx.metadata.count += 1
# Now Continue running
Cassette.recurse(ctx, f, args...)
end
# Let's try it out
ctx = MyCtx(metadata = Counter(1))
Cassette.overdub(ctx, myprogram)
println("Number of function calls is $(ctx.metadata)") |
Better in discussions |
This issue proposes a big change to the structure of Omega and the semantics of ciid. #120
Overall setup
unif1, unif2, ...
that are i.i.d.y(ω) = f(unif(ω))
i ~ x <| (x, y, z, ....)
. This constructs a random variable that is thei
th element in a sequence of random variables that have the same functional form asx
, sharex
,y
andz
as parents. Consequently:x
and conditionally independent givenx
,y
,z
, ....1 ~ x, 2 ~ x, ...
are all i.i.d.Independence
Operationally, it works as follows. First, consider the simplest case, the i.i.d. case, and the following example:
unif1, unif2, ...
unif_gen
be a mapping from tuples of integers to random variables in this sequence.context
, which is a tuple of integersunif(ω)
. In a contexts
,unif(ω)
is interpreted asunif_gen(s)(ω)
a
has the forma(ω) = context_apply(1, unif, ω)
.context_apply(i, x, ω)
means to evaluatesx(ω)
in a modified environment wherei
is appended onto the contexta(ω)
will ultimately evaluateunif(ω)
within the context(1,)
.context_apply
is applied within another context, the contexts are merged.Conditional independence
For example, in the following snippet.
m1
andm2
are conditionally independent givenx
, andm3
is completely independent from them both,Operationally, conditional independence is possible with a single modification.
To illustrate, in order for
m1
to beciid
givenx
, the the evaluation ofm1(ω)
we should evaluatex(ω)
in the context thatx
uses ordinarily, and not whatever contextm1
has introduced. Hence, we simply to evaluatex(ω)
with out any context, a new context will be reintroduced byx
.Prototype
Port to Omega?
There may be some small bugs (please check) in this approach but I'm fairly confident it is both mostly correct, more general, and simpler than what we are currently doing. So, I should probably port the change to real Omega.
A few concerns?
RandVar
sRandVar
s have explicit ids. These ids are used to check random variable equivalence for (i) memoization, and causal interventions. The above code uses Julia's function equivalence checking. It's not clear exactly what that is doing, but I imagine it's doing some kind of memory check. It's not clear that integer ID's are much better because: we can define the same random variable (functionally) and give them different IDs.RandVar
s have type information that can be useful, e.g. for analytic computation of expectations.Overall, I'm inclined to say we support any object that "purely" implements (::Type)(ω::Ω). We can still use typed and/or id'd objects for the above reasons, but not if we don't need that.
Currently a lot of omega code is of the form
This code would break, or more precisely, do something different to what it currently does. The reason is that currently this code would share the value of
x
, butciid
(aka~
) without any shared parameters would create an i.i.d. variable.Fortunately though, because we no longer have a distinction between random variables and functions, this does not mean we always need to explicitly stat what we want the parents to be, we in fact do not need the
ciid
at all in this exampleThe text was updated successfully, but these errors were encountered: