Bestimmung einer Molekülgeometrie
Im vorangegangenen Abschnitt haben wir VQE zur Bestimmung der Grundzustandsenergie eines Moleküls eingesetzt. Das ist eine sinnvolle Anwendung des Quantencomputings, aber noch nützlicher wäre es, die Struktur eines Moleküls zu bestimmen.
Schritt 1: Klassische Eingaben einem Quantenproblem zuordnen
Bleiben wir bei unserem einfachen Beispiel des zweiatomigen Wasserstoffs, so ist der einzige geometrische Parameter, der variiert werden kann, die Bindungslänge. Um dies zu erreichen, gehen wir wie zuvor vor, verwenden aber eine Variable in unserer ursprünglichen Molekülkonstruktion (eine Bindungslänge, x, im Argument). Dies ist eine recht einfache Änderung, die jedoch erfordert, dass die Variable während des gesamten Prozesses in Funktionen einbezogen wird, da sie in der fermionischen Hamilton-Konstruktion beginnt und sich über die Abbildung bis hin zur Kostenfunktion fortpflanzt.
Zunächst laden wir einige der Pakete, die wir zuvor verwendet haben, und definieren die Cholesky-Funktion.
from qiskit.quantum_info import SparsePauliOp
import matplotlib.pyplot as plt
import numpy as np
#!pip install pyscf==2.4.0
from pyscf import ao2mo, gto, mcscf, scf
def cholesky(V, eps):
# see https://arxiv.org/pdf/1711.02242.pdf section B2
# see https://arxiv.org/abs/1808.02625
# see https://arxiv.org/abs/2104.08957
no = V.shape[0]
chmax, ng = 20 * no, 0
W = V.reshape(no**2, no**2)
L = np.zeros((no**2, chmax))
Dmax = np.diagonal(W).copy()
nu_max = np.argmax(Dmax)
vmax = Dmax[nu_max]
while vmax > eps:
L[:, ng] = W[:, nu_max]
if ng > 0:
L[:, ng] -= np.dot(L[:, 0:ng], (L.T)[0:ng, nu_max])
L[:, ng] /= np.sqrt(vmax)
Dmax[: no**2] -= L[: no**2, ng] ** 2
ng += 1
nu_max = np.argmax(Dmax)
vmax = Dmax[nu_max]
L = L[:, :ng].reshape((no, no, ng))
print(
"accuracy of Cholesky decomposition ",
np.abs(np.einsum("prg,qsg->prqs", L, L) - V).max(),
)
return L, ng
def identity(n):
return SparsePauliOp.from_list([("I" * n, 1)])
def creators_destructors(n, mapping="jordan_wigner"):
c_list = []
if mapping == "jordan_wigner":
for p in range(n):
if p == 0:
ell, r = "I" * (n - 1), ""
elif p == n - 1:
ell, r = "", "Z" * (n - 1)
else:
ell, r = "I" * (n - p - 1), "Z" * p
cp = SparsePauliOp.from_list([(ell + "X" + r, 0.5), (ell + "Y" + r, -0.5j)])
c_list.append(cp)
else:
raise ValueError("Unsupported mapping.")
d_list = [cp.adjoint() for cp in c_list]
return c_list, d_listUm unseren Hamiltonian zu definieren, verwenden wir PySCF genau wie im vorherigen Beispiel, aber jetzt fügen wir eine Variable, x, hinzu, die die Rolle unseres interatomaren Abstands spielt. Dies ergibt die Kernenergie, die Ein-Elektronen-Energie und die Zwei-Elektronen-Energie wie zuvor.
def ham_terms(x: float):
distance = x
a = distance / 2
mol = gto.Mole()
mol.build(
verbose=0,
atom=[
["H", (0, 0, -a)],
["H", (0, 0, a)],
],
basis="sto-6g",
spin=0,
charge=0,
symmetry="Dooh",
)
# mf = scf.RHF(mol)
# mx = mcscf.CASCI(mf, ncas=2, nelecas=(1, 1))
# mx.kernel()
mf = scf.RHF(mol)
mf.kernel()
if not mf.converged:
raise RuntimeError(f"SCF did not converge for distance {x}")
mx = mcscf.CASCI(mf, ncas=2, nelecas=(1, 1))
casci_energy = mx.kernel()
if casci_energy is None:
raise RuntimeError(f"CASCI failed for distance {x}")
# Other variables that might come in handy:
# active_space = range(mol.nelectron // 2 - 1, mol.nelectron // 2 + 1)
# E1 = mf.kernel()
# mo = mx.sort_mo(active_space, base=0)
# E2 = mx.kernel(mo)[:2]
h1e, ecore = mx.get_h1eff()
h2e = ao2mo.restore(1, mx.get_h2eff(), mx.ncas)
return ecore, h1e, h2eErinnern Sie sich, dass die obige Konstruktion einen fermionischen Hamiltonian auf der Grundlage der Atomspezies, der Geometrie und der elektronischen Orbitale erstellt. Im Folgenden wird dieser fermionische Hamiltonian auf Pauli-Operatoren abgebildet. Diese Funktion build_hamiltonian wird auch eine geometrische Variable als Argument enthalten.
def build_hamiltonian(distx: float) -> SparsePauliOp:
ecore = ham_terms(distx)[0]
h1e = ham_terms(distx)[1]
h2e = ham_terms(distx)[2]
ncas, _ = h1e.shape
C, D = creators_destructors(2 * ncas, mapping="jordan_wigner")
Exc = []
for p in range(ncas):
Excp = [C[p] @ D[p] + C[ncas + p] @ D[ncas + p]]
for r in range(p + 1, ncas):
Excp.append(
C[p] @ D[r]
+ C[ncas + p] @ D[ncas + r]
+ C[r] @ D[p]
+ C[ncas + r] @ D[ncas + p]
)
Exc.append(Excp)
# low-rank decomposition of the Hamiltonian
Lop, ng = cholesky(h2e, 1e-6)
t1e = h1e - 0.5 * np.einsum("pxxr->pr", h2e)
H = ecore * identity(2 * ncas)
# one-body term
for p in range(ncas):
for r in range(p, ncas):
H += t1e[p, r] * Exc[p][r - p]
# two-body term
for g in range(ng):
Lg = 0 * identity(2 * ncas)
for p in range(ncas):
for r in range(p, ncas):
Lg += Lop[p, r, g] * Exc[p][r - p]
H += 0.5 * Lg @ Lg
return H.chop().simplify()Wir werden die verbleibenden Pakete für die Ausführung von VQE selbst laden, wie z.B. den efficient_su2 Ansatz und SciPy Minimierer:
# General imports
# Pre-defined ansatz circuit and operator class for Hamiltonian
from qiskit.circuit.library import efficient_su2
from qiskit.quantum_info import SparsePauliOp
# SciPy minimizer routine
from scipy.optimize import minimize
# Plotting functions
# qiskit-ibm-runtime tools
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()Wir werden erneut die Kostenfunktion definieren, aber diese hat immer einen vollständig gebauten und abgebildeten Hamiltonian als Argument, so dass sich an dieser Funktion nichts ändert.
def cost_func(params, ansatz, H, estimator):
pub = (ansatz, [H], [params])
result = estimator.run(pubs=[pub]).result()
energy = result[0].data.evs[0]
return energy
# def cost_func_sim(params, ansatz, H, estimator):
# energy = estimator.run(ansatz, H, parameter_values=params).result().values[0]
# return energySchritt 2: Optimierung des Problems für die Quantenausführung
Da sich der Hamiltonian mit jeder neuen Geometrie ändert, ändert sich auch die Transpilierung des Operators bei jedem Schritt. Wir können jedoch einen allgemeinen Pass-Manager definieren, der bei jedem Schritt angewandt wird, und zwar speziell für die Hardware, die wir verwenden wollen.
Hier werden wir das am wenigsten ausgelastete Backend verwenden. Wir werden dieses Backend als Modell für unser AerSimulator, verwenden, so dass unser Simulator z. B. das Rauschverhalten des echten Backends nachahmen kann. Diese Geräuschmodelle sind nicht perfekt, aber sie können Ihnen helfen zu wissen, was Sie von echter Hardware erwarten können.
# Here, we select the least busy backend available:
backend = service.least_busy(operational=True, simulator=False)
print(backend)
# Or to select a specific real backend use the line below, and substitute 'ibm_strasbourg'
# for your chosen device. backend = service.get_backend('ibm_strasbourg')# To run on a simulator:
# -----------
from qiskit_aer import AerSimulator
backend_sim = AerSimulator.from_backend(backend)Wir importieren den Passmanager und zugehörige Pakete, um unsere Schaltung zu optimieren. Dieser Schritt und der darüber liegende sind unabhängig von der Hamiltonfunktion und bleiben daher gegenüber der vorherigen Lektion unverändert.
from qiskit.transpiler import PassManager
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.transpiler.passes import (
ALAPScheduleAnalysis,
PadDynamicalDecoupling,
ConstrainedReschedule,
)
from qiskit.circuit.library import XGate
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
pm.scheduling = PassManager(
[
ALAPScheduleAnalysis(target=target),
ConstrainedReschedule(
acquire_alignment=target.acquire_alignment,
pulse_alignment=target.pulse_alignment,
target=target,
),
PadDynamicalDecoupling(
target=target,
dd_sequence=[XGate(), XGate()],
pulse_alignment=target.pulse_alignment,
),
]
)Schritt 3: Führen Sie den Befehl mithilfe der „ IBM Quantum “-Primitive aus.
Im folgenden Code-Block richten wir ein Array ein, um die Ergebnisse jedes Schritts unserer interatomaren Abstands zu speichern. Wir haben den Bereich von auf der Grundlage unserer Kenntnis des experimentellen Werts für die Gleichgewichtsbindungslänge gewählt: 0.74 Angström. Wir werden dies zunächst auf einem Simulator ausführen und dazu unseren Estimator ( BackendEstimator ) von dort qiskit.primitivesimportieren. Für jeden Geometrieschritt erstellen wir den Hamilton-Operator und führen mit dem Optimierer „cobyla“ eine bestimmte Anzahl von Optimierungsschritten durch (hier 500). Bei jedem Geometrieschritt speichern wir sowohl die Gesamtenergie als auch die elektronische Energie. Aufgrund der hohen Anzahl an Optimierungsschritten kann dies eine Stunde oder länger dauern. Möglicherweise möchten Sie die folgenden Eingaben anpassen, um die benötigte Zeit zu verkürzen.
from qiskit.primitives import BackendEstimatorV2
estimator = BackendEstimatorV2(backend=backend_sim)
distances_sim = np.arange(0.3, 1.3, 0.1)
vqe_energies_sim = []
vqe_elec_energies_sim = []
for dist in distances_sim:
xx = dist
# Random initial state and efficient_su2 ansatz
H = build_hamiltonian(xx)
ansatz = efficient_su2(H.num_qubits)
ansatz_isa = pm.run(ansatz)
x0 = 2 * np.pi * np.random.random(ansatz_isa.num_parameters)
H_isa = H.apply_layout(ansatz_isa.layout)
nuclear_repulsion = ham_terms(xx)[0]
res = minimize(
cost_func,
x0,
args=(ansatz_isa, H_isa, estimator),
method="cobyla",
options={"maxiter": 20, "disp": True},
)
# Note this returns the total energy, and we are often interested in the electronic energy
tot_energy = getattr(res, "fun")
electron_energy = getattr(res, "fun") - nuclear_repulsion
print(electron_energy)
vqe_energies_sim.append(tot_energy)
vqe_elec_energies_sim.append(electron_energy)
# Print all results
print(res)
print("All energies have been calculated")Output:
accuracy of Cholesky decomposition 1.1102230246251565e-15
/home/porter284/.pyenv/versions/3.11.12/lib/python3.11/site-packages/scipy/_lib/pyprima/common/preproc.py:68: UserWarning: COBYLA: Invalid MAXFUN; it should be at least num_vars + 2; it is set to 34
warn(f'{solver}: Invalid MAXFUN; it should be at least {min_maxfun_str}; it is set to {maxfun}')
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = 1.316011435623847
The corresponding X is:
[2.32948769 5.39918229 3.03787975 4.11789904 4.97130735 2.68662232
1.76573151 2.48982571 5.40431972 3.65780829 1.33792786 5.48472494
6.18738702 1.78741883 0.78195251 2.96658955 1.35827677 5.599321
4.54850148 1.0939048 4.26158726 0.52100721 0.82318 4.76796961
3.75795507 3.8526447 5.51100375 5.91023075 2.61494836 1.79908918
2.65937756 5.53964148]
-0.44791260077615314
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: 1.316011435623847
x: [ 2.329e+00 5.399e+00 ... 2.659e+00 5.540e+00]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 5.551115123125783e-16
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = 0.7235003672327549
The corresponding X is:
[2.56282915 5.63369524 5.58059887 4.049643 4.2021266 3.06866011
6.01619635 1.52520776 4.35403161 0.33673958 0.32623161 1.2179545
2.84001371 3.98956684 4.89632562 1.38303588 1.96194695 2.13182089
0.29739166 1.77895165 3.29151585 3.54355374 4.49626674 0.95756626
0.87103927 4.53068385 1.31051302 0.37103108 1.02961355 3.13342311
5.65815319 2.24770604]
-0.5994426600672451
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: 0.7235003672327549
x: [ 2.563e+00 5.634e+00 ... 5.658e+00 2.248e+00]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 5.551115123125783e-16
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = 0.34960914928810116
The corresponding X is:
[5.44143165 6.75955835 1.56836472 3.09522093 4.67873235 1.67071481
0.3056494 0.65998337 1.02197668 5.21162959 0.43690354 3.56522934
4.56033119 1.90736037 0.40863891 2.87007312 3.2516952 5.90360196
1.99057799 5.20726456 0.74710237 6.03179202 3.80685028 0.03844391
5.88580196 3.62233258 3.98723567 2.50591888 5.44020267 2.2792993
5.57102303 4.46548617]
-0.7087452725518989
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: 0.34960914928810116
x: [ 5.441e+00 6.760e+00 ... 5.571e+00 4.465e+00]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 2.220446049250313e-16
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = 0.10594558882184543
The corresponding X is:
[5.35675483 2.26629567 1.45430546 5.56758296 5.76309509 0.73239338
5.1216998 3.03258872 4.33624828 1.93197674 0.5292902 3.32274987
3.43247633 0.81490741 0.48060245 1.9944799 5.67519646 5.12534057
0.06510627 2.52989834 6.1699519 0.94828957 5.91634548 1.5994961
4.27902164 2.3129213 1.82353095 2.10634209 1.43740426 4.06988733
0.59624074 4.93925418]
-0.7760164293781545
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: 0.10594558882184543
x: [ 5.357e+00 2.266e+00 ... 5.962e-01 4.939e+00]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 1.1102230246251565e-16
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = -0.06473600797229297
The corresponding X is:
[6.07735568 0.18019501 0.20743128 4.15445985 3.59388894 5.10047555
6.09938474 6.54707528 3.36251167 2.05475223 3.67078456 5.96010605
2.58589996 5.2723619 3.26352977 2.47432334 3.50289983 2.06620525
6.0946056 1.22751903 0.97320057 2.19564095 5.73174941 2.05127682
5.73805165 3.84046105 1.84816963 2.1247504 3.11106736 2.44136052
3.39002685 0.81596991]
-0.8207034521437214
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.06473600797229297
x: [ 6.077e+00 1.802e-01 ... 3.390e+00 8.160e-01]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 5.551115123125783e-17
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = -0.19562982094782935
The corresponding X is:
[-0.02184462 3.67041038 7.25918653 5.89799546 0.63583624 1.84214506
2.84059837 5.31485182 1.6053784 0.04556618 0.32018993 -0.03884066
0.69131496 0.24203727 1.97397262 3.59723495 0.43355775 2.30131056
4.63482292 3.9857415 4.32320753 4.55388437 2.18753433 5.99034987
2.50489913 0.90650534 4.82518088 2.32954849 2.29901832 5.33658863
5.91246716 3.2405013 ]
-0.8571013345978292
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.19562982094782935
x: [-2.184e-02 3.670e+00 ... 5.912e+00 3.241e+00]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 1.1102230246251565e-16
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = -0.2833766309947055
The corresponding X is:
[ 3.1700088 5.05055456 1.2545611 4.28751811 0.6255103 1.67526577
5.48201473 4.83820497 7.34880059 5.99705431 4.2502643 0.32066274
0.41001404 0.27271241 4.15682546 4.22393693 4.35148115 0.64538137
5.26288622 5.03810489 4.62426621 4.74997689 1.09603919 0.34752466
1.8116275 0.7474807 5.31754143 4.11181763 1.58797998 5.6299796
3.0109383 -0.19062772]
-0.8713513097947054
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.2833766309947055
x: [ 3.170e+00 5.051e+00 ... 3.011e+00 -1.906e-01]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 1.1102230246251565e-16
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = -0.3527503628484244
The corresponding X is:
[3.90513622 4.61398739 5.92552705 1.99953405 4.82157369 1.35702441
2.77701782 5.73612247 4.22710527 1.83463189 0.45796297 4.62509318
0.98998668 0.11666217 3.0234641 4.54298546 0.14034033 4.15635797
1.41257357 4.48719602 2.39365535 0.19672041 5.0763044 1.86357581
3.657757 4.60298344 2.49769577 1.88086199 3.00108725 1.84475841
5.24047385 4.91142914]
-0.8819275737684243
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.3527503628484244
x: [ 3.905e+00 4.614e+00 ... 5.240e+00 4.911e+00]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 2.7755575615628914e-17
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = -0.4022181851996095
The corresponding X is:
[6.09453981 3.5109422 3.37216019 4.94732621 1.25662002 5.89645164
5.06403334 2.68073141 4.40385083 1.13638366 1.73347762 6.82932871
1.15265014 2.07145964 4.36520459 1.14960341 1.62288871 4.32315915
5.45622821 0.93554005 3.17418483 0.47230243 1.31535502 5.77698726
2.04927925 2.50663538 5.9706002 5.4984681 2.9421232 1.56636313
1.09394523 4.62582 ]
-0.8832883769450639
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.4022181851996095
x: [ 6.095e+00 3.511e+00 ... 1.094e+00 4.626e+00]
nfev: 34
maxcv: 0.0
accuracy of Cholesky decomposition 1.1102230246251565e-16
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 34 Least value of F = -0.44423031870708934
The corresponding X is:
[4.05765050e+00 3.99144950e+00 3.13287593e+00 3.28855137e+00
4.32613515e+00 4.91104512e+00 1.86521867e+00 2.18822879e+00
6.01336171e+00 1.82501276e+00 2.64830637e+00 5.53045823e+00
2.36110093e+00 3.98821703e+00 4.69013438e-01 4.38996815e+00
7.78103801e-04 1.72994378e+00 2.24970934e+00 1.11978200e+00
2.24846445e+00 4.90745512e+00 5.38474921e+00 5.03587994e+00
3.54297277e+00 4.78147533e+00 1.25990218e+00 1.99168068e+00
5.89203503e+00 1.77673987e+00 5.37848357e+00 5.60245198e-01]
-0.8852113278070892
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.44423031870708934
x: [ 4.058e+00 3.991e+00 ... 5.378e+00 5.602e-01]
nfev: 34
maxcv: 0.0
All energies have been calculated
xxOutput:
np.float64(1.2000000000000004)
Die Ergebnisse dieser Ausgabe werden weiter unten im Abschnitt zur Nachbearbeitung erläutert; an dieser Stelle sei lediglich angemerkt, dass die Simulation erfolgreich war. Jetzt können Sie das Programm auf echter Hardware ausführen. Wir werden die Ausfallsicherheit auf setzen 1, was bedeutet, dass die TREX-Fehlerbehebung verwendet wird. Da wir nun mit echter Hardware arbeiten, werden wir die Funktionen „ IBM Quantum “ und „ IBM Quantum “ nutzen. Beachten Sie, dass sowohl die for-Schleife für die Geometrie als auch die zahlreichen Variationsdurchläufe innerhalb der Sitzung stattfinden.
Da reale Hardware-Läufe mit Kosten und Zeitbeschränkungen verbunden sind, haben wir die Anzahl der Geometrie- und Optimierungsschritte im Folgenden reduziert. Achten Sie darauf, dass Sie diese Schritte auf Ihre Präzisionsziele und Zeitvorgaben abstimmen.
# To continue running on real hardware use
from qiskit_ibm_runtime import Session
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime import EstimatorOptions
estimator_options = EstimatorOptions(resilience_level=1, default_shots=2000)
distances = np.arange(0.5, 0.9, 0.1)
vqe_energies = []
vqe_elec_energies = []
with Session(backend=backend) as session:
estimator = Estimator(mode=session, options=estimator_options)
for dist in distances:
xx = dist
# Random initial state and efficient_su2 ansatz
H = build_hamiltonian(xx)
ansatz = efficient_su2(H.num_qubits)
ansatz_isa = pm.run(ansatz)
H_isa = H.apply_layout(ansatz_isa.layout)
nuclear_repulsion = ham_terms(xx)[0]
x0 = 2 * np.pi * np.random.random(ansatz_isa.num_parameters)
res = minimize(
cost_func,
x0,
args=(ansatz_isa, H_isa, estimator),
method="cobyla",
options={"maxiter": 50, "disp": True},
)
# Note this returns the total energy, and we are often interested in the electronic energy
tot_energy = getattr(res, "fun")
electron_energy = getattr(res, "fun") - nuclear_repulsion
print(electron_energy)
vqe_energies.append(tot_energy)
vqe_elec_energies.append(electron_energy)
# Print all results
print(res)
print("All energies have been calculated")Schritt 4: Nachbearbeitung
Sowohl für den Simulator als auch für die reale Hardware können wir die für jeden Atomabstand berechneten Grundzustandsenergien aufzeichnen und sehen, wo die niedrigste Energie erreicht wird. Das sollte der in der Natur vorkommende Abstand zwischen den Atomen sein, und er ist tatsächlich sehr gering. Eine glattere Kurve könnte man erhalten, indem man andere Ansaetze und Optimierer ausprobiert und die Berechnung bei jedem Geometrieschritt mehrfach durchführt und den Mittelwert über mehrere zufällige Anfangsbedingungen bildet.
# Here we can plot the results from this simulation.
plt.plot(distances_sim, vqe_energies_sim, label="VQE Energy")
plt.xlabel("Atomic distance (Angstrom)")
plt.ylabel("Energy")
plt.legend()
plt.show()Output:
Es ist zu beachten, dass eine einfache Erhöhung der Anzahl der Optimierungsschritte die Ergebnisse des Simulators wahrscheinlich nicht verbessern wird, da alle Optimierungen tatsächlich in weniger als der maximalen Anzahl von Iterationen zur erforderlichen Toleranz konvergierten.
Die Ergebnisse der realen Hardware sind vergleichbar, abgesehen von einem leicht unterschiedlichen Bereich der abgetasteten Werte.
plt.plot(distances, vqe_energies, label="VQE Energy")
plt.xlabel("Atomic distance (Angstrom)")
plt.ylabel("Energy")
plt.legend()
plt.show()Output:
Zusätzlich zu der erwarteten H2 Bindungslänge von 0.74 Angström sollte die Gesamtenergie -1.17 Hartrees betragen. Wir sehen, dass die realen Hardware-Ergebnisse näher an diesen Werten liegen als die des Simulators. Dies ist wahrscheinlich darauf zurückzuführen, dass in beiden Fällen Rauschen vorhanden war (oder simuliert wurde), aber nur im Fall von echter Hardware wurde eine Fehlerbegrenzung vorgenommen.
Wird geschlossen
Damit ist unser Kurs über VQE für die Quantenchemie abgeschlossen. Wenn Sie daran interessiert sind, die dem Quantencomputing zugrunde liegende Informationstheorie zu verstehen, sollten Sie sich den Kurs von John Watrous über die Grundlagen der Quanteninformation ansehen. Ein weiteres kurzes Beispiel für einen VQE-Arbeitsablauf finden Sie in unserem Tutorial zur Abschätzung der Grundzustandsenergie der Heisenberg-Kette mit VQE. Oder stöbern Sie in den Tutorien und Kursen, um weiteres Lehrmaterial über die neueste Technologie im Quantencomputing zu finden.
Vergessen Sie nicht, die Prüfung für diesen Kurs abzulegen. Bei einer Punktzahl von 80 % oder mehr erhalten Sie ein Credly-Abzeichen, das Ihnen automatisch per E-Mail zugeschickt wird. Vielen Dank, dass Sie Teil des IBM Quantum® Network sind!
import qiskit
import qiskit_ibm_runtime
print(qiskit.version.get_version_info())
print(qiskit_ibm_runtime.version.get_version_info())Output:
1.3.2
0.35.0