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.

Decomposes a single-qubit unitary \(U\) as \(U = e^{i\alpha} R_Z(\beta) R_Y(\gamma) R_Z(\delta)\).

Parameters:
unitary : ndarray | Tensor

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

return_global : bool

If set to True, the global phase angle \(\alpha\) is also returned. Defaults to False.

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. For batch input, each angle is a tensor with shape (m,).

Return type:

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

Note

This function supports batch operations. When input is a batch of unitaries, all angles are computed in parallel.

Examples

from quairkit.database import h
from quairkit.qinfo import decomp_1qubit

# Decompose Hadamard gate
angles = decomp_1qubit(h())
print(f'Z-Y-Z angles for H gate: {angles}')
Z-Y-Z angles for H gate: (tensor(0.), tensor(1.5708), tensor(3.1416))
# Decompose with global phase
angles_with_phase = decomp_1qubit(h(), return_global=True)
print(f'With global phase: {angles_with_phase}')
With global phase: (tensor(0.), tensor(0.), tensor(1.5708), tensor(3.1416))
Raises:

ValueError – If the input matrix is not a 2x2 unitary matrix or 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 two quantum gates.

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

where \(U\) and \(V\) are \(2^n\times 2^n\) unitary gates.

Parameters:
U : ndarray | Tensor

First quantum gate in matrix form (can be a Tensor, ndarray, or State).

V : ndarray | Tensor

Second quantum gate in matrix form (can be a Tensor, ndarray, or State).

Returns:

Fidelity between the two gates. Returns a scalar for single gates, or a tensor for batched gates.

Return type:

ndarray | Tensor

Note

This function supports batch operations. When input gates have batch dimensions, the fidelity is computed element-wise along the batch dimension.

Examples

from quairkit.database import x, y
from quairkit.qinfo import gate_fidelity

# Calculate fidelity between X and Y gates
fid = gate_fidelity(x(), y())
print(f'Fidelity between X and Y gates: {fid}')
Fidelity between X and Y gates: 0.0
# Batch gate fidelity example
from quairkit.database import random_unitary

batch_U = random_unitary(1, size=3)  # Batch of 3 single-qubit unitaries
batch_V = random_unitary(1, size=3)  # Batch of 3 single-qubit unitaries
batch_fid = gate_fidelity(batch_U, batch_V)
print(f'Batch fidelity shape: {batch_fid.shape}')
Batch fidelity shape: torch.Size([3])
quairkit.qinfo.qinfo.general_state_fidelity(rho, sigma)

Calculate the fidelity measure of two general (possibly subnormalized) quantum states.

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

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

This measure is useful for subnormalized states where \(\text{tr}[\rho] \leq 1\).

Parameters:
rho : ndarray | Tensor | StateSimulator | StateOperator

First quantum state (can be a State, Tensor, or ndarray). May be subnormalized.

sigma : ndarray | Tensor | StateSimulator | StateOperator

Second quantum state (can be a State, Tensor, or ndarray). May be subnormalized.

Returns:

The general state fidelity of the input states. Returns a scalar for single states, or a tensor for batched states.

Return type:

ndarray | Tensor

Note

This function supports batch operations. When input states have batch dimensions, the fidelity is computed element-wise along the batch dimension.

Examples

from quairkit.database import bell_state, zero_state
from quairkit.qinfo import general_state_fidelity

# Calculate general fidelity between Bell state and zero state
fid = general_state_fidelity(bell_state(2), zero_state(2))
print(f'General fidelity: {fid}')
General fidelity: 0.70710688829422
# Batch general fidelity example
from quairkit.database import random_state

batch_rho = random_state(1, size=3)  # Batch of 3 states
batch_sigma = random_state(1, size=3)  # Batch of 3 states
batch_fid = general_state_fidelity(batch_rho, batch_sigma)
print(f'Batch general fidelity shape: {batch_fid.shape}')
Batch general fidelity shape: torch.Size([3])

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 | StateSimulator | StateOperator

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 | StateSimulator | StateOperator

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 | StateSimulator | StateOperator

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 | StateSimulator | StateOperator

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 | StateSimulator | StateOperator

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)\]

The purity ranges from \(1/d\) (maximally mixed) to 1 (pure state), where \(d\) is the dimension.

Parameters:
rho : ndarray | Tensor | StateSimulator | StateOperator

Density matrix form of the quantum state (can be a State, Tensor, or ndarray).

Returns:

The purity of the input quantum state. Returns a scalar for single states, or a tensor for batched states.

Return type:

ndarray | Tensor

Note

This function supports batch operations. When input states have batch dimensions, the purity is computed element-wise along the batch dimension.

Examples

from quairkit.database import eye, bell_state
from quairkit.qinfo import purity

# Purity of maximally mixed state
max_mixed_purity = purity(eye(2) / 2)
print(f'Purity of 1-qubit maximally mixed state: {max_mixed_purity}')
Purity of 1-qubit maximally mixed state: 0.5
# Purity of pure state (Bell state)
bell_purity = purity(bell_state(2))
print(f'Purity of Bell state: {bell_purity}')
Purity of Bell state: 1.0
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 | StateSimulator | StateOperator

Density matrix form of the quantum state.

sigma : ndarray | Tensor | StateSimulator | StateOperator

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 | StateSimulator | StateOperator

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}})\]

For pure states, this simplifies to \(|\langle\psi|\phi\rangle|\).

Parameters:
rho : ndarray | Tensor | StateSimulator | StateOperator

First quantum state (can be a State, Tensor, or ndarray).

sigma : ndarray | Tensor | StateSimulator | StateOperator

Second quantum state (can be a State, Tensor, or ndarray).

Returns:

The fidelity between the input quantum states. Returns a scalar for single states, or a tensor for batched states.

Return type:

ndarray | Tensor

Note

The fidelity equation is based on Equation (9.53) in Quantum Computation & Quantum Information, 10th edition. This function supports batch operations. When input states have batch dimensions, the fidelity is computed element-wise along the batch dimension.

Examples

from quairkit.database import bell_state, zero_state, eye
from quairkit.qinfo import state_fidelity

# Single state fidelity
fidelity = state_fidelity(bell_state(2), eye(4)/4)
print(f'Fidelity between Bell state and maximal mixed state: {fidelity}')
Fidelity between Bell state and maximal mixed state: 0.5000725984573364
# Batch fidelity example
from quairkit.database import random_state

batch_rho = random_state(1, size=3)  # Batch of 3 states
batch_sigma = random_state(1, size=3)  # Batch of 3 states
batch_fid = state_fidelity(batch_rho, batch_sigma)
print(f'Batch fidelity shape: {batch_fid.shape}')
Batch fidelity shape: torch.Size([3])
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 | StateSimulator | StateOperator

First quantum state (can be a State, Tensor, or ndarray).

sigma : ndarray | Tensor | StateSimulator | StateOperator

Second quantum state (can be a State, Tensor, or ndarray).

Returns:

The trace distance between the input quantum states. Returns a scalar for single states, or a tensor for batched states.

Return type:

ndarray | Tensor

Note

This function supports batch operations. When input states have batch dimensions, the trace distance is computed element-wise along the batch dimension.

Examples

from quairkit.database import bell_state, eye
from quairkit.qinfo import trace_distance

# Single state trace distance
tr_dist = trace_distance(bell_state(2), eye(4)/4)
print(f'Trace distance between Bell state and maximal mixed state: {tr_dist}')
Trace distance between Bell state and maximal mixed state: 0.75
# Batch trace distance example
from quairkit.database import random_state

batch_rho = random_state(1, size=3)  # Batch of 3 states
batch_sigma = random_state(1, size=3)  # Batch of 3 states
batch_dist = trace_distance(batch_rho, batch_sigma)
print(f'Batch trace distance shape: {batch_dist.shape}')
Batch trace distance shape: torch.Size([3])
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))\]

The von Neumann entropy measures the amount of quantum information in a state. For a \(d\)-dimensional system, it ranges from 0 (pure state) to \(\log_d(\text{base})\) (maximally mixed).

Parameters:
rho : ndarray | Tensor | StateSimulator | StateOperator

Density matrix form of the quantum state (can be a State, Tensor, or ndarray).

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

The base of logarithm. Defaults to 2 (bits). Use \(e\) for nats.

Returns:

The von Neumann entropy of the input quantum state. Returns a scalar for single states, or a tensor for batched states.

Return type:

ndarray | Tensor

Note

This function supports batch operations. When input states have batch dimensions, the entropy is computed element-wise along the batch dimension.

Examples

from quairkit.database import completely_mixed_computational, bell_state
from quairkit.qinfo import von_neumann_entropy

# Entropy of maximally mixed state
ent = von_neumann_entropy(completely_mixed_computational(1))
print(f'Von Neumann entropy of 1-qubit maximally mixed state: {ent}')
Von Neumann entropy of 1-qubit maximally mixed state: 1.0
# Entropy of pure state (should be 0)
pure_ent = von_neumann_entropy(bell_state(2))
print(f'Von Neumann entropy of Bell state: {pure_ent}')
Von Neumann entropy of Bell state: 0.0