Inference (discrete & continuous) with a Bayesian network in C#

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


using BayesServer.Inference.RelevanceTree;
using System;
using System.Collections.Generic;
using System.Text;

namespace BayesServer.HelpSamples
{
    public static class InferenceHybrid
    {
        public static void Main()
        {
            // Uncomment the following line and change the license key, if you are using a licensed version
            // License.Validate("xxx");

            var network = new Network();

            network.Load(@"C:\ProgramData\Bayes Server 8.20\Sample Networks\Waste.bayes");

            Console.WriteLine($"Network has {network.Variables.Count} variables.");

            // Reference some variables
            var wasteType = network.Variables["Waste type", true];
            var co2Concentration = network.Variables["CO2 concentration", true];
            var filterEfficiency = network.Variables["Filter efficiency", true];
            var metalsInWaste = network.Variables["Metals in waste", true];
            var metalsEmission = network.Variables["Metals emission", true];
            var lightPenetrability = network.Variables["Light penetrability", true];

            // Create an inference engine

            var factory = new RelevanceTreeInferenceFactory();
            var inference = factory.CreateInferenceEngine(network);
            var queryOptions = factory.CreateQueryOptions();
            queryOptions.LogLikelihood = true;  // Only set this if you need the log-likelihood
            var queryOutput = factory.CreateQueryOutput();

            // Set some evidence
            var evidence = inference.Evidence;
            var industrial = wasteType.States["Industrial", true];
            evidence.SetState(industrial);  // set discrete evidence

            // evidence.SetStates(wasteType, new double[] { 0.2, 0.8 });   // example of setting soft evidence

            evidence.Set(co2Concentration, -1.0);   // set continuous evidence

            var queryDistributions = inference.QueryDistributions;

            // How to add a discrete query
            var filterState = network.Variables["Filter state", true];
            var queryFilterState = new Table(filterState);
            queryDistributions.Add(queryFilterState);

            // How to add a continuous query
            var queryFilterEfficiency = new CLGaussian(filterEfficiency);
            queryDistributions.Add(queryFilterEfficiency);

            // How to add a joint query

            var queryJoint = new CLGaussian(new Variable[] { lightPenetrability, metalsEmission });
            queryDistributions.Add(queryJoint);

            // Calculate the queries/predictions
            inference.Query(queryOptions, queryOutput);

            // Output the results
            Console.WriteLine($"Log-likelihood: {queryOutput.LogLikelihood}");

            var filterEfficiencyMean = queryFilterEfficiency.GetMean(filterEfficiency);
            var filterEfficiencyVariance = queryFilterEfficiency.GetVariance(filterEfficiency);

            Console.WriteLine($"{filterEfficiencyMean}, {Math.Sqrt(filterEfficiencyVariance)}");

            foreach (var state in filterState.States)
            {
                Console.WriteLine($"Filter state: {state.Name} {queryFilterState[state]}");
            }

            Console.WriteLine($"Joint covariance = {queryJoint.GetCovariance(lightPenetrability, metalsEmission)}");

            // Expected output...
            // Network has 9 variables.
            // Log-likelihood: -3.40279833515147
            // -3.725, 0.762823046322016
            // Filter state: Intact 0.95
            // Filter state: Defect 0.05
            // Joint covariance = -0.36786975428679

        }
    }
}