8/8(土) つくばで「ミニキーボード教室」☆彡
量子ゲート

New!! 栗まんじゅうでわかるショアのアルゴリズム(②21個溜まったら捨てる)

AI要約

前回の法15に続き、今回は法を21に変更してショアのアルゴリズムの周期発見に挑みます。コントロール10ビット、ターゲット5ビットの回路を構築し、底が2や4の場合の周期をシミュレーションで導き出しました。

はじめに

ショアのアルゴリズムを学ぶシリーズ。前回は「15個溜まったら捨てて余りが1個だけになる」タイミングを計算しました。

ネット検索では法が15以外の例があまり見つかりません。今回は「21個溜まったら捨てる」でも計算できるか試してみましょう。

問題

問題をおさらいします。

倍々に増える栗まんじゅうを21個ずつ処分して、ちょうど1個だけ余るタイミングはあるかな?それを僕が食べてトドメを刺すよ!

つまり、1→2→4→8個…と増えていったときに、21の倍数+1になるタイミングが知りたいんだね!

ということで、問題はこちら。

一定時間ごとに2倍に分裂する栗まんじゅうが1個ある。21個溜まるごとに処分する場合、手元に1個だけ残るのは何回分裂したあとか?

手計算してみる

今回も手計算で求めてみましょう。

分裂回数個数mod 21
0回11
1回22
2回44
3回88
4回1616
5回3211
6回64 (22)1
7回128 (2)2
8回256 (4)4

( )の中の数字は、21個溜まる度にこまめに処分した場合です。たくさん溜めてから処分するのも逐一処分するのも、mod 21した数は同じなのでどちらの派閥でも構いません。表より周期は6、答えは「6回分裂後」とわかります。

コードで確認

前回のコードからいくつか微修正があります。法が21なので、ターゲットビットを4個→5個に増やしました。それに伴い、コントロールビットも10個に増やしました。コードを見比べればだいたい理解できると思います。

import numpy as np
import matplotlib.pyplot as plt
from qiskit_aer import AerSimulator
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import UnitaryGate

#コントロール10ビット + ターゲット5ビット
qc = QuantumCircuit(15)

#ターゲットビットの最下位を |1> に初期化
qc.x(10)

#コントロールビットすべてにアダマールを適用
for i in range(10):
    qc.h(i)

# --- モジュロべき乗演算 ---
#行列を用いて x -> (x * a_power) mod N の変換ゲートを作る関数
def get_mod_matrix(a_power):
    U = np.zeros((32, 32)) #ターゲットが5ビットなので 2^5
    for x in range(32):
        if x < 21:
            y = (x * a_power) % 21
            U[y, x] = 1
        else:
            U[x, x] = 1 #N以上は恒等変換
    return U

#コントロールビットすべてにゲートを適用
for i in range(10):
    #aを決め、a^(2^i) mod N を計算
    a_power = pow(2, 2**i, 21)
    U_matrix = get_mod_matrix(a_power)
    
    #行列を制御ゲートに変換
    c_U = UnitaryGate(U_matrix).control(1)
    
    #コントロールビット i から、ターゲットレジスタすべてへ適用
    qc.append(c_U, [i] + list(range(10, 15)))

qc.barrier()

# --- 逆量子フーリエ変換 (IQFT) ---
#ターゲットビットすべてに適用
for j in range(5):
    qc.swap(j, 10 - 1 - j)

#コントロールビットすべてに適用
for i in range(10):
    for m in range(i):
        qc.cp(-np.pi / (2**(i - m)), i, m)
    qc.h(i)

qc.barrier()

#計算
qc.measure_all()
backend = AerSimulator(method='matrix_product_state')
t_qc = transpile(qc, backend) #トランスパイルが必要
result = backend.run(t_qc, shots=1000).result().get_counts()

#解の確認
for r in result:
    print(f'{r[::-1]} | {result[r]}/1000')

#解のコントロールビットを集計して確認
all_pattern = {}
for r in result:
    pattern = r[::-1][:10][::-1] #上位ビットから並ぶようにひっくり返しておく
    if pattern in all_pattern:
        all_pattern += result[r]
    else:
        all_pattern = result[r]
print(all_pattern)

#ピークを確認するためのグラフ
x = range(2**10)
y = [0] * 2**10
for pattern in all_pattern:
    y[int(pattern, 2)] += all_pattern
plt.plot(x, y)
plt.xticks(range(0, 2**10 + 1, 128))
plt.show()
010101010000010 | 5/1000
110101010011010 | 15/1000
111010101001000 | 1/1000
001010101101000 | 3/1000
(中略)
110010101100001 | 1/1000
001010101000001 | 1/1000
001010101110000 | 1/1000
001111001000010 | 1/1000
{'0101010101': 120, '1101010110': 28, (中略), '1010010101': 1, '0010000001': 1}

量子譜↓

ピークを見るグラフ↓

さあどうでしょうか。コントロールレジスタの範囲0~1024を6等分するようにピークが現れました。よって周期=6、「6回分裂後」と求まりました。

低を変えてみる

問題を変えてみます。

一定時間ごとに4倍に分裂する栗まんじゅうが1個ある。21個溜まるごとに処分する場合、手元に1個だけ残るのは何回分裂したあとか?

手計算では、

分裂回数個数mod 21
0回11
1回44
2回1616
3回641
4回256 (4)4
5回1024 (16)16
6回4096 (64)1
7回16384 (4)4
8回65536 (16)16

周期は3と短いですね。

コードで確認

コード中の底「a」の値を4に変えるだけです。

#aを決め、a^(2^i) mod N を計算
a_power = pow(4, 2**i, 21)
000000000010000 | 104/1000
100101010110000 | 1/1000
010111101000100 | 1/1000
110010101010000 | 3/1000
(中略)
010110101000001 | 1/1000
000011010100001 | 1/1000
011100101000100 | 1/1000
000101010100001 | 1/1000
{'0000000000': 347, '1010101001': 8, (中略), '0101001110': 1, '1010101000': 1}

範囲を3等分するピークが得られました。よって周期=3、「3回分裂後」です。

おわりに

興味があれば、底a=5, 8でも試してみてください。

ちなみにa=3, 6, 7では数学的に余りが1に戻ることがないため問題が成立しません。これは21とaが互いに素でないことをユークリッドの互除法で確認することで証明できます。

次回はいよいよ57の素因数分解に挑戦します。

リアクションのお願い

「参考になった!」「刺激された!」と思ったらぜひリアクションをしましょう。エンジニアの世界はGive and Takeによって成り立っています。これからも無料で良質な情報にアクセスできるよう、Giveする人への感謝をリアクションで示しましょう!

この記事をシェアする

自身のブログ等で使用する場合は引用を忘れずに!

また、寄付も受け付けています。コーヒー1杯でとても喜びます(*˘︶˘*)

 Amazonでギフト券(アマギフ)を贈る

こちらのリンク から金額を指定してお贈りください。(デフォルトで10000円になっているのでご変更ください)

配送:Eメール
受取人:staffあっとvigne-cla.com
贈り主:あなたのお名前やニックネーム
メッセージ:◯◯の記事が参考になりました。など

のようにご入力ください。見返りはありませんのでご了承ください。

 Amazonで食事券(すかいらーく優待券)を贈る

500円 1000円 2000円 5000円 からお贈りください。

配送:Eメール
受取人:staffあっとvigne-cla.com
贈り主:あなたのお名前やニックネーム
メッセージ:◯◯の記事が参考になりました。など

のようにご入力ください。見返りはありませんのでご了承ください。

 その他、ギフト券やクーポン券をメールで贈る

デジタルのギフト券/クーポン券はメールアドレス(staffあっとvigne-cla.com)までお送りください。受領の返信をいたします。
紙のギフト券/クーポン券は 「郵便物はこちらへ」の住所 まで送付してください。名刺やメールアドレスを同封していただければ受領の連絡をいたします。
余った株主優待券等の処理におすすめです。
いずれも見返りはありませんのでご了承ください。

不明点はSNSでお気軽にご連絡ください

ビネクラのTwitter・Youtubeでコメントをください!


Slack・Discordの場合はこちらの公開グループに参加してShoya YasudaまでDMをください!


※当ブログに関することは何でもご相談・ご依頼可能です。

この記事を書いた人
Yasuda

博士(理学)。専門は免疫細胞、数理モデル、シミュレーション。米国、中国で研究に携わった。遺伝的アルゴリズム信者。物価上昇のため半額弁当とともに絶滅寸前。

タイトルとURLをコピーしました