3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IBM Bobを使って、量子コンピュータで1+1を計算してみる。

3
Posted at

はじめに

今回は、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 を入れ替えます。それ以外はそのまま通過します。

動作を図で示すと:

{1804F504-1D57-4F31-A4B0-773963684425}.png

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の位の足し算で繰り上げが必要になります。

{E4BEBAB1-32C4-4239-85CD-9B0596A42B61}.png

まずこの繰り上げの仕組みを考えてみましょう。
量子ビットの割り当てですが、以下のように定義します。

q[0] : A     (入力 1)
q[1] : B     (入力 1)
q[2] : C <Sum   (和ビット) >     → 測定
q[3] : D <Carry (桁上がりビット)+ → 測定

A及びBのbitの値が両方1の時にD(桁上がりビット)が1になります。

{DFA5FD73-929A-4F90-816B-EB26723D674C}.png

{724C13AA-6944-421B-9BE0-A97F2DF828EF}.png

続いて1桁目のbitの値については、Aの制御ビットの値が1の時に、値が反転します。

{34D58AB6-F7C1-4AAC-80DA-8921F109FFCF}.png

{EF332C2C-4F91-4C24-BF78-18E51E5EE0F2}.png

つまり量子加算器を作るには、以下のようなイメージの回路を作ればいけそうですね。

{C16A29C9-D6C2-4952-B9B5-D59086ED06BB}.png

IBM Bobで1+1を実装していく

 ここからは、IBM Bobに量子計算をするプログラムをすべて書いてもらい、実行までやってみました。

{9E298F56-9079-41E2-84F7-F4D4A451BA75}.png

量子ビットの割り当て

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 と必ず計算が成功することは考えにくいからです。
シミュレーションで計算していることが分かったので、次は実機で実行できるように指示を出しました。

{F1DA7441-8988-4466-9025-BAC95903EEF2}.png

IBM Quantum 実機で実行

IBM Quantum Platform API KEY

実機に接続するためには、API KEYが必要です。
IBM Quantum PlatformへアクセスしてAPIKEYを作成してください。

{CE50F76D-CAE4-4962-8E4C-12717543FEF0}.png

接続コード

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:
アプリケーション制御ポリシーによってこのファイルがブロックされました。

解決策: 標準ライブラリの jsonorjson を差し替えるモンキーパッチを用意しました。

# 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秒で完了しています。

{6E771C2E-C33C-4CC9-A5B4-296EA7B428E7}.png

実行結果は?

 以下のように1024回実行した結果、2(10)となった割合は93.75%。全部2になったわけではないですね。
量子コンピュータではエラーが発生するためです。でも、数年前よりかなり精度は上がってきていますね。

{5F5264D2-A362-4C47-9536-04F6A59AA4F3}.png

結果 度数 割合
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

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?