はじめに
TensorNetworkCodes.jlは、T. Farrelly, et. al., Local Tensor-Network Codes, New J. Phys. 24 043015(2022)の手法をJuliaでパッケージ化したものである。
大雑把にいうと、量子誤り訂正符号のStabilizer generatorと論理operatorを、物理量子ビットと論理量子ビットの自由度を足と思ったテンソル表現に書き出して、コントラクトを取ると新しい符号が生成できるよって手法です。
研究でを使うことになったので、自分用の備忘録として日本語のライブラリの解説を残しておきます。
(日本人で使ってる人はほぼいないと思うが)間違いがあれば教えてください。
詳細は英語版のdocumentationを読んでください。
codeを表す型の種類
TNCライブラリには符号を表す型が以下の3つある。
Quantum code
SimpleCode
Tensor-network code
Quantum code
は全てのcodeとcontractが取れる型。Abstract supertype for quantum error correcting codesだと思えばいい。
SimpleCode
はTensor-network code
のSeed codeとして使うことができるbasic imolementation。
Tensor-network code
はCodeGraph
に関係している型
Quantum code
QuantumCode型は、quantum error correction codesのAbstruct supertype
Subtype(つまり、Simple CodeとかTensor-network codeとか)は、以下の変数を含んでいるべきである。
stabilizers::Vector{Vector{Int}}
logicals::Vector{Vector{Int}}
pure_errors::Vector{Vector{Int}}
stabilizer
は、linearly independentなstabilizer generatorsの集合で、[[1, 3, 3, 1, 0], [0, 1, 3, 3, 1], [1, 0, 1, 3, 3], [3, 1, 0, 1, 3]]
みたいに書く。(0,1,2,3はI,X,Y,Z)
logicals
は、representatives of logical operators ordered as $X$-type, $Z$-type, ... for each logical qubit.
pure_errors
(or destabilizers) は対応するstabilizer生成元とは非可換だが、その他の生成元とは可換な演算子
Simple code
SimpleCodeは、SimpleCode(name, stabilizers, logicals, pure_errors)
の関数で生成できる。
-
name
: strで名前をつけれる -
stabilizers
:Quantum code
と同様に配列でstabilizerを指定する -
logicals
:Quantum code
と同様に配列で論理Stabilizerを指定する -
pure_errors
:Quantum code
と同様に配列でpure errorを指定する
Simple code自体はname
だけを持っていて、他の変数はQuantumCode
が持ってるイメージ。
~/src/exapmles/simple.jl
に記述されているsimple codeは、比較的小さなcodeをがビルトインされている。
以下にはその例を挙げておく。
-
five_qubit_code()
: 最小構成の誤り訂正符号(と信じられているもの) -
five_qubit_surface_code()
: 表面符号の最終構成、code distance 2の符号 -
steane_code()
: 7-qubit codeと呼ばれる、CSS符号の最小構成 -
random_code(n, k)
: ランダム符号と呼ばれる、n-qubitsでcode-distance kの符号を生成する。根元のrandom状態はrandom_stabilizer_state(n)
で生成 -
random_stabilizer_state(n)
: n-qubitのrandom stabilzier stateの生成
Tensor-network code
Tensor-network code型は、添え字やITensor
の係数を含む"TensorNetworkCodeで使用するすべての幾何学データをまとめた型である。
TensorNetworkCode
はQuantumCode
のsubtypeなので、TensorNetworkCode <: QuantumCode
になっている。
<:演算子は、Juliaでの型のサブタイプ(subtype)関係を示す。
具体的には、TensorNetworkCodeはQuantumCodeのサブタイプであることを意味している。
これは、TensorNetworkCodeがQuantumCodeのすべてのメソッドやフィールドを持ち、QuantumCodeの型のすべてのインスタンスがTensorNetworkCodeの型として扱えることを意味している。
TensorNetworkCodeは、TensorNetworkCode(stabilizers, logicals, pure_errors, code_graph, seed_codes)
で生成できて、QuantumCode
と比べると、以下の変数が追加されている。
code_graph::CodeGraph
seed_codes::Dict{String,SimpleCode}
-
code_graph
: 物理量子ビットのレイアウトに関す情報を格納 -
seed_codes
: the tensor-network codeを構築するために使うsimple codesのDict。
~/src/examples/surface.jl
に記述されているsimple codeは、比較的小さなcodeをがビルトインされている。
以下にはその例を挙げておく。それぞれの意味はdocumentationや論文、サンプルのjupytorノートにあり。
almost_rotated_surface_code(L::Int64, input_seed_code::SimpleCode, input_coords::Array{Int64}) -> TensorNetworkCode
: code distance Lの表面符号に他のcodeをdopeしたTNCを生成
rotated_surface_code(L::Int64) -> TensorNetworkCode
: code distance Lの回転符号のTNCを生成
surface_code(L::Int64)
: code distance Lの表面符号のTNCを生成
操作
ここでは、Tensor-network codesに対する操作を列挙していく
-
verify(code)
: 符号がQECとしての条件を満たしているのかチェックしてくれる。 -
combine(code0, code1)
: 2つのcodeのテンソル積状態に対応する新しい符号を返す。異なる物理量子ビットのセット上にある2つの符号と物理的には等価である。 -
fusion(code, qubit_pair)
: quantumCodeのうちの指定した2つの足をfusionする。物理的にはType-II fusion gateみたいに、$XX$と$ZZ$のパリティ測定をした後にstabilizerを更新するのでこの名前。 -
contract(code0,code1, contract_pair)
: TensorNetworkCode同士をcontractする。これはcombine
してからfusion
してるのと同じ -
gauge(code::SimpleCode, logical_qubit::Int, logical_pauli::Int) -> SimpleCode
-
gauge(code::TensorNetworkCode, logical_qubit::Int, logical_pauli::Int)-> TensorNetworkCode
:logical_qubit::Int
をlogical_pauli::Int
でゲージ固定する。code $[[n,k,*]]$が与えられた時に上からi組目の論理演算子のうちの論理X,Y,Z (1,2,3で指定)でゲージ固定した新しい符号$[[n,k-1,*]]$を返す ($k-1=0$のなった場合はstabilizer状態のStabilizerが帰ってくる。)。 -
contract_by_coords(code0_TN,code2_TN)
: 座標が同じ物理量子ビット同士をontractする。 -
set_coords!(TensorNetworkCode, coordinates)
:TensorNetworkCode
型に座標を登録する。座標の配列順序はTNC内部のnodes
で表現される順番に対応する。 -
shift_coords!(TensorNetworkCode, shifts)
: 全ての座標をシフトする。 -
purify(code::SimpleCode)
: $[[n,k,*]]$を表すSimpleCode
型のcode tensorを$[[n+k,0]]$のSimpleCode
に変換する関数。この時、$[[n+k,0]]$code tensorは単に論理量子ビットの自由度に対応する$k$個の足が先頭に追加されるだけで、Stabilizer状態を表すStabilizer群には基本的にならない。直感的には、TensorNetwork CodesのTABLE. 1みたいな感じ。
具体的な使い方
5-qubit code[[5,1,3]]とStaeneの7-qubits code [[7,1,3]]をコントラクトして、新しい符号を作ってみる。
# ライブラリのimport
using TensorNetworkCodes
Five qubit codeの生成
# SimpleCode型のfive qubit codeを生成
five_qubit = five_qubit_code();
# stabilizer generatorの一覧
five_qubit.stabilizers
4-element Vector{Vector{Int64}}:
[1, 3, 3, 1, 0]
[0, 1, 3, 3, 1]
[1, 0, 1, 3, 3]
[3, 1, 0, 1, 3]
# 論理operatorsの確認
five_qubit.logicals
2-element Vector{Vector{Int64}}:
[1, 1, 1, 1, 1]
[3, 3, 3, 3, 3]
Staene codeの生成
five_qubit= five_qubit_code();
five_qubit.stabilizers
4-element Vector{Vector{Int64}}:
[1, 3, 3, 1, 0]
[0, 1, 3, 3, 1]
[1, 0, 1, 3, 3]
[3, 1, 0, 1, 3]
five_qubit.logicals
2-element Vector{Vector{Int64}}:
[1, 1, 1, 1, 1]
[3, 3, 3, 3, 3]
steane = steane_code();
steane.stabilizers
6-element Vector{Vector{Int64}}:
[1, 0, 0, 1, 0, 1, 1]
[0, 1, 0, 1, 1, 0, 1]
[0, 0, 1, 0, 1, 1, 1]
[3, 0, 0, 3, 0, 3, 3]
[0, 3, 0, 3, 3, 0, 3]
[0, 0, 3, 0, 3, 3, 3]
steane.logicals
2-element Vector{Vector{Int64}}:
[1, 1, 1, 1, 1, 1, 1]
[3, 3, 3, 3, 3, 3, 3]
codeをTensor-Network codesに変換
five_qubit_TN = TensorNetworkCode(five_qubit)
steane_TN = TensorNetworkCode(steane)
適当な物理qubitの足のcontractionをとると、合計で12-qubitあった物理qubitのうちの2箇所がcontractされて、[[10,2,3]]の符号が新たにできる。
new_code_TN = contract(five_qubit_TN, steane_TN, [[1,2]])
v = verify(new_code_TN)
println("This is a QEC code?: $v")
This is a QEC code?: true
TensorNetworkCodes.TNDistance
を使えばcode distanceも計算できる。
using TensorNetworkCodes.TNDistance
dist = tn_distance(new_code_TN)
n = num_qubits(new_code_TN)
k = Int64(length(new_code_TN.logicals)/2)
println("This is a [[$n,$k,$dist]] code!")
This is a [[10,2,3]] code!
新しく作ったTensor-Network codeの描画も可能
plot_code(new_code_TN)
まとめ
Tensor-Network codesは面白いので、みんなも使って遊んでみよう !