Saltar al contenido principal

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.3.0

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 — required packages for this notebook
!pip install -q numpy qiskit
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.
  • dims: 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