terça-feira, 29 de novembro de 2016

Algoritmos Matemáticos para calcular números primos - algoritmo AKS

O algoritmo AKS

No teste de Monte Carlo, se testarmos todas as possibilidades de r, poderemos afirmar se um número é primo. No entanto, isso é inviável para p grande. Logo, se fosse possível achar um sub-conjunto de valores para r quando aplicados ao teste nos fornecesse uma resposta certa, então teríamos um teste determinístico em P. É isso que faz o algoritmo AKS.
Input: Integer n > 1
1. if (n = ab with b > 1) then output COMPOSITE;
2. r := 2;
3. while (r < n) {
4. if (gcd(n,r) is not 1) then output COMPOSITE;
5. if (r is prime greater than 2) then {
6. let q be the largest factor of r-1;
7. if (q > 4sqrt(r)log n) and not(n(r-1)/q 1 (mod r)) then
8. break;
9. r := r + 1;
10. }
11. for a := 1 to 2sqrt(r)log n {
12. if not( (x-a)n (xn-a) (mod xr-1,n) ) then output COMPOSITE;
13. }
14. output PRIME;
As linhas de 1 a 10 funcionam como um filtro para descartar muitos valores que não influem na decisão de primalidade, dados certos princípios algébrico já conhecido.
Na primeira linha, é necessário aplicar um algoritmo que detecte potências perfeitas em tempo polinomial.
A linha 4, verifica se o máximo divisor comum de dois inteiros n e r é diferente de 1.
Note que se n for primo, mdc(n, r) = 1 para qualquer r < n. Já na linha 5, é preciso determinar se o número r é primo por força bruta (todos os valores até sua raiz quadrada), pois se for usado algum algoritmo probabilístico (comum nas linguagens matemáticas como Maple e Matlab), então estaremos tornando o AKS também probabilístico.
A linha 6 determina o maior fator primo de r-1 (q) sendo r primo.
Na linha 12, vemos a aplicação do Pequeno Teorema de Fermat. Considere C(n, p) = n! / p!(n-p)!, n primo diferente de 2 e a co-primo de n. Então, temos que:
(x-a)n = - C(n,0)x0an + C(n,1)x1an-1 + ... - C(n,n-1)xn-1a1 + C(n,n)xna0 =
= -an + C(n,1)x1an-1 + ... - C(n,n-1)xn-1a1 + xn
Como C(n, i) 0 (mod n) (divisível por n) para i [1, n-1], temos em módulo n que:
(x - a)n -an + xn (xn - an) (xn - a) (mod n)
Já se n for composto, então ele terá um fator primo q. Considere qk a maior potência de q que divide n (n = rqk). Então, temos que o binômio de xi quando i = qk:
C(n, i) = n!/i!(n-i)! = (qkr)!/qk!(qkr-qk)! =
= (qkr)(qkr-1)!/(qk)(qk-1)!(qkr-qk)! = (r)(qkr-1)!/(qk-1)!(qkn-1)!
E este binômio não é divisível por n=rqk (igual a zero módulo n) e, por isso, n é composto. Isto é facilmente verificável dividindo-se os binômios de uma linha n do Triângulo de Pascal por n e constatando que todos são divisíveis se e somente se n é primo.
0: 1
1: 1 1
2: 1 2 1
3: 1 3 3 1
4: 1 4 6 4 1
5: 1 5 10 10 5 1
6: 1 6 15 20 15 6 1
7: 1 7 21 35 35 21 7 1
8: 1 8 28 56 70 56 28 8 1
9: 1 9 36 84 126 126 84 36 9 1
10:1 10 45 120 210 252 210 120 45 10 1
Os binômios da linha n são divisíveis por n quando este é primo.
O problema desta abordagem é que quando n for muito grande, calcular todos os n-1 binômios o pior caso, C(n, n-1)0 (mod n) será muito custoso. Alterando a congruência para módulo xr-1, implicitamente, faz-se o teste apenas para os r últimos termos de (x - a)n, ou seja, i [n-r, n-1].
No entanto, agora, alguns compostos n podem equivocadamente satisfazer a congruência da linha 12 para alguns valores de (a, r) e, por isso, são testados separadamente na linha 2.
O algoritmo primeiro escolhe um r primo para obter q, o maior fator primo de r-1, tal que este r delimita um intervalo onde certamente haverá um fator primo de n se este for composto.

Em seguida, o algoritmo testa a congruência para a [1, 2r1/2log(n)], uma quantidade de testes realizáveis em tempo polinomial no pior caso. Este é justamente o avanço feito por este algoritmo.

Nenhum comentário:

Postar um comentário