Przeskocz do treści

Delta mi!

Test na liczbę pierwszą

Wojciech Czerwiński

o artykule ...

  • Publikacja w Delcie: czerwiec 2012
  • Publikacja elektroniczna: 02-06-2012
  • Autor: Wojciech Czerwiński
    Afiliacja: doktorant, Instytut Informatyki, Uniwersytet Warszawski

Chyba wszyscy lubimy liczby pierwsze. Szczególne wrażenie robią te naprawdę duże, wydają się skrywać w sobie jakąś nadzwyczajną tajemnicę: dlaczego akurat one stały się swego rodzaju wybrańcami spośród innych liczb i mają tak niezwykłe właściwości?

Matematycy od dawna zastanawiają się, jak sprawdzać, czy liczba jest pierwsza. Dawniej robili to tylko (a może aż) z ciekawości i poczucia doniosłości zadania. W dzisiejszych czasach mają także bardziej praktyczne motywacje. Przykładowo, na potrzeby algorytmu RSA chcielibyśmy umieć sprawdzać, czy liczba mająca około 500 cyfr jest pierwsza, czy też złożona.

Powszechnie stosowany i w praktyce najszybszy jest test pierwszości Millera–Rabina (w skrócie test MR), wymyślony w 1980 roku.

Wykorzystuje on losowość i opiera się na następującym pomyśle. Powiedzmy, że chcemy sprawdzić, czy liczba math jest pierwsza. Okazuje się, że jeżeli math jest złożona, to co najmniej połowa liczb ze zbioru math jest świadkami złożoności tej liczby (to zresztą bardzo mało dokładne oszacowanie). Nazwa bierze się stąd, że jeżeli dla pewnej liczby math istnieje liczba math będąca jej świadkiem złożoności, to wiadomo, że math jest liczbą złożoną.

Stosunkowo łatwo jest sprawdzić, czy dana liczba math jest świadkiem złożoności dla math ale nie będziemy teraz wchodzić w szczegóły, co to znaczy i jak się to robi. Co więcej, odpowiednie obliczenia można wykonać szybko – jeżeli liczba math ma math cyfr, to algorytm sprawdzający, czy math jest świadkiem złożoności dla math wykonuje mniej więcej math operacji. To znaczy, że dla math będącej liczbą pięćsetcyfrową wykona on mniej więcej math czyli 125 milionów operacji. Nasz domowy komputer potrzebuje na to mniej więcej jednej setnej sekundy – czyli nie jest źle.

Zatem aby sprawdzić, czy liczba math jest pierwsza, postępujemy tak: losujemy math z przedziału od 1 do math i sprawdzamy, czy math jest świadkiem złożoności dla math Jeżeli jest, to wiemy, że math jest złożona. Jeśli nie, to math przeszła pierwszą próbę i sprawdzamy dalej. Ponieważ dla dowolnego math świadkowie złożoności to przynajmniej połowa liczb z przedziału od 1 do math więc prawdopodobieństwo, że liczba złożona math przejdzie pojedynczą próbę, jest nie większe niż math Losujemy więc kolejne math i znów sprawdzamy, czy jest ono świadkiem złożoności dla math Jeżeli liczba math jest złożona, to prawdopodobieństwo przejścia 30 testów bez znalezienia świadka złożoności jest mniejsze niż math (czyli również mniejsze niż math). Po 100 testach prawdopodobieństwo tego, że błędnie uznamy liczbę złożoną za pierwszą, jest już mniejsze niż szansa na to, że w ciągu następnej minuty wielki meteoryt uderzy w Ziemię i zakończy wszelkie nasze matematyczne dywagacje. Czyli mamy pewność zupełnie wystarczającą. Przeprowadzenie 100 testów zajmie na domowym komputerze nie więcej niż sekundę – to bardzo niewiele.

Matematykom jednak problem testowania pierwszości nadal nie dawał spokoju. Chcieli mieć metodę dającą pewność absolutną, obliczającą wynik w sensownym czasie, a nie tylko wystarczającą do celów praktycznych.

Powiemy, że algorytm jest wielomianowy, jeżeli dla danych rozmiaru math wykonuje co najwyżej math operacji, gdzie math  to pewien wielomian. Czyli, na przykład, test MR jest algorytmem wielomianowym, gdyż dla liczby o  math cyfrach wykonuje co najwyżej math  operacji dla pewnej stałej math

Algorytmy wielomianowe są umownie uważane za szybkie, a te o większej złożoności – za wolne. W informatyce teoretycznej dla danego problemu bardzo ważnym pytaniem jest, czy da się skonstruować algorytm wielomianowy rozwiązujący go, który podaje poprawną odpowiedź zawsze, a nie tylko z dużym prawdopodobieństwem. Dla problemu testowania pierwszości pytanie to do niedawna było problemem otwartym. Test MR nie jest rozwiązaniem, ponieważ zawiera element losowości.

Chociaż przez wiele lat nie udawało się znaleźć odpowiedzi, większość matematyków wierzyła w istnienie wielomianowego testu pierwszości. Aż wreszcie w roku 2002 trzech naukowców z Uniwersytetu w Kampurze ogłosiło znalezienie pierwszego takiego algorytmu. Nazwano go algorytmem AKS, od pierwszych liter nazwisk twórców: Agrawal, Kayal, Saxena. To był wielki sukces – kwestia trudności testowania pierwszości została ostatecznie rozstrzygnięta. Autorzy otrzymali za to osiągnięcie m.in. nagrodę Gödla – najbardziej prestiżowe wyróżnienie w dziedzinie informatyki teoretycznej. Co ciekawe, test AKS działa w praktyce wolniej niż test MR. Po pewnych poprawkach dla liczby o  math cyfrach wykonuje rzędu math operacji, a oryginalny algorytm jest nawet jeszcze nieco wolniejszy. To nie umniejsza jednak doniosłości wyniku.

Opis algorytmu mieści się na zaledwie kilku stronach, co jest zupełnie niespotykane dla osiągnięć matematycznych tej trudności. Co więcej, używa (po paru poprawkach) jedynie elementarnej matematyki. Opiera się na kilku bardzo sprytnych spostrzeżeniach. Korzystając z okazji, przyjrzyjmy się temu algorytmowi z lotu ptaka. Głównym pomysłem jest następujące spostrzeżenie.

Lemat. Niech math oraz math Wówczas math jest pierwsza wtedy i tylko wtedy, gdy

display-math(1)

Dowód. Kongruencję z lematu rozumiemy jako równość modulo math współczynników przy odpowiednich potęgach math W wyrażeniu math współczynnik przy math to math Wystarczy więc zastanowić się, kiedy math dzieli math dla math oraz czy math Gdy math jest pierwsza, to łatwo sprawdzić, że liczby math oraz math są podzielne przez math (ten ostatni fakt to małe twierdzenie Fermata), więc teza jest prawdziwa.

Przypuśćmy teraz, że math jest złożona i liczba pierwsza math dzieli math Niech math będzie takim maksymalnym wykładnikiem, że math  Wówczas jednak mamy

display-math

gdyż math dzieli licznik w  math -tej potędze, a mianownik w pierwszej. Liczba math jest względnie pierwsza z  math czyli math a zatem math co dowodzi tezy również dla liczb złożonych.


By rozstrzygnąć, czy math jest pierwsze, wystarczy więc sprawdzić, czy wielomiany math i  math mają wszystkie współczynniki przystające modulo math Gdybyśmy jednak sprawdzali je po kolei przy każdej potędze math to wykonalibyśmy przynajmniej rzędu math operacji. To za dużo, więc trzeba obliczać współczynniki sprytnie.

Kolejny pomysł to sprawdzanie równości (1) modulo wielomian postaci math dla pewnego math czyli

display-math(2)

Może się jednak okazać, że niektóre liczby złożone spełniają równość (2), mimo że nie spełniają równości (1). Rozwiązaniem tego problemu jest sprawdzanie (2) dla odpowiednio dobranego math i dla wszystkich dodatnich wartości math nie większych niż math (gdzie math oznacza liczbę liczb mniejszych od math i względnie pierwszych z  math). Okazuje się, że liczba math spełniająca wszystkie takie równości, musi być pierwsza. Właśnie w wykazaniu prawdziwości tego spostrzeżenia leży główna trudność techniczna dowodu.

Niech math będzie taką najmniejszą liczbą math że math Algorytm AKS działa według następującego schematu:

1.
jeśli math dla math to zwróć ZŁOŻONA
2.
znajdź taką najmniejszą liczbę math że math
3.
jeśli math dla jakiegoś math to zwróć ZŁOŻONA
4.
jeśli math to zwróć PIERWSZA
5.
dla math od math do math wykonuj: jeśli math to zwróć ZŁOŻONA
6.
zwróć PIERWSZA

Bez wielkiej trudności można stwierdzić, że jeśli algorytm zakończy działanie w jednym z pierwszych pięciu kroków, to odpowiedź jest poprawna. Jeżeli zwróci wynik w punkcie 1, to zrobi, oczywiście, słusznie. Jeżeli znajdzie w punkcie 3 taką liczbę math że math to math jest nietrywialnym dzielnikiem math czyli istotnie math jest złożona. Z kolei jeżeli w punkcie 4 okaże się, że math to znaczy, że w punkcie 3 sprawdziliśmy wszystkie math i każda była względnie pierwsza z  math czyli faktycznie math jest pierwsza. Jeśli w punkcie 5 równość modulo math nie jest spełniona, to nie zachodzi również zależność (1), czyli istotnie math jest złożona. Pozostaje jedna wątpliwość co do poprawności algorytmu: czy wynik zwracany w punkcie 6 jest poprawny?

Dowód opiera się na analizie funkcji math oraz liczb math spełniających równanie

display-math

dla pewnego konkretnego czynnika pierwszego math liczby math Jeśli liczba math przeszła testy w punkcie 5, to dla każdej funkcji postaci math oraz math powyższa kongruencja jest prawdziwa. Można wyprowadzić analogiczne zależności dla innych funkcji math i liczb math i, idąc tym tropem, udowodnić, że algorytm słusznie zwraca wynik PIERWSZA w punkcie 6. To rozumowanie pozwala zakończyć dowód poprawności algorytmu, ale wymaga trochę pracy nad szczegółami.

Czytelnik Uważny chciałby pewnie zapytać, czy istotnie algorytm AKS jest wielomianowy. Tę sprawę rozwiązuje lemat, z którego wynika, że dla math istnieje math nie większe niż math spełniające własność z drugiego kroku algorytmu. Analizując dokładnie dalsze kroki (do czego przydaje się pewne doświadczenie w szacowaniu złożoności), zauważymy, że ten fakt rzeczywiście pozwala na oszacowanie czasu działania algorytmu przez wielomian zależny od math Dobrym zadaniem na początek jest znalezienie sposobu wykonania pierwszego kroku w czasie wielomianowym od math

Te wyniki nie oznaczają bynajmniej, że cała sprawa liczb pierwszych doczekała się ostatecznego zamknięcia. Istnieje naprawdę ogromnie dużo nierozwiązanych problemów dotyczących liczb pierwszych. Wiele z nich ma także znaczenie praktyczne. Chyba najważniejszym takim problemem jest zagadnienie faktoryzacji liczb, czyli znajdowania ich rozkładu na czynniki pierwsze. Do dziś nie ma dla tego problemu żadnych algorytmów działających w zadowalającym czasie, choćby takich, które wykorzystują losowość, albo nawet takich, które wydają się poprawne, ale na razie nie umiemy tego udowodnić.