Saltar al contenido principal
Este proyecto está en fase beta. ¿Encontraste un error? Abre un issue en GitHub. ¿Tienes una pregunta o una idea? Pregunta en Discussions — ¡nos encantaría tu opinión!
¿Cómo es la calidad de la traducción en esta página?

Descripción general de las clases de operadores

Versiones de paquetes

El código de esta página fue desarrollado con los siguientes requisitos. Recomendamos usar estas versiones o versiones más recientes.

qiskit[all]~=2.5.2

En Qiskit, los operadores cuánticos se representan usando clases del módulo quantum_info. La clase de operador más importante es SparsePauliOp, que representa un operador cuántico general como combinación lineal de cadenas de Pauli. SparsePauliOp es la clase que se usa con más frecuencia para representar observables cuánticos. El resto de esta página explica cómo usar SparsePauliOp y otras clases de operadores.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import numpy as np
from qiskit.quantum_info.operators import Operator, Pauli, SparsePauliOp

SparsePauliOp​

La clase SparsePauliOp representa una combinación lineal de cadenas de Pauli. Hay varias formas de inicializar un SparsePauliOp, pero la más flexible es usar el método from_sparse_list, como se muestra en la siguiente celda de código. El método from_sparse_list acepta una lista de tripletas (pauli_string, qubit_indices, coefficient).

op1 = SparsePauliOp.from_sparse_list(
[("ZX", [1, 4], 1.0), ("YY", [0, 3], -1 + 1j)], num_qubits=5
)
op1
SparsePauliOp(['XIIZI', 'IYIIY'],
coeffs=[ 1.+0.j, -1.+1.j])

SparsePauliOp admite operaciones aritméticas, como se muestra en la siguiente celda de código.

op2 = SparsePauliOp.from_sparse_list(
[("XXZ", [0, 1, 4], 1 + 2j), ("ZZ", [1, 2], -1 + 1j)], num_qubits=5
)

# Addition
print("op1 + op2:")
print(op1 + op2)
print()
# Multiplication by a scalar
print("2 * op1:")
print(2 * op1)
print()
# Operator multiplication (composition)
print("op1 @ op2:")
print(op1 @ op2)
print()
# Tensor product
print("op1.tensor(op2):")
print(op1.tensor(op2))
op1 + op2:
SparsePauliOp(['XIIZI', 'IYIIY', 'ZIIXX', 'IIZZI'],
coeffs=[ 1.+0.j, -1.+1.j, 1.+2.j, -1.+1.j])

2 * op1:
SparsePauliOp(['XIIZI', 'IYIIY'],
coeffs=[ 2.+0.j, -2.+2.j])

op1 @ op2:
SparsePauliOp(['YIIYX', 'XIZII', 'ZYIXZ', 'IYZZY'],
coeffs=[ 1.+2.j, -1.+1.j, -1.+3.j, 0.-2.j])

op1.tensor(op2):
SparsePauliOp(['XIIZIZIIXX', 'XIIZIIIZZI', 'IYIIYZIIXX', 'IYIIYIIZZI'],
coeffs=[ 1.+2.j, -1.+1.j, -3.-1.j, 0.-2.j])

Pauli​

La clase Pauli representa una única cadena de Pauli con un coeficiente de fase opcional del conjunto { +1,i,−1,−i }\set{+1, i, -1, -i}. Un Pauli puede inicializarse pasando una cadena de caracteres del conjunto {"I", "X", "Y", "Z"}, opcionalmente precedida por uno de {"", "i", "-", "-i"} para representar el coeficiente de fase.

op1 = Pauli("iXX")
op1
Pauli('iXX')

La siguiente celda de código muestra el uso de algunos atributos y métodos.

print(f"Dimension of {op1}: {op1.dim}")
print(f"Phase of {op1}: {op1.phase}")
print(f"Matrix representation of {op1}: \n {op1.to_matrix()}")
Dimension of iXX: (4, 4)
Phase of iXX: 3
Matrix representation of iXX:
[[0.+0.j 0.+0.j 0.+0.j 0.+1.j]
[0.+0.j 0.+0.j 0.+1.j 0.+0.j]
[0.+0.j 0.+1.j 0.+0.j 0.+0.j]
[0.+1.j 0.+0.j 0.+0.j 0.+0.j]]

Los objetos Pauli poseen varios métodos adicionales para manipular los operadores, como determinar su adjunto, si conmuta (o anticonmuta) con otro Pauli y calcular el producto punto con otro Pauli. Consulta la documentación de la API para más información.

Operator​

La clase Operator representa un operador lineal general. A diferencia de SparsePauliOp, Operator almacena el operador lineal como una matriz densa. Debido a que la memoria necesaria para almacenar una matriz densa escala exponencialmente con el número de qubits, la clase Operator solo es adecuada para usarse con un número pequeño de qubits.

Puedes inicializar un Operator pasando directamente un array de NumPy que contenga la matriz del operador. Por ejemplo, la siguiente celda de código crea un operador Pauli XX de dos qubits:

XX = Operator(
np.array(
[
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0],
]
)
)
XX
Operator([[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]],
input_dims=(2, 2), output_dims=(2, 2))

El objeto operador almacena la matriz subyacente y las dimensiones de entrada y salida de los subsistemas.

  • data: Para acceder al array de NumPy subyacente, puedes usar la propiedad Operator.data.

  • dim: Para obtener la dimensión total de entrada y salida del operador, puedes usar la propiedad Operator.dim. Nota: la salida se devuelve como una tupla (input_dim, output_dim), que es el orden inverso al de la forma de la matriz subyacente.

XX.data
array([[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]])
input_dim, output_dim = XX.dim
input_dim, output_dim
(4, 4)

La clase de operadores también lleva registro de las dimensiones de los subsistemas, lo que puede usarse para componer operadores entre sí. Se puede acceder a ellas mediante las funciones input_dims y output_dims.

Para operadores de 2N2^N por 2M2^M, se asume automáticamente que las dimensiones de entrada y salida corresponden a M qubits y N qubits, respectivamente:

op = Operator(np.random.rand(2**1, 2**2))
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (2, 2)
Output dimensions: (2,)

Si la matriz de entrada no es divisible en subsistemas de qubits, se almacenará como un operador de un solo qubit. Por ejemplo, para una matriz de 6×66\times6:

op = Operator(np.random.rand(6, 6))
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (6,)
Output dimensions: (6,)

La dimensión de entrada y salida también puede especificarse manualmente al inicializar un nuevo operador:

# Force input dimension to be (4,) rather than (2, 2)
op = Operator(np.random.rand(2**1, 2**2), input_dims=[4])
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (4,)
Output dimensions: (2,)
# Specify system is a qubit and qutrit
op = Operator(np.random.rand(6, 6), input_dims=[2, 3], output_dims=[2, 3])
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (2, 3)
Output dimensions: (2, 3)

También puedes extraer únicamente las dimensiones de entrada o salida de un subconjunto de subsistemas usando las funciones input_dims y output_dims:

print("Dimension of input system 0:", op.input_dims([0]))
print("Dimension of input system 1:", op.input_dims([1]))
Dimension of input system 0: (2,)
Dimension of input system 1: (3,)

Próximos pasos​

Recomendaciones