https://fr.wikipedia.org/wiki/Prolog
http://gecif.net/articles/linux/prolog.html#exemple1
https://www.tutorialspoint.com/prolog/index.htm
https://www.swi-prolog.org/pldoc/man?section=termrw
Présentation
Terms
Atomes
Les textes constants constituent des atomes. Un atome est ordinairement constitué d'une chaîne de lettres, nombres et traits bas (_), commençant par une lettre minuscule. Pour introduire un atome non alphanumérique, on l'entoure d'apostrophes : ainsi '+' est un atome, + un opérateur).
Nombres
Les implémentations courantes de Prolog ne distinguent pas les nombres entiers des flottants.
Chaînes de caractères
Les chaînes de caractères sont en général écrites comme une séquence de caractères entourés par des apostrophes. Elles sont souvent représentées en interne par une liste de codes ASCII.
Variables
Les variables sont indiquées en utilisant un ensemble de lettres, nombres et caractères de soulignement et commençant avec une lettre majuscule.
Termes composés
Prolog ne peut représenter des données complexes que par termes composés. Un terme composé consiste en une tête (aussi appelée foncteur), qui doit être un atome, et des paramètres sans restriction de type. Le nombre de paramètres, nommé arité du terme, est en revanche significatif. Un terme composé est identifié par sa tête et son arité, et habituellement écrit comme foncteur/arité.
Listes
Une liste n’est pas un type de données isolé, mais est définie par une construction récursive (utilisant le foncteur . d'arité 2, c'est donc au niveau de la représentation interne un terme composé):
l'atome [] est une liste vide ;
si T est une liste et H est un élément, alors le terme '.'(H, T) est une liste.
Prédicats
La programmation en Prolog est très différente de la programmation dans un langage impératif. En Prolog, on alimente une base de connaissances de faits et de règles ; il est alors possible de faire des requêtes à la base de connaissances.
L’unité de base de Prolog est le prédicat, qui est défini comme étant vrai. Un prédicat consiste en une tête et un nombre d’arguments. exemple :
chat(tom).
Prédéfinis
Quelques prédicats sont bâtis dans le langage et permettent à un programme Prolog des activités de routine (comme de l'évaluation numérique, les entrée/sortie, les fonctionnalités de l'interface graphique et généralement communiquer avec le système de l’ordinateur). Par exemple, le prédicat write peut être utilisé pour l’affichage à l’écran.
% print Bonjour
write('Bonjour').
Règles
Le second type d’instructions en Prolog est la règle. Un exemple de règle est :
lumière(on) :- interrupteur(on).
Évaluation
Quand l’interpréteur reçoit une requête, il recherche les règles (faits inclus) dont la partie gauche peut être unifiée avec la requête, et effectue cette unification avec la première règle trouvée. Par exemple ayant ce code Prolog :
frère_ou_sœur(X,Y) :- parent(Z,X), parent(Z,Y), X \= Y.
parent(X,Y) :- père(X,Y).
parent(X,Y) :- mère(X,Y).
mère(trude, sally).
père(tom, sally).
père(tom, erica).
père(mike, tom).
On peut alors questionner:
?- frère_ou_sœur(F,S).
F = sally,
S = erica ;
F = erica,
S = sally ;
false.
?- frère_ou_sœur(sally, erica).
oui.
Négation par l'échec
La négation logique pure n'existe pas en Prolog, on se repose sur la négation par l'échec, qui se note différemment suivant les implémentations de Prolog
Exécution
Prolog est un langage logique, aussi en théorie, on n'a pas à se préoccuper de la façon dont il s’exécute. Cependant il est parfois prudent de prendre en compte comment l’algorithme d’inférence agit, pour éviter qu’un programme Prolog ne dure trop longtemps.
% compter le nombre d’éléments d’une liste.
elems([],0).
elems([H|T], X) :- elems(T, Y), X is Y + 1.
pour miser X, ou j'ai cet argent d'emblée, ou sinon j'ai le crédit nécessaire.
miser(X) :- avoirargent(X), ! ; avoircrédit(X).
Syntax
% # comments
! # Opérateur d’arrêt vert. Le ! dit à l’interpréteur de ne plus chercher d’alternative
_ # récupère un résultat sans affectation, un atome qui commence par _ est équivalent
Operators
Comparison Operators
X > Y % X is greater than Y
X < Y % X is less than Y
X >= Y % X is greater than or equal to Y
X =< Y % X is less than or equal to Y
X =:= Y X == Y % the X and Y values are equal
X =\= Y X \= Y % the X and Y values are not equal
Arithmetic Operators
+ % Addition
- % Subtraction
* % Multiplication
/ % Division
** % Power
// % Integer Division
mod % Modulus
Usage
Base
consult(program). % load program named 'program.pl'
listing. % Lists all predicates defined in the calling module
listing(predicate). % List matching clauses
trace. % start trace
notrace.
nodebug.
trace(predicate). % traces program
trace(predicate/2, +fail). % Trace failures of foo/2 in any module
trace(predicate, -all). % Stop tracing predicate
List
Print elements
print_list([X|L]) :- writeln(X), print_list(L). % print each element in a new line
Examples
statement
test(A) :-
( A =:= 2 ->
write('A is 2')
; A =:= 3 ->
write('A is 3')
; write('HAhahahahaah')
).
start_w
start_w(X,[X|L]).
dce
dce([X,X|_]).
dce([X|S]):- dce(S).
belong_to
belong_to(X,[X|_]):- !.
belong_to(X,[_|L]):- belong_to(X,L).
belong_to(X,[H|L]):- X=H, !; belong_to(X,L).
ended_w
ended_w(X,[X]).
ended_w(X,[_|L]):- ended_w(X,L).
ended_w(X,[_|L]):- [X]=L, !; ended_w(X,L).
remove0
remove0(X,[X|L],L).
remove1
remove1(E,[E|L],L):- !. % set L2 = L when first element of list are E
remove1(E,[X|L],[X|L2]):- remove1(E,L,L2). % resolve & add X to L2 while unstacking
remove1(E,[E|L],L):- write('&'), writeln(L), !. % set L2 = L when first element of list are E
remove1(E,[X|L],[X|L2]):- write(L), write('-'), writeln(L2), remove1(E,L,L2), write('>'), writeln(L2).
remove1(E,[E|L],[5|L]):- write('&'), writeln(L), !. % set L2 = L when first element of list are E
remove1(E,[_|L],[1|L2]):- write(L), write('-'), writeln(L2), remove1(E,L,L2), write('>'), writeln(L2).
min in list
min_get([R],R):- !.
min_get([X,Y|L],R):-
X < Y -> min_get([X|L],R); min_get([Y|L],R).
min_get_t([],R,R):- !.
min_get_t([H|L],T,R):-
H < T -> min_get_t(L,H,R); min_get_t(L,T,R).
min_get_t([H|L],R):- min_get_t(L,H,R).
plus_petit([X],X).
plus_petit([X,Y|L],R):- X =< Y, plus_petit([X|L],R).
plus_petit([X,Y|L],R):- X > Y, plus_petit([Y|L],R).
?- numlist(0,1000000,L), time(min_get(L, 1)).
% 2,000,001 inferences, 0.775 CPU in 0.777 seconds (100% CPU, 2579609 Lips)
?- numlist(0,1000000,L), time(min_get_t(L, 1)).
% 3,000,002 inferences, 0.196 CPU in 0.197 seconds (100% CPU, 15268446 Lips)
?- numlist(0,1000000,L), time(plus_petit(L, 1)).
% 3,000,001 inferences, 5.512 CPU in 5.521 seconds (100% CPU, 544250 Lips)
factoriel
facto(0,1).
facto(1,1):- !.
facto(N,R):- N>1, N1 is N-1, facto(N1,R1), R is R1*N.
facto_t(1,R,R):- !.
facto_t(N,T,R):- N>1, N1 is N-1, R1 is T*N, facto_t(N1,R1,R).
facto_t(0,1).
facto_t(N,R):- facto_t(N,1,R).
fibonacci
get the result
fibo(1,1,1):- !.
fibo(N,R,S):-
N1 is N-1,
fibo(N1,R1,S1),
R is R1+S1,
S is R1.
fibo(N,R):-
N<2 -> R = 1;
fibo(N,R,_).
fibo_t(1,R,R,_):- !. % fibo_t(1,R,X,_):- R = X, !; !. / minus N>1
fibo_t(N,RF,R,S):-
N>1,
N1 is N-1,
R1 is R+S,
fibo_t(N1,RF,R1,R).
fibo_t(N,R):-
N<2 -> R = 1;
fibo_t(N,R,1,1).
fibo(X,1):- X<2. % simple but fat version
fibo(N,R):- N1 is N-1, N2 is N-2, fibo(N1, R1), fibo(N2, R2), R is R1+R2.
% 299,998 inferences, 3.693 CPU in 3.700 seconds (100% CPU, 81244 Lips)
?- time(fibo_t(100000, _)).
% 200,000 inferences, 0.521 CPU in 0.525 seconds (99% CPU, 383935 Lips)
get values in list
fibo_l(1,1,1,[1]):- !.
fibo_l(N,S,R,L):-
N1 is N-1,
fibo_l(N1,S1,R1,L1),
R is R1+S1,
S is R1,
L = [R|L1].
fibo_l(N,L):- fibo_l(N,_,_,L).
fibo_lt(1,L,L,_,_):- !.
fibo_lt(N,L,LT,R,S):-
N>1,
N1 is N-1,
R1 is R+S,
Lt = [R1|LT],
fibo_lt(N1,L,Lt,R1,R).
fibo_lt(N,L):- fibo_lt(N,L,[1],1,1).
?- time(fibo_l(100000, _)).
% 299,998 inferences, 3.876 CPU in 3.883 seconds (100% CPU, 77390 Lips)
?- time(fibo_lt(100000, _)).
% 299,998 inferences, 0.781 CPU in 0.783 seconds (100% CPU, 384010 Lips)
list is sorted
sort_list([],[]).
sort_list(L,R):- min_is(L,M), remove1(M, L, L2), sort_list(L2,R1), R = [M|R1].
is_sorted(L,R):- sort_list(L,LS), R == LS.