The goal of this project is to explore how to write a minimal set of features to allow declarative programming in Python.
The code is loosely based on Prolog, however:
- The data structures used are dicts/tuples/primitive rather than replicating Prolog's functor & term.
- Likewise Python's native star notation is used to indicate that a Variable is assigned to many elements of a list.
The success of this project is measured by the number of the 99 problems actually solved to keep the code focussed on delivering features and not bike-shedding
This code is experimental and incomplete. Do not use it in your work or school! If you wish to use a serious, well tested declarative tool in Python then try the excellent pyDatalog.
- Free software: MIT license
- Documentation: https://inference-logic.readthedocs.io.
The Hello-World of declarative programming is an ancestry query which illustrates the key ideas:
from inference_logic import Variable, Rule, search
X, Y, Z, C, P = Variable.factory("X", "Y", "Z", "C", "P")
db = [
dict(parent="Abe", child="Homer"),
dict(parent="Homer", child="Lisa"),
dict(parent="Homer", child="Bart"),
dict(parent="Homer", child="Maggie"),
Rule(dict(ancestor=X, descendant=Z), dict(parent=X, child=Z)),
Rule(
dict(ancestor=X, descendant=Z),
dict(parent=X, child=Y),
dict(ancestor=Y, descendant=Z),
),
]
query = dict(ancestor=P, descendant=C)
results = search(db, query)
assert next(results) == {C: "Lisa", P: "Abe"}
assert next(results) == {C: "Bart", P: "Abe"}
assert next(results) == {C: "Maggie", P: "Abe"}
assert next(results) == {C: "Homer", P: "Abe"}
assert next(results) == {C: "Lisa", P: "Homer"}
assert next(results) == {C: "Bart", P: "Homer"}
assert next(results) == {C: "Maggie", P: "Homer"}
This is similar to SQL where we have:
- A database which is a list of:
- Things that are true by construction: Tables
- Truths that are inferred: Views
- you can query the database with a statement. The engine will then respond with a list all values for which your query is true.
Here the "database" is a list of:
- Facts which are Python dicts, tuples and primitives (i.e. JSON), this is analogous to a record in table in SQL.
- Rules whose first argument is true if subsequent arguments are all true, this is analogous to a View in SQL.
- The database can then be queried with a statement. The response will be a list of values that satisfy the query.
This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.
This was originally inspired by py4fun some of this code here comes directly from this project.
Thank you to kclaurelie for helping to solve the fundamental problem that had been bugging me for months!