/// <summary> /// Scans the assumption table, looking for assumptions to add to the Facts.Unknowns list. /// </summary> public static void AskAssumedFacts(string rel, Thing e1, Thing e2, Thing e3) { foreach (Pair p in Pairs) { // If A, then B if (p.LeftHandPoint.Relationship == rel) { // For each rightPoint.Arg number, get the corresponding Thing Thing[] args = new Thing[3] { e1, e2, e3 }; int a1 = p.RightHandPoint.Arg1 - 1; // -1 b/c array is base-zero int a2 = p.RightHandPoint.Arg2 - 1; int a3 = p.RightHandPoint.Arg3 - 1; Thing t1 = a1 >= 0 ? args[a1] : null; Thing t2 = a2 >= 0 ? args[a2] : null; Thing t3 = a3 >= 0 ? args[a3] : null; // Investigates all assumptions // TODO: Does not short circuit Facts.Fact f = new Facts.Fact(p.RightHandPoint.Relationship, t1.Id, t2.Id, t3.Id); f.Value(); } } }
/// <summary> /// Scans the assumption table, looking for assumptions to add to the Facts.Unknowns list. /// </summary> public static void AskAssumedFacts(string rel, Thing e1, Thing e2, Thing e3) { foreach (Pair p in Pairs) { // If A, then B if (p.LeftHandPoint.Relationship == rel) { // For each rightPoint.Arg number, get the corresponding Thing Thing[] args = new Thing[3]{e1,e2,e3}; int a1 = p.RightHandPoint.Arg1 - 1; // -1 b/c array is base-zero int a2 = p.RightHandPoint.Arg2 - 1; int a3 = p.RightHandPoint.Arg3 - 1; Thing t1 = a1 >= 0 ? args[a1] : null; Thing t2 = a2 >= 0 ? args[a2] : null; Thing t3 = a3 >= 0 ? args[a3] : null; // Investigates all assumptions // TODO: Does not short circuit Facts.Fact f = new Facts.Fact(p.RightHandPoint.Relationship, t1.Id, t2.Id, t3.Id); f.Value(); } } }
/// <summary> /// Asks the next question or displays the interview results. /// </summary> public static Response Investigate(List<Facts.Fact> goals) { // Default outputs bool allDone = true; int percent = 0; Facts.Fact theNextFact = new Facts.Fact("", null, null, null); InitializeProofTree(); // Pre-evaluate each goal in order to cache the results of // each evaluted function in the FactBase. This will make // look-ahead short-circuiting work in the interview. // There will obviously be performance implications to // evaluating each goal twice. However, a four-line fix // to a vexing problem feels delightful. And the caching // may end up making things tolerable after all. // // But note that the look-ahead short-circuiting issue is not // completely solved: it will still fail in large rules where // the intermediate conditions are not checked/pre-evaluated. foreach (Facts.Fact g in goals) { g.Value(); } // Console.WriteLine(ShowProofTree()); // Prepare to look for unknown facts Facts.GetUnknowns = true; Facts.Unknowns.Clear(); // Iterate through each goal foreach (Facts.Fact g in goals) { if (!g.Value().HasBeenDetermined) { allDone = false; } } Facts.GetUnknowns = false; // Determine the next fact and the percent complete if (!allDone) { theNextFact = Facts.Unknowns[0]; percent = ProgressPercentage(Facts.Count(), Facts.Unknowns.Count); } return new Engine.Response(allDone, theNextFact, percent, goals); }
/// <summary> /// General response constructor. /// </summary> public Response(bool done, Facts.Fact next, int percent, List<Facts.Fact> goals) { InvestigationComplete = done; NextFact = next; PercentComplete = percent; Goals = goals; }
/// <summary> /// Takes an income packet and instantiates a Hammurabi session. /// </summary> public Packet Assess(Packet request) { // Start timer DateTime startTime = DateTime.Now; // Pre-evaluate each goal to enable look-ahead short circuiting. // See Hammurabi | Core | Engine.cs, line ~81, for an explanation. foreach (Factoid g in request.Goals) { Facts.Fact gb = new Facts.Fact(g.Relationship, g.Arg1, g.Arg2, g.Arg3); gb.Value(); } // Start a fresh session // Facts.Clear(); Facts.GetUnknowns = true; Facts.Unknowns.Clear(); bool allDone = true; request.PercentageComplete = 100; // Assert facts into a Hammurabi session foreach(Factoid f in request.AssertedFacts) { AssertFact(f); } // Iterate through each goal foreach(Factoid g in request.Goals) { Facts.Fact gb = new Facts.Fact(g.Relationship, g.Arg1, g.Arg2, g.Arg3); // Assign to a variable so it's only evaluated once Tvar gbVal = gb.Value(); // Convert Tvar to timeline object g.Timeline = TvarToTimeline(gbVal); // All goals resolved? if (!gbVal.HasBeenDetermined) { allDone = false; } } // Stop looking for unknown facts Facts.GetUnknowns = false; // Determine the next fact and the percent complete if (!allDone) { // Factoid neededFact = new Factoid("Tnum","USC.Tit26.Sec151.ThresholdAmount","Jim","",""); // Facts.Fact f = new Facts.Fact("USC.Tit26.Sec151.ThresholdAmount", null, null, null); // Factoid neededFact = new Factoid(f); Factoid neededFact = new Factoid(Facts.Unknowns[0]); request.NeededFacts = new List<Factoid>(){neededFact}; request.PercentageComplete = Interactive.Engine.ProgressPercentage(Facts.Count(), Facts.Unknowns.Count); } // Add elapsed time to response object request.ResponseTimeInMs = Convert.ToInt32((DateTime.Now - startTime).TotalMilliseconds); return request; }
public ProofTreeNode(Facts.Fact fact, int depth) { TheFact = fact; Depth = depth; }