prolog


Many implementations available, including:

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

$ swipl
Welcome 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

Operators

if-else

if cond true-case else false-case is written in prolog like

cond -> true-case; false-case
#+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~

*** head-tail notation
#+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

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
natural(0).
natural(N) :- M is N-1, M >=0, natural(M).

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:

nat(0).
nat(z).
nat(s(N)) :- nat(N).

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:

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)

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)

Definite clause grammars

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:

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