quairkit.qinfo.qinfo

quairkit.qinfo.qinfo.channel_repr_convert(representation, source, target, tol=1e-06)

Convert the given representation of a channel to the target implementation.

Parameters:
representation : ndarray | Tensor | List[Tensor] | List[ndarray]

Input representation.

source : str

Input form, should be 'choi', 'kraus' or 'stinespring'.

target : str

Target form, should be 'choi', 'kraus' or 'stinespring'.

tol : float

Error tolerance for the conversion from Choi, \(10^{-6}\) by default.

Raises:

ValueError – Unsupported channel representation: require Choi, Kraus or Stinespring.

Returns:

Quantum channel by the target implementation.

Return type:

ndarray | Tensor

Examples

# Convert Choi to Kraus representation
bell = torch.tensor([1, 0, 0, 1], dtype=torch.complex64) / torch.sqrt(torch.tensor(2))
choi = torch.outer(bell, bell.conj())
kraus_ops = channel_repr_convert(choi, 'choi', 'kraus')
print(f'The Kraus operators are:\n{kraus_ops}')
The Kraus operators are:
tensor([[-0.7071+0.j,  0.0000+0.j],
        [ 0.0000+0.j, -0.7071+0.j]])

Examples

# Convert Kraus to Stinespring representation
p = 0.1
k0 = torch.tensor([[1, 0], [0, torch.sqrt(torch.tensor(1 - p))]], dtype=torch.complex64)
k1 = torch.tensor([[0, torch.sqrt(torch.tensor(p))], [0, 0]], dtype=torch.complex64)
stinespring = channel_repr_convert([k0, k1], 'kraus', 'stinespring')
print(f'The Stinespring representation is:\n{stinespring}')
The Stinespring representation is:
tensor([[1.0000+0.j, 0.0000+0.j],
        [0.0000+0.j, 0.3162+0.j],
        [0.0000+0.j, 0.9487+0.j],
        [0.0000+0.j, 0.0000+0.j]])

Examples

# Convert Stinespring to Choi representation
stine = torch.zeros((4, 2), dtype=torch.complex64)
stine[:2, :2] = torch.eye(2)  # Valid isometry (V†V = I)
choi = channel_repr_convert(stine, 'stinespring', 'choi')
print(f'The Choi representation is:\n{choi}')
The Choi representation is:
tensor([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
        [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
        [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
        [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]])

Note

choi -> kraus currently has the error of order 1e-6 caused by eigh.

Raises:

NotImplementedError – Does not support the conversion of input data type.

quairkit.qinfo.qinfo.create_choi_repr(linear_map, input_dim, input_dtype=None)

Create the Choi representation of a linear map with input checks.

This function verifies if the map is linear and if the output is a square matrix.

Parameters:
linear_map : Callable[[Tensor | ndarray], Tensor | ndarray]

A function representing the linear map, which takes and returns a square matrix.

input_dim : int

The dimension of the space in which the linear map operates.

input_dtype : dtype | None

The dtype of the input. Defaults to None.

Returns:

The Choi matrix of the linear map.

Return type:

torch.Tensor

Examples

def identity_map(matrix: torch.Tensor) -> torch.Tensor:
    return matrix

choi = create_choi_repr(identity_map, input_dim=2)
print(f'The Choi representation of identity is:\n{choi}')
The Choi representation of identity is:
tensor([[1.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
        [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
        [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
        [1.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]])
Raises:

RuntimeWarning – If linear_map is not linear or the output is not a square matrix.

quairkit.qinfo.qinfo.decomp_1qubit(unitary, return_global=False)

Decompose a single-qubit unitary operator into Z-Y-Z rotation angles.

Parameters:
unitary : ndarray | Tensor

A batch of 2x2 unitary matrices representing single-qubit gates, as either a numpy ndarray or a torch Tensor. The shape should be (m, 2, 2).

return_global : bool

If set to True, the global phase angle alpha is also returned.

Returns:

A tuple containing the angles (beta, gamma, delta) or (alpha, beta, gamma, delta) if return_global is True. The type of the tuple elements matches the input type.

Return type:

Tuple[ndarray, …] | Tuple[Tensor, …]

Examples

angles = decomp_1qubit(h())
print(f'The angles are:\n{angles}')
The angles are:
(tensor(0.), tensor(1.5708), tensor(3.1416))
Raises:

ValueError – Raises a ValueError if the input matrix is not a batch of 2x2 unitary matrices.

quairkit.qinfo.qinfo.decomp_ctrl_1qubit(unitary)

Decompose a controlled single-qubit unitary operator into its components.

Parameters:
unitary : ndarray | Tensor

A 2x2 unitary matrix representing the single-qubit gate, as either a numpy ndarray or a torch Tensor.

Returns:

A tuple containing the global phase alpha and the matrices A, B, C, which are components of the decomposition. The type of the tuple elements matches the input type.

Return type:

Tuple[ndarray, …] | Tuple[Tensor, …]

Examples

# Decompose X gate
alpha, A, B, C = decomp_ctrl_1qubit(x())
print(f'The matrices are:\n{alpha, A, B, C }')
The matrices are:
(tensor(0.), tensor([[ 0.7071+0.j, -0.7071+0.j],
        [ 0.7071+0.j,  0.7071+0.j]]),
 tensor([[ 0.7071+0.j,  0.7071+0.j],
        [-0.7071+0.j,  0.7071+0.j]]),
 tensor([[1.-0.j, 0.+0.j],
        [0.+0.j, 1.+0.j]]))

Examples

# Decompose random unitary
alpha, A, B, C = decomp_ctrl_1qubit(random_unitary(1))
print(f'The matrices are:\n{alpha, A, B, C }')
The matrices are:
(tensor(-0.3577),
 tensor([[ 0.1966+0.9432j, -0.0546-0.2620j],
         [ 0.0546-0.2620j,  0.1966-0.9432j]]),
 tensor([[ 0.3154-0.9104j,  0.0876+0.2529j],
         [-0.0876+0.2529j,  0.3154+0.9104j]]),
 tensor([[0.9918-0.1277j, 0.0000+0.0000j],
         [0.0000+0.0000j, 0.9918+0.1277j]]))
Raises:

ValueError – Raises a ValueError if the input matrix is not a 2x2 unitary matrix.

quairkit.qinfo.qinfo.diamond_norm(channel_repr, dim_io=None, **kwargs)

Calculate the diamond norm of input.

Parameters:
channel_repr : Channel | Tensor

A Channel or a torch.Tensor instance.

dim_io : int | Tuple[int, int]

The input and output dimensions.

**kwargs

Parameters to set cvx.

Raises:
  • RuntimeErrorchannel_repr must be Channel or torch.Tensor.

  • TypeError – “dim_io” should be “int” or “tuple”.

Warning

channel_repr is not in Choi representation, and is converted into ChoiRepr.

Returns:

Its diamond norm.

Return type:

float

Examples

def depolarizing_choi(p: float) -> torch.Tensor:
    bell = bell_state(2).density_matrix
    return (1 - p) * bell + p / 3 * (torch.kron(x(), x()) + torch.kron(y(), y()) + torch.kron(z(), z())) / 2

choi = depolarizing_choi(0.5)
dn = diamond_norm(choi, dim_io=2)
print(f'The diamond norm of this channel is:\n{dn}')
The diamond norm of this channel is:
0.7500035113999476
quairkit.qinfo.qinfo.gate_fidelity(U, V)

Calculate the fidelity between gates.

\[F(U, V) = |\text{tr}(UV^\dagger)|/2^n\]

\(U\) is a \(2^n\times 2^n\) unitary gate.

Parameters:
U : ndarray | Tensor

Quantum gate \(U\) in matrix form.

V : ndarray | Tensor

Quantum gate \(V\) in matrix form.

Returns:

Fidelity between gates.

Return type:

ndarray | Tensor

Examples

xy_fidelity = gate_fidelity(x(), y())
print(f'The fidelity of X and Y is:\n{xy_fidelity}')
The fidelity of X and Y is:
0.0
quairkit.qinfo.qinfo.general_state_fidelity(rho, sigma)

Calculate the fidelity measure of two general states.

\[F_*(\rho, \sigma) = F(\rho, \sigma) + \sqrt{(1 - \text{tr}[\rho])(1 - \text{tr}[\sigma])}\]

where \(F(\rho, \sigma)\) is the state fidelity without square.

Parameters:
rho : ndarray | Tensor | PureState | MixedState

A subnormalized quantum state.

sigma : ndarray | Tensor | PureState | MixedState

A subnormalized quantum state.

Returns:

The general state fidelity of the input subnormalized states.

Return type:

ndarray | Tensor

Examples

fidelity = general_state_fidelity(bell_state(2), zero_state(2))
print(f'The fidelity of Bell state and zero state is:\n{fidelity}')
The fidelity of Bell state and zero state is:
0.70710688829422

Calculate the link product of two Choi matrices of quantum channels.

JE : Tuple[ndarray | Tensor, str, List[int] | int, List[int] | int]

Tuple containing the Choi representation of channel E, its label, input dimensions, and output dimensions.

JF : Tuple[ndarray | Tensor, str, List[int] | int, List[int] | int]

Tuple containing the Choi representation of channel F, its label, input dimensions, and output dimensions.

The resulting Choi matrix after the link product, its label, and input/output dimensions.

Tuple[ndarray | Tensor, str, List[int], List[int]]

Note

The identification convention for input label is exemplified by “AB->CD”, where the same letter in different cases (uppercase vs lowercase) is recognized as the same system, and an apostrophe indicates a different system. When input and output dimensions are specified as an int, it implies that each system has the same dimensionality.

Examples

def identity_choi(dim: int) -> torch.Tensor:
    bell = eye(dim).flatten().to(torch.complex64)
    return torch.outer(bell, bell.conj()) / dim

JE = (identity_choi(2), "A->B", [2], [2])
JF = (identity_choi(2), "B->C", [2], [2])
J_result, label, dim_in, dim_out = link(JE, JF)
print(f'The resulting Choi matrix after the link product is {J_result}.\n'
      f'Its label is {label}.\n'
      f'Input/output dimensions are:{dim_in} and {dim_out}.')
The resulting Choi matrix after the link product is tensor([[0.2500+0.j, 0.0000+0.j, 0.0000+0.j, 0.2500+0.j],
                                                           [0.0000+0.j, 0.0000+0.j, 0.0000+0.j, 0.0000+0.j],
                                                           [0.0000+0.j, 0.0000+0.j, 0.0000+0.j, 0.0000+0.j],
                                                           [0.2500+0.j, 0.0000+0.j, 0.0000+0.j, 0.2500+0.j]]).
Its label is A->C.
Input/output dimensions are: [2] and [2].
quairkit.qinfo.qinfo.logarithmic_negativity(density_op)

Calculate the Logarithmic Negativity \(E_N = ||\rho^{T_A}||\) of the input quantum state.

Parameters:
density_op : ndarray | Tensor | PureState | MixedState

Density matrix form of the quantum state.

Returns:

The Logarithmic Negativity of the input quantum state.

Return type:

ndarray | Tensor

Examples

log_neg = logarithmic_negativity(bell_state(2))
print(f'The logarithmic negativity of Bell state is:\n{log_neg}')
The logarithmic negativity of Bell state is:
1.0
quairkit.qinfo.qinfo.mana(matrix, input_str, out_dim=None)

Compute the mana of states or channels.

Parameters:
matrix : ndarray | Tensor | PureState | MixedState

Quantum state or channel, when “channel”, it should be the choi matrix of channel.

input_str : str

“state” or “channel”.

out_dim : int | None

Output system dimension, only need to compute mana of channel.

Returns:

The output mana.

Return type:

ndarray | Tensor | PureState | MixedState

Examples

bell_mana = mana(bell_state(2), input_str="state")
print(f'The mana of Bell state is:\n{bell_mana}')
The mana of Bell state is:
tensor([0.6813], dtype=torch.float64)

Examples

choi_matrix = eye(4) / 2
mana_chan = mana(choi_matrix, input_str="channel", out_dim=2)
print(f'The mana of a Choi channel is:\n{mana_chan}')
The mana of a Choi channel is:
tensor([0.], dtype=torch.float64)
quairkit.qinfo.qinfo.mutual_information(state, dim_A, dim_B)

Compute the mutual information of a bipartite state.

Parameters:
state : ndarray | Tensor | PureState | MixedState

Input bipartite quantum state with system AB.

dim_A : int

Dimension of system A.

dim_B : int

Dimension of system B.

Returns:

The mutual information of the input quantum state.

Return type:

ndarray | Tensor

Examples

mi = mutual_information(bell_state(2), dim_A=2, dim_B=2)
print(f'The mutual information of Bell state is:\n{mi}')
The mutual information of Bell state is:
2.0
quairkit.qinfo.qinfo.negativity(density_op)

Compute the Negativity \(N = ||\frac{\rho^{T_A}-1}{2}||\) of the input quantum state.

Parameters:
density_op : ndarray | Tensor | PureState | MixedState

Density matrix form of the quantum state.

Returns:

The Negativity of the input quantum state.

Return type:

ndarray | Tensor

Examples

neg = negativity(bell_state(2))
print(f'The negativity of Bell state is:\n{neg}')
The negativity of Bell state is:
0.4999999701976776
quairkit.qinfo.qinfo.pauli_str_convertor(observable)

Concatenate the input observable with coefficient 1.

For example, if the input observable is [['z0,x1'], ['z1']], then this function returns the observable [[1, 'z0,x1'], [1, 'z1']].

Parameters:
observable : List

The observable to be concatenated with coefficient 1.

Returns:

The observable with coefficient 1.

Return type:

List

Examples

pauli_terms = [['Z0,X1'], ['Y2']]
converted = pauli_str_convertor(pauli_terms)
print(f'The converted result is:\n{converted}')
The converted result is:
[[1, 'Z0,X1'], [1, 'Y2']]
quairkit.qinfo.qinfo.purity(rho)

Calculate the purity of a quantum state.

\[P = \text{tr}(\rho^2)\]
Parameters:
rho : ndarray | Tensor | PureState | MixedState

Density matrix form of the quantum state.

Returns:

The purity of the input quantum state.

Return type:

ndarray | Tensor

Examples

max_mixed = purity(eye(2) / 2)
print(f'The purity of 1-qubit maximal mixed state is:\n{max_mixed}')
The purity of 1-qubit maximal mixed state is:
0.5
quairkit.qinfo.qinfo.relative_entropy(rho, sigma, base=2)

Calculate the relative entropy of two quantum states.

\[S(\rho \| \sigma)=\text{tr} \rho(\log \rho-\log \sigma)\]
Parameters:
rho : ndarray | Tensor | PureState | MixedState

Density matrix form of the quantum state.

sigma : ndarray | Tensor | PureState | MixedState

Density matrix form of the quantum state.

base : int | None

The base of logarithm. Defaults to 2.

Returns:

Relative entropy between input quantum states.

Return type:

ndarray | Tensor

Examples

rel_ent = relative_entropy(bell_state(2), eye(4) / 4)
print(f'The relative entropy between 2-qubit maximal mixed state and Bell state is:\n{rel_ent}')
The relative entropy between 2-qubit maximal mixed state and Bell state is:
1.999999761581421
quairkit.qinfo.qinfo.stab_nullity(unitary)

Tool for calculation of unitary-stabilizer nullity.

Parameters:
unitary : ndarray | Tensor

A batch of unitary matrices.

Returns:

Unitary-stabilizer nullity for each unitary matrix.

Return type:

ndarray | Tensor

Examples

unitary_stabilizer_nullity = stab_nullity(h().to(torch.complex128))
print(f'The unitary-stabilizer nullity for Hadamard gate is:\n{unitary_stabilizer_nullity}')
The unitary-stabilizer nullity for Hadamard gate is:
tensor([0.])
quairkit.qinfo.qinfo.stab_renyi(density, alpha)

Tool for calculation of stabilizer Renyi entropy.

Parameters:
density : ndarray | Tensor | PureState | MixedState

A batch of density matrices.

alpha : ndarray | Tensor | Iterable[float] | float

The Renyi entropy exponent.

Returns:

Stabilizer Renyi entropy for each density matrix.

Return type:

ndarray | Tensor

Examples

stabilizer_renyi_entropy = stab_renyi(zero_state(1), alpha=2)
print(f'The stabilizer Renyi entropy for zero state with alpha=2 is:\n{stabilizer_renyi_entropy}')
The stabilizer Renyi entropy for zero state with alpha=2 is:
(tensor([2.3842e-07]),)
quairkit.qinfo.qinfo.state_fidelity(rho, sigma)

Calculate the fidelity of two quantum states, no extra square is taken.

\[F(\rho, \sigma) = \text{tr}(\sqrt{\sqrt{\rho}\sigma\sqrt{\rho}})\]
Parameters:
rho : ndarray | Tensor | PureState | MixedState

A quantum state.

sigma : ndarray | Tensor | PureState | MixedState

A quantum state.

Returns:

The fidelity between the input quantum states.

Return type:

ndarray | Tensor

Note

The fidelity equation is based on Equation (9.53) in Quantum Computation & Quantum Information, 10th edition.

Examples

fidelity = state_fidelity(bell_state(2), eye(4)/4)
print(f'The state fidelity between Bell state and maximal mixed state is:\n{fidelity}')
The state fidelity between Bell state and maximal mixed state is:
0.5000725984573364
quairkit.qinfo.qinfo.trace_distance(rho, sigma)

Calculate the trace distance of two quantum states.

\[D(\rho, \sigma) = \frac{1}{2}\text{tr}|\rho-\sigma|\]
Parameters:
rho : ndarray | Tensor | PureState | MixedState

A quantum state.

sigma : ndarray | Tensor | PureState | MixedState

A quantum state.

Returns:

The trace distance between the input quantum states.

Return type:

ndarray | Tensor

Examples

tr_dist = trace_distance(bell_state(2), eye(4)/4)
print(f'The trace distance between Bell state and maximal mixed state is:\n{tr_dist}')
The trace distance between Bell state and maximal mixed state is:
0.75
quairkit.qinfo.qinfo.von_neumann_entropy(rho, base=2)

Calculate the von Neumann entropy of a quantum state.

\[S = -\text{tr}(\rho \log_\text{base}(\rho))\]
Parameters:
rho : ndarray | Tensor | PureState | MixedState

Density matrix form of the quantum state.

base : ndarray | Tensor | Iterable[float] | float | int | None

The base of logarithm. Defaults to 2.

Returns:

The von Neumann entropy of the input quantum state.

Return type:

ndarray | Tensor

Examples

ent = von_neumann_entropy(completely_mixed_computational(1))
print(f'The von neumann entropy of 1-qubit maximal mixed state is:\n{ent}')
The von neumann entropy of 1-qubit maximal mixed state is:
1.0