A Tiny Prolog in Python
Contents
1. Definitions
2. Building a Tiny Prolog in Python 1. Variables
2. Predicates
3. Goals
4. Lists
5. Environment
6. Unification
7. Resolution
3. References 1. Artifacts
Important: Pyodide takes time to initialize. Initialization completion is indicated by a red border around Run all button.
Run all
TLDR; This tutorial is an implementation of a toy prolog interpreter in Python. It is based on an earlier implementationhere that has since disappeared.
Definitions
For this post, we use the following terms:
• A fact is a statement that is unconditionally true. For example, man(adam). asserts that Adam is a man.
• A rule is a conditional statement that defines when something holds. For example, father(P, C) :- man(P), parent(P, C). states that P is a father of C if P is a man and P is a parent of C.
• A query (or goal sequence) is a question posed to the system, asking for values of variables that make a statement true. For example, ?- father(X, Y). asks for all pairs (X, Y) that satisfy the relation.
• A variable is a placeholder for an unknown value. During execution, variables can be bound to constants or other variables.
• A constant is a literal value such as a number or string (e.g., "adam", 42).
• A predicate is a named relation, such as man/1 or parent/2. Applying a predicate to arguments produces a goal.
• A goal (or predicate term) is an instance of a predicate applied to arguments, such as man(adam). Prolog execution is the process of trying to satisfy goals.
• A clause is a definition consisting of a head and a body. The head is a goal, and the body is a sequence of subgoals that must hold for the head to be true.
• An environment is a mapping from variables to values (or other variables) that records substitutions created during unification.
• Unification is the process of making two terms equal by finding consistent bindings for variables. For example, unifying X with "adam" binds X to "adam".
• Dereferencing means following variable bindings in the environment until reaching either a concrete value or an unbound variable.
• Resolution is the inference mechanism of Prolog: repeatedly trying to satisfy goals by unifying them with predicate definitions and recursively solving subgoals.
• Backtracking is the process of undoing variable bindings and trying alternative clauses when a goal cannot be satisfied.
Building a Tiny Prolog in Python
This implementation is based on an earlier implementation in Python2here. The effort here is to update it for Python3, and to serve as a reference for future. The explanations are partial, and will be completed at a later point.
Prolog is a language designed around first-order predicate logic 1. Instead of writing explicit algorithms, you declare facts and rules, and Prolog automatically searches for values that satisfy them. For example:
means that Adam is a man, Adam is the parent of Cain, and anyone who is both a man and a parent is a father. We will next build a very small Prolog engine in Python. Note that our implementation is very simple, and does not implement advanced concepts such as CUT or the WAM virtual machine. We next start with implementing the basic prolog concepts in Python.
Variables
In Prolog, variables stand for unknown values that the system will try to assign during computation. For example, one may query for man(X), and the X is represented by Var.
class Var: def init(self, name): self.name = name
def str(self): return '