はじめに
今回は、IBM Bobで量子コンピュータを扱う!をテーマに、IBM Quantumに挑戦してみました。
量子コンピュータの原理や、どんなことに利用できるの?といった内容は、専門家の方に任せるとして、今回は量子コンピュータの得意な用途とはちょっと違いますが、一番シンプルな例として 1+1=2 を量子回路で計算してみました。
IBM Quantum の無料アカウントと Python があれば誰でも試せます。シミュレーターだけでなく、実際の量子コンピューター実機でも動かすところまでやってみました。
※.量子コンピュータの実機を使うためには、IBM IDとIBM Quantum Platformへのユーザー登録(無料)が必要となります。
GitHubに今回のプログラムを公開しています。ご自由にダウンロードしてください。
環境
| ツール | バージョン |
|---|---|
| Python | 3.11 |
| qiskit | 1.0以上 |
| qiskit-aer | 0.14以上 |
| qiskit-ibm-runtime | 0.49以上 |
pip install qiskit qiskit-aer qiskit-ibm-runtime
量子加算器
コンピュータの計算
コンピューターにおける計算は、入力値( bit ) を 論理回路で操作して出力することです。
これは、量子コンピュータにおいても同じことで、量子コンピュータでは、量子回路を操作して出力させます。
使用するゲート
量子計算は、U(ユニタリーゲート) と CNOT(制御NOTゲート) の2種類を組み合わせて行います。この2つは「万能量子ゲートの組」と呼ばれます。
U(1qubitユニタリーゲート)
入力された1量子ビットの「0 または 1 である確率」を操作するゲート。
量子ビットは 0 と 1 の可能性を同時に保有しています(重ね合わせ)。
CNOT(制御NOTゲート)
制御ビット(control bit)と標的ビット(target bit)の2つを入力とし、制御ビットが 1 のときだけ標的ビットの 0/1 を入れ替えます。それ以外はそのまま通過します。
動作を図で示すと:
2進数での1ビット加算の仕組み
A + B = C を考えます。(下記表)
| A | B | C(和)10進数 | D(和)2進数 |
|---|---|---|---|
| 0 | 0 | 0 | 00 |
| 0 | 1 | 1 | 01 |
| 1 | 0 | 1 | 01 |
| 1 | 1 | 2 | 10 |
2進数での足し算では、1の位の足し算で繰り上げが必要になります。
まずこの繰り上げの仕組みを考えてみましょう。
量子ビットの割り当てですが、以下のように定義します。
q[0] : A (入力 1)
q[1] : B (入力 1)
q[2] : C <Sum (和ビット) > → 測定
q[3] : D <Carry (桁上がりビット)+ → 測定
A及びBのbitの値が両方1の時にD(桁上がりビット)が1になります。
続いて1桁目のbitの値については、Aの制御ビットの値が1の時に、値が反転します。
つまり量子加算器を作るには、以下のようなイメージの回路を作ればいけそうですね。
IBM Bobで1+1を実装していく
ここからは、IBM Bobに量子計算をするプログラムをすべて書いてもらい、実行までやってみました。
量子ビットの割り当て
q[0] : A (入力 1)
q[1] : B (入力 1)
q[2] : Sum (和ビット) → 測定
q[3] : Carry (桁上がりビット) → 測定
IBM Qで使用するゲート
| ゲート | 役割 | 古典論理との対応 |
|---|---|---|
| X(NOTゲート) | 量子ビットを 0→1 に反転 | 入力値のセット |
| CNOT(CX) | 制御ビットが1のときターゲットを反転 | XOR演算 |
| Toffoli(CCX) | 制御2つが両方1のときターゲットを反転 | AND演算 |
Pythonコード(Qiskit)
import orjson_patch # Windows AppLocker 環境用(後述)
import argparse
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
def build_adder_circuit(a: int, b: int) -> QuantumCircuit:
qr = QuantumRegister(4, name='q') # q[0]=A, q[1]=B, q[2]=Sum, q[3]=Carry
cr = ClassicalRegister(2, name='c') # c[0]=Sum, c[1]=Carry
qc = QuantumCircuit(qr, cr)
# 入力の準備
if a == 1:
qc.x(qr[0]) # A = 1
if b == 1:
qc.x(qr[1]) # B = 1
qc.barrier()
# Sum = A XOR B
qc.cx(qr[0], qr[2]) # CNOT: A → Sum
qc.cx(qr[1], qr[2]) # CNOT: B → Sum
# Carry = A AND B
qc.ccx(qr[0], qr[1], qr[3]) # Toffoli: A, B → Carry
qc.barrier()
# 測定
qc.measure(qr[2], cr[0]) # Sum → c[0]
qc.measure(qr[3], cr[1]) # Carry → c[1]
return qc
回路図(qc.draw() の出力)
最初に説明した回路の内容とは異なりますね。
┌───┐ ░ ░
q_0: ┤ X ├─░───■─────────■───░───────
├───┤ ░ │ │ ░
q_1: ┤ X ├─░───┼────■────■───░───────
└───┘ ░ ┌─┴─┐┌─┴─┐ │ ░ ┌─┐
q_2: ──────░─┤ X ├┤ X ├──┼───░─┤M├───
░ └───┘└───┘┌─┴─┐ ░ └╥┘┌─┐
q_3: ──────░───────────┤ X ├─░──╫─┤M├
░ └───┘ ░ ║ └╥┘
c: 2/═══════════════════════════╩══╩═
0 1
シミュレーターで実行
def run_simulation(qc, shots=1024):
from qiskit_aer import AerSimulator
simulator = AerSimulator()
job = simulator.run(qc, shots=shots)
return job.result().get_counts(qc)
python quantum_add.py --mode sim
結果
【測定結果】 {'10': 1024}
ビット列 回数 確率 解釈
---------------------------------------------
10 1024 100.0% 10(2進) = 2(10進) ← 正解
結論: 1 + 1 = 2 ✓
1024回すべて 10(Carry=1, Sum=0)→ 2進数 10 = 10進数 2 で正解!
なぜ毎回100%同じ結果?
シミュレーターはノイズがゼロの理想環境のため、常に正解が返ります。実機では量子ビットのノイズ(エラー)があるので、こうなります:
10 → 980回 (95.7%) ← 正解
00 → 28回 ( 2.7%) ← ノイズによるエラー
11 → 16回 ( 1.6%) ← ノイズによるエラー
さて、結果がでた時点でおかしいなと思いました。
量子の特性を知っていれば、1 + 1 = 2 と必ず計算が成功することは考えにくいからです。
シミュレーションで計算していることが分かったので、次は実機で実行できるように指示を出しました。
IBM Quantum 実機で実行
IBM Quantum Platform API KEY
実機に接続するためには、API KEYが必要です。
IBM Quantum PlatformへアクセスしてAPIKEYを作成してください。
接続コード
def run_on_real_device(qc, api_token, shots=1024):
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
# IBM Quantum に接続(channel は "ibm_quantum_platform")
service = QiskitRuntimeService(channel="ibm_quantum_platform", token=api_token)
# キュー待ちが最も少ない実機を自動選択
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=4)
print(f"使用するバックエンド: {backend.name}")
# 実機のゲートセットにトランスパイル
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)
# 実行
sampler = Sampler(backend)
job = sampler.run([isa_circuit], shots=shots)
print(f"ジョブID: {job.job_id()}")
result = job.result()
return result[0].data.c.get_counts()
python quantum_add.py --mode real --token <あなたのAPIトークン>
Bobのハマりポイント① channel 名が変わっていた
qiskit-ibm-runtime の新バージョン(0.49以降)で channel の値が変更されました:
# ❌ 古い(エラーになる)
QiskitRuntimeService(channel="ibm_quantum", token=token)
# ✅ 新しい
QiskitRuntimeService(channel="ibm_quantum_platform", token=token)
Bobのハマりポイント② orjson が DLL ブロックされた(Windows 環境)
Windows の AppLocker / WDAC ポリシーが有効な環境では、qiskit-ibm-runtime の依存ライブラリ orjson(Rust製 .pyd)がブロックされるエラーが発生します:
ImportError: DLL load failed while importing orjson:
アプリケーション制御ポリシーによってこのファイルがブロックされました。
解決策: 標準ライブラリの json で orjson を差し替えるモンキーパッチを用意しました。
# orjson_patch.py
import sys, json, types
class _OrjsonModule(types.ModuleType):
@staticmethod
def dumps(obj, default=None, option=None) -> bytes:
return json.dumps(obj, default=default, ensure_ascii=False).encode("utf-8")
@staticmethod
def loads(data) -> object:
if isinstance(data, (bytes, bytearray)):
data = data.decode("utf-8")
return json.loads(data)
__version__ = "3.0.0-compat"
sys.modules["orjson"] = _OrjsonModule("orjson")
メインスクリプトの先頭で import orjson_patch するだけで解決します。
実機のキュー待ち
無料プラン(open plan)では Pending 状態が1時間以上続くことがあります。計算自体は数秒ですが、キューの混雑次第です。IBM Quantum のダッシュボード(https://quantum.ibm.com/jobs)でジョブの進捗を確認できます。
実機での結果を確認
さて、IBM Quantum Platform(https://quantum.cloud.ibm.com/) でジョブの確認をしました。
以下のように、実行完了までに521分かかっています。これは、他のユーザーも実機を使って計算を実行しているために、実行待ちになっていたからです。実際に実行されると2秒で完了しています。
実行結果は?
以下のように1024回実行した結果、2(10)となった割合は93.75%。全部2になったわけではないですね。
量子コンピュータではエラーが発生するためです。でも、数年前よりかなり精度は上がってきていますね。
| 結果 | 度数 | 割合 |
|---|---|---|
| 00 | 38 | 3.71% |
| 01 | 10 | 0.97% |
| 10 | 960 | 93.75% |
| 11 | 16 | 1.56% |
量子ゲート方式は、まだ実用段階までは時間を要する状況。現実問題を扱えるよう量子ビット数を増やすこと、重ね合わせ状態が壊れる量子エラーを訂正する技術の研究開発が必要である点は変わっていません。
IBM Qのロードマップは?
現在のIBMのロードマップは、「実用的な計算の第一歩(〜2026年)」から「エラー訂正技術の確立と規模拡大(2028年)」、そして「完全な誤り耐性を持つ超大規模量子コンピュータの実用化(2029年〜2030年代)」へと段階的に進む野心的な計画となっています。
おわりに
さて、量子コンピュータを使って1+1を計算してみました。2022くらいに、私が触っていたときより、IBM Quantum Platformも洗練されていましたし、また量子誤り耐性も進歩していると感じました。
Bobの登場で簡単に量子コンピュータ用のプログラムも書けるようになったので、次は素因数分解などにも挑戦してみようと思います。
参考
IBM Bob
SPSS Modeler ノードリファレンス目次
SPSS Modeler 逆引きストリーム集
SPSS funさん記事集
IBM 斎藤さんの記事集
SPSS連載ブログバックナンバー
SPSSヒモトクブログなどは以下のTechXchangeのコミュニティに統合されました。
ご興味がある方は、ぜひiBM IDを登録して参加してみてください!!!お待ちしています。
IBM TechXchange Data Science Japan











