Saltar al contenido principal

Especificar observables en la base de Pauli

Versiones de paquetes

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

qiskit[all]~=2.3.0

En mecánica cuántica, los observables corresponden a propiedades físicas que pueden medirse. Al considerar un sistema de espines, por ejemplo, podrías estar interesado en medir la energía del sistema u obtener información sobre la alineación de los espines, como la magnetización o las correlaciones entre espines.

Para medir un observable OO de nn qubits en una computadora cuántica, debes representarlo como una suma de productos tensoriales de operadores de Pauli, es decir

O=k=1KαkPk,  Pk{I,X,Y,Z}n,  αkR,O = \sum_{k=1}^K \alpha_k P_k,~~ P_k \in \{I, X, Y, Z\}^{\otimes n},~~ \alpha_k \in \mathbb{R},

donde

I=(1001)  X=(0110)  Y=(0ii0)  Z=(1001)I = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix} ~~ X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} ~~ Y = \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix} ~~ Z = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}

y se utiliza el hecho de que un observable es hermítico, es decir, O=OO^\dagger = O. Si OO no es hermítico, aún puede descomponerse como una suma de Paulis, pero el coeficiente αk\alpha_k se vuelve complejo.

En muchos casos, el observable se especifica de forma natural en esta representación tras mapear el sistema de interés a qubits. Por ejemplo, un sistema de espín-1/2 puede mapearse a un hamiltoniano de Ising

H=i,jZiZji=1nXi,H = \sum_{\langle i, j\rangle} Z_i Z_j - \sum_{i=1}^n X_i,

donde los índices i,j\langle i, j\rangle recorren los espines en interacción y los espines están sujetos a un campo transversal en XX. El índice de subíndice indica en qué qubit actúa el operador de Pauli, es decir, XiX_i aplica un operador XX en el qubit ii y deja el resto sin cambios.

En el SDK de Qiskit, este hamiltoniano puede construirse con el siguiente código.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
from qiskit.quantum_info import SparsePauliOp

# define the number of qubits
n = 12

# define the single Pauli terms as ("Paulis", [indices], coefficient)
interactions = [
("ZZ", [i, i + 1], 1) for i in range(n - 1)
] # we assume spins on a 1D line
field = [("X", [i], -1) for i in range(n)]

# build the operator
hamiltonian = SparsePauliOp.from_sparse_list(
interactions + field, num_qubits=n
)
print(hamiltonian)
SparsePauliOp(['IIIIIIIIIIZZ', 'IIIIIIIIIZZI', 'IIIIIIIIZZII', 'IIIIIIIZZIII', 'IIIIIIZZIIII', 'IIIIIZZIIIII', 'IIIIZZIIIIII', 'IIIZZIIIIIII', 'IIZZIIIIIIII', 'IZZIIIIIIIII', 'ZZIIIIIIIIII', 'IIIIIIIIIIIX', 'IIIIIIIIIIXI', 'IIIIIIIIIXII', 'IIIIIIIIXIII', 'IIIIIIIXIIII', 'IIIIIIXIIIII', 'IIIIIXIIIIII', 'IIIIXIIIIIII', 'IIIXIIIIIIII', 'IIXIIIIIIIII', 'IXIIIIIIIIII', 'XIIIIIIIIIII'],
coeffs=[ 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j,
1.+0.j, 1.+0.j, 1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,
-1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j])

Si queremos medir la energía, el observable es el hamiltoniano en sí. Alternativamente, podríamos estar interesados en medir propiedades del sistema, como la magnetización promedio, contando el número de espines alineados en la dirección ZZ con el observable

O=1ni=1ZiO = \frac{1}{n} \sum_{i=1} Z_i

Para los observables que no están dados en términos de operadores de Pauli sino en forma matricial, primero debemos reformularlos en la base de Pauli para poder evaluarlos en una computadora cuántica. Siempre podemos encontrar dicha representación, ya que las matrices de Pauli forman una base para las matrices hermitianas de 2n×2n2^n \times 2^n. Expandimos el observable OO como

O=P{I,X,Y,Z}nTr(OP)P,O = \sum_{P \in \{I, X, Y, Z\}^{\otimes n}} \mathrm{Tr}(O P) P,

donde la suma recorre todos los posibles términos de Pauli de nn qubits y Tr()\mathrm{Tr}(\cdot) es la traza de una matriz, que actúa como producto interno. Puedes implementar esta descomposición de una matriz a términos de Pauli usando el método SparsePauliOp.from_operator, así:

import numpy as np
from qiskit.quantum_info import SparsePauliOp

matrix = np.array(
[[-1, 0, 0.5, -1], [0, 1, 1, 0.5], [0.5, 1, -1, 0], [-1, 0.5, 0, 1]]
)

observable = SparsePauliOp.from_operator(matrix)
print(observable)
SparsePauliOp(['IZ', 'XI', 'YY'],
coeffs=[-1. +0.j, 0.5+0.j, 1. -0.j])

Esto significa que la matriz puede escribirse en términos de Pauli como O=Z1+0.5X2+Y2Y1O = -Z_1 + 0.5 X_2 + Y_2 Y_1.

nota

Recuerda que el orden del producto tensorial se mapea a los qubits como qnqn1q1q_n \otimes q_{n-1} \otimes \cdots \otimes q_1.

nota

Si el observable es hermítico (es decir, O=OO^\dagger = O), los coeficientes de Pauli son números reales. Sin embargo, también podemos descomponer cualquier otra matriz compleja en términos de Paulis si permitimos coeficientes de valor complejo.

Medir en bases de Pauli

Una medición proyecta el estado del qubit a la base computacional {0,1}\{|0\rangle, |1\rangle\}. Esto implica que solo puedes medir observables que sean diagonales en esta base, como los Paulis compuestos únicamente de términos II y ZZ. Medir términos de Pauli arbitrarios requiere, por tanto, un cambio de base para diagonalizarlos. Para hacerlo, realiza las siguientes transformaciones,

XZ=HXHYZ=HSYSH,\begin{aligned} X &\rightarrow Z = H X H \\ Y &\rightarrow Z = H S^\dagger Y S H, \end{aligned}

donde HH es la puerta Hadamard y S=ZS = \sqrt{Z} se denomina a veces puerta de fase. Si usas un Estimator para calcular valores esperados, las transformaciones de base se realizan automáticamente.

A continuación se muestra un ejemplo que demuestra cómo preparar un circuito cuántico y medir manualmente el qubit 0 en la base X, el qubit 1 en la base Y y el qubit 2 en la base Z. Aplicamos las transformaciones mostradas en la ecuación anterior y obtenemos el siguiente circuito:

from qiskit.circuit import QuantumCircuit

# create a circuit, where we would like to measure
# q0 in the X basis, q1 in the Y basis and q2 in the Z basis
circuit = QuantumCircuit(3)
circuit.ry(0.8, 0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.barrier()

# diagonalize X with the Hadamard gate
circuit.h(0)

# diagonalize Y with Hadamard as S^\dagger
circuit.sdg(1)
circuit.h(1)

# the Z basis is the default, no action required here

# measure all qubits
circuit.measure_all()
circuit.draw("mpl")

Resultado de la celda de código anterior

Próximos pasos

Recomendaciones