Lumaktaw sa pangunahing nilalaman

Pagtatantya ng ground state energy ng Heisenberg chain gamit ang VQE

Tantiya sa paggamit: Dalawang minuto sa isang Eagle r3 processor (PAALALA: Ito ay isang tantiya lamang. Maaaring mag-iba ang inyong runtime.)

Panimula​

Ang tutorial na ito ay nagpapakita kung paano bumuo, mag-deploy, at magpatakbo ng Qiskit pattern para sa pagsisimula ng Heisenberg chain at pagtatantya ng ground state energy nito. Para sa karagdagang impormasyon tungkol sa Qiskit patterns at kung paano magagamit ang Qiskit Serverless upang i-deploy ang mga ito sa cloud para sa managed execution, bisitahin ang aming docs page sa IBM Quantum® Platform.

Mga Kinakailangan​

Bago magsimula sa tutorial na ito, tiyaking mayroon kayong sumusunod na naka-install:

  • Qiskit SDK v1.2 o mas bago, na may suporta sa visualization
  • Qiskit Runtime v0.28 o mas bago (pip install qiskit-ibm-runtime)
  • Qiskit Serverless (pip install qiskit_serverless)
  • IBM Catalog (pip install qiskit-ibm-catalog)

Pag-set up​

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-ibm-catalog qiskit-ibm-runtime scipy
import numpy as np
import matplotlib.pyplot as plt

from scipy.optimize import minimize
from typing import Sequence

from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives.base import BaseEstimatorV2
from qiskit.circuit.library import XGate
from qiskit.circuit.library import efficient_su2
from qiskit.transpiler import PassManager
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.transpiler.passes.scheduling import (
ALAPScheduleAnalysis,
PadDynamicalDecoupling,
)

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import Session, Estimator

from qiskit_ibm_catalog import QiskitServerless, QiskitFunction
def visualize_results(results):
plt.plot(results["cost_history"], lw=2)
plt.xlabel("Iteration")
plt.ylabel("Energy")
plt.show()

def build_callback(
ansatz: QuantumCircuit,
hamiltonian: SparsePauliOp,
estimator: BaseEstimatorV2,
callback_dict: dict,
):
def callback(current_vector):
# Keep track of the number of iterations
callback_dict["iters"] += 1
# Set the prev_vector to the latest one
callback_dict["prev_vector"] = current_vector
# Compute the value of the cost function at the current vector
current_cost = (
estimator.run([(ansatz, hamiltonian, [current_vector])])
.result()[0]
.data.evs[0]
)
callback_dict["cost_history"].append(current_cost)
# Print to screen on single line
print(
"Iters. done: {} [Current cost: {}]".format(
callback_dict["iters"], current_cost
),
end="\r",
flush=True,
)

return callback

Hakbang 1: I-map ang classical inputs sa isang quantum problem​

  • Input: Bilang ng mga spin
  • Output: Ansatz at Hamiltonian na nagmo-model ng Heisenberg chain

Bumuo ng ansatz at Hamiltonian na nagmo-model ng 10-spin Heisenberg chain. Una, mag-import tayo ng ilang generic na packages at lumikha ng ilang helper functions.

num_spins = 10
ansatz = efficient_su2(num_qubits=num_spins, reps=3)

# Remember to insert your token in the QiskitRuntimeService constructor
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, min_num_qubits=num_spins, simulator=False
)

coupling = backend.target.build_coupling_map()
reduced_coupling = coupling.reduce(list(range(num_spins)))

edge_list = reduced_coupling.graph.edge_list()
ham_list = []

for edge in edge_list:
ham_list.append(("ZZ", edge, 0.5))
ham_list.append(("YY", edge, 0.5))
ham_list.append(("XX", edge, 0.5))

for qubit in reduced_coupling.physical_qubits:
ham_list.append(("Z", [qubit], np.random.random() * 2 - 1))

hamiltonian = SparsePauliOp.from_sparse_list(ham_list, num_qubits=num_spins)

ansatz.draw("mpl", style="iqp")

Output ng nakaraang code cell

Hakbang 2: I-optimize ang problem para sa quantum hardware execution​

  • Input: Abstract circuit, observable
  • Output: Target circuit at observable, na-optimize para sa napiling QPU

Gamitin ang generate_preset_pass_manager function mula sa Qiskit upang awtomatikong makagawa ng optimization routine para sa ating circuit na nauugnay sa napiling QPU. Pipiliin natin ang optimization_level=3, na nagbibigay ng pinakamataas na antas ng optimization sa mga preset pass managers. Isasama rin natin ang ALAPScheduleAnalysis at PadDynamicalDecoupling scheduling passes upang pigilan ang mga decoherence errors.

target = backend.target
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
pm.scheduling = PassManager(
[
ALAPScheduleAnalysis(durations=target.durations()),
PadDynamicalDecoupling(
durations=target.durations(),
dd_sequence=[XGate(), XGate()],
pulse_alignment=target.pulse_alignment,
),
]
)
ansatz_ibm = pm.run(ansatz)
observable_ibm = hamiltonian.apply_layout(ansatz_ibm.layout)
ansatz_ibm.draw("mpl", scale=0.6, style="iqp", fold=-1, idle_wires=False)

Output ng nakaraang code cell

Hakbang 3: Magsagawa gamit ang Qiskit primitives​

  • Input: Target circuit at observable
  • Output: Mga resulta ng optimization

Paliitan ang tinantyang ground state energy ng system sa pamamagitan ng pag-optimize ng mga circuit parameters. Gamitin ang Estimator primitive mula sa Qiskit Runtime upang suriin ang cost function sa panahon ng optimization.

Para sa demo na ito, magpapatakbo tayo sa isang QPU gamit ang qiskit-ibm-runtime primitives. Upang magpatakbo gamit ang qiskit statevector-based primitives, palitan ang bloke ng code na gumagamit ng Qiskit IBM Runtime primitives ng commented block.

# SciPy minimizer routine
def cost_func(
params: Sequence,
ansatz: QuantumCircuit,
hamiltonian: SparsePauliOp,
estimator: BaseEstimatorV2,
) -> float:
"""Ground state energy evaluation."""
return (
estimator.run([(ansatz, hamiltonian, [params])])
.result()[0]
.data.evs[0]
)

num_params = ansatz_ibm.num_parameters
params = 2 * np.pi * np.random.random(num_params)

callback_dict = {
"prev_vector": None,
"iters": 0,
"cost_history": [],
}

# Evaluate the problem on a QPU by using Qiskit IBM Runtime
with Session(backend=backend) as session:
estimator = Estimator()
callback = build_callback(
ansatz_ibm, observable_ibm, estimator, callback_dict
)
res = minimize(
cost_func,
x0=params,
args=(ansatz_ibm, observable_ibm, estimator),
callback=callback,
method="cobyla",
options={"maxiter": 100},
)

visualize_results(callback_dict)

Hakbang 4: I-post-process at ibalik ang resulta sa nais na classical format​

  • Input: Mga tantiya ng ground state energy sa panahon ng optimization
  • Output: Tinantyang ground state energy
print(f'Estimated ground state energy: {res["fun"]}')

I-deploy ang Qiskit pattern sa cloud​

Upang gawin ito, ilipat ang source code sa itaas sa isang file, ./source/heisenberg.py, i-wrap ang code sa isang script na tumatanggap ng mga input at nagbabalik ng final solution, at sa wakas ay i-upload ito sa isang remote cluster gamit ang QiskitFunction class mula sa qiskit-ibm-catalog. Para sa gabay sa pagtukoy ng external dependencies, pagpasa ng input arguments, at iba pa, tingnan ang Qiskit Serverless guides.

Ang input sa Pattern ay ang bilang ng mga spin sa chain. Ang output ay isang tantiya ng ground state energy ng system.

# Authenticate to the remote cluster and submit the pattern for remote execution
serverless = QiskitServerless()
heisenberg_function = QiskitFunction(
title="ibm_heisenberg",
entrypoint="heisenberg.py",
working_dir="./source/",
)
serverless.upload(heisenberg_function)

Patakbuhin ang Qiskit pattern bilang managed service​

Kapag na-upload na natin ang pattern sa cloud, madali na nating mapapatakbo ito gamit ang QiskitServerless client.

# Run the pattern on the remote cluster

ibm_heisenberg = serverless.load("ibm_heisenberg")
job = serverless.run(ibm_heisenberg)
solution = job.result()

print(solution)
print(job.logs())

Survey sa tutorial​

Mangyaring sagutin ang maikling survey na ito upang magbigay ng feedback sa tutorial na ito. Ang inyong mga pananaw ay makakatulong sa amin na mapabuti ang aming mga content offerings at karanasan ng mga user.

Link sa survey