今回は,整数に関する話です。最小原始根と呼ばれるものを考えます。
最小原始根
定義
説明の都合上,群論の基本的な用語である「位数」を定義します。すなわち,元の位数とは「その回数だけ累乗して初めて1になるもの」と考えることができます。ここでは証明しませんが,有限群の元の位数はその群
の要素の数
の約数になります*2。また,これもここでは証明はしませんが,次の命題も成立します。
例: について,
の値を表にまとめると下の表のようになる。したがって,この表から
\begin{align}
(\mathbb{Z}/5 \mathbb{Z})^{\times} = \{ 2^{n} \,|\,n=1,\dots,4\} = \{ 3^{n} \,|\,n=1,\dots,4\}
\end{align}であることが分かる。
| 1 | 2 | 3 | 4 | |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 4 | 3 | 1 |
| 3 | 3 | 4 | 2 | 1 |
| 4 | 4 | 1 | 4 | 1 |
と書きましたが,難しければ単に
で割ったときの余りの話をしていると思えばよいでしょう。今回はややふんわりした言葉で定義しましたが,群論の言葉を使ってしっかりと述べれば,原始根とは「乗法群
の生成元」ということです。言い換えればこれは,
乗しないと1にならない数であるということです*4。以下では
を
と書いてしまい,その元も整数と同じ記号で書いてしまうことにします*5。
原始根の求め方
上の例で述べたように乗法表を全て埋めなければ原始根は求まらないのでしょうか。答えはNoです。例えば,実は次の命題が成り立ちます。
証明
:
は
を満たす整数である。
が
を法とする原始根である,つまり,
乗しないと1にならないことから,
である。
: 対偶を示すことにする。
が原始根でないとする。
の位数
は
の約数なので,素因数分解すると,
(
)と書くことができる。
とし,
,
とおく。
ならば
であり
は原始根となるので矛盾。よって,ある
が存在して,
である。いま,
より,
であることなどに気をつけると,
は整数である。また,
\begin{align}
\operatorname{ord}(a) \cdot \ell = \left( \prod_{j \in A} p_{j}^{e_{j}^{\prime}} \right) \left( \prod_{j \in B} p_{j}^{e_{j}^{\prime}} \right) p_{i}^{e_{i} - e_{i}^{\prime} - 1} \left( \prod_{j \in A \setminus \{i\}} p_{j}^{e_{j} - e_{j}^{\prime}} \right) = \frac{p-1}{p_{i}}.
\end{align}これより,
\begin{align}
1 \equiv (a^{\operatorname{ord}(a)})^{\ell} \equiv a^{\frac{p-1}{p_{i}}} \pmod p.
\end{align}証明終
この命題を用いると,最小原始根を計算するアルゴリズムが導かれます。
最小原始根を計算するアルゴリズム
出力:
Step 1:
Step 2:
Step 3:
Step 4:
これを実際にPythonのコードで書いてみたものが下のコードです。今回は素因数分解をするためにSympyを使っています。試し割りをすれば手製のものも作れるのでしょうが,手間を省きました*6。
import numpy as np import sympy as sp def mod_pow(a,b,mod): # a^{b} b = int(b) x = 1 for times in range(0,b): x = x * a % mod return x # 計算のために,乱数を使って適当な素数pを選ぶ p = sp.prime(int(np.random.rand()*100+1)) # p-1 の素因数を求める prime_factor_list = sp.primefactors(p-1) # ありがとうSympy k = len(prime_factor_list) # ここからが上のアルゴリズムのStep 3にあたる a = 2 i = 0 while (i!=k): if (mod_pow(a, (p-1)//prime_factor_list[i], p) == 1): a += 1 i = 0 else: i += 1 print(a) # a がZ/pZの最小原始根
このコードを用いて実際に最小原始根を計算すると,次の表のようになりました。この表では,の
の値と対応する最小原始根
の値を並べました。
は2から15番目の素数までについて計算しています*7。
| 3 | 5 | 7 | 11 | 13 | 17 | 19 | 23 | 29 | 31 | 37 | 41 | 43 | 47 | |
| 2 | 2 | 3 | 2 | 2 | 3 | 2 | 5 | 2 | 3 | 2 | 6 | 3 | 5 |
参考文献
『工学基礎 代数系とその応用』(著 平林隆一,数理工学社)p.96*2:こののことを群の位数と呼びます。ややこしい……。
*3:このようにある群が一つの元の累乗という形で尽くされるとき,その群は巡回群 (cyclic group) であるといいます。
*4:群の元
によって生成される
の部分群を
と書くと,この
の位数は元
の位数
と等しくなります。ただし,共に有限でない場合は濃度の違いを無視して単に無限だから等しいということにします。
*5:同型になることから後者の集合と同一視することにします。
*6:なんなら原始根を求める関数もSympyにはあるとかないとか……。この実装の意味とはいかに。
*7:この計算を行うときは,の値を乱数を使うのではなくそのままの値を代入しました。