Miller-Rabin 素数判定法 は、正整数 $n$ が与えられたときに、「 $n$ が素数であるか否か」を判定する確率的アルゴリズムである。
1 回の試行にかかる計算量は $O(\log^3 n)$ であり、シンプルな $O(\sqrt{n} \log^2 n)$ のアルゴリズム1と比べて非常に高速である。 $\frac{1}{4}$ 以下の確率で「 $n$ が合成数なのに素数と判定する」という誤りをするが、試行回数を $s$ 回に増やせば誤る確率を $4^{-s}$ 以下に減らせる。
この記事では、より単純だが欠点のある「Fermat テスト」を先に説明し、これを改良する形で「Miller-Rabin 素数判定法」を説明する。
Fermat テスト
Fermat テストでは、以下の Fermat の小定理 を利用する。
- 命題 1 (Fermat の小定理)
- $p$ は素数とする。このとき、 $p$ 未満の任意の正整数 $a$ について、 $a^{p-1} \equiv 1 \pmod{p}$ が成り立つ。
この対偶を取ると、以下のようになる。 $p$ が $n$ に変わっていることに注意。
- 命題 2 (Fermat の小定理の対偶)
- $n$ は正整数とする。このとき、 $a^{n-1} \not\equiv 1 \pmod{n}$ を満たす $n$ 未満の正整数 $a$ が存在するならば、 $n$ は素数でない。
命題 2 より、 $a^{n-1} \not\equiv 1 \pmod{n}$ を満たす$n$ 未満の正整数 $a$ を 1 つ見つければ、「 $n$ は素数でない」と断言できる。このように、「 $n$ は素数でない」と断言する証拠となる $a$ を 証人 (witness)という。
アルゴリズム
「証人が出るまで $a$ を乱択しよう」というのが Fermat テスト である。
- $1 \leq a \lt n$ を満たす整数 $a$ を乱択する。
- $(a^{n-1} \bmod{n}) \neq 1$ ならば「 $n$ は素数でない」と出力して終了する。
- 「 $n$ は多分素数である」と出力する。
$a^{n-1} \bmod{n}$ は二分累乗法によって $O(\log n)$ の乗算・剰余算で求まるので、乗算・剰余算の計算量を $O(\log^2 n)$ とした場合、Fermat テスト 1 回の計算量は $O(\log^3 n)$ となる。
確率評価
$n$ が合成数なら証人は必ず存在する2ので、試行回数を増やすことで精度をいくらでも上げることができる。しかし $n$ によっては証人がとても少ないケースもある。
そのようなケースの例として、 $n=1729$ の場合を考える。この $1729$ は特殊な合成数で、 $1729$ と互いに素な任意の整数 $a$ について $a^{1728} \equiv 1 \pmod{1729}$ が成り立つ3。 よって $n$ と互いに素でない $a$ のみが証人となり、その割合は全体の $25 \%$ となる。 これはまだ現実的だが、同じ性質を持つ $n=410041$ では $4.5 \%$ しかなくなる。
このように、証人の割合が $n$ に大きく依存してしまうことが Fermat テストの欠点と言える。
Miller-Rabin 素数判定法
Fermat テストよりも厳しい判定方法を使うことで、証人の割合を増やしたものが Miller-Rabin 素数判定法 である。 「証人が出るまで $a$ を乱択する」という全体の流れは Fermat テストと同じである。
Miller-Rabin 素数判定法では、Fermat の小定理に加えて以下の命題を用いる。
- 命題 3
- $p$ を素数とする。このとき、 $x^2 \equiv 1 \pmod{p}$ ならば $x \equiv \pm 1 \pmod{p}$ が成り立つ。
証明
「 $x^2 \equiv 1 \pmod{p}$ 」は「 $x^2-1 = (x+1)(x-1)$ が $p$ の倍数である」と同値である。 さらに $p$ は素数なので、 $x+1$ と $x-1$ の少なくとも一方は $p$ の倍数となる。
- $x+1$ が $p$ の倍数の場合は $x \equiv -1 \pmod{p}$
- $x-1$ が $p$ の倍数の場合は $x \equiv 1 \pmod{p}$
が成り立つので、まとめると $x \equiv \pm 1 \pmod{p}$ となる。 $\square$
この対偶を取ると以下のようになる。
- 命題 4 (命題 3 の対偶)
- $n$ を正整数とする。このとき、 $x \not\equiv \pm 1 \pmod{n}$ かつ $x^2 \equiv 1 \pmod{n}$ を満たす $x$ が存在すれば、 $n$ は合成数である。
この補題を、 $a^{n-1} \bmod{n}$ を求める過程で適用する。
アルゴリズム
まず $n=1$ または $n$ が偶数の場合、判定は自明なので除外する。以降 $n$ が $3$ 以上の奇数の場合のみを考える。
$n - 1$ は偶数なので、 $n - 1 = 2^t u$ を満たす正整数 $t$ と奇数 $u$ が一意に定まる。 この $t,u$ を用いて、以下のアルゴリズムで $n$ が素数か否かを判定する。
- $1 \leq a \lt n$ を満たす整数 $a$ を乱択する。
- $x_i = a^{2^i u} \bmod{n}$ なる長さ $t+1$ の数列 $(x_0, x_1, \cdots, x_t)$ を計算する。
- もし $x_{i+1} = ({x_i}^2 \bmod{n}) = 1$ かつ $x_i \neq 1, n-1$ なる $i$ が見つかれば、「 $n$ は素数でない」と出力して終了する (命題 4)。
- $x_t = (a^{n-1} \bmod{n}) \neq 1$ なら「 $n$ は素数でない」と出力して終了する (命題 2)。
- 「 $n$ は多分素数である」と出力する。
$a^{n-1} \bmod{n}$ を求める過程である手順 3 で、命題 4 を用いて判定している点が変更点である。 計算量は Fermat テスト同様 $O(\log^3 n)$ となる。
確率評価
Fermat テストでは証人の割合が $n$ に大きく依存していたことが問題だった。 一方、Miller-Rabin 素数判定法では以下の定理が成り立つ。証明は難しいので割愛。
- 命題 5
- $n$ は奇数の合成数とする。このとき、 Miller-Rabin 素数判定法における $n$ の証人は $\frac{3(n-1)}{4}$ 個以上存在する。
すなわち、乱択で証人を引ける確率はどんな $n$ でも $\frac{3}{4}$ 以上となる。 よって $s$ 回の試行を行った場合、このアルゴリズムが誤る、すなわち $s$ 回で一度も証人を引けない確率は $4^{-s}$ 以下となる。
実装例
Miller-Rabin 素数判定法を Python3 で実装すると以下のようになる。
|
|