Edit

How to build noise models for quantum simulations in the QDK

The Microsoft Quantum Development Kit (QDK) includes a set of quantum simulators that model how your program runs on a quantum computer. Programs that you run on a quantum computer always include some type and degree of noise. The QDK Python package lets you build custom noise models to use in your simulations through the NoiseConfig API.

For instructions on how to install and use the QDK simulators, see How to install and run the QDK quantum simulators.

Types of noise

Each operation or instruction in a quantum program can introduce noise. The following table lists all the operations and instructions that you can set noise for.

Noise source Noise model parameter Source description
$X$ gate x Single-qubit Pauli gate, bit flip
$Y$ gate y Single-qubit Pauli gate, bit flip and phase flip
$Z$ gate z Single-qubit Pauli gate, phase flip
$H$ gate h Single-qubit Hadamard gate, creates equal superposition state
$S$ gate s Single-qubit gate, half-pi phase flip
$S^\dagger$ gate s_adj Single-qubit gate, adjoint of $S$
$T$ gate t Single-qubit gate, quarter-pi phase lip
$T^\dagger$ gate t_adj Single-qubit gate, adjoint of $T$
$S_X$ gate sx Single-qubit gate, half bit flip
$S_X^\dagger$ gate sx_adj Single-qubit gate, adjoint of $S_X$
$R_X$ gate rx Single-qubit gate, general phase rotation about $x$ axis
$R_Y$ gate ry Single-qubit gate, general phase rotation about $y$ axis
$R_Z$ gate rz Single-qubit gate, general phase rotation about $z$ axis
$CX$ gate cx Two-qubit gate, controlled-$X$ gate
$CY$ gate cy Two-qubit gate, controlled-$Y$ gate
$CZ$ gate cz Two-qubit gate, controlled-$Z$ gate
$R_{XX}$ gate rxx Two-qubit gate, analogous to $R_X$
$R_{YY}$ gate ryy Two-qubit gate, analogous to $R_Y$
$R_{ZZ}$ gate rzz Two-qubit gate, analogous to $R_Z$
$SWAP$ gate swap Two-qubit gate, swaps the states of the qubits
$CCX$ gate ccx Three-qubit gate, two-qubit controlled-$X$ gate
Qubit movement mov Qubit movement between device zones (for neutral atom device simulation)
Qubit measurement mz Single-qubit measurement in the Pauli-$Z$ basis
Qubit measurement and reset mresetz Single-qubit measurement and reset to 0 state

With NoiseConfig, you can apply four different kinds of noise to the preceding operations with specific probabilities. The following table lists the noise type parameters that you can set with NoiseConfig, including a parameter for no noise.

Noise type Noise model parameter Noise description Example use Example description
Pauli $X$ noise x Bit flip noise.z.x = 0.03 Bit flip occurs in 3% of $Z$ operations
Pauli $Y$ noise y Bit flip and phase flip noise.sx.y = 0.01 Bit flip and phase flip occurs in 1% of $S_X$ operations
Pauli $Z$ noise z Phase flip noise.h.z = 0.02 Phase flip occurs in 2% of $H$ operations
No noise i Identity operation, no effect noise.cz.ix = 0.02 Bit flip on only the target qubit occurs in 2% of $CZ$ operations
Qubit loss l Qubit is lost from the device noise.mov.l = 0.03 Qubit is lost in 3% of movements between device zones on a neutral atom quantum computer

The noise occurs after the source operation, not instead of the source operation. For example, noise.z.x means that the program applies the intended $Z$ gate to the qubit, and then applies an unintended $X$ gate to the qubit. Because the noise applies after the source, you can configure noise that has the same effect as the source. For example, noise.x.x applies an unintended bit flip after the intended bit flip.

Note

The neutral atom device simulation APIs support noise from a limited number of sources. For more information, see How to build noise models for neutral atom device simulations in the QDK.

Build a noise model

To build a noise model for a simulation and view the effects of that noise on the results of your quantum program, follow these steps.

  1. In VS Code, open the View menu and choose Command Palette.

  2. Enter Create: New Jupyter Notebook. An empty Jupyter Notebook file opens in a new tab.

  3. In the first cell of the notebook, import the required Python objects.

    from qdk import init, TargetProfile
    from qdk.openqasm import compile
    from qdk.simulation import NoiseConfig, run_qir
    from qdk.widgets import Histogram
    
  4. In a new cell, set the device QIR target profile and compile your OpenQASM circuit into QIR.

    init(target_profile=TargetProfile.Base)
    
    qasm_src = """
    include "stdgates.inc";
    qubit[2] qs;
    bit[2] r;
    
    h qs[0];
    cx qs[0], qs[1];
    r = measure qs;
    """
    
    qir = compile(qasm_src)
    
  5. Create a NoiseConfig object and build your noise model.

    noise = NoiseConfig()
    
    noise.h.x = 0.01
    noise.cx.zi = 0.02
    

    This code produces the following noise model, where the noise rate is the probability that the source causes the corresponding type of noise.

    Noise source Noise type Noise rate
    $H$ gate Bit flip 1%
    $CX$ gate Phase flip on control qubit 2%
  6. Run the simulator with the noise model and view a histogram of measurement results. For example, run the following code to simulate 1,000 shots of your program on the Clifford simulator.

    results = run_qir(qir, shots=1000, noise=noise, type="clifford")
    Histogram(results, labels="kets")
    
  7. To compare the noisy results with a noiseless simulation, run the simulation again with no noise model.

    results = run_qir(qir, shots=1000, type="clifford")
    Histogram(results, labels="kets")
    

Set multiple types of noise on the same source

You can model different types of noise on the same source, with different probabilities for each type of noise. For example, the following code sets a 1% chance that a bit flip occurs and a 3% chance that a phase flip occurs after a Hadamard gate.

noise.h.x = 0.01
noise.h.z = 0.03

When you configure multiple noise types for the same operation, only one noise type can apply to each operation in your program. For example, each Hadamard gate can have either $X$ noise or $Z$ noise, but not both.

Noise model functions

Instead of noise model parameters, you can use the following set of noise functions to build your noise model.

Set Pauli noise

To include Pauli noise in your model, call the set_pauli_noise function on a gate or movement operation.

For single-qubit operations, pass a one-character Pauli string and a noise rate. For example, the following code sets a 1% chance that a bit flip occurs during qubit movement.

# Equivalent to: noise.mov.x = 0.01
noise.mov.set_pauli_noise('X', 0.01)

For two-qubit operations, pass a two-character Pauli string and a noise rate. The first character of the Pauli string corresponds to noise on the control qubit and the second character corresponds to noise on the target qubit. For example, the following code sets correlated phase flips after 1% of $CX$ operations.

# Equivalent to: noise.cx.zz = 0.01
noise.cx.set_pauli_noise('ZZ', 0.01)

Set depolarizing noise

The set_depolarizing function sets equal but uncorrelated noise rates for all three types of Pauli noise. For example, the following code sets a 3% chance that Pauli noise occurs after an $H$ operation, distributed evenly as a 1% chance for each of the three Pauli noise types.

# Equivalent to:
#     noise.h.x = 0.01
#     noise.h.y = 0.01
#     noise.h.z = 0.01
noise.h.set_depolarizing(0.03)

Set bit flip noise

To set the noise rate for bit flips, use the set_bitflip function on a gate or movement operation. For example, the following code sets a 1% chance that a phase flip occurs after an $R_Z$ operation.

# Equivalent to: noise.rz.x = 0.01
noise.rz.set_bitflip(0.01)

Set phase flip noise

To set the noise rate for phase flips in an operation, use the set_phaseflip function on a gate or movement operation. For example, the following code sets a 1% chance that a phase flip occurs after an $R_Y$ operation.

# Equivalent to: noise.ry.z = 0.01
noise.ry.set_phaseflip(0.01)