Esercizio - Euristiche dell'8-puzzle e fattore di diramazione effettivo (slide del corso)
In questa pagina 7
Esercizio ricavato dalle slide del corso di Intelligenza Artificiale, Ing. dell'Informazione UniPD, sul puzzle dell'8: calcolo delle due euristiche (tessere fuori posto e distanza di Manhattan) sullo stato delle slide, prime espansioni di A∗, dominanza, fattore di diramazione effettivo con i dati misurati. Teoria in Ricerca informata - greedy best-first, A* ed euristicheLa ricerca informata usa una funzione euristica h(n) che stima il costo da n all'obiettivo. Greedy best-first espande il nodo con h minima (f = h): veloce ma non ottima né in generale completa. A∗ usa f = g + h e, con h ammissibile (mai sopra il costo vero) e, sul grafo con tabella dei raggiunti, consistente, è completa e ottima; il fattore di diramazione effettivo b∗ misura la qualità di h, e un'euristica che ne domina un'altra espande meno nodi. A∗ pesato (f = g + W h) rinuncia all'ottimalità per espandere meno nodi. Per i problemi in cui conta solo lo stato finale esiste la ricerca locale (hill climbing, simulated annealing, beam search, algoritmi genetici). In appendice, cenni di ricerca avversaria (minimax e potatura alfa-beta).Ricerca informata - greedy best-first, A* ed euristiche →; la formulazione del problema è in 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 →. Tutti i numeri sono verificati con il programma in fondo.
Testo
Si consideri il puzzle dell'8 con stato iniziale e obiettivo come in figura (la casella vuota è _):
- Calcolare (numero di tessere fuori posto) e (distanza di Manhattan totale: per ogni tessera da 1 a 8, il numero di caselle, righe più colonne, dalla posizione finale).
- Mostrare che e sono ammissibili e che domina .
- Con A∗ e , scrivere i quattro successori di con , , .
- Risolvere con ampiezza, A∗() e A∗() e confrontare i nodi generati e il fattore di diramazione effettivo.
- Verificare con la definizione i valori di della tabella delle slide.
Punto 1 - le due euristiche
Posizioni come (riga, colonna) da in alto a sinistra. In : 7 in , 2 in , 4 in , 5 in , vuoto in , 6 in , 8 in , 3 in , 1 in . Nell'obiettivo: 1 in , 2 in , 3 in , 4 in , 5 in , 6 in , 7 in , 8 in .
| tessera | in | nell'obiettivo | fuori posto? | distanza di Manhattan |
|---|---|---|---|---|
| 1 | sì | |||
| 2 | sì | |||
| 3 | sì | |||
| 4 | sì | |||
| 5 | sì | |||
| 6 | sì | |||
| 7 | sì | |||
| 8 | sì |
Tutte le 8 tessere sono fuori posto: . La somma delle distanze è come nella slide. La casella vuota non si conta (non è una tessera).
Punto 2 - ammissibilità e dominanza
Ogni mossa sposta una tessera di una casella. Quindi:
- una tessera fuori posto richiede almeno una mossa: servono almeno mosse, ;
- una tessera a distanza di Manhattan dalla sua casella richiede almeno mosse, e ogni mossa avvicina una sola tessera: servono almeno mosse, .
Entrambe valgono 0 solo nell'obiettivo: sono ammissibili. Dominanza: una tessera fuori posto ha distanza di Manhattan almeno 1, quindi per ogni stato (verificato anche su 2000 stati casuali). Quindi domina e A∗() espande al più i nodi di A∗(), perché A∗ espande tutti i nodi con (e alcuni con ), e . Qui .
Euristiche da problemi rilassati. è il costo esatto del problema in cui una tessera può saltare dovunque in una mossa; è il costo esatto di quello in cui una tessera si può muovere di una casella anche sopra una casella occupata. Meno vincoli, costo minore: per questo non sovrastimano.
Punto 3 - i successori di con A∗()
Il vuoto è in e ha quattro mosse. Ogni successore ha (un passo di costo 1).
| mossa del vuoto | stato | |||
|---|---|---|---|---|
| su (scambia con 2) | 8 | 19 | ||
| giù (scambia con 3) | 8 | 17 | ||
| sinistra (scambia con 5) | 8 | 17 | ||
| destra (scambia con 6) | 8 | 17 |
Come cambia : spostare la tessera 2 verso il basso la allontana dalla sua casella (distanza da 1 a 2: ); spostare la 3 verso l'alto la avvicina (, distanza da 2 a 1) e così per la 5 e la 6: . Tre successori hanno la stessa : A∗ ne sceglie uno secondo la regola di pareggio. Si noti che è anche : nessuna mossa ha peggiorato la stima. Con consistente ogni mossa cambia di , quindi non decresce lungo un cammino e arriva a sull'obiettivo.
Punto 4 - risoluzione e confronto
Soluzione ottima: 26 mosse (il vuoto: sinistra, su, destra, giù, giù, sinistra, su, destra, destra, su, sinistra, sinistra, giù, destra, destra, giù, sinistra, sinistra, su, destra, destra, su, sinistra, giù, sinistra, su; rieseguendo le mosse si arriva all'obiettivo; con un altro criterio di pareggio la sequenza può cambiare, la lunghezza no, ed è confermata dall'ampiezza). Nodi generati (con tabella dei raggiunti) e risolvendo :
| algoritmo | nodi generati | nodi espansi | |
|---|---|---|---|
| ampiezza | 177 809 | ||
| A∗ con | 62 570 | 44 989 | |
| A∗ con | 6 130 | 3 978 |
A∗() genera circa 10 volte meno nodi di A∗() e circa 29 volte meno dell'ampiezza, e il suo fattore di diramazione effettivo è il più vicino a 1 (il fattore di diramazione massimo del puzzle è 4, con il vuoto al centro). Una sola esecuzione, non una media su 100 puzzle come nelle slide: i valori hanno lo stesso ordine di grandezza della riga della tabella (: , , ).
Con il peso. Con , sullo stesso : trova ancora 26 mosse con 1202 nodi; trova 30 mosse con 638 nodi (circa 10 volte meno nodi, il 15% di mosse in più): meno nodi ma niente ottimo (Ricerca informata - greedy best-first, A* ed euristicheLa ricerca informata usa una funzione euristica h(n) che stima il costo da n all'obiettivo. Greedy best-first espande il nodo con h minima (f = h): veloce ma non ottima né in generale completa. A∗ usa f = g + h e, con h ammissibile (mai sopra il costo vero) e, sul grafo con tabella dei raggiunti, consistente, è completa e ottima; il fattore di diramazione effettivo b∗ misura la qualità di h, e un'euristica che ne domina un'altra espande meno nodi. A∗ pesato (f = g + W h) rinuncia all'ottimalità per espandere meno nodi. Per i problemi in cui conta solo lo stato finale esiste la ricerca locale (hill climbing, simulated annealing, beam search, algoritmi genetici). In appendice, cenni di ricerca avversaria (minimax e potatura alfa-beta).Ricerca informata - greedy best-first, A* ed euristiche →).
Punto 5 - i delle slide
La tabella delle slide (dati medi su 100 puzzle per ogni profondità ) dà il numero di nodi generati e . Risolvendo per e date si ritrovano i valori stampati. Esempi:
- : BFS : dà ; A∗() dà ; A∗() dà .
- : BFS 6783 dà ; A∗() 678 dà ; A∗() 174 dà .
- : BFS 463 234 dà ; A∗() 202 565 dà ; A∗() 22 055 dà .
Su tutte le 12 righe (da a ) i 36 valori calcolati coincidono con quelli delle slide, salvo due scarti di (A∗() per : invece di ; per : invece di ), dovuti all'arrotondamento dei dati medi.
Per ogni profondità della tabella A∗() ha tra e , contro - di A∗(): l'euristica più informata tiene più vicino a 1.
Programma di verifica
import heapq, itertools
S = (7, 2, 4, 5, 0, 6, 8, 3, 1) # 0 = casella vuota
G = (0, 1, 2, 3, 4, 5, 6, 7, 8)
def successori(s):
z = s.index(0); r, c = divmod(z, 3)
for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
rr, cc = r + dr, c + dc
if 0 <= rr < 3 and 0 <= cc < 3:
l = list(s); l[z], l[rr*3 + cc] = l[rr*3 + cc], l[z]
yield tuple(l)
def h1(s): return sum(1 for i, t in enumerate(s) if t and t != G[i])
def h2(s):
return sum(abs(i//3 - G.index(t)//3) + abs(i%3 - G.index(t)%3) for i, t in enumerate(s) if t)
def astar(start, h, w=1):
conta = itertools.count()
fr = [(w*h(start), next(conta), 0, start)]
best = {start: 0}
generati = 1
while fr:
f, _, g, s = heapq.heappop(fr)
if g > best[s]: continue
if s == G: return g, generati
for t in successori(s):
if t not in best or g + 1 < best[t]:
best[t] = g + 1; generati += 1
heapq.heappush(fr, (g + 1 + w*h(t), next(conta), g + 1, t))
def b_star(N, d): # N + 1 = 1 + b + ... + b^d, per bisezione
lo, hi = 1.0001, 10
for _ in range(100):
m = (lo + hi) / 2
if sum(m**i for i in range(d + 1)) < N + 1: lo = m
else: hi = m
return lo
print(h1(S), h2(S)) # 8 18
for nome, h in (('h1', h1), ('h2', h2)):
d, N = astar(S, h)
print(nome, d, N, round(b_star(N, d), 3)) # h1 26 62570 1.463 / h2 26 6130 1.325
print(astar(S, h2, w=1.4), astar(S, h2, w=2)) # (26, 1202) (30, 638)
print(round(b_star(24, 6), 2), round(b_star(12, 2), 2)) # 1.42 3.0Versione ripasso
- Stato : ; obiettivo . Posizioni (riga, colonna) da .
- (tutte le 8 tessere fuori posto). (tessere 1..8: da a distanza 3; 2: 1; 3: 2; 4: 2; 5: 2; 6: 3; 7: 3; 8: 2). Il vuoto non si conta.
- Ammissibili: ogni mossa sposta una tessera di una casella, quindi servono almeno e almeno mosse. Dominanza: (una tessera fuori posto dista almeno 1); A∗() espande al più i nodi di A∗() perché espande tutti i nodi con . Da problemi rilassati (tessere che saltano; tessere che si muovono su caselle occupate).
- Successori di (): vuoto su (, ), giù (, ), sinistra (, ), destra (, ); tre pareggi a .
- Risultati su (26 mosse ottime): ampiezza nodi (); A∗() (); A∗() (), circa 10 volte meno di A∗(). Con peso: dà 26 mosse e 1202 nodi, dà 30 mosse e 638 nodi.
- : soluzione di (per bisezione). Esempi: , : ; , : . Tabella delle slide ritrovata riga per riga (: BFS 128 , A∗() 24 , A∗() 19 ; : 463 234, 202 565, 22 055 , , ), con due scarti di dovuti alle medie.
- Errori tipici: contare il vuoto come tessera; usare la distanza euclidea invece di Manhattan; dimenticare che va con nodi (si conta anche la radice); calcolare con sbagliata (è la profondità della soluzione, non il numero di nodi espansi).