Pular para o conteúdo principal

Especificar observáveis na base de Pauli

Versões dos pacotes

O código nesta página foi desenvolvido utilizando os seguintes requisitos. Recomendamos o uso dessas versões ou versões mais recentes.

qiskit[all]~=2.3.0

Na mecânica quântica, os observáveis correspondem a propriedades físicas que podem ser medidas. Ao considerar um sistema de spins, por exemplo, você pode estar interessado em medir a energia do sistema ou obter informações sobre o alinhamento dos spins, como a magnetização ou as correlações entre spins.

Para medir um observável OO de nn qubits em um computador quântico, você deve representá-lo como uma soma de produtos tensoriais de operadores de Pauli, ou seja

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},

onde

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}

e você utiliza o fato de que um observável é hermitiano, isto é, O=OO^\dagger = O. Se OO não for hermitiano, ainda é possível decompô-lo como uma soma de Paulis, mas o coeficiente αk\alpha_k se torna complexo.

Em muitos casos, o observável é naturalmente especificado nessa representação após mapear o sistema de interesse para qubits. Por exemplo, um sistema de spin-1/2 pode ser mapeado para um Hamiltoniano de Ising

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

onde os índices i,j\langle i, j\rangle percorrem os spins em interação e os spins estão sujeitos a um campo transversal em XX. O índice subscrito indica em qual qubit o operador de Pauli atua, ou seja, XiX_i aplica um operador XX no qubit ii e deixa os demais inalterados.

No Qiskit SDK, este Hamiltoniano pode ser construído com o seguinte 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])

Se quisermos medir a energia, o observável é o próprio Hamiltoniano. Alternativamente, podemos estar interessados em medir propriedades do sistema, como a magnetização média, contando o número de spins alinhados na direção ZZ com o observável

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

Para observáveis que não são dados em termos de operadores de Pauli, mas na forma de matriz, precisamos primeiro reformulá-los na base de Pauli para avaliá-los em um computador quântico. Podemos sempre encontrar tal representação, pois as matrizes de Pauli formam uma base para as matrizes hermitianas 2n×2n2^n \times 2^n. Expandimos o observável 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,

onde a soma percorre todos os possíveis termos de Pauli de nn qubits e Tr()\mathrm{Tr}(\cdot) é o traço de uma matriz, que atua como produto interno. Você pode implementar essa decomposição de uma matriz para termos de Pauli usando o método SparsePauliOp.from_operator, da seguinte forma:

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])

Isso significa que a matriz pode ser escrita em termos de Pauli como O=Z1+0.5X2+Y2Y1O = -Z_1 + 0.5 X_2 + Y_2 Y_1.

nota

Lembre-se de que a ordem do produto tensorial mapeia para os qubits como qnqn1q1q_n \otimes q_{n-1} \otimes \cdots \otimes q_1.

nota

Se o observável for hermitiano (ou seja, O=OO^\dagger = O), os coeficientes de Pauli são números reais. No entanto, também podemos decompor qualquer outra matriz complexa em termos de Paulis, se permitirmos coeficientes de valor complexo.

Medir nas bases de Pauli

Uma medição projeta o estado do qubit na base computacional {0,1}\{|0\rangle, |1\rangle\}. Isso implica que você só pode medir observáveis que são diagonais nessa base, como Paulis compostos apenas por termos II e ZZ. Medir termos de Pauli arbitrários requer, portanto, uma mudança de base para diagonalizá-los. Para isso, realize as seguintes transformações,

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

onde HH é a porta Hadamard e S=ZS = \sqrt{Z} é às vezes referida como a porta de fase. Se você estiver usando um Estimator para calcular valores esperados, as transformações de base são realizadas automaticamente.

A seguir há um exemplo que demonstra como preparar um circuito quântico e medir manualmente o qubit 0 na base X, o qubit 1 na base Y e o qubit 2 na base Z. Aplicamos as transformações mostradas na equação anterior e obtemos o seguinte 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")

Saída da célula de código anterior

Próximos passos

Recomendações