QTensor
The qtensor module defines the QTensor
class and related helpers for representing and manipulating quantum states and
operators in sparse form.
The QTensor wraps a dense NumPy array or SciPy sparse matrix into a CSR-format sparse matrix, and can represent:
Kets (column vectors of shape
(2**N, 1))Bras (row vectors of shape
(1, 2**N))Operators / Density Matrices (square matrices of shape
(2**N, 2**N))Scalars (
(1, 1)matrices)
Examples of creating various quantum objects:
import numpy as np
from qilisdk.core.qtensor import QTensor
# 1‑qubit |0> ket
psi_ket = QTensor(np.array([[1], [0]]))
print("Ket:", psi_ket.dense(), "is_ket?", psi_ket.is_ket())
print("-" * 20)
# 1‑qubit <0| bra
psi_bra = QTensor(np.array([[1, 0]]))
print("Bra:", psi_bra.dense(), "is_bra?", psi_bra.is_bra())
print("-" * 20)
# Density matrix |0><0|
rho = QTensor(np.array([[1, 0], [0, 0]]))
print("Density matrix:\n", rho.dense(), "is_density_matrix?", rho.is_density_matrix())
print("-" * 20)
# Scalar 0.5
scalar = QTensor(np.array([[0.5]]))
print("Scalar:", scalar.dense(), "is_scalar?", scalar.is_scalar())
Output
Ket: [[1]
[0]] is_ket? True
--------------------
Bra: [[1 0]] is_bra? True
--------------------
Density matrix:
[[1 0]
[0 0]] is_density_matrix? True
--------------------
Scalar: [[0.5]] is_scalar? True
Helper constructors
There are also several constructors for common quantum objects:
ket()for computational basis kets
bra()for computational basis bras
basis_state()for N-dimensional basis states with a single 1 at the specified index
identity()for identity operators of specified dimension
zero()for generating statevectors in the all-zero state.
one()for generating statevectors in the all-one state.
ghz()for generating GHZ states of specified number of qubits
uniform()for generating uniform superposition states of specified number of qubits
from qilisdk.core.qtensor import QTensor
# Single‑qubit
print("ket(0):\n", QTensor.ket(0), "\nis_ket?", QTensor.ket(0).is_ket())
print("bra(1):\n", QTensor.bra(1), "\nis_bra?", QTensor.bra(1).is_bra())
# Fock basis in N=4 Hilbert space
print("basis_state(2,4):\n", QTensor.basis_state(2, 4), "\nshape:", QTensor.basis_state(2, 4).shape)
# GHZ state for 2 qubits
print("GHZ state for 2 qubits:\n", QTensor.ghz(2))
# Identity operators
print("Identity (4x4):\n", QTensor.identity(2))
Output
ket(0):
[[1.]
[0.]]
is_ket? True
bra(1):
[[0. 1.]]
is_bra? True
basis_state(2,4):
[[0.]
[0.]
[1.]
[0.]]
shape: (4, 1)
Quantum Object Properties & Operations
All data are stored sparsely, but you can retrieve dense or sparse views:
.data: get the underlying sparse matrix (SciPy CSR format).dense(): convert to a dense NumPy array (use with caution for large tensors)or directly accessing elements by value with
qtensor[i, j]
Common matrix operations are also available:
.adjoint(): conjugate transpose.conjugate(): element-wise complex conjugate.transpose(): matrix transpose.exp(): matrix exponential.log(): matrix logarithm.sqrt(): matrix square root.rank(): compute the rank of the operator.pow(exponent): matrix power.norm(order="l2"): vector or matrix norm.normalized(order='l2'): normalize to unit norm.eig(): get the eigenvalues and eigenvectors.trace(): compute the trace of an operator.dot(other): Frobenius inner product with another QTensor
As well as some quantum-specific transformations:
.entropy_von_neumann(): compute the von Neumann entropy of a density matrix.entropy_renyi(alpha): compute the Rényi entropy of a density matrix for a given order alpha.commutator(other): compute the commutator with another operator.anticommutator(other): compute the anticommutator with another operator.fidelity(other): compute the fidelity between two quantum states.probabilities(): compute the probability distribution of each state in the computational basis.partial_trace(keep): partial trace.reset_qubits(qubits): reset specified qubits to 0.dagger(): alias for adjoint
Examples:
import numpy as np
from qilisdk.core.qtensor import QTensor
# Adjoint of a non-Hermitian operator
A = QTensor(np.array([[1+1j, 2], [3, 4]]))
A_dag = A.adjoint()
print("A:\n", A.dense())
print("A†:\n", A_dag.dense())
# Matrix exponential of Pauli-X
X = QTensor(np.array([[0, 1], [1, 0]]))
expX = X.exp()
print("exp(X):\n", np.round(expX.dense(), 3))
# Norm of a ket and a density matrix
ket0 = QTensor(np.array([[1], [0]]))
dm = ket0.to_density_matrix()
print("||ket0|| =", ket0.norm())
print("trace norm(dm) =", dm.norm(order='l2'))
# Partial trace of a Bell state
from qilisdk.core.qtensor import ket, tensor_prod
bell = (tensor_prod([ket(0), ket(0)]) + tensor_prod([ket(1), ket(1)])).unit()
rho_bell = bell.to_density_matrix()
print("rho_bell:\n", rho_bell)
rhoA = rho_bell.ptrace([0])
print("rho_A:\n", rhoA.dense())
Output
A:
[[1.+1.j 2.+0.j]
[3.+0.j 4.+0.j]]
A†:
[[1.-1.j 3.+0.j]
[2.+0.j 4.+0.j]]
exp(X):
[[1.543 1.175]
[1.175 1.543]]
||ket0|| = 1.0
trace norm(dm) = 1.0
rho_bell:
QTensor(shape=4x4, nnz=4, format='csr')
[[0.5 0. 0. 0.5]
[0. 0. 0. 0. ]
[0. 0. 0. 0. ]
[0.5 0. 0. 0.5]]
rho_A:
[[0.5 0. ]
[0. 0.5]]
Extra Utilities
Tensor product with
tensor_prod()Expectation value with
expect_val()
from qilisdk.core.qtensor import QTensor, expect_val, ket, tensor_prod
import numpy as np
# Two‑qubit Hadamard tensor
H = QTensor(np.array([[1, 1], [1, -1]]) / np.sqrt(2))
H2 = tensor_prod([H, H])
print("H ⊗ H:\n", np.round(H2.dense(), 3))
# Expectation of Z⊗Z on |00>
Z = QTensor(np.array([[1, 0], [0, -1]]))
zz = tensor_prod([Z, Z])
psi00 = tensor_prod([ket(0), ket(0)])
rho00 = psi00.to_density_matrix()
ev = expect_val(zz, rho00)
print("⟨ZZ⟩ on |00> =", ev)
Output
H ⊗ H:
[[ 0.5 0.5 0.5 0.5]
[ 0.5 -0.5 0.5 -0.5]
[ 0.5 0.5 -0.5 -0.5]
[ 0.5 -0.5 -0.5 0.5]]
⟨ZZ⟩ on |00> = 1.0
Visualization of Quantum States
You can also visualize single-qubit states on the Bloch sphere using .draw():
from qilisdk.core import QTensor
state = QTensor.ket(0)
state.draw()
The appearance of this plot can be customized using a QTensorStyle object,
which allows you to set colors, point density, and other visual elements:
from qilisdk.core import QTensor
from qilisdk.utils.visualization import QTensorStyle
state = QTensor.ket(0)
style = QTensorStyle(
sphere_color="blue",
arrow_color="lightblue",
draw_center_circle=True,
sphere_points=100,
draw_reference_points=True,
)
state.draw(style=style)