Quantum information tools¶
This tutorial introduces the qinfo
module in QuAIRKit. The functions in quairkit.qinfo
can be categorized into several application areas relevant to quantum computation and quantum information. For quantum computation, there are functions mainly to compute the Kronecker product, conjugate transpose, and trace of matrices. There are also functions associated with quantum gates, such as decomposing a single-qubit unitary operation into rotation angles around the Z and Y axes. For functions
related to quantum information theory, this module includes partial trace, quantum entropies, the fidelity of quantum states, various kinds of norms, and so on. Additionally, this module provides data format validation such as verifying whether a matrix is a unitary, density matrix, or a projector.
Table of Contents - Functions in quantum computation - Functions in quantum information - Validation functions - Compatibility with different data formats
[1]:
import quairkit as qkit
from quairkit import to_state
from quairkit.database import *
from quairkit.qinfo import *
qkit.set_dtype("complex128")
Functions in quantum computation¶
First, initialize two random unitary matrices through a built-in function of QuAIRKit. The matrix A and B are both in torch.tensor format.
[2]:
A = random_unitary(num_qubits=1)
B = random_unitary(num_qubits=1)
print(f"Matrix A is:\n{A}\n")
print(f"Matrix B is:\n{B}")
Matrix A is:
tensor([[-0.1954+0.2146j, 0.1822+0.9394j],
[-0.1701-0.9417j, 0.2599+0.1293j]])
Matrix B is:
tensor([[ 0.1297-0.5157j, -0.4703-0.7043j],
[ 0.4578+0.7125j, -0.5246-0.0871j]])
Users can use functions in qinfo
to implement specific operations on these two matrices. - Calculate the trace of a matrix by trace
. - Calculate the direct sum of matrix A and B with direct_sum
. Direct sum is an operation that combines two matrices into a larger matrix where A and B occupy diagonal blocks of the resulting matrix, and the remaining entries are zero. - Calculate the Kronecker products of at least two matrices by NKron
. - Implement conjugate transpose of a matrix by
dagger
. - Decompose a single-qubit unitary operator into Z-Y-Z rotation angles by decomp_1qubit
. - …
[3]:
print(f"The trace of matrix A is {trace(A)}")
print(f"The direct sum of matrix A and B is: \n{direct_sum(A,B)}\n")
print(f"The tensor product of matrix A and B is: \n{NKron(A,B)}\n")
print(f"The conjugate transpose of matrix A is: \n{dagger(A)}\n")
print(f"The decomposition of single-qubit unitary operator A to Z-Y-Z rotation angles is {decomp_1qubit(A)}")
The trace of matrix A is (0.06443467586598006+0.343978055135579j)
The direct sum of matrix A and B is:
tensor([[-0.1954+0.2146j, 0.1822+0.9394j, 0.0000+0.0000j, 0.0000+0.0000j],
[-0.1701-0.9417j, 0.2599+0.1293j, 0.0000+0.0000j, 0.0000+0.0000j],
[ 0.0000+0.0000j, 0.0000+0.0000j, 0.1297-0.5157j, -0.4703-0.7043j],
[ 0.0000+0.0000j, 0.0000+0.0000j, 0.4578+0.7125j, -0.5246-0.0871j]])
The tensor product of matrix A and B is:
tensor([[ 0.0853+0.1286j, 0.2431+0.0367j, 0.5081+0.0279j, 0.5760-0.5702j],
[-0.2424-0.0410j, 0.1212-0.0956j, -0.5859+0.5599j, -0.0138-0.5087j],
[-0.5077-0.0344j, -0.5832+0.5627j, 0.1004-0.1172j, -0.0311-0.2439j],
[ 0.5930-0.5524j, 0.0073+0.5088j, 0.0268+0.2444j, -0.1251-0.0905j]])
The conjugate transpose of matrix A is:
tensor([[-0.1954-0.2146j, -0.1701+0.9417j],
[ 0.1822-0.9394j, 0.2599-0.1293j]])
The decomposition of single-qubit unitary operator A to Z-Y-Z rotation angles is (tensor(-4.0590), tensor(2.5525), tensor(2.2114))
Functions in quantum information¶
Users can use functions in qinfo
to quantify information-theoretic properties of quantum states. - Calculate the von-Neumann entropy of a quantum state by von_neumann_entropy
. - Calculate the trace distance of two quantum states by trace_distance
. - Calculate the fidelity of two quantum states by state_fidelity
. - Calculate the purity of a quantum state by purity
. - Calculate the relative entropy of two quantum states by relative_entropy
. - Calculate of Schatten p-norm by
p_norm
. - …
[4]:
state1 = random_state(2).density_matrix
print(f"The first quantum state is:\n {state1}\n")
state2 = random_state(2, rank=1).ket
print(f"The second quantum state is:\n {state2}")
The first quantum state is:
tensor([[ 0.7755+0.0000j, 0.0727-0.0237j, -0.1560-0.2811j, -0.2145-0.1373j],
[ 0.0727+0.0237j, 0.0075+0.0000j, -0.0060-0.0311j, -0.0159-0.0194j],
[-0.1560+0.2811j, -0.0060+0.0311j, 0.1333+0.0000j, 0.0929-0.0501j],
[-0.2145+0.1373j, -0.0159+0.0194j, 0.0929+0.0501j, 0.0836+0.0000j]])
The second quantum state is:
tensor([[0.3182-0.1243j],
[0.0199-0.5031j],
[0.1631-0.3059j],
[0.3035-0.6461j]])
[5]:
entropy = von_neumann_entropy(state1)
print(f"The von Neumann entropy between state 1 is:\n{entropy}")
traceDistance = trace_distance(state1, state2)
print(traceDistance.dtype)
print(f"The trace distance between state 1 and state 2 is:\n{traceDistance}")
fidelity = state_fidelity(state1, state2)
print(f"The state fidelity between state 1 and state 2 is:\n{fidelity}")
purity_state = purity(state1)
print(f"The purity of state 1 is:\n{purity_state}")
r_entropy = relative_entropy(state1, state2)
print(f"The relative entropy of state 1 and state 2 is:\n{r_entropy}")
p = 2
pnorm = p_norm(state1, p)
print(f"The Schatten {p}-norm of state 1 is:\n{pnorm}")
The von Neumann entropy between state 1 is:
1.3013920171748103e-15
torch.float64
The trace distance between state 1 and state 2 is:
0.9986828156358498
The state fidelity between state 1 and state 2 is:
0.05130919865131176
The purity of state 1 is:
0.9999999999999994
The relative entropy of state 1 and state 2 is:
55.26619734246961
The Schatten 2-norm of state 1 is:
0.9999999999999998
Validation functions¶
Users can use validation functions in qinfo
to check if the matrix satisfies certain conditions. - Check if the input matrix is a positive semi-definite matrix by is_positive
. - Check if the input quantum state is PPT by is_ppt
. - Check if the input matrix is unitary by is_unitary
.
[6]:
is_positive(A)
print(f"The matrix is a positive matrix: {is_positive(A)}")
is_unitary(A)
print(f"The matrix is a unitary matrix: {is_unitary(A)}")
is_ppt(state1)
print(f"The state 1 is a PPT state: {is_ppt(state1)}")
The matrix is a positive matrix: False
The matrix is a unitary matrix: True
The state 1 is a PPT state: False
Compatibility with different data formats¶
Functions in qinfo
support different formats of input, including torch.Tensor, numpy.ndarray, and State. The input data format is transformed through _type_transform
. At the same time, the output format is consistent with the input format in the most situations. For example, the output will be numpy.ndarray format if the input is also numpy.ndarray format.
[7]:
# Input with torch.tensor format
print(f"State fidelity dtype (torch.tensor): {type(state_fidelity(state1, state2))}")
# Input with numpy.ndarray format
state1_num = state1.numpy()
state2_num = state2.numpy()
print(f"State fidelity dtype (numpy.ndarray): {type(state_fidelity(state1_num, state2_num))}")
# Input with State format
state1_sta = to_state(state1)
state2_sta = to_state(state2)
print(f"State fidelity dtype (State): {type(state_fidelity(state1_sta, state2_sta))}")
State fidelity dtype (torch.tensor): <class 'torch.Tensor'>
State fidelity dtype (numpy.ndarray): <class 'numpy.ndarray'>
State fidelity dtype (State): <class 'torch.Tensor'>
[8]:
qkit.print_info()
---------VERSION---------
quairkit: 0.2.0
torch: 2.4.1+cpu
numpy: 1.26.0
scipy: 1.14.1
matplotlib: 3.9.2
---------SYSTEM---------
Python version: 3.10.15
OS: Windows
OS version: 10.0.26100
---------DEVICE---------
CPU: ARMv8 (64-bit) Family 8 Model 1 Revision 201, Qualcomm Technologies Inc