This repository contains a naive, bottom-up implementation of Datalog's semantics, in about 200 lines of C# 10 code.
A Datalog program consists of a set of facts and rules. Facts denote assertions, while rules denote relationships (from which new facts are obtainable.)
The "Hello World" of Datalog is graph reachability:
// Rules
ancestor(x,y) :- parent(x,y).
ancestor(x,y) :- ancestor(x,z), parent(z,y).
// Facts
parent(Homer, Lisa).
parent(Homer, Bart).
parent(Grampa, Homer).
For the snippet above, running the query ?ancestor(x, Bart) (in English:
for which values of x does ancestor(x,Bart) hold?) would output 2
results, namely:
x = Homerx = Grampa
which are obtainable only by first deriving the facts
ancestor(Grampa,Homer), ancestor(Homer, Bart) and
ancestor(Grampa,Bart), by repeated application of the rules to the facts.
The snippet above can be encoded in VeryNaiveDatalog as follows (see EvaluatorTests.cs):
// Rules
var r0 = new Rule(new Atom("ancestor", new Variable("x"), new Variable("y")),
new Atom("parent", new Variable("x"), new Variable("y")));
var r1 = new Rule(new Atom("ancestor", new Variable("x"), new Variable("y")),
new Atom("ancestor", new Variable("x"), new Variable("z")),
new Atom("parent", new Variable("z"), new Variable("y")));
var rules = new[]{r0, r1};
// Facts
var f0 = new Atom("parent", new Symbol("Homer"), new Symbol("Lisa"));
var f1 = new Atom("parent", new Symbol("Homer"), new Symbol("Bart"));
var f2 = new Atom("parent", new Symbol("Grampa"), new Symbol("Homer"));
var facts = new[]{f0, f1, f2};
// Query
var q = new Atom("ancestor", new Variable("x"), new Symbol("Bart"));
// Run
var result = facts.Query(q, rules);Public domain (see UNLICENSE.)
- The Essence of Datalog in Mistral Contrastin's blog.