Skip to main content

Function Nodes example in C#

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FunctionNodesExample.cs" company="Bayes Server">
// Copyright (C) Bayes Server. All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace BayesServer.HelpSamples
{
using System;
using BayesServer.Inference;
using BayesServer.Inference.RelevanceTree;

public static class FunctionNodesExample
{
public static void Main()
{
// In this example we programatically create and query the sample
// network 'Functions' included with the Bayes Server User Interface.

var network = new Network("Functions");

// add the variables/nodes

var d1 = new State("D1");
var d2 = new State("D2");
var d = new Variable("D", d1, d2);
d.ExpressionAlias = "d";
network.Nodes.Add(new Node(d));

var c = new Variable("C", VariableValueType.Continuous);
c.ExpressionAlias= "c";
network.Nodes.Add(new Node(c));

var f1 = new Variable("F1", VariableValueType.Function);
f1.ExpressionAlias= "f1";
network.Nodes.Add(new Node(f1));

var f2 = new Variable("F2", VariableValueType.Function);
network.Nodes.Add(new Node(f2));

var f3 = new Variable("F3", VariableValueType.Function);
network.Nodes.Add(new Node(f3));

// add some directed links

network.Links.Add(new Link(d.Node, c.Node));
network.Links.Add(new Link(f1.Node, f2.Node)); // the expression in f2 uses the result from f1, so we need a link here

var tableD = d.Node.NewDistribution().Table;

tableD[d1] = 0.6961106280502056;
tableD[d2] = 0.3038893719497943;

d.Node.Distribution = tableD;

var gaussianC = (CLGaussian)c.Node.NewDistribution();
gaussianC.SetMean(c, 100.0, d1);
gaussianC.SetVariance(c, 20.0, d1);
gaussianC.SetMean(c, -50.0, d2);
gaussianC.SetVariance(c, 45.0, d2);

c.Node.Distribution = gaussianC;

f1.Function = new FunctionVariableExpression(
@"
var d1 = d.States.Get(""D1"", true);
var probD1 = ctx.TableValue(d1);

var meanC1 = ctx.Mean(c);

return probD1 * meanC1;
",
ExpressionReturnType.Double);

f2.Function = new FunctionVariableExpression(
@"
var f1Val = ctx.FunctionValue(f1);

return f1Val * 2.0;
",
ExpressionReturnType.Double);

f3.Function = new FunctionVariableExpression(
@"
return ""PI = "" + Math.PI;
",
ExpressionReturnType.String);


// The network is now fully specified

// Now we will query the nodes

var factory = new RelevanceTreeInferenceFactory();
var inference = factory.CreateInferenceEngine(network);
var queryOptions = factory.CreateQueryOptions();
var queryOutput = factory.CreateQueryOutput();

// set any evidence, e.g.
// inference.Evidence.SetState(d1); // set D = D1

var queryD = new Table(d);
inference.QueryDistributions.Add(queryD);

var queryC = new CLGaussian(c);
inference.QueryDistributions.Add(queryC);

var queryF1 = new QueryFunctionOutput(f1);
inference.QueryFunctions.Add(queryF1);

var queryF2 = new QueryFunctionOutput(f2);
inference.QueryFunctions.Add(queryF2);

var queryF3 = new QueryFunctionOutput(f3);
inference.QueryFunctions.Add(queryF3);

inference.Query(queryOptions, queryOutput); // note that this can raise an exception (see help for details)

Console.WriteLine("P(D|-) = { " + queryD[d1] + "," + queryD[d2] + " }.");
Console.WriteLine("P(C|-) = { " + queryC.GetMean(c) + "," + queryC.GetVariance(c) + " }.");

Console.WriteLine("F1 = { " + queryF1.Value + " }.");
Console.WriteLine("F2 = { " + queryF2.Value + " }.");
Console.WriteLine("F3 = { " + queryF3.Value + " }.");

// expected output...

// P(D | -) = { 0.6961106280502056,0.3038893719497943 }.
// P(C | -) = { 54.41659420753085,4787.261219528207 }.
// F1 = { 37.87996957015748 }.
// F2 = { 75.75993914031496 }.
// F3 = { PI = 3.141592653589793 }.

}
}
}