Backtracking: Sudoku
Università degli Studi di Milano
Marco Frasca
●
Il sudoku è un gioco la cui soluzione che consiste nel riempire
una griglia 9x9 con i numeri interi da 1 a 9, in modo che ogni
riga, ogni colonna e ogni sottogriglia principale 3x3 contenga
tutte le cifre da 1 a 9.
●
La griglia iniziale è popolata con alcune cifre, note come
“indizio”.
Backtracking: Sudoku
Università degli Studi di Milano
Marco Frasca
Backtracking: Sudoku
Università degli Studi di Milano
Marco Frasca
●
●
Per vedere come il programma lavora, usiamo come esempio una griglia 4x4, con
sottogriglie principali 2x2. (Una tale variante è detta Shidoku, perché “Shi” vuol
dire 4 in giapponese)
La figura a sinistra è la situazione iniziale. In figura 2 sono indicate in piccolo, in
base alla conoscenza attuale, le possibili mosse. Per esempio, la riga 2 contiene
un “3” e la colonna 1 contiene un “1”, quindi i candidati possibili in posizione
(2,1) sono “2” e “4.” Quattro celle contengono un solo candidato e sono dette
“singletons”. Questo primo esempio può essere risolto semplicemente riempiendo
i singleton. Ma non sempre la soluzione è così facile.
Backtracking: Sudoku
Università degli Studi di Milano
Marco Frasca
●
●
●
In basso un esempio di gioco in cui non ci sono singleton. Serve approccio di forza
bruta.
Esso può essere generato dall'istruzione MATLAB : X = diag(1:4)
Non essendoci singleton, applichiamo il backtracking ricorsivo. Scegliamo una delle
celle vuote e proviamo uno dei suoi valori candidati. Fissiamo l'ordine delle celle
da analizzare (per esempio alto-basso, sinistra-destra) e dei valori candidati (es. in
ordine crescente). La prima cella è la (2,1), inseriamo un “3”, ottenendo la
situazione in figura 3. Quindi chiamiamo il programma ricorsivamente. Il risultato
è in Figura 4. Comunque, tale soluzione dipende dalla scelta fatta prima della
chiamata ricorsiva. Altre scelte possono dare soluzioni diverse.
Backtracking: Sudoku
Università degli Studi di Milano
Marco Frasca
●
●
●
●
Chiaramente, una scelta tra le possibili candidate può portare ad
una configurazione senza soluzione (una cella non ha valori
candidati)
In tal caso occorre tornare indietro (backtrack) e provare un'altra
possibile scelta
L'algoritmo termina quando determina una soluzione o quando,
provate tutte le configurazioni, non si è trovata una soluzione
L'algoritmo Sudoku
1. Riempi tutti i singleton.
2. Esci se una cella non ha valori candidati
3. Scegli la prossima cella e riempila con il primo valore non ancora tentato.
4. Chiama il programma ricorsivamente
Backtracking: Sudoku
Università degli Studi di Milano
Marco Frasca
●
●
La funzione chiave è “candidates”
➢ Data la griglia X 9x9 che rappresenta il gioco, restituisce una matrice
di celle C in cui la cella (i,j) è un vettore che contiene i valori
candidati per tale cella
Per esempio, la cella (1,1) in Figura 1, restituirà C{1,1} = [1 5 7 9]
Backtracking: Sudoku
Università degli Studi di Milano
Marco Frasca
●
Si inizia provando un “1” nella cella (1,1). Dopo circa 2000 passi, la
ricorsione mette un “5” in posizione (1,1), e dopo circa 6000 passi, il
“7”. Dopo 12000 circa passi la situazione è quella in Figura 2. La
soluzione pare vicina, ma per la cella (1,9) non ci sono valori
candidati. E la ricorsione termina. infine, dopo circa 16000 passi,
l'algoritmo inserisce un “9” nella cella (1,1). Meno di 200 passi dopo
il programma raggiunge la soluzione in Figura 3.
Function candidates()
Università degli Studi di Milano
Marco Frasca
end
function [C,s,e] = candidates(X)
end
% X matrice iniziale 9x9
end
C = cell(9,9);
% Per ogni cella il numero di candidati.
% posizioni relative alla sottocella relativa a k
L = cellfun(@length,C);
% “,1” prende solo il primo indice che soddisfa
tri = @(k) 3*ceil(k/3-1) + (1:3);
s = find(X==0 & L==1, 1); % singleton
for j = 1:9
% vettore di indici per colonna.
for i = 1:9
e = find(X==0 & L==0, 1); % no candidati
% vettore di indici per colonna.
if X(i,j)==0
end % candidates
z = 1:9;
% nonzeros() : valori diversi da 0 in X(i,:) per
colonna, non gli indici
z(nonzeros(X(i,:))) = 0;
z(nonzeros(X(:,j))) = 0;
z(nonzeros(X(tri(i),tri(j)))) = 0;
C{i,j} = nonzeros(z)'; % ' è il trasposto
Function Sudoku()
Università degli Studi di Milano
Marco Frasca
function X = sudoku(X)
% Solve Sudoku using recursive backtracking.
% sudoku(X), expects a 9-by-9 array X.
[C,s,e] = candidates(X);
% riempie tutti i singleton
while ~isempty(s) && isempty(e)
X(s) = C{s}; % Xe C considerati come vettori
[C,s,e] = candidates(X);
end
if ~isempty(e) % Return per sudoku impossibile
return
end
if any(X(:) == 0) % Recursive backtracking.
Y = X;
% Trova la prima cella ancora vuota
z = find(X(:) == 0, 1);
for r = [C{z}] % Itera sui candidati
X = Y;
X(z) = r;
% inserisce un valore
X = sudoku(X);
% Chiamata ricorsiva
if all(X(:) > 0)
% Trovata soluzione.
return
end
end
end
end
Ottimizzazione di
Funzioni: Spazio Continuo
●
●
●
●
Università degli Studi di Milano
Marco Frasca
Cercare il minimo o il massimo di una funzione è un problema
che si ritrova piuttosto facilmente in ambito scientifico
Esistono molti metodi computazionali per affrontare questa
ricerca, in genere non esiste il metodo migliore, e molti
approcci sono possibili.
Spesso il calcolo dell'ottimo globale è computazionalmente
molto costoso
●
Funzione definita sullo spazio {0,1}n
● 2n possibili soluzioni
Una possibilità è usare un algoritmi di ricerca locale, che
garantiscono il raggiungimento di ottimi locali (ne parleremo)
Ottimizzazione di Funzioni
Università degli Studi di Milano
Marco Frasca
●
Molti algoritmi di minimizzazione discendono lungo la
superficie di energia e quindi riescono a localizzare il minimo
più vicino al punto d’inizio (quindi un minimo locale).
➢
Esempio: Metodo del gradiente
➢
La funzione deve essere derivabile
●
Gli ottimi locali possono essere di qualità molto bassa
●
Per localizzare più di un minimo o per localizzare un minimo
globale sono richiesti metodi che permettano di partire da
differenti condizioni iniziali
➢
È quindi molto costoso
Ottimizzazione di Funzioni
Università degli Studi di Milano
Marco Frasca
Per ovviare questo problema talvolta si usano algoritmi che non
scelgono sempre la soluzione ottima. Questi algoritmi sono in
genere probabilistici e non sempre hanno una caratterizzazione
matematica precisa.
● Una semplice tecnica algoritmica per la soluzione di problemi di
minimo (o massimo) è il cosiddetto “Particle Swarm
Optimization”
●
➢
➢
➢
➢
➢
Tecnica che non richiede la derivabilità della funzione
può essere utilizzata con successo in problemi di ottimizzazione irregolari,
rumorosi, variabili nel tempo, eccetera
Informalmente, una serie di agenti esplorano lo spazio delle soluzioni in
maniera tale da comportarsi come stormi di uccelli
nessuno degli agenti ha la capacità individuale di affrontare il problema
l’interazione collettiva è la base della soluzione
PSO
Università degli Studi di Milano
Marco Frasca
●
●
Ogni particella (punto nello spazio, possibile soluzione) che nel
suo movimento trova una valore migliore della funzione, si
trova di fronte a due alternative:
➢ allontanarsi dal gruppo per raggiungerlo (individualismo)
➢ rimanere nel gruppo (socialità)
Se più individui si dirigono verso la soluzione migliore, anche
altri membri possono cambiare la loro direzione per sfruttare
lo stesso miglioramento
Il gruppo cambia gradualmente direzione verso le zone più
promettenti, ovvero l’informazione gradualmente si propaga a
tutti
● la strategia di ricerca si esprime come bilanciamento tra i due
aspetti, individuale e collettivo
●
PSO
Università degli Studi di Milano
Marco Frasca
●
●
●
●
Ogni agente è caratterizzato da una posizione, ed una velocità (che
controlla come mi muovo nello spazio delle soluzioni).
La velocità dipende da parametri fra cui la migliore soluzione trovata
finora dall’agente e la migliore soluzione globalmente individuata
Gli agenti si muoveranno in tutte le tutte le direzioni cercando la soluzione
migliore. In genere è preferibile limitare la velocità massima per evitare
che gli agenti si disperdano troppo
Ad ogni posizione viene associata una fitness, cioè un valore che misura
la bontà di quella posizione (in genere il valore assunto dalla funzione in
quel punto)
PSO
Università degli Studi di Milano
Marco Frasca
●
➢
●
L’algoritmo procede per intervalli di tempo discreti. L’agente i al
tempo t mantiene
➢
La sua posizione pi,j (t), per ogni dimensione j
➢
La sua velocità velocità vi,j (t), per ogni dimensione j
➢
la posizione bi,· con fitness massima dell’agente i trovata fino al tempo corrente
➢
la posizione g· con fitness massima fra tutti gli agenti al tempo corrente .
Velocità e posizione dell’agente i vengono aggiornati al tempo t + 1
come segue per ogni dimensione j
➢
vi,j (t + 1) = w · vi,j (t) + c1 · rand() · (bi,j − pi,j (t)) + c2 · rand() · (gj − pi,j (t))
➢
pi,j (t + 1) = pi,j (t) + vi,j (t + 1)
Si noti che i valori casuali sono in genere diversi. Il valore w è detto inerzia,
ed è buona norma che lo si riduca iterazione dopo iterazione. Le costanti
c1 e c2 sono in genere settate ad un valore tra 1 e 2.
PSO
Università degli Studi di Milano
Marco Frasca
●
Algoritmo PSO (f,n, c1, c2, dim, w, n_iter) % dim =dimensione dello spazio
Inizializza i parametri e gli n agenti
Inizializza le posizioni e velocità degli n agenti in maniera casuale
t=1
while t < n_iter do
calcola fitness posizioni attuali
aggiorna migliori posizioni individuali
aggiorna migliore posizione globale
for i = 1 to n do
for j = 1 to dim do % aggiorno posizioni e velocità
vi,j (t + 1) = w ·vi,j (t)+c1 ·rand()·(bi,j (t)−pi,j (t))+c2 ·rand()·((gj (t))−pi,j (t))
pi,j (t + 1) = pi,j (t) + vi,j (t + 1)
end for
end for
t ←t +1
Riduci w
end while
Esercizi
Università degli Studi di Milano
Marco Frasca
●
1. Scrivere un programma in MATLAB che utilizzi l'algoritmo PSO descritto
per trovare il minimo della funzione
f (x, y) = (1 − x)2 + 100 · (y − x2 )2
●
●
Disegnate l’evoluzione della configurazione degli agenti (usate plot).
2. Scrivere un programma in MATLAB che utilizzi l'algoritmo PSO
descritto per trovare il minimo della funzione
3
1
2
(−0.2sqrt ∑ x i )
3 i=1
f (x 1, x 2, x 3)=−20⋅e
●
●
3
1
( ∑ cos (2πxi ))
3 i=1
−e
Disegnate l’evoluzione della configurazione degli agenti (usate plot3).
3. Modificare la funzione TSP_sim in modo da ottenere la soluzione al
problema TSP, cioè il cammino trovato deve essere hamiltoniano, cioè
deve poi ritornare nella città di partenza