Пример #1
0
        private void TopologicalSortRecursive(BayesianNode node, HashSet <BayesianNode> visited, Stack <BayesianNode> result)
        {
            if (visited.Contains(node))
            {
                return;
            }

            // Visit the current node
            visited.Add(node);

            // Visit the children
            foreach (BayesianNode child in node.children)
            {
                TopologicalSortRecursive(child, visited, result);
            }

            result.Push(node);
        }
Пример #2
0
        /// <summary>
        /// Given an xml string in GeNIe 2.0 format, this function parses it and creates a Bayesian Network.
        /// </summary>
        /// <param name="s">an xml string in GeNIe 2.0 format</param>
        /// <returns>the bayesian network parsed from the xml string</returns>
        public override BayesianNetwork Parse(string s)
        {
            Dictionary <string, BayesianNode> nodeMap = new Dictionary <string, BayesianNode>();
            List <BayesianNode> nodes = new List <BayesianNode>();

            try {
                XElement rootElement        = XDocument.Parse(s).Root;
                IEnumerable <XElement> cpts = rootElement.Elements()
                                              .First(node => node.Name.LocalName.Equals("nodes"))
                                              .Elements().Where(node => node.Name.LocalName.Equals("cpt"));

                foreach (XElement cpt in cpts)
                {
                    string   name    = cpt.Attribute("id").Value;
                    string[] domains = cpt.Elements().Where(e => e.Name.LocalName.Equals("state")).Select(e => e.Attribute("id").Value).ToArray();
                    double[] values  = ((XText)cpt.Elements().First(e => e.Name.LocalName.Equals("probabilities")).FirstNode)
                                       .Value.Split(' ').Select(v => double.Parse(v)).ToArray();

                    IEnumerable <XElement> parentsXmlNode = cpt.Elements().Where(e => e.Name.LocalName.Equals("parents"));
                    BayesianNode[]         parents;
                    if (parentsXmlNode.Count() == 0)
                    {
                        parents = new BayesianNode[] { };
                    }
                    else
                    {
                        parents = ((XText)parentsXmlNode.First().FirstNode).Value.Split(' ').Select(n => nodeMap[n]).ToArray();
                    }

                    BayesianNode node = new BayesianNode(name, domains, values, parents);
                    nodes.Add(node);
                    nodeMap.Add(name, node);
                }

                return(new BayesianNetwork(nodes.ToArray()));
            } catch (Exception e)
            {
                throw new FormatException("Encounter error when trying to read in the network from the GeNie file. " +
                                          "If you believe it is not your fault, please report to the author of this package." +
                                          "(Reason: " + e.Message + " " + e.StackTrace + ")"
                                          );
            }
        }
Пример #3
0
        /// <summary>
        /// Given a JSON string, this function parses it and creates a Bayesian Network.
        /// </summary>
        /// <param name="s">JSON string</param>
        /// <returns>a bayesian network parsed from the json string</returns>
        public override BayesianNetwork Parse(string json)
        {
            Dictionary <string, BayesianNode> nodeMap = new Dictionary <string, BayesianNode>();
            List <BayesianNode> nodes = new List <BayesianNode>();

            Dictionary <string, object> jsonObj;

            try
            {
                jsonObj = Json.Deserialize(json) as Dictionary <string, object>;
            }
            catch (Exception e)
            {
                throw new FormatException("The string is not valid JSON. Error detail: " + e.Message + " " + e.StackTrace);
            }

            try
            {
                List <object> jsonNodes = (List <object>)jsonObj["nodes"];
                foreach (Dictionary <string, object> jsonNode in jsonNodes)
                {
                    string         name    = (string)jsonNode["name"];
                    string[]       domains = ((List <object>)jsonNode["domain"]).Select(d => (string)d).ToArray();
                    double[]       values  = ((List <object>)jsonNode["values"]).Select(v => (double)v).ToArray();
                    BayesianNode[] parents = ((List <object>)jsonNode["parents"]).Select(n => nodeMap[(string)n]).ToArray();

                    BayesianNode node = new BayesianNode(name, domains, values, parents);
                    nodes.Add(node);
                    nodeMap.Add(name, node);
                }

                return(new BayesianNetwork(nodes.ToArray()));
            }
            catch (Exception e)
            {
                throw new FormatException("Encounter error when trying to read in the network from the file." +
                                          "Most likely the JSON file is not valid or the nodes are not valid. " +
                                          "If you believe it is not your fault, please report to the author of this package." +
                                          "Actual Error (Reason: " + e.Message + " " + e.StackTrace + ")"
                                          );
            }
        }
Пример #4
0
        private bool MarkVariablesRecursive(BayesianNode node, HashSet <BayesianNode> relevantNodes, HashSet <BayesianNode> irrelevantNodes)
        {
            if (relevantNodes.Contains(node))
            {
                return(true);
            }

            if (irrelevantNodes.Contains(node))
            {
                return(false);
            }

            foreach (BayesianNode child in node.children)
            {
                if (MarkVariablesRecursive(child, relevantNodes, irrelevantNodes))
                {
                    relevantNodes.Add(node);
                }
            }
            return(relevantNodes.Contains(node));
        }
Пример #5
0
        /// <summary>
        /// Given a BayesianNode object and an array of Proposition objects as observations,
        /// this function perform inferences and return the inferred distribution of the node variable.
        /// </summary>
        /// <param name="query">the BayesianNode object being query</param>
        /// <param name="observations">the array of Proposition objects</param>
        /// <returns>a distribution table for the values of the query node</returns>
        public double[] Infer(BayesianNode query, params Proposition[] observations)
        {
            try {
                string[] evidenceNames = observations.Select(o => o.name).ToArray();

                IEnumerable <BayesianNode> nodes = TopologicalSort(network.GetNodes()).Reverse();

                HashSet <BayesianNode> relevantNodes = new HashSet <BayesianNode>();
                relevantNodes.Add(query);
                foreach (Proposition p in observations)
                {
                    relevantNodes.Add(network.FindNode(p.name));
                }
                MarkRelevantVariables(relevantNodes, nodes);
                // Remove variables that are not ancestor of a query variable or evidence variable
                nodes = nodes.Intersect(relevantNodes);

                List <CPT> factors = new List <CPT>();
                foreach (BayesianNode node in nodes)
                {
                    factors.Add(node.MakeFactor(observations));
                    if (node.var.name.Equals(query.var.name) || Array.IndexOf(evidenceNames, node.var.name) >= 0)
                    {
                        continue;
                    }

                    CPT[] factorsToSumOut = factors.Where(f => f.ContainsVar(node.var)).ToArray();
                    factors.RemoveAll(f => Array.IndexOf(factorsToSumOut, f) != -1);

                    CPT factorToSumOut;
                    if (factorsToSumOut.Count() > 1)
                    {
                        factorToSumOut = factorsToSumOut.Skip(1).Aggregate(factorsToSumOut.First(), (acc, f) => acc.PointWiseProduct(f));
                    }
                    else
                    {
                        factorToSumOut = factorsToSumOut.First();
                    }

                    CPT afterSumOut = factorToSumOut.SumOut(node.var);
                    factors.Add(afterSumOut);
                }

                CPT result;
                if (factors.Count() > 1)
                {
                    result = factors.Skip(1).Aggregate <CPT, CPT>(factors.First(), (acc, f) => acc.PointWiseProduct(f));
                }
                else
                {
                    result = factors.First();
                }
                return(result.Distribution());
            } catch (Exception e)
            {
                throw new Exception("Unable to perform inference on the network. " +
                                    "Please make sure the network is valid and the propositions are valid. " +
                                    "Contact the author of this library if you suspect it is a problem in the library." +
                                    "Actual Error (Reason: " + e.Message + " " + e.StackTrace + ")"
                                    );
            }
        }
Пример #6
0
 /// <summary>
 /// Given a BayesianNode object and a list of Proposition objects as observations,
 /// this function perform inferences and return the inferred distribution of the node variable.
 /// </summary>
 /// <param name="query">the BayesianNode object being query</param>
 /// <param name="observations">the list of Proposition objects</param>
 /// <returns>a distribution table for the values of the query node</returns>
 public double[] Infer(BayesianNode query, IEnumerable <Proposition> observations)
 {
     return(Infer(query, observations.ToArray()));
 }
Пример #7
0
 /// <summary>
 /// Get the array of all the nodes in the network. The array is a copy of the internal
 /// structure but the BayesianNode objects are not clones. It means a modification on the node
 /// results in a modification of the same node in the network.
 /// </summary>
 /// <returns>an array of all the nodes in the network</returns>
 public BayesianNode[] GetNodes()
 {
     BayesianNode[] result = new BayesianNode[nodes.Length];
     Array.Copy(nodes, result, nodes.Length);
     return(result);
 }