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); }
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); } }
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); }
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, }); } }
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; }
public bool BuildAndSaveXmlDocumentFromTree(IXmlFileController controller, IDecisionNode firstNode, string treename, string myName) { throw new System.NotImplementedException(); }
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); }