A B C D ... X Y Z;
a b c ... x y z;
0 1 2 3 4 5 6 7 8 9;
! " # $ % & ' ( ) = - ~ ^ \ | { } [ ] _ ` @ + ; * < > , . ? /
Gli atomi possono essere di due tipi:
_" inserito
nel corpo di un atomo per migliorarne la leggibilità.
Esempio:
tavolo "Tavolo" tavolo_di_legno a113
:- ?-
Gli interi sono utilizzati per rappresentare numeri; sono costituiti da sole cifre e non possono contenere il punto decimale.
_" che è chiamato "indifferenza".
legge(giovanni,libro).
dove il predicato "legge" viene detto funtore e gli argomenti "giovanni"
e "libro" sono chiamati componenti. Una struttura mostra chiaramente
che il Prolog è basato sulla logica dei predicati.
[a, b, [c, d]]è una lista non vuota; [ ]è una lista vuota.
In una lista è possibile individuare due parti strutturalmente
significative: la testa e la coda. La testa di una lista è il primo
elemento della lista stessa; la coda è sempre una lista ed è quello
che rimane alla lista originaria dopo aver tolto la testa. La coda può
anche essere la lista vuota. La notazione per rappresentare la
distinzione fra testa e coda è una barretta verticale: [a|b].
Le operazioni più comuni sulle liste sono le seguenti:
membro(X,L)");
conc(L1,L2,L3)"
dove L1 e L2 sono due liste e L3
è la loro concatenazione);
permutazione(A,P)").
Definire una semantica procedurale per un linguaggio di programmazione significa definire una macchina astratta (cioè un modello astratto del programma) e definire come l'esecuzione delle varie istruzioni del linguaggio viene condotta su tale macchina. Il significato di un programma è definito dal comportamento della macchina astratta per effetto della esecuzione del programma, cioè dalla sequenza di stati che la macchina assume.
Un esempio per capire la differenza dei due significati è il seguente:
Data la clausola:
P :- Q, R.
Pè vero seQeRsono veri;
per risolvere il problemaP, prima risolvi il sottoproblemaQe poi risolvi il sottoproblemaR.
Il significato dichiarativo di un programma Prolog definisce se un dato obiettivo è vero rispetto a un dato programma e, in caso affermativo, per quali istanziazioni di variabili esso risulti vero.
Questa definizione è incentrata sul concetto di verità, equivalente a quello di conseguenza logica. Infatti dal punto di vista della dimostrazione di teoremi, l'interesse è quello di dimostrare la conseguenza logica, ma dal punto di vista della programmazione si è molto più interessati ai valori a cui vengono istanziate le variabili presenti nell'obiettivo; questi valori costituiscono infatti il risultato ottenuto in seguito all'esecuzione del programma.
Questa visione è tuttavia molto riduttiva; molti programmi possono infatti essere capiti solo in modo procedurale a causa della presenza di componenti non logiche che inquinano la corrispondenza fra linguaggio e logica formale, ma che portano molti vantaggi dal punto di vista pratico. Per questo si parla di "Prolog puro" e "Prolog impuro".
Il procedimento utilizzato per ottenere i valori cui istanziare le variabili presenti nel programma è il Principio di risoluzione.
Per il teorema:
P Æ G S { G } è inconsistente,
se G è l'obiettivo " ?- B1, ..., Bn." con le variabili y1, ..., yn, mostrare che il programma P {G} è inconsistente è lo stesso che mostrare che y1, ..., yn (B1, ..., Bn) è conseguenza logica di P dunque che G è vero rispetto a P.
L'obiettivo principale di un sistema di programmazione logica è dunque quello di calcolare valori. Introduciamo un importante concetto, quello di risposta corretta ottenuta per sostituzione che fornisce una comprensione dichiarativa del risultato che si desidera ottenere da un programma e da un obiettivo.
Diamo la definizione di risposta calcolata ottenuta per sostituzione definita mediante l'impiego della risoluzione diretta.
"se un atomo chiusoSecondo questa assunzione il mondo è chiuso nel senso che ogni cosa che esiste si trova nel programma o può venire derivata da esso. Di conseguenza se qualcosa non si trova nel programma, allora essa non è vera ed è vera la sua negazione.Anon è conseguenza logica di un programma, allora si inferiscenot A".
La regola di negazione come fallimento è definita nel seguente modo:
"dato il predicatonot(Obiettivo), seObiettivoha successo, alloranot(Obiettivo)fallisce, altrimentinot(Obiettivo)ha successo".
In Prolog:
true è un obiettivo che ha sempre successo.
Inoltre per esprimere programmi che vogliono affermare qualcosa ed
escludere qualcos'altro si può utilizzare la combinazione dei due
predicati "cut" e "fail", ma in genere è preferibile in casi del genere
utilizzare il predicato unario not tale che:
not è un costrutto che offre vantaggi rispetto al predicato cut;
infatti il programma diventa più leggibile e la formulazione è più
naturale.
Esempio.
Maria ama tutte le piante tranne quelle carnivore, diventa:ama (maria, X) :- pianta (X), not_pianta_carnivora (X).
cut e
il metodo di ricerca in profondità che segue un ordine fisso di analisi delle clausole.
La regola di ricerca utilizzata dal Prolog combina la selezione della chiamata procedurale più a sinistra con la ricerca in profondità.
Una pila è una struttura dati i cui elementi sono in ordine uno sopra l'altro e a cui è possibile accedere attraverso due operazioni che permettono di inserire un elemento in cima alla pila (push) oppure estrarre l'elemento che è in cima alla pila (pop).
Un'istanza della pila di obiettivi rappresenta il ramo che si sta considerando; il calcolo diventa perciò una sequenza intervallata di operazioni push e pop sulla pila.
Una operazione push si ha quando la chiamata procedurale selezionata nel primo obiettivo della pila viene unificata con successo con la testa di una clausola del programma. Il risultato viene inserito nella pila.
Una operazione pop si ha quando non ci sono più clausole nel programma la cui testa si possa unificare con la chiamata procedurale del primo obiettivo della pila. Questo obiettivo viene rimosso mediante una operazione pop e si prende in considerazione il nuovo primo obiettivo della pila.
La ricerca in profondità può essere vista come una regola che specifica in che ordine debbano essere esaminate le clausole del programma. Negli ambienti standard Prolog l'ordine delle clausole è fisso; questo facilita l'implementazione, ma ha lo svantaggio che ad ogni esecuzione del programma le clausole vengono analizzate sempre nello stesso ordine. Per gli alberi infiniti è meglio una regola di ricerca che utilizzi una ricerca in ampiezza, ma questa ha lo svantaggio di essere poco compatibile con una implementazione efficiente.
Il metodo di ricerca in profondità consente di ottenere vantaggi dal punto di vista pratico di efficienza del programma, ma costituisce una forzatura del principio di risoluzione che comporta la perdita di certezza di risposta anche quando la risposta ci sarebbe. Questa è la ragione per cui comunemente si preferisce considerare il Prolog un linguaggio di programmazione piuttosto che un dimostratore di teoremi.
P (a,c)
{a/X}
{c/Z}
P (a,Y), (Y,c)
{b/Y}
P ( b,c)
{b/X}
{c/Y}
P {G} ha una refutazione che
utilizza tutti i fatti e tutte le regole P (c,b)
{b/X}
{c/Y}
P (c,b)
P (a, c)
{a/X}
{c/Z}
P (a, Y), P (Y, c)
{b/Y}
P (b, c)
{b/X}
{c/Z}
P (b, Y1), P (Y1, c)
{c/X}
{Y1/Z}
P (b, Y2), P (Y2, Y1), P (Y1, c)
.
(il risolvente diventa sempre piu' grande all'infinito)
Procedendo con la regola o strategia di ricerca del Prolog non si
troverà mai una refutazione; questo è dovuto al fatto che le regole
del programma P hanno una testa del tutto generale e possono unificarsi
con qualsiasi sottobiettivo. Il Prolog procedendo sempre "dall'alto in
basso" secondo la strategia di ricerca in profondità, non arriverà mai
a considerare la seconda delle due regole cosa indispensabile ai fini
della refutazione.
cut
usato congiuntamente al predicato predefinito "fail".
Il fail è un predicato che fallisce sempre forzando il backtracking che sarà alterato dalla presenza del cut. L'uso congiunto del cut e del fail serve per tradurre in Prolog definizioni che contengono delle esclusioni.
Per esempio, la frase
"Maria ama tutte le piante tranne quelle carnivore",può essere tradotta in:
ama(maria,X) :-
pianta_carnivora(X), !, fail.
ama(maria,X) :-
pianta(X).