Readout error mitigation
実機のデバイスは不完全であるため、状態の準備や測定でエラーが発生します。読み出しエラーの軽減は、このよ うなノイズ演算の逆変換を適用することにより、これらのエラーの影響を軽減します。ノイズ演算の逆行列(ここではフィルター行列と呼ぶ)は、読み出しエラー緩和において重要な役割を果たします。ノイジーカウントは、ノイズのない世界で得ることのできる理想的なカウントとエラー行列の積として考えることができます。
の要素は、真の状態がであった場合に測定結果としてを得る確率を表しており、と表現されます。つまり、列方向に合計すると1になります。例えば、2量子ビットのデバイスのは
は、各基底において状態の準備と測定を繰り返し、実際の測定結果のヒストグラムから確率分布を求めることによって推定されます。
フィルター行列はエラー行列の逆行列として定義されます。フィルター行列を用いれば、エラーのないカウントを推定することができます。
このチュートリアルでは、フィルター行列を構築し、ノイズのないサンプリング数を予測する方法を示します。
前提条件
このチュートリアルで使用されるQURI Partsモジュール:quri-parts-algo
,quri-parts-circuit
, quri-parts-core
以下のようにインストールできます:
# !pip install "quri-parts[qulacs]"
準備と概要
ここでは、このチュートリアルで使用する回路とノイズモデルを準備します。このチュートリアルで使用する回路は、恒等パートと非自明パートで構成されています。非自明パートは状態をに変換する部分を担っている一方、ノイズの影響を増幅するために、恒等回路を複数のゲートに分解します。
from quri_parts.circuit import QuantumCircuit
from quri_parts.circuit.utils.circuit_drawer import draw_circuit
qubit_count = 3
identity_circuit = QuantumCircuit(3)
identity_circuit.add_RX_gate(0, 1.3)
identity_circuit.add_RY_gate(1, 0.2)
identity_circuit.add_RZ_gate(0, -2.3)
identity_circuit.add_SqrtXdag_gate(1)
identity_circuit.add_T_gate(0)
identity_circuit.add_RX_gate(1, 0.4)
identity_circuit.add_RY_gate(0, 2.7)
identity_circuit.add_Tdag_gate(1)
identity_circuit.add_RY_gate(0, -2.7)
identity_circuit.add_T_gate(1)
identity_circuit.add_Tdag_gate(0)
identity_circuit.add_RX_gate(1, -0.4)
identity_circuit.add_RZ_gate(0, 2.3)
identity_circuit.add_SqrtX_gate(1)
identity_circuit.add_RX_gate(0, -1.3)
identity_circuit.add_RY_gate(1, -0.2)
circuit = QuantumCircuit(3)
circuit += identity_circuit
circuit.add_H_gate(0)
circuit.add_CNOT_gate(0, 1)
circuit.add_CNOT_gate(0, 2)
print("The circuit:")
draw_circuit(circuit, line_length=200)
#output
The circuit:
___ ___ ___ ___ ___ ___ ___ ___ ___
|RX | |RZ | | T | |RY | |RY | |Tdg| |RZ | |RX | | H |
--|0 |---|2 |---|4 |---|6 |---|8 |---|10 |---|12 |---|14 |---|16 |-----●-------●---
|___| |___| |___| |___| |___| |___| |___| |___| |___| | |
___ ___ ___ ___ ___ ___ ___ ___ _|_ |
|RY | |sXd| |RX | |Tdg| | T | |RX | |sqX| |RY | |CX | |
--|1 |---|3 |---|5 |---|7 |---|9 |---|11 |---|13 |---|15 |-----------|17 |-----|---
|___| |___| |___| |___| |___| |___| |___| |___| |___| |
_|_
|CX |
----------------------------------------------------------------------------------|18 |-
|___|
次に、いくつかのNoiseInstructions
でノイズモデルを作成します。ここでは、MeasurementNoise
だけを考えます。
from quri_parts.circuit.noise import BitFlipNoise, MeasurementNoise, NoiseModel
noise_model = NoiseModel([
MeasurementNoise([BitFlipNoise(0.01)])
])
このノイズモデルでは、測定中にビット反転エラーが発生します。
読み出し誤差の軽減と性能
ここでは、読み出し誤差緩和を行うestimatorの構築方法を示します。この簡単な例では、読み出し誤差の緩和を実行するsampling estimatorの性能を、ノイズのないestimatorやノイズのあるestimatorと比較します。まずは演算子を 用意します。
from quri_parts.core.operator import Operator, pauli_label, PAULI_IDENTITY
op = Operator({
pauli_label("Z0"): 0.25,
pauli_label("Z1 Z2"): 2.0,
pauli_label("X1 X2"): 0.5,
pauli_label("Z1 Y2"): 1.0,
pauli_label("X1 Y2"): 2.0,
PAULI_IDENTITY: 3.0,
})
次に、読み出し誤差を軽減するサンプリング推定器の構築方法を示します。sampling estimatorのチュートリアルで示したように、サンプリング推定器を作成するには同時サンプラーが必要です。読み出しエラー軽減sampling estimatorの場合、フィルター行列を構築し、軽減スキームを内部で実行するサンプラーを構築します。このサンプラーはquri_parts.algo
で提供されているcreate_readout_mitigation_concurrent_sampler
関数で作成します。
from quri_parts.qulacs.estimator import create_qulacs_vector_estimator, create_qulacs_density_matrix_estimator
from quri_parts.qulacs.sampler import create_qulacs_density_matrix_concurrent_sampler
from quri_parts.core.estimator.sampling import create_sampling_estimator
from quri_parts.core.estimator import QuantumEstimator
from quri_parts.core.sampling.shots_allocator import create_equipartition_shots_allocator
from quri_parts.core.measurement import bitwise_commuting_pauli_measurement
from quri_parts.core.state import CircuitQuantumState, quantum_state
from quri_parts.algo.mitigation.readout_mitigation import create_readout_mitigation_concurrent_sampler
def get_readout_mit_estimator(qubit_count: int, shots: int=int(1e6)) -> QuantumEstimator[CircuitQuantumState]:
noisy_concurrent_sampler = create_qulacs_density_matrix_concurrent_sampler(noise_model)
allocator = create_equipartition_shots_allocator()
readout_mit_concurrent_sampler = create_readout_mitigation_concurrent_sampler(
qubit_count,
noisy_concurrent_sampler, # takes in a noisy concurrent sampler
shots
)
return create_sampling_estimator(
shots,
readout_mit_concurrent_sampler,
bitwise_commuting_pauli_measurement,
allocator
)
# Returns the estimator
readout_mit_estimator = get_readout_mit_estimator(qubit_count=3)
ここで、読み出し誤差の緩和を行うsampling estimatorができたので、その推定結果をノイズのないestimator、ノイズのあるestimatorと比較します。
exact_estimator = create_qulacs_vector_estimator()
noisy_estimator = create_qulacs_density_matrix_estimator(noise_model)
state = quantum_state(3, circuit=circuit)
print("Noiseless estimate:", exact_estimator(op, state).value)
print("Noisy estimate:", noisy_estimator(op, state).value)
print("Readout mitigation estimate:", readout_mit_estimator(op, state).value)
#output
Noiseless estimate: (4.999999999999998+0j)
Noisy estimate: (4.920800000000014+0j)
Readout mitigation estimate: 4.998136830346459
ノイズは確かに緩和され、ノイズのある場合の推定値と比較してより良い期待値の推定値が得られていることがわかります。
読み出しエラー軽減サンプラーをステップバイステップで構築
ここで、読み出しエラー軽減(コンカレント)サンプラーを構築するために必要なすべてのステップを説明します。ここでは以下のことを含みます:
- ノイズありサンプラーからフィルター行列を作成
- ノイズありサンプラーによって生成されたサンプリングカウントにフィルターマトリックスを適用
Qulacsでのサンプリングシミュレーション
まず、ノイズありSampler
を作成し、誤差を軽減せずにサンプリングを実行します。
from quri_parts.qulacs.sampler import create_qulacs_density_matrix_sampler
sampler = create_qulacs_density_matrix_sampler(noise_model)
counts = sampler(circuit, shots=10000)
counts
#output
{0: 4912, 1: 44, 2: 49, 3: 48, 4: 51, 5: 52, 6: 45, 7: 4799}
フィルター行列の作成
フィルター行列を作成するためにcreate_filter_matrix
を使用します。
from quri_parts.algo.mitigation.readout_mitigation import create_filter_matrix
from quri_parts.qulacs.sampler import create_qulacs_density_matrix_concurrent_sampler
concurernt_sampler = create_qulacs_density_matrix_concurrent_sampler(noise_model)
filter_matrix = create_filter_matrix(qubit_count, concurernt_sampler, shots=1000000)
filter_matrix.round(5)
#output
array([[ 1.03065e+00, -1.01600e-02, -1.05200e-02, 1.00000e-04,
-1.03600e-02, 9.00000e-05, 9.00000e-05, 0.00000e+00],
[-1.05200e-02, 1.03066e+00, 1.20000e-04, -1.05200e-02,
1.10000e-04, -1.03900e-02, -0.00000e+00, 1.10000e-04],
[-1.02800e-02, 1.00000e-04, 1.03128e+00, -1.03600e-02,
1.10000e-04, -0.00000e+00, -1.04700e-02, 1.00000e-04],
[ 1.00000e-04, -1.05300e-02, -1.04100e-02, 1.03087e+00,
-0.00000e+00, 1.00000e-04, 1.10000e-04, -1.01200e-02],
[-1.01300e-02, 1.10000e-04, 1.00000e-04, -0.00000e+00,
1.03076e+00, -1.06300e-02, -1.04400e-02, 1.10000e-04],
[ 9.00000e-05, -1.02800e-02, -0.00000e+00, 1.10000e-04,
-1.04400e-02, 1.03110e+00, 1.20000e-04, -1.02800e-02],
[ 9.00000e-05, -0.00000e+00, -1.06800e-02, 1.20000e-04,
-1.03100e-02, 1.10000e-04, 1.03115e+00, -1.03900e-02],
[-0.00000e+00, 1.00000e-04, 1.20000e-04, -1.03300e-02,
1.20000e-04, -1.03800e-02, -1.05600e-02, 1.03047e+00]])
読み出しエラーの緩和を実行
readout_mitigation
を呼び出すことで、エラーが軽減されたカウントを得ることができます。
from quri_parts.algo.mitigation.readout_mitigation import readout_mitigation
mitigated_counts = readout_mitigation([counts], filter_matrix)
next(mitigated_counts)
#output
{0: 5062.934660510149,
4: 0.7909420515811665,
5: 3.290159602996353,
7: 4946.536432906023}