Japanese
言語
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

注釈

このページは tutorials/simulators/3_building_noise_models.ipynb から生成されました。

ノイズモデルの構築

はじめに

このノートブックでは、ノイズがあるシミュレーション用にカスタムノイズモデルを構築するための Qiskit Aer noise モジュールの使用方法をご紹介します。

[1]:
import numpy as np
from qiskit import QuantumCircuit, transpile
from qiskit.quantum_info import Kraus, SuperOp
from qiskit_aer import AerSimulator
from qiskit.tools.visualization import plot_histogram

# Import from Qiskit Aer noise module
from qiskit_aer.noise import (NoiseModel, QuantumError, ReadoutError,
    pauli_error, depolarizing_error, thermal_relaxation_error)

Qiskit Aer Noise Module

Qiskit Aer noise モジュールには、シミュレーション用にカスタマイズされたノイズモデルを構築する Python クラスが含まれています。3 つのキークラスがあります。

  1. ノイズがあるシミュレーションで使用されるノイズモデルを格納する NoiseModel クラス。

  2. CPTP ゲートエラーを記述する QuantumError クラス。以下のように適用できます。

    • gate または reset の命令の後

    • measure 命令の前に。

  3. 古典的な読み出しエラーを記述する ReadoutError クラス。

Quantum Errors

QuantumError オブジェクトを直接扱うのではなく、特定のパラメータ化された量子エラーを自動的に生成する多くのヘルパー関数が存在します。 これらは noise モジュールに含まれており、量子コンピューティング研究で使用される多くの一般的なエラータイプの関数を含んでいます。 関数名と返すエラーの種類は以下のとおりです。

標準エラー関数

詳細

kraus_error

Kraus matrices \([K_0, ...]\) のリストとして与えられた一般的な n-qubit CPTP エラーチャネル。

mixed_unitary_error

ユニタリー行列と確率のリスト \([(U_0, p_0),...]\) で与えられた n 量子ビットのユニタリーエラー。

coherent_unitary_error

1つのユニタリー行列 \(U\) として与えられたn量子ビットのコヒーレントなユニタリーエラー。

pauli_error

Pauli行列と確率のリスト \([(P_0, p_0),...]\) で与えられた n 量子ビット Pauli エラー (混合ユニタリー) チャネル

depolarizing_error

depolarizing 確率が \(p\) の n量子ビット depolarizing エラーチャネル。

reset_error

\(|0\rangle\), \(|1\rangle\) 状態にリセットする確率 \(p_0, p_1\) によりパラメーター化された、単一量子ビットのリセット・エラー

thermal_relaxation_error

緩和時間 \(T_1\) , \(T_2\) と ゲート操作時間 \(t\) と 励起状態の熱占有率 \(p_1\) で特徴付けられる1量子ビット熱緩和チャネル

phase_amplitude_damping_error

振幅dampingパラメーター \(\lambda\)、位相dampingパラメーター \(\gamma\)、 励起状態熱占有率 \(p_1\) で与えられる1量子ビットの一般化された位相と振幅を結合したdamping エラーチャネル

amplitude_damping_error

振幅減衰パラメータ \(\lambda\) および励起状態の熱集団である \(p_1\) によって与えられる単一量子ビット一般化された振幅減衰誤差チャネル。

phase_damping_error

A single-qubit phase damping error channel given by a phase damping parameter \(\gamma\)

量子エラーを結合する

QuantumError インスタンスは、コンポジション、テンソル積、テンソル拡張(逆順テンソル積) を使用して結合することで、新しい QuantumErrors を生成できます。

  • 合成: \(\cal{E}(\rho)=\cal{E_2}(\cal{E_1}(\rho))\)error = error1.compose(error2) とする

  • テンソル積: \(\cal{E}(\rho) =(\cal{E_1}\otimes\cal{E_2})(\rho)\)error error1.tensor(error2) とする

  • 逆順テンソル積: \(\cal{E}(\rho) =(\cal{E_2}\otimes\cal{E_1})(\rho)\)error 1.expand(error2) とする

例えば、5%の単一量子ビットのビットフリップエラーを構築するには、次のようにします。

[2]:
# Construct a 1-qubit bit-flip and phase-flip errors
p_error = 0.05
bit_flip = pauli_error([('X', p_error), ('I', 1 - p_error)])
phase_flip = pauli_error([('Z', p_error), ('I', 1 - p_error)])
print(bit_flip)
print(phase_flip)
QuantumError on 1 qubits. Noise circuits:
  P(0) = 0.05, Circuit =
   ┌───┐
q: ┤ X ├
   └───┘
  P(1) = 0.95, Circuit =
   ┌───┐
q: ┤ I ├
   └───┘
QuantumError on 1 qubits. Noise circuits:
  P(0) = 0.05, Circuit =
   ┌───┐
q: ┤ Z ├
   └───┘
  P(1) = 0.95, Circuit =
   ┌───┐
q: ┤ I ├
   └───┘
[3]:
# Compose two bit-flip and phase-flip errors
bitphase_flip = bit_flip.compose(phase_flip)
print(bitphase_flip)
QuantumError on 1 qubits. Noise circuits:
  P(0) = 0.0025000000000000005, Circuit =
   ┌───┐┌───┐
q: ┤ X ├┤ Z ├
   └───┘└───┘
  P(1) = 0.0475, Circuit =
   ┌───┐┌───┐
q: ┤ X ├┤ I ├
   └───┘└───┘
  P(2) = 0.0475, Circuit =
   ┌───┐┌───┐
q: ┤ I ├┤ Z ├
   └───┘└───┘
  P(3) = 0.9025, Circuit =
   ┌───┐┌───┐
q: ┤ I ├┤ I ├
   └───┘└───┘
[4]:
# Tensor product two bit-flip and phase-flip errors with
# bit-flip on qubit-0, phase-flip on qubit-1
error2 = phase_flip.tensor(bit_flip)
print(error2)
QuantumError on 2 qubits. Noise circuits:
  P(0) = 0.0025000000000000005, Circuit =
     ┌───┐
q_0: ┤ X ├
     ├───┤
q_1: ┤ Z ├
     └───┘
  P(1) = 0.0475, Circuit =
     ┌───┐
q_0: ┤ I ├
     ├───┤
q_1: ┤ Z ├
     └───┘
  P(2) = 0.0475, Circuit =
     ┌───┐
q_0: ┤ X ├
     ├───┤
q_1: ┤ I ├
     └───┘
  P(3) = 0.9025, Circuit =
     ┌───┐
q_0: ┤ I ├
     ├───┤
q_1: ┤ I ├
     └───┘

QuantumChannel 演算子との変換

Qiskit Aer の QuantumError オブジェクトと Qiskit Terra の QuantumChannel オブジェクトの間でも行ったり来たりすることができます。

[5]:
# Convert to Kraus operator
bit_flip_kraus = Kraus(bit_flip)
print(bit_flip_kraus)
Kraus([[[ 9.74679434e-01+0.j,  0.00000000e+00+0.j],
        [-1.20234617e-16+0.j,  9.74679434e-01+0.j]],

       [[ 2.62045272e-16+0.j,  2.23606798e-01+0.j],
        [ 2.23606798e-01+0.j, -2.84112242e-16+0.j]]],
      input_dims=(2,), output_dims=(2,))
[6]:
# Convert to Superoperator
phase_flip_sop = SuperOp(phase_flip)
print(phase_flip_sop)
SuperOp([[1. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],
         [0. +0.j, 0.9+0.j, 0. +0.j, 0. +0.j],
         [0. +0.j, 0. +0.j, 0.9+0.j, 0. +0.j],
         [0. +0.j, 0. +0.j, 0. +0.j, 1. +0.j]],
        input_dims=(2,), output_dims=(2,))
[7]:
# Convert back to a quantum error
print(QuantumError(bit_flip_kraus))

# Check conversion is equivalent to original error
QuantumError(bit_flip_kraus) == bit_flip
QuantumError on 1 qubits. Noise circuits:
  P(0) = 1.0, Circuit =
   ┌───────┐
q: ┤ kraus ├
   └───────┘
[7]:
True

読み出しエラー

古典的な読み出しエラーは、代入ベクトル \(P(A|B)\) のリストで指定されます。

  • \(A\) is the recorded classical bit value

  • \(B\) is the true bit value returned from the measurement

例えば 1 量子ビットの場合: $ P(A|B) = [P(A|0), P(A|1)]$

[8]:
# Measurement miss-assignement probabilities
p0given1 = 0.1
p1given0 = 0.05

ReadoutError([[1 - p1given0, p1given0], [p0given1, 1 - p0given1]])
[8]:
ReadoutError([[0.95 0.05]
 [0.1  0.9 ]])

読み出しエラーは compose, tensorexpand を量子エラーと同様に組み合わせることもできます。

ノイズモデルにエラーを追加する

ノイズモデルに量子エラーを追加する場合、作用させる 命令 のタイプとどの量子ビットに適用するのかを指定する必要があります。量子エラーには2つのケースがあります:

  1. すべての量子ビットが量子エラー

  2. 特定量子ビットが量子エラー

1. すべての量子ビットが量子エラー

これは、どの量子ビットに作用するかにかかわらず、どのような命令の発生にも同じエラーを適用します。

It is added as noise_model.add_all_qubit_quantum_error(error, instructions):

[9]:
# Create an empty noise model
noise_model = NoiseModel()

# Add depolarizing error to all single qubit u1, u2, u3 gates
error = depolarizing_error(0.05, 1)
noise_model.add_all_qubit_quantum_error(error, ['u1', 'u2', 'u3'])

# Print noise model info
print(noise_model)
NoiseModel:
  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
  Instructions with noise: ['u3', 'u2', 'u1']
  All-qubits errors: ['u1', 'u2', 'u3']

2. 特定量子ビットが量子エラー

これは、指定された量子ビットのリスト上で動作する命令の発生にエラーが適用されます。 量子ビットの順序が重要であることに注意してください: 2 量子ビットゲートの場合、量子ビット [0, 1] に適用されるエラーは量子ビット [1, 0] に適用されるものとは異なります。

noise_model.add_quantum_error(error, instructions, qubits) として追加されます。

[10]:
# Create an empty noise model
noise_model = NoiseModel()

# Add depolarizing error to all single qubit u1, u2, u3 gates on qubit 0 only
error = depolarizing_error(0.05, 1)
noise_model.add_quantum_error(error, ['u1', 'u2', 'u3'], [0])

# Print noise model info
print(noise_model)
NoiseModel:
  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
  Instructions with noise: ['u3', 'u2', 'u1']
  Qubits with noise: [0]
  Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]

非ローカル量子ビット量子エラーに関する注意

NoiseModel は、追加された非ローカル量子ビット量子エラーをサポートしていません。これらは NoiseModel の外部で処理する必要があります。これは、独自の条件下で回路に量子エラーを挿入する必要がある場合、独自のトランスパイラー・パス (TransformationPass) を作成し、シミュレーターを実行する直前に、パスを実行する必要があることを示しています。 このようなトランスパイラー・パスの実装方法の例については、 noise.passes.LocalNoisePass を参照してください。

ノイズモデルでノイズがあるシミュレーションを実行する

コマンド AerSimulator(noise_model=noise_model) は、指定されたノイズ・モデルに構成されたシミュレーターを返します。 シミュレーターのノイズ・モデルを設定するだけでなく、ノイズ・モデルのゲートに従って、シミュレーターの基底ゲートもオーバーライドします。

ノイズモデルの例

ここでは、ノイズモデルの例をいくつか紹介します。デモでは、n量子GHZ状態を生成する単純なテスト回路を使用します。

[11]:
# System Specification
n_qubits = 4
circ = QuantumCircuit(n_qubits)

# Test Circuit
circ.h(0)
for qubit in range(n_qubits - 1):
    circ.cx(qubit, qubit + 1)
circ.measure_all()
print(circ)
        ┌───┐                ░ ┌─┐
   q_0: ┤ H ├──■─────────────░─┤M├─────────
        └───┘┌─┴─┐           ░ └╥┘┌─┐
   q_1: ─────┤ X ├──■────────░──╫─┤M├──────
             └───┘┌─┴─┐      ░  ║ └╥┘┌─┐
   q_2: ──────────┤ X ├──■───░──╫──╫─┤M├───
                  └───┘┌─┴─┐ ░  ║  ║ └╥┘┌─┐
   q_3: ───────────────┤ X ├─░──╫──╫──╫─┤M├
                       └───┘ ░  ║  ║  ║ └╥┘
meas: 4/════════════════════════╩══╩══╩══╩═
                                0  1  2  3

理想的なシミュレーション

[12]:
# Ideal simulator and execution
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(circ).result()
plot_histogram(result_ideal.get_counts(0))
[12]:
../../_images/tutorials_simulators_3_building_noise_models_25_0.png

ノイズの例1: 基本ビットフリップエラーノイズモデル

量子情報理論の研究で一般的なおもちゃノイズモデルの例を考えてみましょう。

  • 単一量子ビットゲートを適用する場合は、確率 p_gate1 で 量子ビットの状態を反転します。

  • 2量子ビットゲートを適用する場合、各量子ビットに単一量子ビットエラーを適用します。

  • 量子ビットを確率 p_reset で0ではなく1にリセットする場合。

  • 量子ビットを測定する時に、確率 p_meas で量子ビットの状態を反転させます。

[13]:
# Example error probabilities
p_reset = 0.03
p_meas = 0.1
p_gate1 = 0.05

# QuantumError objects
error_reset = pauli_error([('X', p_reset), ('I', 1 - p_reset)])
error_meas = pauli_error([('X',p_meas), ('I', 1 - p_meas)])
error_gate1 = pauli_error([('X',p_gate1), ('I', 1 - p_gate1)])
error_gate2 = error_gate1.tensor(error_gate1)

# Add errors to noise model
noise_bit_flip = NoiseModel()
noise_bit_flip.add_all_qubit_quantum_error(error_reset, "reset")
noise_bit_flip.add_all_qubit_quantum_error(error_meas, "measure")
noise_bit_flip.add_all_qubit_quantum_error(error_gate1, ["u1", "u2", "u3"])
noise_bit_flip.add_all_qubit_quantum_error(error_gate2, ["cx"])

print(noise_bit_flip)
NoiseModel:
  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
  Instructions with noise: ['reset', 'measure', 'u3', 'u1', 'cx', 'u2']
  All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']

ノイズがあるシミュレーションの実行

[14]:
# Create noisy simulator backend
sim_noise = AerSimulator(noise_model=noise_bit_flip)

# Transpile circuit for noisy basis gates
circ_tnoise = transpile(circ, sim_noise)

# Run and get counts
result_bit_flip = sim_noise.run(circ_tnoise).result()
counts_bit_flip = result_bit_flip.get_counts(0)

# Plot noisy output
plot_histogram(counts_bit_flip)
[14]:
../../_images/tutorials_simulators_3_building_noise_models_29_0.png

例2: T1/T2 熱緩和

熱緩和ベースのより現実的なエラーモデルを考えてみます。次の量子ビット環境を考えます: * 各量子ビットが熱緩和時間定数 \(T_1\) と脱位相(dephasing) 時間定数 \(T_2\) でパラメータ化されるとします。 * \(T_2 \le 2 T_1\) である必要があることに注意してください。 * 命令のエラー率はゲート時間と量子ビットの \(T_1\), \(T_2\) の値によって決められます。

[15]:
# T1 and T2 values for qubits 0-3
T1s = np.random.normal(50e3, 10e3, 4) # Sampled from normal distribution mean 50 microsec
T2s = np.random.normal(70e3, 10e3, 4)  # Sampled from normal distribution mean 50 microsec

# Truncate random T2s <= T1s
T2s = np.array([min(T2s[j], 2 * T1s[j]) for j in range(4)])

# Instruction times (in nanoseconds)
time_u1 = 0   # virtual gate
time_u2 = 50  # (single X90 pulse)
time_u3 = 100 # (two X90 pulses)
time_cx = 300
time_reset = 1000  # 1 microsecond
time_measure = 1000 # 1 microsecond

# QuantumError objects
errors_reset = [thermal_relaxation_error(t1, t2, time_reset)
                for t1, t2 in zip(T1s, T2s)]
errors_measure = [thermal_relaxation_error(t1, t2, time_measure)
                  for t1, t2 in zip(T1s, T2s)]
errors_u1  = [thermal_relaxation_error(t1, t2, time_u1)
              for t1, t2 in zip(T1s, T2s)]
errors_u2  = [thermal_relaxation_error(t1, t2, time_u2)
              for t1, t2 in zip(T1s, T2s)]
errors_u3  = [thermal_relaxation_error(t1, t2, time_u3)
              for t1, t2 in zip(T1s, T2s)]
errors_cx = [[thermal_relaxation_error(t1a, t2a, time_cx).expand(
             thermal_relaxation_error(t1b, t2b, time_cx))
              for t1a, t2a in zip(T1s, T2s)]
               for t1b, t2b in zip(T1s, T2s)]

# Add errors to noise model
noise_thermal = NoiseModel()
for j in range(4):
    noise_thermal.add_quantum_error(errors_reset[j], "reset", [j])
    noise_thermal.add_quantum_error(errors_measure[j], "measure", [j])
    noise_thermal.add_quantum_error(errors_u1[j], "u1", [j])
    noise_thermal.add_quantum_error(errors_u2[j], "u2", [j])
    noise_thermal.add_quantum_error(errors_u3[j], "u3", [j])
    for k in range(4):
        noise_thermal.add_quantum_error(errors_cx[j][k], "cx", [j, k])

print(noise_thermal)
NoiseModel:
  Basis gates: ['cx', 'id', 'rz', 'sx', 'u2', 'u3']
  Instructions with noise: ['reset', 'measure', 'u3', 'cx', 'u2']
  Qubits with noise: [0, 1, 2, 3]
  Specific qubit errors: [('reset', (0,)), ('reset', (1,)), ('reset', (2,)), ('reset', (3,)), ('measure', (0,)), ('measure', (1,)), ('measure', (2,)), ('measure', (3,)), ('u2', (0,)), ('u2', (1,)), ('u2', (2,)), ('u2', (3,)), ('u3', (0,)), ('u3', (1,)), ('u3', (2,)), ('u3', (3,)), ('cx', (0, 0)), ('cx', (0, 1)), ('cx', (0, 2)), ('cx', (0, 3)), ('cx', (1, 0)), ('cx', (1, 1)), ('cx', (1, 2)), ('cx', (1, 3)), ('cx', (2, 0)), ('cx', (2, 1)), ('cx', (2, 2)), ('cx', (2, 3)), ('cx', (3, 0)), ('cx', (3, 1)), ('cx', (3, 2)), ('cx', (3, 3))]

ノイズがあるシミュレーションの実行

[16]:
# Run the noisy simulation
sim_thermal = AerSimulator(noise_model=noise_thermal)

# Transpile circuit for noisy basis gates
circ_tthermal = transpile(circ, sim_thermal)

# Run and get counts
result_thermal = sim_thermal.run(circ_tthermal).result()
counts_thermal = result_thermal.get_counts(0)

# Plot noisy output
plot_histogram(counts_thermal)
[16]:
../../_images/tutorials_simulators_3_building_noise_models_33_0.png
[17]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.24.0.dev0+dba2eff
qiskit-aer0.11.2
qiskit-ibmq-provider0.19.2
qiskit0.40.0
System information
Python version3.8.11
Python compilerClang 12.0.5 (clang-1205.0.22.11)
Python builddefault, Jul 27 2021 10:46:38
OSDarwin
CPUs8
Memory (Gb)64.0
Tue Feb 07 10:30:00 2023 JST

This code is a part of Qiskit

© Copyright IBM 2017, 2023.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.