예제 #1
0
        public SimpleSingleClauseSolver(IClause clause, ISolver subclauseSolver)
        {
            if (clause == null)
            {
                throw new ArgumentNullException("clause");
            }
            if (subclauseSolver == null)
            {
                throw new ArgumentNullException("subclauseSolver");
            }

            _clause          = clause;
            _subclauseSolver = subclauseSolver;

            // Compile each part of the clause to its subclauses
            _clauseAssignments = new[] { clause.Implies }.Concat(clause.If)
            .Select(predicate =>
            {
                var assignments = PredicateAssignmentList.FromPredicate(predicate);
                return(new AssignmentData
                {
                    PredicateName = predicate.UnificationKey,
                    NumArguments = assignments.CountArguments(),
                    Assignments = assignments.Assignments.ToArray()
                });
            })
            .ToList();
        }
        /// <summary>
        /// Retrieves an object representing the assignments for a particular literal when used as a predicate
        /// </summary>
        public static PredicateAssignmentList FromPredicate(ILiteral predicate)
        {
            var result = new PredicateAssignmentList();

            if (predicate.UnificationKey != null)
            {
                foreach (var argument in predicate.Dependencies)
                {
                    result.AddArgument(argument);
                }
            }

            return(result);
        }
        /// <summary>
        /// Retrieves an object representing the assignments for a particular literal when used as a predicate
        /// </summary>
        public static PredicateAssignmentList FromPredicate(ILiteral predicate)
        {
            var result = new PredicateAssignmentList();

            if (predicate.UnificationKey != null)
            {
                foreach (var argument in predicate.Dependencies)
                {
                    result.AddArgument(argument);
                }
            }

            return result;
        }
예제 #4
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()));
        }
예제 #5
0
        /// <summary>
        /// Compiles a clause to a bytecode program
        /// </summary>
        public static void Compile(this IClause clause, ByteCodeProgram program)
        {
            var unifier = new ByteCodeUnifier(program);

            // Take each part of the clause and retrieve the assignments for it, with the 'implies' set at the start
            var allPredicates = new[] { clause.Implies }.Concat(clause.If).ToArray();
            var assignmentList = allPredicates
                                 .Select(predicate => new
            {
                Assignments    = PredicateAssignmentList.FromPredicate(predicate),
                UnificationKey = predicate.UnificationKey
            })
                                 .ToArray();

            // Allocate space for the arguments and any permanent variables
            var permanentVariables = PermanentVariableAssignments.PermanentVariables(assignmentList.Select(assign => assign.Assignments));
            var numArguments       = assignmentList[0].Assignments.CountArguments();

            if (permanentVariables.Count > 0 || allPredicates.Length > 1)
            {
                program.Write(Operation.Allocate, permanentVariables.Count, numArguments);
            }

            // Unify with the predicate first
            unifier.ProgramUnifier.Bind(assignmentList[0].Assignments.Assignments, permanentVariables);
            unifier.ProgramUnifier.Compile(assignmentList[0].Assignments.Assignments);

            // Call the clauses
            foreach (var assignment in assignmentList.Skip(1))
            {
                unifier.QueryUnifier.Bind(assignment.Assignments.Assignments, permanentVariables);
                unifier.QueryUnifier.Compile(assignment.Assignments.Assignments);

                program.Write(Operation.Call, assignment.UnificationKey, assignment.UnificationKey.Dependencies.Count());
            }

            // Deallocate any permanent variables that we might have found
            if (permanentVariables.Count > 0 || allPredicates.Length > 1)
            {
                program.Write(Operation.Deallocate);
            }
        }