This is a mini-module for experimenting basic datalog within Python environment. Features include:
- mini-engine with backward-chain algorithm for inference process
metaclass
frontend for easy-writing facts and rules of KB
A KB can be defined like with ease in prolog-like style:
from yalog import var, kbmeta
class kb(metaclass=kbmeta):
# Facts
father('ooopa', 'opa')
father('opa', 'ucl')
father('opa', 'pa')
mother('oma', 'pa')
father('pa', 'a')
father('pa', 'b')
mother('mum', 'a')
mother('mum', 'b')
# Definite clauses
grandfather(X, Y) <= [
father(X, Z), father(Z, Y)
]
parent(X, Y) <= father(X, Y)
parent(X, Y) <= mother(X, Y)
sibling(X, Y) <= [
parent(Z, X) , parent(Z, Y) , (X != Y)
]
ancester(X, Y) <= father(X, Y)
ancester(X, Y) <= [
father(X, Z), ancester(Z, Y)
]
and goals can be queried by simply accessing attributes kb
with corresponding rule names:
from yalog import var
q = kb.sibling(var.X, var.Y)
>>> list(q)
[{x: 'ucl', y: 'pa'},
{x: 'pa', y: 'ucl'},
{x: 'a', y: 'b'},
{x: 'b', y: 'a'},
{x: 'a', y: 'b'},
{x: 'b', y: 'a'}]
q = kb.ancester(var.W, 'a')
>>> list(q)
[{W: 'pa'}, {W: 'ooopa'}, {W: 'opa'}]
note the repetition in query results is valid due to the alternative rules for parent
during inferencing sibling
.
Equality and non-equality are supported by extending the back-chaining-OR
function.
- Support
NOT
expressions in definite clauses.