private static double CalculateAccuracy(IDecisionNode root, List <Episode> episodes)
        {
            double correctWeight = episodes.AsParallel().Sum(ep => root.Evaluate(ep.World, ep.Hero) == ep.Tactic ? ep.Weight : 0.0);
            double totalWeight   = episodes.Sum(ep => ep.Weight);

            return(correctWeight / totalWeight);
        }
Пример #2
0
    public DecisionTreeStatus Tick(long TickTime, T context)
    {
        IEnumerable <IDecisionNode <T> > searchNodes = (m_CurrentRunningNode == null) ? m_nodes : m_nodes.SkipWhile(node => node != m_CurrentRunningNode);

        DecisionTreeStatus accumulator = DecisionTreeStatus.Failure;

        foreach (IDecisionNode <T> currentNode in searchNodes)
        {
            if (accumulator != DecisionTreeStatus.Success)
            {
                DecisionTreeStatus NodeDecisionResult = currentNode.Tick(TickTime, context);
                if (NodeDecisionResult == DecisionTreeStatus.Running)
                {
                    m_CurrentRunningNode = currentNode;
                }
                else
                {
                    m_CurrentRunningNode = null;
                }

                accumulator = NodeDecisionResult;
            }
        }

        return(accumulator);
    }
        /// <summary>
        /// Verifies that the substitution configured is applicable here
        /// </summary>
        /// <param name="nodeToEvaluate">the node to evaluate</param>
        /// <param name="substitution">the substitution case</param>
        private static bool EvaluateSubstitution(IDecisionNode nodeToEvaluate, Substition substitution)
        {
            if (nodeToEvaluate.ToString().Replace("RNPC.DecisionLeaves.", "").ToLower() != substitution.LeafName.ToLower())
            {
                return(false);
            }

            switch (substitution.Condition)
            {
            case SubstitionCondition.Default:
                return(true);

            case SubstitionCondition.ParentNot:
                string parentName = nodeToEvaluate.GetParentNode()?.ToString().Replace("RNPC.DecisionNodes.", "").ToLower();
                if (!substitution.ConditionName.ToLower().Split(',').Contains(parentName))
                {
                    return(true);
                }

                return(false);

            default:
                return(false);
            }
        }
Пример #4
0
        public List <Reaction> Evaluate(Character character, Action action, IDecisionNode decisionTreeRootNode)
        {
            var reaction = decisionTreeRootNode.Evaluate(character.MyTraits, character.MyMemory, action);

            character.MyMemory.AddNodeTestResults(((AbstractDecisionNode)decisionTreeRootNode).GetNodeTestsData());

            reaction[0].ReactionScore = ((AbstractDecisionNode)decisionTreeRootNode).GetNodeTestsData().Sum(info => info.ProfileScore);

            character.MyMemory.AddRecentReactions(reaction);

            return(reaction);
        }
        /// <summary>
        /// Builds an XML document from a decision tree, starting with the root node.
        /// </summary>
        /// <param name="writer">file writer</param>
        /// <param name="rootNode">The root of the tree</param>
        /// <param name="decisionTreeName">The name of the decision tree</param>
        /// <param name="myName">Character name</param>
        /// <returns>An xmldocument with the complete decision tree</returns>
        public bool BuildAndSaveXmlDocumentFromTree(IXmlFileController writer, IDecisionNode rootNode, string decisionTreeName, string myName)
        {
            XmlDocument document = new XmlDocument();

            var declaration = document.CreateXmlDeclaration("1.0", "UTF-8", null);

            document.InsertBefore(declaration, document.DocumentElement);

            XmlNode decisionTree = document.CreateElement(decisionTreeName);

            document.AppendChild(decisionTree);

            XmlNode root = document.CreateElement("Root");
            var     name = document.CreateAttribute("text");

            name.Value = rootNode.ToString().Replace("RNPC.DecisionNodes.", "").Replace("RNPC.DecisionLeaves.", "");
            root.Attributes?.Append(name);

            //If it's not a tree with only a leaf
            var branchNode = rootNode as AbstractDecisionNode;

            if (branchNode != null)
            {
                if (branchNode.ConfiguredPassFailValue != 0)
                {
                    var testValue = document.CreateAttribute("test");
                    testValue.Value = branchNode.ConfiguredPassFailValue.ToString();
                    root.Attributes?.Append(testValue);
                }

                if (!string.IsNullOrEmpty(branchNode.DefaultTreeReaction))
                {
                    var defaultReaction = document.CreateAttribute("defaultreaction");
                    defaultReaction.Value = branchNode.DefaultTreeReaction;
                    decisionTree.Attributes?.Append(defaultReaction);
                }

                if (branchNode.LeftNode != null)
                {
                    root.AppendChild(CreateElementFromNode(branchNode.LeftNode, document, "left"));
                }

                if (branchNode.RightNode != null)
                {
                    root.AppendChild(CreateElementFromNode(branchNode.RightNode, document, "right"));
                }
            }

            decisionTree.AppendChild(root);
            writer.WriteDecisionTreeToXmlFile(myName, document);

            return(true);
        }
        /// <summary>
        /// Adds the test value attribute
        /// </summary>
        /// <param name="node"></param>
        /// <param name="document"></param>
        /// <param name="newNode"></param>
        private static void AddTestAttribute(IDecisionNode node, XmlDocument document, XmlNode newNode)
        {
            var abstractNode = node as AbstractDecisionNode;

            if (abstractNode == null || abstractNode.ConfiguredPassFailValue == 0)
            {
                return;
            }

            var testValue = document.CreateAttribute("test");

            testValue.Value = abstractNode.ConfiguredPassFailValue.ToString();
            newNode.Attributes?.Append(testValue);
        }
        /// <summary>
        /// Recursive method that iterates through the tree and finds nodes that are subject to substitution
        /// </summary>
        /// <param name="currentNode">node to start with</param>
        /// <param name="substitution">substitution to do</param>
        /// <param name="nodeToReplace">The node will be substituted</param>
        private static bool FindMatchingNodes(IDecisionNode currentNode, Substition substitution, IDecisionNode nodeToReplace)
        {
            var abstractNode = (AbstractDecisionNode)currentNode;

            if (abstractNode.LeftNode != null)
            {
                // ReSharper disable once UsePatternMatching
                var leftNode = abstractNode.LeftNode as AbstractDecisionNode;

                if (leftNode != null)
                {
                    if (FindMatchingNodes(leftNode, substitution, nodeToReplace))
                    {
                        return(true);
                    }
                }
                else
                {
                    if (EvaluateSubstitution(abstractNode.LeftNode, substitution))
                    {
                        abstractNode.LeftNode = nodeToReplace;
                        return(true);
                    }
                }
            }

            if (abstractNode.RightNode == null)
            {
                return(false);
            }

            // ReSharper disable once UsePatternMatching
            var rightNode = abstractNode.RightNode as AbstractDecisionNode;

            if (rightNode != null)
            {
                if (FindMatchingNodes(rightNode, substitution, nodeToReplace))
                {
                    return(true);
                }
            }

            if (!EvaluateSubstitution(abstractNode.RightNode, substitution))
            {
                return(false);
            }

            abstractNode.RightNode = nodeToReplace;
            return(true);
        }
        private IDecisionNode FitPolicyToHero(HeroType heroType, List <Episode> episodes, Policy policy)
        {
            DecisionNodeAccuracy rootAccuracy = CalculateDecisionTree(episodes);
            IDecisionNode        root         = rootAccuracy.Root;

            Console.WriteLine(string.Format(
                                  "GPU: Policy [{0}] ({1} leaves from {2} episodes) accuracy: {3}",
                                  heroType == HeroType.None ? "All" : heroType.ToString(),
                                  CountLeaves(root),
                                  episodes.Count,
                                  rootAccuracy.Accuracy));

            return(root);
        }
Пример #9
0
 private int CountLeaves(IDecisionNode node)
 {
     if (node is DecisionLeaf)
     {
         return(1);
     }
     else if (node is DecisionNode)
     {
         DecisionNode decisionNode = (DecisionNode)node;
         return(CountLeaves(decisionNode.Left) + CountLeaves(decisionNode.Right));
     }
     else
     {
         throw new ArgumentException("Unknown node type: " + node);
     }
 }
        private void SanityCheckDecisionTree(IDataNode root, IDecisionNode decisionTree, double gpuAccuracy, List <Episode> episodes)
        {
            double gpuTotalWeight = Leaves(root).Sum(x => x.ClassDistribution.Sum());
            double cpuTotalWeight = episodes.Sum(x => x.Weight);

            if (Math.Abs(gpuTotalWeight - cpuTotalWeight) > 1.0)
            {
                throw new InvalidOperationException("Weights don't match");
            }

            double cpuAccuracy = CalculateAccuracy(decisionTree, episodes);

            if (Math.Abs(gpuAccuracy - cpuAccuracy) > 0.01)
            {
                Console.WriteLine(string.Format("Inaccurate: CPU {0:F3} vs GPU {1:F3}", cpuAccuracy, gpuAccuracy));
            }
        }
 private static void Serialize(string prefix, IDecisionNode node, string suffix, CodeWriter writer)
 {
     if (node == null)
     {
         writer.AppendLine("{0}null{1}", prefix, suffix);
     }
     else if (node is DecisionLeaf)
     {
         Serialize(prefix, (DecisionLeaf)node, suffix, writer);
     }
     else if (node is DecisionNode)
     {
         Serialize(prefix, (DecisionNode)node, suffix, writer);
     }
     else
     {
         writer.AppendLine("{0}<{1}>{2}", prefix, node, suffix);
     }
 }
        /// <summary>
        /// Takes a node and creates an XML element
        /// </summary>
        /// <param name="node"></param>
        /// <param name="document"></param>
        /// <param name="decision"></param>
        /// <returns></returns>
        private static XmlNode CreateElementFromNode(IDecisionNode node, XmlDocument document, string decision)
        {
            string nodeName;

            var abstractNode = node as AbstractDecisionNode;

            if (abstractNode != null)
            {
                nodeName = "Node";
            }
            else
            {
                nodeName = "Leaf";
            }

            XmlNode newNode = document.CreateElement(nodeName);

            var name = document.CreateAttribute("text");

            name.Value = node.ToString().Replace("RNPC.DecisionNodes.", "").Replace("RNPC.DecisionLeaves.", "");
            newNode.Attributes?.Append(name);

            AddDecisionAttribute(document, decision, newNode);
            AddTestAttribute(node, document, newNode);

            if (abstractNode == null)
            {
                return(newNode);
            }

            if (abstractNode.LeftNode != null)
            {
                newNode.AppendChild(CreateElementFromNode(abstractNode.LeftNode, document, "left"));
            }

            if (abstractNode.RightNode != null)
            {
                newNode.AppendChild(CreateElementFromNode(abstractNode.RightNode, document, "right"));
            }

            return(newNode);
        }
        /// <summary>
        /// Method that calls the recursive method that finds nodes that are subject to substitution
        /// </summary>
        /// <param name="firstNode">node to start with</param>
        /// <param name="substitution">substitution to do</param>
        /// <param name="replacementNode"></param>
        private static bool FindAndReplaceMatchingNode(IDecisionNode firstNode, Substition substitution, IDecisionNode replacementNode)
        {
            //A decision tree could conceivably be only a leaf
            //That would be an extremely simple decision process
            //an subject to evolving
            var abstractNode = firstNode as AbstractDecisionNode;

            if (abstractNode == null)
            {
                if (!EvaluateSubstitution(firstNode, substitution))
                {
                    return(false);
                }

                firstNode = replacementNode;
                return(true);
            }

            return(FindMatchingNodes(firstNode, substitution, replacementNode));
        }
        private DecisionNodeAccuracy CalculateDecisionTree(List <Episode> episodes)
        {
            List <DataPoint> dataPoints = EpisodesToDataPoints(episodes);

            using (DecisionLearner decisionLearner = new DecisionLearner(_cudaManager, dataPoints)) {
                DataNodeAccuracy rootAccuracy = decisionLearner.FitDecisionTree();
                double           gpuAccuracy  = rootAccuracy.Accuracy;

                IDecisionNode decisionTree = NodeToDecisionTree(rootAccuracy.Node);

#if DEBUGCUDA
                SanityCheckDecisionTree(rootAccuracy.Node, decisionTree, gpuAccuracy, episodes);
#endif

                return(new DecisionNodeAccuracy {
                    Root = decisionTree,
                    Accuracy = gpuAccuracy,
                });
            }
        }
Пример #15
0
        public Rules()
        {
            _startLoanNode = new DecisionNode <Person>
            {
                Condition     = (x) => x.IsCitiZen,
                ConditionDesc = "(x) => x.IsCitiZen"
            };
            var conditionIfCitizenOrValidImmigrant = new DecisionNode <Person>()
            {
                Condition     = x => !x.HasCriminalRecord,
                ConditionDesc = "x => x.HasCriminalRecord",
                TrueNode      = new DecisionNode <Person>()
                {
                    Condition = x => x.CreditScore > 500, ConditionDesc = "x => x.CreditScore > 500"
                }
            };

            _startLoanNode.FalseNode = new DecisionNode <Person>()
            {
                Condition = x => x.IsImmigrantStatusValid, ConditionDesc = "x.IsImmigrantStatusValid", TrueNode = conditionIfCitizenOrValidImmigrant
            };
            _startLoanNode.TrueNode = conditionIfCitizenOrValidImmigrant;
        }
Пример #16
0
 public bool BuildAndSaveXmlDocumentFromTree(IXmlFileController controller, IDecisionNode firstNode, string treename, string myName)
 {
     throw new System.NotImplementedException();
 }
Пример #17
0
 public void SetParentNode(IDecisionNode parent)
 {
     ParentNode = parent;
 }
        /// <summary>
        /// Uses information found in an element to initialize the values of a decision node
        /// </summary>
        /// <param name="element">Current node to initialize</param>
        /// <param name="parent">Parent node</param>
        /// <param name="defaultReaction">The default reaction for the tree being built</param>
        /// <returns></returns>
        private IDecisionNode InitializeNodeWithXmlElement(XmlNode element, IDecisionNode parent, string defaultReaction)
        {
            if (element.Attributes == null || element.Attributes.Count == 0)
            {
                throw new NodeInitializationException($"Element attributes for node {element.Name} are empty");
            }

            var nodeName = element.Attributes["text"]?.Value;

            if (nodeName == null)
            {
                throw new NodeInitializationException($"Text attribute for node {element.Name} is empty");
            }

            var invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());

            nodeName = invalid.Aggregate(nodeName, (current, c) => current.Replace(c.ToString(), string.Empty)).Replace(" ", string.Empty);

            //We have a subtree
            if (element.Attributes["type"] != null && element.Attributes["type"].Value == "subtree")
            {
                //conditional load of a subtree. Minimizes unnecessary loads
                if (element.Attributes["keyword"] != null)
                {
                    var keywords = element.Attributes["keyword"].Value.ToLower();
                    //if none of the keyword is found
                    if (keywords.Split(',').Any(keyword => !_currentAction.Message.ToLower().Contains(keyword)))
                    {
                        return(null);
                    }
                }
                var subElement = GetXmlElementForAction(nodeName);

                var rootNode = InitializeNodeWithXmlElement(subElement.FirstChild, null, defaultReaction);

                return(rootNode);
            }

            //Leaf
            if (element.Name.ToLower() == "leaf")
            {
                if (nodeName.ToLower() == "default" && !string.IsNullOrEmpty(defaultReaction))
                {
                    nodeName = defaultReaction;
                }

                var leaf = FindLeafClassByReflection(nodeName);

                if (leaf == null)
                {
                    throw new NullNodeException("A tree leaf could not be found in class DecisionTreeBuilder. Check that the class associated with the tree exists.");
                }

                leaf.SetParentNode(parent);

                return(leaf);
            }

            //Regular node
            var node = FindNodeClassByReflection(nodeName);

            if (node == null)
            {
                return(null);
            }

            //is this the root node?
            if (parent == null)
            {
                node.DefaultTreeReaction = defaultReaction;
            }
            else
            {
                node.SetParentNode(parent);
            }

            if (element.Attributes["test"] != null)
            {
                var testValue = int.Parse(element.Attributes["test"].Value);
                node.ConfiguredPassFailValue = testValue;
            }

            if (!element.HasChildNodes || element.FirstChild?.Attributes == null)
            {
                return(node);
            }

            switch (element.FirstChild.Attributes["decision"]?.Value)
            {
            case "left":
                node.LeftNode = InitializeNodeWithXmlElement(element.FirstChild, node, defaultReaction);

                if (element.ChildNodes.Count > 1)
                {
                    node.RightNode = InitializeNodeWithXmlElement(element.ChildNodes[1], node, defaultReaction);
                }
                break;

            case "right":
                node.RightNode = InitializeNodeWithXmlElement(element.FirstChild, node, defaultReaction);

                if (element.ChildNodes.Count > 1)
                {
                    node.LeftNode = InitializeNodeWithXmlElement(element.ChildNodes[1], node, defaultReaction);
                }
                break;

            default:
                throw new NodeInitializationException("Decision attribute set to an unknown value");
            }

            return(node);
        }