Many implementations available, including:
- swi-prolog (
swipl
) - gnu-prolog (
gprolog
) - yap
- Scryer Prolog
Heart of prolog is the concept of unification.
Each command needs to be appended with a .
to let the interpreter know we are done typing.
# Two atoms
| ?- a = a.
yes
# Still two atoms
| ?- a = 'a'.
yes
# atom and an integer
| ?- x = 2.
no
# atom and a variable (unifying value for the variable is also printed)
| ?- X = 2.
X = 2
yes
# Variable unify with anything. In this case, both X and Y should be equal
| ?- X = Y.
Y = X
yes
—
$ swiplWelcome to SWI-Prolog (threaded, 64 bits, version 8.2.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- [user].
: male(albert).
|: ^D% user://1 compiled 0.02 sec, 1 clauses
|true.
?- male(albert).
true.
General
- Comments:
- Single line:
%
- Multi-line:
/* <comment> */
- Single line:
- Names of (quantified?) variables got to be upper case.
- Constant names start with lower case letter.
- or are enclosed in single quotes.
- File extension:
.pl
Operators
=
: identical with unification (ie, equivalent upon eval?)==
: identical (syntactically, I guess)\=
: not identical upon unification (ie, not unifiable)\==
: not identical (syntactically)\+
: negation;
: disjunction (ie, OR),
: AND:-
IFnot
: NOT=<
: <=>=
: >=!
: 'cut' operator- Stops backtracking.
//2
: (binary) division-/1
: unary minus-/2
: binary minus=:=
: evaluate both LHS and RHS, then evaluate resultsis
: evaluate only RHS, then eval result
if-else
if cond true-case else false-case
is written in prolog like
-> true-case; false-case
cond
#+end src
** Lists
- Syntax is like that of python lists
+ Eg: ~[1,2,3]~
- ~member(E, L)~: check if ~E~ is an element of list ~L~
-tail notation
*** head
#+begin_src[H | T]
- Separate a list into two parts.
- Head need not be a single element, apparently and can be a sub-list.
- Useful for splitting for unification (and for pattern matching?)
From http://www.cs.trincoll.edu/~ram/cpsc352/notes/prolog/search.html:
Suppose we have a list [0,1,2,3]
.
Pattern | H | T |
---|---|---|
[X │ Y] |
X=0 |
Y=[1,2,3] |
[X,Y │ Z] |
X=0, Y=1 |
Z=[2,3] |
[X,Y,Z │ W] |
X=0, Y=1, Z=2 |
W=[3] |
[X,Y,Z,W │ V] |
X=0, Y=1, Z=2, W=3 |
V=[] |
[X,Y,Z,Y] |
Unification error | Y1=1 and Y2=3 |
[X,Y,Z,W,V │ U] |
Unification error | List length is lesser |
An implementation of member(E, L)
member(X, [X|_]).
member(X, [_|L]) :- member(X, L).
Running:
$ swipl
?- [user].
|: member(X, [X|_]).
|: member(X, [_|L]) :- member(X, L).
|: ^D% user://1 compiled 0.02 sec, 2 clauses
true.
?- member(3, [3]).
true .
?- member(3, []).
false.
?- member(3, [1,2,3,4,5]).
true .
Examples
Natural numbers
% https://stackoverflow.com/questions/42965186/how-to-tell-prolog-that-n-is-a-natural-number-if-n-1-is-a-natural-number
0).
natural(N) :- M is N-1, M >=0, natural(M). natural(
Running (swi-prolog):
?- [user].
: natural(0).
|: natural(N) :- M is N-1, M >=0, natural(M).
|: ^D% user://2 compiled 0.00 sec, 2 clauses
|true.
?- natural(3).
true .
?- natural(-2).
false.
Peano representation:
0).
nat(.
nat(z)N)) :- nat(N). nat(s(
Check if a number is within a range
range(ST,EN,N) :- N>=ST, N=<EN.
?- range(0,5,0).
true.
?- range(0,5,-1).
false.
TODO list append
(This seems to be predefined in prolog.)
append(l1,l2,l3) means l3=l1++l2.
append(L, [], L).
append([H1|T1], l2, l3) :- append(
?- append([a,b], [c], X).
X = [a, b, c].
?- append([a], X, [a,b,c]).
X = [b, c].
Who gossips
Given:
gossips(X)
:X
gossipsknows(X, S)
:X
knows the secretS
friend(X, Y)
:X
is a friend ofY
Find if X
gets to know secret S
:
gets-to-know(X, S) :- knows(X, S)
gets-to-know(X, S) :- friend(X, Y), gossips(Y), gets-to-know(Y, S)
clp (Constraint Logic Programming)
- clpfd: https://github.com/Anniepoo/swiplclpfd/blob/master/clpfd.adoc
- clpb: https://www.swi-prolog.org/pldoc/man?section=clpb
—
Operators
e * e | logical AND |
e + e | logical OR |
e # e | XOR |
var ^ e | ∃ var, e |
e =:= e | equality (iff) |
e =\= e | not equal |
—
?- use_module(library(clpb)).
true.
?- sat(A =:= ~A*B).
A = B, B = 0.
?- sat(X * ~X).
false.
?- sat(a =:= ~b), sat(b =:= ~(a#c))
% ?- use_module(library(clpfd)).
% true.
—
Use labeling
to show possible assignment:
?- sat(card([1,3], [A, B, C])).
sat(A=\=B#C).
?- sat(card([1,3], [A, B, C])), labeling([A, B, C]).
A = B, B = 0,
C = 1 .
eDSLs in prolog
https://www.metalevel.at/acomip/
op(precedence, type, name)
- type
- xfx, xfy, yfx (infix)
- fx, fy (prefix)
- xf, yf (postfix)
- precedence: lesser the value, higher the precedence
Definite clause grammars
F//N
means a non-terminalF
withN
arguments
DCG corresponding to a regex a*
:
?- [user].
|: as --> [].
|: as --> [a], as.
|: ^D% user://1 compiled 0.00 sec, 2 clauses
true.
?- phrase(as, [a, X, a]).
X = a.
?- set_prolog_flag(double_quotes, chars).
true.
?- phrase(as, "aaa").
true.
?- phrase(as, "abc").
false.
Here as//0
is a non-terminal accepting 0
arguments.
All strings with only 'X'
and 'Y'
with length n
.
?- [user].
|: xy --> [].
|: xy --> ("X" | "Y"), xy.
|: ^D% user://2 compiled 0.00 sec, 2 clauses
true.
% Keep hitting Space to enumerate.
% Enter key will stop it.
?- phrase(xy, Ls).
Ls = [] ;
Ls = ['X'] ;
Ls = ['X', 'X'] ;
Ls = ['X', 'X', 'X'] ;
Ls = ['X', 'X', 'X', 'X'] ;
% This is an 'unfair enumeration.
% To make it more fair, use another constraint.
?- length(Ls, _), phrase(xy, Ls).
Ls = [] ;
Ls = ['X'] ;
Ls = ['Y'] ;
Ls = ['X', 'X'] ;
Ls = ['X', 'Y'] ;
Ls = ['Y', 'X'] ;
Ls = ['Y', 'Y'] ;
Ls = ['X', 'X', 'X'] ;
% This will print possibilities lengthwise.
% Original goal. Sequences limited to length n
?- length(Ls, 3), phrase(xy, Ls).
Ls = ['X', 'X', 'X'] ;
Ls = ['X', 'X', 'Y'] ;
Ls = ['X', 'Y', 'X'] ;
Ls = ['X', 'Y', 'Y'] ;
Ls = ['Y', 'X', 'X'] ;
Ls = ['Y', 'X', 'Y'] ;
Ls = ['Y', 'Y', 'X'] ;
Ls = ['Y', 'Y', 'Y'] ;
false.
See:
- https://www.metalevel.at/prolog/dcg
- https://www.swi-prolog.org/pldoc/man?section=basics
- https://youtu.be/CvLsVfq6cks?list=PLEvH6T-1oh75UagVp5BqeOVageBljdmaC
Strings
A string is a list of characters.
Use set_prolog_flag(double_quotes, chars).
to use double quote notation for strings.
?- set_prolog_flag(double_quotes, chars).
true.
?- "a" = "a".
true.
Misc
- Constraint Handling Rules (CHR): https://www.swi-prolog.org/pldoc/man?section=chr-intro
- I tried this only on swi-prolog.
- Original prolog system: Marseilles Prolog ʳ