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

F# builders for simpler stochastic block syntax (DSL) #146

Open
nightroman opened this issue Apr 4, 2019 · 0 comments
Open

F# builders for simpler stochastic block syntax (DSL) #146

nightroman opened this issue Apr 4, 2019 · 0 comments

Comments

@nightroman
Copy link

nightroman commented Apr 4, 2019

F# builders for simpler stochastic block syntax (DSL)

I would like to share some helpers used in my F# scripts, either as a
suggestion for Infer.NET FSharpWrapper.fs or just a tip for F# folks.

The below F# module defines block builders for stochastic
If, IfNot, Case, Switch, ForEach, Repeat.

The module

[<AutoOpen>]
module InferNetBlocks
open Microsoft.ML.Probabilistic.Models

/// The base builder literally wrapping a code block.
/// Derived builders have custom overrides, e.g. Run.
type BlockBuilder () =
    member __.Delay (f) =
        f
    member __.Run (f) =
        f ()
    member __.Zero () =
        ()
    member __.Return (x) =
        x
    member __.Combine (a, b) =
        b a
    member __.For (sequence, body) =
        for item in sequence do
            body item
    member __.While (guard, body) =
        while guard () do
            body ()
    member __.TryWith (body, handler) =
        try body ()
        with exn -> handler exn
    member __.TryFinally (body, compensation) =
        try body ()
        finally compensation ()
    member __.Using (disposable:#System.IDisposable, body) =
        try body disposable
        finally if not (isNull disposable) then disposable.Dispose ()

/// Creates a stochastic if statement when the variable is true.
/// Example: If variable { ... }
type If (variable) =
    inherit BlockBuilder ()
    member __.Run (f) =
        use __ = Variable.If variable
        f ()

/// Creates a stochastic if statement when the variable is false.
/// Example: IfNot variable { ... }
type IfNot (variable) =
    inherit BlockBuilder ()
    member __.Run (f) =
        use __ = Variable.IfNot variable
        f ()

/// Creates a stochastic case statement when the integer variable has the specified value.
/// Example: Case (variable, value) { ... }
type Case (variable, value) =
    inherit BlockBuilder ()
    member __.Run (f) =
        use __ = Variable.Case (variable, value)
        f ()

/// Creates a stochastic switch statement using the specified condition variable.
/// Example: Switch variable { ... }
type Switch (variable) =
    inherit BlockBuilder ()
    member __.Run (f) =
        use __ = Variable.Switch variable
        f ()

/// Creates a 'for each' block.
/// Example: ForEach range { ... }
type ForEach (range) =
    inherit BlockBuilder ()
    member __.Run (f) =
        use __ = Variable.ForEach range
        f ()

/// Creates a 'repeat' block.
/// Example: Repeat count { ... }
type Repeat (count) =
    inherit BlockBuilder ()
    member __.Run (f) =
        use __ = Variable.Repeat count
        f ()

Examples with stochastic blocks

From my version of causality example (ForEach, If, IfNot):

// Loop over the data points
ForEach N {
    If doB.[N] {
        B.[N] <- Variable.Bernoulli probBIntervention
    }
}

// First model: A causes B
If AcausesB {
    ForEach N {
        A.[N] <- Variable.Bernoulli 0.5
        IfNot doB.[N] {
            B.[N] <- Variable.NotEqual (A.[N], Variable.Bernoulli q)
        }
    }
}

// Second model: B causes A
IfNot AcausesB {
    ForEach N {
        IfNot doB.[N] {
            B.[N] <- Variable.Bernoulli 0.5
        }
        A.[N] <- Variable.NotEqual (B.[N], Variable.Bernoulli q)
    }
}

From my version of Gaussian mixture example (ForEach, Switch):

ForEach n {
    z.[n] <- Variable.Discrete weights
    Switch z.[n] {
        data.[n] <- Variable.VectorGaussianFromMeanAndPrecision (means.[z.[n]], precs.[z.[n]])
    }
}

From my version of "A Murder Mystery" (Case):

Case (murderer, Major) {
    weapon.SetTo (Variable.Discrete (0.1, 0.9))
    hair.SetTo (Variable.Bernoulli 0.5)
}
Case (murderer, Miss) {
    weapon.SetTo (Variable.Discrete (0.8, 0.2))
    hair.SetTo (Variable.Bernoulli 0.05)
}
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