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 das qdk.azurePython Modul verwenden, um Schaltkreise in bestimmten Formaten an den Azure Quantum-Dienst zu übermitteln. In diesem Artikel wird gezeigt, wie Sie Schaltkreise in den folgenden Formaten übermitteln:
Weitere Informationen finden Sie unter Quantenschaltungen.
Voraussetzungen
Um Ihre Schaltkreise in Visual Studio Code (VS Code) zu entwickeln und auszuführen, benötigen Sie Folgendes:
Ein Azure-Konto mit einem aktiven Abonnement. Wenn Sie nicht über ein Azure-Konto verfügen, registrieren Sie sich kostenlos, und registrieren Sie sich für ein Kostenpflichtiges Abonnement.
Azure Quantum-Arbeitsbereich Weitere Informationen finden Sie unter 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 derazureErweiterung und demipykernelPaket.python -m pip install --upgrade "qdk[azure]" ipykernel
Erstellen eines neuen Jupyter-Notizbuchs
Führen Sie die folgenden Schritte aus, um ein Notizbuch in VS Code zu erstellen:
Ö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.
Um eine Verbindung mit dem Azure Quantum-Dienst herzustellen, benötigt Ihr Programm 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 navigieren Sie zu "Übersicht".
- Kopieren Sie die Parameter in den Feldern.
Fügen Sie in der ersten Zelle Ihres Notizbuchs die Werte in den folgenden
WorkspaceKonstruktor ein, um einworkspaceObjekt zu erstellen, das eine Verbindung mit Ihrem Azure Quantum-Arbeitsbereich herstellt.from qdk.azure import Workspace workspace = Workspace ( resource_id = "", # Add your resource_id location = "" # Add your workspace location (for example, "westus") )
Übermitteln von QIR-formatierten Schaltkreisen
Die Quantenzwischendarstellung (Quantum Intermediate Representation, QIR) ist eine Zwischendarstellung, die als allgemeine Schnittstelle zwischen Quantenprogrammiersprachen/-frameworks und zielgerichteten Quantencomputingplattformen fungiert. Weitere Informationen finden Sie unter Quantum Intermediate Representation.
Erstellen Sie den QIR-Schaltkreis. Der folgende Code erstellt z. B. einen einfachen Veranglement-Schaltkreis.
QIR_routine = """%Result = type opaque %Qubit = type opaque define void @ENTRYPOINT__main() #0 { call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*)) call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*)) call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*)) call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*)) call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*)) call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 3 to %Qubit*)) call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*)) call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 3 to %Qubit*)) call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1 call void @__quantum__rt__tuple_record_output(i64 2, i8* null) call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null) call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null) ret void } declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*) declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*) declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*) declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*) declare void @__quantum__qis__rx__body(double, %Qubit*) declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*) declare void @__quantum__qis__ry__body(double, %Qubit*) declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*) declare void @__quantum__qis__rz__body(double, %Qubit*) declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*) declare void @__quantum__qis__h__body(%Qubit*) declare void @__quantum__qis__s__body(%Qubit*) declare void @__quantum__qis__s__adj(%Qubit*) declare void @__quantum__qis__t__body(%Qubit*) declare void @__quantum__qis__t__adj(%Qubit*) declare void @__quantum__qis__x__body(%Qubit*) declare void @__quantum__qis__y__body(%Qubit*) declare void @__quantum__qis__z__body(%Qubit*) declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*) declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1 declare void @__quantum__rt__result_record_output(%Result*, i8*) declare void @__quantum__rt__array_record_output(i64, i8*) declare void @__quantum__rt__tuple_record_output(i64, i8*) attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="4" "required_num_results"="2" } attributes #1 = { "irreversible" } ; module flags !llvm.module.flags = !{!0, !1, !2, !3} !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} """Erstellen Sie eine
submit_qir_jobHilfsfunktion, um den QIR-Schaltkreis an eine target. Beachten Sie, dass die Eingabe- und Ausgabedatenformate entsprechendqir.v1microsoft.quantum-results.v1angegeben werden.# Submit the job with proper input and output data formats def submit_qir_job(target, input, name, count=100): job = target.submit( input_data=input, input_data_format="qir.v1", output_data_format="microsoft.quantum-results.v1", name=name, input_params = { "entryPoint": "ENTRYPOINT__main", "arguments": [], "count": count } ) print(f"Queued job: {job.id}") job.wait_until_completed() print(f"Job completed with state: {job.details.status}") #if job.details.status == "Succeeded": result = job.get_results() return resultWählen Sie einen target QIR-Schaltkreis aus, und übermitteln Sie sie an Azure Quantum. Um z. B. den QIR-Schaltkreis an den IonQ Simulator targetzu übermitteln:
target = workspace.get_targets(name="ionq.simulator") result = submit_qir_job(target, QIR_routine, "QIR routine") result{'Histogram': ['(0, 0)', 0.5, '(1, 1)', 0.5]}
Übermitteln eines Schaltkreises mit einem anbieterspezifischen Format an Azure Quantum
Neben QIR-Sprachen wie Q# oder Qiskit können Sie Quantenschaltungen in anbieterspezifischen Formaten an Azure Quantum übermitteln. Jeder Anbieter hat ein eigenes Format für die Darstellung von Quantenschaltungen.
Übermitteln eines Schaltkreises an IonQ im JSON-Format
Erstellen Sie eine Quantenschaltung mit dem sprachunabhängigen JSON-Format, das vom IonQ unterstützt wird, wie in der IonQ-API-Dokumentation targetsbeschrieben. So wird etwa im folgenden Beispiel eine Superposition zwischen drei Qubits erstellt:
circuit = { "qubits": 3, "circuit": [ { "gate": "h", "target": 0 }, { "gate": "cnot", "control": 0, "target": 1 }, { "gate": "cnot", "control": 0, "target": 2 }, ] }Übermitteln Sie den Schaltkreis an den IonQ target. Im folgenden Beispiel wird der IonQ-Simulator verwendet, der ein
Job-Objekt zurückgibt.target = workspace.get_targets(name="ionq.simulator") job = target.submit(circuit)Warten Sie, bis der Auftrag abgeschlossen ist, und rufen Sie dann die Ergebnisse ab.
results = job.get_results() print(results)..... {'duration': 8240356, 'histogram': {'0': 0.5, '7': 0.5}}Anschließend können die Ergebnisse mithilfe von Matplotlib visualisiert werden.
import pylab as pl pl.rcParams["font.size"] = 16 hist = {format(n, "03b"): 0 for n in range(8)} hist.update({format(int(k), "03b"): v for k, v in results["histogram"].items()}) pl.bar(hist.keys(), hist.values()) pl.ylabel("Probabilities")
Bevor Sie einen Auftrag auf der QPU ausführen, sollten Sie schätzen, wie viel die Ausführung kostet.
Hinweis
Die aktuellen Preisdetails finden Sie unter Preise. Suchen Sie alternativ nach Ihrem Arbeitsbereich, und zeigen Sie die Preisoptionen auf der Registerkarte „Anbieter“ Ihres Arbeitsbereichs über aka.ms/aq/myworkspaces an.
Übermitteln eines Schaltkreises an PASQAL mit Pulser SDK
Um einen Schaltkreis an PASQAL zu übermitteln, können Sie das Pulser SDK verwenden, um Impulssequenzen zu erstellen und an den PASQAL targetzu übermitteln.
Installieren des Pulser SDK
Pulser ist ein Framework zum Verfassen, Simulieren und Ausführen von Impulssequenzen für neutrale Atom-Quantengeräte. Es wurde von PASQAL als Pass-Through entwickelt, um Quantenexperimente an ihre Quantenprozessoren zu übermitteln. Weitere Informationen finden Sie in der Pulser-Dokumentation.
Um die Impulssequenzen zu übermitteln, installieren Sie zuerst die Pulser SDK-Pakete:
try:
import pulser
import pulser_pasqal
except ImportError:
!pip -q install pulser pulser-pasqal --index-url https://pypi.org/simple
Erstellen eines Quantenregisters
Sie müssen sowohl ein Register als auch ein Layout definieren, bevor Sie fortfahren. Das Register gibt an, wo Atome angeordnet werden sollen, während das Layout die Positionierung von Fallen angibt, die zum Erfassen und Strukturieren dieser Atome innerhalb des Registers erforderlich sind.
Ausführliche Informationen zu Layouts finden Sie in der Pulser-Dokumentation.
Zunächst erstellen Sie ein "Devices"-Objekt zum Importieren des PASQAL-Quantencomputers targetFresnel.
from pulser_pasqal import PasqalCloud devices = PasqalCloud().fetch_available_devices() QPU = devices["FRESNEL"]
Vorkalibrierungslayouts
Das Gerät definiert eine Liste der vordefinierten Layouts. Sie können Ihr Register aus einem dieser Layouts erstellen.
Dies ist die empfohlene Option, da sie die Leistung der QPU verbessert.
Option 1: Definieren Ihres Registers mithilfe von vorkalibrierungsbasierten Layouts
Überprüfen Sie die auf Fresnel verfügbaren Layouts, und definieren Sie Ihr Register aus diesem Layout. Weitere Informationen dazu finden Sie in der Pulserdokumentation.
Beispiel:
# let's say we are interested in the first layout available on the device layout = QPU.pre_calibrated_layouts[0] # Select traps 1, 3 and 5 of the layout to define the register traps = [1,3,5] reg = layout.define_register(*traps) # You can draw the resulting register to verify it matches your expectations reg.draw()
Beliebige Layouts
Wenn vordefinierte Layouts die Anforderungen Ihres Experiments nicht erfüllen, können Sie ein benutzerdefiniertes Layout erstellen.
Für jedes gegebene beliebige Register platziert eine neutrale Atom-QPU Fallen nach dem Layout, die dann einer Kalibrierung unterzogen werden müssen. Da jede Kalibrierung Zeit erfordert, ist es im Allgemeinen ratsam, ein vorhandenes kalibriertes Layout nach Möglichkeit wiederzuverwenden.
Option 2: Automatisches Ableiten eines Layouts aus dem definierten Register
Diese Option ermöglicht die automatische Generierung eines Layouts basierend auf einem angegebenen Register. Bei großen Registern kann dieser Prozess jedoch aufgrund von Einschränkungen im Algorithmus, der zum Erstellen des Layouts verwendet wird, suboptimale Lösungen liefern.
from pulser import Register qubits = { "q0": (0, 0), "q1": (0, 10), "q2": (8, 2), "q3": (1, 15), "q4": (-10, -3), "q5": (-8, 5), } reg = Register(qubits).with_automatic_layout(device)Option 3: Definieren Des Registers mithilfe eines manuell definierten Layouts
Erstellen eines beliebigen Layouts mit 20 Fallen, die zufällig in einer 2D-Ebene positioniert sind
import numpy as np from pulser.register.register_layout import RegisterLayout # Generating random coordinates np.random.seed(301122) # Keeps results consistent between runs traps = np.random.randint(0, 30, size=(20, 2)) traps = traps - np.mean(traps, axis=0) # Creating the layout layout = RegisterLayout(traps, slug="random_20")- Definieren Des Registers mit bestimmten Trap-IDs
trap_ids = [4, 8, 19, 0] reg = layout.define_register(*trap_ids, qubit_ids=["a", "b", "c", "d"]) reg.draw()
Schreiben einer Impulssequenz
Die neutralen Atome werden mit Laserpulsen gesteuert. Mit dem Pulser SDK können Sie Impulssequenzen erstellen, die auf das Quantenregister angewendet werden.
Zunächst definieren Sie die Impulssequenzattribute, indem Sie die Kanäle deklarieren, die zum Steuern der Atome verwendet werden. Zum Erstellen eines
Sequence, müssen Sie eineRegisterInstanz zusammen mit dem Gerät bereitstellen, auf dem die Sequenz ausgeführt wird. Der folgende Code deklariert beispielsweise einen Kanal:ch0.Hinweis
Sie können das
QPU = devices["FRESNEL"]Gerät verwenden oder ein virtuelles Gerät aus Pulser importieren, um mehr Flexibilität zu erhalten. Die Verwendung einerVirtualDeviceErmöglicht die Sequenzerstellung, die von Gerätespezifikationen weniger eingeschränkt ist, sodass sie für die Ausführung in einem Emulator geeignet ist. Weitere Informationen finden Sie in der Pulser-Dokumentation.from pulser import Sequence seq = Sequence(reg, QPU) # print the available channels for your sequence print(seq.available_channels) # Declare a channel. In this example we will be using `rydberg_global` seq.declare_channel("ch0", "rydberg_global")Fügen Sie Ihrer Sequenz Impulse hinzu. Dazu erstellen und fügen Sie Impulse zu den kanälen hinzu, die Sie deklariert haben. Der folgende Code erstellt z. B. einen Impuls und fügt ihn dem Kanal
ch0hinzu.from pulser import Pulse from pulser.waveforms import RampWaveform, BlackmanWaveform import numpy as np amp_wf = BlackmanWaveform(1000, np.pi) det_wf = RampWaveform(1000, -5, 5) pulse = Pulse(amp_wf, det_wf, 0) seq.add(pulse, "ch0") seq.draw()Die folgende Abbildung zeigt die Impulssequenz.
Konvertieren der Sequenz in eine JSON-Zeichenfolge
Um die Impulssequenzen zu übermitteln, müssen Sie die Pulser-Objekte in eine JSON-Zeichenfolge konvertieren, die als Eingabedaten verwendet werden kann.
import json
# Convert the sequence to a JSON string
def prepare_input_data(seq):
input_data = {}
input_data["sequence_builder"] = json.loads(seq.to_abstract_repr())
to_send = json.dumps(input_data)
return to_send
Übermitteln der Impulssequenz an PASQAL target
Zunächst müssen Sie die richtigen Eingabe- und Ausgabedatenformate festlegen. Der folgende Code legt z. B. das Eingabedatenformat
pasqal.pulser.v1und das Ausgabedatenformat aufpasqal.pulser-results.v1.# Submit the job with proper input and output data formats def submit_job(target, seq, shots): job = target.submit( input_data=prepare_input_data(seq), # Take the JSON string previously defined as input data input_data_format="pasqal.pulser.v1", output_data_format="pasqal.pulser-results.v1", name="PASQAL sequence", shots=shots # Number of shots ) print(f"Queued job: {job.id}") return jobHinweis
Die zum Ausführen eines Auftrags auf der QPU erforderliche Zeit hängt von den aktuellen Warteschlangenzeiten ab. Sie können die durchschnittliche Warteschlangenzeit für ein Objekt target anzeigen, indem Sie das Blatt "Anbieter " Ihres Arbeitsbereichs auswählen.
Übermitteln Sie das Programm an PASQAL. Bevor Sie Ihren Code an echte Quantenhardware übermitteln, können Sie Ihren Code mit dem Emulator
pasqal.sim.emu-tnals target testen.target = workspace.get_targets(name="pasqal.sim.emu-tn") # Change to "pasqal.qpu.fresnel" to use Fresnel QPU job = submit_job(target, seq, 10) job.wait_until_completed() print(f"Job completed with state: {job.details.status}") result = job.get_results() print(result){ "1000000": 3, "0010000": 1, "0010101": 1 }
Übermitteln eines Schaltkreises an Quantinuum mit OpenQASM
Erstellen Sie eine Quantenschaltung in der OpenQASM-Darstellung. Im folgenden Beispiel wird etwa eine Teleportationsschaltung erstellt:
circuit = """OPENQASM 2.0; include "qelib1.inc"; qreg q[3]; creg c0[3]; h q[0]; cx q[0], q[1]; cx q[1], q[2]; measure q[0] -> c0[0]; measure q[1] -> c0[1]; measure q[2] -> c0[2]; """Die Schaltung kann optional auch aus einer Datei geladen werden:
with open("my_teleport.qasm", "r") as f: circuit = f.read()Übermitteln Sie den Schaltkreis an das Quantinuum target. Im folgenden Beispiel wird die Quantinuum-API-Validierung verwendet, die ein
Job-Objekt zurückgibt.target = workspace.get_targets(name="quantinuum.sim.h2-1sc") job = target.submit(circuit, shots=500)Warten Sie, bis der Auftrag abgeschlossen ist, und rufen Sie dann die Ergebnisse ab.
results = job.get_results() print(results)........ {'c0': ['000', '000', '000', '000', '000', '000', '000', ... ]}Anschließend können die Ergebnisse mithilfe von Matplotlib visualisiert werden.
import pylab as pl pl.hist(results["c0"]) pl.ylabel("Counts") pl.xlabel("Bitstring")
Wenn Sie das Histogramm betrachten, stellen Sie möglicherweise fest, dass der Zufallszahlengenerator jedes Mal 0 zurückgegeben hat, was nicht sehr zufällig ist. Das liegt daran, dass die API-Validierung zwar sicherstellt, dass Ihr Code erfolgreich auf Quantinuum-Hardware ausgeführt wird, aber auch 0 für jede Quantenmessung zurückgegeben wird. Für einen echten Zufallszahlengenerator müssen Sie Ihre Schaltung auf Quantenhardware ausführen.
Bevor Sie einen Auftrag auf der QPU ausführen, sollten Sie schätzen, wie viel die Ausführung kostet.
Hinweis
Die aktuellsten Preisdetails finden Sie unter Azure Quantum-Preise, oder suchen Sie Ihren Arbeitsbereich und zeigen Sie Preisoptionen auf der Registerkarte "Anbieter" Ihres Arbeitsbereichs über: aka.ms/aq/myworkspaces an.
Übermitteln eines Schaltkreises an Rigetti mithilfe von Quil
Die einfachste Möglichkeit zum Übermitteln von Quil-Aufträgen ist die Verwendung des pyquil-for-azure-quantum-Pakets , da Sie die Tools und Dokumentationen der pyQuil-Bibliothek verwenden können. Ohne dieses Paket kann pyQuil verwendet werden, um Quil-Programme zu erstellen , aber nicht, um sie an Azure Quantum zu übermitteln.
Sie können quil-Programme auch manuell erstellen und mithilfe des azure-quantum Pakets direkt übermitteln.
Laden Sie zunächst die erforderlichen Importe.
from pyquil.gates import CNOT, MEASURE, H from pyquil.quil import Program from pyquil.quilbase import Declare from pyquil_for_azure_quantum import get_qpu, get_qvmVerwenden Sie die
get_qvmFunktion,get_qpuum eine Verbindung mit QVM oder QPU abzurufen.qc = get_qvm() # For simulation # qc = get_qpu("Ankaa-3") for submitting to a QPUErstellen Sie ein Quil-Programm. Jedes gültige Quil-Programm wird akzeptiert, aber das Lesen muss benannt
rowerden.program = Program( Declare("ro", "BIT", 2), H(0), CNOT(0, 1), MEASURE(0, ("ro", 0)), MEASURE(1, ("ro", 1)), ).wrap_in_numshots_loop(5) # Optionally pass to_native_gates=False to .compile() to skip the compilation stage result = qc.run(qc.compile(program)) data_per_shot = result.readout_data["ro"]data_per_shotHier ist einnumpyArray, sodass Sie Methoden verwendennumpykönnen.assert data_per_shot.shape == (5, 2) ro_data_first_shot = data_per_shot[0] assert ro_data_first_shot[0] == 1 or ro_data_first_shot[0] == 0Drucken Sie alle Daten aus.
print("Data from 'ro' register:") for i, shot in enumerate(data_per_shot): print(f"Shot {i}: {shot}")
Wichtig
Sie können nicht mehrere Schaltkreise an einem einzigen Auftrag übermitteln. Sie können allerdings die Methode backend.run aufrufen, um die einzelnen Schaltungen asynchron zu übermitteln, und anschließend die Ergebnisse jedes Auftrags abrufen. Zum Beispiel:
jobs = []
for circuit in circuits:
jobs.append(backend.run(circuit, shots=N))
results = []
for job in jobs:
results.append(job.result())