mimiqcircuits.operations.noisechannel.mixedunitary

Classes

MixedUnitary(*args)

MixedUnitary(p,umatrices).

class mimiqcircuits.operations.noisechannel.mixedunitary.MixedUnitary(*args)[source]

Bases: krauschannel

MixedUnitary(p,umatrices).

Custom N-qubit mixed unitary channel specified by a list of \(2^N \times 2^N\) unitary matrices 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 KrausChannel() instead.

The unitary 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\).

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

See also

Kraus ismixedunitary() krauschannel

Parameters:
  • p (list) – List of probabilities, must be positive real numbers and add up to 1.

  • umatrices (list) – List of complex-valued \(2^N \times 2^N\) matrices. The number of qubits is equal to \(N\).

The length of the lists p and umatrices must be equal.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> c = Circuit()
>>> c.push(MixedUnitary([0.9, 0.1], [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [1, 0]])]), 0)
1-qubit circuit with 1 instruction:
└── MixedUnitary((0.9, "Custom([1 0; 0 1])"),(0.1, "Custom([0 1; 1 0])")) @ q[0]
>>> c.push(MixedUnitary([0.8, 0.2], [Matrix(GateID().matrix()), Matrix(GateRX(0.2).matrix())]), 1)
2-qubit circuit with 2 instructions:
├── MixedUnitary((0.9, "Custom([1 0; 0 1])"),(0.1, "Custom([0 1; 1 0])")) @ q[0]
└── MixedUnitary((0.8, "Custom([1.0 0; 0 1.0])"),(0.2, "Custom([0.995004165278026 -0.0 - 0.0998334166468282*I; -0.0 - 0.0998334166468282*I 0.995004165278026])")) @ q[1]

RescaleGate

>>> p1= 0.2
>>> p2 = 0.8
>>> U1 = Matrix([[1, 0], [0, 1]])  # Identity matrix
>>> U2 = Matrix([[0, 1], [1, 0]])  # Pauli-X matrix
>>> gate1 = GateCustom(U1)
>>> gate2 = GateCustom(U2)
>>> rescaled_gate1 = RescaledGate(gate1, sqrt(p1))
>>> rescaled_gate2 = RescaledGate(gate2, sqrt(p2))
>>> op = MixedUnitary([rescaled_gate1, rescaled_gate2])
>>> op
MixedUnitary((0.2, "Custom([1 0; 0 1])"), (0.8, "Custom([0 1; 1 0])"))
>>> c.push(op,1)
2-qubit circuit with 3 instructions:
├── MixedUnitary((0.9, "Custom([1 0; 0 1])"),(0.1, "Custom([0 1; 1 0])")) @ q[0]
├── MixedUnitary((0.8, "Custom([1.0 0; 0 1.0])"),(0.2, "Custom([0.995004165278026 -0.0 - 0.0998334166468282*I; -0.0 - 0.0998334166468282*I 0.995004165278026])")) @ q[1]
└── MixedUnitary((0.2, "Custom([1 0; 0 1])"),(0.8, "Custom([0 1; 1 0])")) @ q[1]
__init__(*args)[source]
evaluate(values)[source]

Evaluates symbolic parameters in the MixedUnitary using a dictionary of values.

Parameters:

values (dict) – A dictionary where keys are symbolic variables and values are the corresponding numerical values.

Returns:

A new MixedUnitary instance with evaluated parameters.

Return type:

MixedUnitary

krausmatrices()[source]

Returns the Kraus matrices associated with the given Kraus channel.

A mixed unitary channel is written as:

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

where \(U_k\) are the unitary matrices returned by this function.

If the Kraus channel is parametric, the matrix elements are wrapped in a symengine or sympy object.

Returns:

A list of symengine matrices representing the Kraus operators.

Return type:

list

probabilities()[source]

Returns the probabilities for each Kraus operator in a mixed unitary channel.

A mixed unitary channel is written as:

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

where \(p_k\) are the probabilities.

This method is valid only for mixed unitary channels.

Returns:

A list of probabilities for each Kraus operator.

Return type:

list

unitarymatrices()[source]

Unitary matrices associated with the given mixed unitary Kraus channel.

A mixed unitary channel is written as:

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

where \(U_k\) are the unitary matrices.

An error is raised if the channel is not mixed unitary (i.e., ismixedunitary(self)==False).

Note

If the Kraus channel is parametric, the matrix elements are wrapped in a symbolic object (e.g., from sympy or symengine). To manipulate expressions, use the appropriate symbolic manipulation libraries.

Examples

>>> from mimiqcircuits import *
>>> PauliX(0.2).unitarymatrices()
[[1.0, 0]
[0, 1.0]
, [0, 1.0]
[1.0, 0]
]
unitarygates()[source]

Returns the unitary gates associated with 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.

This method is valid only for mixed unitary channels.

unwrappedkrausmatrices()[source]

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

Example

>>> from mimiqcircuits import *
>>> op = PauliX(0.2)
>>> op.unwrappedkrausmatrices()
[[0.894427190999916, 0]
[0, 0.894427190999916]
, [0, 0.447213595499958]
[0.447213595499958, 0]
]
krausoperators()[source]

Returns the Kraus operators associated with the given Kraus channel.

This should be implemented for each specific channel.

Returns:

A list of matrices representing the Kraus operators.

Return type:

list

classmethod ismixedunitary()[source]

Determine whether the quantum operation is a mixed unitary channel.

A channel is considered mixed unitary if all the Kraus operators \(E_k\) are proportional to a unitary matrix \(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\).

Parameters:

krauschannel – The Kraus channel to check.

Returns:

True if the channel is a mixed unitary channel, False otherwise.

Return type:

bool

Examples

>>> from mimiqcircuits import *
>>> PauliX(0.1).ismixedunitary()
True
>>> AmplitudeDamping(0.1).ismixedunitary()
False
__str__()[source]

Compact string representation for the MixedUnitary.

__repr__()[source]

Full string representation for the MixedUnitary.