Hamilton-Operatoren für die Quantenchemie
Beginnen wir mit einem kurzen Überblick über die Rolle, die Hamiltonianer in der VQE spielen.
Der Hamilton-Operator in VQE – Überblick
Dr. Victoria Lipinska erklärt uns die Hamiltonianer und wie man sie für den Einsatz im Quantencomputing abbildet.
Referenzen
Auf die folgenden Artikel wird in dem obigen Video Bezug genommen.
- Quantenalgorithmen für Fermionensimulationen, Ortiz et al.
- Simulation chemischer Vorgänge mit Quantencomputern, Kassal et al.
- Ein Vergleich der Bravyi-Kitaev- und der Jordan-Wigner-Transformation für die Quantensimulation in der Quantenchemie, Tranter et al.
- Quantenchemie im Zeitalter des Quantencomputings, Cao et al.
- Quantenchemie, McArdle, et al.
- Die Bravyi-Kitaev-Transformation für die Quantencomputierung der elektronischen Struktur, Seeley et al.
Vorbereitung der Hamilton-Funktion für die Quantenchemie
Ein guter erster Schritt bei der Anwendung von Quantencomputing auf ein chemisches Problem ist die Definition eines Hamiltonian für das betreffende System. Hier beschränken wir uns auf die Hamiltonianer der Quantenchemie, da diese Hamiltonianer einige spezifische Abbildungen für Systeme mit identischen Fermionen erfordern.
Als jemand, der in der Quantenchemie arbeitet, haben Sie wahrscheinlich bereits Ihre Lieblingssoftware für die Modellierung von Molekülen, mit der Sie einen Hamiltonian erzeugen können, der Ihr System von Interesse beschreibt. Hier werden wir Code verwenden, der ausschließlich auf PySCF, numpy und Qiskit basiert. Der Prozess der Hamiltonianischen Vorbereitung lässt sich jedoch auch auf vorgefertigte Lösungen übertragen. Der einzige Unterschied zwischen diesem Ansatz und anderer Software sind geringfügige Unterschiede in der Syntax; einige dieser Unterschiede werden im Unterabschnitt "Software von Drittanbietern" behandelt, um die Integration bestehender Arbeitsabläufe zu erleichtern.
Die Generierung eines quantenchemischen Hamiltonianers zur Verwendung auf IBM Quantum® QPUs umfasst die folgenden Schritte:
- Definieren Sie Ihr Molekül (Geometrie, Spin, aktiver Raum, usw.)
- Generierung des fermionischen Hamiltonianers (Erzeugungs- und Annihilationsoperatoren)
- Abbildung des fermionischen Hamiltonianers auf einen bosonischen Operator (in diesem Zusammenhang unter Verwendung von Pauli-Operatoren)
- Bei Verwendung von Software von Drittanbietern: Behandeln Sie alle Syntaxabweichungen zwischen der generierenden Software und Qiskit
Der fermionische Hamiltonian wird in Form von fermionischen Operatoren geschrieben und berücksichtigt insbesondere, dass Elektronen ununterscheidbare Fermionen sind. Das bedeutet, dass sie einer völlig anderen Statistik gehorchen als unterscheidbare bosonische Qubits. Daraus ergibt sich der Mapping-Prozess.
Diejenigen unter Ihnen, die mit diesen Verfahren bereits vertraut sind, können diesen Abschnitt wahrscheinlich überspringen.
Ziel:
Das Ziel ist es, einen Hamiltonian der Form zu erhalten:
H = [(1, "XX"), (1, "YY"), (1, "ZZ")]
print(H)Output:
[(1, 'XX'), (1, 'YY'), (1, 'ZZ')]
Oder
from qiskit.quantum_info import SparsePauliOp
H = SparsePauliOp(["XX", "YY", "ZZ"], coeffs=[1.0 + 0.0j, 1.0 + 0.0j, 1.0 + 0.0j])
print(H)Output:
SparsePauliOp(['XX', 'YY', 'ZZ'],
coeffs=[1.+0.j, 1.+0.j, 1.+0.j])
Wir beginnen damit, einige Pakete zu importieren:
import numpy as np
from pyscf import ao2mo, gto, mcscf, scf- Definieren Sie Ihr Molekül
Hier geben wir die Attribute des Moleküls von Interesse an. In diesem Beispiel haben wir uns für zweiatomigen Wasserstoff entschieden (weil die resultierenden Hamiltonians kurz genug sind, um sie anzuzeigen).
Das auf der „ Python “ basierende „Simulations of Chemistry Framework“ ( PySCF ) verfügt über eine umfangreiche Sammlung von Modulen zur Berechnung der elektronischen Struktur, mit denen unter anderem für die Quantenberechnung geeignete molekulare Hamilton-Operatoren generiert werden können. Die Schnellstartanleitung zu „ PySCF “ ist eine hervorragende Quelle für eine umfassende Beschreibung aller Variablen und Funktionen. Wir werden nur einen ganz kurzen Überblick geben, da dies vielen von Ihnen bereits bekannt sein dürfte. Um diese besser zu verstehen, besuchen Sie PySCF. Kurz gesagt:
abstand kann für zweiatomige Moleküle verwendet werden, oder man gibt einfach kartesische Koordinaten für jedes Atom an. Die Abstände sind in der Einheit Angström angegeben.
gto erzeugt Orbitale vom Gauß-Typ.
basis bezieht sich auf die Funktionen, die zur Modellierung von Molekülorbitalen verwendet werden. Hier ist " sto-6g " eine gängige Minimalbasis, die für die Anpassung von Slater-Orbitalen unter Verwendung von 6 primitiven Gauß-Orbitalen benannt wurde.
spin ein ganzzahliger Wert, der die Anzahl der ungepaarten Elektronen angibt (gleich ). Beachten Sie, dass manche Software stattdessen die Multiplizität verwendet ( ).
ladung die Ladung des Moleküls.
symmetrie - die Punktsymmetriegruppe des Moleküls, die entweder mit einer Zeichenkette angegeben oder durch die Einstellung "Symmetrie = Wahr" automatisch erkannt wird. Hier ist "Dooh" die geeignete Symmetriegruppe für zweiatomige Moleküle mit zwei gleichen Atomsorten.
distance = 0.735
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",
)Output:
<pyscf.gto.mole.Mole at 0x7fc718f07610>
Denken Sie daran, dass man die Gesamtenergie (die sowohl die nukleare als auch die elektronische Abstoßungsenergie umfasst), die gesamte elektronische Orbitalenergie oder die Energie einer Teilmenge elektronischer Orbitale beschreiben kann (wobei die komplementäre Teilmenge eingefroren wird). Im speziellen Fall von sind die verschiedenen Energien unten aufgeführt, und es ist zu beachten, dass die Gesamtenergie abzüglich der Kernabstoßungsenergie tatsächlich die elektronische Energie ergibt:
mf = scf.RHF(mol)
mf.scf()
print(
mf.energy_nuc(),
mf.energy_elec()[0],
mf.energy_tot(),
mf.energy_tot() - mol.energy_nuc(),
)Output:
0.7199689944489797 -1.8455976628764188 -1.125628668427439 -1.8455976628764188
active_space = range(mol.nelectron // 2 - 1, mol.nelectron // 2 + 1)- Erzeugung eines fermionischen Hamiltonianers
scf bezieht sich auf eine breite Palette von selbstkonsistenten Feldmethoden.
rhf wie in mf = scf.RHF (mol) in mf ist ein Solver, der die Restricted Hartree Fock Berechnung verwendet. Der Kern (E, unten) ist die Gesamtenergie, einschließlich der Kernabstoßung und der Molekularorbitale.
mcscf ist ein Paket für selbstkonsistente Felder mit mehreren Konfigurationen.
ao2mo ist eine Umwandlung von Atomorbitalen in Molekülorbitale.
Wir verwenden auch die folgenden Variablen:
ncas : Anzahl der Orbitale im gesamten aktiven Raum
nelecas : Anzahl der Elektronen im gesamten aktiven Raum
E1 = mf.kernel()
mx = mcscf.CASCI(mf, ncas=2, nelecas=(1, 1))
mo = mx.sort_mo(active_space, base=0)
E2 = mx.kernel(mo)[:2]Wir wollen einen Hamiltonian, und dieser wird oft in die Energie eines elektronischen Kerns (ecore, nicht an der Minimierung beteiligt), Ein-Elektronen-Operatoren ( h1e ) und Zwei-Elektronen-Energien ( h2e ) aufgeteilt. Diese werden in den letzten beiden Zeilen explizit extrahiert.
h1e, ecore = mx.get_h1eff()
h2e = ao2mo.restore(1, mx.get_h2eff(), mx.ncas)Diese Hamiltonianer sind derzeit fermionische Operatoren (Erzeugungs- und Vernichtungsoperatoren), die auf Systeme von (ununterscheidbaren) Fermionen anwendbar sind und dementsprechend einer Antisymmetrie beim Austausch unterliegen. Dies führt zu einer anderen Statik als bei einem unterscheidbaren oder bosonischen System. Um Berechnungen auf IBM Quantum QPUs durchzuführen, benötigen wir einen bosonischen Operator, der die Energie beschreibt. Das Ergebnis einer solchen Abbildung wird üblicherweise in Form von Pauli-Operatoren geschrieben, da diese sowohl hermitesch als auch unitär sind. Es gibt verschiedene Zuordnungen, die man verwenden kann. Eine der einfachsten ist die Jordan-Wigner-Transformation.
- Abbildung des Hamiltonianers
Es sei darauf hingewiesen, dass es viele Hilfsmittel gibt, um einen chemischen Hamiltonian in einen für einen Quantencomputer geeigneten abzubilden. Hier implementieren wir die Jordan-Wigner-Zuordnung direkt und verwenden nur PySCF, numpy und Qiskit. Im Folgenden werden Überlegungen zur Syntax bei anderen Lösungen angestellt.
Mit Hilfe der Cholesky-Funktion erhalten wir eine Zerlegung der Zwei-Elektronen-Terme im Hamiltonian mit niedrigem Rang.
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, ngDie Funktionen identity und creators_destructors ersetzen Schöpfungs- und Annihilationsoperatoren im fermionischen Hamiltonian durch Pauli-Operatoren; creators_destructors verwendet die Jordan-Wigner-Abbildung.
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_listSchließlich verwendet build_hamiltonian die Funktionen cholesky, identity und creators_destructors , um den endgültigen Hamiltonian zu erstellen, der auf einem Quantencomputer ausgeführt werden kann.
def build_hamiltonian(ecore: float, h1e: np.ndarray, h2e: np.ndarray) -> SparsePauliOp:
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()Schließlich verwenden wir build_hamiltonian , um unseren Qubit-Hamiltonianer aus Pauli-Operatoren unter Verwendung der Jordan-Wigner-Transformation zu konstruieren. Daraus ergibt sich auch die Genauigkeit der von uns verwendeten Cholesky-Zerlegung.
H = build_hamiltonian(ecore, h1e, h2e)
print(H)Output:
accuracy of Cholesky decomposition 2.220446049250313e-16
SparsePauliOp(['IIII', 'IIIZ', 'IZII', 'IIZI', 'ZIII', 'IZIZ', 'IIZZ', 'ZIIZ', 'IZZI', 'ZZII', 'ZIZI', 'YYYY', 'XXYY', 'YYXX', 'XXXX'],
coeffs=[-0.09820182+0.j, -0.1740751 +0.j, -0.1740751 +0.j, 0.2242933 +0.j,
0.2242933 +0.j, 0.16891402+0.j, 0.1210099 +0.j, 0.16631441+0.j,
0.16631441+0.j, 0.1210099 +0.j, 0.17504456+0.j, 0.04530451+0.j,
0.04530451+0.j, 0.04530451+0.j, 0.04530451+0.j])
Dieses Beispielmolekül-Notizbuch zeigt den Aufbau und die Hamiltonians für mehrere Moleküle unterschiedlicher Komplexität; mit ein paar Modifikationen sollten Sie damit die meisten kleinen Moleküle untersuchen können.
Lassen Sie uns kurz zwei wichtige Punkte anmerken, die bei der Konstruktion der fermionischen Operatoren für ein Molekül zu beachten sind. Wenn sich der Molekültyp ändert, ändert sich auch die Symmetrie. Auch die Anzahl der Orbitale mit verschiedenen Symmetrien, wie dem zylindersymmetrischen " A1 ", ändert sich. Diese Veränderungen sind selbst bei der einfachen Erweiterung auf LiH,, wie hier zu sehen, offensichtlich:
distance = 1.56
mol = gto.Mole()
mol.build(
verbose=0,
atom=[["Li", (0, 0, 0)], ["H", (0, 0, distance)]],
basis="sto-6g",
spin=0,
charge=0,
symmetry="Coov",
)
mf = scf.RHF(mol)
E1 = mf.kernel()
# %% ----------------------------------------------------------------------------------------------
mx = mcscf.CASCI(mf, ncas=5, nelecas=(1, 1))
cas_space_symmetry = {"A1": 3, "E1x": 1, "E1y": 1}
mo = mcscf.sort_mo_by_irrep(mx, mf.mo_coeff, cas_space_symmetry)
E2 = mx.kernel(mo)[:2]
h1e, ecore = mx.get_h1eff()
h2e = ao2mo.restore(1, mx.get_h2eff(), mx.ncas)Es ist auch erwähnenswert, dass man schnell die Intuition für den resultierenden Hamiltonian verlieren kann. Der Hamiltonian für LiH (unter Verwendung des Jordan-Wigner-Mappers) besteht bereits aus 276 Termen.
len(build_hamiltonian(ecore, h1e, h2e))Output:
accuracy of Cholesky decomposition 1.1102230246251565e-16
276
Im Zweifelsfall kann man auch einige Symmetrieinformationen für das Molekül erzeugen, indem man symmetry = True und verbose = 4 setzt:
distance = 1.56
mol = gto.Mole()
mol.build(
verbose=4,
atom=[["Li", (0, 0, 0)], ["H", (0, 0, distance)]],
basis="sto-6g",
spin=0,
charge=0,
symmetry=True,
)Output:
System: uname_result(system='Linux', node='IBM-R912JTRT', release='5.10.102.1-microsoft-standard-WSL2', version='#1 SMP Wed Mar 2 00:30:59 UTC 2022', machine='x86_64') Threads 16
Python 3.11.12 (main, May 16 2025, 02:33:32) [GCC 11.4.0]
numpy 2.3.1 scipy 1.16.0 h5py 3.14.0
Date: Mon Jun 30 12:56:55 2025
PySCF version 2.9.0
PySCF path /home/porter284/.pyenv/versions/3.11.12/lib/python3.11/site-packages/pyscf
[CONFIG] conf_file None
[INPUT] verbose = 4
[INPUT] num. atoms = 2
[INPUT] num. electrons = 4
[INPUT] charge = 0
[INPUT] spin (= nelec alpha-beta = 2S) = 0
[INPUT] symmetry True subgroup None
[INPUT] Mole.unit = angstrom
[INPUT] Symbol X Y Z unit X Y Z unit Magmom
[INPUT] 1 Li 0.000000000000 0.000000000000 0.000000000000 AA 0.000000000000 0.000000000000 0.000000000000 Bohr 0.0
[INPUT] 2 H 0.000000000000 0.000000000000 1.560000000000 AA 0.000000000000 0.000000000000 2.947972754321 Bohr 0.0
nuclear repulsion = 1.01764848253846
point group symmetry = Coov
symmetry origin: [0. 0. 0.73699319]
symmetry axis x: [1. 0. 0.]
symmetry axis y: [0. 1. 0.]
symmetry axis z: [0. 0. 1.]
num. orbitals of irrep A1 = 4
num. orbitals of irrep E1x = 1
num. orbitals of irrep E1y = 1
number of shells = 4
number of NR pGTOs = 36
number of NR cGTOs = 6
basis = sto-6g
ecp = {}
CPU time: 9.85
<pyscf.gto.mole.Mole at 0x7fc719f94850>
Neben anderen nützlichen Informationen liefert dies sowohl point group symmetry = Coov als auch die Anzahl der Orbitale in jeder irreduziblen Darstellung.
point group symmetry = Coov
num. orbitals of irrep A1 = 4
num. orbitals of irrep E1x = 1
num. orbitals of irrep E1y = 1
number of shells = 4
Dies sagt nicht unbedingt etwas darüber aus, wie viele Orbitale Sie in Ihrem aktiven Raum haben wollen, aber es hilft Ihnen zu sehen, welche Orbitale vorhanden sind und welche Symmetrien sie haben.
Die Angabe von Symmetrie und Orbitalen ist oft hilfreich, aber Sie können auch die Anzahl der Orbitale angeben, die Sie einbeziehen möchten. Betrachten Sie den Fall von Ethen (siehe unten). Mit verbose = 4 können wir die Symmetrien der verschiedenen Orbitale ausdrucken:
# Replace these variables with correct distances:
a = 1
b = 1
c = 1
# Build
mol = gto.Mole()
mol.build(
verbose=4,
atom=[
["C", (0, 0, a)],
["C", (0, 0, -a)],
["H", (0, c, b)],
["H", (0, -c, b)],
["H", (0, c, -b)],
["H", (0, -c, -b)],
],
basis="sto-6g",
spin=0,
charge=0,
symmetry=True,
)Output:
System: uname_result(system='Linux', node='IBM-R912JTRT', release='5.10.102.1-microsoft-standard-WSL2', version='#1 SMP Wed Mar 2 00:30:59 UTC 2022', machine='x86_64') Threads 16
Python 3.11.12 (main, May 16 2025, 02:33:32) [GCC 11.4.0]
numpy 2.3.1 scipy 1.16.0 h5py 3.14.0
Date: Mon Jun 30 12:57:07 2025
PySCF version 2.9.0
PySCF path /home/porter284/.pyenv/versions/3.11.12/lib/python3.11/site-packages/pyscf
[CONFIG] conf_file None
[INPUT] verbose = 4
[INPUT] num. atoms = 6
[INPUT] num. electrons = 16
[INPUT] charge = 0
[INPUT] spin (= nelec alpha-beta = 2S) = 0
[INPUT] symmetry True subgroup None
[INPUT] Mole.unit = angstrom
[INPUT] Symbol X Y Z unit X Y Z unit Magmom
[INPUT] 1 C 0.000000000000 0.000000000000 1.000000000000 AA 0.000000000000 0.000000000000 1.889726124565 Bohr 0.0
[INPUT] 2 C 0.000000000000 0.000000000000 -1.000000000000 AA 0.000000000000 0.000000000000 -1.889726124565 Bohr 0.0
[INPUT] 3 H 0.000000000000 1.000000000000 1.000000000000 AA 0.000000000000 1.889726124565 1.889726124565 Bohr 0.0
[INPUT] 4 H 0.000000000000 -1.000000000000 1.000000000000 AA 0.000000000000 -1.889726124565 1.889726124565 Bohr 0.0
[INPUT] 5 H 0.000000000000 1.000000000000 -1.000000000000 AA 0.000000000000 1.889726124565 -1.889726124565 Bohr 0.0
[INPUT] 6 H 0.000000000000 -1.000000000000 -1.000000000000 AA 0.000000000000 -1.889726124565 -1.889726124565 Bohr 0.0
nuclear repulsion = 29.3377079104231
point group symmetry = D2h
symmetry origin: [0. 0. 0.]
symmetry axis x: [0. 1. 0.]
symmetry axis y: [1. 0. 0.]
symmetry axis z: [-0. -0. -1.]
num. orbitals of irrep Ag = 4
num. orbitals of irrep B2g = 2
num. orbitals of irrep B3g = 1
num. orbitals of irrep B1u = 4
num. orbitals of irrep B2u = 1
num. orbitals of irrep B3u = 2
number of shells = 10
number of NR pGTOs = 84
number of NR cGTOs = 14
basis = sto-6g
ecp = {}
CPU time: 9.92
<pyscf.gto.mole.Mole at 0x7fc719fa9290>
Wir erhalten:
anzahl der Orbitale des Irrep Ag = 4
anzahl der Orbitale des Irrep B2g = 2
anzahl der Orbitale des Irrep B3g = 1
anzahl der Orbitale des Irrep B1u = 4
anzahl der Orbitale des Irrep B2u = 1
anzahl der Orbitale des Irrep B3u = 2
Anstatt jedoch alle Orbitale durch die Symmetrie zu spezifizieren, können wir einfach schreiben:
active_space = range(mol.nelectron // 2 - 2, mol.nelectron // 2 + 2)Bei diesem Ansatz nehmen wir mehrere Orbitale in der Nähe des Füllungsniveaus (Valenz und unbesetzt). Hier wurden 5 Orbitale zur Aufnahme in den aktiven Raum ausgewählt (das 6. bis 10.).
print(
mol.nelectron // 2 - 2,
mol.nelectron // 2 + 2,
)Output:
6 10
- Software anderer Anbieter
Es gibt mehrere Softwarepakete für die Quantenchemie, von denen einige mehrere Mapper und Werkzeuge zur Einschränkung aktiver Räume anbieten. Die oben beschriebenen Schritte sind allgemein und gelten auch für Software von Drittanbietern. Diese andere Software kann jedoch Hamiltonians in einem Format zurückgeben, das von Qiskit nicht akzeptiert wird. Manche Software liefert zum Beispiel Hamiltonianer der Form:
H = -0.042 [] + -0.045 [X0 X1 Y2 Y3] + ... + 0.178 [Z0] + ... + 0.176 [Z2 Z3] + -0.243 [Z3]
Beachten Sie insbesondere, dass die Gatter nummeriert sind und die Identitätsoperatoren nicht dargestellt sind. Dies steht im Gegensatz zu den in Qiskit verwendeten Hamiltonianern, bei denen der Begriff [Z2 Z3] als ZZII geschrieben wird (auf die Qubits 0 und 1 wirkt der Identitätsoperator, auf die Qubits 2 und 3 wirkt der Z-Operator, wobei das Qubit 0 am weitesten rechts liegt).
Um alle vorhandenen Workstreams zu berücksichtigen, konvertiert der folgende Codeblock von einer Syntax in die andere. Die Funktion convert_openfermion_to_qiskit nimmt als Argumente einen Hamiltonian, der in OpenFermion oder Tangelo generiert wurde (und bereits mit einem beliebigen verfügbaren Mapper auf Pauli-Operatoren abgebildet wurde), und die Anzahl der für das Molekül benötigten Qubits.
from openfermion import QubitOperator
from qiskit.quantum_info import SparsePauliOp
def convert_openfermion_to_qiskit(
openfermion_operator: QubitOperator, num_qubits: int
) -> SparsePauliOp:
terms = openfermion_operator.terms
labels = []
coefficients = []
for term, constant in terms.items():
# Default set to identity
operator = list("I" * num_qubits)
# Iterate through PauliSum and replace I with Pauli
for index, pauli in term:
operator[index] = pauli
label = "".join(operator)
labels.append(label)
coefficients.append(constant)
return SparsePauliOp(labels, coefficients)Darüber hinaus enthält dieses Python Notizbuch einen vollständigen Beispielcode für die Migration von Hamiltonians aus anderen Software-Workflows in Qiskit, einschließlich der oben beschriebenen Konvertierung.
Sie sollten nun über ein ganzes Arsenal von Werkzeugen verfügen, um den Hamiltonian zu erhalten, den Sie für quantenchemische Berechnungen auf IBM® Quantencomputern benötigen.