quimbというツールを使って、テンソルネットワークで量子計算をします。
インストール
pipインストールとgithubのバージョンが違うらしく、github経由でのインストールをお勧めします。
pip install --no-deps -U git+git://github.com/jcmgray/quimb.git@develop
こちらで大丈夫です。
早速例題
80量子ビットのGHZを実行します。GHZは全ての量子ビットがもつれますが、Hを一つかけて、それから順番にCXを階段上にかけていくことで実装できます。下記は例題から取りました。
%config InlineBackend.figure_formats = ['svg']
import random
import quimb as qu
import quimb.tensor as qtn
N = 80
circ = qtn.Circuit(N)
# シャッフル
regs = list(range(N))
random.shuffle(regs)
# アダマールゲートかける
circ.apply_gate('H', regs[0])
# CXチェーンを作ってGHZ作成
for i in range(N - 1):
circ.apply_gate('CNOT', regs[i], regs[i + 1])
# 状態ベクトルからサンプリング
for b in circ.sample(1):
print(b)
実行結果は、
00000000000000000000000000000000000000000000000000000000000000000000000000000000
0が80個もつれた状態で出てきました。次にGHZを8回サンプリングしてみます。
%%time
# 8回サンプリング
for b in circ.sample(8):
print(b)
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
00000000000000000000000000000000000000000000000000000000000000000000000000000000
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
CPU times: user 341 ms, sys: 13.1 ms, total: 354 ms
Wall time: 396 ms
できました。きちんと000...と111...でGHZができているのがわかります。最後に100回サンプル取ります。
%%time
from collections import Counter
100回サンプル取ります
Counter(circ.sample(100))
CPU times: user 448 ms, sys: 49.4 ms, total: 498 ms
Wall time: 493 ms
[4]:
Counter({'00000000000000000000000000000000000000000000000000000000000000000000000000000000': 56,
'11111111111111111111111111111111111111111111111111111111111111111111111111111111': 44})
いい感じですね。
blueqatみたいに短くかけますので、
N = 80
qc = qtn.Circuit(N)
qc.h(0)
for i in range(N - 1):
qc.cx(i, i+1)
Counter(qc.sample(100))
Counter({'11111111111111111111111111111111111111111111111111111111111111111111111111111111': 53,
'00000000000000000000000000000000000000000000000000000000000000000000000000000000': 47})
非常に簡単ですね。
より大きな量子回路
次により大きな量子回路を作ってみます。
# 10量子ビット準備
circ = qtn.Circuit(N=10)
# 重ね合わせを作ります
for i in range(10):
circ.apply_gate('H', i, gate_round=0)
# 同じ処理を8周します
for r in range(1, 9):
# even pairs
for i in range(0, 10, 2):
circ.apply_gate('CNOT', i, i + 1, gate_round=r)
# Y-rotations
for i in range(10):
circ.apply_gate('RZ', 1.234, i, gate_round=r)
# odd pairs
for i in range(1, 9, 2):
circ.apply_gate('CZ', i, i + 1, gate_round=r)
# X-rotations
for i in range(10):
circ.apply_gate('RX', 1.234, i, gate_round=r)
# 最後に再度アダマールゲートをかけます
for i in range(10):
circ.apply_gate('H', i, gate_round=r + 1)
circ
作った回路は描画できます。これはかなり便利ですね。
circ.psi.draw(color=['PSI0', 'H', 'CNOT', 'RZ', 'RX', 'CZ'])
慣れない人もいるかもしれませんが、かなり効率的な描画ですね。。。美しい。
描画に関しては、様々な色付けがありましたので、気になる方は元の例題をみてみてください。
利用できるゲート
利用できるゲートの種類は、
" ".join(qtn.circuit.GATE_FUNCTIONS)
でみれます。
'H X Y Z S T X_1_2 Y_1_2 Z_1_2 W_1_2 HZ_1_2 CNOT CX CY CZ IS ISWAP IDEN SWAP RX RY RZ U3 U2 U1 CU3 CU2 CU1 FS FSIM RZZ'
FSIMなどマニアックなゲートもあっていいですね。楽しそうです。FSIMゲートは聞き慣れませんが、fsim(θ,φ) = iswap†(θ) + cphase(φ)とのことです。角度が二つ指定できます。Googleの量子超越でも利用されたゲートです。
パラメータ付き回路
パラメータ付きの回路もできます。FSIM回路にはパラメータが2種類、途中にU3を入れて回路を作っています。
circ_param = qtn.Circuit(6)
for l in range(3):
for i in range(0, 6, 2):
circ_param.apply_gate('FSIM', random.random(), random.random(), i, i + 1, parametrize=True, contract=False)
for i in range(1, 5, 2):
circ_param.apply_gate('FSIM', random.random(), random.random(), i, i + 1, parametrize=True, contract=False)
for i in range(6):
circ_param.apply_gate('U3', random.random(), random.random(), random.random(), i, parametrize=True)
circ_param.psi.draw(color=['PSI0', 'FSIM', 'U3'])
いい感じですね。ここで注意書きがありますね。先程のネットワーク図と違うのは、2量子ビットゲートが特異値分解されていません。オプションでfalseを選んでいますが、実際パラメータ付きの2量子ビットゲートは分解できないぽいです。なので、パラメータ付きの2量子ビットゲートがある場合には、テンソルのランクを落とすことはできないようなので、注意が必要です。
この状態で特定のサンプルに対する振幅を求めることができました。
circ_param.amplitude('101001')
下記のように振幅が出ました。
(0.011457218223033066+0.049324953703641004j)
どうでしたでしょうか。最近の量子コンピュータはどんどん量子回路も大きくなりますし、FSIMゲートをはじめとしてパラメータ付き2量子ビットゲートなどの出現によって様々なルールの拡張や表現方法が変わっています。
私たちが通常慣れ親しんだ五線譜の量子計算もグラフネットワークに拡張することで、テンソル計算として扱うことができるのでとても楽しいと思います。がんばりましょう!
(追記)80量子ビットのテンソルネットワークでのGHZ描画したら面白かったので載せておきます。