Pular para o conteúdo principal

Implementação com Qiskit

Na lição anterior, tivemos um primeiro contato com as classes Statevector e Operator do Qiskit, e as usamos para simular operações e medições em qubits individuais. Nesta seção, usaremos essas classes para explorar o comportamento de múltiplos qubits.

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

print(__version__)
2.1.1

Começaremos importando as classes Statevector e Operator, bem como a função de raiz quadrada do NumPy. A partir daqui, em geral, cuidaremos de todos os imports necessários logo no início de cada lição.

from qiskit.quantum_info import Statevector, Operator
from numpy import sqrt

Produtos tensoriais

A classe Statevector possui um método tensor, que retorna o produto tensorial daquele Statevector com outro, fornecido como argumento. O argumento é interpretado como o fator tensorial à direita.

Por exemplo, abaixo criamos dois vetores de estado representando 0\vert 0\rangle e 1,\vert 1\rangle, e usamos o método tensor para criar um novo vetor, ψ=01.\vert \psi\rangle = \vert 0\rangle \otimes \vert 1\rangle. Observe que estamos usando o método from_label para definir os estados 0\vert 0\rangle e 1,\vert 1\rangle, em vez de defini-los manualmente.

zero = Statevector.from_label("0")
one = Statevector.from_label("1")
psi = zero.tensor(one)
display(psi.draw("latex"))

01 |01\rangle

Outros rótulos permitidos incluem "+" e "-" para os estados mais e menos, bem como "r" e "l" (abreviações de "right" e "left") para os estados

+i=120+i21ei=120i21.\vert {+i} \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle + \frac{i}{\sqrt{2}} \vert 1 \rangle \qquad\text{e}\qquad \vert {-i} \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle - \frac{i}{\sqrt{2}} \vert 1 \rangle.

Aqui, "+" , "-" ou "right" e "left" vêm do contexto do spin na mecânica quântica, no qual uma componente do spin pode apontar para a esquerda ou para a direita em um experimento; não se refere ao qubit mais à direita ou mais à esquerda em sistemas de múltiplos qubits. Veja um exemplo do produto tensorial de +\vert {+} \rangle e i.\vert {-i} \rangle.

plus = Statevector.from_label("+")
minus_i = Statevector.from_label("l")
phi = plus.tensor(minus_i)
display(phi.draw("latex"))

1200i201+1210i211\frac{1}{2} |00\rangle- \frac{i}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{i}{2} |11\rangle

Uma alternativa é usar a operação ^ para produtos tensoriais, que naturalmente fornece os mesmos resultados.

display((plus ^ minus_i).draw("latex"))

1200i201+1210i211\frac{1}{2} |00\rangle- \frac{i}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{i}{2} |11\rangle

A classe Operator também possui um método tensor (assim como um método from_label), como vemos nos exemplos a seguir.

H = Operator.from_label("H")
Id = Operator.from_label("I")
X = Operator.from_label("X")
display(H.tensor(Id).draw("latex"))
display(H.tensor(Id).tensor(X).draw("latex"))
[220220022022220220022022] \begin{bmatrix} \frac{\sqrt{2}}{2} & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & \frac{\sqrt{2}}{2} \\ \frac{\sqrt{2}}{2} & 0 & - \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & - \frac{\sqrt{2}}{2} \\ \end{bmatrix} [02200022002200022000000220002200220002200220002200220002200000022000220022000220] \begin{bmatrix} 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 \\ \end{bmatrix}

Novamente, como no caso dos vetores, a operação ^ é equivalente.

display((H ^ Id ^ X).draw("latex"))
[02200022002200022000000220002200220002200220002200220002200000022000220022000220] \begin{bmatrix} 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 \\ \end{bmatrix}

Estados compostos podem ser evoluídos usando operações compostas como esperaríamos — assim como vimos para sistemas únicos na lição anterior. Por exemplo, o código a seguir calcula o estado (HI)ϕ(H\otimes I)\vert\phi\rangle para ϕ=+i\vert\phi\rangle = \vert + \rangle \otimes \vert {-i}\rangle (que já foi definido acima).

display(phi.evolve(H ^ Id).draw("latex"))

22002i201\frac{\sqrt{2}}{2} |00\rangle- \frac{\sqrt{2} i}{2} |01\rangle

Aqui está um código que define uma operação CXCX e calcula CXψCX \vert\psi\rangle para ψ=+0.\vert\psi\rangle = \vert + \rangle \otimes \vert 0 \rangle. Para deixar claro, esta é uma operação CXCX em que o qubit à esquerda é o controle e o qubit à direita é o alvo. O resultado é o estado de Bell ϕ+.\vert\phi^{+}\rangle.

CX = Operator([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
psi = plus.tensor(zero)
display(psi.evolve(CX).draw("latex"))

2200+2211\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle

Medições parciais

Na lição anterior, usamos o método measure para simular uma medição de um vetor de estado quântico. Este método retorna dois itens: o resultado simulado da medição e o novo Statevector dado essa medição.

Por padrão, measure mede todos os qubits no vetor de estado. Como alternativa, podemos fornecer uma lista de inteiros como argumento, o que faz com que apenas os índices de qubit indicados sejam medidos. Para demonstrar isso, o código abaixo cria o estado

w=001+010+1003\vert w\rangle = \frac{\vert 001\rangle + \vert 010\rangle + \vert 100\rangle}{\sqrt{3}}

e mede o qubit de número 0, que é o qubit mais à direita. (O Qiskit numera os qubits a partir de 0, da direita para a esquerda. Voltaremos a essa convenção de numeração na próxima lição.)

w = Statevector([0, 1, 1, 0, 1, 0, 0, 0] / sqrt(3))
display(w.draw("latex"))

result, state = w.measure([0])
print(f"Measured: {result}\nState after measurement:")
display(state.draw("latex"))

result, state = w.measure([0, 1])
print(f"Measured: {result}\nState after measurement:")
display(state.draw("latex"))

33001+33010+33100\frac{\sqrt{3}}{3} |001\rangle+\frac{\sqrt{3}}{3} |010\rangle+\frac{\sqrt{3}}{3} |100\rangle

Measured: 0
State after measurement:

22010+22100\frac{\sqrt{2}}{2} |010\rangle+\frac{\sqrt{2}}{2} |100\rangle

Measured: 00
State after measurement:

100 |100\rangle