示例#1
0
        /// <summary>
        /// Ask the knowledge base if a given statement about the model is true, given what it knows.
        /// </summary>
        /// <param name="query"></param>
        /// <returns>True if the statement is known to be true, false if it is known to be false or cannot be determined.</returns>
        public bool Ask(Expression <Predicate <TModel> > query)
        {
            // NB: Very raw implementation - there are a number of possible performance improvements that could be made here
            // Will return to give them a go at some point..

            var queryAsCnf = new CNFExpression <TModel>(query);
            var clauses    = sentences.Append(queryAsCnf).SelectMany(s => s.Clauses).ToList();
            List <CNFClause <TModel> > newClauses = new List <CNFClause <TModel> >();

            while (true)
            {
                // TODO-PERFORMANCE: While this is how the source book writes the algorithm, its very inefficient -
                // we'll end up resolving the same clauses again and again. Need to improve this (and move this
                // implementation to the benchmarks project as a baseline).
                foreach (var ci in clauses)
                {
                    foreach (var cj in clauses)
                    {
                        var resolvents = CNFClause <TModel> .Resolve(ci, cj);

                        if (resolvents.IsEmpty)
                        {
                            return(true);
                        }

                        newClauses.Add(resolvents);
                    }
                }

                // if new ⊆ clauses then return false // need clause equality..
                clauses.AddRange(newClauses);
            }

            return(false);
        }
示例#2
0
        public void NeedsNormalisation()
        {
            var e = new CNFExpression <MyModel>(PLExpression <MyModel> .Iff(m => m.L, m => m.R1 || m.R2));

            e.ShouldHaveState(clauseCount: 3);

            e.Clauses.ElementAt(0).ShouldHaveState(
                isDefiniteClause: false,
                isGoalClause: false,
                isHornClause: false,
                isUnitClause: false,
                literalCount: 3);
            e.Clauses.ElementAt(0).Literals.ElementAt(0).ShouldHaveState(
                atomicSentenceSymbol: "m.L",
                isNegated: true);
            e.Clauses.ElementAt(0).Literals.ElementAt(1).ShouldHaveState(
                atomicSentenceSymbol: "m.R1",
                isNegated: false);
            e.Clauses.ElementAt(0).Literals.ElementAt(2).ShouldHaveState(
                atomicSentenceSymbol: "m.R2",
                isNegated: false);

            e.Clauses.ElementAt(1).ShouldHaveState(
                isDefiniteClause: true,
                isGoalClause: false,
                isHornClause: true,
                isUnitClause: false,
                literalCount: 2);
            e.Clauses.ElementAt(1).Literals.ElementAt(0).ShouldHaveState(
                atomicSentenceSymbol: "m.R1",
                isNegated: true);
            e.Clauses.ElementAt(1).Literals.ElementAt(1).ShouldHaveState(
                atomicSentenceSymbol: "m.L",
                isNegated: false);

            e.Clauses.ElementAt(2).ShouldHaveState(
                isDefiniteClause: true,
                isGoalClause: false,
                isHornClause: true,
                isUnitClause: false,
                literalCount: 2);
            e.Clauses.ElementAt(2).Literals.ElementAt(0).ShouldHaveState(
                atomicSentenceSymbol: "m.R2",
                isNegated: true);
            e.Clauses.ElementAt(2).Literals.ElementAt(1).ShouldHaveState(
                atomicSentenceSymbol: "m.L",
                isNegated: false);
        }
示例#3
0
        public void UnitClause()
        {
            var e = new CNFExpression <MyModel>(m => m.L);

            e.ShouldHaveState(clauseCount: 1);

            e.Clauses.Single().ShouldHaveState(
                isDefiniteClause: true,
                isGoalClause: false,
                isHornClause: true,
                isUnitClause: true,
                literalCount: 1);

            e.Clauses.Single().Literals.Single().ShouldHaveState(
                atomicSentenceSymbol: "m.L",
                isNegated: false);
        }
示例#4
0
 public static void ShouldHaveState(
     this CNFExpression <MyModel> expression,
     int clauseCount)
 {
     Assert.Equal(clauseCount, expression.Clauses.Count);
 }