マルチ量子ビット ゲートのノイズ モデルを構築する

Microsoft Quantum Development Kit (QDK) Python パッケージは、量子プログラム シミュレーションにおけるマルチ量子ビット ゲート用の柔軟なノイズ モデルをサポートします。 複数の量子ビット間の相関エラーやその他のノイズ効果をモデル化して、量子ハードウェアの動作をより正確に表すことができます。

QDKのノイズ モデルの詳細については、「QDKで量子シミュレーション用のノイズ モデルを構築する方法」を参照してください

前提条件

QDKでノイズ モデルを構築するには、次のツールをインストールします。

  • Visual Studio Code (VS Code) QDK 拡張機能Jupyter 拡張機能 がインストールされています。
  • jupyter qdk パッケージのPython追加機能付き最新バージョン。
pip install --upgrade "qdk[jupyter]"

相関ノイズ

マルチ量子ビット ゲートでは、相関ノイズが生成される可能性があります。この場合、ゲートが動作するすべての量子ビットに同じノイズ パターンが適用されます。 複数量子ビット ゲートに相関ノイズを設定するには、各量子ビットのノイズ パラメーターを指定します。

たとえば、次の Python コードは、2% 確率で $CX$ ゲートに相関ビット フリップを設定します。 $CX$ ゲートでノイズが発生した場合、$X$ ゲートは制御量子ビットとターゲット量子ビットの両方に適用されます。 ノイズは常に両方の量子ビットに適用されるため、ノイズは相関しています。

from qdk.simulation import NoiseConfig

noise = NoiseConfig()

noise.cx.xx = 0.02

ノイズに相関関係を持たせない場合は、ID パラメーターを使用して複数のノイズの種類を設定します。

noise.cx.xi = 0.02 # Bit flip on control qubit, do nothing to target qubit
noise.cx.ix = 0.02 # Do nothing to control qubit, bit flip on target qubit

相関のないモデルでは、各ノイズ設定は 2% 確率で個別に発生します。 個々のゲートに適用できるノイズ設定は 1 つだけなので、このノイズ モデルでは、同じゲート内の両方の量子ビットに $X$ ノイズを適用できません。

両方の量子ビットでノイズの可能性をモデル化するには、両方の量子ビットにノイズを適用する別のノイズ設定を構成します。

noise.cx.xi = 0.02 # Bit flip on control qubit, do nothing to target qubit
noise.cx.ix = 0.02 # Do nothing to control qubit, bit flip on target qubit
noise.cx.xx = 0.02 # Bit flip on both qubits

量子ビット損失ポリシー

量子ビット損失は、デバイスから量子ビットが失われるノイズの一種です。 損失ポリシーは、操作の開始時に 1 つ以上の量子ビットが欠落している場合のマルチ量子ビット ゲートの動作を定義します。 QDKでは、次の損失ポリシーがサポートされています。

損失ポリシー ポリシーを適用できるゲート 残りの量子ビットへの影響
SKIP すべてのゲート ゲートは残りの量子ビットには影響しません
PROPAGATE すべてのゲート その他の量子ビットも失われます
DEGRADE rxxryy、および rzz 残りの量子ビットに単一量子ビット ゲートとして適用する
RESIDUAL_S_DAGGER すべてのゲート 残りの量子ビットに s_sdj ゲートを適用する
APPLY_ANYWAY swap 残りの量子ビットは、失われた量子ビットと状態を入れ替えます

損失ポリシーがシミュレーションに影響を与えるには、ノイズ モデルに量子ビット損失を含める必要があります。 失われた量子ビットは、シミュレーション中に追跡されます。 損失ポリシーは、ゲートが少なくとも 1 つの失われた量子ビットで動作する場合に適用されます。

ノイズ モデルに損失ポリシーを含めるには、qdk.simulation モジュールのLossPolicyを使用します。 次のコードは、各ポリシーを設定する例を示しています。

from qdk.simulation import NoiseConfig, LossPolicy

noise = NoiseConfig()

noise.x.l = 0.01 # 1% chance of qubit loss after X gates

noise.cz.on_loss   = LossPolicy.SKIP               # Don't apply CZ to remaining qubit
noise.cx.on_loss   = LossPolicy.PROPAGATE          # Both qubits are lost from CX gate
noise.rxx.on_loss  = LossPolicy.DEGRADE            # Apply Rx gate to remaining qubit
noise.ryy.on_loss  = LossPolicy.RESIDUAL_S_DAGGER  # Apply S-adjoint to remaining qubit
noise.swap.on_loss = LossPolicy.APPLY_ANYWAY       # Perform swap anyway

どの損失ポリシーでも、設定されたノイズは依然として残りの量子ビットに影響を与える可能性があります。 たとえば、次のコードでは、CZ ゲート内のいずれかの量子ビットが欠落している場合でも、CZ ゲートにビット フリップ ノイズを適用できます。

noise.z.l = 0.01 # Introduce qubit loss

noise.cz.xx = 0.02 # Set correlated bit flip noise on CZ gates
noise.cz.on_loss = LossPolicy.SKIP

カスタム ノイズ特性

より複雑なノイズ モデルを構築するために、 QDK には Q# および OpenQASM プログラム用のカスタム ノイズ組み込み関数があります。 ノイズ組み込み関数は、関連するノイズをモデル化するためにプログラムに挿入するカスタム ゲートのように動作します。 カスタム組み込みを使用して、 NoiseConfig がサポートするゲートまたはカスタム ゲートのノイズをモデル化できます。

次の例は、3 つの量子ビット間でクロストークをモデル化するカスタム ノイズ組み込み関数を構築する方法を示しています。 ノイズ組み込み関数は、$CNOT$ ゲートが適用された後、相関ビット フリップを 2 つの量子ビットに適用します。

Q# プログラムにノイズ組み込みを追加する

Q# プログラムでは、ノイズ組み込みを宣言するために@NoiseIntrinsic() を使用します。 次に、NoiseConfig からの intrinsic メソッドを使用して、ノイズ特性を構成します。

サンプル ノイズ特性を構成して、使用するには、Jupyter Notebook で次の手順を実行します。

  1. 必要なオブジェクトをインポートし、QIR ターゲット プロファイルを設定します。

    from qdk import init, TargetProfile
    from qdk import qsharp
    from qdk.simulation import run_qir, NoiseConfig
    
    init(target_profile=TargetProfile.Adaptive_RIF)
    
  2. 各 $CNOT$ ゲートの後に GHZ というノイズ組み込み関数を呼び出す、Crosstalk3Q という名前の Q# プログラムを作成してください。

    %%qsharp
    
    // A noise intrinsic representing crosstalk on 3 qubits.
    // In the ideal circuit this is a no-op; the simulator injects
    // Pauli errors according to the NoiseConfig.
    @NoiseIntrinsic()
    operation Crosstalk3Q(q0: Qubit, q1: Qubit, q2: Qubit) : Unit {
        body intrinsic;
    }
    
    // Prepare a GHZ state on 3 qubits, with crosstalk after each CNOT.
    operation GHZ() : Result[] {
        use qs = Qubit[3];
        H(qs[0]);
        CNOT(qs[0], qs[1]);
        Crosstalk3Q(qs[0], qs[1], qs[2]);  // crosstalk hits all 3 qubits
        CNOT(qs[1], qs[2]);
        Crosstalk3Q(qs[0], qs[1], qs[2]);  // crosstalk again
        MResetEachZ(qs)
    }
    
  3. 組み込み関数用のノイズ テーブルを設定します。 量子ビットの数、ノイズの種類、および各ノイズの種類の確率を設定します。

    noise = NoiseConfig()
    table = noise.intrinsic("Crosstalk3Q", num_qubits=3)
    table.ixx = 0.10  # 10% XX on qubits 1-2
    table.xxi = 0.05  #  5% XX on qubits 0-1
    
  4. プログラムを QIR にコンパイルします。

    qir = qsharp.compile("GHZ()")
    
  5. 結果のヒストグラムのシミュレーションとプロットを実行します。

    result = run_qir(qir, shots=1000, noise=noise)
    Histogram(result)
    
  6. ノイズのないシミュレーションと結果を比較するには、ノイズ モデルなしでシミュレーションを再度実行します。

    result = run_qir(qir, shots=1000)
    Histogram(result)
    

OpenQASM プログラムにノイズ組み込み関数を追加する

OpenQASM プログラムでは、@qdk.qir.noise_intrinsic を使用して、ノイズ特性をカスタム ゲート定義として作成します。 次に、NoiseConfig からの intrinsic メソッドを使用して、ノイズ特性を構成します。

crosstalk_3qと呼ばれるノイズ組み込みを使用して OpenQASM プログラムを記述し、プログラムを QIR にコンパイルするには、Jupyter ノートブックで次のコードを実行します。

from qdk.openqasm import compile, OutputSemantics
from qdk import TargetProfile
from qdk.simulation import run_qir, NoiseConfig
from qdk.widgets import Histogram

qasm_source = """
OPENQASM 3.0;
include "stdgates.inc";

// A noise intrinsic representing crosstalk on 3 qubits.
// In the ideal circuit this is a no-op; the simulator injects
// Pauli errors according to the NoiseConfig.
@qdk.qir.noise_intrinsic
gate crosstalk_3q q0, q1, q2 {}

qubit[3] qs;

// Prepare a GHZ state on 3 qubits, with crosstalk after each CNOT.
h qs[0];
cx qs[0], qs[1];
crosstalk_3q qs[0], qs[1], qs[2];  // crosstalk hits all 3 qubits
cx qs[1], qs[2];
crosstalk_3q qs[0], qs[1], qs[2];  // crosstalk again

bit[3] res = measure qs;
"""

qir_qasm = compile(
    qasm_source,
    output_semantics=OutputSemantics.OpenQasm,
    target_profile=TargetProfile.Base,
)

ノイズ組み込みを構成し、シミュレーションを実行するには、次のコードを実行します。

noise = NoiseConfig()
table = noise.intrinsic("crosstalk_3q", num_qubits=3)
table.ixx = 0.10  # 10% XX on qubits 1-2
table.xxi = 0.05  #  5% XX on qubits 0-1

result = run_qir(qir_qasm, shots=1000, noise=noise)
Histogram(result)