Vai al contenuto
coden

Logica e sistemi basati sulla conoscenza: concatenazione in avanti e all’indietro, risoluzione e sistemi esperti

La base di conoscenza, la conseguenza logica e la verifica dei modelli, le clausole di Horn, la concatenazione in avanti e all’indietro, la risoluzione, Prolog e i sistemi esperti da MYCIN ai grafi di conoscenza, con un piccolo sistema che riconosce un animale.

15 minuti Matěj Žalmánek 2026-10-15

Serie Basi di IA Parte 24 di 52
  1. Mappa dell’intelligenza artificiale: che cos’è ciascuna cosa e come si incastra tutto
  2. Breve storia dell’intelligenza artificiale: da Turing ai modelli linguistici
  3. Dati, modello, addestramento, inferenza: i concetti di base su un unico esempio
  4. Come leggere la notazione matematica: simboli, indici, sommatorie e quantificatori
  5. Insiemi e relazioni: i mattoncini con cui si costruiscono le definizioni nell’IA
  6. Funzioni e applicazioni: perché ogni modello di IA è una funzione
  7. Logica e dimostrazioni: le regole con cui si ragiona nell’IA
  8. Grafi e alberi: la struttura su cui poggiano la ricerca e le reti neurali
  9. Algebra lineare per l’apprendimento automatico: vettori, matrici e perché l’IA soprattutto moltiplica
  10. Derivate, gradiente e regola della catena: come un modello capisce in quale direzione imparare
  11. Discesa del gradiente: come impara un modello
  12. Che cos’è la probabilità: dal lancio di un dado agli assiomi di Kolmogorov
  13. Probabilità condizionata e teorema di Bayes: come cambiare una stima quando scopri qualcosa di nuovo
  14. Variabile aleatoria e funzione di ripartizione: una sola funzione che dice tutto sulla distribuzione
  15. Funzione di densità e funzione di massa: perché una variabile continua ha probabilità zero in un punto
  16. Valore atteso, varianza e covarianza: dove si trova una distribuzione, quanto è larga e che cosa è legato a che cosa
  17. Panoramica delle distribuzioni di probabilità: Bernoulli, binomiale, Poisson, uniforme, normale ed esponenziale
  18. Legge dei grandi numeri e teorema del limite centrale: perché le medie si comportano in modo così prevedibile
  19. Statistica e stima dei parametri: massima verosimiglianza, MAP e intervalli di confidenza
  20. Teoria dell’informazione: entropia, entropia incrociata e divergenza KL — da dove vengono le funzioni di perdita
  21. Ricerca nello spazio degli stati: BFS, DFS, UCS e A* con animazioni
  22. Giochi e avversari: minimax, potatura alfa-beta e Monte Carlo tree search
  23. Soddisfacimento di vincoli: backtracking, propagazione dei vincoli e AC-3 su un sudoku e una mappa delle regioni ceche
  24. Logica e sistemi basati sulla conoscenza: concatenazione in avanti e all’indietro, risoluzione e sistemi esperti
  25. Pianificazione: STRIPS, il mondo dei blocchi, euristiche dal rilassamento e pianificazione negli agenti IA
  26. Ricerca locale e ricottura simulata: un commesso viaggiatore tra i capoluoghi di regione cechi
  27. Algoritmi genetici: popolazione, incrocio, mutazione e selezione su uno zaino per l’escursione
  28. Strategie evolutive e programmazione genetica: dalla regola di un quinto alla legge di Keplero
  29. Ottimizzazione con colonie di formiche: come una traccia di feromone trova un percorso breve
  30. Ottimizzazione a sciame di particelle: inerzia, esperienza propria ed esperienza dello sciame
  31. Neuroevoluzione: evoluzione dei pesi e della forma delle reti neurali e l’algoritmo NEAT
  32. Insiemi fuzzy e funzioni di appartenenza: come scrivere «un po’ caldo»
  33. Logica fuzzy e probabilità: perché «un po’ caldo» non significa «probabilmente caldo»
  34. Logica fuzzy: t-norme, implicazioni e regole SE–ALLORA
  35. Controllo fuzzy: Mamdani e Sugeno, dal ventilatore al pendolo inverso su un carrello
  36. Clustering fuzzy: l’algoritmo fuzzy c-means e i punti tra i cluster
  37. Sistemi neuro-fuzzy (ANFIS): regole fuzzy che imparano dai dati
  38. Catene di Markov: matrice di transizione, distribuzione stazionaria e PageRank
  39. Modelli di Markov nascosti: l’algoritmo di Viterbi e il casinò disonesto
  40. Reti bayesiane: perché l’erba è bagnata e che cosa significa per l’irrigatore
  41. Filtro di Kalman: come stimare da misure imprecise dove si trova un’auto e a che velocità va
  42. Tipi di apprendimento automatico: supervisionato, non supervisionato, semi-supervisionato e altri
  43. Prompt, contesto e RAG: come dare a un modello le informazioni giuste
  44. Autoencoder variazionali (VAE): immagini nuove da uno spazio latente continuo
  45. Reti generative avversarie (GAN): il falsario contro il detective
  46. Modelli di diffusione: come il rumore puro diventa un’immagine
  47. Processi decisionali di Markov: stati, azioni, ricompense ed equazioni di Bellman
  48. Q-learning e DQN: imparare il valore delle azioni, dalla tabella alla rete neurale
  49. Policy gradient e PPO: imparare direttamente la politica
  50. Come funziona un agente IA: un modello linguistico in un ciclo con strumenti
  51. Programmare con agenti IA: incarico, test e controllo
  52. Valutazione e sicurezza dei sistemi di IA: come misurare e come sorvegliare

Programma completo della serie 52 di 83 argomenti pubblicati

Cosa porterai a casa
  • Che cosa significa che qualcosa segue da una base di conoscenza, e perché verificare tutti i mondi possibili è inutilmente lento.
  • Come la concatenazione in avanti e quella all’indietro traggono conclusioni da regole «se–allora», e quando usare l’una o l’altra.
  • Perché i sistemi esperti hanno avuto successo e poi si sono scontrati con i loro limiti, e dove la conoscenza scritta a mano vive ancora oggi.

Utile sapere prima: Logica e dimostrazioni: le regole con cui si ragiona nell’IA

Prima che le macchine cominciassero a imparare dai dati, si è provato a insegnare a mano all’intelligenza artificiale: scrivere ciò che sa un esperto come regole «se–allora» e lasciare che il computer ne traesse conclusioni. Così sono nati i sistemi esperti degli anni Settanta e Ottanta, che diagnosticavano infezioni o configuravano computer su ordinazione. Poi si sono scontrati con i propri limiti ed è arrivato un inverno dell’intelligenza artificiale. Le loro idee però non sono scomparse: vivono in Prolog, nelle basi di conoscenza dietro i motori di ricerca e nel controllo di ciò che affermano i modelli linguistici.

Questa parte prosegue Logica e dimostrazioni, dove trovi i connettivi, l’implicazione e il modus ponens.

1. La base di conoscenza e il motore inferenziale

Definizione — base di conoscenza

Una base di conoscenza KB è un insieme di enunciati di un linguaggio formale (qui la logica proposizionale) che il sistema considera veri. Il sistema sa fare due operazioni con essa: dire — aggiungere a KB un nuovo enunciato — e chiedere — scoprire se da KB segue un enunciato α.

In parole semplici

Una base di conoscenza è un quaderno in cui annoti ciò che è vero: «ogni animale con il pelo è un mammifero», «questo animale ha il pelo». Il motore inferenziale è chi sfoglia il quaderno e risponde alle domande, anche quando la risposta non vi è scritta direttamente.

Questo approccio si chiama dichiarativo. Non programmi il procedimento per arrivare alla risposta: scrivi solo che cosa è vero, e il procedimento è sempre lo stesso motore inferenziale. Vuoi insegnare qualcosa di nuovo al sistema? Aggiungi un enunciato, senza riscrivere nulla.

Per tutta la parte ci accompagnerà un piccolo sistema esperto sul modello del ZOOKEEPER da manuale di Patrick Winston: dodici regole con cui si riconosce un animale dalle sue proprietà osservate. Abbiamo osservato un animale che ha il pelo, denti aguzzi e artigli, è fulvo e ha strisce nere. Che cos’è?

2. Conseguenza logica e modelli

Definizione — modello e conseguenza logica

Un modello di un enunciato è un’assegnazione di valori di verità ai simboli proposizionali in cui l’enunciato è vero. L’insieme dei modelli di un enunciato α si indica con M(α).

Da KB segue α (ne è conseguenza logica), e si scrive KB ⊨ α, se e solo se M(KB) ⊆ M(α): in ogni modello della base di conoscenza vale anche α.

In parole semplici

Un modello è un «mondo possibile»: una combinazione di ciò che è vero e ciò che non lo è. Conseguenza logica significa: comunque sia il mondo, se in esso vale tutto ciò che c’è nel quaderno, vale anche α. Non si tratta di ciò che è probabile, ma di ciò che è inevitabile.

KB ⊨ α ⇔ M(KB) ⊆ M(α)

KB ⊨ α
ciò che chiediamo: α segue dalla base? Il simbolo ⊨ parla di verità nei mondi, non del fatto che sappiamo dedurre qualcosa
M(KB)
i mondi che la base ammette: le assegnazioni in cui valgono tutti i suoi enunciati contemporaneamente (la base è la loro congiunzione); gli altri mondi non ci interessano, di essi la base afferma che non si sono verificati
⊆
inclusione: in nessun mondo ammesso può mancare α; basterebbe un solo controesempio perché α non seguisse
M(α)
i mondi in cui vale α; possono essere molti di più: α può valere anche dove la base non vale
Più la base sa, meno mondi ammette e più cose ne seguono. Una base vuota ammette tutti i mondi, perciò ne seguono solo tautologie.

Il modo più diretto per verificare la conseguenza logica è la verifica dei modelli (model checking): percorrere tutte le assegnazioni, scegliere quelle in cui vale l’intera base e controllare se in esse vale anche la domanda. La nostra base ha 24 simboli proposizionali («ha il pelo», «mammifero», «tigre»…), quindi le assegnazioni sono 224 = 16 777 216. Di queste, 13 440 sono modelli della base, e in tutti vale «tigre». La risposta è sì, ma al prezzo di sedici milioni di righe di una tavola di verità. A ogni simbolo in più il numero raddoppia; con una base di centinaia di simboli non finirebbe mai.

Esempio — verifica dei modelli su tre simboli

Base KB = {piove ⇒ bagnato, bagnato ⇒ scivola, piove}, domanda α = scivola. Tre simboli danno 23 = 8 assegnazioni (1 = vero, 0 = falso); l’implicazione p ⇒ q è falsa solo per p = 1, q = 0.

piovebagnatoscivolapiove ⇒ bagnatobagnato ⇒ scivolaKB
000110
001110
010100
011110
100010
101010
110100
111111

L’intera base vale solo nell’ultima riga, quindi |M(KB)| = 1. In quella riga vale anche «scivola»: M(KB) ⊆ M(scivola), e perciò KB ⊨ scivola. L’algoritmo ha percorso 8 righe e in ciascuna ha valutato i 3 enunciati della base; in generale la verifica dei modelli costa O(2n · |KB|).

Esempio — da dove vengono i 13 440 modelli

In ogni modello della base valgono i cinque fatti osservati, e le regole R1, R6 e R9 impongono allora «mammifero», «carnivoro» e «tigre». Questi 8 simboli sono veri in modo fisso. I restanti 16 si dividono in gruppi che nessuna regola collega tra loro, e i numeri delle loro assegnazioni si moltiplicano:

  • «dà latte» (R2 è soddisfatta, mammifero vale) e «mangia carne» (R5 è soddisfatta, carnivoro vale): liberi, 2 · 2 = 4;
  • «ha macchie scure», «ghepardo» con la regola R8: tre assegnazioni; non possono esserci macchie senza ghepardo;
  • «ha zoccoli», «ungulato», «ha collo lungo», «giraffa», «zebra» con R7, R10, R11: se ungulato è falso, devono essere falsi anche gli zoccoli e gli altri tre simboli sono liberi (8 possibilità); se è vero, deve valere zebra, gli zoccoli sono liberi e collo con giraffa hanno 3 possibilità (2 · 3 = 6); in tutto 14;
  • il gruppo degli uccelli «ha le piume», «vola», «depone uova», «uccello», «non vola», «nuota», «pinguino» con R3, R4, R12: senza uccello non possono valere le piume né insieme vola e uova (3 possibilità) e gli ultimi tre simboli sono liberi (8): 24; con uccello le piume sono libere (2), vola e uova libere (4) e delle otto assegnazioni di «non vola, nuota, pinguino» è vietata solo 1, 1, 0 (7): 56; in tutto 80.

In totale 4 · 3 · 14 · 80 = 13 440, esattamente quanti ne ha contati la verifica dei modelli. E in ognuno di essi vale tigre, perché è tra i simboli veri in modo fisso.

3. Inferenza: corretta e completa

Invece di percorrere i mondi si possono manipolare gli enunciati: da quelli che abbiamo, produrne di nuovi secondo regole di inferenza come il modus ponens. È quello che fa anche una persona.

Definizione — inferenza, correttezza, completezza

Scriviamo KB ⊢ α quando α si può ottenere da KB con un numero finito di applicazioni di regole di inferenza.

Un procedimento di inferenza è corretto se da KB ⊢ α segue KB ⊨ α: deduce solo ciò che segue davvero.

È completo se da KB ⊨ α segue KB ⊢ α: deduce tutto ciò che segue.

In parole semplici

Il simbolo ⊨ vuol dire «è così», il simbolo ⊢ «so dedurlo». Un motore corretto non inventa mai una falsità. Un motore completo non si lascia sfuggire nulla. Vogliamo entrambe le cose: per la logica generale è costoso, per una forma più semplice di regole invece costa poco.

Definizione — clausola di Horn

Una clausola di Horn è una disgiunzione di letterali di cui al più uno è positivo. Una clausola con esattamente un letterale positivo è definita e si può scrivere come regola

p1 ∧ p2 ∧ … ∧ pk ⇒ q,

dove p1, …, pk sono le premesse e q la conclusione. Per k = 0 è un fatto q.

In parole semplici

Una clausola di Horn è una regola «se vale questo e questo e questo, allora vale quello». Nessun «o» nella conclusione, nessun «non» nelle premesse. Sembra una grossa limitazione, ma la maggior parte delle regole degli esperti ha proprio questa forma, e l’inferenza a partire da esse è veloce.

Perché «una disgiunzione con al più un letterale positivo» è la stessa cosa di una regola? L’implicazione A ⇒ q è equivalente a ¬A ∨ q, e per la legge di De Morgan ¬(p1 ∧ … ∧ pk) è la stessa cosa di ¬p1 ∨ … ∨ ¬pk:

¬p1 ∨ … ∨ ¬pk ∨ q ≡ (p1 ∧ … ∧ pk) ⇒ q

¬p1 ∨ … ∨ ¬pk
i letterali negativi della clausola; insieme dicono «qualche premessa non vale», ed è esattamente la negazione della congiunzione delle premesse
(p1 ∧ … ∧ pk)
le premesse della regola: la disgiunzione di letterali negativi è diventata una condizione grazie a De Morgan; nessuna può essere negativa, altrimenti la regola direbbe «se non vale …»
q
l’unico letterale positivo, la conclusione; se ce ne fossero due positivi, otterremmo «allora q o r» e il motore inferenziale non saprebbe quale aggiungere
⇒
la clausola è vera quando qualche premessa non vale o vale la conclusione: è la definizione dell’implicazione; la forma di regola legge solo in un altro modo la stessa disgiunzione
Per esempio R6, mammifero ∧ ha denti aguzzi ∧ ha artigli ⇒ carnivoro, è la clausola ¬mammifero ∨ ¬ha denti aguzzi ∨ ¬ha artigli ∨ carnivoro.

4. Concatenazione in avanti

Algoritmo — concatenazione in avanti
  1. Ogni regola ricorda quante delle sue premesse non sono ancora note. Metti tutti i fatti nell’agenda.
  2. Prendi un simbolo dall’agenda. Se è già stato elaborato, passa al successivo.
  3. A ogni regola che lo ha tra le premesse diminuisci il contatore di 1. Se scende a 0, la regola scatta: aggiungi la sua conclusione all’agenda.
  4. Ripeti finché l’agenda non è vuota.

Teorema. Per una base di clausole di Horn definite, la concatenazione in avanti è corretta e completa per i simboli proposizionali: deduce esattamente quelli che seguono da KB. Gira in tempo lineare rispetto alla dimensione della base.

In parole semplici

Parti da ciò che sai e guarda quale regola si è così «sbloccata». Ogni nuova conclusione può sbloccare un’altra regola, come un domino. Ti fermi quando non cade più nulla di nuovo. Si parla di inferenza guidata dai dati.

fatti regole 1. ha il pelo 2. ha denti aguzzi 3. ha artigli 4. è fulvo 5. ha strisce nere 6. mammifero 7. carnivoro 8. tigre R1 ha il pelo ⇒ mammifero R2 dà latte ⇒ mammifero R3 ha le piume ⇒ uccello R4 vola ∧ depone uova ⇒ uccello R5 mammifero ∧ mangia carne ⇒ carnivoro R6 mammifero ∧ ha denti aguzzi ∧ ha artigli ⇒ carnivoro R7 mammifero ∧ ha zoccoli ⇒ ungulato R8 carnivoro ∧ è fulvo ∧ ha macchie scure ⇒ ghepardo R9 carnivoro ∧ è fulvo ∧ ha strisce nere ⇒ tigre R10 ungulato ∧ ha collo lungo ⇒ giraffa R11 ungulato ∧ ha strisce nere ⇒ zebra R12 uccello ∧ non vola ∧ nuota ⇒ pinguino
Concatenazione in avanti: i fatti nell’ordine di elaborazione, quelli dedotti in verde passi: 8

Già la prima osservazione, «ha il pelo», sblocca la regola R1, che aggiunge «mammifero» in fondo all’agenda. Le altre quattro osservazioni per ora non fanno scattare nulla, ma abbassano i contatori. Quando arriva il turno di mammifero, sblocca R6 (denti aguzzi e artigli li conosciamo già) e nasce «carnivoro». Carnivoro sblocca R9 e abbiamo una tigre. In otto passi, senza milioni di righe. La regola R5 («un mammifero che mangia carne è un carnivoro») non è mai scattata: che l’animale mangi carne non lo sappiamo, e non abbiamo bisogno di saperlo.

def dopredne(fakta, pravidla):
    chybi = {r.id: len(r.kdyz) for r in pravidla}
    zname, agenda = set(), list(fakta)
    while agenda:
        p = agenda.pop(0)
        if p in zname:
            continue
        zname.add(p)
        for r in pravidla:
            if p in r.kdyz:
                chybi[r.id] -= 1
                if chybi[r.id] == 0:          # conosciamo tutte le premesse
                    agenda.append(r.pak)
    return zname

Il cuore dell’algoritmo è il contatore di ogni regola r con premesse P(r):

mancano(r) = |P(r)| − |P(r) ∩ Noti|

mancano(r)
quante premesse non conosciamo ancora; con mancano(r) = 0 la regola scatta; grazie al numero il motore se ne accorge senza scorrere l’elenco delle premesse
|P(r)|
il valore iniziale: all’inizio non sappiamo nulla, mancano tutte le premesse
|P(r) ∩ Noti|
le premesse già elaborate; ogni simbolo elaborato abbassa di 1 il contatore di ogni regola in cui compare, e viene elaborato una sola volta, perciò nulla viene contato due volte
Ogni simbolo viene elaborato al più una volta e ogni occorrenza di una premessa abbassa un contatore al più una volta: da qui il tempo lineare, il numero di passi è proporzionale alla somma delle lunghezze delle regole.

Come scendono i contatori durante la nostra esecuzione (dopo l’elaborazione del simbolo della riga; in grassetto lo zero, cioè lo scatto):

passosimbolo elaboratoR1R5R6R9R8
0—12333
1ha il pelo02333
2ha denti aguzzi02233
3ha artigli02133
4è fulvo02122
5ha strisce nere02112
6mammifero01012
7carnivoro01001
8tigre01001

R5 si ferma a uno (manca «mangia carne») e così anche R8, quella del ghepardo (manca «ha macchie scure»). Le altre regole non sono in tabella; le loro premesse nell’esecuzione non sono comparse affatto, oppure solo in parte.

Teorema — la concatenazione in avanti è corretta e completa (dimostrazione)

Correttezza. Ogni simbolo dedotto è nato dallo scatto di una regola le cui premesse erano già tutte note. In ogni modello della base valgono i fatti e (per induzione sull’ordine di deduzione) anche i simboli dedotti prima, quindi per la regola vale anche la nuova conclusione: è il modus ponens.

Completezza. Alla fine prendiamo l’assegnazione m: vero per i simboli dedotti (e i fatti), falso per tutti gli altri. È un modello della base: se qualche regola p1 ∧ … ∧ pk ⇒ q non valesse in m, tutte le pi sarebbero dedotte e q no; ma allora il contatore della regola sarebbe sceso a zero e q sarebbe stato dedotto. Se quindi q segue dalla base, vale nel modello m, e dunque è stato dedotto. ∎

Il modello m è il «più modesto»: crede solo a ciò a cui deve credere. Per la nostra base è l’assegnazione in cui valgono esattamente le 5 osservazioni, mammifero, carnivoro e tigre.

5. Concatenazione all’indietro

Algoritmo — concatenazione all’indietro

Dimostra l’obiettivo q:

  • se q è un fatto noto, è dimostrato;
  • altrimenti, per ogni regola p1 ∧ … ∧ pk ⇒ q, prova a dimostrare una dopo l’altra tutte le pi; se con qualche regola ci riesci, q è dimostrato;
  • se nessuna regola ha successo, la dimostrazione è fallita.

Per clausole di Horn definite, la concatenazione all’indietro è corretta e completa ed esamina solo i simboli legati all’obiettivo.

In parole semplici

Parti dalla domanda «è una tigre?» e ti chiedi che cosa lo confermerebbe: una tigre è un carnivoro fulvo con strisce nere. È un carnivoro? Un carnivoro è un mammifero che mangia carne, oppure un mammifero con denti aguzzi e artigli. È un mammifero? … Finché non arrivi a ciò che sai. Si parla di inferenza guidata dall’obiettivo.

def zpetne(cil, fakta, pravidla, cesta=()):
    if cil in fakta:
        return True                           # lo sappiamo direttamente
    if cil in cesta:
        return False                          # ciclo: l’obiettivo dimostra sé stesso
    for r in pravidla:
        if r.pak == cil:                      # O: basta una regola
            if all(zpetne(p, fakta, pravidla, cesta + (cil,))
                   for p in r.kdyz):          # E: devono riuscire tutte le premesse
                return True
    return False                              # non sappiamo come dimostrarlo

La funzione all si ferma alla prima premessa che non riesce: per questo, in R5, dopo il fallimento con «mangia carne» non si esamina nient’altro. La lista cesta (percorso) fa sì che regole come «a ⇒ b, b ⇒ a» non vadano in ciclo.

R9 R5 ✗ R1 R6 R1 tigre carnivoro mammifero ha il pelo mangia carne ? mammifero ha il pelo ha denti aguzzi ha artigli è fulvo ha strisce nere
Concatenazione all’indietro per l’obiettivo «tigre»: sotto i nodi ci sono le regole

L’algoritmo ha esaminato 11 obiettivi. Carnivoro ha provato prima a dimostrarlo con la regola R5: ha dimostrato mammifero, ma si è scontrato con «mangia carne». Questo non lo sappiamo, quindi ha rinunciato a R5 e ha provato R6, che è riuscita. Qui la concatenazione all’indietro è forte: sa che cosa le manca. In un momento del genere un sistema esperto chiede all’utente: «L’animale mangia carne?». Tutta la conversazione con un sistema esperto è in realtà concatenazione all’indietro ad alta voce.

Quando usare quale? La concatenazione in avanti è adatta quando arrivano dati e vuoi sapere che cosa ne segue, per esempio nel monitoraggio di una produzione. Quella all’indietro quando hai una domanda precisa: una diagnosi, un’interrogazione a un database. Se chiedessimo «è una zebra?», la concatenazione all’indietro lo confuterebbe dopo aver esaminato solo 5 obiettivi: una zebra è un ungulato e il nostro animale non ha zoccoli.

6. Risoluzione: l’inferenza per tutta la logica

Le clausole di Horn non bastano per tutto. L’enunciato «l’animale è un mammifero o un uccello» ha una «o» nella conclusione, e come regola non lo si può scrivere. Per proposizioni qualsiasi esiste un’unica regola che basta per tutto.

Definizione — risoluzione

Gli enunciati si convertono in forma normale congiuntiva: una congiunzione di clausole, ognuna delle quali è una disgiunzione di letterali. Regola di risoluzione: dalle clausole (A ∨ ℓ) e (B ∨ ¬ℓ) deduci (A ∨ B).

Dimostrazione per assurdo: KB ⊨ α se e solo se KB ∧ ¬α è insoddisfacibile. La risoluzione deduce nuove clausole da KB ∧ ¬α; se deduce la clausola vuota, la contraddizione è trovata. Questo procedimento è corretto e completo (Robinson, 1965).

In parole semplici

Se vale «piove o è asciutto» e allo stesso tempo «non è asciutto o tira vento», allora «piove o tira vento»: l’asciutto si elide. La risoluzione dimostra per assurdo: suppone il contrario di ciò che vuole dimostrare e accorcia le clausole finché ne resta una vuota, una contraddizione. Il contrario dunque non vale.

( A ∨ ℓ ), ( B ∨ ¬ℓ ) ⊢ ( A ∨ B )

ℓ, ¬ℓ
letterali complementari: in ogni mondo è vero esattamente uno dei due, quindi non soddisfa una delle clausole; quella deve essere soddisfatta dal suo resto. Per questo ℓ manca nel risultato
A
il resto della prima clausola: vale ogni volta che ℓ è falso (allora la prima clausola la regge solo A)
B
il resto della seconda clausola: vale ogni volta che ℓ è vero (allora ¬ℓ non vale e la seconda clausola la regge B)
Comunque sia ℓ, uno dei resti deve valere: è tutta la dimostrazione che la risoluzione è corretta. Da (ℓ) e (¬ℓ) nasce la clausola vuota, che nulla soddisfa: una contraddizione.
Algoritmo — conversione in forma normale congiuntiva
  1. Elimina le equivalenze: sostituisci α ⇔ β con (α ⇒ β) ∧ (β ⇒ α).
  2. Elimina le implicazioni: sostituisci α ⇒ β con ¬α ∨ β.
  3. Sposta le negazioni fino ai simboli: ¬¬α ≡ α, ¬(α ∧ β) ≡ ¬α ∨ ¬β, ¬(α ∨ β) ≡ ¬α ∧ ¬β (De Morgan).
  4. Distribuisci ∨ su ∧: α ∨ (β ∧ γ) ≡ (α ∨ β) ∧ (α ∨ γ).

Esempio: (piove ∨ nevica) ⇒ bagnato

passo 2: ¬(piove ∨ nevica) ∨ bagnato

passo 3: (¬piove ∧ ¬nevica) ∨ bagnato

passo 4: (¬piove ∨ bagnato) ∧ (¬nevica ∨ bagnato): due clausole, entrambe perfino di Horn.

La distribuzione al 4° passo può allungare la formula in modo esponenziale; per questo in pratica i risolutori usano la trasformazione di Tseitin con simboli ausiliari, che dà un risultato solo linearmente più lungo (soddisfacibile se e solo se lo è la formula originale).

Esempio: la base {piove ⇒ bagnato, bagnato ⇒ scivola, piove}, domanda «scivola». In forma normale e con la negazione della domanda aggiunta:

(¬piove ∨ bagnato), (¬bagnato ∨ scivola), (piove), (¬scivola)

(piove) e (¬piove ∨ bagnato) danno (bagnato); (bagnato) e (¬bagnato ∨ scivola) danno (scivola); (scivola) e (¬scivola) danno la clausola vuota. Contraddizione: «scivola» segue dalla base.

La risoluzione è universale, ma in generale costosa: per la logica proposizionale il problema della soddisfacibilità (SAT) è NP-completo. I moderni risolutori SAT gestiscono comunque milioni di variabili; ne abbiamo parlato nella parte sul soddisfacimento di vincoli.

7. Regole con variabili e Prolog

La logica proposizionale ha un difetto: «Rex è un mammifero» e «Micka è un mammifero» sono per lei due simboli senza relazione. Una regola su tutti i mammiferi andrebbe ricopiata per ogni animale separatamente. La logica dei predicati della parte su logica e dimostrazioni lo risolve con le variabili: ∀x : ha_il_pelo(x) ⇒ mammifero(x).

Definizione — unificazione

Un unificatore di due espressioni è una sostituzione delle variabili dopo la quale le due espressioni sono identiche. Per esempio rodič(jan, Y) e rodič(X, petr) (rodič = genitore) sono unificate dalla sostituzione {X / jan, Y / petr}. L’algoritmo di unificazione trova l’unificatore più generale, se esiste.

In parole semplici

Unificare significa «trovare che cosa sostituire perché combaci». Quando una regola parla di un qualche x e tu chiedi di Rex, l’unificazione sostituisce x = Rex e la regola si può applicare. La concatenazione funziona poi come nella logica proposizionale, solo con le sostituzioni.

def unifikuj(a, b, s):                    # s: sostituzione trovata finora (dizionario)
    if s is None:
        return None                           # è già fallita prima
    a, b = dosad(a, s), dosad(b, s)           # applica ciò che sappiamo già
    if a == b:
        return s
    if je_promenna(a):
        return None if vyskytuje_se(a, b) else {**s, a: b}
    if je_promenna(b):
        return None if vyskytuje_se(b, a) else {**s, b: a}
    if slozeny(a) and slozeny(b) and a.jmeno == b.jmeno and len(a.args) == len(b.args):
        for x, y in zip(a.args, b.args):      # gli argomenti uno dopo l’altro
            s = unifikuj(x, y, s)
        return s
    return None                               # costanti o predicati diversi

Nell’esempio rodič(jan, Y) e rodič(X, petr): i predicati coincidono, quindi si confrontano gli argomenti. jan e X danno {X / jan}, Y e petr aggiungono Y / petr. Invece rodič(jan, Y) e rodič(petr, eva) non si unificano: jan e petr sono costanti diverse. Il controllo vyskytuje_se (occurs check) impedisce una sostituzione come X / f(X), che porterebbe a un’espressione infinita. (Prolog per velocità lo omette di default.)

Sulla concatenazione all’indietro con unificazione si basa Prolog (Alain Colmerauer, Marsiglia, 1972), un linguaggio in cui il programma è una base di conoscenza ed eseguire il programma è un’interrogazione (rodic = genitore, prarodic = nonno o nonna, kdo = chi):

rodic(jan, petr).
rodic(petr, eva).

prarodic(X, Z) :- rodic(X, Y), rodic(Y, Z).

?- prarodic(jan, Kdo).
Kdo = eva.

Prolog arriva all’obiettivo prarodic(jan, Kdo) esattamente come il nostro albero per la tigre: trova la regola, unifica X = jan, dimostra rodic(jan, Y), trova Y = petr e poi rodic(petr, Z) con il risultato eva.

8. Sistemi esperti

Un sistema esperto è una base di conoscenza scritta insieme a un esperto più un motore inferenziale, di solito con concatenazione all’indietro e con la possibilità di spiegare perché è arrivato a una conclusione: basta leggere l’albero che abbiamo disegnato sopra. I più noti erano tre:

  • DENDRAL (Stanford, dal 1965) determinava la struttura delle molecole dai dati di uno spettrometro di massa: il primo sistema che faceva il lavoro degli scienziati secondo le loro stesse regole.
  • MYCIN (Stanford, anni Settanta) diagnosticava le infezioni batteriche del sangue e consigliava antibiotici. Aveva circa seicento regole e, in una valutazione del 1979, le sue proposte si sono rivelate buone quanto quelle degli specialisti di Stanford, o migliori. Ciononostante non è mai stato usato in ospedale.
  • XCON (azienda DEC, dal 1980) componeva le configurazioni dei computer VAX in base all’ordine. Aveva migliaia di regole e, secondo l’azienda, faceva risparmiare decine di milioni di dollari all’anno.

La medicina però conosce di rado la certezza. MYCIN associava quindi a ogni regola un numero che diceva quanto l’esperto vi facesse affidamento:

Definizione — fattore di certezza

Il fattore di certezza CF ∈ [−1, 1] esprime il grado di fiducia in una conclusione: 1 vale di sicuro, −1 di sicuro non vale, 0 non lo sappiamo. Se due regole con fattori positivi CF1 e CF2 sostengono la stessa conclusione, il fattore risultante è

CF = CF1 + CF2 · (1 − CF1).

In parole semplici

Un indizio ti convince a 0,6, un secondo, indipendente, a 0,5. Insieme 0,6 + 0,5 · 0,4 = 0,8: il secondo indizio toglie metà dell’incertezza rimasta. I fattori di certezza non sono probabilità e non rispettano il teorema di Bayes; in seguito sono stati sostituiti dalle reti bayesiane, che nel programma hanno una parte propria.

CF = CF1 + CF2 · (1 − CF1)

CF1
la fiducia data dalla prima regola; la seconda regola non può abbassarla, solo aggiungere
CF2
quale parte dell’incertezza rimasta elimina la seconda regola; se si sommasse semplicemente, due indizi da 0,6 darebbero un assurdo 1,2
1 − CF1
l’incertezza rimasta dopo la prima regola; si può togliere ancora solo da essa, e per questo il risultato non supera mai 1
In modo equivalente 1 − CF = (1 − CF1) · (1 − CF2): le incertezze rimaste si moltiplicano. Per questo l’ordine delle regole non conta.
Esempio — tre indizi e una regola con premesse incerte

Tre indizi 0,6, 0,5 e 0,5: prima 0,6 + 0,5 · (1 − 0,6) = 0,8, poi 0,8 + 0,5 · (1 − 0,8) = 0,9. Verifica tramite le incertezze: 1 − 0,4 · 0,5 · 0,5 = 0,9.

Premesse incerte. In MYCIN (Shortliffe e Buchanan, 1975) una congiunzione di premesse riceve il fattore del suo anello più debole, e la conclusione di una regola riceve il fattore della regola moltiplicato per questo fattore minimo (la regola si applica solo se il minimo supera 0,2): CF(conclusione) = CF(regola) · mini CF(pi). Una regola con fattore 0,7 le cui premesse hanno fattori 0,9 e 0,6 contribuisce così alla conclusione con 0,7 · min(0,9; 0,6) = 0,42.

Alla fine degli anni Ottanta i limiti divennero evidenti. L’acquisizione della conoscenza era il collo di bottiglia: spesso l’esperto non sa esprimere il proprio know-how sotto forma di regole, e ogni regola costava ore di colloqui. I sistemi erano fragili: un passo fuori dal loro ambito non sapevano nulla, e non sapevano nemmeno di non sapere nulla. E migliaia di regole erano difficili da mantenere: una nuova regola poteva contraddirne in silenzio una vecchia. Il mercato dei sistemi esperti crollò e arrivò il secondo inverno dell’intelligenza artificiale. La risposta venuta dopo è l’opposto: non scrivere la conoscenza, ma impararla dai dati.

9. La conoscenza nell’intelligenza artificiale di oggi

  • Grafi di conoscenza. Dal 2012 Google risponde a molte ricerche dal suo grafo di conoscenza, una rete di fatti del tipo (Praga, capitale, Cechia). Wikidata, liberamente accessibile, ha oltre cento milioni di elementi. È una base di conoscenza, solo che al posto delle regole prevalgono i fatti.
  • Regole dove tutto deve poter essere verificato. I calcoli fiscali, le condizioni assicurative, l’approvazione dei crediti o le politiche di sicurezza si scrivono ancora oggi come regole: ogni decisione si può spiegare e difendere.
  • Modelli linguistici e conoscenza. Un modello linguistico contiene un’enorme quantità di conoscenza, ma distribuita nei pesi della rete: non la si può leggere né correggere un pezzo alla volta, e a volte il modello inventa con sicurezza. Per questo gli si collega la ricerca in una base di conoscenza (RAG), oppure strumenti e motori inferenziali che verificano il risultato.
  • L’IA neurosimbolica unisce le due cose: la rete riconosce ciò che vede e la logica ne deduce ciò che segue. Un esempio sono i sistemi che cercano dimostrazioni matematiche: il modello propone un passo e uno strumento formale lo verifica meccanicamente.

10. Riepilogo

  • Una base di conoscenza è un insieme di enunciati; KB ⊨ α significa che α vale in tutti i modelli della base. La verifica dei modelli lo controlla, ma al prezzo di 2n assegnazioni.
  • L’inferenza (⊢) lavora con gli enunciati invece che con i mondi. Vogliamo che sia corretta (non inventa nulla) e completa (non si lascia sfuggire nulla).
  • Per le clausole di Horn basta la concatenazione in avanti (dai fatti, guidata dai dati) o all’indietro (dall’obiettivo, guidata dalla domanda); quella in avanti gira in tempo lineare, quella all’indietro esamina solo ciò che è legato all’obiettivo.
  • Per tutta la logica proposizionale ci sono la risoluzione e la dimostrazione per assurdo; per le regole con variabili l’unificazione e Prolog.
  • I sistemi esperti hanno mostrato la forza e i limiti della conoscenza scritta a mano, e hanno preparato il terreno all’apprendimento dai dati.

Vuoi provarci? Fai scrivere a un agente IA un sistema esperto con concatenazione all’indietro che chieda dei fatti mancanti, e inventa regole tue per qualcosa che conosci bene.

La vedi diversamente? Scrivi a support@coden-app.com.

Un Agente sul tuo computer, guidato dal telefono