Détermination d'une géométrie moléculaire
Dans la section précédente, nous avons mis en œuvre VQE pour déterminer l'énergie de l'état fondamental d'une molécule. Il s'agit là d'une utilisation valable de l'informatique quantique, mais il serait encore plus utile de déterminer la structure d'une molécule.
Étape 1 : Mettre en correspondance les entrées classiques avec un problème quantique
En restant dans notre exemple de base de l'hydrogène diatomique, le seul paramètre géométrique à faire varier est la longueur de la liaison. Pour ce faire, nous procédons comme précédemment, mais en utilisant une variable dans notre construction initiale de la molécule (une longueur de liaison, x, dans l'argument). Il s'agit d'un changement assez simple, mais qui exige que la variable soit incluse dans les fonctions tout au long du processus, puisqu'elle commence dans la construction du hamiltonien fermionique et se propage à travers la cartographie et enfin dans la fonction de coût.
Tout d'abord, nous chargeons certains des paquets que nous avons utilisés précédemment et nous définissons la fonction Cholesky.
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_listPour définir notre hamiltonien, nous utiliserons PySCF exactement comme dans l'exemple précédent, mais nous inclurons maintenant une variable, x, qui jouera le rôle de notre distance interatomique. Cette opération renvoie l'énergie du noyau, l'énergie d'un seul électron et l'énergie de deux électrons comme précédemment.
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, h2eRappelons que la construction ci-dessus consiste à créer un hamiltonien fermionique basé sur l'espèce atomique, la géométrie et les orbitales électroniques. Ci-dessous, nous mettons en correspondance cet hamiltonien fermionique avec les opérateurs de Pauli. Cette fonction build_hamiltonian comprendra également une variable géométrique comme argument.
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()Nous chargerons les paquets restants pour exécuter VQE lui-même, tels que l'ansatz efficient_su2 et les minimiseurs SciPy :
# 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()Nous allons à nouveau définir la fonction de coût, mais celle-ci prend toujours comme argument un hamiltonien entièrement construit et cartographié, de sorte que rien ne change à propos de cette fonction.
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 energyÉtape 2 : Optimiser le problème pour l'exécution quantique
Comme l'hamiltonien change à chaque nouvelle géométrie, le transpiling de l'opérateur change à chaque étape. Nous pouvons néanmoins définir un gestionnaire de passe général à appliquer à chaque étape, spécifique au matériel que nous voulons utiliser.
Nous utiliserons ici le backend le moins chargé disponible. Nous utiliserons ce backend comme modèle pour notre AerSimulator,, ce qui permettra à notre simulateur d'imiter, par exemple, le comportement du backend réel en matière de bruit. Ces modèles de bruit ne sont pas parfaits, mais ils peuvent vous aider à savoir à quoi vous attendre avec du matériel réel.
# 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)Nous importons le gestionnaire de passes et les paquets connexes pour nous aider à optimiser notre circuit. Cette étape, et celle qui la précède, sont indépendantes de l'hamiltonien et sont donc inchangées par rapport à la leçon précédente.
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,
),
]
)Étape 3 : Exécuter à l'aide des primitives de l' IBM Quantum.
Dans le bloc de code ci-dessous, nous définissons un tableau destiné à stocker les résultats obtenus à chaque étape de notre calcul de distance interatomique . Nous avons choisi l'intervalle de valeurs en nous basant sur la valeur expérimentale de la longueur de liaison à l'équilibre : 0.74 angströms. Nous allons d'abord l'exécuter sur un simulateur, et nous allons donc importer notre Estimator ( BackendEstimator ) depuis qiskit.primitives. Pour chaque étape géométrique, nous construisons l'hamiltonien et effectuons un certain nombre d'itérations d'optimisation (ici 500) à l'aide de l'optimiseur « cobyla ». À chaque étape de la modélisation géométrique, nous enregistrons à la fois l'énergie totale et l'énergie électronique. En raison du nombre élevé d'étapes de l'optimiseur, cette opération peut prendre une heure, voire plus. Vous pouvez modifier les données ci-dessous afin de réduire le temps nécessaire.
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)
Les résultats de cette simulation sont abordés ci-dessous dans la section consacrée au post-traitement; pour l'instant, notons simplement que la simulation s'est déroulée avec succès. Vous êtes désormais prêt à exécuter le programme sur du matériel réel. Nous allons définir la résilience sur 1, ce qui indique que le mécanisme d'atténuation des erreurs TREX sera utilisé. Maintenant que nous travaillons avec du matériel réel, nous allons utiliser le service de calcul IBM Quantum et les primitives IBM Quantum. Notez que tant la boucle « for » relative à la géométrie que les multiples essais variationnels se trouvent à l'intérieur de la session.
En raison des coûts et des délais associés à l'utilisation de matériel réel, nous avons réduit le nombre d'étapes géométriques et d'étapes d'optimisation ci-dessous. Veillez à adapter ces étapes en fonction de vos objectifs de précision et des délais impartis.
# 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")Étape 4 : Post-traitement
Tant pour le simulateur que pour le matériel réel, nous pouvons tracer les énergies de l'état fondamental calculées pour chaque distance inter-atomique et voir où l'énergie la plus basse est atteinte. C'est la distance interatomique que l'on trouve dans la nature, et elle est en effet très proche. Une courbe plus régulière pourrait être obtenue en essayant d'autres réponses, d'autres optimiseurs et en effectuant le calcul plusieurs fois à chaque étape de la géométrie et en calculant la moyenne sur plusieurs conditions initiales aléatoires.
# 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:
Il est à noter que le simple fait d'augmenter le nombre d'étapes d'optimisation n'est pas susceptible d'améliorer les résultats du simulateur, puisque toutes les optimisations ont convergé vers la tolérance requise en moins de temps que le nombre maximum d'itérations.
Les résultats obtenus avec le matériel réel sont comparables, à l'exception d'une gamme de valeurs échantillonnées légèrement différente.
plt.plot(distances, vqe_energies, label="VQE Energy")
plt.xlabel("Atomic distance (Angstrom)")
plt.ylabel("Energy")
plt.legend()
plt.show()Output:
En plus d'attendre une longueur de liaison H2 de 0.74 Angstrom, l'énergie totale devrait être de -1.17 Hartrees. Nous constatons que les résultats du matériel réel sont plus proches de ces valeurs que ceux du simulateur. Cela est probablement dû au fait que le bruit était présent (ou simulé) dans les deux cas, mais ce n'est que dans le cas du matériel réel que des mesures d'atténuation des erreurs ont été employées.
Fermeture en cours
Ceci conclut notre cours sur le VQE pour la chimie quantique. Si vous souhaitez comprendre la théorie de l'information sous-jacente utilisée dans l'informatique quantique, consultez le cours de John Watrous sur les bases de l'information quantique. Pour un exemple plus court d'un flux de travail VQE, voir notre tutoriel sur l'estimation de l'énergie de l'état fondamental de la chaîne de Heisenberg à l'aide de VQE. Vous pouvez également consulter les didacticiels et les cours pour trouver d'autres supports pédagogiques sur les dernières technologies en matière d'informatique quantique.
N'oubliez pas de passer l'examen de ce cours. Un score de 80 % ou plus vous permettra d'obtenir un badge Credly, qui vous sera automatiquement envoyé par courrier électronique. Merci de faire partie du réseau IBM Quantum®!
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