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