quairkit.qinfo¶
The library of functions in quantum information theory and quantum computing.
- quairkit.qinfo.is_choi(op)¶
- Check if the input op is a Choi operator of a physical operation.
Support batch input.
- Parameters:¶
- op : ndarray | Tensor¶
matrix form of the linear operation.
- Returns:¶
Whether the input op is a valid quantum operation Choi operator. For batch input, return a boolean array with the same batch dimensions as input.
- Return type:¶
bool | List[bool]
Note
The operation op is (default) applied to the second system.
ischoi = is_choi(eye(4) / 4) print(f'The operation is choi or not:\n{ischoi}')
The operation is choi or not: True
-
quairkit.qinfo.is_density_matrix(rho, eps=
1e-06
)¶ - Verify whether
rho
is a legal quantum density matrix Support batch input
- Parameters:¶
- Returns:¶
determine whether
rho
is a PSD matrix with trace 1- Return type:¶
bool | List[bool]
is_dens_mat = is_density_matrix(eye(4) / 4) print(f'The operation is density matrix or not:\n{is_dens_mat}')
The operation is density matrix or not: True
- Verify whether
-
quairkit.qinfo.is_hermitian(mat, eps=
1e-06
)¶ - Verify whether
mat
is Hermitian. Support batch input.
- Parameters:¶
- Returns:¶
determine whether \(P - P^\dagger = 0\) For batch input, return a boolean array with the same batch dimensions as input.
- Return type:¶
bool | List[bool]
is_hermit = is_hermitian(x()) print(f'The operation is hermitian or not:\n{is_hermit}')
The operation is hermitian or not: True
- Verify whether
-
quairkit.qinfo.is_linear(func, info, input_dtype=
None
, eps=1e-05
)¶ Check if the provided function ‘func’ is linear.
- Parameters:¶
- func : Callable[[Tensor | ndarray], Tensor | ndarray]¶
A callable function to be tested. This function should accept and return either a torch.Tensor or a numpy.ndarray.
- info : List[int] | Callable[[], ndarray] | Callable[[], Tensor]¶
A parameter specifying the shape of the input for ‘func’. It can be a list of two integers (defining the shape of a tensor), a callable that returns a numpy.ndarray, or a callable that returns a torch.Tensor.
- eps : float | None¶
An optional tolerance value used to determine if the function’s behavior is close enough to linear. Default value is 1e-6.
- Returns:¶
True if ‘func’ behaves as a linear function within the specified tolerance ‘eps’; False otherwise.
- Return type:¶
bool
- Raises:¶
TypeError – If ‘func’ is not callable, does not accept a torch.Tensor or numpy.ndarray as input, or does not return a torch.Tensor or numpy.ndarray. If ‘info’ is not a valid type (not a list of integers or a callable returning a torch.Tensor or numpy.ndarray).
def f(X): return torch.trace(X) is_lin = is_linear(f, info=[2, 2]) print(f'The function f is linear or not:\n{is_lin}')
The function f is linear or not: True
-
quairkit.qinfo.is_positive(mat, eps=
1e-06
)¶ - Verify whether
mat
is a positive semi-definite matrix. Support batch input.
- Parameters:¶
- Returns:¶
determine whether \(P\) is Hermitian and eigenvalues are non-negative For batch input, return a boolean array with the same batch dimensions as input.
- Return type:¶
bool | List[bool]
is_pos = is_positive(x()) print(f'The operator is positive or not:\n{is_pos}')
The operator is positive or not: False
- Verify whether
-
quairkit.qinfo.is_povm(set_op, eps=
1e-06
)¶ Check if a set of operators forms a positive operator-valued measure (POVM).
is_pov = is_povm(x()) print(f'The operator is POVM or not:\n{is_pov}')
The operator is POVM or not: False
-
quairkit.qinfo.is_projector(mat, eps=
1e-06
)¶ - Verify whether
mat
is a projector. Support batch input.
- Parameters:¶
- Returns:¶
determine whether \(PP - P = 0\) For batch input, return a boolean array with the same batch dimensions as input.
- Return type:¶
bool | List[bool]
is_proj = is_projector(x()) print(f'The operator is projector or not:\n{is_proj}')
The operator is projector or not: False
- Verify whether
- quairkit.qinfo.is_ppt(density_op)¶
- Check if the input quantum state is PPT.
Support batch input.
- Parameters:¶
- density_op : ndarray | Tensor | PureState | MixedState¶
Density matrix form of the quantum state.
- Returns:¶
Whether the input quantum state is PPT. For batch input, return a boolean array with the same batch dimensions as input.
- Return type:¶
bool | List[bool]
is_pt = is_ppt(bell_state(2)) print(f'The input quantum state is PPT or not:\n{is_pt}')
The input quantum state is PPT or not: False
-
quairkit.qinfo.is_pvm(set_op, eps=
1e-06
)¶ Check if a set of operators forms a projection-valued measure (PVM).
- Parameters:¶
- Returns:¶
True if the operators form a PVM; otherwise, False.
- Return type:¶
bool or List[bool]
is_pv = is_pvm(eye(4).reshape(1, 4, 4)) print(f'The operator is PVM or not:\n{is_pv}')
The operator is PVM or not: False
-
quairkit.qinfo.is_state_vector(vec, eps=
1e-06
)¶ - Verify whether
vec
is a legal quantum state vector. Support batch input.
st = torch.rand(5) is_st_vec = is_state_vector(st / st.norm()) print(f'The vector is state vector or not:\n{is_st_vec}')
The vector is state vector or not: True
- Verify whether
-
quairkit.qinfo.is_unitary(mat, eps=
0.0001
)¶ - Verify whether
mat
is a unitary. Support batch input.
- Parameters:¶
- Returns:¶
determine whether \(PP^\dagger - I = 0\) For batch input, return a boolean array with the same batch dimensions as input.
- Return type:¶
bool | List[bool]
is_unit = is_unitary(random_unitary(1)) print(f'The operator is unitary or not:\n{is_unit}')
The operator is unitary or not: True
- Verify whether
- quairkit.qinfo.abs_norm(mat)¶
Tool for calculation of matrix norm.
- Parameters:¶
- mat : ndarray | Tensor | PureState | MixedState¶
matrix
- Returns:¶
norm of input matrix
- Return type:¶
float
Examples
abs_nor = abs_norm(eye(2) / 2) print(f'The abs norm is:\n{abs_nor}')
The abs norm is: 0.7071067690849304
-
quairkit.qinfo.block_enc_herm(mat, num_block_qubits=
1
)¶ Generate a (qubitized) block encoding of Hermitian
mat
.Examples
block_enc = block_enc_herm(x()) print(f'The block encoding of X is:\n{block_enc}')
The block encoding of X is: tensor([[0.+0.j, 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, 1.+0.j], [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j]])
-
quairkit.qinfo.create_matrix(linear_map, input_dim, input_dtype=
None
)¶ Create a matrix representation of a linear map without needing to specify the output dimension.
This function constructs a matrix representation for a given linear map and input dimension.
- Parameters:¶
- Returns:¶
A matrix representing the linear map.
- Raises:¶
RuntimeWarning – the input linear_map may not be linear.
- Return type:¶
ndarray | Tensor
Examples
def f(X): return X[0] + X[1] mat_repr = create_matrix(f, input_dim=2) print(f'The matrix representation is:\n{mat_repr}')
The matrix representation is: tensor([1.+0.j, 1.+0.j])
- quairkit.qinfo.dagger(mat)¶
Tool for calculation of matrix dagger.
- Parameters:¶
- mat : ndarray | Tensor¶
matrix
- Returns:¶
The dagger of matrix
- Return type:¶
ndarray | Tensor
Examples
dag = dagger(t()) print(f'The dagger of this matrix is:\n{dag}')
The dagger of this matrix is: tensor([[1.0000-0.0000j, 0.0000-0.0000j], [0.0000-0.0000j, 0.7071-0.7071j]])
- quairkit.qinfo.direct_sum(A, B)¶
Calculate the direct sum of A and B.
- Parameters:¶
- Returns:¶
A direct sum of A and B, with shape \((m + p) \times (n + q)\)
- Return type:¶
ndarray | Tensor
Examples
dir_sum = direct_sum(x(), y()) print(f'The direct sum is:\n{dir_sum}')
The direct sum is: tensor([[0.+0.j, 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.-1.j], [0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j]])
- quairkit.qinfo.gradient(loss_function, var, n)¶
Compute the gradient of a given loss function with respect to its input variable.
Examples
def quadratic_loss(x: torch.Tensor) -> torch.Tensor: # loss function is: L(x) = x₁² + 2x₂² + 3x₃² return x[0]**2 + 2 * x[1]**2 + 3 * x[2]**3 var = torch.tensor([[1.0], [2.0], [3.0]], requires_grad=True) grad = gradient(quadratic_loss, var, n=1) print(f"Input variable is:\n{var}") print(f"Computed gradient is:\n{grad}")
Input variable is: tensor([[1.], [2.], [3.]], requires_grad=True) Computed gradient is: tensor([[ 2.], [ 8.], [81.]], grad_fn=<CopySlices>)
- quairkit.qinfo.hessian(loss_function, var)¶
Compute the Hessian matrix of a given loss function with respect to its input variables.
Examples
def quadratic_loss(x: torch.Tensor) -> torch.Tensor: # loss function is: L(x) = x₁² + 2x₂² + 3x₃² return x[0]**2 + 2 * x[1]**2 + 3 * x[2]**3 var = torch.tensor([[1.0], [2.0], [3.0]], requires_grad=True) hes = hessian(quadratic_loss, var) print(f"Input variable is:\n{var}") print(f"Computed Hessian is:\n{hes}")
Input variable is: tensor([[1.], [2.], [3.]], requires_grad=True) Computed Hessian is: tensor([[[ 2., 0., 0.], [ 0., 4., 0.], [ 0., 0., 54.]]])
-
quairkit.qinfo.herm_transform(fcn, mat, ignore_zero=
False
)¶ Function transformation for a Hermitian matrix.
- Parameters:¶
- fcn : Callable[[float], float]¶
A function \(f\) that can be expanded by Taylor series.
- mat : ndarray | Tensor | PureState | MixedState¶
Hermitian matrix \(H\).
- ignore_zero : bool | None¶
Whether to ignore eigenspaces with zero eigenvalue. Defaults to False.
- Returns:¶
\(f(H)\)
- Return type:¶
ndarray | Tensor
Examples
fH = herm_transform(math.exp, eye(2)) print(f'The result is:\n{fH}')
The result is: tensor([[2.7183+0.j, 0.0000+0.j], [0.0000+0.j, 2.7183+0.j]])
- quairkit.qinfo.kron_power(matrix, n)¶
Calculate the Kronecker product of identical matrices.
- Parameters:¶
- matrix : ndarray | Tensor | PureState | MixedState¶
The matrix to be powered.
- n : int¶
The number of identical matrices.
- Returns:¶
Kronecker product of n identical matrices.
- Return type:¶
ndarray | Tensor
Examples
kp = kron_power(x(), 2) print(f'The Kronecker product of 2 X is:\n{kp}')
The Kronecker product of 2 X is: tensor([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j], [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j], [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j], [1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]])
- quairkit.qinfo.logm(mat)¶
Calculate the logarithm of a matrix.
- Parameters:¶
- mat : ndarray | Tensor | PureState | MixedState¶
Input matrix.
- Returns:¶
The matrix of natural base logarithms.
- Return type:¶
ndarray | Tensor
Examples
lgm = logm(x()) print(f'The log of X is:\n{lgm}')
The log of X is: tensor([[-1.8562e-16+1.5708j, 1.8562e-16-1.5708j], [ 1.8562e-16-1.5708j, -1.8562e-16+1.5708j]])
- quairkit.qinfo.nkron(matrix_1st, *args)¶
Calculate the Kronecker product of matrices.
- Parameters:¶
- matrix_1st : ndarray | Tensor | PureState | MixedState¶
The first matrix.
- args : ndarray | Tensor | PureState | MixedState¶
Other matrices.
- Returns:¶
Kronecker product of the given matrices.
- Return type:¶
ndarray | Tensor | PureState | MixedState
Examples
A = random_state(1) B = random_state(1) C = random_state(1) result = nkron(A, B, C) print(f'The result is:\n{result}')
The result is: ----------------------------------------------------- Backend: density_matrix System dimension: [2, 2, 2] System sequence: [0, 1, 2] [[ 0.02+0.j 0.01-0.01j -0.01+0.j -0.-0.01j 0.04+0.04j 0.05-0.01j -0.04-0.03j -0.04+0.02j] [ 0.01+0.01j 0.01-0.j -0.01-0.01j -0.01+0.j -0.01+0.05j 0.04+0.03j -0.-0.04j -0.03-0.02j] [-0.01-0.j -0.01+0.01j 0.02+0.j 0.01-0.02j -0.03-0.04j -0.04+0.j 0.06+0.06j 0.07-0.02j] [-0.-0.01j -0.01-0.j 0.01+0.02j 0.02-0.j 0.02-0.04j -0.02-0.03j -0.01+0.08j 0.05+0.05j] [ 0.04-0.04j -0.01-0.05j -0.03+0.04j 0.02+0.04j 0.21-0.j 0.1-0.16j -0.16+0.03j -0.06+0.14j] [ 0.05+0.01j 0.04-0.03j -0.04-0.j -0.02+0.03j 0.1+0.16j 0.18-0.j -0.11-0.11j -0.14+0.03j] [-0.04+0.03j -0.-0.04j 0.06-0.06j -0.01-0.08j -0.16-0.03j -0.11+0.11j 0.29-0.j 0.15-0.23j] [-0.04-0.02j -0.03+0.02j 0.07+0.02j 0.05-0.05j -0.06-0.14j -0.14-0.03j 0.15+0.23j 0.25-0.j ]] -----------------------------------------------------
- quairkit.qinfo.NKron(matrix_1st, *args)¶
Calculate the Kronecker product of matrices.
- Parameters:¶
- matrix_1st : ndarray | Tensor | PureState | MixedState¶
The first matrix.
- args : ndarray | Tensor | PureState | MixedState¶
Other matrices.
- Returns:¶
Kronecker product of the given matrices.
- Return type:¶
ndarray | Tensor | PureState | MixedState
Examples
A = random_state(1) B = random_state(1) C = random_state(1) result = nkron(A, B, C) print(f'The result is:\n{result}')
The result is: ----------------------------------------------------- Backend: density_matrix System dimension: [2, 2, 2] System sequence: [0, 1, 2] [[ 0.02+0.j 0.01-0.01j -0.01+0.j -0.-0.01j 0.04+0.04j 0.05-0.01j -0.04-0.03j -0.04+0.02j] [ 0.01+0.01j 0.01-0.j -0.01-0.01j -0.01+0.j -0.01+0.05j 0.04+0.03j -0.-0.04j -0.03-0.02j] [-0.01-0.j -0.01+0.01j 0.02+0.j 0.01-0.02j -0.03-0.04j -0.04+0.j 0.06+0.06j 0.07-0.02j] [-0.-0.01j -0.01-0.j 0.01+0.02j 0.02-0.j 0.02-0.04j -0.02-0.03j -0.01+0.08j 0.05+0.05j] [ 0.04-0.04j -0.01-0.05j -0.03+0.04j 0.02+0.04j 0.21-0.j 0.1-0.16j -0.16+0.03j -0.06+0.14j] [ 0.05+0.01j 0.04-0.03j -0.04-0.j -0.02+0.03j 0.1+0.16j 0.18-0.j -0.11-0.11j -0.14+0.03j] [-0.04+0.03j -0.-0.04j 0.06-0.06j -0.01-0.08j -0.16-0.03j -0.11+0.11j 0.29-0.j 0.15-0.23j] [-0.04-0.02j -0.03+0.02j 0.07+0.02j 0.05-0.05j -0.06-0.14j -0.14-0.03j 0.15+0.23j 0.25-0.j ]] -----------------------------------------------------
- quairkit.qinfo.p_norm(mat, p)¶
Calculate the Schatten p-norm of a matrix.
- Parameters:¶
- mat : ndarray | Tensor | PureState | MixedState¶
matrix
- p : ndarray | Tensor | Iterable[float] | float¶
p-norm parameter
- Returns:¶
p-norm of input matrix
- Return type:¶
ndarray | Tensor
Examples
p_nor = p_norm(x(), p=2) print(f'The 2-norm of X is:\n{p_nor}')
The 2-norm of X is: 1.4142135381698608
-
quairkit.qinfo.partial_trace(state, trace_idx, system_dim=
2
)¶ Calculate the partial trace of the quantum state.
- Parameters:¶
- state : ndarray | Tensor | PureState | MixedState¶
Input quantum state.
- trace_idx : List[int] | int¶
The system indices to be traced out.
- system_dim : List[int] | int¶
The dimension of all systems. Defaults to the qubit case.
- Returns:¶
Partial trace of the quantum state with arbitrarily selected subsystem.
- Return type:¶
ndarray | Tensor | PureState | MixedState
Examples
pt = partial_trace(bell_state(2), 0, [2, 2]) print(f'The partial trace of Bell state is:\n{pt}')
The partial trace of Bell state is: ----------------------------------------------------- Backend: density_matrix System dimension: [2] System sequence: [0] [[0.5+0.j 0. +0.j] [0. +0.j 0.5+0.j]] -----------------------------------------------------
-
quairkit.qinfo.partial_trace_discontiguous(state, preserve_qubits=
None
)¶ Calculate the partial trace of the quantum state with arbitrarily selected subsystem.
- Parameters:¶
- state : ndarray | Tensor | PureState | MixedState¶
Input quantum state.
- preserve_qubits : List[int]¶
Remaining qubits; if None, all qubits are preserved.
- Returns:¶
Partial trace of the quantum state with arbitrarily selected subsystem.
- Return type:¶
ndarray | Tensor | PureState | MixedState
Examples
ptdis = partial_trace_discontiguous(bell_state(2), [0]) print(f'The partial trace of Bell state is:\n{ptdis}')
The partial trace of Bell state is: ----------------------------------------------------- Backend: density_matrix System dimension: [2] System sequence: [0] [[0.5+0.j 0. +0.j] [0. +0.j 0.5+0.j]] -----------------------------------------------------
-
quairkit.qinfo.partial_transpose(state, transpose_idx, system_dim=
2
)¶ Calculate the partial transpose \(\rho^{T_A}\) of the input quantum state.
- Parameters:¶
- state : ndarray | Tensor | PureState | MixedState¶
Input quantum state.
- transpose_idx : List[int] | int¶
The system indices to be transposed.
- system_dim : List[int] | int¶
The dimension of all systems. Defaults to the qubit case.
- Returns:¶
The partial transpose of the input quantum state.
- Return type:¶
ndarray | Tensor
Examples
pt = partial_transpose(bell_state(2), [0]) print(f'The partial transpose of Bell state is:\n{pt}')
The partial transpose of Bell state is: ----------------------------------------------------- Backend: density_matrix System dimension: [2, 2] System sequence: [0, 1] [[0.5+0.j 0. +0.j 0. +0.j 0. +0.j] [0. +0.j 0. +0.j 0.5+0.j 0. +0.j] [0. +0.j 0.5+0.j 0. +0.j 0. +0.j] [0. +0.j 0. +0.j 0. +0.j 0.5+0.j]] -----------------------------------------------------
- quairkit.qinfo.pauli_decomposition(mat)¶
Decompose the matrix by the Pauli basis.
- Parameters:¶
- mat : ndarray | Tensor¶
The matrix to be decomposed.
- Returns:¶
A list of coefficients corresponding to the Pauli basis.
- Return type:¶
ndarray | Tensor
Examples
pauli_dec = pauli_decomposition(random_state(1).density_matrix) print(f'The decomposition is:\n{pauli_dec}')
The decomposition is: tensor([ 0.7071+0.j, 0.5076+0.j, 0.4494+0.j, -0.0572+0.j])
-
quairkit.qinfo.permute_systems(state, perm_list, system_dim=
2
)¶ Permute quantum systems based on a permutation list.
- Parameters:¶
- state : ndarray | Tensor | PureState | MixedState¶
A matrix representation of a quantum state.
- perm_list : List[int]¶
The permutation list. For example, [0, 2, 1, 3] will swap the 2nd and 3rd subsystems.
- system_dim : List[int] | int¶
A list of dimension sizes of each subsystem.
- Returns:¶
The permuted matrix.
- Return type:¶
ndarray | Tensor | PureState | MixedState
Examples
result = permute_systems(random_state(3), [2, 1, 0]) print(f'The permuted matrix is:\n{result}')
The permuted matrix is: ----------------------------------------------------- Backend: density_matrix System dimension: [2, 2, 2] System sequence: [0, 1, 2] [[ 0.06+0.j -0.02+0.j -0.02-0.07j -0.03-0.j 0.06+0.01j -0.02+0.03j -0.01-0.06j 0.01+0.01j] [-0.02-0.j 0.13+0.j -0.05+0.01j -0.02-0.01j 0.06-0.06j -0.01-0.03j -0.+0.08j 0.03-0.03j] [-0.02+0.07j -0.05-0.01j 0.24+0.j 0.06+0.03j -0.09+0.05j 0.01-0.05j 0.04-0.05j -0.13+0.04j] [-0.03+0.j -0.02+0.01j 0.06-0.03j 0.1+0.j -0.07+0.02j 0.02-0.05j -0.01+0.01j -0.03+0.j ]] -----------------------------------------------------
-
quairkit.qinfo.prob_sample(distribution, shots=
1024
, binary=True
, proportional=False
)¶ Sample from a probability distribution.
- Parameters:¶
- Returns:¶
A dictionary containing the ordered sampled results and their counts.
- Return type:¶
Dict[str, int | float]
Examples
dist = torch.abs(haar_state_vector(3)) result = prob_sample(dist / torch.sum(dist)) print(f'The sample result is:\n{result}')
The sample result is: {'0': tensor([1024, 1024, 1024])}
-
quairkit.qinfo.schmidt_decompose(psi, sys_A=
None
)¶ Calculate the Schmidt decomposition of a quantum state.
For a state \(\lvert\psi\rangle=\sum_i c_i \lvert i_A\rangle\otimes\lvert i_B \rangle\).
- Parameters:¶
- psi : ndarray | Tensor | PureState | MixedState¶
State vector form of the quantum state, with shape \((2**n)\).
- sys_A : List[int]¶
Qubit indices to be included in subsystem A. By default, the first half of the qubits belong to subsystem A.
- Returns:¶
A one-dimensional array of Schmidt coefficients with shape (k).
A high-dimensional array of bases for subsystem A with shape (k, 2**m, 1).
A high-dimensional array of bases for subsystem B with shape (k, 2**m, 1).
- Return type:¶
A tuple containing
Examples
# Example usage (assuming a proper state vector 'psi'): c, u, v = schmidt_decompose(psi) print("Schmidt coefficients:", c) print("Subsystem A bases:", u) print("Subsystem B bases:", v)
Schmidt coefficients: tensor([...]) Subsystem A bases: tensor([...]) Subsystem B bases: tensor([...])
- quairkit.qinfo.sqrtm(mat)¶
Calculate the square root of a matrix.
- Parameters:¶
- mat : ndarray | Tensor | PureState | MixedState¶
Input matrix.
- Returns:¶
The square root of the matrix.
- Return type:¶
ndarray | Tensor
Examples
sqrt = sqrtm(x()) print(f'The square root of X is:\n{sqrt}')
The square root of X is: tensor([[0.5000+0.5000j, 0.5000-0.5000j], [0.5000-0.5000j, 0.5000+0.5000j]])
-
quairkit.qinfo.trace(mat, axis1=
-2
, axis2=-1
)¶ Return the sum along the diagonals of the tensor.
If \(mat\) is a 2-D tensor, the sum along its diagonal is returned. For tensors with more than two dimensions, the axes specified by
axis1
andaxis2
determine the 2-D sub-tensors whose traces will be taken.- Parameters:¶
- mat : ndarray | Tensor | PureState | MixedState¶
Input tensor from which the diagonal is taken.
- axis1 : int¶
The first axis for the 2-D sub-tensor. Defaults to -2.
- axis2 : int¶
The second axis for the 2-D sub-tensor. Defaults to -1.
- Returns:¶
The trace (sum along the diagonal) of the tensor.
- Return type:¶
ndarray | Tensor
Examples
tr = trace(x()) print(f'The trace of X is:\n{tr}')
The trace of X is: 0j
- quairkit.qinfo.trace_norm(mat)¶
Calculate the trace norm of a matrix.
- Parameters:¶
- mat : ndarray | Tensor | PureState | MixedState¶
matrix
- Returns:¶
Trace norm of the input matrix
- Return type:¶
ndarray | Tensor
Examples
tr_norm = trace_norm(x()) print(f'The trace norm of X is:\n{tr_norm}')
The trace norm of X is: 2.0
-
quairkit.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.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.
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.decomp_1qubit(unitary, return_global=
False
)¶ Decompose a single-qubit unitary operator into Z-Y-Z rotation angles.
- Parameters:¶
- 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.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.diamond_norm(channel_repr, dim_io=
None
, **kwargs)¶ Calculate the diamond norm of input.
- Parameters:¶
- Raises:¶
RuntimeError – channel_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.
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.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.
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.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
- quairkit.qinfo.link(JE, JF)¶
Calculate the link product of two Choi matrices of quantum channels.
- Parameters:¶
- 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.
- Returns:¶
The resulting Choi matrix after the link product, its label, and input/output dimensions.
- Return type:¶
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.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.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.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.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.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.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.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.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.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.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.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.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