Many implementations available, including:
swipl
)gprolog
)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.
%
/* <comment> */
.pl
=
: 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
:-
IF
not
: NOT
=<
: <=
>=
: >=
!
: 'cut' operator
//2
: (binary) division
-/1
: unary minus
-/2
: binary minus
=:=
: evaluate both LHS and RHS, then evaluate results
is
: evaluate only RHS, then eval result
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]
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 |
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 .
% 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(
range(ST,EN,N) :- N>=ST, N=<EN.
?- range(0,5,0).
true.
?- range(0,5,-1).
false.
(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].
Given:
gossips(X)
: X
gossipsknows(X, S)
: X
knows the secret S
friend(X, Y)
: X
is a friend of Y
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)
—
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 .
https://www.metalevel.at/acomip/
op(precedence, type, name)
F//N
means a non-terminal F
with N
argumentsDCG 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:
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.