Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Erfahren Sie, wie Sie eine Qiskit-Quantenschaltung mit dem Azure Quantum Development Kit (QDK) übermitteln. Sie können Qiskit-Schaltkreise mithilfe des Azure Quantum Development Kit (QDK) und des Jupyter-Notizbuchs in Visual Studio Code (VS Code) an Azure Quantum übermitteln. Sie können Ihre Schaltkreise auch mit dem lokalen Sparsesimulator testen. Der QDK unterstützt die Versionen 1 und 2 von Qiskit.
Weitere Informationen finden Sie unter Quantenschaltungen.
Voraussetzungen
Einzelheiten zur Installation finden Sie unter Einrichten der QDK-Erweiterung.
Ein Azure Quantum-Arbeitsbereich in Ihrem Azure-Abonnement. Zur Erstellung eines Arbeitsbereichs, siehe bitte Erstellen eines Azure Quantum Arbeitsbereichs.
Eine Python Umgebung mit Python installierter Pip .
VS Code mit installierten Azure Quantum Development Kit- Pythonund Jupyter-Erweiterungen .
Die
qdkPython Bibliothek mit denazureundqiskitExtras sowie demipykernelPaket.python -m pip install --upgrade "qdk[azure,qiskit]" ipykernel
Erstellen eines neuen Jupyter Notebooks
- Öffnen Sie im VS Code das Menü "Ansicht" , und wählen Sie "Befehlspalette" aus.
- Geben Sie ein und wählen Sie Erstellen: Neues Jupyter-Notizbuch aus.
- VS Code erkennt und zeigt die Version von Python und die virtuelle Python Umgebung, die für das Notizbuch ausgewählt wurden, an. Wenn Sie über mehrere Python Umgebungen verfügen, müssen Sie möglicherweise einen Kernel mit der Kernelauswahl oben rechts auswählen. Wenn keine Umgebung erkannt wurde, finden Sie Informationen zum Einrichten unter Jupyter-Notizbücher in VS Code .
Laden der erforderlichen Importe
Führen Sie in der ersten Zelle Ihres Notizbuchs den folgenden Code aus, um die erforderlichen Importe zu laden:
from qdk.azure import Workspace
from qdk.azure.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
Herstellen einer Verbindung mit dem Azure Quantum-Dienst
Um eine Verbindung mit dem Azure Quantum-Dienst herzustellen, benötigen Sie die Ressourcen-ID und den Standort Ihres Azure Quantum-Arbeitsbereichs.
- Melden Sie sich bei Ihrem Azure-Konto an. https://portal.azure.com
- Wählen Sie Ihren Azure Quantum-Arbeitsbereich aus, und wechseln Sie zu "Übersicht".
- Kopieren Sie die Parameter "Resource ID " und "Location ".
Fügen Sie eine neue Zelle in Ihrem Notizbuch hinzu, und verwenden Sie Ihre Kontoinformationen, um eine Workspace Verbindung mit Ihrem Azure Quantum-Arbeitsbereich herzustellen.AzureQuantumProvider
workspace = Workspace(
resource_id = "", # Add the resourceID of your workspace
location = "" # Add the location of your workspace (for example "westus")
)
provider = AzureQuantumProvider(workspace)
Auflisten aller Back-Ends
Sie können jetzt alle Quantencomputing-Back-Ends ausgeben, die in Ihrem Arbeitsbereich verfügbar sind:
print("This workspace's targets:")
for backend in provider.backends():
print("- " + backend.name)
This workspace's targets:
- ionq.simulator
- ionq.qpu.aria-1
- ionq.qpu.forte-1
- ionq.qpu.forte-enterprise-1
- quantinuum.sim.h2-1sc
- quantinuum.sim.h2-2sc
- quantinuum.sim.h2-1e
- quantinuum.sim.h2-2e
- quantinuum.qpu.h2-1
- quantinuum.qpu.h2-2
- rigetti.sim.qvm
- rigetti.qpu.ankaa-3
- rigetti.qpu.cepheus-1-36q
Ausführen einer einfachen Schaltung
Erstellen Sie in einer neuen Zelle einen einfachen Qiskit-Schaltkreis.
# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(3, 3)
circuit.name = "Qiskit Sample - 3-qubit GHZ circuit"
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure([0,1,2], [0, 1, 2])
# Print out the circuit
circuit.draw()
┌───┐ ┌─┐
q_0: ┤ H ├──■───────┤M├──────
└───┘┌─┴─┐ └╥┘┌─┐
q_1: ─────┤ X ├──■───╫─┤M├───
└───┘┌─┴─┐ ║ └╥┘┌─┐
q_2: ──────────┤ X ├─╫──╫─┤M├
└───┘ ║ ║ └╥┘
c: 3/════════════════╩══╩══╩═
0 1 2
Wählen Sie ein target , um Ihr Programm auszuführen.
Ausführen im IonQ-Simulator
Bevor Sie Ihren Schaltkreis auf realer Hardware ausführen, testen Sie Ihren Schaltkreis im Simulator. Dient get_backend zum Erstellen eines Objekts zum Herstellen einer Backend Verbindung mit dem IonQ Simulator-Back-End:
simulator_backend = provider.get_backend("ionq.simulator")
IonQ-Back-Ends unterstützen Gates aus einem definierten Gateset, die für die optimale Ausführung auf der Hardware kompiliert werden. Wenn Ihr Schaltkreis Tore enthält, die nicht in dieser Liste enthalten sind, müssen Sie die unterstützte gateset Funktion mithilfe der transpile von Qiskit bereitgestellten Funktion transpilieren:
from qiskit import transpile
circuit = transpile(circuit, simulator_backend)
Die Transpile-Funktion gibt ein neues Schaltkreisobjekt zurück, bei dem Gates in Tore zerlegt werden, die im angegebenen Back-End unterstützt werden.
Sie können das Programm jetzt über den Azure Quantum-Dienst ausführen und das Ergebnis abrufen. Die folgende Zelle übermittelt einen Auftrag, der die Schaltung mit 100 Ausführungen durchläuft:
job = simulator_backend.run(circuit, shots=8)
job_id = job.id()
print("Job id", job_id)
Job id 00000000-0000-0000-0000-000000000000
Führen Sie Folgendes aus, um zu warten, bis der Auftrag abgeschlossen ist, und die Ergebnisse zurückzugeben:
result = job.result()
print(result)
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=8, success=True, meas_level=2, data=ExperimentResultData(counts={'000': 4, '111': 4}, memory=['000', '000', '000', '000', '111', '111', '111', '111'], probabilities={'000': 0.5, '111': 0.5}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits=3, metadata={}), status=JobStatus.DONE, name='Qiskit Sample - 3-qubit GHZ circuit')], date=None, status=None, header=None, error_data=None)
Da das Ergebnis ein Objekttyp ist, der für das Qiskit-Paket spezifisch ist, verwenden Sie result.get_counts und plot_histogram, um die Ergebnisse zu visualisieren. Um alle möglichen Beschriftungen von Bitzeichenfolgen darzustellen, fügen Sie die Beschriftungen zu counts hinzu.
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 4, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 4}
Sie können die get_memory Funktion auch verwenden, um einzelne Aufnahmedaten aus dem Auftrag anzuzeigen:
result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']
Hinweis
Wenn Sie auf IonQ targetseinen Auftrag mit einer ungeraden Anzahl von Aufnahmen einreichen, wird die Anzahl der Aufnahmen auf die nächste gerade Zahl abgerundet. Wenn Sie beispielsweise 9 Aufnahmen angeben, werden in den Ergebnissen Daten für 8 Aufnahmen angezeigt.
Schätzen der Auftragskosten
Schätzen Sie, wie hoch die Kosten für einen Job sind, bevor Sie einen auf der QPU ausführen.
Die aktuellsten Preisdetails finden Sie unter IonQ-Preise, oder suchen Sie Ihren Arbeitsbereich und sehen Sie sich die Preisoptionen auf der Registerkarte Anbieter Ihres Arbeitsbereichs über aka.ms/aq/myworkspaces an.
Ausführen auf der IonQ-QPU
Um eine Verbindung mit echter Hardware herzustellen (eine Quantum Processor Unit (QPU)), geben Sie einfach den Namen der target"ionq.qpu.aria-1" Methode get_backend an:
qpu_backend = provider.get_backend("ionq.qpu.aria-1")
Übermitteln Sie den Schaltkreis, der auf Azure Quantum ausgeführt werden soll, rufen Sie die Ergebnisse ab, und führen Sie dann aus plot_histogram , um die Ergebnisse zu zeichnen.
Hinweis
Die zum Ausführen einer Schaltung auf der QPU erforderliche Zeit hängt von den aktuellen Warteschlangenzeiten ab.
# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)
# Get the job results (this method waits for the Job to complete):
result = job.result()
print(result)
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
Job id 00000000-0000-0000-0000-000000000000
Job Status: job has successfully run
Result(backend_name='ionq.qpu.aria-1', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2, data=ExperimentResultData(counts={'0': 505, '1': 6, '2': 1, '3': 1, '4': 1, '5': 10, '6': 11, '7': 488}, probabilities={'0': 0.4932, '1': 0.0059, '2': 0.001, '3': 0.001, '4': 0.001, '5': 0.0098, '6': 0.0117, '7': 0.4766}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])
{'000': 505, '001': 6, '010': 1, '011': 1, '100': 1, '101': 10, '110': 11, '111': 488}
Wichtig
Sie können nicht mehrere Schaltkreise in einem einzigen Auftrag einreichen. Als Problemumgehung können Sie die backend.run Methode aufrufen, um jeden Schaltkreis asynchron zu übermitteln, und dann die Ergebnisse jedes Auftrags abzurufen. Zum Beispiel:
jobs = []
for circuit in circuits:
jobs.append(backend.run(circuit, shots=N))
results = []
for job in jobs:
results.append(job.result())
Voraussetzungen
Einzelheiten zur Installation finden Sie unter Einrichten der QDK-Erweiterung.
Eine Python Umgebung mit Python installierter Pip .
VS Code mit installiertem Azure Quantum Development Kit und Python Erweiterungen.
Das
qdkPython Paket mit denqiskitundjupyterExtras.python pip install "qdk[qiskit,jupyter]"
Ausführen einer Basisschaltung
Öffnen Sie in VS Code eine neue Python Datei, um eine einfache Schaltung mit dem integrierten Sparsesimulator aus dem qsharp Modul zu erstellen und auszuführen.
# load the required imports
from qdk import qsharp
from qsharp.interop.qiskit import QSharpBackend
from qiskit.circuit.random import random_circuit
# define and display the circuit
circuit = random_circuit(2, 2, measure=True)
print(circuit)
# run the circuit using the built-in sparse simulator
backend = QSharpBackend()
job = backend.run(circuit)
counts = job.result().get_counts()
print(counts)
Um das Programm auszuführen, wählen Sie oben rechts das Symbol "Ausführen" und dann Python ausführen" aus. Die Ausgabe wird in einem neuen Terminalfenster angezeigt.
┌─────────────────────────┐┌─┐
q_0: ─■───────────┤0 ├┤M├───
│P(0.79983) │ (XX-YY)(1.9337,1.7385) │└╥┘┌─┐
q_1: ─■───────────┤1 ├─╫─┤M├
└─────────────────────────┘ ║ └╥┘
c: 2/═════════════════════════════════════════╩══╩═
0 1
{'11': 680, '00': 344}
QIR für den Circuit generieren
Aus demselben Schaltkreis können Sie QIR generieren, der für die Ausführung auf Quantenhardware verwendet wird.
Hinweis
Um QIR zu generieren, müssen alle Register gemessen werden. Wenn keine nicht verwendeten Register vorhanden sind, wird ein Fehler ausgelöst. Darüber hinaus erhalten Sie eine Fehlermeldung, wenn Sie versuchen, QIR mit einem Unrestrictedtarget Profil zu generieren. Das Profil Unrestricted ist nur für die Simulation gültig. Sie müssen TargetProfile.Base, TargetProfile.Adaptive_RI oder TargetProfile.Adaptive_RIF verwenden. Sie können den Aufruf von target_profile in backend.qir(...) außer Kraft setzen, um die Profile zu wechseln.
QSharpErrorundTargetProfileimportierenfrom qdk.qsharp import QSharpError, TargetProfileUm QIR zu generieren, ändern Sie die Ausgabe:
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
Ihr Code sollte nun wie folgt aussehen:
# load the required imports
from qdk import qsharp
from qsharp import QSharpError, TargetProfile
from qsharp.interop.qiskit import QSharpBackend
from qiskit.circuit.random import random_circuit
# define and display the circuit
circuit = random_circuit(2, 2, measure=True)
print(circuit)
# generate QIR for the circuit
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
Die Codeausgabe sollte wie folgt aussehen:
┌────────────┐ ┌─┐
q_0: ┤ Rx(2.7195) ├─■───────────┤M├───
└──┬─────┬───┘ │U1(5.5924) └╥┘┌─┐
q_1: ───┤ Tdg ├─────■────────────╫─┤M├
└─────┘ ║ └╥┘
c: 2/════════════════════════════╩══╩═
0 1
%Result = type opaque
%Qubit = type opaque
define void @ENTRYPOINT__main() #0 {
block_0:
call void @__quantum__qis__rx__body(double 2.7194945105768586, %Qubit* inttoptr (i64 0 to %Qubit*))
call void @__quantum__qis__rz__body(double 2.796204066686262, %Qubit* inttoptr (i64 0 to %Qubit*))
call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__rz__body(double -2.796204066686262, %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__rz__body(double 2.796204066686262, %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
call void @__quantum__rt__array_record_output(i64 2, i8* null)
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
ret void
}
declare void @__quantum__qis__rx__body(double, %Qubit*)
declare void @__quantum__qis__rz__body(double, %Qubit*)
declare void @__quantum__qis__t__adj(%Qubit*)
declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
declare void @__quantum__rt__array_record_output(i64, i8*)
declare void @__quantum__rt__result_record_output(%Result*, i8*)
attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
attributes #1 = { "irreversible" }
; module flags
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
!0 = !{i32 1, !"qir_major_version", i32 1}
!1 = !{i32 7, !"qir_minor_version", i32 0}
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
!3 = !{i32 1, !"dynamic_result_management", i1 false}
!4 = !{i32 1, !"classical_ints", i1 true}
!5 = !{i32 1, !"qubit_resetting", i1 true}
!6 = !{i32 1, !"classical_floats", i1 false}
!7 = !{i32 1, !"backwards_branching", i1 false}
!8 = !{i32 1, !"classical_fixed_points", i1 false}
!9 = !{i32 1, !"user_functions", i1 false}
!10 = !{i32 1, !"multiple_target_branching", i1 false}
Nicht alle Programme können auf der gesamten Hardware ausgeführt werden. Wenn Sie hier versuchen, das target Profil zu Base, erhalten Sie detaillierte Fehlermeldungen dazu, welche Programmteile nicht unterstützt werden.
try:
backend.qir(qc, target_profile=TargetProfile.Base)
except QSharpError as e:
print(e)