Relational programming in Python
Logic/relational programming in Python with miniKanren.
Logic programming is a general programming paradigm. This implementation however came about specifically to serve as an algorithmic core for Computer Algebra Systems in Python and for the automated generation and optimization of numeric software. Domain specific languages, code generation, and compilers have recently been a hot topic in the Scientific Python community.
kanren aims to be a low-level core for these projects.
kanren enables one to express sophisticated relations—in the form of goals—and generate values that satisfy the relations. The following code is the "Hello, world!" of logic programming; it asks for values of the logic variable
x such that
x == 5:
>>> from kanren import run, eq, membero, var, lall >>> x = var() >>> run(1, x, eq(x, 5)) (5,)
Multiple logic variables and goals can be used simultaneously. The following code asks for one list containing the values of
z such that
x == z and
z == 3:
>>> z = var() >>> run(1, [x, z], eq(x, z), eq(z, 3)) ([3, 4],)
kanren uses unification to match forms within expression trees. The following code asks for values of
x such that
(1, 2) == (1, x):
>>> run(1, x, eq((1, 2), (1, x))) (2,)
The above examples use
eq: a goal constructor that creates a goal for unification between two objects. Other goal constructors, such as
membero(item, coll), express more sophisticated relations and are often constructed from simpler ones like
eq. More specifically,
membero states that
item is a member of the collection
The following example uses
membero to ask for all values of
x, such that
x is a member of
(1, 2, 3) and
x is a member of
(2, 3, 4).
>>> run(0, x, membero(x, (1, 2, 3)), # x is a member of (1, 2, 3) membero(x, (2, 3, 4))) # x is a member of (2, 3, 4) (2, 3)
The examples above made implicit use of the goal constructors
lany, which represent goal conjunction and disjunction, respectively. Many useful relations can be expressed with
eq alone, but in
kanren it's also easy to leverage the host language and explicitly create any relation expressible in Python.
kanren stores data as facts that state relationships between terms. The following code creates a parent relationship and uses it to state facts about who is a parent of whom within the Simpsons family:
>>> from kanren import Relation, facts >>> parent = Relation() >>> facts(parent, ("Homer", "Bart"), ... ("Homer", "Lisa"), ... ("Abe", "Homer")) >>> run(1, x, parent(x, "Bart")) ('Homer',) >>> run(2, x, parent("Homer", x)) ('Lisa', 'Bart')
We can use intermediate variables for more complex queries. For instance, who is Bart's grandfather?
>>> grandparent_lv, parent_lv = var(), var() >>> run(1, grandparent_lv, parent(grandparent_lv, parent_lv), parent(parent_lv, 'Bart')) ('Abe',)
We can express the grandfather relationship as a distinct relation by creating a goal constructor:
>>> def grandparent(x, z): ... y = var() ... return lall(parent(x, y), parent(y, z)) >>> run(1, x, grandparent(x, 'Bart')) ('Abe,')
kanren provides a fully functional constraint system that allows one to restrict unification and object types:
>>> from kanren.constraints import neq, isinstanceo >>> run(0, x, ... neq(x, 1), # Not "equal" to 1 ... neq(x, 3), # Not "equal" to 3 ... membero(x, (1, 2, 3))) (2,) >>> from numbers import Integral >>> run(0, x, ... isinstanceo(x, Integral), # `x` must be of type `Integral` ... membero(x, (1.1, 2, 3.2, 4))) (2, 4)
kanren comes with support for relational graph operations suitable for basic symbolic algebra operations. See the examples in
multipledispatch and the
logical-unification library to support pattern matching on user defined types. Essentially, types that can be unified can be used with most
kanren goals. See the
logical-unification project's examples for demonstrations of how arbitrary types can be made unifiable.
pip install miniKanren
To install from source:
git clone email@example.com:pythological/kanren.git cd kanren pip install -r requirements.txt
Tests can be run with the provided
This project is a fork of
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
|Filename, size||File type||Python version||Upload date||Hashes|
|Filename, size miniKanren-0.3.5-py3-none-any.whl (23.9 kB)||File type Wheel||Python version py3||Upload date||Hashes View hashes|
|Filename, size miniKanren-0.3.5.tar.gz (38.1 kB)||File type Source||Python version None||Upload date||Hashes View hashes|
Hashes for miniKanren-0.3.5-py3-none-any.whl