• Non ci sono risultati.

Dunque il numero di moltiplicazioni nell’algoritmo è <t(t/n)+1) e l’algoritmo ha complessità polinomiale nel numero di cifre binarie t dell’input x

N/A
N/A
Protected

Academic year: 2021

Condividi "Dunque il numero di moltiplicazioni nell’algoritmo è <t(t/n)+1) e l’algoritmo ha complessità polinomiale nel numero di cifre binarie t dell’input x"

Copied!
3
0
0

Testo completo

(1)

Matematica Discreta II

Lezione del giorno 21 novembre 2007

Esaminiamo la complessità dell’algoritmo della lezione precedente, che calcola la parte intera della radice n-esima di un input naturale x (fissato il numero naturale n>1).

Il numero k di iterazioni nel passo 2) è maggiorato da un’espressione polinomiale nel numero t di cifre binarie dell’input x: infatti k coincide con il numero di blocchi di n cifre binarie che è ovviamente (t/n)+1.

Inoltre nell’istruzione a) si deve calcolare una potenza con esponente n, che si ottiene moltiplicando la base per sé stessa n volte, ma notiamo che essendo x<2t (perché x ha t cifre binarie) ed essendo x2n (perché si è escluso il caso banale x<2n in cui la parte intera cercata è 1) si ha n<t.

Dunque il numero di moltiplicazioni nell’algoritmo è <t(t/n)+1) e l’algoritmo ha complessità polinomiale nel numero di cifre binarie t dell’input x.

Ovviamente tale algoritmo si può trasformare facilmente in un algoritmo che testi se un numero naturale x>1 sia la potenza n-esima esatta di un opportuna base naturale, dove n è un naturale >1 fissato.

Infatti basta calcolare con l’algoritmo precedente la parte intera yk della radice n-esima di x, ed verificare se essa coincide esattamente con la radice n-esima di x; basta quindi aggiungere all’algoritmo una istruzione che esegua il calcolo della potenza ykn e verifichi se il risultato è =x : in caso affermativo x è una potenza n-esima esatta di base naturale (e la base è proprio yk), in caso negativo non lo é.

Ovviamente anche tale algoritmo ha complessità polinomiale, perché l’istruzione aggiunta comporta il calcolo di una potenza con esponente n<t.

Infine possiamo notare che si può anche costruire un algoritmo che, dato in input un naturale x>1, testi se x è potenza n-esima di un opportuna base naturale, per un opportuno naturale n>1 (notare che n non è fissato a priori).

Infatti abbiamo notato sopra che in ogni caso si ha n<t, quindi basta ripetere l’algoritmo precedente per tutti i valori n con 2nt e se per nessuno di tali valori il test dà esito positivo concludere con certezza che l’input x non è potenza n-esima di un opportuna base naturale, per nessun naturale n>1.

Osservando che in questo algoritmo si ripete l’algoritmo precedente per un numero di volte che è maggiorato da un’espressione polinomiale nel numero di cifre binarie t dell’input x, si può concludere che anche quest’ultimo algoritmo ha complessità polinomiale.

Algoritmi di fattorizzazione.

Sono algoritmi che, dato in input un naturale n>1, calcolano tutti i fattori primi di n: a tutt’oggi non è stato trovato un algoritmo di fattorizzazione di complessità polinomiale.

Un algoritmo di fattorizzazione in genere cerca di decomporre n nel prodotto n=ab, dove a,b sono naturali (non necessariamente primi) tali che 1<a,b<n (se a,b non esistono, si conclude che n è primo). Una volta trovati a,b l’algoritmo viene riapplicato separatamente ad a,b per decomporli ulteriormente (se possibile): dopo un numero finito di ripetute applicazioni dell’algoritmo, si perviene al calcolo dei fattori primi di n.

Ovviamente un algoritmo “ingenuo” di fattorizzazione consiste (come nel test ingenuo di primalità) nel testare, per ogni naturale a in [2, n], se a è divisore di n, e in caso affermativo porre b=n/a: il numero dei test da effettuare è maggiorato da n=n1/2 < 2t/2 , se t è il numero di cifre binarie di n e quindi n<2t (complessità esponenziale).

Questo algoritmo trova un fattore a di n in tempi di calcolo ragionevoli se n ha un fattore relativamente “piccolo”.

(2)

Illustriamo ora un algoritmo di fattorizzazione che invece è efficiente se n ha un fattore relativamente “grande”.

Algoritmo di fattorizzazione di Fermat.

Supponiamo l’input n dispari: non è una limitazione in un algoritmo di fattorizzazione perché se n è pari, con successive divisioni per 2 si può fattorizzare n nella forma n=2km, con m dispari.

L’algoritmo si basa sul seguente risultato, il quale dimostra che fattorizzare n nel prodotto di 2 numeri naturali equivale sostanzialmente a rappresentare n come differenza di 2 quadrati:

Teorema (Fermat).

Sia n un naturale dispari, e siano:

S = { (a,b)NxN / ab, n=ab } T = { (r,s)ZxZ / r>s0, n=r2-s2 }

Allora esiste una funzione biunivoca f : S  T.

Dimostrazione:

Definiamo f(a,b)=((a+b)/2,(a-b)/2) per ogni (a,b)S (notare che essendo n=ab, anche a,b sono dispari dunque (a+b)/2, (a-b)/2 sono interi).

Essendo a,b>0 ed ab, si ha (a+b)/2>(a-b)/20, ed inoltre [(a+b)/2]2-[(a-b)/2]2=ab=n, dunque f(a.b)T.

La funzione f è iniettiva perché da f(a,b)=((a+b)/2,(a-b)/2)=f(c,d)=((c+d)/2,(c-d)/2) segue (a+b)/2=(c+d)/2, (a-b)/2=(c-d)/2 e si ricava facilmente a=c, b=d.

Dimostriamo la surgettività di f: data una coppia (r,s)T, poniamo a=r+s, b=r-s; essendo r>s0 si ha ab con a,bN, ed n=r2-s2=ab, dunque (a,b)S, ed infine f(a,b)=((a+b)/2,(a-b)/2)=(r,s).

Come conseguenza del teorema precedente, è possibile implementare il seguente algoritmo di fattorizzazione: dato in input un intero dispari n>1, per trovare una fattorizzazione di n nel prodotto di 2 numeri naturali a,b, basta trovare una coppia (r,s)T (quindi r,s interi, r>s0, tali che n=r2-s2) e porre (a,b)=f-1(r,s)=(r+s,r-s) (vedere la dimostrazione della surgettività di f nel teorema).

Per trovare una coppia (r,s)T, possiamo fissare un intero r>0, e cercare un intero s0 tale che si abbia r2-n=s2 : se r2-n =0 allora s=0, n=r2, a=b=r; se invece r2-n >0 si può usare il test già esaminato in precedenza per verificare se il numero naturale r2-n è un quadrato perfetto di base naturale opportuna s.

Dovendo essere r2-n=s20, si ha r n, dunque il valore minimo da fissare per r è r= n (il cosiddetto “tetto” di  n, ossia il minimo intero non inferiore a  n).

Per quanto riguarda il valore massimo di r, notiamo che al crescere di r, cresce il valore corrispondente di a (se esiste) nella coppia (a,b): se r1>r, e se n=r2-s2=r12-s12 , allora s1>s, dunque a=r+s<a1=r1+s1 . Poiché in una fattorizzazione non banale di n (dispari) certamente é an/3 (perché n=ab con b3), e ricordando che r=(a+b)/2, si ottiene che il valore massimo per r è ≤ [(n/3)+3]/2=(n+9)/6, quindi il valore massimo di r è la parte intera di (n+9)/6.

Dunque, l’algoritmo di fattorizzazione di Fermat si può implementare nel modo seguente:

- input n intero dispari >1

- per r= n,  n +1,……, (n+9)/6 si testa se r2-n è un quadrato perfetto (di base opportuna s0) e in caso affermativo si esce con output “n=ab dove a=r+s, b=r-s”

- se nel ciclo precedente nessun test ha avuto esito positivo, si esce con output “n è primo”

Notiamo che ogni passo del ciclo ha complessità polinomiale (test del quadrato perfetto), ma il numero dei passi è maggiorato da funzioni lineari di n, n, e quindi da funzioni esponenziali nel numero di cifre binarie di n (la complessità è perciò esponenziale).

(3)

Notiamo anche, come già premesso, che il test di Fermat trova un fattore non banale di n in tempi ragionevoli se n ha un fattore abbastanza “ grande” cioè  n, perché in tale caso, se n=ab, anche b n, dunque r=(a+b)/2 n, ossia il valore r che nel ciclo permette di trovare la fattorizzazione di n è “vicino” alla radice quadrata di n, e dunque (partendo dal valore iniziale r= n) tale valore viene trovato relativamente “presto”.

Esempio.

Se l’input é n=6077,  n=78, (n+9)/6=1014, il ciclo si dovrà eseguire per r=78, 79,…., 1014 e si ha:

r=78  r2-n =7 (non quadrato) r=79  r2-n =164 (non quadrato) r=80  r2-n =323 (non quadrato) r=81  r2-n =484 =222

ottenendo la fattorizzazione n=ab dove a=r+s=81+22=103, b=r-s=81-22=59.

Riferimenti