Esercizio - Prolog - cut e negazione come fallimento (laboratorio 4)
In questa pagina 4
Testo (laboratorio 4, Prolog, corso di Intelligenza Artificiale, Ing. dell'Informazione UniPD). Le soluzioni del corso non sono disponibili: i punti sono risolti a mano e verificati con un interprete Prolog scritto in Python. Teoria in Prolog - fatti, regole, ricorsione, liste e cutProlog come logica del primo ordine ristretta alle clausole di Horn: fatti, regole, query, motore di inferenza (backward chaining in profondità con backtracking, ordine delle clausole), termini, unificazione e occur check, aritmetica con is, ricorsione, liste e operatore barra, length e append, cut verde e rosso, cut e fail, negazione come fallimento.Prolog - fatti, regole, ricorsione, liste e cut →.
Programma A (senza cut):
antibodies_owner(maria).
dance(linda).
sing(linda).
sing(gianni).
noproblems(vittorio).
healthy(X) :- happy(X).
healthy(X) :- antibodies_owner(X).
happy(X) :- sing(X), dance(X).
happy(X) :- noproblems(X).Programma B: come A ma con la clausola happy(X) :- sing(X), !, dance(X).
Programma C (uccelli): bird(nightingale)., bird(blackbird)., penguin(king_penguin)., ostrich(camelus_ostrich)., e
fly(X) :- penguin(X), !, fail., fly(X) :- ostrich(X), !, fail., fly(X) :- bird(X).
Programma D: fly(X) :- bird(X), not(penguin(X)), not(ostrich(X)). con gli stessi fatti.
- Elencare le risposte di
?- healthy(X).nel programma A e nel B. Perché Vittorio non è sano nel B? Cosa risponde?- healthy(vittorio).nel B? - Dire se il cut è verde o rosso in:
min(X,Y,X) :- X=<Y, !.emin(X,Y,Y) :- Y<X, !.; poi inmin2(X,Y,X) :- X=<Y, !.emin2(X,Y,Y).Provaremin2(3,5,5). - Programma C: valutare
fly(blackbird),fly(king_penguin),fly(camelus_ostrich),fly(X)e spiegare l'ultima. Cosa cambia se si tolgono i cut? - Programma D: stesse query. Dire perché
notva dopobird(X).
Punto 1: Vittorio e il cut
Programma A (verificato): X = linda ; X = vittorio ; X = maria. Ordine di esecuzione di healthy(X):
- Clausola 1:
happy(X). Clausola 1 dihappy:sing(X), dance(X).sing(X)dà ,dance(linda)riesce: linda. - Ritorno:
sing(X)dà ,dance(gianni)fallisce. - Clausola 2 di
happy:noproblems(X)dà : vittorio. - Clausola 2 di
healthy:antibodies_owner(X)dà : maria.
Programma B, con happy(X) :- sing(X), !, dance(X).: risposte X = linda ; X = maria. Esecuzione:
healthyclausola 1,happyclausola 1:sing(X)dà ; si esegue!;dance(linda)riesce: linda.- Al ritorno il cut ha eliminato le alternative: non si prova
sing(gianni)e non si prova la clausola 2 dihappy(noproblems(vittorio)).happy(X)è esaurito. - Clausola 2 di
healthy:antibodies_owner(X)dà maria.
Vittorio non compare perché la sua unica via per essere sano, happy(vittorio) :- noproblems(vittorio), è la clausola 2 di happy, scartata dal cut quando ha superato sing.
?- healthy(vittorio). nel B risponde true: con già legata, sing(vittorio) fallisce prima di raggiungere il cut, quindi non si impegna nulla e si prova la clausola 2 di happy, che riesce. È un cut rosso: cambia il significato, e i risultati dipendono da come si interroga il programma (healthy(X) e healthy(vittorio) non sono coerenti), cioè il programma non è reversibile.
Punto 2: cut verde o rosso
min con due cut. Le condizioni X=<Y e Y<X si escludono a vicenda. Senza i cut le soluzioni sono le stesse: il cut serve solo a non provare la seconda clausola dopo il successo della prima. Cut verde. Verifiche: min(3,5,M) dà ; min(5,3,M) dà ; min(4,4,M) dà (solo la prima clausola, perché è falso).
min2: min2(X,Y,X) :- X=<Y, !. e min2(X,Y,Y). La seconda clausola non ha condizione e conta sul cut per essere raggiunta solo quando . Cut rosso: togliendo il cut min2(3,5,M) darebbe e anche (sbagliato). Anche con il cut:
min2(3,5,M)dà ,min2(5,3,M)dà : giusto;min2(3,5,5)rispondetrue, sbagliato. Con il terzo argomento già istanziato a la testa della clausola 1 (min2(X,Y,X)) non si unifica ( e in contrasto), il cut non viene raggiunto e la clausola 2, senza condizioni, riesce.
Si corregge scrivendo la condizione nella seconda clausola (Y<X, come in min) oppure unificando l'uscita dopo il cut: min3(X,Y,Z) :- X=<Y, !, Z = X. e min3(_,Y,Y). Ora il cut viene raggiunto anche con Z istanziato: min3(3,5,5) e min3(5,3,5) sono false, min3(3,5,M) e min3(5,3,M) danno (verificato).
Punto 3: cut e fail
Programma C (verificato):
| Query | Risposta | Spiegazione |
|---|---|---|
fly(blackbird) |
true | penguin(blackbird) e ostrich(blackbird) falliscono, la clausola 3 riesce con bird(blackbird) |
fly(king_penguin) |
false | clausola 1: penguin(king_penguin) riesce, il cut impegna, fail fa fallire fly, senza provare le clausole 2 e 3 |
fly(camelus_ostrich) |
false | clausola 1 fallisce (non è un pinguino), clausola 2: ostrich riesce, cut, fail |
fly(X) |
false | (primo fatto di penguin), cut, fail: le clausole 2 e 3 non si provano, quindi si perde nightingale |
L'ultimo caso è l'attenzione delle slide: con la variabile libera il primo legame è il pinguino e il cut-fail chiude tutto, quindi fly(X) risponde false benché volino nightingale e blackbird. Il predicato funziona solo con l'argomento istanziato.
Nota sul programma delle slide: king_penguin e camelus_ostrich non sono dichiarati bird: fly(king_penguin) sarebbe false comunque. Con anche bird(king_penguin). e bird(camelus_ostrich). le risposte della tabella restano le stesse (verificato) e a bloccare i pinguini sono davvero cut e fail; senza i cut fly(king_penguin) darebbe true, perché fail fallirebbe sulla clausola 1 ma poi si proverebbe la 3.
Punto 4: negazione come fallimento
Programma D (verificato, anche con bird per i pinguini):
| Query | Risposta | Spiegazione |
|---|---|---|
fly(blackbird) |
true | bird riesce; not(penguin(blackbird)) e not(ostrich(blackbird)) riescono perché penguin(blackbird) e ostrich(blackbird) non sono dimostrabili |
fly(king_penguin) |
false | penguin(king_penguin) è un fatto: not(...) fallisce |
fly(camelus_ostrich) |
false | not(ostrich(...)) fallisce |
fly(X) |
X = nightingale ; X = blackbird |
bird(X) lega a ogni uccello, e il not filtra: i pinguini e gli struzzi sono scartati |
La query aperta ora funziona, a differenza del programma C: il filtro non impegna con il cut.
Perché not dopo bird(X). Con fly(X) :- not(penguin(X)), bird(X). e i fatti bird(nightingale). bird(king_penguin). penguin(king_penguin). la query fly(X) risponde false: not(penguin(X)) con X libera prova penguin(X), che riesce (), quindi il not fallisce prima che bird(X) assegni un valore. Con bird(X), not(penguin(X)) (verificato) la risposta è X = nightingale. Regola: i goal che generano valori vanno prima, quelli che filtrano (not, confronti, \=) dopo.
not non è la negazione logica: dice "non riesco a dimostrare", sotto l'ipotesi del mondo chiuso (ciò che non è nel programma è falso). Per fly(opus), con opus mai nominato, bird(opus) fallisce e fly(opus) è false anche se in realtà non si sa nulla di lui.
Versione ripasso
- Vittorio: programma A (senza cut) dà
linda ; vittorio ; maria. Programma B (happy(X) :- sing(X), !, dance(X).) dàlinda ; maria: il cut dopo eliminasing(gianni)e la clausola 2 dihappy(noproblems(vittorio)).healthy(vittorio)nel B è però true (sing(vittorio)fallisce prima del cut). Cut rosso, programma non reversibile. - min:
min(X,Y,X) :- X=<Y, !.emin(X,Y,Y) :- Y<X, !.cut verde (condizioni già esclusive).min2(X,Y,X) :- X=<Y, !.emin2(X,Y,Y).cut rosso:min2(3,5,5)risponde true (sbagliato). Si corregge conY<Xoppure conmin3(X,Y,Z) :- X=<Y, !, Z = X.emin3(_,Y,Y).(uscita dopo il cut). - Cut e fail (programma C):
fly(blackbird)true,fly(king_penguin)efly(camelus_ostrich)false,fly(X)false (primo legameking_penguin, cut, fail:nightingalemai provato). Funziona solo con l'argomento istanziato. Nelle slide i pinguini non sonobird: aggiungendoli le risposte non cambiano. Senza i cutfly(king_penguin)diventerebbe true. - Negazione (programma D):
fly(X) :- bird(X), not(penguin(X)), not(ostrich(X)).dàfly(X):nightingale ; blackbird.not(G)riesce seGnon è dimostrabile (mondo chiuso).notdopo il generatore:not(penguin(X)), bird(X)dà false conXlibera. - Passi del programma B per
healthy(X):sing(X)dà ,!,dance(linda)riesce: linda. Il cut ha toltosing(gianni)ehappy(X) :- noproblems(X).; restaantibodies_owner(maria): maria. - Tabella di
min2:min2(3,5,M)dà ;min2(5,3,M)dà ;min2(3,5,5)true (sbagliato: la testa non si unifica, il cut non si raggiunge, la seconda clausola non ha condizione). Senza cutmin2(3,5,M)darebbe anche . - Perché
fly(X)fallisce con cut-fail e funziona connot: il cut-fail impegna sul primo pinguino;bird(X)genera uccelli enotli filtra senza impegnare. - Errori tipici: cut rosso involontario;
fly(X)con cut-fail su variabile libera;notsu variabile libera; scambiarenotcon la negazione logica.