Pular para o conteúdo principal
Este projeto está em fase beta. Encontrou um bug? Abra uma issue no GitHub. Tem uma pergunta ou ideia? Pergunte no Discussions — adoraríamos receber seu feedback!
Como está a qualidade da tradução nesta página?

Simule um modelo de Ising com chutes de 127 qubits

Neste guia, usamos o pacote pauli-prop para simular classicamente a dinâmica temporal de um modelo de Ising com chutes de 127 qubits em uma rede heavy-hex e aproximar a magnetização de um único sítio, ⟨Z62⟩\langle Z_{62} \rangle. O Hamiltoniano considerado é:

H=−J∑⟨i,j⟩ZiZj+h∑iXiH = -J\sum\limits_{\langle i,j \rangle} Z_iZ_j + h\sum\limits_iX_i

onde J>0J>0 descreve o acoplamento de spins vizinhos mais próximos, i<ji<j, e hh é o campo transversal global. Uma decomposição de Trotter de primeira ordem do operador evoluído no tempo será implementada como um circuito quântico, UU, ao longo de 2020 passos de Trotter. A constante de acoplamento, JJ, será fixada em J=−π2J=-\frac{\pi}{2}, de modo que UU seja Clifford sempre que hmod  π2=0h\mod\frac{\pi}{2}=0.

Fluxo de trabalho:

  • Crie circuitos quânticos que implementem o modelo de Ising com Trotterização

    • Varie hh entre os pontos de Clifford, 0.00.0 e π2\frac{\pi}{2}
  • Escolha um sítio no meio da rede (qubit 6262) e estime a magnetização após 2020 passos de Trotter para cada circuito

  • Observe a magnetização cair de 1.01.0 para 0.00.0 conforme hh se move de um ponto de Clifford para outro

Crie os circuitos​

Primeiro, usamos FakeSherbrooke de qiskit-ibm-runtime para obter os índices das arestas do mapa de acoplamento da QPU Eagle de 127 qubits. Depois de obter os índices das arestas, criamos os circuitos de Trotter para os diferentes valores de hh que queremos simular. Os circuitos implementarão uma Trotterização de primeira ordem do Hamiltoniano usando 20 passos de Trotter e 5420 portas.

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

_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "pauli_prop": "pauli-prop", "qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_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 import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

# Get the edges in the device coupling map
backend = FakeSherbrooke()
edges = backend.coupling_map.get_edges()

# Num Trotter steps
num_steps = 20

# Create Trotter circuits with varying global fields
hs = [i * np.pi / 32 for i in range(17)]
circuits = []
for h in hs:
circuit = QuantumCircuit(backend.num_qubits)
for _ in range(num_steps):
circuit.rx(h, [i for i in range(backend.num_qubits)])
for edge in edges:
circuit.rzz(-np.pi / 2, edge[0], edge[1])
circuits.append(circuit)

Simule a dinâmica temporal com propagação de Pauli​

Em seguida, especificamos o observável, OO, que queremos medir. Neste caso, estimamos ⟨Z62⟩\langle Z_{62} \rangle.

Para estudar a magnetização entre os pontos de Clifford, propagamos OO de forma aproximada até o início do circuito, UU, resultando em um novo observável, O′≈U†OUO^\prime \approx U^{\dagger}OU.

Durante a propagação, o número de termos no observável evoluído cresce exponencialmente com o número de portas, então geralmente é necessário limitar o quanto ele pode crescer. Aqui, limitamos o número de termos em O′O^\prime a 10510^5 e truncamos termos com coeficientes menores que 10−510^{-5}. O truncamento de termos gera algum erro. Depois de obter O′O^\prime, podemos estimar facilmente o valor esperado, ⟨0∣U†OU∣0⟩=⟨0∣O′∣0⟩\langle0|U^{\dagger}OU|0\rangle = \langle0|O^\prime|0\rangle, somando os coeficientes dos termos diagonais em O′O^\prime (termos que consistem apenas em I ou Z em todos os qubits).

Definimos frame='h' para especificar que queremos evoluir o observável no referencial de Heisenberg (U†OUU^{\dagger}OU). Use frame=s para a evolução de Schrödinger (UOU†UOU^{\dagger}).

import time

from pauli_prop import propagate_through_circuit
from qiskit.quantum_info import Pauli, SparsePauliOp

# Z_62 observable
id_pauli = Pauli("I" * backend.num_qubits)
observable = SparsePauliOp(id_pauli.dot(Pauli("Z"), [62]))

# Estimate the single-site magnetization for varying magnetic fields
times = []
approx_evs = []
for circuit in circuits:
st = time.perf_counter()
propagated_obs = propagate_through_circuit(
observable, circuit, 100_000, 1e-5, frame="h"
)[0]
times.append(time.perf_counter() - st)
approx_evs.append(
float(
propagated_obs.coeffs[~propagated_obs.paulis.x.any(axis=1)].sum()
)
)
print(f"Finished {len(circuits)} simulations in {sum(times):.0f}s")
Finished 17 simulations in 494s

Visualizar​

Por fim, plotamos a magnetização em função de hh. Quando h=0h=0, o circuito não afeta o estado inicial na base computacional, e sabemos que ⟨0∣O∣0⟩=1.0\langle0|O|0\rangle = 1.0. À medida que hh se afasta de 00, a magnetização decai monotonicamente até que hh alcance o próximo ângulo de Clifford, π2\frac{\pi}{2}, e a magnetização converge para 00.

import matplotlib.pyplot as plt

plt.xlabel(r"$R_x$ angle $\theta_h$")
plt.ylabel(r"$\langle Z_{62} \rangle$")
plt.plot(hs, approx_evs, marker="o")
[<matplotlib.lines.Line2D at 0x123f68b00>]

Output of the previous code cell