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