Noise

MimiqCircuitsBase.add_noise!Method
add_noise!(c, g, noise; before=false, parallel=false)

Add a noise operation noise to every operation g in the circuit c.

The noise operation noise can be a Kraus channel or a gate and will act on the same qubits as the operation g it is being added to.

The operations g and noise have to act on the same number of qubits.

Arguments

  • c: Circuit.
  • g: Operation to which noise will be added.
  • noise: Kraus channel or gate that will be added to each operation g.
  • before: (optional) Bool, default=false. If before is false then the noise is added right after the operation; if it's true it's added right before.
  • parallel: (optional) Bool, default=false. If parallel is false then the noise is added immediately after/before the operation. If it's true the function identifies blocks of consecutive transversal operations of type g and adds after each such block a block of transversal noise operations noise. The result of both should be equivalent, it's only the order of operations that changes.

Returns

The circuit c with the noise added in place.

Examples

Parallel vs not parallel.

julia> c = push!(Circuit(), GateH(), 1:3);

julia> add_noise!(c, GateH(), AmplitudeDamping(0.2))
3-qubit circuit with 6 instructions:
├── H @ q[1]
├── AmplitudeDamping(0.2) @ q[1]
├── H @ q[2]
├── AmplitudeDamping(0.2) @ q[2]
├── H @ q[3]
└── AmplitudeDamping(0.2) @ q[3]

julia> c = push!(Circuit(), GateH(), 1:3);

julia> add_noise!(c, GateH(), AmplitudeDamping(0.2); parallel=true)
3-qubit circuit with 6 instructions:
├── H @ q[1]
├── H @ q[2]
├── H @ q[3]
├── AmplitudeDamping(0.2) @ q[1]
├── AmplitudeDamping(0.2) @ q[2]
└── AmplitudeDamping(0.2) @ q[3]

Parallel will not work if gates aren't transversal.

julia> c = push!(Circuit(), GateCZ(), 1, 2:4);

julia> add_noise!(c, GateCZ(), Depolarizing2(0.1); parallel=true)
4-qubit circuit with 6 instructions:
├── CZ @ q[1], q[2]
├── Depolarizing(2,0.1) @ q[1:2]
├── CZ @ q[1], q[3]
├── Depolarizing(2,0.1) @ q[1,3]
├── CZ @ q[1], q[4]
└── Depolarizing(2,0.1) @ q[1,4]

The before=true option is mostly used for Measure.

julia> c = push!(Circuit(), Measure(), 1:3, 1:3);

julia> add_noise!(c, Measure(), PauliX(0.1); before=true)
3-qubit circuit with 6 instructions:
├── PauliX(0.1) @ q[1]
├── M @ q[1], c[1]
├── PauliX(0.1) @ q[2]
├── M @ q[2], c[2]
├── PauliX(0.1) @ q[3]
└── M @ q[3], c[3]

Unitary gates are added in the same way.

julia> c = push!(Circuit(), GateH(), 1:3);

julia> add_noise!(c, GateH(), GateRX(0.01))
3-qubit circuit with 6 instructions:
├── H @ q[1]
├── RX(0.01) @ q[1]
├── H @ q[2]
├── RX(0.01) @ q[2]
├── H @ q[3]
└── RX(0.01) @ q[3]
source
MimiqCircuitsBase.add_noiseMethod
add_noise(c, g, noise; before=false, parallel=false)

Add noise operation noise to every operation g in circuit c.

A copy of c is created and then noise is added to the copy.

See [add_noise!] for more information.

source
MimiqCircuitsBase.sample_mixedunitariesMethod
sample_mixedunitaries(c; rng, ids=false)

Samples one unitary gate for each mixed unitary Kraus channel in the circuit.

This is possible because for mixed unitary noise channels the probabilities of each Kraus operator are fixed (state-independent).

Note: This function is internally called (before applying any gate) when executing a circuit with noise using trajectories, but it can also be used to generate samples of circuits without running them.

See also ismixedunitary, MixedUnitary, probabilities, and unitarygates.

Arguments

  • c: Circuit to be sampled.
  • rng: (optional) Random number generator.
  • ids: (optional) Boolean, default=false. When the selected Kraus operator is an identity it has no effect on the circuit. The parameter ids decides whether to add it to the circuit (ids=true) or not (ids=false`; default). Usually, most of the Kraus operators selected will be identity gates.

Returns

A copy of circuit but with every mixed unitary Kraus channel replaced by one of the unitary gates of the channel (or nothing if identity and ids==false).

Examples

Gates and non-mixed-unitary Kraus channels remain unchanged.

julia> using Random

julia> c = push!(Circuit(), GateH(), 1:3);

julia> push!(c, Depolarizing1(0.5), 1:3);

julia> push!(c, AmplitudeDamping(0.5), 1:3)
3-qubit circuit with 9 instructions:
├── H @ q[1]
├── H @ q[2]
├── H @ q[3]
├── Depolarizing(1,0.5) @ q[1]
├── Depolarizing(1,0.5) @ q[2]
├── Depolarizing(1,0.5) @ q[3]
├── AmplitudeDamping(0.5) @ q[1]
├── AmplitudeDamping(0.5) @ q[2]
└── AmplitudeDamping(0.5) @ q[3]

julia> rng = MersenneTwister(42);

julia> sample_mixedunitaries(c; rng=rng, ids=true)
3-qubit circuit with 9 instructions:
├── H @ q[1]
├── H @ q[2]
├── H @ q[3]
├── Y @ q[1]
├── ID @ q[2]
├── ID @ q[3]
├── AmplitudeDamping(0.5) @ q[1]
├── AmplitudeDamping(0.5) @ q[2]
└── AmplitudeDamping(0.5) @ q[3]

By default identities are not included.

julia> rng = MersenneTwister(42);

julia> sample_mixedunitaries(c; rng=rng)
3-qubit circuit with 7 instructions:
├── H @ q[1]
├── H @ q[2]
├── H @ q[3]
├── Y @ q[1]
├── AmplitudeDamping(0.5) @ q[1]
├── AmplitudeDamping(0.5) @ q[2]
└── AmplitudeDamping(0.5) @ q[3]

Different calls to the function generate different results.

julia> sample_mixedunitaries(c; rng=rng)
3-qubit circuit with 6 instructions:
├── H @ q[1]
├── H @ q[2]
├── H @ q[3]
├── AmplitudeDamping(0.5) @ q[1]
├── AmplitudeDamping(0.5) @ q[2]
└── AmplitudeDamping(0.5) @ q[3]

julia> sample_mixedunitaries(c; rng=rng)
3-qubit circuit with 6 instructions:
├── H @ q[1]
├── H @ q[2]
├── H @ q[3]
├── AmplitudeDamping(0.5) @ q[1]
├── AmplitudeDamping(0.5) @ q[2]
└── AmplitudeDamping(0.5) @ q[3]
source
MimiqCircuitsBase.ProjectiveNoiseFunction
ProjectiveNoise(basis)

Single qubit projection noise onto a Pauli basis.

This channel is defined by the Kraus operators

\[E_1 = |\alpha\rangle \langle\alpha|, \quad E_2 = |\beta\rangle \langle\beta|,\]

where the states $|\alpha\rangle$ and $|\beta\rangle$ are the +1 and -1 eigenstates of a Pauli operator. Specifically, they correspond to $\{ |0\langle, |1\langle \}$ ($Z$ basis), $\{ |+\langle, |-\langle \}$ ($X$ basis), or $\{ |y+\langle, |y-\langle \}$ (Y basis).

This operation is similar to measuring in the corresponding basis ($X$, $Y$, or $Z$), except that the outcome of the measurement is not stored, i.e. there's loss of information.

Arguments

  • basis: Symbol, String or Char that selects the Pauli basis, "X", "Y", or "Z".

Examples

julia> push!(Circuit(), ProjectiveNoise("Z"), 1)
1-qubit circuit with 1 instructions:
└── ProjectiveNoiseZ @ q[1]

The Kraus matrices are given by:

julia> krausmatrices(ProjectiveNoise("X"))
2-element Vector{Matrix{Float64}}:
 [0.5 0.5; 0.5 0.5]
 [0.5 -0.5; -0.5 0.5]

julia> krausmatrices(ProjectiveNoise("Y"))
2-element Vector{Matrix{ComplexF64}}:
 [0.5 + 0.0im 0.0 - 0.5im; 0.0 + 0.5im 0.5 + 0.0im]
 [0.5 + 0.0im 0.0 + 0.5im; 0.0 - 0.5im 0.5 + 0.0im]

julia> krausmatrices(ProjectiveNoise("Z"))
2-element Vector{Matrix{Int64}}:
 [1 0; 0 0]
 [0 0; 0 1]
source
MimiqCircuitsBase.KrausType
Kraus(E)

Custom $N$ qubit Kraus channel specified by a list of Kraus operators.

A Kraus channel is defined by

\[\mathcal{E}(\rho) = \sum_k E_k \rho E_k^\dagger,\]

where $E_k$ are Kraus operators that need to fulfill $\sum_k E_k^\dagger E_k = I$.

If the Kraus operators are all proportional to unitaries, use MixedUnitary instead.

The Kraus matrices are defined in the computational basis in the usual textbook order (the first qubit corresponds to the left-most qubit). For 1 qubit we have $|0\rangle$, $|1\rangle$. For 2 qubits we have $|00\rangle$, $|01\rangle$, $|10\rangle$, $|11\rangle$. See also GateCustom.

Note

Currently only 1 and 2-qubit custom Kraus channels are supported.

See also MixedUnitary, AbstractKrausChannel.

Arguments

  • E: Vector of $2^N \times 2^N$ complex matrices or $N$ qubit operators. Both can be mixed.

Examples

julia> push!(Circuit(), Kraus([[1 0; 0 sqrt(0.9)], [0 sqrt(0.1); 0 0]]), 1)
1-qubit circuit with 1 instructions:
└── Kraus(Operator([1.0 0.0; 0.0 0.948683]), Operator([0.0 0.316228; 0.0 0.0])) @ q[1]

julia> push!(Circuit(), Kraus([Projector0(), Projector1()]), 1)
1-qubit circuit with 1 instructions:
└── Kraus(Projector0(1), Projector1(1)) @ q[1]

julia> push!(Circuit(), Kraus([[1 0; 0 0], Projector1()]), 1)
1-qubit circuit with 1 instructions:
└── Kraus(Operator([1.0 0.0; 0.0 0.0]), Projector1(1)) @ q[1]

julia> @variables x
1-element Vector{Symbolics.Num}:
 x

julia> g = Kraus([Projector0(), Projector1(x)])
Kraus(Projector0(1), Projector1(x))

julia> evaluate(g,Dict(x=>1))
Kraus(Projector0(1), Projector1(1))

julia> g = Kraus([[1 0; 0 sqrt(0.9)], [0 sqrt(0.1); 0 x]])
Kraus(Operator([1.0 0.0; 0.0 0.948683]), Operator([0 0.316228; 0 x]))

julia> evaluate(g,Dict(x=>0))
Kraus(Operator([1.0 0.0; 0.0 0.948683]), Operator([0 0.316228; 0 0]))
source
MimiqCircuitsBase.AbstractKrausChannelType
AbstractKrausChannel{N} <: Operation{N,0,0}

Supertype for all the $N$-qubit Kraus channels.

A Kraus channel is a quantum operation on a density matrix $\rho$ of the form

\[\mathcal{E}(\rho) = \sum_k E_k \rho E_k^\dagger,\]

where $E_k$ are Kraus operators that need to fulfill $\sum_k E_k^\dagger E_k \leq I$.

Special properties:

  • isCPTP: A Kraus channel a completely positive and trace preserving (CPTP) operation when $\sum_k E_k^\dagger E_k = I$. Currently, all noise channels are CPTP.

  • ismixedunitary: A Kraus channel is called a mixed unitary channel when the Kraus operators $E_k$ are each proportional to a unitary matrix $U_k$, i.e. when $\mathcal{E}(\rho) = \sum_k p_k U_k \rho U_k^\dagger$ with some probabilities $0\leq p_k \leq 1$ that add up to 1 and $U_k^\dagger U_k = I$.

See also krausmatrices, unitarymatrices, probabilities.

source
MimiqCircuitsBase.cumprobabilitiesMethod
cumprobabilities(mixedunitarychannel)

Cumulative sum of probabilities of a mixed unitary Kraus channel.

A mixed unitary channel is written as $\sum_k p_k U_k \rho U_k^\dagger$, where $p_k$ are the probabilities.

An error is returned for Kraus channels with ismixedunitary(krauschannel)==false.

Note

if the Kraus channel is parametric, the cumprobabilities are wrapped in a Symbolics.Num object. To manipulate expressions use the Symbolics package.

See also probabilities, ismixedunitary.

Examples

julia> cumprobabilities(Depolarizing1(0.1))
4-element Vector{Symbolics.Num}:
                0.9
 0.9333333333333333
 0.9666666666666667
                1.0
source
MimiqCircuitsBase.ismixedunitaryMethod
ismixedunitary(krauschannel)

Whether the quantum operation is a mixed unitary channel.

This is the case when all the Kraus operators $E_k$ are proportional to a unitary $U_k$, i.e. $\mathcal{E}(\rho) = \sum_k p_k U_k \rho U_k^\dagger$ with some probabilities $0\leq p_k \leq 1$ that add up to 1 and $U_k^\dagger U_k = I$.

Examples

julia> ismixedunitary(PauliX(0.1))
true

julia> ismixedunitary(AmplitudeDamping(0.1))
false
source
MimiqCircuitsBase.krausmatricesMethod
krausmatrices(krauschannel)

Kraus matrices associated to the given Kraus channel.

A mixed unitary channel is written as $\sum_k p_k U_k \rho U_k^\dagger$, where $U_k$ are the unitary matrices returned by this function.

Note

if the Kraus channel is parametric, the matrix elements are wrapped in a Symbolics.Num object. To manipulate expressions use the Symbolics package.

Examples

julia> krausmatrices(AmplitudeDamping(0.1))
2-element Vector{Matrix{Float64}}:
 [1.0 0.0; 0.0 0.9486832980505138]
 [0.0 0.31622776601683794; 0.0 0.0]

For mixed unitary channels the Kraus matrices are the unitary matrices times the square root of the probabilities.

julia> krausmatrices(PauliX(0.2))
2-element Vector{Matrix{Symbolics.Num}}:
 [0.8944271909999159 -0.0; 0.0 0.8944271909999159]
 [0.0 0.4472135954999579; 0.4472135954999579 0.0]
source
MimiqCircuitsBase.krausoperatorsMethod
krausoperators(kraus)

Kraus operators associated to the given Kraus channel.

See also krausmatrices.

Examples

julia> krausoperators(PauliX(0.2))
2-element Vector{Operator{1}}:
 Operator([0.8944271909999159 -0.0; 0.0 0.8944271909999159])
 Operator([0.0 0.4472135954999579; 0.4472135954999579 0.0])

julia> krausoperators(AmplitudeDamping(0.1))
2-element Vector{AbstractOperator{1}}:
 D(1, 0.9486832980505138)
 SigmaMinus(0.31622776601683794)
source
MimiqCircuitsBase.probabilitiesMethod
probabilities(mixedunitarychannel)

Probabilities of each Kraus operator for mixed unitary Kraus channels.

A mixed unitary channel is written as $\sum_k p_k U_k \rho U_k^\dagger$, where $p_k$ are the probabilities.

An error is returned for Kraus channels with ismixedunitary(krauschannel)==false.

Note

if the Kraus channel is parametric, the probabilities are wrapped in a Symbolics.Num object. To manipulate expressions use the Symbolics package.

See also ismixedunitary, unitarymatrices, and krausmatrices.

Examples

julia> probabilities(PauliX(0.1))
2-element Vector{Symbolics.Num}:
 0.9
 0.1
source
MimiqCircuitsBase.squaredkrausoperatorsMethod
squaredkrausoperators(kraus)

Square of of Kraus operators ($O^\dagger O$) associated to the given Kraus channel.

See also krausoperators.

Examples

julia> squaredkrausoperators(AmplitudeDamping(0.1))
2-element Vector{AbstractOperator{1}}:
 D(1, 0.8999999999999999)
 P₁(0.1)
source
MimiqCircuitsBase.unitarygatesMethod
unitarygates(krauschannel)

Unitary gates associated to the given mixed unitary Kraus channel.

A mixed unitary channel is written as $\sum_k p_k U_k \rho U_k^\dagger$, where $U_k$ are the unitary operators returned by this function.

An error is returned for Kraus channels with ismixedunitary(krauschannel)==false.

See also ismixedunitary, unitarymatrices, and krausmatrices.

Examples

julia> unitarygates(PauliNoise([0.9,0.1],["II","XX"]))
2-element Vector{PauliString{2}}:
 II
 XX
source
MimiqCircuitsBase.unitarymatricesMethod
unitarymatrices(mixedunitarychannel)

Unitary matrices associated to the given mixed unitary Kraus channel.

A mixed unitary channel is written as $\sum_k p_k U_k \rho U_k^\dagger$, where $U_k$ are the unitary matrices.

An error is returned for Kraus channels with ismixedunitary(krauschannel)==false.

Note

if the Kraus channel is parametric, the matrix elements are wrapped in a Symbolics.Num object. To manipulate expressions use the Symbolics package.

See also ismixedunitary, probabilities, and krausmatrices.

Examples

julia> unitarymatrices(PauliX(0.2))
2-element Vector{Matrix}:
 [1.0 -0.0; 0.0 1.0]
 [0 1; 1 0]
source
MimiqCircuitsBase.unwrappedcumprobabilitiesMethod
unwrappedcumprobabilities(mixedunitarychannel)

Cumulative sum of probabilities associated to the specified mixed unitary Kraus channel without the Symbolics.Num wrapper.

Note

If any of the noise channel's parameters is symbolic, an error is thrown.

See cumprobabilities for more information.

julia> unwrappedcumprobabilities(Depolarizing1(0.1))
4-element Vector{Float64}:
 0.9
 0.9333333333333333
 0.9666666666666667
 1.0
source
MimiqCircuitsBase.unwrappedkrausmatricesMethod
unwrappedkrausmatrices(krauschannel)

Returns the Kraus matrices associated to the specified Kraus channel without the Symbolics.Num wrapper.

Note

If any of the noise channel's parameters is symbolic, an error is thrown.

See krausmatrices for more information.

Examples

julia> unwrappedkrausmatrices(AmplitudeDamping(0.1))
2-element Vector{Matrix{Float64}}:
 [1.0 0.0; 0.0 0.9486832980505138]
 [0.0 0.31622776601683794; 0.0 0.0]
source
MimiqCircuitsBase.unwrappedprobabilitiesMethod
unwrappedprobabilities(mixedunitarychannel)

Probabilities associated to the specified mixed unitary Kraus channel without the Symbolics.Num wrapper.

Note

If any of the noise channel's parameters is symbolic, an error is thrown.

See probabilities for more information.

julia> unwrappedprobabilities(PauliX(0.1))
2-element Vector{Float64}:
 0.9
 0.1
source
MimiqCircuitsBase.unwrappedunitarymatricesMethod
unwrappedunitarymatrices(krauschannel)

Returns the unitary Kraus matrices associated to the mixed unitary Kraus channel without the Symbolics.Num wrapper.

Note

If any of the noise channel's parameters is symbolic, an error is thrown.

See unitarymatrices for more information.

Examples

julia> unwrappedunitarymatrices(PauliX(0.2))
2-element Vector{Matrix}:
 [1.0 -0.0; 0.0 1.0]
 [0 1; 1 0]
source
MimiqCircuitsBase.AmplitudeType
Amplitude(bs::BitString)

Operation to get amplitude of a state vector element.

The operation gets the quantum state's amplitude (which is a complex number) corresponding to the state defined by the bitstring bs in the computational basis and stores it in a z-register.

See BitString.

Examples

When defining a circuit, only the z-register to store the result needs to be specified.

julia> Amplitude(BitString("001"))
Amplitude(bs"001")

julia> c = push!(Circuit(),Amplitude(BitString("001")), 1)
0-qubit circuit with 1 instructions:
└── Amplitude(bs"001") @ z[1]
source
MimiqCircuitsBase.DiagonalOpType
DiagonalOp(a,b)

One-qubit diagonal operator.

The corresponding matrix

\[\begin{pmatrix} a & 0\\ 0 & b \end{pmatrix}\]

is parametrized by complex numbers a and b.

See also Operator, Projector0, Projector1.

Examples

julia> DiagonalOp(1,0.5)
D(1, 0.5)

julia> push!(Circuit(), ExpectationValue(DiagonalOp(1,0.5)), 1, 2)
1-qubit circuit with 1 instructions:
└── ⟨D(1,0.5)⟩ @ q[1], z[2]
source
MimiqCircuitsBase.AmplitudeDampingType
AmplitudeDamping(γ)

One-qubit amplitude damping noise channel.

This channel is defined by the Kraus operators

\[E_1 = \begin{pmatrix} 1 & 0 \\ 0 & \sqrt{1-\gamma} \end{pmatrix} ,\quad E_2 = \begin{pmatrix} 0 & \sqrt{\gamma} \\ 0 & 0 \end{pmatrix},\]

where $\gamma \in [0,1]$.

Physically, it corresponds to an energy gain/loss process, such as spontaneous emission.

Examples

julia> push!(Circuit(), AmplitudeDamping(0.1), 1)
1-qubit circuit with 1 instructions:
└── AmplitudeDamping(0.1) @ q[1]
source
MimiqCircuitsBase.GeneralizedAmplitudeDampingType
GeneralizedAmplitudeDamping(p,γ)

One-qubit generalized amplitude damping noise channel.

This channel is defined by the Kraus operators

\[E_1 = \sqrt{p} \begin{pmatrix} 1 & 0 \\ 0 & \sqrt{1-\gamma} \end{pmatrix} ,\quad E_2 = \sqrt{p} \begin{pmatrix} 0 & \sqrt{\gamma} \\ 0 & 0 \end{pmatrix} ,\quad E_3 = \sqrt{1-p} \begin{pmatrix} \sqrt{1-\gamma} & 0 \\ 0 & 1 \end{pmatrix} ,\quad E_4 = \sqrt{1-p} \begin{pmatrix} 0 & 0 \\ \sqrt{\gamma} & 0 \end{pmatrix},\]

where $\gamma, p \in [0,1]$.

Physically, it corresponds to a combination of spontaneous emission and spontaneous absorption with probabilities $p$ and $1-p$, respectively.

Examples

julia> push!(Circuit(), GeneralizedAmplitudeDamping(0.1, 0.3), 1)
1-qubit circuit with 1 instructions:
└── GeneralizedAmplitudeDamping(0.1,0.3) @ q[1]
source
MimiqCircuitsBase.PhaseAmplitudeDampingType
PhaseAmplitudeDamping(p,γ,β)

One-qubit phase amplitude damping noise channel.

This channel is defined by:

\[\mathcal{E}(\rho) = \begin{pmatrix} (1-\gamma)\rho_{00}+\gamma p & (1-2\beta)\sqrt{1-\gamma}\rho_{01} \\ (1-2\beta)\sqrt{1-\gamma}\rho_{10} & (1-\gamma)\rho_{11} + (1-p)\gamma \end{pmatrix}\]

Here, $p, \gamma, \beta \in [0,1]$.

This channel is equivalent to a GeneralizedAmplitudeDamping(p,γ) channel (see GeneralizedAmplitudeDamping), followed by a PauliZ(β) channel (see PauliZ).

Use krausmatrices to see a Kraus matrix representation of the channel.

See also AmplitudeDamping, GeneralizedAmplitudeDamping, and ThermalNoise.

Examples

julia> push!(Circuit(), PhaseAmplitudeDamping(0.1, 0.2, 0.3), 1)
1-qubit circuit with 1 instructions:
└── PhaseAmplitudeDamping(0.1,0.2,0.3) @ q[1]
source
MimiqCircuitsBase.ThermalNoiseType
ThermalNoise(T₁, T₂, t, nₑ)

One-qubit thermal noise channel.

The thermal noise channel is equivalent to the PhaseAmplitudeDamping channel, but it is parametrized instead as

\[\mathcal{E}(\rho) = \begin{pmatrix} e^{-\Gamma_1 t}\rho_{00}+(1-n_e)(1-e^{-\Gamma_1 t}) & e^{-\Gamma_2 t}\rho_{01} \\ e^{-\Gamma_2 t}\rho_{10} & e^{-\Gamma_1 t}\rho_{11} + n_e(1-e^{-\Gamma_1 t}) \end{pmatrix}\]

where $\Gamma_1=1/T_1$ and $\Gamma_2=1/T_2$, and the parameters must fulfill $T_1 \geq 0$, $T_2 \leq 2 T_1$, $t \geq 0$, and $0 \leq n_e \leq 1$.

These parameters can be related to the ones used to define the PhaseAmplitudeDamping channel through $p = 1-n_e$, $\gamma = 1-e^{-\Gamma_1 t}$, and $\beta = \frac{1}{2}(1-e^{-(\Gamma_2-\Gamma_1/2)t})$.

See also PhaseAmplitudeDamping, AmplitudeDamping, and GeneralizedAmplitudeDamping.

Arguments

  • T₁: Longitudinal relaxation rate.
  • T₂: Transversal relaxation rate.
  • t: Time duration of gate.
  • nₑ: Excitation fraction when in thermal equilibrium with the environment.

Examples

julia> push!(Circuit(), ThermalNoise(0.5, 0.6, 1.2, 0.3), 1)
1-qubit circuit with 1 instructions:
└── ThermalNoise(0.5,0.6,1.2,0.3) @ q[1]
source
MimiqCircuitsBase.DepolarizingType
Depolarizing(N,p)

$N$ qubit depolarizing noise channel.

The Kraus operators for the depolarizing channel are given by

\[E_1 = \sqrt{1-p} I_N, \quad E_i = \sqrt{p/(4^N-1)} P_i\]

where $p\in [0,1]$ is a probability, and $P_i` is an$N$-qubit Pauli string operator, i.e. a tensor product of one-qubit Pauli operators (see [`Paulistring`](@ref)). There is exactly one Kraus operator$E{i>1}$for each distinct combination of Pauli operators$Pi$, except for the$N$-qubit identity$I_N = I\otimes I \otimes I \otimes...``

For example, for one qubit we have 3 operators $P_i \in \{X,Y,Z\}$, and for two qubits we have 15 operators $P_i \in \{ I\otimes X, I\otimes Y, I\otimes Z, X\otimes I, Y\otimes I, Z\otimes I, X\otimes X, X\otimes Y, X\otimes Z, Y\otimes X, Y\otimes Y, Y\otimes Z, Z\otimes X, Z\otimes Y, Z\otimes Z \}$. Use unitarygates to see this.

This channel is a mixed unitary channel, see ismixedunitary, and is a special case of PauliNoise.

See also PauliString and PauliNoise.

Arguments

  • N: Number of qubits.
  • p: Probability of error, i.e. of not applying identity.

Examples

Depolarizing channels can be defined for any $N$:

julia> push!(Circuit(), Depolarizing(1, 0.1), 1)
1-qubit circuit with 1 instructions:
└── Depolarizing(1,0.1) @ q[1]

julia> push!(Circuit(), Depolarizing(5, 0.1), 1, 2, 3, 4, 5)
5-qubit circuit with 1 instructions:
└── Depolarizing(5,0.1) @ q[1:5]

For one and two qubits you can use the shorthand notation:

julia> push!(Circuit(), Depolarizing1(0.1), 1)
1-qubit circuit with 1 instructions:
└── Depolarizing(1,0.1) @ q[1]

julia> push!(Circuit(), Depolarizing2(0.1), 1, 2)
2-qubit circuit with 1 instructions:
└── Depolarizing(2,0.1) @ q[1:2]
source
MimiqCircuitsBase.PauliNoiseType
PauliNoise(p, paulistrings)

$N$ qubit Pauli noise channel specified by a list of probabilities and Pauli gates.

A Pauli channel is defined by

\[\mathcal{E}(\rho) = \sum_k p_k P_k \rho P_k,\]

where $0 \leq p_k \leq 1$ and $P_k$ are Pauli string operators, defined as tensor products of one-qubit Pauli operators (see PauliString) The probabilities must fulfill $\sum_k p_k = 1$.

This channel is a mixed unitary channel, see ismixedunitary.

See also Depolarizing, PauliX, PauliY, PauliZ, which are special cases of PauliNoise.

Arguments

  • p: Vector of probabilities that must add up to 1.
  • paulistrings: Vector of strings, each one of length $N$ and with each character being either "I", "X", "Y", or "Z". The number of qubits is equal to $N$.

The vectors p and paulistrings must have the same length.

Examples

PauliNoise channels can be defined for any number of qubits, and for any number of Pauli strings.

julia> push!(Circuit(), PauliNoise([0.8, 0.1, 0.1], ["I","X","Y"]), 1)
1-qubit circuit with 1 instructions:
└── PauliNoise((0.8,pauli"I"),(0.1,pauli"X"),(0.1,pauli"Y")) @ q[1]

julia> push!(Circuit(), PauliNoise([0.9, 0.1], ["XY","II"]), 1, 2)
2-qubit circuit with 1 instructions:
└── PauliNoise((0.9,pauli"XY"),(0.1,pauli"II")) @ q[1:2]

julia> push!(Circuit(), PauliNoise([0.5, 0.2, 0.2, 0.1], ["IXIX","XYXY","ZZZZ","IXYZ"]), 1, 2, 3, 4)
4-qubit circuit with 1 instructions:
└── PauliNoise((0.5,pauli"IXIX"),(0.2,pauli"XYXY"),(0.2,pauli"ZZZZ"),(0.1,pauli"IXYZ")) @ q[1:4]
source
MimiqCircuitsBase.PauliXType
PauliX(p)

One-qubit Pauli X noise channel (bit flip error).

This channel is defined by the Kraus operators

\[E_1 = \sqrt{1-p}\,I, \quad E_2 = \sqrt{p}\,X,\]

where $0 \leq p \leq 1$.

This channel is a mixed unitary channel, see ismixedunitary, and is a special case of PauliNoise.

PauliX(p) is the same as PauliNoise([1-p,p],["I","X"]).

Examples

julia> push!(Circuit(), PauliX(0.1), 1)
1-qubit circuit with 1 instructions:
└── PauliX(0.1) @ q[1]
source
MimiqCircuitsBase.PauliYType
PauliY(p)

One-qubit Pauli Y noise channel (bit-phase flip error).

This channel is determined by the Kraus operators

\[E_1 = \\sqrt{1-p}\,I, \\quad E_2 = \sqrt{p}\,Y,\]

where $0\\leq p \\leq 1$.

This channel is a mixed unitary channel, see ismixedunitary, and is a special case of PauliNoise.

PauliY(p) is the same as PauliNoise([1-p,p],["I","Y"]).

Examples

julia> push!(Circuit(), PauliY(0.1), 1)
1-qubit circuit with 1 instructions:
└── PauliY(0.1) @ q[1]
source
MimiqCircuitsBase.PauliZType
PauliZ(p)

One-qubit Pauli Z noise channel (phase flip error).

This channel is determined by the Kraus operators

\[E_1 = \sqrt{1-p}\,I, \quad E_2 = \sqrt{p}\,Z,\]

where $0 \leq p \leq 1$.

This channel is a mixed unitary channel, see ismixedunitary, and is a special case of PauliNoise.

PauliZ(p) is the same as PauliNoise([1-p,p],["I","Z"]).

Examples

julia> push!(Circuit(), PauliZ(0.1), 1)
1-qubit circuit with 1 instructions:
└── PauliZ(0.1) @ q[1]
source
MimiqCircuitsBase.MixedUnitaryType
MixedUnitary(p,U)

Custom $N$ qubit mixed unitary channel specified by a list of unitary gates and a list of probabilities that add up to 1.

A mixed unitary noise channel is defined by

\[\mathcal{E}(\rho) = \sum_k p_k U_k \rho U_k^\dagger,\]

where $0\leq p_k \leq 1$ and $U_k$ are unitary matrices. The probabilities must fulfill $\sum_k p_k = 1$.

If your Kraus matrices are not all proportional to unitaries, use Kraus instead.

The Kraus matrices are defined in the computational basis in the usual textbook order (the first qubit corresponds to the left-most qubit). For 1 qubit we have $|0\rangle$, $|1\rangle$. For 2 qubits we have $|00\rangle$, $|01\rangle$, $|10\rangle$, $|11\rangle$. See also GateCustom.

Note

Currently only 1 and 2-qubit custom MixedUnitary channels are supported.

See also Kraus, ismixedunitary, AbstractKrausChannel, and RescaledGate.

Arguments

  • p: Vector of probabilities, must be positive real numbers and add up to 1.
  • U: Vector of either complex-valued $2^N \times 2^N$ matrices or unitary gates acting on $N$ qubits. Both can be mixed.

The length of the vectors p and U must be equal.

Examples

julia> push!(Circuit(), MixedUnitary([0.9, 0.1], [[1 0; 0 1], [0 1; 1 0]]), 1)
1-qubit circuit with 1 instructions:
└── MixedUnitary((0.9,Custom([1.0 0.0; 0.0 1.0])),(0.1,Custom([0.0 1.0; 1.0 0.0]))) @ q[1]

julia> push!(Circuit(), MixedUnitary([0.8, 0.2], [GateID(), GateRX(0.2)]), 1)
1-qubit circuit with 1 instructions:
└── MixedUnitary((0.8,ID),(0.2,RX(0.2))) @ q[1]

julia> push!(Circuit(), MixedUnitary([0.8, 0.2], [[1 0; 0 1], GateRX(0.2)]), 1)
1-qubit circuit with 1 instructions:
└── MixedUnitary((0.8,Custom([1.0 0.0; 0.0 1.0])),(0.2,RX(0.2))) @ q[1]

julia> @variables x
1-element Vector{Symbolics.Num}:
 x

julia> g= MixedUnitary([0.9, x], [[1 0; 0 1], [0 1; 1 0]])
MixedUnitary((0.9, Custom([1.0 0.0; 0.0 1.0])), (x, Custom([0.0 1.0; 1.0 0.0])))

julia> evaluate(g,Dict(x=>.1))
MixedUnitary((0.9, Custom([1.0 0.0; 0.0 1.0])), (0.1, Custom([0.0 1.0; 1.0 0.0])))

julia> g= MixedUnitary([0.9, 0.1], [[1 0; 0 1], [0 1; 1 x]])
MixedUnitary((0.9, Custom([1 0; 0 1])), (0.1, Custom([0 1; 1 x])))

julia> evaluate(g,Dict(x=>0))
MixedUnitary((0.9, Custom([1 0; 0 1])), (0.1, Custom([0 1; 1 0])))
source
MimiqCircuitsBase.PauliStringType
PauliString(paulistr)

$N$-qubit tensor product of Pauli operators.

The PauliString gate can represent any $N$-qubit tensor product of Pauli operators of the form

\[P_1 \otimes P_2 \otimes P_3 \otimes \ldots \otimes P_N,\]

where each $P_i \in \{ I, X, Y, Z \}$ is a Pauli operator, including the identity.

See also GateID, GateX, GateY, GateZ.

Arguments

  • paulistr: string of length $N$ where each character is either "I", "X", "Y", or "Z". The number of qubits is equal to $N$.

Examples

PauliStrings of any length are supported.

julia> c = push!(Circuit(), PauliString("XX"), 1, 2)
2-qubit circuit with 1 instructions:
└── XX @ q[1:2]

julia> push!(c, PauliString("IXYZZYXI"), 1, 2, 3, 4, 5, 6, 7, 8)
8-qubit circuit with 2 instructions:
├── XX @ q[1:2]
└── IXYZZYXI @ q[1:8]

Decomposition

Decomposes into one-qubit Pauli gates.

julia> decompose(PauliString("XIYZZ"))
5-qubit circuit with 5 instructions:
├── X @ q[1]
├── ID @ q[2]
├── Y @ q[3]
├── Z @ q[4]
└── Z @ q[5]
source