量子誤り訂正(QEC)は、今日の量子コンピューティングにおいて最も活発な研究分野の一つです。QECの目的は、量子ビットに格納された繊細な量子情報を、ノイズやデコヒーレンスから保護することです。
量子ビットの信頼性の尺度はエラー確率に基づいており、今日の物理量子ビットは、10,000回のゲート操作につき約1回のエラー(10⁻⁴回)というオーダーのエラー率を達成できます。しかし、完全に効率的であるためには、ゲートエラー率は少なくとも10億回に1回(10⁻⁹回)、あるいは1兆回に1回(10⁻¹²回)に達する必要があります。

このメモは、実装の観点から量子誤り訂正(QEC)を理解するための、簡潔で分かりやすいガイドを提供することを目的としています。最初のセクションでは、論理量子ビットを作成するために必要なさまざまな誤り訂正計算方法の概要を説明します。2番目のセクションでは、論理的に訂正された量子ビットに対するゲート操作の実装の可能性を検討します。そして最後のセクションでは、CUDA-QECフレームワークと、量子誤り訂正システムを作成するためのプログラムによるアプローチを紹介します。
QECは何を、どのように解決しようとしているのか?
見出しへのリンク
QECの課題は、一見すると単純です。まずエラーが発生したことを検知し、次にそれを修正するだけです。ただし、これは量子ビットの量子状態を測定したり崩壊させたりすることなく行う必要があります。ここで、エンタングルした補助量子ビットの概念が登場します。
QECは、単一の量子ビットに情報を格納する代わりに、1つの論理量子ビットを複数の物理量子ビットにエンコードします。これらの物理量子ビットは、データ量子ビットと補助量子ビット(測定量子ビットとも呼ばれる)の2つのカテゴリに分けられます。量子ビットのグループは「エンタングルメント」状態を形成し、データ量子ビットの状態を崩壊させることなく補助量子ビットを読み出すことが可能になります。下の図では、赤い線が物理量子ビットへのいくつかの可能な論理量子ビットのマッピングを示しています。

論理量子ビットを誤り訂正したいと仮定しましょう。論理量子ビットは複数の物理量子ビットに符号化されています。エラーが発生すると、物理量子ビットの1つが反転する可能性があります。反転はビット反転(X)の形、位相反転(Z)の形、またはその両方(Y)の形のいずれかで起こります。
フリップをチェックするために、QECは周期的な*シンドローム測定*を実行します。これは、データ量子ビットと相互作用する特定の補助量子ビットを測定するものです。まず補助量子ビットをデータ量子ビットとエンタングルさせ、次に読み出しを行います。エンタングルメントは、読み出しを実行するのに十分な短い期間だけ行われます。Googleの場合、このエンタングルメントはCZ(コントロールZ)ゲートを使用して実現され、CZゲート自体もエンタングルメントを利用しています。
(画像出典: Google Quantum AI - 表面コード論理量子ビットの実装)
症候群が特定されると、補正を実行できます。このために、古典的なアルゴリズムによって発生した可能性のあるエラーが特定されます。システムは、関連する補正(X、Y、またはZゲート)を適用します。Googleの場合、位相ずれ(T2?)エラーを軽減するために、追加の動的デカップリング(DD)が使用されます。
データと測定用の量子ビットは非局所的に分散されており、1つまたは2つの量子ビットにエラーが発生してもグループの一貫性が損なわれません。この分散は「量子コード」と呼ばれます。実際のシステムでは、より大規模で高度なコードが使用されます。
Shorコード (9量子ビット): ビット反転エラーと位相反転エラーの両方を訂正します。
Steaneコード (7量子ビット): 初の完全量子誤り訂正コード。
表面符号 (\(2n^2-1\) 量子ビット) — 量子ビットを2次元グリッド上に配置します。表面符号距離\(n\)は、同時に訂正できるエラーの数を表します。
実際には、各測定量子ビットは、古典アルゴリズムの判定ロジックに使用される安定化演算子を射影的に測定する役割を担っています。安定化符号は、古典的な誤り訂正における線形符号の量子版であり、パリティチェックを用いてノイズビットの誤りを検出します。
論理量子ビット上で量子アルゴリズムを実行する方法は?
見出しへのリンク
物理量子ビット上で量子アルゴリズムを実行するということは、物理量子ビット上でゲートを操作することを意味します。では、論理量子ビットを扱う場合はどうでしょうか?これは単純な質問のように思えるかもしれませんが、答えはそれほど単純ではなく、論理量子ビットゲートへのアプローチ方法は複数あります。まずは単一量子ビットゲートから始め、その後、複数量子ビットゲートの課題に取り組みましょう。
論理量子ビットへの単一量子ビットゲートの適用
見出しへのリンク
論理ゲートの実装の種類:
- 横断ゲート: 横断ゲートは、各物理キュービットに対して独立して作用します。
論理量子ビットゲートは、n個の物理量子ビットそれぞれに同じゲートを適用することと同等です。例えば、7量子ビットのスティーン符号では、論理アダマールゲートは、7個の物理量子ビットそれぞれに物理的なHゲートを適用することによって実現されます。
表面符号では、論理量子ビットは物理量子ビットの大きなパッチとして符号化される。論理演算は、パッチの結合と分割、あるいは欠陥の編み込みによって実現され、これによって符号のトポロジーが変化する。
arxiv.2505.15907に掲載されている右側の画像は、格子手術操作が、2つのコードパッチを端に沿って結合することによって実行される様子を示しています。この操作は、耐障害性を実現するためにO(d)ラウンドを必要とします。
論理量子ビットへのマルチ量子ビットゲートの適用
見出しへのリンク
*横断型マルチ量子ビットゲート:多くの量子コード(例:Steane、Bacon–Shor)では、論理CNOTを横断的に実行できます:\( CNOT_L=\sum_{i=1}^n CNOT(a_i,b_i) \)
つまり、制御ブロック内の各物理量子ビット\(a_i\)に対して、ターゲットブロック内の対応する量子ビット\(b_i\)に物理CNOTを適用する。
*補助量子ビットに基づくマルチ量子ビット論理ゲート:横断的な実装が不可能な場合、補助量子ビットとテレポート回路を介してマルチ論理量子ビットゲートを実行できます。
例えば、CCNOT(トフォリ)ゲートは、ほとんどのコードでは横断的に実装できません(*)。代わりに、CNOTなどを用いて条件付きで「テレポート」される状態であるマジックステートを作成することで実装されます。この場合、テレポートするゲートは論理ゲート演算であることに注意してください。
*表面コードにおけるマルチ論理量子ビットゲート:表面コードのようなトポロジカルコードでは、マルチ量子ビットゲートはゲートに応じて異なる方法で実装されます。
例えば、ラティス手術によるCNOTや、編み込みによるCZなど。
論理量子ビットにマルチ量子ビットゲートを適用するには、コードの構造に従って、符号化された物理量子ビットに対して操作を行う必要があります。
横断的: 論理ブロックの物理量子ビット間のペアワイズゲート。
アンシラベース:テレポートまたは魔法状態の方法を使用する。
トポロジー:編み込みや格子手術などの幾何学的操作を実行します。
ここまで読み進めてくださった読者の皆様には、お詫び申し上げます。このセクションはやや内容が薄く、表面的な説明にとどまっており、深い考察には至っていません。現時点で知っておいていただきたいのは、論理量子ビットの単一/複数量子ビットゲートには単一の解決策はなく、各ゲートおよび量子コードの種類ごとに適用できる一連の手順が存在するということです。
プログラムによるアプローチ:CUDA-QX QECフレームワーク
見出しへのリンク

2024年、NvidiaのQuantumチームは、オープンソースのCUDA-Qプラットフォームの拡張機能として、量子開発者向けに最適化されたライブラリを提供するCUDA-QXを発表しました。CUDA-QXに含まれるライブラリのうち2つは、CUDA-Q QEC(量子誤り訂正プリミティブとデコーダ)とCUDA-Q Solvers(VQE/ADAPT-VQE、QAOAヘルパー)です。
安定化演算子の古典論理をカスタム実装するためのプログラムAPIを公開する彼らのアプローチを簡単に見てみましょう。以下は、単一量子ビットのビット反転エラーを検出するために使用される最も単純なデコーダを実装した最小限の例です。デコーダは、シンドロームがパリティ行列Hzの単一の列と一致するかどうかをチェックすることで機能します。一致する場合は、量子ビットが反転していると検出されます。
import cudaq_qec as qec
def run_simple_code_capacity( nShots=1000, errorProbability=0.1 ):
steane = qec.get_code("steane") # get built-in Steane code from CUDA-Q QEC
parity_check_matrix = steane.get_parity_z() # parity-check matrix for Z (bit-flip) errors
observable = steane.get_observables_z() # Get the Pauli Z observables of the code
decoder = MyCustomDecoder(Hz) # instantiate custom decoder
nLogicalErrors = 0
for _ in range(nShots):
# Generate noisy data
data = qec.generate_random_bit_flips(Hz.shape[1], errorProbability)
# Calculate which syndromes are flagged.
syndrome = (parity_check_matrix @ data) % 2
# Decode the syndrome to predict what happened to the data
result = decoder.decode(syndrome)
data_prediction = np.array(result.result, dtype=np.uint8)
# See if this prediction flipped the observable
predicted_observable = (observable @ data_prediction) % 2
# See if the observable was actually flipped
actual_observable = observable @ data % 2
if (predicted_observable != actual_observable):
nLogicalErrors += 1
return nLogicalErrors
上記のアルゴリズムにおいて重要なのは、パリティ行列と予測される観測量が、事前に定義されたスティーン量子コードから得られる点である。そして、シンプルなデコーダは次のように実装できる。
class SingleColumnMatchDecoder:
def __init__(self, Hz): # Hz is a parity-check matrix shape (nChecks, nDataQubits)
self.Hz = np.array(Hz) % 2
self.n_qubits = self.Hz.shape[1]
class SimpleDecoderResult:
def __init__(self):
self.result = np.zeros(self.n_qubits, dtype=np.uint8)
def flipped(self, q):
self.result[q]=1
return self
def decode(self, syndrome):
# ensure syndrome is 1D numpy array of length nChecks
s = np.asarray(syndrome).flatten() % 2
# Initialize the flip prediction list
prediction = SimpleDecoderResult()
# Compare to each column of Hz: if any column equals the syndrome, pick that qubit
for q in range(self.n_qubits):
col = self.Hz[:, q] % 2
if np.array_equal(col, s):
return prediction.flipped(q)
# no single-column match -> predict no flips (all zeros)
return prediction
デコーダーが実装されたので、アルゴリズムを実行できるようになりました。
nShots = 1000
nLogicalErrors = run_simple_code_capacity(nShots)
print(f"Shots = {nShots}, Logical error rate ≈ {nLogicalErrors/nShots:.4f}")
ご覧のとおり、CUDA QECは基本的に、QECの古典的な計算ロジックを実装するための効率的なツールとライブラリを提供することによって成り立っています。残る疑問は、このCUDA QECを実際の量子スタックにどのように接続するか、特に、制御スタックからQECデコーダにシンドロームがどのように伝達されるか、そしてデコーダが制御スタックに適用すべき修正ゲートをどのように通知するかということです。そこで、魅力的なCUDA-Qフレームワークが登場しますが、この調査については今後のメモで取り上げたいと思います。
# 結論
ほら、量子誤り訂正の世界を深く掘り下げるのはフルタイムの仕事になることが明らかになったので、量子計算機のアーキテクチャに関する勢いを維持するには、かなり高いレベルにとどまる必要があるだろう。今のところ、「論理的に正しい」量子計算機と言うべきか、それとも単に「信頼できる量子計算機」と言うべきか迷っている。前者の場合、重点は機械を正しくするモデルに置かれ、後者の場合、重点は動作に置かれる。
以前の投稿(/posts/executing-a-quantum-algorithm/)でも述べたように、QECを量子アルゴリズムの装飾として適用すべきなのか、つまり、量子ゲートシーケンスを制御スタックで実行可能なものに変換するコンパイラが、表面コードの読み出しを得るためにゲート操作を「インライン化」する責任も負うべきなのか、それとも「信頼性の高い量子計算機」の「バックグラウンド」操作として実行すべきなのか、私にはまだはっきりしていません。
- Ancillary と Auxiliary のどちらを使うべきか迷う場合は、Ancillary (ラテン語 ancilla: 侍女) が正しいです。Ancillary の意味は「主要な機能に必要なサポートを提供する」ことであり、Auxiliary (ラテン語 auxilium: 助ける) の意味は「追加の助けを提供する、または予備のサポートを提供する」ことです。
この注記は、最初のメモが作成された後に追記されたものです。
- IEEE QCE24 には、「量子誤り訂正と最適制御のための GPU と QPU の緊密な統合」に関する興味深いチュートリアルがあり、ビデオ録画が こちら で入手可能で、上記の未解決の疑問に対する多くの回答と洞察を与えているようです。このチュートリアルについては、今後のメモで詳しく説明します。今のところ、回路を特定の量子コードに適合するように書き換え、表面レベルのトポロジーに適合するようにレベルを下げ、それを可能にするゲート (クリフォードゲート) に対して後処理するというアイデアです。
