Inference algorithm for Bayesian networks, loosely based on the Variable Elimination algorithm.
Namespace:
BayesServer.Inference.VariableEliminationAssembly: BayesServer.Inference (in BayesServer.Inference.dll)
Version: 2.2.0.0 (2.2.0.0)
Syntax
| C# |
|---|
public sealed class VariableEliminationInference : IInference, IDisposable |
| Visual Basic (Declaration) |
|---|
Public NotInheritable Class VariableEliminationInference _ Implements IInference, IDisposable |
| Visual C++ |
|---|
public ref class VariableEliminationInference sealed : IInference, IDisposable |
Examples
using System; using BayesServer; using System.IO; using BayesServer.Inference; using BayesServer.Inference.VariableElimination; namespace BayesServer.HelpSamples { public static class NetworkExample { public static void Main() { // create a simple Bayesian network Network network = new Network("Demo"); string[] defaultStates = new string[]{"True", "False"}; // add the nodes (variables) Node a = new Node("A", defaultStates); Node b = new Node("B", defaultStates); Node c = new Node("C", defaultStates); Node d = new Node("D", defaultStates); network.Nodes.Add(a); network.Nodes.Add(b); network.Nodes.Add(c); network.Nodes.Add(d); // add some directed links network.Links.Add(new Link(a, b)); network.Links.Add(new Link(a, c)); network.Links.Add(new Link(b, d)); network.Links.Add(new Link(c, d)); // at this point we have fully specified the structural (graphical) specification of the Bayesian Network. // next we must define the necessary probability distributions. // Each node in a Bayesian Network requires a probability distribution conditioned on it's parents. // NewDistribution() can be called on a Node to create the appropriate probability distribution for a node // or it can be created manually. // The interface IDistribution has been designed to represent both discrete and continuous variables, // As we are currently dealing with discrete distributions, we will use the // Table class. // To access the discrete part of a distribution, we use IDistribution.Table. // The Table class is used to define distributions over a number of discrete variables. Table tableA = a.NewDistribution().Table; // access the table property of the Distribution // IMPORTANT // Note that calling Node.NewDistribution() does NOT assign the distribution to the node. // A distribution cannot be assigned to a node until it is correctly specified. // If a distribution becomes invalid (e.g. a parent node is added), it is automatically set to null. // as node A has no parents there is no ambiguity about the order of variables in the distribution tableA[0] = 0.1; tableA[1] = 0.9; // now tableA is correctly specified we can assign it to Node A; a.Distribution = tableA; // node B has node A as a parent // here we use a TableIterator to access the values in the table ( sequentially ), with a particular ordering of the nodes, // the right most node always toggles fastest // e.g. // A, B // True, True // True, False // False, True // False, False Table tableB = b.NewDistribution().Table; TableIterator iteratorB = new TableIterator(tableB, new Node[] { a, b }); double[] values = new double[] { 0.2, 0.8, 0.15, 0.85 }; // see later use of TableIterator for an example of using CopyTo(). for (int i = 0; i < tableB.Count; i++, iteratorB++) { iteratorB.Value = values[i]; } b.Distribution = tableB; Table tableC = c.NewDistribution().Table; // we could also update the values using a TableAccessor ( which allows random access ). TableAccessor accessor = new TableAccessor(tableC, new Node[] { a, c }); accessor[0] = 0.3; accessor[1] = 0.7; accessor[2] = 0.4; accessor[3] = 0.6; c.Distribution = tableC; Table tableD = d.NewDistribution().Table; TableIterator iteratorD = new TableIterator(tableD, new Node[] { b, c, d }); iteratorD.CopyFrom(new double[] { 0.4, 0.6, 0.55, 0.45, 0.32, 0.68, 0.01, 0.99 }); d.Distribution = tableD; // The network is now fully specified // If required the network can be saved... if (false) // change this to true to save the network { network.Save("fileName.bayes"); // replace 'fileName.bayes' with your own path } // Now we will calculate P(A|D=True), i.e. the probability of A given the evidence that D is true // use the factory design pattern to create the necessary inference related objects IInferenceFactory factory = new VariableEliminationInferenceFactory(); IInference inference = factory.CreateInferenceEngine(network); IQueryOptions queryOptions = factory.CreateQueryOptions(); IQueryOutput queryOutput = factory.CreateQueryOutput(); // we could have created these objects explicitly instead, but as the number of algorithms grows // this makes it easier to switch between them inference.Evidence.SetState(d, 0); // set P(A|D=True) Table queryA = new Table(a); inference.QueryDistributions.Add(queryA); if (inference.Query(queryOptions, queryOutput)) { Console.WriteLine("P(A|D=True) = {" + queryA[0] + "," + queryA[1] + "}."); // Expected output ... // P(A|D=True) = {0.0980748663101604,0.90192513368984} } else { Console.WriteLine("Inconsistent evidence was detected."); } // to perform another query we reuse all the objects // now lets calculate P(A|D=True, C=True) inference.Evidence.SetState(c, 0); // we will also return the log-likelihood of the case queryOptions.LogLikelihood = true; // only request the log-likelihood if you really need it, as extra computation is involved if (inference.Query(queryOptions, queryOutput)) { Console.WriteLine(string.Format("P(A|D=True, C=True) = {{{0},{1}}}, log-likelihood = {2}.", queryA[0], queryA[1], queryOutput.LogLikelihood.Value)); // Expected output ... // P(A|D=True, C=True) = {0.0777777777777778,0.922222222222222}, log-likelihood = -2.04330249506396. } else { Console.WriteLine("Inconsistent evidence was detected."); } } } }
Inheritance Hierarchy
System..::.Object
BayesServer.Inference.VariableElimination..::.VariableEliminationInference
BayesServer.Inference.VariableElimination..::.VariableEliminationInference
