// Decision tree logic private static DecisionQuery MainDecisionTree() { var cooldownBranch = new DecisionQuery { Test = (tower) => tower.CooldownOver <= 0f, Positive = new DecisionResult { Result = State.Shoot }, Negative = new DecisionResult { Result = State.TargetLocked } }; var inRangeBranch = new DecisionQuery { Test = (tower) => tower.EnemyInRange <= 15f, Positive = cooldownBranch, Negative = new DecisionResult { Result = State.TargetLocked } }; var trunk = new DecisionQuery { Test = (tower) => tower.EnemyAppeared, Positive = inRangeBranch, Negative = new DecisionResult { Result = State.Idle } }; return(trunk); }
public virtual void Visit(DecisionQuery <TIn, TOut> decisionQuery) { GraphBuilder.AddPositiveEdgeStatement(decisionQuery, decisionQuery.Positive); decisionQuery.Positive.Accept(this); GraphBuilder.AddNegativeEdgeStatement(decisionQuery, decisionQuery.Negative); decisionQuery.Negative.Accept(this); }
public QueryCache(DecisionQuery query) { query.ComputeHash(); if (query.valueIndices == null) { throw new Exception("WTF"); } valueIndices = query.valueIndices; hashCode = query.GetHashCode(); }
public bool?CachedResolve(DecisionQuery query) { bool result; QueryCache item = new QueryCache(query); if (!cache.TryGetValue(item, out result)) { return(null); } return(result); }
public void Decide() { // Calculate the sqr to compare to the dot product float nearSqr = near * near; List <AttributeValue> values = new List <AttributeValue>(); foreach (var need in needs) { var dist = need.target.transform.position - character.transform.position; // If the need is selected we simple state whether its Near or Far // If it isn't selected we simply state "No" values.Add(new AttributeValue(need.inputName, need.toggle.isOn ? ((dist.sqrMagnitude > nearSqr) ? "Far" : "Near") : "No")); } // Now we use the decision tree to see which of the needs we need to satisfy first // o In human reasoning thirst and hunger will always take precedence over other needs // o The distance to satisfy the need is also a factor // o Please note that in a game context these needs would have their own // mecanisms such as using energy depletion as an indication of hunger. DecisionQuery query = new DecisionQuery(); bool decided = false; StringBuilder builder = new StringBuilder(); foreach (var need in needs) { if (!need.toggle.isOn) { continue; } query.Set(treeName, need.inputName, values.ToArray()); tree.Decide(query); if (query.Yes) { character.target = need.target; decided = true; } builder.AppendLine(tree.PrintDecision(query)); } // Print the last query text.text = builder.ToString(); if (!decided) { character.target = startPoint; } }
public void Cache(DecisionQuery query, bool value) { QueryCache item = new QueryCache(query); if (cache.ContainsKey(item)) { cache[item] = value; } else { cache.Add(item, value); } }
public void Evaluate_GivenNullNegative_Throws() { // GIVEN var positiveDecision = new Mock <Decision <EmployeeInfo, BonusCalculation> >(); var decisionQuery = new DecisionQuery <EmployeeInfo, BonusCalculation> { Test = _ => true, Positive = positiveDecision.Object, Negative = null }; var input = new EmployeeInfo(); // WHEN THEN Assert.Throws <DecisionException>(() => decisionQuery.Evaluate(input), "'Positive' cannot be null"); }
public string PrintDecision(DecisionQuery query) { var info = GetDecisionTree(query.decisionTreeName); if (info == null) { return(null); } var logic = info.GetOutcome(query.outcomeName); if (logic == null || logic.root == null) { return(null); } return("<color=#ffe900>" + query.outcomeName + "</color>\n" + id3.PrintResolve(logic.root, info.predictColumn, "o ", query.predicate)); }
public void Evaluate_GivenNegativeTest_EvaluatesNegative() { // GIVEN var positiveDecision = new Mock <Decision <EmployeeInfo, BonusCalculation> >(); var negativeDecision = new Mock <Decision <EmployeeInfo, BonusCalculation> >(); var decisionQuery = new DecisionQuery <EmployeeInfo, BonusCalculation> { Test = _ => false, Positive = positiveDecision.Object, Negative = negativeDecision.Object }; var input = new EmployeeInfo(); // WHEN decisionQuery.Evaluate(input); // THEN positiveDecision.Verify(decision => decision.Evaluate(input), Times.Never); negativeDecision.Verify(decision => decision.Evaluate(input), Times.Once); }
public bool?Decide(DecisionQuery query) { query.result = null; var info = GetDecisionTree(query.decisionTreeName); if (info == null) { return(null); } query.info = info; var logic = info.GetOutcome(query.outcomeName); if (logic == null || logic.root == null) { return(null); } query.result = logic.CachedResolve(query); if (query.result == null) { var node = id3.Resolve(logic.root, info.predictColumn, query.predicate); if (node == null) { return(null); } if (node.attribute.IsValue) { query.root = logic.root; query.result = (bool)node.attribute.Value; logic.Cache(query, query.result.Value); return(query.result); } return(null); } return(query.result); }
public override void Visit(DecisionQuery <TIn, TOut> decisionQuery) { if (_pathStack.Count != 0 && _nextDecisionInPath == null || _nextDecisionInPath == decisionQuery) { var isPositiveDecision = _pathStack.Pop(); _nextDecisionInPath = isPositiveDecision ? decisionQuery.Positive : decisionQuery.Negative; GraphBuilder.AddPositiveEdgeStatement(decisionQuery, decisionQuery.Positive, thickLine: isPositiveDecision); decisionQuery.Positive.Accept(this); GraphBuilder.AddNegativeEdgeStatement(decisionQuery, decisionQuery.Negative, thickLine: !isPositiveDecision); decisionQuery.Negative.Accept(this); } else { GraphBuilder.AddPositiveEdgeStatement(decisionQuery, decisionQuery.Positive); decisionQuery.Positive.Accept(this); GraphBuilder.AddNegativeEdgeStatement(decisionQuery, decisionQuery.Negative); decisionQuery.Negative.Accept(this); } }
public void EvaluateWithPath_GivenNegativeTest_ReturnsExpectedPath() { // GIVEN var decisionQuery = new DecisionQuery <EmployeeInfo, BonusCalculation> { Test = _ => false, Positive = new DecisionResult <EmployeeInfo, BonusCalculation> { CreateResult = _ => new BonusCalculation() }, Negative = new DecisionResult <EmployeeInfo, BonusCalculation> { CreateResult = _ => new BonusCalculation() } }; var input = new EmployeeInfo(); // WHEN var result = decisionQuery.EvaluateWithPath(input); // THEN result.DecisionPath.Path.Should().HaveCount(1); result.DecisionPath.Path.Single().Should().BeFalse(); }
private DecisionQuery MainDecisionTree() { var check = new DecisionQuery { Title = "Provjera", Test = async(z) => { List <Utakmica> lista = new List <Utakmica>(); if (z.naziv == "lokacija") { lista = await _apiServiceUtakmice.Get <List <Utakmica> >(new UtakmiceeSearchRequest() { GradID = z.id }); } else if (z.naziv == "stadioni") { lista = await _apiServiceUtakmice.Get <List <Utakmica> >(new UtakmiceeSearchRequest() { StadionID = z.id }); } else { lista = await _apiServiceUtakmice.Get <List <Utakmica> >(new UtakmiceeSearchRequest() { TimID = z.id }); } return(lista); }, Positive = new DecisionResult() { result = true, utakmice = new List <Utakmica>() }, Negative = new DecisionResult() { result = false, utakmice = new List <Utakmica>() } }; var datumi = new DecisionQuery { Title = "Datumi", Test = async(z) => { UtakmiceeSearchRequest req = new UtakmiceeSearchRequest(); if (z.naziv == "lokacija") { req.GradID = z.id; req.PoLokaciji = true; } else if (z.naziv == "stadioni") { req.StadionID = z.id; req.PoStadionu = true; } else { req.TimID = z.id; req.PoTimu = true; } if (z.d1 != DateTime.MinValue && z.d2 != DateTime.MinValue) { req.d1 = z.d1; req.d2 = z.d2; } var lista = await _apiServiceUtakmice.Get <List <Utakmica> >(req); return(lista); }, Positive = check, Negative = new DecisionResult() { result = false, utakmice = new List <Utakmica>() } }; var cijene = new DecisionQuery { Title = "Cijene", Test = async(z) => { UtakmiceeSearchRequest req = new UtakmiceeSearchRequest(); if (z.naziv == "lokacija") { req.GradID = z.id; req.PoLokaciji = true; } else if (z.naziv == "stadioni") { req.StadionID = z.id; req.PoStadionu = true; } else { req.TimID = z.id; req.PoTimu = true; } if (z.d1 != DateTime.MinValue && z.d2 != DateTime.MinValue) { req.d1 = z.d1; req.d2 = z.d2; } if (z.cijena != -1) { req.cijena = z.cijena; } var lista = await _apiServiceUtakmice.Get <List <Utakmica> >(req); return(lista); }, Positive = datumi, Negative = new DecisionResult() { result = false, utakmice = new List <Utakmica>() } }; return(cijene); }
private static DecisionQuery MainDecisionTree() { //Decision 4 var creditBranch = new DecisionQuery { Title = "Use credit card", Test = (client) => client.UsesCreditCard, Positive = new DecisionResult { Result = true }, Negative = new DecisionResult { Result = false } }; //Decision 3 var experienceBranch = new DecisionQuery { Title = "Have more than 3 years experience", Test = (client) => client.YearsInJob > 3, Positive = creditBranch, Negative = new DecisionResult { Result = false } }; //Decision 2 var moneyBranch = new DecisionQuery { Title = "Earn more than 40k per year", Test = (client) => client.Income > 40000, Positive = experienceBranch, Negative = new DecisionResult { Result = false } }; //Decision 1 var criminalBranch = new DecisionQuery { Title = "Have a criminal record", Test = (client) => client.CriminalRecord, Positive = new DecisionResult { Result = false }, Negative = moneyBranch }; //Decision 0 var trunk = new DecisionQuery { Title = "Want a loan", Test = (client) => client.IsLoanNeeded, Positive = criminalBranch, Negative = new DecisionResult { Result = false } }; return(trunk); }
// private DecisionQuery targetDecisionTree() { //Decision 9 var waterWeak = new DecisionQuery { title = "Finding Water weakness", targetTest = (target) => target.m_dtWaterWeak == true, positive = new DecisionResult { result = true }, negative = new DecisionResult { result = false } }; //Decision 8 var earthWeak = new DecisionQuery { title = "Finding Earth weakness", targetTest = (target) => target.m_dtEarthWeak == true, positive = waterWeak, negative = waterWeak }; //Decision 7 var windWeak = new DecisionQuery { title = "Finding Wind weakness", targetTest = (target) => target.m_dtWindWeak == true, positive = earthWeak, negative = earthWeak }; //Decision 6 var fireWeak = new DecisionQuery { title = "Finding Fire weakness", targetTest = (target) => target.m_dtFireWeak == true, positive = windWeak, negative = windWeak }; //Decision 7 var magicWeak = new DecisionQuery { title = "Finding physical weaknesses", targetTest = (target) => target.m_magicWeak == true, positive = fireWeak, negative = new DecisionResult { result = false } }; //Decision 6 var pierceWeak = new DecisionQuery { title = "Finding Pierce weakness", targetTest = (target) => target.m_dtPierceWeak == true, positive = magicWeak, negative = magicWeak }; //Decision 5 var slashWeak = new DecisionQuery { title = "Finding Slash weakness", targetTest = (target) => target.m_dtSlashWeak == true, positive = pierceWeak, negative = pierceWeak }; //Decision 4 var bluntWeak = new DecisionQuery { title = "Finding Blunt weakness", targetTest = (target) => target.m_dtBluntWeak == true, positive = slashWeak, negative = slashWeak }; //Decision 3 var physicalWeak = new DecisionQuery { title = "Finding physical weaknesses", targetTest = (target) => target.m_physicalWeak == true, positive = bluntWeak, negative = magicWeak }; //Decision 2 var canHeal = new DecisionQuery { title = "Finding if they can heal", targetTest = (target) => target.m_dtCanHeal == true, positive = physicalWeak, negative = physicalWeak }; //Decision 1 var lowestMP = new DecisionQuery { title = "Finding lowest MP", targetTest = (target) => target.m_lowMP == true, positive = canHeal, negative = canHeal }; //Decision 0 var lowestHP = new DecisionQuery { title = "Finding lowest HP", targetTest = (target) => target.m_lowHP == true, positive = canHeal, negative = lowestMP }; return(lowestHP); }
public DecisionTreeHead(DecisionQuery <Activity, IEnumerable <Activity> > entryPoint) { _entryPoint = entryPoint; }
public bool?Decide(DecisionQuery query) { return(decisionTree.Decide(query)); }
public AttributeValue(string name, string value, DecisionQuery basedOn = null) { this.name = name; this.value = value; this.basedOn = basedOn; }
static void MainDecisionTrees() { // The tree is constructed from a query var tree = new DecisionQuery { Title = "More than $40k", // Test is specified using a lambda function Test = (client) => client.Income > 40000, // Sub-trees can be 'DecisionResult' or 'DecisionQuery' Positive = new DecisionResult { Result = true }, Negative = new DecisionResult { Result = false } }; // Test a client using this tree // Create client using object initializer var john = new Client { Name = "John Doe", Income = 40000, YearsInJob = 1, UsesCreditCard = true, CriminalRecord = false }; tree.Evaluate(john); }