Bactracking
Algoritmi e Strutture Dati
Capitolo 16 - Backtrack
Alberto Montresor
Università di Trento
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License. To view a
copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.5/ or send a letter to Creative
Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.
© Alberto Montresor
1
Introduzione
Classi di problemi (decisionali, di ricerca, di ottimizzazione)
✦
Definizioni basate sul concetto di soluzione ammissibile: una soluzione che
soddisfa un certo insiemi di criteri
✦
Problemi “tipici”
✦
Contare le soluzioni ammissibili
✦
Costruire almeno una o tutte le soluzioni ammissibili
✦
Trovare le soluzioni ammissibili “più grandi”, “più piccole” o
in generale “ottimali”
✦
Esempio:
✦
Elencare tutti i sottoinsiemi di k elementi di un insieme S
✦
© Alberto Montresor
2
Problemi: commenti
Enumerazione
✦
Elencare algoritmicamente tutte le possibili soluzioni ammissibili
(spazio di ricerca)
✦
Costruire almeno una soluzione
✦
Si utilizza l'algoritmo per elencare tutte le soluzioni, fermandosi alla prima
✦
Contare le soluzioni
✦
In molti casi, è possibile contare in modo analitico
✦
Esempio: |S| = n, # sottoinsiemi di k elementi:
✦
In altri casi, si costruiscono le soluzioni e si contano
✦
© Alberto Montresor
3
Problemi: commenti


Trovare le soluzioni ottimali

Si costruiscono tutte le soluzioni e si valuta una funzione di costo

Si possono utilizzare altre tecniche:

Programmazione dinamica, greedy

Tecniche risolutive per problemi intrattabili
Esempi:

Circuito hamiltoniano (commesso viaggiatore)
© Alberto Montresor
4
Costruire tutte le soluzioni
Per costruire tutte le possibili soluzioni, si utilizza un approccio “brute-force”: si
esamina interamente lo spazio delle possibili soluzioni
✦
A volte è l'unica strada possibile
✦
La potenza dei computer moderni rende “affrontabili” problemi
di discrete dimensioni
✦
10!
✦
= 3.63 · 106
220 = 1.05 · 106
✦
permutazione di 10 elementi
sottoinsieme di 20 elementi
Inoltre, a volte non è necessario analizzare l'intero spazio delle soluzioni
✦
© Alberto Montresor
5
Backtracking
Filosofia:
✦
“Prova a fare qualcosa, e se non va bene, disfalo e prova qualcos'altro”
✦
Come funziona?
✦
Un metodo sistematico per iterare su tutte le possibili istanze di uno spazio di
ricerca
✦
E' una tecnica algoritmica che, come altre, deve essere personalizzata per ogni
applicazione individuale
✦
© Alberto Montresor
6
Backtracking
Organizzazione generale
✦
Una soluzione viene rappresentata come un vettore S[1..n]
✦
Il contenuto degli elementi S[i] è preso da un insieme di scelte C
dipendente dal problema
✦
Esempi:
✦
C insieme generico, possibili soluzioni permutazioni di C
✦
C insieme generico, possibili soluzioni sottoinsiemi di C
✦
C mosse di gioco, possibili soluzioni sequenze di mosse
✦
C archi di un grafo, possibili soluzioni percorsi sul grafo
✦
© Alberto Montresor
7
Backtracking
Come procedere: ad ogni passo, partiamo da una soluzione parziale S[1..k]
✦
Se S[1..k] è una soluzione ammissibile, la “processiamo” in qualche modo e
abbiamo finito
✦
Altrimenti:
✦
Se è possibile, estendiamo S[1..k] con una delle possibili scelte in una
soluzione S[1..k+1], e valutiamo la nuova soluzione ricorsivamente
✦
Altrimenti, “cancelliamo” (ritornando indietro nella ricorsione) l'elemento
S[k] (backtrack) e ripartiamo dalla soluzione S[1..k-1]
✦
Si può fare backtrack su più passi di ricorsione
✦
© Alberto Montresor
8
Backtracking
Spazio di ricerca ≡ albero di decisione
✦
Soluzioni ≡ foglie in un albero di decisione
✦
Soluzioni parziali ≡ nodi interni dell'albero di decisione
✦
Radice ≡ soluzione parziale vuota
✦
© Alberto Montresor
9
Backtracking
Lo spazio di ricerca può essere ridotto:
✦
“Rami” dell'albero che sicuramente non portano a soluzioni ammissibili possono
essere “potati” (pruned)
✦
La valutazione viene fatta nelle soluzioni parziali radici del sottoalbero
da potare
✦
© Alberto Montresor
10
Backtracking
Due possibili approcci:
✦
Ricorsivo:
✦
lavora tramite una visita in profondità nell'albero delle scelte, basata su un
approccio ricorsivo
✦
Iterativo: utilizza un approccio greedy, eventualmente tornando
sui propri passi
✦
Esempio: Inviluppo convesso
✦
Esempio: String matching
✦
© Alberto Montresor
11
Algoritmo generico


Ritorna true per bloccare
l'esecuzione, ad esempio
dopo la prima soluzione
Ritorna false per
le soluzioni parziali



© Alberto Montresor
C insieme di possibili
candidati per estendere
la soluzione
S: vettore contenente la
soluzione parziale S[1..i]
...: informazioni addizionali
12
Esempio 1
Problema
✦
Elencare tutti i sottoinsiemi di un insieme S
✦
Problemi
✦
Quali sono le scelte possibili?
✦
© Alberto Montresor
13
Esempio 1: commenti

Commenti



Non c'è pruning. Tutto lo spazio possibile viene esplorato.
Ma questo avviene per definizione
In che ordine vengono stampati gli insiemi?
E' possibile pensare ad una soluzione iterativa, ad-hoc?
(non-backtracking)
© Alberto Montresor
14
Esempio 1: versione iterativa
© Alberto Montresor
15
Esempio 2
Problema
✦
Elencare tutti i sottoinsiemi di dimensione k di un insieme S
✦
Versione iterativa
✦
Qual è il costo?
✦
Soluzione basata su backtracking
✦
Possiamo potare?
✦
© Alberto Montresor
16
Esempio 2: 1° tentativo
Qual è il problema?
© Alberto Montresor
17
Esempio 2: 2° tentativo
Qual è il problema?
© Alberto Montresor
18
Esempio 2: Tentativo corretto
© Alberto Montresor
19
Esempio 2: vantaggi
© Alberto Montresor
20
Esempio 2: sommario
Cosa abbiamo imparato?
✦
“Specializzando” l'algoritmo generico, possiamo ottenere una versione più
efficiente
✦
Versione efficiente per
✦
valori di k “piccoli” (vicini a 1)
✦
valori di k “grandi” (vicini a n)
✦
Miglioramento solo parziale verso n/2
✦
E' difficile ottenere la stessa efficienza con un algoritmo iterativo
✦
© Alberto Montresor
21
Esempio 3

Problema


Stampa di tutte le permutazioni di un insieme A
Rispetto al problema precedente:

L'insieme dei candidati dipende dalla soluzione parziale corrente
© Alberto Montresor
22
n Regine
Problema: posizionare n regine in una scacchiera n·n, in modo tale che nessuna
regina ne “minacci” un'altra.
✦
Commenti storici:
✦
Il problema classico, con n=8, è stato studiato, fra gli altri,
anche da Gauss
✦
Metodo
✦
Partiamo dall'approccio più stupido,
e mano a mano raffiniamo la soluzione.
✦
© Alberto Montresor
23
n Regine
Idea: ci sono n2 caselle dove piazzare una regina
✦
Algoritmo:
✦
S[1..n2] array binario
✦
controllo soluzione
✦
choices(S, n, i)
✦
S[i] = true ⇒ “regina in S[i]”
se i = n2
ritorna { true, false} se regina in
S[i] non minaccia le
regine in
S[1..i-1], { false }
altrimenti
# soluzioni per n=8
✦
264 ~ 1.84 · 1019
Commenti:
✦
Forse abbiamo un problema di rappresentazione?
✦
Matrice binaria molto sparsa
✦
© Alberto Montresor
24
n Regine
Idea: Dobbiamo piazzare n regine, ci sono n2 caselle
✦
Algoritmo
✦
S[1..n] coordinate in 1..n2
S[i] coordinata della regina i
controllo soluzione
se i = n
✦
✦
choices(S, n, i)
✦
# soluzioni per n=8
✦
ritorna posizioni legali
(n2)n = 648 = 248 ~ 2.81 · 1014
Commenti
✦
C'è un miglioramento, ma lo spazio è ancora grande...
✦
Problema: una soluzione “1-7-....” come si distingue da “7-1-....” ?
✦
© Alberto Montresor
25
n regine
Idea: la regina i non può stare in una casella “precedente” alla regina i-1
(S[i-1] < S[i])
✦
Algoritmo
✦
S[1..n] coordinate in 1..n2
S[i] coordinata della regina i
controllo soluzione
se i = n
✦
✦
choices(S, n, i)
✦
# soluzioni per n=8
✦
ritorna posizioni legali, S[i-1] < S[i]
(n2)n / n! = 648 / 40320 ~ 6.98 · 109
Commenti:
✦
Ottimo, abbiamo ridotto molto, ma si può ancora fare qualcosa
✦
© Alberto Montresor
26
n regine
Idea: ogni riga della scacchiera deve contenere esattamente una regina. Infatti non
ne può contenere 2 o più, e se ne contenesse 0 un'altra riga dovrebbe contenerne 2
✦
Algoritmo
✦
S[1..n] valori in 1..n
S[i] colonna della regina i
✦
controllo soluzione
✦
choices(S, n, i)
✦
# soluzioni per n=8
✦
se i = n
ritorna le colonne “legali”
nn = 88 ~ 1.67 · 107
Commenti
✦
Quasi alla fine
✦
© Alberto Montresor
27
n regine
Idea: anche ogni colonna deve contenere esattamente una regina;
i numeri 1..n devono apparire in S[1..n] come permutazione
✦
Algoritmo
✦
Modifichiamo l'algoritmo delle permutazioni per verificare anche le diagonali
✦
# soluzioni per n=8
✦
n! = 40320 ~ 4.03 · 104
# soluzioni effettivamente visitate: 15720
✦
QuickTime™ and a
GIF decompressor
are needed to see this picture.
© Alberto Montresor
28
n regine
Non è la soluzione migliore per ottenere una soluzione
✦
Minimum-conflicts heuristic
✦
Si muove il pezzo con il più grande numero di conflitti nella casella delle stessa
colonna con il numero minimo di conflitti
✦
Per n=106, circa 50 passi in media
✦
Assume che la soluzione iniziale sia “ragionevolmente buona”.
✦
Ogni regina viene messa nella colonna che ha il numero minimo di conflitti
con le regine già sulla scacchiera
✦
Al contrario, se tutte le regine sono sulla stessa riga, ci vogliono almeno n-1
spostamenti
✦
Questo algoritmo non garantisce che la terminazione sia sempre corretta
✦
© Alberto Montresor
29
Giro di cavallo
Problema:
✦
Si consideri ancora una scacchiera n·n; lo scopo è trovare un “giro di cavallo”,
ovvero un percorso di mosse valide del cavallo in modo che ogni casella venga
visitata al più una volta
✦
Soluzione:
✦
Tramite backtrack
✦
© Alberto Montresor
30
Giro di cavallo
Soluzione
✦
Matrice n∙n contenente le cui celle contengono
✦
0
se la cella non è mai stata visitata
i
se la cella è stata visitata al passo i
✦
✦
# soluzioni: 64! ~ 1089
✦
Ma: ad ogni passo ho al massimo 8 caselle possibili, quindi ne visito al più
864 ~1057
✦
In realtà, grazie al pruning ne visito molto meno
✦
© Alberto Montresor
31
Giro di cavallo
© Alberto Montresor
32
Sudoku
“Suuji wa dokushin ni kagiru”
✦
© Alberto Montresor
33
Sudoku
© Alberto Montresor
34
Sudoku
© Alberto Montresor
35
Generazione labirinti


Problemi

Come generare un labirinto in una scacchiera n·n?

Come uscire da un labirinto?
Esempio:
© Alberto Montresor
36
Un ultimo puzzle
Problema
✦
Si consideri ancora una scacchiera n·n, con n=2k
✦
Qualsiasi scacchiera di questo tipo con una cella rimossa può essere ricoperta da
triomini a forma di L
✦
Trovare un algoritmo che trovi una possibile
ricopertura della scacchiera
✦
© Alberto Montresor
37
Inviluppo convesso
Definizione
✦
Un poligono nel piano bidimensionale è convesso se ogni segmento di retta che
congiunge due punti del poligono sta interamente nel poligono stesso, incluso il
bordo.
✦
Inviluppo convesso (Convex hull)
✦
Dati n punti p1, . . . , pn nel piano, con n ≥ 3, trovare il più piccolo poligono
convesso che li contiene tutti
✦
© Alberto Montresor
38
Inviluppo convesso
Un algoritmo banale ma inefficiente
✦
Un poligono può essere rappresentato per mezzo dei suoi spigoli
✦
Si consideri la retta che passa per una coppia di punti i,j, che divide il piano in due
semipiani chiusi
✦
Se tutti i rimanenti n-2 punti stanno dalla stessa parte, allora lo spigolo Sij fa parte
dell’inviluppo convesso
✦
© Alberto Montresor
39
Inviluppo convesso
© Alberto Montresor
40
Algoritmo di Graham
Algoritmo di Graham (1972)
✦
Il punto con ordinata minima fa parte dell’inviluppo convesso
✦
Si ordinano i punti in base all’angolo formato dalla retta passante per il punto con
ordinata minima e la retta orizzontale
✦
© Alberto Montresor
41
© Alberto Montresor
42
Algoritmo di Graham
© Alberto Montresor
43
Algoritmo di Graham
© Alberto Montresor
44
Algoritmo di Graham
Complessità
✦
O(n log n), perchè dominato dalla fase di ordinamento degli angoli
✦
© Alberto Montresor
45
Scarica

Bactracking