QTensor
El módulo qtensor define la clase QTensor y funciones auxiliares relacionadas para representar y manipular estados cuánticos y operadores en forma dispersa.
La clase QTensor envuelve un array denso de NumPy o una matriz dispersa de SciPy en una matriz dispersa en formato CSR y puede representar:
Kets (vectores columna de forma
(2**N, 1))Bras (vectores fila de forma
(1, 2**N))Operadores / Matrices de densidad (matrices cuadradas de forma
(2**N, 2**N))Escalares (matrices
(1, 1))
Ejemplos de creación de distintos objetos cuánticos:
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())
Salida
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
Constructores auxiliares
También existen varios constructores para objetos cuánticos comunes:
ket()para kets de la base computacional
bra()para bras de la base computacional
basis_state()para estados de base N-dimensionales con un único 1 en el índice especificado
identity()para operadores identidad de dimensión especificada
zero()para generar tensores cero de dimensión especificada
ghz()para generar estados GHZ con un número de qubits especificado
uniform()para generar estados de superposición uniforme con un número de qubits especificado
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 and zero operators
print("Identity (4x4):\n", QTensor.identity(2))
print("Zero (2x2):\n", QTensor.zero(2))
Salida
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)
Propiedades y Operaciones de Objetos Cuánticos
Todos los datos se almacenan en formato disperso, pero se pueden obtener vistas densas o dispersas:
.data: obtiene la matriz dispersa subyacente (formato CSR de SciPy).dense(): convierte a un array denso de NumPy (usar con precaución para tensores grandes)o accediendo directamente a elementos por valor con
qtensor[i, j]
También están disponibles operaciones matriciales comunes:
.adjoint(): traspuesta conjugada.conjugate(): conjugada compleja elemento a elemento.transpose(): traspuesta matricial.exp(): exponencial matricial.log(): logaritmo matricial.sqrt(): raíz cuadrada matricial.rank(): calcula el rango del operador.pow(exponent): potencia matricial.norm(order="l2"): norma vectorial o matricial.normalized(order='l2'): normaliza a norma unitaria.eig(): obtiene los valores propios y vectores propios.trace(): calcula la traza de un operador.dot(other): producto interior de Frobenius con otro QTensor
Así como algunas transformaciones específicas para objetos cuánticos:
.entropy_von_neumann(): calcula la entropía de von Neumann de una matriz de densidad.entropy_renyi(alpha): calcula la entropía de Rényi de una matriz de densidad para un orden alpha dado.commutator(other): calcula el conmutador con otro operador.anticommutator(other): calcula el anticonmutador con otro operador.fidelity(other): calcula la fidelidad entre dos estados cuánticos.probabilities(): calcula la distribución de probabilidad de cada estado en la base computacional.partial_trace(keep): traza parcial.reset_qubits(qubits): restablece los qubits especificados a 0.dagger(): alias de adjoint
Ejemplos:
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())
Salida
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]]
Utilidades Adicionales
Producto tensorial con
tensor_prod()Valor esperado con
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)
Salida
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
Visualización de Estados Cuánticos
También puede visualizar estados de un solo qubit en la esfera de Bloch usando .draw():
from qilisdk.core import QTensor
state = QTensor.ket(0)
state.draw()
El aspecto de este gráfico se puede personalizar usando un objeto QTensorStyle, que permite establecer colores, densidad de puntos y otros elementos visuales:
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)