Esponenziazione veloce per quadrature successive
In questa pagina 7
Sia un dominio e un operatore binario associativo, , con elemento neutro , cioè per ogni . Esempi: con (); matrici con (prodotto righe per colonne, ). L'operatore non deve essere commutativo.
Definizione (potenza). Per e :
Per , ( fattori), senza parentesi per l'associatività.
L'uguaglianza vale per associatività anche per operatori non commutativi (come il prodotto di matrici). Il modello di costo assegna costo a ogni applicazione di e costo al resto. Si cerca un algoritmo efficiente per .
Algoritmo basato sulla definizione
STUPID_POWER(x, n)
if n = 0 then return e
p <- x
for i <- 1 to n - 1 do
p <- x ∘ p
return pLa definizione è ricorsiva, ma è una ricorsione di coda, eliminabile in un ciclo. : lineare nell'esponente. Si vuole battere questo valore.
Proprietà di sottostruttura
Proprietà. Sia .
- Se è pari: .
- Se è dispari: .
Dimostrazione. Per : , perché l'associatività permette di raggruppare i fattori in due gruppi da . Per : , con un fattore in più. Nessuna ipotesi su oltre l'associatività.
La proprietà lega a : noto , bastano una applicazione di se è pari () e due se è dispari (). Per pari, a partire da la definizione richiederebbe ancora applicazioni, qui ne basta una: si quadra il valore. Gli algoritmi di questo tipo sono detti di squaring.
Algoritmo ricorsivo POWER
POWER(x, n)
if n = 0 then return e { BASE }
if n = 1 then return x
k <- floor(n / 2) { DIVIDE: nessun lavoro }
y <- POWER(x, k) { RECURSE }
if EVEN(n) then return y ∘ y { CONQUER }
else return y ∘ y ∘ xIl caso base sarebbe superfluo (si otterrebbe ricorsivamente), ma evita due applicazioni inutili di (con si farebbe ). La correttezza discende da quella della proprietà di sottostruttura.
Analisi
Il conquer costa al più (per dispari), il divide :
Per i valori ogni istanza generata è dispari (): il costo è a ogni livello, quindi il limite è raggiunto. La ricorrenza è del tipo del Master Theorem - enunciato, casi e applicazioniMaster Theorem per T(n) = aT(n/b) + w(n): si confronta w(n) con la funzione soglia n^(log_b a). Caso 1 (w minore di una potenza polinomiale): Theta(n^(log_b a)); caso 2 (w della stessa taglia): Theta(n^(log_b a) log n); caso 3 (w maggiore e regolare): Theta(w(n)). Prova completa dai livelli dell'albero, versione estesa (parti intere, n0 qualsiasi), esempi, e l'uso scorretto quando nessun caso si applica (w = n log n).Master Theorem - enunciato, casi e applicazioni → con , , : la soglia è , caso 2, e . Il Master Theorem copre dunque anche soluzioni logaritmiche; la stessa ricorrenza è quella della ricerca binaria. Il risultato è un miglioramento esponenziale rispetto a STUPID_POWER.
Conto esatto. Sia e il numero di bit a della rappresentazione binaria di . Per :
Dimostrazione per induzione su (vedi Dimostrazioni, induzione e invariantiTecniche di dimostrazione (esempio, controesempio, assurdo), induzione con casi base multipli, invarianti di ciclo (inizializzazione, conservazione, uso alla fine), schema generale per provare la correttezza; esempi svolti su arrayMax, sequenza di bit e numeri di Fibonacci.Dimostrazioni, induzione e invarianti →). Base: dà . Se è pari, ; poiché e (si toglie uno finale), Se è dispari, ; ora e (si toglie l'ultimo bit, che è ), quindi
In parole: quadrature (una per ogni livello) più moltiplicazioni per (una per ogni bit a tranne il primo). Il minimo su è ( potenza di ) e il massimo (, tutti bit a ). Per la formula generale (Albero della ricorrenza e formula generale per le ricorrenzeL'albero della ricorrenza ha la forma dell'albero delle chiamate dell'istanza peggiore e T(n) è la somma dei lavori dei nodi. Per la famiglia T(n) = s(n)T(f(n)) + w(n) con base T0 per n <= n0, contando i nodi per livello con le iterate di f e il livello f*(n,n0) si ottiene la formula chiusa T(n) = somma_l [prodotto_j s(f^(j)(n))] w(f^(l)(n)) + [prodotto s] T0, verificata per induzione e applicata a esempi (merge sort, Hanoi, ricorrenze con radice).Albero della ricorrenza e formula generale per le ricorrenze →) con , , dà .
Esempio (). . POWER(x,1) (nessuna operazione); POWER(x,3): , dispari, ( operazioni); POWER(x,6): , pari, (); POWER(x,13): , dispari, (). Totale , contro le di STUPID_POWER.
Osservazione sul costo. Il modello a costo unitario è ragionevole per somme e prodotti di interi o reali, ma non per operatori i cui risultati sono più grandi degli operandi (unione di insiemi, prodotto di polinomi, interi con tantissime cifre): lì l'analisi va rifatta con un modello di costo adeguato.
Algoritmi iterativi
I pacchetti di aritmetica non usano la ricorsione, per non pagarne i costi (nascosti dal modello). Si ottiene facilmente una versione iterativa con lo stesso numero di moltiplicazioni asintotico. Se in binario, con ( bit), e per l'associatività
Si accumulano quindi le potenze con , e queste si ottengono iterativamente con .
POWER2(x, n)
if n = 0 then return e
* n = b_k b_{k-1} ... b_0 *
p <- e { accumula le potenze x^(2^i) con b_i = 1 }
s <- x { a inizio iterazione i: s = x^(2^i) }
for i <- 0 to k do
if b_i = 1 then p <- p ∘ s
s <- s ∘ s
return pConto letterale: un quadrato per ognuna delle iterazioni e un prodotto per ognuno dei bit a : al caso peggiore, .
I bit non servono: si possono ottenere con il test di parità e la divisione intera, con una variabile inizializzata a (lo shift destro della rappresentazione di ):
POWER3(x, n)
p <- e; s <- x; m <- n
for i <- 0 to k do
if NOT EVEN(m) then p <- p ∘ s
s <- s ∘ s
m <- floor(m / 2)
return pPOWER3 esegue le stesse applicazioni di operatore di POWER, in ordine bottom-up: è come se eseguisse solo le fasi di conquer, risparmiandosi tutta la generazione top-down dell'albero.
Esempio (, ).
| dopo il passo | dopo il passo | ||
|---|---|---|---|
| 0 | 1 | ||
| 1 | 0 | ||
| 2 | 1 | ||
| 3 | 1 | (inutile) |
Una precisazione sul conteggio. Le dispense affermano che POWER2/POWER3 eseguono esattamente le stesse applicazioni di di POWER. Contando letteralmente il codice di sopra, POWER3 ne esegue (per : contro ), per due ragioni: la prima moltiplicazione con non produce niente di nuovo, e l'ultimo quadrato calcola una potenza che non si usa. Con le due ottimizzazioni (partire da al primo bit a , non quadrare dopo l'ultimo bit) i conteggi coincidono esattamente. Il confronto è stato controllato con un programma per da a .
Verifica con un programma
def power_rec(n): # numero di applicazioni di o in POWER
if n <= 1: return 0
return power_rec(n // 2) + (1 if n % 2 == 0 else 2)
# per n = 1..5000: power_rec(n) == n.bit_length() - 1 + bin(n).count("1") - 1Per ogni da a vale , il massimo su è e il minimo .
Esempio con matrici: numeri di Fibonacci
Con il prodotto di matrici e si ha (induzione: ). Per : con POWER, e , quindi . Basta quindi prodotti di matrici per calcolare (confronta con la ricorsione e la memoizzazione in Programmazione dinamica - Fibonacci, memoizzazione e schema del paradigmala programmazione dinamica (DP) evolve il divide and conquer: invece di risolvere di nuovo le stesse sottoistanze, le salva in una tabella. Fibonacci ricorsivo costa F_n - 1 addizioni (esponenziale), quello con tabella n - 1. Tre condizioni: sottostruttura, sottoistanze ripetute, spazio dei sottoproblemi ristretto. Bottom-up o memoizzazione (ricorsione + tabella globale). Per i problemi di ottimizzazione lo schema è: sottostruttura ottima, ricorrenza sui costi, informazione addizionale, calcolo della tabella, ricostruzione.Programmazione dinamica - Fibonacci, memoizzazione e schema del paradigma →). Attenzione al modello di costo: ha cifre binarie, quindi le operazioni su scalari non sono più a costo unitario per grande. Lo stesso vale per matrici qualsiasi: calcolare richiede prodotti di matrici, ciascuno da operazioni scalari con la definizione (Prodotto di matrici - algoritmo iterativo e ricorsivo a blocchimodello di costo sulle matrici n x n (operazioni tra scalari, taglia n oppure N = n^2); somma in n^2 operazioni (ottima); prodotto righe per colonne iterativo con costo esatto 2n^3 - n^2; proprietà frattale del prodotto a blocchi dimostrata sugli indici; algoritmo ricorsivo RMUL con T(n) = 8T(n/2) + n^2, Theta(n^3) e soluzione esatta 2n^3 - n^2 per induzione e per srotolamento: fa le stesse operazioni dell'iterativo.Prodotto di matrici - algoritmo iterativo e ricorsivo a blocchi →) o meno con Algoritmo di Strassen e ibridazioneStrassen calcola il prodotto n x n con 7 chiamate ricorsive invece di 8, usando 10 somme/sottrazioni nel divide e 8 nel conquer: T(n) = 7T(n/2) + (9/2)n^2, Theta(n^(log2 7)) con soluzione esatta 7n^(log2 7) - 6n^2; la costante 7 è più che tripla di quella dell'iterativo (2) e Strassen batte l'iterativo solo da n = 655 (per le potenze di 2, da 1024). L'ibridazione cambia il caso base (iterativo per n <= n0): costo n^(log2 7)(2n0+5)/n0^(log2 7 - 2) - 6n^2, minimo per n0 = 8 con costante ~3.92.Algoritmo di Strassen e ibridazione →; per matrici con struttura (circolanti) il prodotto è più economico (Matrici circolanti e supercircolanti - algoritmi divide and conquerle matrici supercircolanti (quadranti alternati ricorsivi) hanno solo n valori distinti: somma in n operazioni, prodotto in 4n log2 n + n con il trucco (A1+A2)(B1+B2) e (A1-A2)(B1-B2) invece delle 4 chiamate (Theta(n^2)); gli autovalori sono la trasformata di Hadamard della prima riga (FHT, n log2 n) e il prodotto passa dalla base diagonalizzante; le matrici circolanti sono polinomi nella matrice di rotazione R, il loro prodotto è la convoluzione ciclica delle prime righe e si diagonalizzano con la matrice di Fourier: prodotto in O(n log n) con la FFT.Matrici circolanti e supercircolanti - algoritmi divide and conquer →).
Esercizi collegati
- Esercizio - domande di prima parte su moltiplicazione di matrici (simulazioni d'esame): domande di allenamento sul numero di applicazioni di di
POWER.
Domande d'esame
- Quante applicazioni dell'operatore esegue
POWER(x, 31)? Risposta: , , : (caso peggiore, ;STUPID_POWERne fa ). Traccia: , i quattro livelli dispari costano ciascuno. - Quale ricorrenza regola
POWERe qual è la sua complessità? Traccia: , , , , soglia , caso 2 del Master Theorem: ; esatto . - Quali proprietà dell'operatore servono? Traccia: solo associatività (e l'elemento neutro per ); non serve la commutatività, quindi vale per le matrici.
Versione ripasso
- Setting: associativo con neutro (anche non commutativo, per esempio il prodotto di matrici con ); , . Costo numero di applicazioni di .
STUPID_POWER: , poi volte : .- Sottostruttura: con , ( pari) e ( dispari). Dimostrazione: e , raggruppando per associatività. Da : applicazione (pari) o (dispari).
POWER: base () e (, evita due applicazioni inutili); divide ;POWER; conquer oppure .- Ricorrenza: , . , , , soglia : caso 2, (Master Theorem - enunciato, casi e applicazioniMaster Theorem per T(n) = aT(n/b) + w(n): si confronta w(n) con la funzione soglia n^(log_b a). Caso 1 (w minore di una potenza polinomiale): Theta(n^(log_b a)); caso 2 (w della stessa taglia): Theta(n^(log_b a) log n); caso 3 (w maggiore e regolare): Theta(w(n)). Prova completa dai livelli dell'albero, versione estesa (parti intere, n0 qualsiasi), esempi, e l'uso scorretto quando nessun caso si applica (w = n log n).Master Theorem - enunciato, casi e applicazioni →); è la ricorrenza della ricerca binaria. Il limite per livello è raggiunto da (tutte istanze dispari). Per : (formula generale con , ).
- Esatto: , con numero di bit a .
- Induzione: base dà .
- Pari: , con e .
- Dispari: , con .
- Quindi: quadrature e moltiplicazioni per . Minimo (), massimo ().
- Esempio : , operazioni (contro ). Esempio : .
- Iterativo: con in binario, e .
POWER2: , ; per : se allora ; poi .- Costo letterale , .
POWER3: i bit si ottengono conEVENe , con all'inizio.- Esempio : vale e vale .
- Il codice letterale fa applicazioni in più di
POWER( al primo bit a e l'ultimo quadrato inutile); con al primo bit a e senza l'ultimo quadrato coincidono.
- Fibonacci: , , con prodotti ( dà ), purché si accetti il costo unitario sugli scalari.
- Modello di costo: il costo unitario vale per somme e prodotti di interi o reali, non per operatori che ingrandiscono i risultati (unione di insiemi, prodotto di polinomi, interi lunghi, i numeri di Fibonacci grandi): serve un modello adeguato.
- Errori tipici: usare il costo unitario con operandi che crescono; omettere il caso base ; contare invece dei bit; pensare che serva la commutatività (basta l'associatività).
Esercizi su questo argomento
- Esercizio - convoluzione con il vettore delle potenze di due in tempo lineare (compito del 5 settembre 2025, es. 2)
- Esercizio - domande di prima parte su moltiplicazione di matrici (simulazioni d'esame)
- Esercizio - matrice V per V trasposta con V di Vandermonde, formula degli elementi e calcolo in tempo quadratico (compito del 4 settembre 2024, es. 2)