Exemplo n.º 1
0
        /// <summary>
        /// Returns the possible ways that a query term can unify with a program term
        /// </summary>
        public static IBindings Unify(this ILiteral query, ILiteral program, IBindings bindings = null)
        {
            var simpleUnifier = new SimpleUnifier();
            var freeVariables = new HashSet<ILiteral>();

            // Run the unifier
            var queryFreeVars = simpleUnifier.QueryUnifier.Compile(query, bindings);
            if (queryFreeVars == null) return null;

            simpleUnifier.PrepareToRunProgram();

            var programFreeVars = simpleUnifier.ProgramUnifier.Compile(program, bindings);
            if (programFreeVars == null) return null;

            freeVariables.UnionWith(queryFreeVars);

            // Retrieve the unified value for the program
            var result = simpleUnifier.UnifiedValue(query.UnificationKey ?? query);

            // If the result was valid, return as the one value from this function
            if (result != null)
            {
                var variableBindings = freeVariables.ToDictionary(variable => variable,
                    variable => simpleUnifier.UnifiedValue(variable));

                return new BasicBinding(result, variableBindings);
            }
            else
            {
                return null;
            }
        }
Exemplo n.º 2
0
        public void FindFreeVariableInMoreComplicatedFunctor()
        {
            var functor = GetQueryAndProgram1().Item1;
            var unifier = new SimpleUnifier();

            var freeVars = unifier.QueryUnifier.Compile(functor).ToList();
            Assert.AreEqual(2, freeVars.Count);
        }
Exemplo n.º 3
0
        public void AtomIsNotFreeVariable()
        {
            var atom = Literal.NewAtom();
            var unifier = new SimpleUnifier();

            var freeVars = unifier.QueryUnifier.Compile(atom).ToList();
            Assert.AreEqual(0, freeVars.Count);
        }
Exemplo n.º 4
0
        public void VariableIsFreeVariable()
        {
            var variable = Literal.NewVariable();
            var unifier = new SimpleUnifier();

            var freeVars = unifier.QueryUnifier.Compile(variable).ToList();
            Assert.AreEqual(1, freeVars.Count);
            Assert.AreEqual(variable, freeVars[0]);
        }
Exemplo n.º 5
0
        public void FindFreeVariableInFunctor()
        {
            var variable = Literal.NewVariable();
            var functor = Literal.NewFunctor(1).With(variable);
            var unifier = new SimpleUnifier();

            var freeVars = unifier.QueryUnifier.Compile(functor).ToList();
            Assert.AreEqual(1, freeVars.Count);
            Assert.AreEqual(variable, freeVars[0]);
        }
Exemplo n.º 6
0
        /// <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()));
        }
        public Func<bool> Call(ILiteral predicate, params IReferenceLiteral[] arguments)
        {
            // Assume that predicate is correct

            // Load the arguments into a simple unifier
            var unifier = new SimpleUnifier();
            unifier.LoadArguments(arguments);

            // Unify using the predicate
            unifier.ProgramUnifier.Bind(_clauseAssignments[0].Assignments);
            if (!unifier.ProgramUnifier.Compile(_clauseAssignments[0].Assignments))
            {
                // Fail if we can't unify
                return () => false;
            }

            // Call using the clauses
            return SolveAllSubclauses(_clauseAssignments.Skip(1), unifier);
        }
        /// <summary>
        /// Returns a function that solves a list of subclauses
        /// </summary>
        private Func<bool> SolveAllSubclauses(IEnumerable<AssignmentData> assignments, SimpleUnifier unifier)
        {
            // The first solution is always true once
            bool solvedOnce = false;
            Func<bool> solve = () =>
            {
                if (solvedOnce)
                {
                    // Reset the unifier to its original state and give up
                    unifier.ResetTrail();
                    return false;
                }
                else
                {
                    solvedOnce = true;
                    return true;
                }
            };

            // Chain the solutions for each subclause to generate the final result
            foreach (var clause in assignments)
            {
                solve = SolveSubclause(clause, unifier, solve);
            }

            // This generates the result
            return solve;
        }
        /// <summary>
        /// Solves a subclause
        /// </summary>
        private Func<bool> SolveSubclause(AssignmentData clause, SimpleUnifier unifier, Func<bool> solvePreviousClause)
        {
            // Create a new trail
            unifier.PushTrail();

            Func<bool> nextInThisClause = null;

            return () =>
            {
                if (nextInThisClause == null || !nextInThisClause())
                {
                    // Reset the state and get the solution for the previous clause
                    unifier.ResetTrail();

                    if (!solvePreviousClause())
                    {
                        return false;
                    }

                    // Push a new trail for this clause
                    unifier.PushTrail();

                    // Solve this clause
                    unifier.QueryUnifier.Bind(clause.Assignments);
                    if (!unifier.QueryUnifier.Compile(clause.Assignments))
                    {
                        return false;
                    }

                    // Call the predicate
                    nextInThisClause = _subclauseSolver.Call(clause.PredicateName, unifier.GetArgumentVariables(clause.NumArguments));

                    // Result depends on the next item in this clause
                    return nextInThisClause();
                }
                else
                {
                    // nextInThisClause() returned true, so this clause was solved
                    return true;
                }
            };
        }
Exemplo n.º 10
0
        public void ManualUnification()
        {
            var simpleUnifier = new SimpleUnifier();
            var unifier = new TraceUnifier(simpleUnifier);
            var X = new[] { new Variable(), new Variable(), new Variable(), new Variable(), new Variable(), new Variable(), new Variable(), new Variable() };
            var h2 = new UnboundFunctor(2);
            var f1 = new UnboundFunctor(1);
            var p3 = new UnboundFunctor(3);
            var a0 = new UnboundFunctor(0);

            unifier.BindVariable(0, X[1]);
            unifier.BindVariable(1, X[2]);
            unifier.BindVariable(2, X[3]);
            unifier.BindVariable(3, X[4]);
            unifier.BindVariable(4, X[5]);
            unifier.BindVariable(5, X[6]);
            unifier.BindVariable(6, X[7]);

            unifier.PutStructure(h2, 2, X[3]);
            unifier.SetVariable(X[2]);
            unifier.SetVariable(X[5]);
            unifier.PutStructure(f1, 1, X[4]);
            unifier.SetValue(X[5]);
            unifier.PutStructure(p3, 3, X[1]);
            unifier.SetValue(X[2]);
            unifier.SetValue(X[3]);
            unifier.SetValue(X[4]);

            unifier.GetStructure(p3, 3, X[1]);
            unifier.UnifyVariable(X[2]);
            unifier.UnifyVariable(X[3]);
            unifier.UnifyVariable(X[4]);
            unifier.GetStructure(f1, 1, X[2]);
            unifier.UnifyVariable(X[5]);
            unifier.GetStructure(h2, 2, X[3]);
            unifier.UnifyValue(X[4]);
            unifier.UnifyVariable(X[6]);
            unifier.GetStructure(f1, 1, X[6]);
            unifier.UnifyVariable(X[7]);
            unifier.GetStructure(a0, 0, X[7]);

            var result = simpleUnifier.UnifiedValue(X[1]);
            Assert.IsNotNull(result);
        }