Introduzione Algoritmi e Strutture Dati ✦ “Audentes furtuna iuvat” - Virgilio ✦ ✦ Capitolo 17 - Algoritmi probabilistici Abbiamo già incontrato il concetto di casualità ✦ ✦ Alberto Montresor Università di Trento ✦ 1 Esempio - espressione polinomiale nulla ✦ ✦ ✦ 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à 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 Se non sapete quale strada prendere, fate una scelta casuale ✦ Algoritmi corretti, il cui tempo di funzionamento è probabilistico ✦ Algoritmo la cui correttezza è probabilistica 2 © Alberto Montresor Statistica Definizione: data un’espressione algebrica polinomiale p(x1 , ... , xn) in n variabili, determinare se p è identicamente nulla oppure no ✦ Discussione ✦ Algoritmi statistici su vettori: Estraggono da un vettore numerico alcune caratteristiche statisticamente rilevanti Esempi ✦ Assumiamo che non sia in forma di monomi - altrimenti è banale ✦ ✦ Gli algoritmi basati su semplificazioni sono molto complessi ✦ 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 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 ✦ Media: µ = (A[1] + A[2] + ... + A[n])/n n 2 1X = (A[i] n i=1 µ)2 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 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 © 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) min. Si confronta min con gli elementi compresi for fra integer le posizioni i ⇤ 12toe8n; doogni volta che si incontra un elemento minore, si aggiorna il minimo parziale. Al termine, min contiene il n ⇤ x + m [i] x Selezione:x casi particolari minimo dell’insieme, che viene restituito al chiamante. 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) I TEM min(I TEM[ ] A, integer n) Trovare il secondo elemento più piccolo dell'array return C % Minimo parziale Domanda: Analisi del caso peggiore e medio ✦ I TEM min A[1] for integer i 2 to n do if A[i] < min then min A[i] ✦ I TEM min2(I TEM ] A, integer n) parziale % [ Nuovo minimo I TEM min1 ⇤ A[1] return min I TEM min2 ⇤ A[2] if min2 < min1 then min1 ⌅ min2 for integer i ⇤ 3 to n do if A[i] < min2 then Ricerca della posizione Come sopra, supponiamo che la sequenza sia memorizzata in un 2 ⇤ A[i] vettore. L’algoritmo proposto per risolvere questo problemamin prende il nome di ricerca binaria if min2 < min1 then min1 ⌅ min2 return min2 5 © Alberto Montresor Selezione: casi particolari ✦ Selezione per piccoli valori di k Ricerca del secondo minimo ✦ ✦ ✦ 5 3 Dimostrazione n passi necessari per la ricerca del minimo 6 7 ✦ Siano M e S il minimo e il secondo minimo ✦ Sicuramente c'è stato un “incontro” fra M e S, dove M ha “vinto” ✦ ✦ 2 L'albero del torneo permette di trovare il secondo minimo in O(n + log n) confronti nel caso pessimo ✦ 6 © Alberto Montresor 4 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) 8 ✦ Se così non fosse, esisterebbe un valore X<S che ha “battuto” S → assurdo dalla definizione di S ✦ 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) Quindi, basta cercare nei log n valori “battuti” direttamente da M per trovare il secondo minimo. Totale: O(n + log n) 10 © Alberto Montresor 7 © 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 Idea proposta da Hoare (1961), richiama la perno() ed individua cosı̀ il q-esimo elemento più piccolo 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 (A, 1, n, k). partizioni, basta cercare in una sola di esse I TEM selezione(I TEM[ ] A, integer primo, integer ultimo, integer k) 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 vettore A, il numero medio di confronti T (n) tra elementi di A effettuati da selezione() è da posizione j del vettore A dalla relazione di ricorrenza ✦ if primo = ultimo then primo j ultimo n 1 return A[primo] else q integer j perno(A, primo, ultimo) Algoritmi e Strutture di Dati integer q j primo + 1 if k = q then return A[j] ori bn/2c+1, bn/2c+2, . . . , n 1 vengono ottenuti due volte, mentre bn/2c viene ottenuto else if k < q then volta sola –return da cui la disequazione. selezione (A, primo, j 1, k) else un ragionamento informale per cercare di ricavare una buona soluzione sulla Effettuiamo return selezione(A, j + 1, ultimo, k q) per n = 0, 1 T (n) = 0, n T (n) = n n 1+ 1X T (max{q n q=1 2 1+ n n X1 T (q), 1, n q}) per n 2 q=bn/2c le applicare la tecnica di dimostrazione per tentativi. In media, selezione() dovrebbe Infatti, essere nel caso n sia pari, è facile vedere che i valori bn/2c, bn/2c + 1, . . . , n 1 vengon ottenuti iamata ogni volta su una porzione dimezzata del vettore A. Poiché la perno() richiede tem- due volte dall’espressione max{q 1, n q}, per q = 1 . . . n; se invece n è dispari 9 10 © Alberto Montresor © Alberto Montresor che perno()della restituisca con la stessa una complessivo qualsiasi posizione del ineareAssumendo nella lunghezza porzione di A,probabilità il numero di jconfronti dovrebbe vettore A, il numero medio di confronti T (n) tra elementi di A effettuati da selezione() è dato cere come n + n/2 + n/4 + · · · + 1 2n. Pertanto, una soluzione promettente di T (n) Dimostrazione Versione probabilistica dalla relazione di ricorrenza la quale tentare sembra essere O(n). ✦ Per sostituzione T (n) = 0,T (n) cn per qualche costante per n =c.0, 1La base dell’induzione è ba✦ Siamo partiti dall’assunzione Tentiamo quindi con n 1 1TX mente verificata perché 0 = (0)T (max{q, = T (1)n q})c. Si assuma che valga l’ipotesi induttiva ✦ j assume equiprobabilisticamente tutti i valori compresi fra 1 e n + T (n0 ) cnT0(n) , = 8nn0 <1 n n q=1 ) cq per ogni q n 1. Sostituendo, si ricava: ✦ E se non è vero? n 1 0 1 2 nX nper1n 2 bn/2c n 1 + X1 T (q), X 1 ✦ Lo forziamo noi 2c n 2c @ X q=dn/2e q n + T (n) n 1 + q qA n n q=1 ✦ A[random(primo, ultimo)] ↔ A[primo] q=1 perché max{q, n q} è uguale a q,q=bn/2c se q dn/2e, mentre è uguale ad n q, se q < dn/2e. ✓ ◆ 2c n (n 1) bn/2c (bn/2c 1) ✦ Questo accorgimento vale anche per QuickSort =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 una 11 ortuna scelta di c, la relazione T (n) cn vale per ogni n m per le stesse costanti c Montresor © Alberto Montresor © Alberto 12 Selezione in tempo pessimo lineare ✦ ✦ Selezione in tempo pessimo lineare Algoritmo deterministico ✦ Se conoscessi tale algoritmo ✦ Deterministico: non necessita di randomizzazione ✦ il problema della selezione sarebbe quindi risolto ✦ Algoritmo complesso, con fattori coinvolti molto alti ✦ ... ma dove lo trovo un simile algoritmo? ✦ Interessante dal punto di vista della tecnica 14 ✦ 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) integer[ ] scc(G RAPH G) ✦ Domanda S TACK S topSort(G) % Prima visita ✦ Potrei utilizzarlo per ottimizzare il problema della selezione? G RAPH GT Graph() % Calcolo grafo trasposto ✦ Che complessità otterrei? foreach u 2 G.V() do GT .insertNode(u) foreach u 2 G.V() do ✦ Un algoritmo del genere esiste! foreach v 2 G.adj(u) do GT .insertEdge(v, u) 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? return cc(GT , S) © Alberto Montresor 13 Selezione deterministica - cenni ✦ Trova il mediano mi di ogni gruppo Si ✦ Tramite una chiamata ricorsiva, trova il mediano M dei mediani mi ✦ ✦ % 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) Usa M come pivot e richiama l'algoritmo ricorsivamente sull'array opportuno, come nella selezione() randomizzata Caso base ✦ % 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) Possiamo utilizzare un algoritmo d'ordinamento per trovare il mediano quando la dimensione scende sotto una certa soglia © Alberto Montresor 14 © Alberto Montresor 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] Suddividi i valori in gruppi di 5. Chiameremo l'i-esimo gruppo Si, con i ∈ [1, ⎡n/5⎤] ✦ % Seconda visita Selezione deterministica L'idea dell'algoritmo ✦ Algoritmi e Strutture di Dati 15 % 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 to dn/5e do Selezione1deterministica M [i] median5(A, primo + (i Seleziona deterministica - cenni 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) ✦ ✦ 14 Alcune note storiche ✦ ✦ ✦ 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) 18 © Alberto Montresor ✦ Nel 1883 Lewis Carroll (!) notò che il secondo premio nei tornei di tennis non veniva assegnato in maniera equa. Ipotesi sull'input ✦ 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 ✦ ✦ ✦ 19 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 ✦ © Alberto Montresor La seconda chiamata ricorsiva dell'algoritmo select() viene effettuata al massimo su 7n/10 elementi (esattamente n - 3⎡⎡n/5⎤/2⎤) Bucket sort Il problema della selezione nella storia... ✦ La prima chiamata ricorsiva dell'algoritmo select() viene effettuata su circa n/5 (esattamente ⎡n/5⎤) elementi Lemma 3 ✦ 17 Il calcolo dei mediani M[] richiede al più 6⎡n/5⎤ confronti. Lemma 2 ✦ ✦ © Alberto Montresor Lemma 1 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