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