public void PicksCorrectVariablesInSimpleCase() { // Predicate p(X,Y) :- q(X, Z), r(Z,Y) should have Z and Y as permanent variables var p = Literal.NewAtom(); var q = Literal.NewAtom(); var r = Literal.NewAtom(); var X = Literal.NewVariable(); var Y = Literal.NewVariable(); var Z = Literal.NewVariable(); var pXY = Literal.NewFunctor(2).With(X, Y); var qXZ = Literal.NewFunctor(2).With(X, Z); var rZY = Literal.NewFunctor(2).With(Z, Y); // Create the clause var clause = Clause.If(qXZ, rZY).Then(pXY); // Compile to assignments var allPredicates = new[] { clause.Implies }.Concat(clause.If).ToArray(); var assignmentList = allPredicates.Select(predicate => PredicateAssignmentList.FromPredicate(predicate)); // Get the set of permanent variables var permanent = PermanentVariableAssignments.PermanentVariables(assignmentList); // Z and Y are the only permanent variables Assert.IsFalse(permanent.Contains(X)); Assert.IsTrue(permanent.Contains(Y)); Assert.IsTrue(permanent.Contains(Z)); Assert.AreEqual(2, permanent.Count); }
/// <summary> /// Queries a solver for a goal /// </summary> public static IQueryResult Query(this ISolver solver, ILiteral goal) { // Result is false for something without a key if (goal.UnificationKey == null) { return(new BasicQueryResult(false, new EmptyBinding(null))); } // Compile the query var unifier = new SimpleUnifier(); var assignments = new PredicateAssignmentList(); // Assume we have a basic predicate foreach (var arg in goal.Dependencies) { assignments.AddArgument(arg); } // Run through the unifier var freeVariableNames = unifier.QueryUnifier.Bind(assignments.Assignments); var freeVariables = freeVariableNames.Select(variable => unifier.GetVariableLocation(variable).Dereference()); unifier.QueryUnifier.Compile(assignments.Assignments); // Call via the solver var moveNext = solver.Call(goal.UnificationKey, unifier.GetArgumentVariables(assignments.CountArguments())); Func <IQueryResult> nextResult = () => { // Update the variables to the next result var succeeded = moveNext(); // Nothing to do if we didn't succeed if (!succeeded) { return(new BasicQueryResult(false, new EmptyBinding(null))); } // Bind the variables var variableValues = freeVariables .Select(varRef => varRef.Freeze()) .Zip(freeVariableNames, (value, name) => new { Value = value, Name = name }).ToArray(); var binding = new BasicBinding(null, variableValues.ToDictionary(val => val.Name, val => val.Value)); // Return the result return(new BasicQueryResult(true, binding)); }; // Chain to produce the final result return(new ChainedResult(nextResult(), () => Task.FromResult(nextResult()))); }