スタビライザーシミュレータのStimを使ってみる【量子計算】

Oct. 21, 2023, 11:04 a.m. edited Oct. 21, 2023, 3:02 p.m.

#量子情報  #量子力学  #Python 

表面符号に代表される量子誤り訂正の計算はスタビライザー演算から成り立つ。このシミュレートをプログラムで実行するとき、QulacsやQiskitなどの通常の量子計算ライブラリよりもはるかに高速に実行できるライブラリがStimである。どれくらい速いかというと、ドキュメント冒頭や論文にあるように、符号距離にもよるが1,000倍以上高速となっている。

このStimを利用してみた際のメモをここに記録していく。

インストール

pip install stim

量子回路手動作成

クリフォードゲートにもちろん限られるが、 appendappend_from_stim_program_text で回路を作れる。詳しくはドキュメントAPIリファレンスを見ればすぐわかる。それから、どのクリフォードゲートを使えるかも一覧に載っている。

表面符号自動生成

手動で append などをすれば量子回路を作れるが、よく使う表面符号などの回路は generated により自動で作ることができる。例えば、回転しない通常の表面符号(符号距離は3、ラウンドは3とする)は次のようになる:

import stim

circuit = stim.Circuit.generated(
        'surface_code:unrotated_memory_x',
        rounds=3,
        distance=3,
        )

print(circuit)

すると、 print の結果は

QUBIT_COORDS(0, 0) 0
QUBIT_COORDS(1, 0) 1
QUBIT_COORDS(2, 0) 2
QUBIT_COORDS(3, 0) 3
QUBIT_COORDS(4, 0) 4
QUBIT_COORDS(0, 1) 5
QUBIT_COORDS(1, 1) 6
QUBIT_COORDS(2, 1) 7
QUBIT_COORDS(3, 1) 8
QUBIT_COORDS(4, 1) 9
QUBIT_COORDS(0, 2) 10
QUBIT_COORDS(1, 2) 11
QUBIT_COORDS(2, 2) 12
QUBIT_COORDS(3, 2) 13
QUBIT_COORDS(4, 2) 14
QUBIT_COORDS(0, 3) 15
QUBIT_COORDS(1, 3) 16
QUBIT_COORDS(2, 3) 17
QUBIT_COORDS(3, 3) 18
QUBIT_COORDS(4, 3) 19
QUBIT_COORDS(0, 4) 20
QUBIT_COORDS(1, 4) 21
QUBIT_COORDS(2, 4) 22
QUBIT_COORDS(3, 4) 23
QUBIT_COORDS(4, 4) 24
RX 0 2 4 6 8 10 12 14 16 18 20 22 24
R 1 3 5 7 9 11 13 15 17 19 21 23
TICK
H 1 3 11 13 21 23
TICK
CX 1 2 11 12 21 22 3 4 13 14 23 24 6 5 16 15 8 7 18 17
TICK
CX 1 6 11 16 3 8 13 18 10 5 20 15 12 7 22 17 14 9 24 19
TICK
CX 11 6 21 16 13 8 23 18 0 5 10 15 2 7 12 17 4 9 14 19
TICK
CX 1 0 11 10 21 20 3 2 13 12 23 22 6 7 16 17 8 9 18 19
TICK
H 1 3 11 13 21 23
TICK
MR 1 3 5 7 9 11 13 15 17 19 21 23
DETECTOR(1, 0, 0) rec[-12]
DETECTOR(1, 2, 0) rec[-7]
DETECTOR(1, 4, 0) rec[-2]
DETECTOR(3, 0, 0) rec[-11]
DETECTOR(3, 2, 0) rec[-6]
DETECTOR(3, 4, 0) rec[-1]
REPEAT 2 {
    TICK
    H 1 3 11 13 21 23
    TICK
    CX 1 2 11 12 21 22 3 4 13 14 23 24 6 5 16 15 8 7 18 17
    TICK
    CX 1 6 11 16 3 8 13 18 10 5 20 15 12 7 22 17 14 9 24 19
    TICK
    CX 11 6 21 16 13 8 23 18 0 5 10 15 2 7 12 17 4 9 14 19
    TICK
    CX 1 0 11 10 21 20 3 2 13 12 23 22 6 7 16 17 8 9 18 19
    TICK
    H 1 3 11 13 21 23
    TICK
    MR 1 3 5 7 9 11 13 15 17 19 21 23
    SHIFT_COORDS(0, 0, 1)
    DETECTOR(1, 0, 0) rec[-12] rec[-24]
    DETECTOR(3, 0, 0) rec[-11] rec[-23]
    DETECTOR(0, 1, 0) rec[-10] rec[-22]
    DETECTOR(2, 1, 0) rec[-9] rec[-21]
    DETECTOR(4, 1, 0) rec[-8] rec[-20]
    DETECTOR(1, 2, 0) rec[-7] rec[-19]
    DETECTOR(3, 2, 0) rec[-6] rec[-18]
    DETECTOR(0, 3, 0) rec[-5] rec[-17]
    DETECTOR(2, 3, 0) rec[-4] rec[-16]
    DETECTOR(4, 3, 0) rec[-3] rec[-15]
    DETECTOR(1, 4, 0) rec[-2] rec[-14]
    DETECTOR(3, 4, 0) rec[-1] rec[-13]
}
MX 0 2 4 6 8 10 12 14 16 18 20 22 24
DETECTOR(1, 0, 1) rec[-10] rec[-12] rec[-13] rec[-25]
DETECTOR(1, 2, 1) rec[-5] rec[-7] rec[-8] rec[-10] rec[-20]
DETECTOR(1, 4, 1) rec[-2] rec[-3] rec[-5] rec[-15]
DETECTOR(3, 0, 1) rec[-9] rec[-11] rec[-12] rec[-24]
DETECTOR(3, 2, 1) rec[-4] rec[-6] rec[-7] rec[-9] rec[-19]
DETECTOR(3, 4, 1) rec[-1] rec[-2] rec[-4] rec[-14]
OBSERVABLE_INCLUDE(0) rec[-3] rec[-8] rec[-13]

となる。これだとわかりづらいのでStimには色々な描画方法が存在する:

with open('timeline.svg', 'w') as f:
    print(circuit.diagram('timeline-svg'), file=f)
with open('timeslice.svg', 'w') as f:
    print(circuit.diagram('timeslice-svg'), file=f)
with open('detector-slice.svg', 'w') as f:
    print(circuit.diagram('detector-slice-svg'), file=f) # equivalent with detslice-svg
with open('detslice-with-ops.svg', 'w') as f:
    print(circuit.diagram('detslice-with-ops-svg'), file=f)
with open('match-graph.svg', 'w') as f:
    print(circuit.diagram('match-graph-svg'), file=f)

このようにすると、上から順番に以下の画像が得られる(なお、素直にJupyter Notebookを使う場合はドキュメント通りのやり方で良い):

timeline-svg

単純に量子回路の形で描画したもの。確かに一番上の行の量子ビットはデータ量子ビットであり、その下の行の補助ビットによって \(X\) スタビライズされ、そして別の補助ビットからは \(Z\) スタビライズされているのがわかる。

timeslice-svg

それぞれの物理量子ビットを空間的に並べた図を時系列に並べたものである。つまり、初期化から始まり、それぞれにかかるゲートが一目でわかるようになっている。

detector-slice-svg

ここまでの図と比べていまいち何を表しているのかわかりづらいが、右上から1つ下の図はそれぞれのデータ量子ビットがそれぞれの補助ビットによって \(X\) もしくは \(Z\) スタビライズされている様子を色で表しているので、おそらく他の図もそんなような意味なのだろう。なお、これは 'detslice-svg' とやっても同じ結果となる。

detslice-with-ops-svg

'timeslice-svg''detector-slice-svg' を合わせて描いたもの。わかりやすい感がある。

match-graph-svg

これだけだと何を意味しているかさっぱりだが、後に書く予定のエラー検知関係で役に立ちそうな予感がしている。

エラー関係

あとで書くつもり。多分