Simula un modelo de Ising con pulsos de 127 qubits
En esta guía usamos el paquete pauli-prop para simular de forma clásica la dinámica temporal de un modelo de Ising con pulsos de 127 qubits en una red heavy-hex y aproximar la magnetización de un solo sitio, . El hamiltoniano considerado es:
donde describe el acoplamiento de espines vecinos más cercanos, , y es el campo transversal global. Se implementará una descomposición de Trotter de primer orden del operador evolucionado en el tiempo como un circuito cuántico, , a lo largo de pasos de Trotter. La constante de acoplamiento, , se fijará en de modo que sea Clifford siempre que .
Flujo de trabajo:
-
Crear circuitos cuánticos que implementen el modelo de Ising de Trotter
- Variar entre los puntos Clifford, y
-
Elegir un sitio en el centro de la red (qubit ) y estimar la magnetización tras pasos de Trotter para cada circuito
-
Observar cómo la magnetización decae de a cuando pasa de un punto Clifford a otro
Crea los circuitos
Primero, usamos FakeSherbrooke de qiskit-ibm-runtime para obtener los índices de las aristas del mapa de acoplamiento de la QPU Eagle de 127 qubits. Una vez que tenemos los índices de las aristas, creamos los circuitos de Trotter para los distintos valores de que queremos simular. Los circuitos implementarán una trotterización de primer orden del hamiltoniano usando 20 pasos de Trotter y 5420 puertas.
# 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)
Simula la dinámica temporal con propagación de Pauli
A continuación, especificamos el observable, , que queremos medir. En este caso, estimamos .
Para estudiar la magnetización entre puntos Clifford, propagamos de forma aproximada hasta el inicio del circuito, , obteniendo un nuevo observable, .
Durante la propagación, el número de términos del observable evolucionado crece exponencialmente con el número de puertas, por lo que normalmente es necesario limitar cuánto puede crecer. Aquí limitamos el número de términos de a y truncamos los términos con coeficientes menores que . Truncar términos introduce cierto error.
Una vez que tenemos , podemos estimar fácilmente el valor esperado, , sumando los coeficientes de los términos diagonales de (términos formados únicamente por I o Z en todos los qubits).
Establecemos frame='h' para indicar que queremos evolucionar el observable en el marco de Heisenberg (). Usa frame=s para la evolución de Schrödinger ().
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
Visualiza
Por último, graficamos la magnetización en función de . Cuando , el circuito no afecta al estado inicial en la base computacional, y sabemos que . A medida que se aleja de , la magnetización decae de forma monótona hasta que alcanza el siguiente ángulo Clifford, , y la magnetización converge a .
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>]
