Logica del primo ordine - unificazione, forward e backward chaining
In questa pagina 8
Argomento del corso da 9 CFU. Fonte: slide del corso di Intelligenza Artificiale, Ing. dell'Informazione UniPD. Presuppone Agenti logici e logica proposizionale - inferenza e risoluzioneAgenti basati sulla conoscenza (KB, Tell e Ask), mondo del Wumpus come banco di prova, sintassi e semantica della logica proposizionale, conseguenza logica, equivalenze, inferenza per model checking (7 simboli, 128 modelli, 3 modelli della KB) e per risoluzione (CNF, regola di risoluzione, dimostrazione per assurdo). Limite: poca espressività, da cui la logica del primo ordine.Agenti logici e logica proposizionale - inferenza e risoluzione → (CNF, risoluzione, conseguenza logica).
Dalla logica proposizionale al primo ordine
La logica proposizionale assume che il mondo contenga solo fatti. La logica del primo ordine (FOL, first-order logic) assume, come il linguaggio naturale, che contenga:
- oggetti: persone, case, numeri, teorie, colori, guerre, secoli;
- relazioni o proprietà: fratello di, più grande di, dentro, possiede, sta tra; rosso, rotondo, primo;
- funzioni (restituiscono un valore preciso): padre di, migliore amico di, uno in più di.
Elementi della sintassi:
| Elemento | Esempi |
|---|---|
| costanti (oggetti) | , |
| funzioni | , |
| variabili | |
| predicati (relazioni) | , |
| connettivi | |
| uguaglianza | |
| quantificatori |
- Termine: una costante, una variabile oppure . Indica un oggetto.
- Enunciato atomico: . Esprime un fatto che può essere vero o falso: .
- Enunciato complesso: enunciati atomici combinati con i connettivi, per esempio .
Quantificatori
è vero se è vero per ogni oggetto : è circa la congiunzione di tutte le istanze. è vero se è vero per almeno un oggetto: è circa la disgiunzione delle istanze.
Errore tipico con . Il connettivo principale con è di norma . "Tutti a Oxford sono intelligenti" è . Con , significa "tutti sono a Oxford e tutti sono intelligenti".
Errore tipico con . Il connettivo principale con è di norma . "Qualcuno non a Oxford è intelligente" è . Con , è vero anche se esiste una persona a Oxford (antecedente falso, implicazione vera a vuoto) o intelligente: dice molto meno.
Proprietà.
- equivale a (si scrive ); lo stesso per .
- non equivale a : è "c'è una persona che ama tutti", è "ognuno è amato da qualcuno".
- Dualità: ; .
Esempi di frasi per una KB:
- fratelli e sorelle sono fratelli: ;
- "Sibling" è simmetrica: ;
- la madre è il genitore femmina: ;
- un cugino di primo grado è figlio di un fratello di un genitore: .
Sostituzioni
Un agente del Wumpus con una KB in FOL percepisce puzza, brezza e luccichio al tempo : Tell(KB, Percept([Stench, Breeze, Glitter], 5)). Poi chiede Ask(KB, ∃a Action(a, 5)): la KB implica qualche azione? Sì, per esempio con la sostituzione .
Definizione (sostituzione). Una sostituzione assegna un termine a ciascuna variabile. Dato un enunciato , è il risultato di applicare a .
Esempio. e danno . Ask(KB, S) restituisce alcune o tutte le tali che .
Proposizionalizzazione
Con le sostituzioni si può ricondurre l'inferenza FOL a quella proposizionale.
Istanziazione universale (UI). Da si ricava con sostituita da un termine chiuso (senza variabili): dà , ma anche e così via. Si può applicare più volte: la nuova KB è equivalente alla vecchia.
Istanziazione esistenziale (EI). Da si ricava con sostituita da una costante di Skolem che non compare altrove nella KB: dà , con nome inventato. Si applica una volta per eliminare l'enunciato esistenziale; la nuova KB non è equivalente alla vecchia, ma è soddisfacibile se e solo se lo era la vecchia.
Se l'esistenziale sta dentro un , la costante diventa una funzione di Skolem delle variabili universali: dà , che è diverso da (la seconda dice che c'è un'unica anima gemella per tutti).
Esempio. KB: , , , con soli tre oggetti . Istanziando la prima regola in tutti i modi si ottengono enunciati ( e gli analoghi per Richard e Henry) più i fatti: i simboli proposizionali sono , , , , ecc. Si risolve come nella logica proposizionale.
Problemi.
- Genera moltissimi enunciati irrilevanti: con si producono , anche solo per provare .
- Con i simboli di funzione gli oggetti diventano infiniti: , , , ...
La soluzione è cercare direttamente la sostituzione che serve: l'unificazione.
Unificazione
Nell'esempio, per ricavare basta trovare che faccia combaciare e con e : .
Definizione (unificazione). con . Se non esiste l'unificazione fallisce.
| fallisce (variabile in comune) |
L'ultimo fallimento è fittizio: le due appartengono a enunciati diversi, ma hanno lo stesso nome. Si risolve standardizzando (standardize apart) cioè rinominando le variabili di uno dei due: con si ha . Nei calcoli si rinominano sempre le variabili di una clausola prima di unificarla con un'altra.
Come si procede, regola per regola, confrontando i due termini da sinistra a destra:
- due termini identici: si prosegue senza legare nulla;
- una variabile e un termine : si lega , solo se non compare in (occur check);
- due termini composti: servono lo stesso simbolo di funzione o predicato e lo stesso numero di argomenti, e poi si unificano gli argomenti a coppie, applicando le sostituzioni già trovate;
- in ogni altro caso (due costanti diverse, costante contro composto, simboli diversi) si fallisce.
Occur check. e non si unificano: richiederebbe un termine infinito . Senza il controllo l'algoritmo non terminerebbe o sarebbe scorretto. Prolog di solito non lo fa (vedi 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 →).
Il restituito è il più generale (most general unifier): ogni altro unificatore se ne ottiene con un'ulteriore sostituzione. Per esempio e danno , non .
# variabili: stringhe minuscole; costanti: stringhe maiuscole; composti: tuple ("F", arg1, ...)
def is_var(t): return isinstance(t, str) and t[0].islower()
def walk(t, s): # segue i legami già fatti
while is_var(t) and t in s: t = s[t]
return t
def occurs(v, t, s): # v compare dentro t?
t = walk(t, s)
return t == v or (isinstance(t, tuple) and any(occurs(v, a, s) for a in t[1:]))
def unify(a, b, s=None): # restituisce la sostituzione, o None se fallisce
s = {} if s is None else s
a, b = walk(a, s), walk(b, s)
if a == b: return s
if is_var(a) or is_var(b):
v, t = (a, b) if is_var(a) else (b, a)
return None if occurs(v, t, s) else {**s, v: t} # occur check
if isinstance(a, tuple) and isinstance(b, tuple) and a[0] == b[0] and len(a) == len(b):
for x, y in zip(a[1:], b[1:]):
s = unify(x, y, s)
if s is None: return None
return s
return None
def subst(t, s): # applica la sostituzione fino in fondo
t = walk(t, s)
return (t[0],) + tuple(subst(a, s) for a in t[1:]) if isinstance(t, tuple) else t
a, b = ("Knows", "John", "x"), ("Knows", "y", ("Mother", "y"))
s = unify(a, b)
print({v: subst(t, s) for v, t in s.items()}) # {'y': 'John', 'x': ('Mother', 'John')}
print(unify(("Knows", "John", "x"), ("Knows", "x", "Mary"))) # None
print(unify("x", ("Father", "x"))) # None (occur check)Gli esempi di unificazione svolti sono in Esercizio - Unificazione e conversione in CNF nel primo ordine (slide del corso).
Risoluzione nel primo ordine
Come nel caso proposizionale: si converte in CNF e si applica la risoluzione; se si ottiene la clausola vuota, (dimostrazione per assurdo).
Regola di risoluzione in FOL. Date due clausole standardizzate (con variabili diverse), con :
Esempio. Da e , con si ottiene .
Il sistema è completo per refutazione: se la KB implica , la clausola vuota si deriva. Ma il problema è solo semidecidibile: se non è implicata, l'algoritmo può non terminare mai.
Conversione in CNF
I passi sono quelli proposizionali, più la gestione di variabili e quantificatori. Esempio: "chi ama tutti gli animali è amato da qualcuno",
- Eliminare e : .
- Portare all'interno, ricordando e : , poi con De Morgan e doppia negazione . Le due sono variabili diverse, che per caso hanno lo stesso nome.
- Standardizzare le variabili (un nome diverso per ogni quantificatore): .
- Skolemizzare: ogni è dentro , quindi diventa una funzione di (, ): .
- Togliere i (restano impliciti): .
- Distribuire su :
Due clausole. (Verifica: su tutte le interpretazioni di e su un dominio di oggetti, l'enunciato originale è vero se e solo se esistono due funzioni che rendono vera la CNF: è la proprietà che la Skolemizzazione garantisce.)
Esempio: Colonnello West
La legge dice che è un reato per un americano vendere armi a nazioni ostili. Il paese Nono, nemico dell'America, ha dei missili, e tutti i suoi missili gli sono stati venduti dal colonnello West, che è americano. Dimostrare che West è un criminale.
Enunciati in logica, con le convenzioni che i nemici dell'America sono ostili e i missili sono armi:
- : con EI, ( costante di Skolem)
Dimostrazione per risoluzione di . Clausole della KB (variabili già distinte per ogni clausola):
- :
- :
- :
- :
- :
- :
- :
- :
- : (negazione della tesi)
| Passo | Clausole | Nuova clausola | |
|---|---|---|---|
| 1 | , | ||
| 2 | passo 1, | ||
| 3 | passo 2, | ||
| 4 | passo 3, | ||
| 5 | passo 4, | ||
| 6 | passo 5, | ||
| 7 | passo 6, | ||
| 8 | passo 7, | ||
| 9 | passo 8, |
Clausola vuota: è insoddisfacibile, quindi sì. (I passi sono stati rieseguiti con un piccolo programma Python che applica l'unificazione a ogni passo.) La versione svolta come esercizio è Esercizio - Risoluzione, forward e backward chaining sul caso Criminal West (slide del corso).
Clausole definite, forward e backward chaining
La risoluzione completa può essere lenta. Se la KB ha solo clausole definite (definite clauses: disgiunzione con esattamente un letterale positivo, cioè implicazioni e fatti) si usano due algoritmi più semplici. Il caso dell'esempio vale: tutti gli enunciati 1-7 sono definiti. I fatti (, , , ) sono clausole definite con corpo vuoto.
Backward chaining (concatenazione all'indietro)
Parte dalla domanda e la verifica ricorsivamente all'indietro: per dimostrare un obiettivo si cerca una clausola la cui conseguenza si unifica con esso, e si dimostrano le premesse con la sostituzione propagata. È una ricerca in profondità (vedi Ricerca nello spazio degli stati - formulazione dei problemi e ricerca non informataUn agente risolutore di problemi è un agente basato su obiettivi con rappresentazione atomica: formula un problema (stato iniziale, azioni, modello di transizione, test dell'obiettivo, costo dei passi) e cerca una sequenza di azioni che porta a uno stato obiettivo costruendo un albero di ricerca. Le strategie non informate usano solo la definizione del problema e si distinguono per l'ordine di espansione della frontiera: ampiezza (coda FIFO), costo uniforme (coda con priorità sul costo g), profondità (pila LIFO), profondità limitata, approfondimento iterativo e ricerca bidirezionale. Si confrontano per completezza, ottimalità, tempo e spazio in funzione di b, d, m; tutte sono casi di best-first search con una diversa funzione di valutazione f.Ricerca nello spazio degli stati - formulazione dei problemi e ricerca non informata →): non ottima ma molto efficiente. Si applica solo a KB di fatti e implicazioni. È ciò che fa Prolog.
Traccia su (ogni riga: obiettivo, clausola usata, sostituzioni nuove; le variabili delle clausole sono rinominate a ogni uso):
Criminal(West) <- regola 1, {x/West}
American(West) <- fatto, {}
Weapon(y) <- regola 5, {y/x'}
Missile(x') <- fatto Missile(M1), {x'/M1} quindi y = M1
Sells(West, M1, z) <- regola 6, {z/Nono, x''/M1}
Missile(M1) <- fatto, {}
Owns(Nono, M1) <- fatto, {}
Hostile(Nono) <- regola 3, {x'''/Nono}
Enemy(Nono, America) <- fatto, {}Tutte le foglie sono fatti: è dimostrato con . Un solo ramo di ricerca, nessun tentativo inutile: nella risoluzione servono tutti i passi sopra e in più si potrebbero generare clausole irrilevanti.
Forward chaining (concatenazione in avanti)
Parte dai fatti e applica ripetutamente le regole le cui premesse sono già tutte note, aggiungendo le conseguenze, finché non si ricava la domanda o non c'è più nulla di nuovo (punto fisso). Su questa KB:
- Giro 1 (fatti: , , , ): con dà ; con dà ; con dà .
- Giro 2: la regola 1 ha ora tutte le premesse, con : nasce .
- Giro 3: nessuna conseguenza nuova, punto fisso.
(Giri e fatti controllati con un programma Python.) Il forward chaining è corretto e, per clausole definite senza simboli di funzione, termina sempre; ricava però tutte le conseguenze, anche le irrilevanti per la domanda. Il backward chaining è invece guidato dall'obiettivo.
| Forward | Backward | |
|---|---|---|
| Parte da | fatti noti | domanda |
| Direzione | dalle premesse alle conseguenze | dalla conseguenza alle premesse |
| Adatto a | produrre nuovi fatti quando arrivano dati | rispondere a una domanda precisa |
| Rischio | deduce molto di irrilevante | può non terminare (cicli, ricorsione a sinistra) |
Ingegneria della conoscenza
L'ingegneria della conoscenza (knowledge engineering) è il processo di costruzione di una KB. I passi:
- identificare le domande (analogo al PEAS dell'agente);
- raccogliere la conoscenza rilevante;
- scegliere un vocabolario di predicati, funzioni e costanti (ontologia);
- codificare la conoscenza generale del dominio;
- codificare la descrizione dell'istanza di problema;
- porre domande al motore di inferenza e leggere le risposte;
- correggere e valutare la KB.
Esempio: circuito sommatore. Domande: il circuito somma correttamente? Se tutti gli ingressi sono alti, qual è l'uscita della porta ? Quali porte sono collegate al primo terminale di ingresso? Ci sono anelli di retroazione? Conoscenza: i circuiti sono fatti di fili e porte; i segnali vanno lungo i fili ai terminali di ingresso delle porte; ogni porta produce un segnale sul terminale di uscita; i tipi di porta sono AND, OR, XOR (due ingressi) e NOT (uno).
Vocabolario: ogni porta è un oggetto con nome costante, per esempio , , ; il tipo con una funzione, . Regola generale: . Istanza: ("l'uscita di è collegata all'ingresso di "). Domanda: per quali ingressi di l'uscita di vale ?, cioè . Per il debug si perturba la KB togliendo o modificando regole e fatti per vedere quali comportamenti errati compaiono.
Domande d'esame
- Unificare e . Fallisce se si lasciano le due con lo stesso nome (si dovrebbe avere e ). Dopo aver standardizzato la seconda come si ottiene .
- Tradurre "chi possiede un cane ama gli animali" e dare la CNF. . Eliminando l'implicazione e portando dentro, l' dell'antecedente diventa : . Una sola clausola, senza Skolem.
- Skolemizzare e . Il primo dà (funzione di , perché l'amante dipende da chi è amato); il secondo con costante .
- Perché l'occur check? Senza, si unificherebbe con in un termine infinito, e l'algoritmo non terminerebbe o dedurrebbe cose sbagliate. Con il controllo l'unificazione di con fallisce.
Versione ripasso
- FOL: oggetti, relazioni, funzioni. Sintassi: costanti, funzioni, variabili, predicati, connettivi, , , . Termine = oggetto; enunciato atomico = fatto. Base: Agenti logici e logica proposizionale - inferenza e risoluzioneAgenti basati sulla conoscenza (KB, Tell e Ask), mondo del Wumpus come banco di prova, sintassi e semantica della logica proposizionale, conseguenza logica, equivalenze, inferenza per model checking (7 simboli, 128 modelli, 3 modelli della KB) e per risoluzione (CNF, regola di risoluzione, dimostrazione per assurdo). Limite: poca espressività, da cui la logica del primo ordine.Agenti logici e logica proposizionale - inferenza e risoluzione →.
- Quantificatori: con il connettivo principale è (); con è . Errori: con ("tutti sono a Oxford e tutti intelligenti"); con (vero a vuoto). diverso da . Dualità: .
- Sostituzione ; = enunciato dopo la sostituzione;
Askrestituisce le con . - UI: da si ottiene con termine chiuso (KB equivalente). EI: dà con costante di Skolem nuova (soddisfacibile sse lo era la KB); dentro un serve una funzione di Skolem .
- Proposizionalizzazione: istanzia tutto e usa la logica proposizionale; genera molti enunciati irrilevanti e con funzioni infiniti termini (, ...).
- Unificazione: con . Si confronta da sinistra: termini uguali, variabile con termine ( solo se non compare in ), composti con stesso funtore e arità e argomenti unificabili in cascata. con dà . Con fallisce finché non si standardizza (rinominare le variabili): . Si cerca l'unificatore più generale.
- Occur check: e non si unificano (termine infinito). Prolog di solito non lo fa (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 →).
- Risoluzione FOL: clausole standardizzate, , risolvente con applicata. Esempio: con , dà . Completa per refutazione, ma semidecidibile.
- CNF in FOL: 1 eliminare , ; 2 portare dentro (, ); 3 standardizzare; 4 Skolemizzare; 5 togliere i ; 6 distribuire su . Esempio animali: .
- Criminal(West): ; con , poi , , , , , , , : clausola vuota in passi. Esercizio: Esercizio - Risoluzione, forward e backward chaining sul caso Criminal West (slide del corso).
- Clausole definite = un solo letterale positivo (implicazioni e fatti). Backward chaining: dall'obiettivo alle premesse, in profondità, sostituzioni propagate, usato da Prolog; trova . Forward chaining: dai fatti a un punto fisso; qui giro 1 dà , , , giro 2 dà , giro 3 niente.
- Esempio di proposizionalizzazione: , , con oggetti : istanze della regola più fatti; i simboli sono , , , ecc. Unificando invece basta (con ).
- Clausole della KB Criminal: ; ; ; ; ; ; ; .
- Passi dell'unificatore: si legano ( con ), (), (), e (), (); le altre risoluzioni hanno .
- Forward vs backward: forward parte dai fatti e arriva a un punto fisso, produce anche fatti irrilevanti; backward parte dalla domanda, in profondità, può non terminare (cicli, ricorsione a sinistra); entrambi su clausole definite, il secondo è quello di Prolog.
- Domande tipiche: con fallisce finché non si standardizza; "chi possiede un cane ama gli animali" dà (l' nell'antecedente diventa ); dà , mentre dà .
- Altre unificazioni verificate: e danno ; e danno ; e falliscono; e falliscono per occur check.
- Ingegneria della conoscenza: domande, conoscenza, vocabolario (ontologia), conoscenza generale, istanza, query, debug. Esempio: circuito sommatore con e .
- Errori tipici: non standardizzare; legare senza occur check; dimenticare di applicare le sostituzioni già trovate; Skolem con costante invece di funzione dentro un .