This is an old revision of the document!
TODO
Scopul laboratorului:
- TODO
- TODO
Cut
Green cut
Red cut
Negation as failure
Colectare rezultate
Fie următoarea bază de cunoștiințe genealogice:
% File: norse.pl father(buri, borr). father(borr, odin). father(borr, vili). father(borr, ve). father(odin, thor). father(odin, baldr). mother(bestla, odin). mother(bestla, vili). mother(bestla, ve). mother(jorth, thor). mother(frigg, baldr).
Putem defini ușor un predicat pentru a determina relația părinte-copil:
parent(P, C) :- mother(P, C). parent(P, C) :- father(P, C).
După cum ați observat până acum, predicatul definit e versatil; poate fi folosit pentru a verifica o relație, pentru a determina părinții unei persoane, pentru a determina copiii unei persoane, sau pentru a genera toate perechile părinte-copil din baza de cunoștiințe:
?- parent(odin, thor). true. ?- parent(buri, odin). false. ?- parent(borr, C). C = odin ; C = vili ; C = ve. ?-
Pentru ultima interogare, există mai multe posibilități de unificare a variabilei C
, iar prolog ni le oferă pe rând (introducând ;
interactiv, primim următoarea soluție). Uneori, este util să putem colecta toate aceste soluții într-o listă pe care putem, ulterior, face alte procesări. În continuare, vom studia trei predicate pentru a realiza acest lucru.
findall
findall/3 este un predicat care primește un tipar de rezultate, un goal de demonstrat și o listă de ieșire care va conține toate rezultatele construite pe baza tiparului, pentru care goal-ul primit este adevărat. Cel mai simplu tipar util este o singură variabilă, care se regăsește în scopul primit.
?- findall(C, parent(borr, C), L). L = [odin, vili, ve]. ?-
Dacă nu există niciun rezultat, findall
generează o listă vidă:
?- findall(C, parent(baldr, C), L). L = []. ?-
Deasemenea primul argument poate fi un termen compus:
?- findall(child(C, borr), parent(borr, C), L). L = [child(odin, borr), child(vili, borr), child(ve, borr)]. ?-
bagof
bagof/3 este un predicat asemănător cu findall
, având aceeași semnificație a parametrilor. Diferența dintre cele două este vizibilă atunci când introducem o variabilă în goal, care nu apare în template.
?- findall(C, parent(P, C), L). L = [odin, vili, ve, thor, baldr, borr, odin, vili, ve|...]. ?-
Observăm că findall
ne întoarce o singură listă cu toate rezultatele posibile. În unele cazuri, ar fi util ca, pentru fiecare părinte P
, să primim o altă listă. Pentru asta folosim bagof
:
?- bagof(C, parent(P, C), L). P = bestla, L = [odin, vili, ve] ; P = borr, L = [odin, vili, ve] ; P = buri, L = [borr] ; P = frigg, L = [baldr] ; P = jorth, L = [thor] ; P = odin, L = [thor, baldr]. ?-
Rezultatele sunt generate în stilul clasic, necesitând ;
interactiv. Putem apoi să le colectăm folosind din nou bagof
:
?- bagof(children(P, L), bagof(C, parent(P, C), L), R). R = [children(bestla, [odin, vili, ve]), children(borr, [odin, vili, ve]), children(buri, [borr]), children(frigg, [baldr]), children(jorth, [thor]), children(odin, [thor, baldr])]. ?-
bagof
sau findall
. Goal-ul de demonstrat (bagof(C, parent(P, C), L)
) nu conține variabile “din afară”.