Terminazione Programmi terminanti esempio decrescenza
Transcript
Terminazione Programmi terminanti esempio decrescenza
Programmi terminanti Terminazione esempio member(X, [X| _ ]). member(X, [ _ |L]) :- member(X,L). append([], L, L). append([X|L1], L2, [X|L]) :- append(L1,L2,L). ?- member(t1,t2). ha SLD finito per ogni coppia di termini t1,t2 ground. ?- append(t1,t2,t3). ha SLD finito per ogni terna di termini t1,t2,t3 ground. Un programma logico si dice terminante se, fissata una qualsiasi regola di selezione, ogni albero SLD per un goal ground è finito (ovvero ogni SLD-derivazione di un goal ground è finita). decrescenza Osserviamo che se t2 in member(t1,t2) è ground ed unifica con [_|L] allora anche L rimane associata ad un termine ground che è più "semplice" di t2. Analoga proprietà vale per t1 in append(t1,t2,t3) quando unifica con [X|L1]. Terminazione "a sinistra" esempio Un programma logico P si dice terminante-asinistra se, fissata la regola di selezione leftmost, ogni albero SLD per P che ha alla radice un goal ground è finito. quicksort([],[]). quicksort([X|L], L2) :- partition(L,X,Small, Bigs), quicksort(Small,Sord), quicksort(Bigs, Bord), append(Sord,[X|Bord],L2). Notazione. Chiamiamo LD-derivazione una derivazione SLD con regola di selezione leftmost. Nota: è una terminazione "universale" nel senso che tutte le LD-derivazioni di goal ground sono finite. ?- quicksort(t1,t2). ha SLD finito per ogni coppia di termini t1,t2 ground. E' vero? Perché? E' terminante? Che dire di partition? (non è chiamata con termini ground). partition partition([],Y,[],[]). partition([X|L],Y,[X|L1],L2):- X≤Y, partition(L,Y,L1,L2). partition([X|L],Y,L1,[X|L2]):- X>Y, partition(L,Y,L1,L2). Notiamo che se [X|L] viene legato ad un termine ground allora L è un termine ground più semplice. Se t1 è ground allora tutte le derivazioni (leftmost) per la query partition(t1,t2,t3,t4) sono finite (anche se t3 e t4 non sono ground). decrescenza e terminazione quicksort([X|L], L2) :- partition(L,X,Small, Bigs), quicksort(Small,Sord), quicksort(Bigs, Bord), append(Sord,[X|Bord],L2). Possiamo convincerci che se [X|L] viene legata ad un termine ground [t0|t1] allora tutte le derivazioni (leftmost) per quicksort([X|L],L2) sono finite. Infatti: - la chiamata a partition ha i primi due argomenti ground e quindi partition(L,X,Small, Bigs) con L legata a t1 termina, e se ha successo le variabili Small e Bigs vengono legate a termini ground più semplici di t1. cont. % decrescenza di quicksort - le due chiamate ricorsive a quicksort si applicano a termini più semplici di t1 e pertanto terminano; - inoltre la loro esecuzione lega Sord e Bord a termini ground; - pertanto l'append viene chiamata con il primo argomento ground e questo è sufficiente a garantirne la terminazione. Mappe di livello Chiamiamo mappa di livello una funzione |.| che associa ad ogni elemento della base di Herbrand (atomo ground) un naturale. |.| : HB --> N Nel definire una mappa di livello utilizziamo delle norme definite sui termini che compaiono negli atomi. Esempi | append(t1,t2,t3) | = list_lenght(t1) | pre-order(t1,t2) | = size(t1) Norme Chiamiamo norma una funzione weight che associa ad ogni termine un valore (su di un insieme ben fondato). weight : Term --> N Esempi: list_lenght: conta il numero di elementi in una lista, è 0 su termini che non sono liste. list_lenght([1,X,[[2]|Y]]) = 3 size: conta il numero di funtori in un termine size([1,X,[2|Y]]) = size([1|[X|[[2|[]]|Y]]]) = 5 Accettabilità Definizione Sia P un programma, |.| una mappa di livello e I un modello per P. P si dice accettabile rispetto a |.| ed I se - per ogni clausola c di P e per ogni istanza ground H :- A,B,C di c se I |= A allora |H| > |B| Accettabilità e terminazione-a-sinistra Teorema 1 Ogni programma accettabile è terminante-asinistra. Esempio. Il programma quicksort è accettabile e quindi è terminante-a-sinistra. esempio Sia |append(t1,t2,t3)| = list_lenght(t1) Consideriamo la query Q = append([1,2], [X,3], Z), append(Z,Y,W). Q è limitata rispetto a |.| ed il minimo modello di Herbrand di append: Siano t1 e t2 due termini ground M |= append([1,2], [t1,3], t2) solo se t2 è una lista di lunghezza 4. | append([1,2], [t1,3], t2)| ≤ 4 | append(t2, t3, t4)| ≤ 4 Interrogazioni (query) limitate Definizione Sia |.| una mappa di livello, I una interpretazione e Q una query (anche non ground). Diciamo che Q è limitata rispetto a |.| ed I se esiste un naturale k tale che - per ogni istanza ground A,B,C di Q se I|= A allora |B| ≤ k Accettabilità e query limitate Teorema 2 Sia P un programma accettabile rispetto ad una mappa di livello |.| ed un modello I, e sia Q una query bounded rispetto a |.| ed I. Allora ogni LD-derivazione di Q è finita. esempi Ogni LD-derivazione di ?- append([1,2], [X,3], Z), append(Z,Y,W). è finita. Ogni LD-derivazione di ?- append([2,X,5],Y,W). è finita. Ogni LD-derivazione di ?- quicksort([2,4,5,1], L). è finita. quicksort_dl Versione 1 quicksort_dl([],L-L). quicksort_dl([X|L], S - D ) :- partition(L,X,Small, Bigs), quicksort_dl(Small,S-[X|B]), quicksort_dl(Bigs, B-D). Versione 2 quicksort_dl([],L-L). quicksort_dl([X|L], S - D ) :- partition(L,X,Small, Bigs), quicksort_dl(Bigs, B-D), quicksort_dl(Small,S-[X|B]). esercizi Dimostrare che ogni LD-derivazione di append(X,Y,[2,4,6]) è finita. Dire se ogni LD-derivazione di quicksort(L,[2,4,6]) è finita. Dire se ogni LD-derivazione di quicksort_dl(L,[2,4,6]-[]) è finita in entrambi i programmi riportati nella diapositiva successiva.