// --------------------------------------------------------------------------------------------------------------------// <copyright file="CausalOptimizationExample.cs" company="Bayes Server">//   Copyright (C) Bayes Server.  All rights reserved.// </copyright>// --------------------------------------------------------------------------------------------------------------------using BayesServer.Inference;using BayesServer.Inference.RelevanceTree;using BayesServer.Optimization;using BayesServer.Optimization.Genetic;using BayesServer.Statistics;using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace BayesServer.HelpSamples{    public static class CausalOptimizationExample    {        public static void Main()        {            var network = LoadNetwork();            // reference some variables and their states            var gender = network.Variables["Gender", true];            var genderMale = gender.States["Male", true];            var drugA = network.Variables["DrugA", true];            var drugB = network.Variables["DrugB", true];            var recovered = network.Variables["Recovered", true];            var recoveredTrue = recovered.States["True", true];            // the objective here is to maximize the recovery rate of patients            var objective = new Objective(recoveredTrue, ObjectiveKind.Maximize);            var optimizer = new GeneticOptimizer();            var optimizerOptions = new GeneticOptimizerOptions();            // simplification is optional, but tests whether            // fewer variables having evidence provides a 'close enough' solution            var simplify = new GeneticSimplification();            var simplifyOptions = new GeneticSimplificationOptions();            {                // Example 1.  Non-causal optimization                var designVariables = new List<DesignVariable>                {                    new DesignVariable(drugA, 0.0, 1.0, true, InterventionType.None),   // 'None' does not permit interventions                    new DesignVariable(drugB, 0.0, 1.0, true, InterventionType.None)    // 'None' does not permit interventions                };                var output = optimizer.Optimize(                    network,                    objective,                    designVariables,                    null,                    optimizerOptions);                simplifyOptions.EvidenceToSimplify = output.Evidence;                var outputSimple = simplify.Optimize(                    network,                    objective,                    designVariables,                    null,                    simplifyOptions);                                Console.WriteLine($"Example 1 (Non-causal), objective = {outputSimple.ObjectiveValue:P2}."); Console.WriteLine($"    Drug A = {EvidenceToString(outputSimple.Evidence, drugA)}");                Console.WriteLine($" Drug B = {EvidenceToString(outputSimple.Evidence, drugB)}"); Console.WriteLine($"    Gender = {EvidenceToString(outputSimple.Evidence, gender)}");            }            {                // Example 2.  Causal optimization                var designVariables = new List<DesignVariable>                {                    new DesignVariable(drugA, 0.0, 1.0, true, InterventionType.Do),                    new DesignVariable(drugB, 0.0, 1.0, true, InterventionType.Do)                };                var options = new GeneticOptimizerOptions();                var output = optimizer.Optimize(                    network,                    objective,                    designVariables,                    null,                    options);                simplifyOptions.EvidenceToSimplify = output.Evidence;                var outputSimple = simplify.Optimize(                    network,                    objective,                    designVariables,                    null,                    simplifyOptions);                Console.WriteLine($"Example 2 (Causal), objective = {outputSimple.ObjectiveValue:P2}."); Console.WriteLine($"    Drug A = {EvidenceToString(outputSimple.Evidence, drugA)}");                Console.WriteLine($" Drug B = {EvidenceToString(outputSimple.Evidence, drugB)}"); Console.WriteLine($"    Gender = {EvidenceToString(outputSimple.Evidence, gender)}");            }            {                // Example 3.  Mixed causal/non-causal optimization                var designVariables = new List<DesignVariable>                {                    new DesignVariable(drugA, 0.0, 1.0, true, InterventionType.Do),                    new DesignVariable(drugB, 0.0, 1.0, true, InterventionType.Do),                    new DesignVariable(gender, 0.0, 1.0, true, InterventionType.None),                };                var options = new GeneticOptimizerOptions();                var output = optimizer.Optimize(                    network,                    objective,                    designVariables,                    null,                    options);                simplifyOptions.EvidenceToSimplify = output.Evidence;                var outputSimple = simplify.Optimize(                    network,                    objective,                    designVariables,                    null,                    simplifyOptions);                Console.WriteLine($"Example 3 (Mixed causal/non-causal), objective = {outputSimple.ObjectiveValue:P2}."); Console.WriteLine($"    Drug A = {EvidenceToString(outputSimple.Evidence, drugA)}");                Console.WriteLine($" Drug B = {EvidenceToString(outputSimple.Evidence, drugB)}"); Console.WriteLine($"    Gender = {EvidenceToString(outputSimple.Evidence, gender)}");            }            // The following example use fixed evidence, which allow            // us to explore solutions within specified sub-populations            {                // Example 4.  Non-causal optimization with fixed evidence                var designVariables = new List<DesignVariable>                {                    new DesignVariable(drugA, 0.0, 1.0, true, InterventionType.None),                    new DesignVariable(drugB, 0.0, 1.0, true, InterventionType.None)                };                var fixedEvidence = new Evidence(network);                fixedEvidence.SetState(genderMale);                var options = new GeneticOptimizerOptions();                var output = optimizer.Optimize(                    network,                    objective,                    designVariables,                    fixedEvidence,                    options);                simplifyOptions.EvidenceToSimplify = output.Evidence;                var outputSimple = simplify.Optimize(                    network,                    objective,                    designVariables,                    fixedEvidence,                    simplifyOptions);                Console.WriteLine($"Example 4 (Non-causal, Fixed evidence), objective = {outputSimple.ObjectiveValue:P2}."); Console.WriteLine($"    Drug A = {EvidenceToString(outputSimple.Evidence, drugA)}");                Console.WriteLine($" Drug B = {EvidenceToString(outputSimple.Evidence, drugB)}"); Console.WriteLine($"    Gender = {EvidenceToString(outputSimple.Evidence, gender)}");            }            {                // Example 5.  Causal optimization with fixed evidence                var designVariables = new List<DesignVariable>                {                    new DesignVariable(drugA, 0.0, 1.0, true, InterventionType.Do),                    new DesignVariable(drugB, 0.0, 1.0, true, InterventionType.Do)                };                var fixedEvidence = new Evidence(network);                fixedEvidence.SetState(genderMale);                var options = new GeneticOptimizerOptions();                var output = optimizer.Optimize(                    network,                    objective,                    designVariables,                    fixedEvidence,                    options);                simplifyOptions.EvidenceToSimplify = output.Evidence;                var outputSimple = simplify.Optimize(                    network,                    objective,                    designVariables,                    fixedEvidence,                    simplifyOptions);                Console.WriteLine($"Example 5 (Causal with fixed evidence), objective = {outputSimple.ObjectiveValue:P2}."); Console.WriteLine($"    Drug A = {EvidenceToString(outputSimple.Evidence, drugA)}");                Console.WriteLine($" Drug B = {EvidenceToString(outputSimple.Evidence, drugB)}"); Console.WriteLine($"    Gender = {EvidenceToString(outputSimple.Evidence, gender)}");            }            // Expected output ...            // Example 1 (Non-causal), objective = 85.83 %.            //     Drug A = False            //     Drug B = False            //     Gender = <missing>            // Example 2 (Causal), objective = 87.65 %.            //     Drug A = Do(True)            //     Drug B = Do(True)            //     Gender = <missing>            // Example 3 (Mixed causal / non-causal), objective = 95.00 %.            //     Drug A = Do(True)            //     Drug B = Do(True)            //     Gender = Male            // Example 4 (Non - causal, Fixed evidence), objective = 95.00 %.            //     Drug A = True            //     Drug B = True            //     Gender = Male            // Example 5 (Causal with fixed evidence), objective = 95.00 %.            //     Drug A = Do(True)            //     Drug B = Do(True)            //     Gender = Male        }        private static string EvidenceToString(IEvidence evidence, Variable variable)        {            var evdTypes = evidence.GetEvidenceTypes(variable);            if (evdTypes.EvidenceType == EvidenceType.None)                return "<missing>";            var text = string.Empty;            if (variable.ValueType == VariableValueType.Discrete)            {                text = variable.States[evidence.GetState(variable).Value].Name;            }            else            {                text = evidence.Get(variable).Value.ToString();            }            if(evdTypes.InterventionType == InterventionType.Do)            {                text = "Do(" + text + ")";            }            return text;        }        private static Network LoadNetwork()        {            var network = new Network();            // you can load a network in a number of different ways            // a) Load from a file...            //network.Load(@"C:\ProgramData\Bayes Server 9.3\Sample Networks\Asia.bayes");            // b) Load from a stream            // c) Load from a string            // d) construct manually, which is what we do here            var genderFemale = new State("Female");            var genderMale = new State("Male");            var gender = new Variable("Gender", genderFemale, genderMale);            network.Nodes.Add(new Node(gender));            gender.Node.Bounds = new Bounds(404.5, 23.0, 183.5, 102.5);            var drugAFalse = new State("False");            var drugATrue = new State("True");            var drugA = new Variable("DrugA", drugAFalse, drugATrue);            network.Nodes.Add(new Node(drugA));            drugA.Node.Bounds = new Bounds(50.5, 136.0, 183.5, 102.5);            var drugBFalse = new State("False");            var drugBTrue = new State("True");            var drugB = new Variable("DrugB", drugBFalse, drugBTrue);            network.Nodes.Add(new Node(drugB));            drugB.Node.Bounds = new Bounds(45.5, 340, 183.5, 102.5);            var recoveredFalse = new State("False");            var recoveredTrue = new State("True");            var recovered = new Variable("Recovered", recoveredFalse, recoveredTrue);            network.Nodes.Add(new Node(recovered));            recovered.Node.Bounds = new Bounds(665, 240, 183.5, 102.5);            network.Links.Add(new Link(gender.Node, drugA.Node));            network.Links.Add(new Link(gender.Node, drugB.Node));            network.Links.Add(new Link(gender.Node, recovered.Node));            network.Links.Add(new Link(drugA.Node, recovered.Node));            network.Links.Add(new Link(drugB.Node, recovered.Node));            // at this stage you could learn the parameters from data            // but to keep this example self contained            // we are specifiying the parameters manually            {                var table = gender.Node.NewDistribution().Table;                table[genderFemale] = 0.49;                table[genderMale] = 0.51;                gender.Node.Distribution = table;            }            {                var table = drugA.Node.NewDistribution().Table;                table[drugAFalse, genderFemale] = 0.233236151603499;                table[drugATrue, genderFemale] = 0.766763848396501;                table[drugAFalse, genderMale] = 0.756302521008403;                table[drugATrue, genderMale] = 0.243697478991597;                drugA.Node.Distribution = table;            }            {                var table = drugB.Node.NewDistribution().Table;                table[drugBFalse, genderFemale] = 0.2;                table[drugBTrue, genderFemale] = 0.8;                table[drugBFalse, genderMale] = 0.85;                table[drugBTrue, genderMale] = 0.15;                drugB.Node.Distribution = table;            }            {                var table = recovered.Node.NewDistribution().Table;                table[genderFemale, drugAFalse, drugBFalse, recoveredFalse] = 0.31;                table[genderFemale, drugAFalse, drugBFalse, recoveredTrue] = 0.69;                table[genderFemale, drugAFalse, drugBTrue, recoveredFalse] = 0.22;                table[genderFemale, drugAFalse, drugBTrue, recoveredTrue] = 0.78;                table[genderFemale, drugATrue, drugBFalse, recoveredFalse] = 0.27;                table[genderFemale, drugATrue, drugBFalse, recoveredTrue] = 0.73;                table[genderFemale, drugATrue, drugBTrue, recoveredFalse] = 0.2;                table[genderFemale, drugATrue, drugBTrue, recoveredTrue] = 0.8;                table[genderMale, drugAFalse, drugBFalse, recoveredFalse] = 0.13;                table[genderMale, drugAFalse, drugBFalse, recoveredTrue] = 0.87;                table[genderMale, drugAFalse, drugBTrue, recoveredFalse] = 0.1;                table[genderMale, drugAFalse, drugBTrue, recoveredTrue] = 0.9;                table[genderMale, drugATrue, drugBFalse, recoveredFalse] = 0.07;                table[genderMale, drugATrue, drugBFalse, recoveredTrue] = 0.93;                table[genderMale, drugATrue, drugBTrue, recoveredFalse] = 0.05;                table[genderMale, drugATrue, drugBTrue, recoveredTrue] = 0.95;                recovered.Node.Distribution = table;            }            return network;        }    }}