Skip to main content

Infer.NET user guide : FSharp Wrapper

Imperative Statement Blocks in F#

The module Variable contains various functions to replace the imperative statement blocks in Infer.NET, these include ForeachBlock, SwitchBlock and IfBlock methods.

ForEach blocks

The Variable.ForeachBlock method which returns a ForEachBlock used for looping over a Range of values in a similar manner to a foreach loop in C#. This is
a function with the following type signature: Variable.ForEachBlock: RRange->(Range->unit)->unit

//using the Foreach Block  
let pixel = new Range(10)  
let bools = Variable.Array<bool>(pixel);  

Variable.ForeachBlock pixel ( fun pixel ->  
                bools.[pixel] <- Variable.Bernoulli(0.7) ||| Variable.Bernoulli(0.4)())

It should be noted that the Variable.ArrayInit method or the Variable.AssignVariableArray method can also be used to assign the values of a VariableArray as shown in the section Variable Arrays

Switch blocks

The Variable.SwitchBlock method which returns a SwitchBlock used for branching on the values of a variable. This is a function with the following type signature: Variable.SwitchBlock: Variable<int>->(Variable<int>->unit)->unit

//using the Switch Block  

let mixtureSize = 2  
let k2 = new Range(mixtureSize)  
let c = Variable.Discrete(k2, [|0.5;0.5|])  
let means2 = Variable.Observed( [|1.0;2.0|], k2)
let x = Variable.New<double>();  
Variable.SwitchBlock c (fun _ -> 
    let _ = x.SetTo(Variable.GaussianFromMeanAndVariance(means2.[c], 1.0))  
    ()  
)

There is also another Switch construct which returns a Variable<'a> and can be used to initialise or set the values of VariableArrays. The function Variable.SwitchExpr has the following type signature: VVariable<int> -> (Variable<int>->Variable<'a>)->Variable<int>

//using the SwitchExpr Block  

let k = new Range(2) 
let means = Variable.ArrayInit k (fun k ->  
                Variable.VectorGaussianFromMeanAndPrecision(  
                    Vector.Zero(2), PositiveDefiniteMatrix.Identity(2)))  
let precs = Variable.ArrayInit k (fun k ->  
                Variable.WishartFromShapeAndScale(1.0,  
                    PositiveDefiniteMatrix.Identity(2)))  
let weights = Variable.Dirichlet(k,[|1.0; 1.0|])
let n = new Range(100)

let z = Variable.ArrayInit n (fun i -> Variable.Discrete(weights))  
let data = Variable.ArrayInit n (fun i ->  
               Variable.SwitchExpr (z.[i]) (fun zi ->  
                   Variable.VectorGaussianFromMeanAndPrecision(means.[zi], precs.[zi])))

If Blocks

The Variable.IfBlock method returns an IfBlock for creating if then else statements which are dependant on the value of a Variable<bool>. This is a function with type signature: Variable.IfBlock: Variable<bool>->(Variable<bool>->unit)->Variable<bool>->unit)->unit where, the first argument is a boolean variable, the second argument is a function to be applied if the Boolean Variable has value true and the third argument is a function to be applied if the Boolean Variable has value false. Here the If block is used in the Clinical trial tutorial shown below

// Data from a clinical trial  
let controlGroup = Variable.Observed<bool>([|false; false; true; false; false|])  
let treatedGroup = Variable.Observed<bool>([|true; false; true; true; true |])  
let i = controlGroup.Range  
let j = treatedGroup.Range  
// Prior on being an effective treatment  
let isEffective = Variable.Bernoulli(0.5).Named("isEffective");  
let probIfTreated = ref (Variable.New<float>())  
let probIfControl = ref (Variable.New<float>())

// If Block function  
let f1 (vb1: Variable<bool>) =  
    probIfControl := Variable.Beta(1.0, 1.0).Named("probIfControl")  
    let controlGroup = Variable.AssignVariableArray controlGroup i (fun i ->
        Variable.Bernoulli(!probIfControl)) 
    let treatedGroup = Variable.AssignVariableArray treatedGroup j (fun j ->
        Variable.Bernoulli(!probIfTreated))  
        ()  

// IfNot Block function  
let f2 (vb2: Variable<bool>) =  
    let probAll = Variable.Beta(1.0, 1.0).Named("probAll")  
    let controlGroup = Variable.AssignVariableArray controlGroup i (fun i ->Variable.Bernoulli(probAll))  
    let treatedGroup = Variable.AssignVariableArray treatedGroup j (fun j ->Variable.Bernoulli(probAll))  
    ()  

// Call IfBlock  
let _ = Variable.IfBlock isEffective f1 f2