Qiskit 1.0 Feature-Änderungen
Dieser Leitfaden beschreibt Migrationspfade für die wichtigsten Feature-Änderungen in Qiskit 1.0, geordnet nach Modulen. Nutze das Inhaltsverzeichnis auf der rechten Seite, um zum gewünschten Modul zu navigieren.
Qiskit 1.0 Migrationswerkzeug
Um die Migration zu erleichtern, kannst du das
flake8-qiskit-migration
Werkzeug verwenden, das entfernte Import-Pfade in deinem Code erkennt und Alternativen vorschlägt.
- Run with pipx
- Run with venv
Wenn du pipx installiert hast, führe einfach
den folgenden Befehl aus.
pipx run flake8-qiskit-migration <path-to-source-directory>
Das Paket wird in einer temporären virtuellen Umgebung installiert und auf deinen Code angewendet.
Wenn du pipx nicht verwenden möchtest, kannst du manuell eine neue
Umgebung für das Werkzeug erstellen. Dieser Ansatz ermöglicht es dir auch,
nbqa zu nutzen, um Codebeispiele in
Jupyter-Notebooks zu prüfen. Lösche die Umgebung, wenn du fertig bist.
# Make new environment and install
python -m venv .flake8-qiskit-migration-venv
source .flake8-qiskit-migration-venv/bin/activate
pip install flake8-qiskit-migration
# Run plugin on Python code
flake8 --select QKT100 <path-to-source-directory> # e.g. `src/`
# (Optional) run plugin on notebooks
pip install nbqa
nbqa flake8 ./**/*.ipynb --select QKT100
# Deactivate and delete environment
deactivate
rm -r .flake8-qiskit-migration-venv
Dieses Werkzeug erkennt nur entfernte Import-Pfade. Es erkennt nicht die Verwendung entfernter
Methoden (wie QuantumCircuit.qasm) oder Argumente. Es kann auch keine Zuweisungen wie
qk = qiskit nachverfolgen, aber es kann Aliase wie import qiskit as qk verarbeiten.
Weitere Informationen findest du im Repository des Projekts.
Globale Instanzen und Funktionen
Aer
Das Objekt qiskit.Aer steht in Qiskit 1.0 nicht mehr zur Verfügung. Verwende stattdessen
dasselbe Objekt aus dem Namensraum qiskit_aer, das als direkter Ersatz dient.
Um qiskit_aer zu installieren, führe folgenden Befehl aus:
pip install qiskit-aer
BasicAer
Das Objekt qiskit.BasicAer steht in Qiskit 1.0 nicht mehr zur Verfügung. Sieh dir den
basicaer-Migrationsabschnitt für
Migrationsmöglichkeiten an.
execute
Die Funktion qiskit.execute steht in Qiskit 1.0 nicht mehr zur Verfügung. Diese
Funktion diente als High-Level-Wrapper um die Funktionen
transpile und
run in Qiskit.
Anstelle von qiskit.execute verwendest du die Funktion
transpile gefolgt von
backend.run().
# Legacy path
from qiskit import execute
job = execute(circuit, backend)
# New path
from qiskit import transpile
new_circuit = transpile(circuit, backend)
job = backend.run(new_circuit)
Alternativ ist das Sampler-Primitive
semantisch gleichwertig zur entfernten Funktion qiskit.execute.
Die Klasse
BackendSampler ist ein
generischer Wrapper für Backends, die keine Primitives unterstützen:
from qiskit.primitives import BackendSampler
sampler = BackendSampler(backend)
job = sampler.run(circuit)
qiskit.circuit
QuantumCircuit.qasm
Die Methode QuantumCircuit.qasm wurde entfernt. Verwende stattdessen
qasm2.dump oder
qasm2.dumps.
Für Pygments-formatierte Ausgabe verwende das eigenständige Paket
openqasm-pygments,
da qasm2.dump und qasm2.dumps keine Pygments-farbige Ausgabe liefern.
from qiskit import QuantumCircuit
qc = QuantumCircuit(1)
# Old
qasm_str = qc.qasm()
# Alternative
from qiskit.qasm2 import dumps
qasm_str = dumps(qc)
# Alternative: Write to file
from qiskit.qasm2 import dump
with open("my_file.qasm", "w") as f:
dump(qc, f)
QuantumCircuit-Gates
Die folgenden Gate-Methoden wurden zugunsten etablierterer Methoden entfernt, die dieselben Gates hinzufügen:
| Entfernt | Alternative |
|---|---|
QuantumCircuit.cnot | QuantumCircuit.cx |
QuantumCircuit.toffoli | QuantumCircuit.ccx |
QuantumCircuit.fredkin | QuantumCircuit.cswap |
QuantumCircuit.mct | QuantumCircuit.mcx |
QuantumCircuit.i | QuantumCircuit.id |
QuantumCircuit.squ | QuantumCircuit.unitary |
Die folgenden Circuit-Methoden wurden entfernt. Diese Gates können stattdessen
mit QuantumCircuit.append auf einen Circuit angewendet werden.
| Entfernt | Alternative (append) |
|---|---|
QuantumCircuit.diagonal | DiagonalGate |
QuantumCircuit.hamiltonian | HamiltonianGate |
QuantumCircuit.isometry | Isometry |
QuantumCircuit.iso | Isometry |
QuantumCircuit.uc | UCGate |
QuantumCircuit.ucrx | UCRXGate |
QuantumCircuit.ucry | UCRYGate |
QuantumCircuit.ucrz | UCRZGate |
Beispiel für ein DiagonalGate:
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.library import DiagonalGate # new location in the circuit library
circuit = QuantumCircuit(2)
circuit.h([0, 1]) # some initial state
gate = DiagonalGate([1, -1, -1, 1])
qubits = [0, 1] # qubit indices on which to apply the gate
circuit.append(gate, qubits) # apply the gate
Die folgenden QuantumCircuit-Methoden wurden ebenfalls entfernt:
| Entfernt | Alternative |
|---|---|
QuantumCircuit.bind_parameters | QuantumCircuit.assign_parameters |
QuantumCircuit.snapshot | qiskit-aer's save instructions |
qiskit.converters
Die Funktion qiskit.converters.ast_to_dag wurde aus Qiskit entfernt. Sie konvertierte den
abstrakten Syntaxbaum des veralteten OpenQASM-2-Parsers in einen
DAGCircuit. Da der veraltete
OpenQASM-2-Parser entfernt wurde (siehe qiskit.qasm), ist
diese Funktion nicht mehr nützlich. Stattdessen kannst du deine OpenQASM-2-Dateien mit
QuantumCircuit.from_qasm_file
oder
QuantumCircuit.from_qasm_str
(oder dem Modul qiskit.qasm2) in einen QuantumCircuit parsen und diesen
anschließend mit
circuit_to_dag
in einen DAGCircuit umwandeln.
# Previous
from qiskit.converters import ast_to_dag
from qiskit.qasm import Qasm
dag = ast_to_dag(Qasm(filename="myfile.qasm").parse())
# Current alternative
import qiskit.qasm2
from qiskit.converters import circuit_to_dag
dag = circuit_to_dag(qiskit.qasm2.load("myfile.qasm"))
qiskit.extensions
Das Modul qiskit.extensions steht nicht mehr zur Verfügung. Die meisten seiner Objekte wurden in die
Circuit-Bibliothek (qiskit.circuit.library) integriert.
Ersetze für die Migration einfach qiskit.extensions durch qiskit.circuit.library
im Import-Pfad der Objekte. Dies ist ein direkter Ersatz.
# Previous
from qiskit.extensions import DiagonalGate
# Current alternative
from qiskit.circuit.library import DiagonalGate
Die nach qiskit.circuit.library verschobenen Klassen sind:
DiagonalGateHamiltonianGateInitializeIsometryqiskit.circuit.library.generalized_gates.mcg_up_diag.MCGupDiagUCGateUCPauliRotGateUCRXGateUCRYGateUCRZGateUnitaryGate
Die folgenden Klassen wurden aus der Codebasis entfernt, da ihre
Funktionen entweder redundant waren oder mit dem extensions-Modul verknüpft:
| Entfernt | Alternative |
|---|---|
SingleQubitUnitary | qiskit.circuit.library.UnitaryGate |
Snapshot | Verwende qiskit-aer's save instructions |
ExtensionError | Eine passende Fehlerklasse |
qiskit.primitives
Die bedeutendste Änderung im Modul qiskit.primitives ist die
Einführung der neuen Primitives-V2-Schnittstelle. Dieser Abschnitt zeigt, wie du deinen
Workflow von Primitives V1 auf Primitives V2 migrierst, sowie die wenigen Änderungen
an den von der V1-Schnittstelle akzeptierten Eingaben.
Ab der Version 1.0 bezeichnen wir die Primitives-Schnittstelle vor Version 1.0 als „Primitives V1".
Von V1 auf V2 migrieren
Der formale Unterschied zwischen den APIs Primitives V1 und V2 sind die Basisklassen, von denen
Primitives-Implementierungen erben. Um auf die neuen Basisklassen umzusteigen, kannst du den
ursprünglichen Import-Pfad aus qiskit.primitives beibehalten:
| Migriere von | Ersetze durch |
|---|---|
BaseEstimator | BaseEstimatorV2 |
BaseSampler | BaseSamplerV2 |
Die Namen der Qiskit-Core-Implementierungen der V2-Primitives (importierbar aus qiskit.primitives)
wurden angepasst, um ihren Zweck als Implementierungen klarzustellen, die lokal
mit einem Statevector-Simulator-Backend ausgeführt werden können. Die neuen Namen enthalten kein -V2-Suffix.
| Migriere von | Ersetze durch |
|---|---|
qiskit.primitives.Estimator | qiskit.primitives.StatevectorEstimator |
qiskit.primitives.Sampler | qiskit.primitives.StatevectorSampler |
Bei der Migration von V1 auf V2 gibt es einige konzeptionelle Unterschiede zu beachten.
Diese Unterschiede werden durch die Basisklasse vorgegeben, sind aber in den folgenden Beispielen
anhand der Statevector-Implementierungen aus qiskit.primitives dargestellt:
Für die folgenden Beispiele werden folgende Importe und Primitive-Initialisierungen angenommen:
from qiskit.primitives import (
Sampler,
StatevectorSampler,
Estimator,
StatevectorEstimator,
)
estimator_v1 = Estimator()
sampler_v1 = Sampler()
estimator_v2 = StatevectorEstimator()
sampler_v2 = StatevectorSampler()
# define circuits, observables and parameter values
Sampler und Estimator: Die neuen V2-Primitives sind für vektorisierte Eingaben konzipiert, bei denen einzelne Circuits mit array-wertigen Spezifikationen gruppiert werden können. Das bedeutet, ein Circuit kann für Arrays mitnParametersätzen,nObservablen oder beidem (beim Estimator) ausgeführt werden. Jede Gruppe wird als Primitive Unified Bloc (PUB) bezeichnet und kann als Tupel dargestellt werden:(1 x Circuit, [n x Observablen], [n x Parameter]). Die V1-Schnittstelle erlaubte diese Flexibilität nicht. Stattdessen musste die Anzahl der Eingabe-Circuits mit der Anzahl der Observablen und Parametersätze übereinstimmen, wie in den folgenden Beispielen gezeigt (wähle einen Tab, um das jeweilige Beispiel zu sehen):
- Estimator, 1 circuit, 4 observables
- Sampler, 1 circuit, 3 parameter sets
- Estimator, 1 circuit, 4 observables, 2 parameter sets
# executing 1 circuit with 4 observables using Estimator V1
job = estimator_v1.run([circuit] * 4, [obs1, obs2, obs3, obs4])
evs = job.result().values
# executing 1 circuit with 4 observables using Estimator V2
job = estimator_v2.run([(circuit, [obs1, obs2, obs3, obs4])])
evs = job.result()[0].data.evs
# executing 1 circuit with 3 parameter sets using Sampler V1
job = sampler_v1.run([circuit] * 3, [vals1, vals2, vals3])
dists = job.result().quasi_dists
# executing 1 circuit with 3 parameter sets using Sampler V2
job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])
counts = job.result()[0].data.meas.get_counts()
# executing 1 circuit with 4 observables and 2 parameter sets using Estimator V1
job = estimator_v1.run([circuit] * 8, [obs1, obs2, obs3, obs4] * 2, [vals1, vals2] * 4)
evs = job.result().values
# executing 1 circuit with 4 observables and 2 parameter sets using Estimator V2
job = estimator_v2.run([(circuit, [[obs1, obs2, obs3, obs4]], [[vals1], [vals2]])])
evs = job.result()[0].data.evs
V2-Primitives akzeptieren mehrere PUBs als Eingabe, und jedes PUB erhält sein eigenes Ergebnis. Damit kannst du verschiedene Circuits mit unterschiedlichen Parameter-/Observablen-Kombinationen ausführen, was mit der V1-Schnittstelle nicht immer möglich war:
- Sampler, 2 circuits, 1 parameter set
- Estimator, 2 circuits, 2 different observables
# executing 2 circuits with 1 parameter set using Sampler V1
job = sampler_v1.run([circuit1, circuit2], [vals1] * 2)
dists = job.result().quasi_dists
# executing 2 circuits with 1 parameter set using Sampler V2
job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)])
counts1 = job.result()[0].data.meas.get_counts() # result for pub 1 (circuit 1)
counts2 = job.result()[1].data.meas.get_counts() # result for pub 2 (circuit 2)
# executing 2 circuits with 2 different observables using Estimator V1
job = estimator_v1.run([circuit1, circuit2] , [obs1, obs2])
evs = job.result().values
# executing 2 circuits with 2 different observables using Estimator V2
job = estimator_v2.run([(circuit1, obs1), (circuit2, obs2)])
evs1 = job.result()[0].data.evs # result for pub 1 (circuit 1)
evs2 = job.result()[1].data.evs # result for pub 2 (circuit 2)
-
Sampler: Der V2-Sampler gibt Messergebnis-Samples nun in Form von Bitstrings oder Counts zurück, anstelle der Quasi-Wahrscheinlichkeitsverteilungen der V1-Schnittstelle. Die Bitstrings zeigen die Messergebnisse und bewahren dabei die Reihenfolge der Shots, in der sie gemessen wurden. Die Ergebnisobjekte des V2-Samplers ordnen die Daten nach den Namen der klassischen Register der Eingabe-Circuits, um die Kompatibilität mit dynamischen Circuits zu gewährleisten.
# Define quantum circuit with 2 qubits
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw()┌───┐ ░ ┌─┐
q_0: ┤ H ├──■───░─┤M├───
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├─░──╫─┤M├
└───┘ ░ ║ └╥┘
meas: 2/══════════════╩══╩═
0 1Standardname des klassischen RegistersIm obigen Circuit ist zu sehen, dass der Name des klassischen Registers standardmäßig
"meas"lautet. Dieser Name wird später verwendet, um auf die Mess-Bitstrings zuzugreifen.# Run using V1 sampler
result = sampler_v1.run(circuit).result()
quasi_dist = result.quasi_dists[0]
print(f"The quasi-probability distribution is: {quasi_dist}")The quasi-probability distribution is: {0: 0.5, 3: 0.5}# Run using V2 sampler
result = sampler_v2.run([circuit]).result()
# Access result data for pub 0
data_pub = result[0].data
# Access bitstrings for the classical register "meas"
bitstrings = data_pub.meas.get_bitstrings()
print(f"The number of bitstrings is: {len(bitstrings)}")
# Get counts for the classical register "meas"
counts = data_pub.meas.get_counts()
print(f"The counts are: {counts}")The number of bitstrings is: 1024
The counts are: {'00': 523, '11': 501} -
Sampler und Estimator: Der Sampling-Overhead, der bei V1-Implementierungen üblicherweise über die Run-Optionshotsgesteuert wurde, ist nun ein Argument derrun()-Methode der Primitives, das auf PUB-Ebene angegeben werden kann. Die V2-Basisklassen legen die Argumente in einem anderen Format als die V1-API fest:-
BaseSamplerV2.runstellt einshots-Argument bereit (ähnlich wie bisher):# Sample two circuits at 128 shots each.
sampler_v2.run([circuit1, circuit2], shots=128)
# Sample two circuits at different amounts of shots. The "None"s are necessary
# as placeholders
# for the lack of parameter values in this example.
sampler_v2.run([(circuit1, None, 123), (circuit2, None, 456)]) -
EstimatorV2.runführt einprecision-Argument ein, das die Fehlerbalken angibt, auf die die Primitives-Implementierung bei der Schätzung von Erwartungswerten abzielen soll:# Estimate expectation values for two PUBs, both with 0.05 precision.
estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)
-
Änderungen an der V1-Schnittstelle
-
Die implizite Konvertierung eines dichten
BaseOperatorin einenSparsePauliOpin Observable-Argumenten vonEstimatorist nicht mehr erlaubt. Verwende stattdessen explizitSparsePauliOp.from_operator(operator)zur Konvertierung. -
Die Verwendung einer
PauliListin Observable-Argumenten des Estimators ist nicht mehr erlaubt. Konvertiere das Argument stattdessen explizit mitSparsePauliOp(pauli_list).
qiskit.providers
basicaer
Der Großteil der Funktionalität im Modul qiskit.providers.basicaer wurde durch das neue
Modul qiskit.providers.basic_provider
ersetzt, mit Ausnahme der Klassen UnitarySimulatorPy und StatevectorSimulatorPy,
die entfernt wurden; ihre Funktionalität war bereits im
Modul quantum_info enthalten.
Die Migration zu den neuen Pfaden ist unkompliziert. Du kannst die meisten
Klassen in qiskit.providers.basicaer durch ihre entsprechende
qiskit.providers.basic_provider-Klasse
ersetzen (direkter Ersatz). Beachte, dass folgende Klassen
neue Pfade und Namen haben:
| Entfernt | Alternative |
|---|---|
qiskit.providers.basicaer | qiskit.providers.basic_provider |
BasicAerProvider | BasicProvider |
BasicAerJob | BasicProviderJob |
QasmSimulatorPy | BasicSimulator |
Beachte globale Instanzen bei der Migration auf das neue Modul. Es gibt keinen Ersatz für
die globale BasicAer-Instanz, die direkt als qiskit.BasicAer importiert werden konnte. Das bedeutet,
dass from qiskit import BasicProvider kein gültiger Import mehr ist.
Stattdessen muss die Provider-Klasse aus ihrem Untermodul importiert und vom Nutzer instanziiert werden:
# Previous
from qiskit import BasicAer
backend = BasicAer.get_backend("backend_name")
# Current
from qiskit.providers.basic_provider import BasicProvider
backend = BasicProvider().get_backend("backend_name")
Die Unitary- und Statevector-Simulatoren können durch
verschiedene quantum_info-Klassen ersetzt werden.
Das ist kein direkter Ersatz, aber die Änderungen sind minimal. Sieh dir die folgenden
Migrationsbeispiele an:
| Entfernt | Alternative |
|---|---|
UnitarySimulatorPy | quantum_info.Operator |
StatevectorSimulatorPy | quantum_info.Statevector |
Die folgenden Beispiele zeigen die Migrationspfade der basicaer-Simulatoren.
- Statevector simulator
- Unitary simulator
- QASM simulator
from qiskit import QuantumCircuit
qc = QuantumCircuit(3)
qc.h(0)
qc.h(1)
qc.cx(1, 2)
qc.measure_all()
# Previous
from qiskit import BasicAer
backend = BasicAer.get_backend("statevector_simulator")
statevector = backend.run(qc).result().get_statevector()
# Current
qc.remove_final_measurements() # no measurements allowed
from qiskit.quantum_info import Statevector
statevector = Statevector(qc)
from qiskit import QuantumCircuit
qc = QuantumCircuit(3)
qc.h(0)
qc.h(1)
qc.cx(1, 2)
qc.measure_all()
# Previous
from qiskit import BasicAer
backend = BasicAer.get_backend("unitary_simulator")
result = backend.run(qc).result()
# Current
qc.remove_final_measurements() # no measurements allowed
from qiskit.quantum_info import Operator
result = Operator(qc).data
from qiskit import QuantumCircuit
qc = QuantumCircuit(3)
qc.h(0)
qc.h(1)
qc.cx(1, 2)
qc.measure_all()
# Previous
from qiskit import BasicAer
backend = BasicAer.get_backend("qasm_simulator")
result = backend.run(qc).result()
# One current option
from qiskit.providers.basic_provider import BasicProvider
backend = BasicProvider().get_backend("basic_simulator")
result = backend.run(qc).result()
# Another current option is to specify it directly
from qiskit.providers.basic_provider import BasicSimulator
backend = BasicSimulator()
result = backend.run(qc).result()
fake_provider
Der Großteil der nutzerseitigen
qiskit.providers.fake_provider-Komponenten wurde in das Python-Paket qiskit-ibm-runtime migriert.
Dazu gehören die Fake-Provider-Klassen, alle gerätespezifischen Fake-Backends (wie
FakeVigo, FakeNairobiV2 und FakeSherbrooke) sowie die Fake-Backend-Basisklassen.
Klicke durch die folgenden Tabs, um die betroffenen Klassen zu sehen.
- Fake Backends
- Fake Providers
- Jede Klasse in
qiskit.providers.fake_provider.backends fake_provider.fake_backend.FakeBackendfake_provider.fake_backend.FakeBackendV2
fake_provider.FakeProviderfake_provider.FakeProviderForBackendV2fake_provider.FakeProviderFactory
So migrierst du zum neuen Pfad:
-
Installiere
qiskit-ibm-runtime0.17.1oder neuer:pip install 'qiskit-ibm-runtime>=0.17.1' -
Ersetze alle Vorkommen von
qiskit.providers.fake_providerin deinem Code durchqiskit_ibm_runtime.fake_provider. Zum Beispiel:# Old
from qiskit.providers.fake_provider import FakeProvider
backend1 = FakeProvider().get_backend("fake_ourense")
from qiskit.providers.fake_provider import FakeSherbrooke
backend2 = FakeSherbrooke()
# Alternative
from qiskit_ibm_runtime.fake_provider import FakeProvider
backend1 = FakeProvider().get_backend("fake_ourense")
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend2 = FakeSherbrooke()
Die Fake-Backend-Basisklassen wurden ebenfalls migriert, haben aber einige Unterschiede im Import-Pfad:
| Entfernt | Alternative |
|---|---|
qiskit.providers.fake_provider.FakeQasmBackend | qiskit_ibm_runtime.fake_provider.fake_qasm_backend.FakeQasmBackend |
qiskit.providers.fake_provider.FakePulseBackend | qiskit_ibm_runtime.fake_provider.fake_pulse_backend.FakePulseBackend |
Wenn du für Unit-Tests einer nachgelagerten Bibliothek von Fake-Backends abhängig bist und Konflikte
mit der qiskit-ibm-runtime-Abhängigkeit hast, findest du auch neue Qiskit-native generische
Fake-Backend-Alternativen. Dazu gehören folgende BackendV1-Klassen (direkter Ersatz):
qiskit.providers.fake_provider.Fake5QV1qiskit.providers.fake_provider.Fake20QV1qiskit.providers.fake_provider.Fake7QPulseV1qiskit.providers.fake_provider.Fake27QPulseV1qiskit.providers.fake_provider.Fake127QPulseV1
Diese konfigurierbare Klasse gibt BackendV2-Instanzen zurück:
fake_provider (spezielle Test-Backends)
Die Fake-Backend-Klassen für spezielle Testzwecke in
qiskit.providers.fake_provider wurden
nicht nach qiskit_ibm_runtime.fake_provider migriert. Der empfohlene
Migrationspfad besteht darin, die neue Klasse
GenericBackendV2
zu verwenden, um ein Backend mit ähnlichen Eigenschaften zu konfigurieren oder ein benutzerdefiniertes
Target zu erstellen.
| Entfernt | Alternative |
|---|---|
fake_provider.FakeBackendV2 | fake_provider.GenericBackendV2 |
fake_provider.FakeBackend5QV2 | fake_provider.GenericBackendV2 |
fake_provider.FakeBackendV2LegacyQubitProps | fake_provider.GenericBackendV2 |
fake_provider.FakeBackendSimple | fake_provider.GenericBackendV2 |
fake_provider.ConfigurableFakeBackend | fake_provider.GenericBackendV2 |
Beispiel: Migration zur neuen Klasse
GenericBackendV2:
# Legacy path
from qiskit.providers.fake_provider import FakeBackend5QV2
backend = FakeBackend5QV2()
# New path
from qiskit.providers.fake_provider import GenericBackendV2
backend = GenericBackendV2(num_qubits=5)
# Note that this class generates a 5q backend with generic
# properties that serves the same purpose as FakeBackend5QV2
# but will not be identical.
Weitere Migrationstipps
-
Der Import aus
qiskit.providers.aerist nicht mehr möglich. Importiere stattdessen ausqiskit_aer, das ein direkter Ersatz ist. Umqiskit_aerzu installieren, führe folgenden Befehl aus:pip install qiskit-aer -
Die Unterstützung für das Ausführen von Pulse-Jobs auf Backends aus
qiskit.providers.fake_providerwurde in Qiskit 1.0 entfernt. Das liegt daran, dass Qiskit Aer seine Simulationsfunktionalität für solche Jobs entfernt hat. Für Low-Level-Hamiltonsche-Simulations- Workloads solltest du eine spezialisierte Bibliothek wie Qiskit Dynamics in Betracht ziehen.
qiskit.pulse
ParametricPulse
Die Basisklasse qiskit.pulse.library.parametric_pulses.ParametricPulse und
die Pulse-Bibliothek wurden durch
qiskit.pulse.SymbolicPulse
und die entsprechende Pulse-Bibliothek ersetzt. SymbolicPulse unterstützt
QPY-Serialisierung:
from qiskit import pulse, qpy
with pulse.build() as schedule:
pulse.play(pulse.Gaussian(100, 0.1, 25), pulse.DriveChannel(0))
with open('schedule.qpy', 'wb') as fd:
qpy.dump(schedule, fd)
| Entfernt | Alternative |
|---|---|
pulse.library.parametric_pulses.ParametricPulse | qiskit.pulse.SymbolicPulse |
pulse.library.parametric_pulses.Constant | pulse.library.symbolic_pulses.Constant |
pulse.library.parametric_pulses.Drag | pulse.library.symbolic_pulses.Drag |
pulse.library.parametric_pulses.Gaussian | pulse.library.symbolic_pulses.Gaussian |
qiskit.pulse.library.parametric_pulses.GaussianSquare | pulse.library.symbolic_pulses.GaussianSquare |
Komplexwertige Amplitude
Die komplexwertige Pulsamplitude (amp) wurde durch ein (amp,
angle)-Paar ersetzt. Diese Darstellung ist intuitiver, besonders für bestimmte
Kalibrierungsaufgaben wie die Winkelkalibrierung:
from qiskit import pulse
from qiskit.circuit import Parameter
from math import pi
with pulse.build() as schedule:
angle = Parameter("θ")
pulse.play(pulse.Gaussian(100, 0.1, 25, angle=angle), pulse.DriveChannel(0))
schedule.assign_parameters({angle: pi})
Circuit-Gate-Operationen einbetten
Das Einbetten von Circuit-Gate-Operationen in den Pulse-Builder-Kontext über
qiskit.pulse.builder.call ist nicht mehr möglich.
Diese Entfernung betrifft Eingabeargumente vom Typ QuantumCircuit sowie die
folgenden Funktionen:
qiskit.pulse.builder.call_gateqiskit.pulse.builder.cxqiskit.pulse.builder.u1qiskit.pulse.builder.u2qiskit.pulse.builder.u3qiskit.pulse.builder.x
Wenn du weiterhin backend-kalibrierte Schedules einbetten möchtest, verwende stattdessen das folgende Muster anstelle von Gate-Befehlen.
from qiskit.providers.fake_provider import GenericBackendV2
from qiskit import pulse
backend = GenericBackendV2(num_qubits=5)
sched = backend.target["x"][(qubit,)].calibration
with pulse.build() as only_pulse_scheds:
pulse.call(sched)
Ebenso kann ein QuantumCircuit in den
Builder-Kontext eingebettet werden, indem das Objekt manuell transpiliert und geplant wird.
from math import pi
from qiskit.compiler import schedule, transpile
qc = QuantumCircuit(2)
qc.rz(pi / 2, 0)
qc.sx(0)
qc.rz(pi / 2, 0)
qc.cx(0, 1)
qc_t = transpile(qc, backend)
sched = schedule(qc_t, backend)
with pulse.build() as only_pulse_scheds:
pulse.call(sched)
Es empfiehlt sich, ein minimales Pulse-Programm mit dem Builder zu schreiben und es über die Methode
QuantumCircuit.add_calibration
als Mikrocode einer Gate-Anweisung an einen QuantumCircuit anzuhängen,
anstatt das gesamte Programm mit dem Pulse-Modell zu schreiben.
builder.build
Die folgenden Argumente in qiskit.pulse.builder.build wurden ohne Alternative entfernt.
default_transpiler_settingsdefault_circuit_scheduler_settings
Diese Funktionen wurden ebenfalls entfernt:
qiskit.pulse.builder.active_transpiler_settingsqiskit.pulse.builder.active_circuit_scheduler_settingsqiskit.pulse.builder.transpiler_settingsqiskit.pulse.builder.circuit_scheduler_settings
Dies liegt daran, dass es nicht mehr möglich ist, Circuit-Objekte in den Builder-Kontext einzubetten (siehe Circuit-Gate-Operationen einbetten); diese Einstellungen dienten dazu, eingebettete Objekte in Pulse-Darstellungen umzuwandeln.
library
Die diskrete Pulse-Bibliothek wurde aus der Codebasis entfernt. Dies umfasst:
qiskit.pulse.library.constantqiskit.pulse.library.zeroqiskit.pulse.library.squareqiskit.pulse.library.sawtoothqiskit.pulse.library.triangleqiskit.pulse.library.cosqiskit.pulse.library.sinqiskit.pulse.library.gaussianqiskit.pulse.library.gaussian_derivqiskit.pulse.library.sechqiskit.pulse.library.sech_derivqiskit.pulse.library.gaussian_squareqiskit.pulse.library.drag
Verwende stattdessen den entsprechenden
qiskit.pulse.SymbolicPulse
mit
SymbolicPulse.get_waveform().
Verwende beispielsweise anstelle von pulse.gaussian(100,0.5,10) den Ausdruck
pulse.Gaussian(100,0.5,10).get_waveform(). Beachte, dass die Phase von
Sawtooth und
Square so definiert ist,
dass eine Phase von 2\\pi um einen vollen Zyklus verschoben wird, im Gegensatz zum diskreten
Gegenstück. Außerdem sind komplexe Amplituden in der symbolischen Pulse-Bibliothek nicht mehr
unterstützt; verwende stattdessen float, amp und angle.
ScalableSymbolicPulse
Es ist nicht mehr möglich, qiskit.pulse.ScalableSymbolicPulse-Objekte aus der Bibliothek
mit einem komplexen amp-Parameter aus QPY-Dateien der Version 5 oder früher
(Qiskit Terra < 0.23.0) zu laden. Es ist keine Migrationsmaßnahme erforderlich, da komplexe amp-Werte
automatisch in float (amp, angle) umgewandelt werden.
Diese Änderung betrifft folgende Pulse:
qiskit.qasm
Das veraltete OpenQASM-2-Parser-Modul, das zuvor in qiskit.qasm verfügbar war,
wurde durch das Modul qiskit.qasm2 ersetzt, das
einen schnelleren und genaueren Parser für OpenQASM 2 bereitstellt. Die übergeordneten
QuantumCircuit-Methoden
from_qasm_file()
und
from_qasm_str()
bleiben gleich, verwenden aber intern den neuen Parser. Die öffentliche
Schnittstelle des Moduls qasm2 ist jedoch nicht dieselbe. Während das Modul qiskit.qasm
eine Schnittstelle zu einem abstrakten Syntaxbaum bot, der vom Parser der ply-Bibliothek zurückgegeben wurde,
legt qiskit.qasm2 weder den AST noch andere Implementierungsdetails des Parsers offen.
Es nimmt stattdessen OpenQASM-2-Eingaben entgegen und gibt ein
QuantumCircuit-Objekt aus.
Wenn du beispielsweise bisher so etwas wie das Folgende ausgeführt hast:
import qiskit.qasm
from qiskit.converters import ast_to_dag, dag_to_circuit
ast = qiskit.qasm.Qasm(filename="myfile.qasm").parse()
dag = ast_to_dag(ast)
qasm_circ = dag_to_circuit(dag)
Ersetze es durch das Folgende:
import qiskit.qasm2
qasm_circ = qiskit.qasm2.load("myfile.qasm")
qiskit.quantum_info
Das Modul qiskit.quantum_info.synthesis wurde an verschiedene Stellen in der Codebasis migriert,
hauptsächlich nach qiskit.synthesis.
| Entfernt | Alternative |
|---|---|
OneQubitEulerDecomposer | qiskit.synthesis.one_qubit.OneQubitEulerDecomposer |
TwoQubitBasisDecomposer | qiskit.synthesis.two_qubits.TwoQubitBasisDecomposer |
XXDecomposer | qiskit.synthesis.two_qubits.XXDecomposer |
two_qubit_cnot_decompose | qiskit.synthesis.two_qubits.two_qubit_cnot_decompose |
Quaternion | qiskit.quantum_info.Quaternion |
Diese Verschiebung hat den üblichen Import-Pfad von Quaternion nicht verändert, du kannst aber
nicht mehr über qiskit.quantum_info.synthesis darauf zugreifen.
Schließlich wurde cnot_rxx_decompose entfernt.
qiskit.test
Das Modul qiskit.test ist kein öffentliches Modul mehr. Es war nie als öffentlich gedacht
und sollte außerhalb der Qiskit-Testsuite nicht verwendet werden. Alle Funktionen waren spezifisch für Qiskit und
es wird keine Alternative bereitgestellt; wenn du ähnliche Funktionalität benötigst, solltest du sie in
deinen eigenen Test-Frameworks implementieren.
qiskit.tools
Das Modul qiskit.tools wurde in Qiskit 1.0 entfernt. Der Großteil dieser Funktionalität wurde
entweder durch ähnliche Funktionalität in anderen Paketen ersetzt oder ohne Alternative entfernt.
Die wesentliche Ausnahme ist die Funktion qiskit.tools.parallel_map(), die in das
Modul qiskit.utils verlagert wurde. Sie kann
von diesem neuen Speicherort aus verwendet werden. Zum Beispiel:
Wenn du bisher folgendes ausgeführt hast:
# Previous
from qiskit.tools import parallel_map
parallel_map(func, input)
# Current
from qiskit.utils import parallel_map
parallel_map(func, input)
jupyter
Das Untermodul qiskit.tools.jupyter wurde entfernt, da die Funktionalität
in diesem Modul an das veraltete Paket qiskit-ibmq-provider gebunden war, das nicht mehr
unterstützt wird. Es unterstützte außerdem nur BackendV1 und nicht die neuere
BackendV2-Schnittstelle.
monitor
Das Untermodul qiskit.tools.monitor wurde entfernt, da es an das
veraltete Paket qiskit-ibmq-provider gebunden war, das nicht mehr unterstützt wird (es
unterstützte auch nur die BackendV1-Schnittstelle und nicht die neuere
BackendV2-Schnittstelle). Für diese
Funktionalität gibt es keinen Ersatz.
visualization
Das Untermodul qiskit.tools.visualization wurde entfernt. Dieses Modul war eine
veraltete Weiterleitung vom ursprünglichen Speicherort des Qiskit-Visualisierungsmoduls, das
in Qiskit 0.8.0 nach qiskit.visualization verschoben wurde.
Wenn du diesen Pfad noch verwendest, aktualisiere deine Importe von
qiskit.tools.visualization auf
qiskit.visualization.
# Previous
from qiskit.tools.visualization import plot_histogram
plot_histogram(counts)
# Current
from qiskit.visualization import plot_histogram
plot_histogram(counts)
events
Das Modul qiskit.tools.events und das darin enthaltene progressbar()-Hilfsprogramm
wurden entfernt. Die Funktionalität dieses Moduls war wenig verbreitet und wird durch
dedizierte Pakete wie tqdm besser abgedeckt.
qiskit.transpiler
synthesis
Die Elemente im Modul qiskit.transpiler.synthesis wurden an neue Speicherorte migriert:
| Entfernt | Alternative |
|---|---|
qiskit.transpiler.synthesis.aqc (außer AQCSynthesisPlugin) | qiskit.synthesis.unitary.aqc |
qiskit.transpiler.synthesis.graysynth | qiskit.synthesis.synth_cnot_phase_aam |
qiskit.transpiler.synthesis.cnot_synth | qiskit.synthesis.synth_cnot_count_full_pmh |
passes
Der Transpiler-Pass NoiseAdaptiveLayout wurde durch
VF2Layout und
VF2PostLayout ersetzt,
die ein Layout auf Basis der gemeldeten Rauscheigenschaften eines Backends festlegen.
Sowohl der Pass als auch das entsprechende Layout-Stage-Plugin "noise_adaptive" wurden aus Qiskit entfernt.
Der Transpiler-Pass CrosstalkAdaptiveSchedule wurde aus der
Codebasis entfernt. Dieser Pass war nicht mehr verwendbar, da sein interner Betrieb
von benutzerdefinierten Eigenschaften abhing, die in der BackendProperties-Nutzlast
einer BackendV1-Instanz gesetzt wurden. Da keine Backends diese Felder setzen, wurde der Pass
entfernt.
passmanager
Die append-Methoden der Klassen
ConditionalController,
FlowControllerLinear und
DoWhileController
wurden entfernt. Stattdessen müssen alle Tasks beim Erstellen der Controller-Objekte übergeben werden.
qiskit.utils
Die folgenden Werkzeuge in qiskit.utils wurden ohne Ersatz entfernt:
qiskit.utils.arithmeticqiskit.utils.circuit_utilsqiskit.utils.entangler_mapqiskit.utils.name_unnamed_args
Diese Funktionen wurden ausschließlich in den Modulen qiskit.algorithms und
qiskit.opflow verwendet, die ebenfalls entfernt wurden.
qiskit.visualization
Das Modul qiskit.visualization.qcstyle wurde entfernt. Verwende
qiskit.visualization.circuit.qcstyle als direkten Ersatz.