Algoritmi e Strutture Dati Capitolo 17 - Algoritmi probabilistici 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 ✦ “Audentes furtuna iuvat” - Virgilio ✦ ✦ Abbiamo già incontrato il concetto di casualità ✦ ✦ ✦ Se non sapete quale strada prendere, fate una scelta casuale Analisi del caso medio - si calcola una media su tutti i possibili dati di ingresso, dopo aver individuato una distribuzione di probabilità per essi Esempio: caso medio Quicksort, si assume che tutte le permutazioni siano equiprobabili Negli algoritmi probabilistici ✦ Il calcolo delle probabilità è applicato non ai dati di input, ma ai dati di output ✦ Due possibilità ✦ Algoritmi corretti, il cui tempo di funzionamento è probabilistico ✦ Algoritmo la cui correttezza è probabilistica © Alberto Montresor 2 Esempio - espressione polinomiale nulla ✦ ✦ ✦ Definizione: data un’espressione algebrica polinomiale p(x1 , ... , xn) in n variabili, determinare se p è identicamente nulla oppure no Discussione ✦ Assumiamo che non sia in forma di monomi - altrimenti è banale ✦ Gli algoritmi basati su semplificazioni sono molto complessi Algoritmo ✦ Si genera una n-pla di valori v1, ..., vn ✦ Si calcola x= p(v1 , ... , vn) ✦ ✦ ✦ Se x ≠ 0, p non è identicamente nullo ✦ Se x = 0, p potrebbe essere identicamente nullo Se vi = random(1, 2d), dove d è il grado massimo del polinomio, allora la probabilità di errore non supera 1/2. Si ripete k volte, riducendo la probabilità di errore a (1/2)k © Alberto Montresor 3 Statistica ✦ ✦ Algoritmi statistici su vettori: Estraggono da un vettore numerico alcune caratteristiche statisticamente rilevanti Esempi ✦ ✦ Media: µ = (A[1] + A[2] + ... + A[n])/n n 2 1X = (A[i] n i=1 µ)2 ✦ Varianza (sample variance): ✦ Moda: il valore più frequente (o i valori) ✦ Mediano: il valore che occuperebbe la posizione ⎡n/2⎤ se l'array fosse ordinato Selezione: ✦ Dato un array A[1..n] di valori distinti e un valore 1 ≤ k ≤ n, trovare l'elemento che è maggiore di esattamente k-1 elementi © Alberto Montresor 4 Selezione: casi particolari ✦ Ricerca del minimo, massimo ✦ T(n) = n-1 = θ(n) confronti ✦ Possiamo dimostrare che questo algoritmo è ottimale? ✦ ✦ ✦ Idea: scelta del minimo come un “torneo” Tutti gli elementi (tranne il vincitore) deve perdere almeno un “partita” Quindi il problema è Ω(n) © Alberto Montresor min. Si confronta min con gli elementi co incontra un elemento minore, si aggiorna minimo dell’insieme, che viene restituito al I TEM min(I TEM[ ] A, integer n) I TEM min A[1] for integer i 2 to n do if A[i] < min then min A[i] return min Ricerca della posizione Come sopra, sup vettore. L’algoritmo proposto per risolvere q 5 for integer i ⇤ 1 to 8 do nx casi ⇤ xparticolari + mx [i] Selezione: ny ⇤ y + my [i] if 1 ⇥ nx ⇥ 8 and 1 ⇥ ny ⇥ 8 and S[nx , ny ] = 0 then ✦ Ricerca del secondo minimo C.insert(i) ✦ Trovare il secondo elemento più piccolo dell'array return C ✦ Domanda: Analisi del caso peggiore e medio I TEM min2(I TEM[ ] A, integer n) I TEM min1 ⇤ A[1] I TEM min2 ⇤ A[2] if min2 < min1 then min1 ⌅ min2 for integer i ⇤ 3 to n do if A[i] < min2 then min2 ⇤ A[i] if min2 < min1 then min1 ⌅ min2 return min2 © Alberto Montresor 6 Selezione: casi particolari ✦ Ricerca del secondo minimo ✦ ✦ L'albero del torneo permette di trovare il secondo minimo in O(n + log n) confronti nel caso pessimo 5 3 Dimostrazione 6 7 ✦ n passi necessari per la ricerca del minimo ✦ Siano M e S il minimo e il secondo minimo ✦ Sicuramente c'è stato un “incontro” fra M e S, dove M ha “vinto” ✦ ✦ 2 4 8 Se così non fosse, esisterebbe un valore X<S che ha “battuto” S → assurdo dalla definizione di S Quindi, basta cercare nei log n valori “battuti” direttamente da M per trovare il secondo minimo. Totale: O(n + log n) © Alberto Montresor 7 Selezione per piccoli valori di k ✦ Intuizione ✦ L'albero del torneo può essere “simulato” da uno heap ✦ L'algoritmo può essere generalizzato a valori generici di k > 2 ✦ Complessità computazionale: O(n + k log n) ✦ ✦ Se k = O(n/log n), il costo è O(n) ✦ Non va ancora bene per k = n/2 Codice heapselect(ITEM[] A, integer n, integer k) buildHeap(A) for i := 1 to k-1 do deleteMin(A, n) return min(A) © Alberto Montresor 8 Per trovare il k-esimo elemento più piccolo senza ordinare il vettore, si può utilizzare la procedura perno() [cfr. § 12]. Ricordiamo che la procedura perno(A, primo, ultimo) scambia Selezione tra loro elementi di A[primo . . . ultimo] e restituisce l’indice j del “perno” tale che A[i] A[j], per primo i j, e A[i] A[j], per j i ultimo. La seguente procedura selezione(), u Ideada Hoare (1961), richiama la perno() ed individua cosı̀ il q-esimo elemento più picproposta colo di uA[primo . . . ultimo], dove q = j primo + 1alè Quicksort il numero di elementi di A[primo . . . j]. Approccio divide-et-impera simile Se k q, allora selezione() è riapplicata ad A[primo . . . j]; se invece k > q, allora selezione() u Ma problema diricercare ricerca, ilnon necessario cercare entrambe è riapplicata ad essendo A[j + 1 . .un . ultimo], ma per (k è q)-esimo elemento piùin piccolo. La le chiamata iniziale è selezione 1, n, k). partizioni, basta(A, cercare in una sola di esse I TEM selezione(I TEM[ ] A, integer primo, integer ultimo, integer k) if primo = ultimo then primo 1 return A[primo] else integer j perno(A, primo, ultimo) integer q j primo + 1 if k = q then return A[j] else if k < q then return selezione(A, primo, j 1, k) else return selezione(A, j + 1, ultimo, k q) © Alberto Montresor j ultimo n q 9 return A[j] else if k < q then Complessità return selezione(A, primo, j 1, k) else ✦ Caso pessimo: O(n2) return selezione(A, j + 1, ultimo, k q) ✦ Caso ottimo: O(n) Caso medio Assumendo che perno() restituisca con la stessa probabilità una qualsiasi posizione j d ✦ Assumiamo che perno() restituisca con la stessa probabilità una qualsiasi ettore A, il numero medio di confronti T (n) tra elementi di A effettuati da selezione() è da posizione j del vettore A alla relazione di ricorrenza ✦ per n = 0, 1 T (n) = 0, n T (n) = n n 1X 1+ T (max{q n q=1 2 1+ n n X1 T (q), 1, n q}) per n 2 q=bn/2c nfatti, nel caso n sia pari, è facile vedere che i valori bn/2c, bn/2c + 1, . . . , n 1 vengon ttenuti due volte dall’espressione max{q 1, n q}, per q = 1 . . . n; se invece n è dispari © Alberto Montresor 10 ineare nella lunghezza della porzione di A, il numero complessivo di confronti dovr cereDimostrazione come n + n/2 + n/4 + · · · + 1 2n. Pertanto, una soluzione promettente di T la quale tentare sembra essere O(n). ✦ Per sostituzione Tentiamo quindi con T (n) cn per qualche costante c. La base dell’induzione è mente verificata perché 0 = T (0) = T (1) c. Si assuma che valga l’ipotesi indu T (n0 ) cn0 , 8n0 < n ) cq per ogni q n 1. Sostituendo, si ricava: 0 1 bn/2c 1 n 1 n 1 X X X 2c 2c @ T (n) n 1 + q n+ q qA n n q=1 q=1 q=bn/2c ✓ ◆ 2c n (n 1) bn/2c (bn/2c 1) =n+ n 2 2 c n+ n (n 1) (n/2 + 1) (n/2) n = n + c (n 1) (c/2) (n/2 + 1) = n + cn c cn/4 c/2 ✓ ◆ 1 3 3 = cn + c 4 2n Poiché l’ultima quantità tra parentesi è minore di 1 per n sufficientemente grande e per 11 ortuna scelta di c, la relazione T (n) cn vale per ogni n m per le stesse costa © Alberto Montresor Versione probabilistica ✦ ✦ Siamo partiti dall’assunzione ✦ j assume equiprobabilisticamente tutti i valori compresi fra 1 e n ✦ E se non è vero? Lo forziamo noi ✦ ✦ A[random(primo, ultimo)] ↔ A[primo] Questo accorgimento vale anche per QuickSort © Alberto Montresor 12 Selezione in tempo pessimo lineare ✦ ✦ Algoritmo deterministico ✦ Deterministico: non necessita di randomizzazione ✦ Algoritmo complesso, con fattori coinvolti molto alti ✦ Interessante dal punto di vista della tecnica Sviluppiamo l'idea ✦ ✦ Supponiamo di avere un algoritmo “black box” che mi ritorni il mediano di n valori in tempo O(n) Domanda ✦ Potrei utilizzarlo per ottimizzare il problema della selezione? ✦ Che complessità otterrei? © Alberto Montresor 13 Selezione in tempo pessimo lineare ✦ ✦ Se conoscessi tale algoritmo ✦ il problema della selezione sarebbe quindi risolto ✦ ... ma dove lo trovo un simile algoritmo? Rilassiamo le nostre pretese ✦ ✦ ✦ Supponiamo di avere un algoritmo “black box” che mi ritorni un valore che dista al più n/4 dal mediano (nell'ordinamento) Domanda ✦ Potrei utilizzarlo per ottimizzare il problema della selezione? ✦ Che complessità otterrei? Un algoritmo del genere esiste! © Alberto Montresor 14 Selezione deterministica - cenni ✦ L'idea dell'algoritmo ✦ ✦ Trova il mediano mi di ogni gruppo Si ✦ Tramite una chiamata ricorsiva, trova il mediano M dei mediani mi ✦ ✦ Suddividi i valori in gruppi di 5. Chiameremo l'i-esimo gruppo Si, con i ∈ [1, ⎡n/5⎤] Usa M come pivot e richiama l'algoritmo ricorsivamente sull'array opportuno, come nella selezione() randomizzata Caso base ✦ Possiamo utilizzare un algoritmo d'ordinamento per trovare il mediano quando la dimensione scende sotto una certa soglia © Alberto Montresor 15 Selezione deterministica I TEM select(I TEM[ ] A, integer primo, integer ultimo, integer k) % Se la dimensione è inferiore ad una soglia (10), ordina il vettore e % restituisci il k-esimo elemento di A[primo . . . ultimo] if ultimo primo + 1 10 then InsertionSort(A, primo, ultimo) % Versione con indici inizio/fine return A[primo + k 1] % Divide A in dn/5e sottovettori di dim. 5 e calcola la mediana di ognuno di essi M new integer[1 . . . dn/5e] for i 1 to dn/5e do M [i] median5(A, primo + (i 1) · 5, ultimo) % Individua la mediana delle mediane e usala come perno I TEM m select(M, 1, dn/5e, ddn/5e/2e) integer j perno(A, primo, ultimo, m) % Versione con m in input % Calcola l’indice q di m in [primo . . . ultimo ] % Confronto q con l’indice cercato e ritorna il valore conseguente integer q j primo + 1 if q = k then return m © Alberto Montresor else if q < k then 16 M new integer[1 . . . dn/5e] for i 1deterministica to dn/5e do Selezione M [i] median5(A, primo + (i 1) · 5, ultimo) % Individua la mediana delle mediane e usala come perno I TEM m select(M, 1, dn/5e, ddn/5e/2e) integer j perno(A, primo, ultimo, m) % Versione con m in input % Calcola l’indice q di m in [primo . . . ultimo] % Confronto q con l’indice cercato e ritorna il valore conseguente integer q j primo + 1 if q = k then return m else if q < k then return select(A, primo, q 1, k) else return select(A, q + 1, ultimo, k q) © Alberto Montresor 17 Seleziona deterministica - cenni ✦ Lemma 1 ✦ ✦ Lemma 2 ✦ ✦ La prima chiamata ricorsiva dell'algoritmo select() viene effettuata su circa n/5 (esattamente ⎡n/5⎤) elementi Lemma 3 ✦ ✦ Il calcolo dei mediani M[] richiede al più 6⎡n/5⎤ confronti. La seconda chiamata ricorsiva dell'algoritmo select() viene effettuata al massimo su 7n/10 elementi (esattamente n - 3⎡⎡n/5⎤/2⎤) Teorema ✦ L'algoritmo select() esegue nel caso pessimo O(n) confronti ✦ Equazione di ricorrenza: T(n) ≤ T(n/5) + T(7n/10) + 11/5n ✦ E' possibile dimostrare che T(n) = O(n) © Alberto Montresor 18 Alcune note storiche ✦ Il problema della selezione nella storia... ✦ ✦ ✦ Nel 1883 Lewis Carroll (!) notò che il secondo premio nei tornei di tennis non veniva assegnato in maniera equa. Nel 1932, Schreier dimostrò che n + log n - 2 incontri sono sempre sufficienti per trovare il secondo posto Nel 1973, a opera di Blum, Floyd, Pratt, Rivest e Tarjan, appare il primo algoritmo deterministico © Alberto Montresor 19 Bucket sort ✦ Ipotesi sull'input ✦ ✦ ✦ I valori da ordinare sono numeri reali uniformemente distribuiti nell'intervallo [0, 1) Qualunque insieme di valori distribuiti uniformemente può essere normalizzato nell'intervallo [0, 1) Idea ✦ ✦ ✦ Dividere l'intervallo in n sottointervalli di dimensione 1/n, detti bucket, e poi distribuire gli n numeri nei bucket Per l'ipotesi di uniformità, il numero atteso di valori nei bucket è 1 I singoli bucket possono essere ordinati con Insertion Sort © Alberto Montresor 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 20