Skip to content

Commit

Permalink
* Evaluator.cs: Fixes a performance issue in Evaluator.Evaluate
Browse files Browse the repository at this point in the history
* EvaluatorTests.cs: Adds a simple parsing example

* Unification.cs: Fixes typo.
  • Loading branch information
xavierpinho committed Sep 14, 2021
1 parent ad91a8b commit 2c237c4
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
52 changes: 52 additions & 0 deletions VeryNaiveDatalog.Test/EvaluatorTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;

namespace VeryNaiveDatalog.Test
Expand Down Expand Up @@ -36,5 +39,54 @@ public void Evaluator_Ancestor_Example()

CollectionAssert.AreEquivalent(expected, result);
}

[Test]
public void Evaluator_Parsing_Example()
{
// Helpers
var i = new Variable("i");
var j = new Variable("j");
var k = new Variable("k");
Func<int, Symbol> s = i => new Symbol(i.ToString());
Func<int, Atom> eps = i => new Atom("Epsilon", s(i), s(i));

// Grammar
// A ::= <epsilon> | A A | L B
// B ::= A R
// L ::= '('
// R ::= ')'
var a0 = new Rule(new Atom("A", i, j), new Atom("Epsilon", i, j));
var a1 = new Rule(new Atom("A", i, j), new Atom("A", i, k), new Atom("A", k, j));
var a2 = new Rule(new Atom("A", i, j), new Atom("L", i, k), new Atom("B", k, j));
var b0 = new Rule(new Atom("B", i, j), new Atom("A", i, k), new Atom("R", k, j));

var rules = new[] { a0, a1, a2, b0 };

IEnumerable<Atom> Lex(Char c, int i)
{
yield return eps(i);
if ('(' == c)
{
yield return new Atom("L", s(i), s(i + 1));
}

if (')' == c)
{
yield return new Atom("R", s(i), s(i + 1));
}
}

// Test case: can we find of derivation of A from
// offset 0 to offset src.Length?
var src = "(()())()";
var facts = src.SelectMany(Lex);
var query = new Atom("A", s(0), s(src.Length));
var result = facts.Query(query, rules);

// The resulting substitution is empty since there's no
// variables in the query.
Assert.AreEqual(1, result.Count());
}

}
}
10 changes: 5 additions & 5 deletions VeryNaiveDatalog/Evaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ private static IEnumerable<Atom> Apply(this Rule rule, IEnumerable<Atom> kb)
// Repeatedly applies rules to atoms until no more atoms are derivable.
private static IEnumerable<Atom> Evaluate(this IEnumerable<Atom> kb, IEnumerable<Rule> rules)
{
int prevSize, nextSize;
bool productive;
do
{
prevSize = kb.Count();
kb = rules.Apply(kb).Union(kb);
nextSize = kb.Count();
} while (prevSize < nextSize);
var nextKb = rules.Apply(kb).ToHashSet(); // ToHashSet for performance
productive = nextKb.Except(kb).Any();
kb = kb.Union(nextKb);
} while (productive);

return kb;
}
Expand Down
2 changes: 1 addition & 1 deletion VeryNaiveDatalog/Unification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private static bool TryUnify(Atom a1, Atom a2, Substitution env)
}

// Attempt to unify an atom against a collection of atoms under a given environment.
// Returning empty means to unification was possible.
// Returning empty means no unification was possible.
public static IEnumerable<Substitution> UnifyWith(this Atom atom, IEnumerable<Atom> kb, Substitution env)
{
var a1 = atom.Apply(env);
Expand Down

0 comments on commit 2c237c4

Please sign in to comment.