PEC(確率的誤りキャンセル法)の使い方

PEC(確率的誤りキャンセル法)の使い方#

前前節で紹介した外挿法は、ハードウェアでの実行性に優れているものの、ノイズのバイアスに関する理論保証がない、という問題を抱えていました。 ここでは、ノイズチャネル\(\mathcal{E}\)に関する表式が得られているとの仮定のもとで、不偏推定を可能にする量子エラー抑制の手法である、 確率的誤りキャンセル法 (Probabilistic Error Cancellation, 以下PEC) を紹介します。

\(\newcommand{\ket}[1]{| #1 \rangle}\) \(\newcommand{\bra}[1]{\langle #1 |}\) \(\newcommand{\braket}[2]{\langle #1 | #2 \rangle}\)

# notebookを実行する前に、以下のライブラリをインストールしてください。
# mitiqは量子エラー抑制用のライブラリです。
# 
# !pip install mitiq ply cirq

PECでは、エラーに対応するノイズチャネル\(\mathcal{E}\)の逆演算\(\mathcal{E}^{-1}\)を、物理的な量子チャネルの線形和として実現します。

\[ \mathcal{E}^{-1} = \sum_k q_k \mathcal{B}_k,~\sum_k q_k =1 \]

ここで、\(\{\mathcal{B}_k\}\)はノイズなく実行できる量子操作の集合で、\(\{q_k\}\)はその符号付き重みに対応しています。

import mitiq
mitiq.SUPPORTED_PROGRAM_TYPES.keys()
frontend = "qiskit"
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[2], line 1
----> 1 import mitiq
      2 mitiq.SUPPORTED_PROGRAM_TYPES.keys()
      3 frontend = "qiskit"

ModuleNotFoundError: No module named 'mitiq'

問題設定#

1量子ビットの深さ2の量子回路を定義します。

from qiskit import QuantumCircuit
import numpy as np

circuit = QuantumCircuit(1)

circuit.h(0)
circuit.ry(np.pi/8, 0)

print(circuit)
from cirq import DensityMatrixSimulator, depolarize
from mitiq.interface import convert_to_mitiq

noise_rate = 0.3
mitiq_circuit, _ = convert_to_mitiq(circuit)
noisy_circuit = mitiq_circuit.with_noise(depolarize(p=noise_rate))

print(noisy_circuit)

#q_0: ───H───D(0.3)[<virtual>]───Ry(0.125π)───D(0.3)[<virtual>]───

実行器の定義とノイズ付き期待値計算#

import cirq
import numpy as np

def estimate_Z_noisy(circuit, noise_level=0.3):
    """Returns Tr[ρ Z] where ρ is the state prepared by the circuit
    executed with depolarizing noise.
    """
    # Replace with code based on your frontend and backend.
    mitiq_circuit, _ = convert_to_mitiq(circuit)
    # We add a simple noise model to simulate a noisy backend.
    noisy_circuit = mitiq_circuit.with_noise(depolarize(p=noise_level))
    rho = DensityMatrixSimulator().simulate(noisy_circuit).final_density_matrix
    return rho[0, 0].real - rho[1, 1].real
noisy_value = estimate_Z_noisy(circuit, noise_level = noise_rate)
ideal_value = estimate_Z_noisy(circuit, noise_level=0.0)
print(f"誤差(補正なし): {abs(ideal_value - noisy_value):.5f}")

#誤差(補正なし): 0.24492

擬確率表現の生成とPECの適用#

ノイズチャネルは脱分局ノイズで、以下のように与えられています。

\[ \mathcal{E}_{\rm dep}=(1-p)\mathcal{I} + \frac{p}{3}(\mathcal{X}+ \mathcal{Y}+ \mathcal{Z}) \]

これに対して、逆写像を計算すると、以下のように与えられることがわかります。

\[ \mathcal{E}_{\rm dep}^{-1} = \frac{1-\frac{p}{3}}{1-\frac{4p}{3}}\mathcal{I} - \frac{p}{3(1-\frac{4p}{3})}(\mathcal{X}+\mathcal{Y}+\mathcal{Z}) \]

例えば、 \(p=0.3\)とおくと、

\[ \mathcal{E}_{\rm dep}^{-1} = 1.5 \mathcal{I} - \frac{1}{6}(\mathcal{X} + \mathcal{Y} + \mathcal{Z}) \]

であり、\(\gamma = \sum_k|q_k| = 1.5 + 3 * (1/6) = 2\)であることから、物理量の推定を実行する際には\(\gamma^{N_g}=4\)倍された値を用いる。 例えばパウリ演算子の期待値推定を行う際には、 測定によって\(0, 1\)が得られた場合、推定値を\(\pm4\)に割り当てる。

from mitiq.pec.representations.depolarizing import represent_operations_in_circuit_with_local_depolarizing_noise

#reps_ideal = represent_operations_in_circuit_with_local_depolarizing_noise(circuit, 0)
reps_noisy = represent_operations_in_circuit_with_local_depolarizing_noise(circuit, noise_rate)

print(f"ゲートのノイズ除去のための擬確率表現:")
print(reps_noisy[0])
print(reps_noisy[1])

#q_0: ───Ry(0.125π)─── = 1.500*(q_0: ───Ry(0.125π)───)-0.167*(q_0: ───Ry(0.125π)───X───)-0.167*(q_0: ───Ry(0.125π)───Y───)-0.167*(q_0: ───Ry(0.125π)───Z───)
#q_0: ───H─── = 1.500*(q_0: ───H───)-0.167*(q_0: ───H───X───)-0.167*(q_0: ───H───Y───)-0.167*(q_0: ───H───Z───)
from mitiq import pec
sampled_circuits = pec.construct_circuits(circuit, representations=reps_noisy, num_samples = 300)

print(f"Number of sample circuits:    {len(sampled_circuits)}")

for i in range(4):
    print(f"\n{i}番目の量子回路: ")
    print(sampled_circuits[i])
from mitiq import pec

noisy_value = estimate_Z_noisy(circuit, noise_level = noise_rate)
print(f"誤差(PECなし): {abs(ideal_value - noisy_value):.5f}")

for num_shots in [10, 100, 1000]:

    pec_value = pec.execute_with_pec(circuit, estimate_Z_noisy, representations=reps_noisy, num_samples = num_shots)


    print(f"\n測定回数 = {num_shots}")
    print(f"誤差(PECあり): {abs(ideal_value - pec_value):.5f}")


#誤差(PECなし): 0.24492

#測定回数 = 10
#誤差(PECあり): 0.05817

#測定回数 = 100
#誤差(PECあり): 0.02780

#測定回数 = 1000
#誤差(PECあり): 0.01612