Zum Hauptinhalt springen

Hamiltonoperatoren für die Quantenchemie

Beginnen wir mit einem kurzen Überblick über die Rolle, die Hamiltonoperatoren im VQE spielen.

Überblick: Der Hamiltonoperator im VQE

Dr. Victoria Lipinska führt uns durch Hamiltonoperatoren und erklärt, wie sie für den Einsatz im Quantencomputing gemappt werden.

Referenzen

Die folgenden Artikel werden im obigen Video referenziert.

Hamiltonoperatoren für die Quantenchemie vorbereiten

Ein guter erster Schritt bei der Anwendung von Quantencomputing auf ein Chemieproblem ist die Definition eines Hamiltonoperators für das betrachtete System. Wir beschränken uns hier auf quantenchemische Hamiltonoperatoren, da diese ein spezielles Mapping für Systeme identischer Fermionen erfordern.

Als jemand, der in der Quantenchemie arbeitet, hast du wahrscheinlich bereits deine bevorzugte Software zur Modellierung von Molekülen, mit der ein Hamiltonoperator generiert werden kann, der dein System von Interesse beschreibt. Hier verwenden wir Code, der ausschließlich auf PySCF, numpy und Qiskit aufbaut. Der Prozess der Hamiltonoperator-Vorbereitung lässt sich jedoch auch auf vorgefertigte Lösungen übertragen. Der einzige Unterschied zwischen diesem Ansatz und anderer Software liegt in kleinen Syntaxunterschieden; einige davon werden im Unterabschnitt „Software von Drittanbietern" behandelt, um die Integration bestehender Arbeitsabläufe zu erleichtern.

Die Generierung eines quantenchemischen Hamiltonoperators für den Einsatz auf IBM Quantum® QPUs umfasst die folgenden Schritte:

  1. Definiere dein Molekül (Geometrie, Spin, aktiver Raum usw.)
  2. Generiere den fermionischen Hamiltonoperator (Erzeugungs- und Vernichtungsoperatoren)
  3. Bilde den fermionischen Hamiltonoperator auf einen bosonischen Operator ab (in diesem Kontext mittels Pauli-Operatoren)
  4. Bei Verwendung von Drittanbieter-Software: Behandle eventuelle Syntaxunterschiede zwischen der generierenden Software und Qiskit

Der fermionische Hamiltonoperator wird in Form von Fermionenoperatoren geschrieben und berücksichtigt insbesondere, dass Elektronen ununterscheidbare Fermionen sind. Das bedeutet, sie gehorchen einer völlig anderen Statistik als unterscheidbare, bosonische Qubits. Daher ist das Mapping notwendig.

Wer mit diesen Prozessen bereits vertraut ist, kann diesen Abschnitt wahrscheinlich überspringen. Ziel:

Das Endziel ist es, einen Hamiltonoperator der folgenden Form zu erhalten:

# Added by doQumentation — required packages for this notebook
!pip install -q numpy openfermion pyscf qiskit
H = [(1, "XX"), (1, "YY"), (1, "ZZ")]
print(H)
[(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)
SparsePauliOp(['XX', 'YY', 'ZZ'],
coeffs=[1.+0.j, 1.+0.j, 1.+0.j])

Wir beginnen mit dem Importieren einiger Pakete:

import numpy as np
from pyscf import ao2mo, gto, mcscf, scf
  1. Definiere dein Molekül

Hier legen wir die Eigenschaften des betrachteten Moleküls fest. In diesem Beispiel haben wir zweiatomigen Wasserstoff gewählt (da die resultierenden Hamiltonoperatoren kurz genug sind, um angezeigt zu werden). Das Python-basierte Simulations-Framework für Chemie (PySCF) bietet eine umfangreiche Sammlung von Elektronenstrukturmodulen, die unter anderem zur Generierung von Molekül-Hamiltonoperatoren für Quantenberechnungen eingesetzt werden können. Der PySCF-Quickstart-Guide ist eine ausgezeichnete Ressource für eine vollständige Beschreibung aller Variablen und Funktionen. Wir geben hier nur einen knappen Überblick, da dies vielen von euch bereits bekannt sein dürfte. Um mehr zu erfahren, besuche PySCF. Kurz zusammengefasst:

distance kann für zweiatomige Moleküle verwendet werden, oder gib einfach kartesische Koordinaten für jedes Atom an. Abstände sind in Ångström angegeben.

gto generiert Gauß-artige Orbitale.

basis bezieht sich auf die Funktionen, die zur Modellierung von Molekülorbitalen verwendet werden. Hier ist 'sto-6g' eine verbreitete minimale Basis, benannt nach der Anpassung von Slater-Typ-Orbitalen mit 6 primitiven Gauß-Orbitalen.

spin ein ganzzahliger Wert, der die Anzahl der ungepaarten Elektronen angibt (entspricht 2S2S). Beachte, dass manche Software stattdessen die Multiplizität verwendet (2S+12S+1).

charge die Ladung des Moleküls.

symmetry - die Punktsymmetriegruppe des Moleküls, entweder als String angegeben oder durch Setzen von "symmetry = True" automatisch erkannt. "Dooh" ist die passende Symmetriegruppe für zweiatomige Moleküle mit zwei Atomen derselben Spezies.

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",
)
<pyscf.gto.mole.Mole at 0x7fc718f07610>

Beachte, dass man die Gesamtenergie (die auch die Kernabstoßungsenergie sowie die elektronische Energie umfasst), die gesamte elektronische Orbitalenergie oder die Energie einer Teilmenge der elektronischen Orbitale (wobei die komplementäre Teilmenge eingefroren ist) beschreiben kann. Im speziellen Fall von H2\text{H}_2 sind die verschiedenen Energien unten aufgeführt; die Gesamtenergie abzüglich der Kernabstoßungsenergie ergibt tatsächlich die elektronische Energie:

mf = scf.RHF(mol)
mf.scf()

print(
mf.energy_nuc(),
mf.energy_elec()[0],
mf.energy_tot(),
mf.energy_tot() - mol.energy_nuc(),
)
0.7199689944489797 -1.8455976628764188 -1.125628668427439 -1.8455976628764188
active_space = range(mol.nelectron // 2 - 1, mol.nelectron // 2 + 1)
  1. Generiere den fermionischen Hamiltonoperator

scf bezieht sich auf eine breite Palette von Self-Consistent-Field-Methoden.

rhf wie in mf = scf.RHF(mol): mf ist ein Solver, der die eingeschränkte Hartree-Fock-Berechnung verwendet. Der Kernel davon (E, unten) ist die Gesamtenergie, einschließlich Kernabstoßung und Molekülorbitale.

mcscf ist ein Multi-Konfiguration-Self-Consistent-Fields-Paket.

ao2mo ist eine Transformation von Atomorbitalen zu Molekülorbitalen.

Wir verwenden auch die folgenden Variablen:

ncas: Anzahl der Orbitale im vollständigen aktiven Raum

nelecas: Anzahl der Elektronen im vollständigen 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 benötigen einen Hamiltonoperator, der oft in die Energie eines elektronischen Kerns (ecore, nicht an der Minimierung beteiligt), Einelektronen-Operatoren (h1e) und Zweielektronen-Energien (h2e) aufgeteilt wird. Diese werden in den letzten beiden Zeilen explizit extrahiert.

h1e, ecore = mx.get_h1eff()
h2e = ao2mo.restore(1, mx.get_h2eff(), mx.ncas)

Diese Hamiltonoperatoren sind derzeit fermionische (Erzeugungs- und Vernichtungs-) Operatoren, die auf Systeme (ununterscheidbarer) Fermionen anwendbar sind und entsprechend der Antisymmetrie unter Austausch unterliegen. Dies führt zu einer anderen Statistik 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 eines solchen Mappings wird konventionell in Form von Pauli-Operatoren geschrieben, da diese sowohl hermitesch als auch unitär sind. Es gibt verschiedene Mappings, die man verwenden kann. Eines der einfachsten ist die Jordan-Wigner-Transformation.

  1. Mapping des Hamiltonoperators

Es sei darauf hingewiesen, dass es viele Tools zur Abbildung eines chemischen Hamiltonoperators auf einen für Quantencomputer geeigneten gibt. Hier implementieren wir das Jordan-Wigner-Mapping direkt, unter ausschließlicher Verwendung von PySCF, numpy und Qiskit. Im Folgenden kommentieren wir Syntaxüberlegungen für andere Lösungen. Die Cholesky-Funktion hilft uns dabei, eine Niedrig-Rang-Zerlegung der Zweielektronenterme im Hamiltonoperator zu erhalten.

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

Die Funktionen identity und creators_destructors ersetzen Erzeugungs- und Vernichtungsoperatoren im fermionischen Hamiltonoperator durch Pauli-Operatoren; creators_destructors verwendet das Jordan-Wigner-Mapping.

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_list

Schließlich verwendet build_hamiltonian die Funktionen cholesky, identity und creators_destructors, um den endgültigen Hamiltonoperator zu erstellen, der für den Einsatz auf einem Quantencomputer geeignet ist.

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()

Abschließend verwenden wir build_hamiltonian, um unseren Qubit-Hamiltonoperator aus Pauli-Operatoren mithilfe der Jordan-Wigner-Transformation zu konstruieren. Dies liefert uns auch die Genauigkeit der verwendeten Cholesky-Zerlegung.

H = build_hamiltonian(ecore, h1e, h2e)
print(H)
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 Beispiel-Molekül-Notebook zeigt die Einrichtung und Hamiltonoperatoren für mehrere Moleküle unterschiedlicher Komplexität; mit wenigen Anpassungen sollte es dir ermöglichen, die meisten kleinen Moleküle zu untersuchen.

Kurz zwei wichtige Punkte, die beim Aufbau der Fermionenoperatoren für ein Molekül zu beachten sind: Wenn sich der Molekültyp ändert, ändert sich auch die Symmetrie. Ebenso ändert sich die Anzahl der Orbitale mit verschiedenen Symmetrien, wie dem zylindrisch symmetrischen „A1". Diese Änderungen sind bereits bei der einfachen Erweiterung auf LiH ersichtlich, wie hier zu sehen:

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 Hamiltonoperator verliert. Der Hamiltonoperator für LiH (mit dem Jordan-Wigner-Mapper) besteht bereits aus 276 Termen.

len(build_hamiltonian(ecore, h1e, h2e))
accuracy of Cholesky decomposition  1.1102230246251565e-16
276

Bei Unsicherheiten bezüglich der Symmetrien kann man auch Symmetrieinformationen für das Molekül generieren, 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,
)
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>

Unter anderem 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 dir nicht unbedingt, wie viele Orbitale du in deinen aktiven Raum aufnehmen möchtest, aber es hilft dir zu erkennen, welche Orbitale vorhanden sind und welche Symmetrien sie haben.

Das Festlegen von Symmetrie und Orbitalen ist oft hilfreich, aber du kannst auch einfach die Anzahl der Orbitale angeben, die du einbeziehen möchtest. Betrachte das Beispiel von Ethen unten. Mit verbose = 4 können wir die Symmetrien der verschiedenen Orbitale ausgeben:

# 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,
)
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:

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

Statt jedoch alle Orbitale nach Symmetrie anzugeben, können wir einfach schreiben:

active_space = range(mol.nelectron // 2 - 2, mol.nelectron // 2 + 2)

Bei diesem Ansatz wählen wir mehrere Orbitale nahe dem Füllungsniveau (Valenz- und unbesetzte Orbitale). Hier wurden 5 Orbitale für die Aufnahme in den aktiven Raum ausgewählt (das 6. bis 10.).

print(
mol.nelectron // 2 - 2,
mol.nelectron // 2 + 2,
)
6 10
  1. Drittanbieter-Software

Es gibt verschiedene Softwarepakete für die Quantenchemie, von denen einige mehrere Mapper und Tools zur Einschränkung aktiver Räume bieten. Die oben beschriebenen Schritte sind allgemein und gelten auch für Drittanbieter-Software. Allerdings kann diese andere Software Hamiltonoperatoren in einem Format zurückgeben, das von Qiskit nicht akzeptiert wird. Zum Beispiel geben manche Programme Hamiltonoperatoren in der folgenden Form zurück:

H = -0.042 [] + -0.045 [X0 X1 Y2 Y3] + ... + 0.178 [Z0] + ... + 0.176 [Z2 Z3] + -0.243 [Z3] Beachte insbesondere, dass die Gates nummeriert sind und Identitätsoperatoren nicht angezeigt werden. Dies steht im Gegensatz zu Hamiltonoperatoren in Qiskit, wo der Term [Z2 Z3] als ZZII geschrieben würde (Qubits 0 und 1 werden durch den Identitätsoperator beeinflusst, Qubits 2 und 3 durch den Z-Operator, mit Qubit 0 ganz rechts).

Um bestehende Arbeitsabläufe zu unterstützen, konvertiert der folgende Codeblock von einer Syntax zur anderen. Die Funktion convert_openfermion_to_qiskit nimmt als Argumente einen in OpenFermion oder Tangelo generierten Hamiltonoperator (der bereits mit einem beliebigen verfügbaren Mapper auf Pauli-Operatoren abgebildet wurde) sowie die Anzahl der für das Molekül benötigten Qubits entgegen.

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-Notebook vollständigen Beispielcode für die Migration von Hamiltonoperatoren aus anderen Software-Workflows nach Qiskit, einschließlich der obigen Konvertierung.

Du hast jetzt eine Sammlung von Werkzeugen, um den Hamiltonoperator zu erhalten, den du für quantenchemische Berechnungen auf IBM®-Quantencomputern benötigst.