
量子乱数生成器をQiskitで作る|"本物のランダム"をハードウェアから
2026-08-21 ・ 実践
普通のプログラムの乱数は、実は計算で作られた擬似乱数(種を知れば再現できる)です。一方、量子の測定は原理的に予測不能。これを使うと 真の乱数(QRNG) が作れます。この記事ではQiskitでQRNGを実装し、偏りがないかまで検定します。暗号や乱択アルゴリズムの土台になる話です。
なぜ量子は"本物"か
重ね合わせを測定すると、結果は根本的に確率的で、どんな計算でも事前予測できません。擬似乱数のような「種」が存在しないので、再現も予測も不可能です。
擬似乱数との違い
擬似乱数は高速で便利ですが、アルゴリズムとシード次第で再現できます。セキュリティ用途では「予測されうる」ことがリスク。量子乱数は物理法則が予測不能性を保証します。
準備
pip install qiskit qiskit-aer
① 1ビットの量子乱数
アダマールで50:50の重ね合わせを作り、測定するだけ。
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
def quantum_bits(n_bits):
qc = QuantumCircuit(n_bits, n_bits)
qc.h(range(n_bits)) # 全ビットを重ね合わせ
qc.measure(range(n_bits), range(n_bits))
# 1ショット = n_bitsのランダムビット列
counts = AerSimulator().run(qc, shots=1).result().get_counts()
return list(counts.keys())[0]
print(quantum_bits(8)) # 例: "10110001"(毎回変わる)
② 整数・任意範囲の乱数に変換
ビット列を整数にして、欲しい範囲へ。
def quantum_randint(low, high):
span = high - low + 1
n = span.bit_length()
while True:
bits = quantum_bits(n)
val = int(bits, 2)
if val < span: # 偏りを避けるため範囲外は捨てる(棄却法)
return low + val
print("サイコロ:", [quantum_randint(1, 6) for _ in range(5)])
棄却法で偏りゼロ
「2ⁿをそのまま範囲で割った余り」を使うと、端の目が少しだけ出やすくなります。範囲外を捨てる棄却法なら完全に均等。地味ですが、乱数の質を守る大事なテクニックです。
③ 偏りを検定する
大量に生成して0と1がほぼ半々か確かめます。
big = quantum_bits(4000)
ones = big.count("1")
print(f"1の割合: {ones/len(big):.3f}(理想 0.5)")
1の割合: 0.50 前後になれば、偏りのない良質な乱数です。
まとめ
- 量子の測定は予測不能なので「真の乱数」が作れる(擬似乱数は再現可能)
- アダマール→測定で1ビットずつランダムに生成
- 任意範囲は棄却法で偏りなく変換
- 大量生成して0/1が半々かを検定すると品質がわかる
もう少し詳しく(背景と理論)
量子乱数生成(QRNG)の予測不能性は、測定結果が根本的に確率的であるという量子力学の原理に由来します1。擬似乱数(PRNG)は決定的アルゴリズムで、種(シード)が漏れれば再現・予測できるため、暗号用途では暗号論的擬似乱数(CSPRNG)や真性乱数が求められます2。ただし現実の QRNG は、測定器のバイアスやノイズが混じるため、生の出力に乱数抽出(フォン・ノイマン抽出やトープリッツ・ハッシュ)を施して偏りを除くのが標準です3。さらに強い保証として、CHSH 不等式の破れを使い装置を信用せずに乱数性を認証するデバイス非依存乱数の枠組みもあります4。
次の一歩 🌸
重ね合わせの基礎は重ね合わせってなに?、乱数が効く暗号の話は量子時代のセキュリティ、回路の基礎はQiskit入門へどうぞ。