Jak przesłać określone sformatowane obwody do usługi Azure Quantum
Dowiedz się, jak używać azure-quantum
Python pakietu do przesyłania obwodów w określonych formatach do usługi Azure Quantum. W tym artykule przedstawiono sposób przesyłania obwodów w następujących formatach:
Aby uzyskać więcej informacji, zobacz Quantum circuits (Obwody kwantowe).
Uwaga
Zestaw Microsoft Quantum Development Kit (klasyczny zestaw QDK) nie będzie już obsługiwany po 30 czerwca 2024 r. Jeśli jesteś istniejącym deweloperem zestawu QDK, zalecamy przejście do nowego zestawu Azure Quantum Development Kit (Modern QDK), aby kontynuować opracowywanie rozwiązań kwantowych. Aby uzyskać więcej informacji, zobacz Migrowanie kodu Q# do nowoczesnego zestawu QDK.
Wymagania wstępne
Aby uruchomić obwody w notesie w witrynie Azure Portal, potrzebne są następujące elementy:
- Konto platformy Azure z aktywną subskrypcją. Jeśli nie masz konta platformy Azure, zarejestruj się bezpłatnie i zarejestruj się w celu korzystania z subskrypcji z płatnością zgodnie z rzeczywistym użyciem.
- Obszar roboczy usługi Azure Quantum. Aby uzyskać więcej informacji, zobacz Tworzenie obszaru roboczego usługi Azure Quantum.
Aby opracowywać i uruchamiać obwody w programie Visual Studio Code, potrzebne są również następujące elementy:
Środowisko Python z zainstalowanym programem Python i programem Pip .
Program VS Code z zainstalowanym zestawem Azure Quantum Development Kit i Pythonrozszerzeniami Jupyter.
Pakiet Azure Quantum
qsharp
,azure-quantum
iipykernel
.python -m pip install --upgrade qsharp azure-quantum ipykernel
Tworzenie nowego notesu Jupyter
Notes można utworzyć w programie VS Code lub bezpośrednio w witrynie Azure Quantum Portal.
- Zaloguj się do witryny Azure Portal i wybierz obszar roboczy z poprzedniego kroku.
- W bloku po lewej stronie wybierz pozycję Notesy.
- Kliknij pozycję Moje notesy i kliknij pozycję Dodaj nowy.
- W obszarze Typ jądra wybierz pozycję IPython.
- Wpisz nazwę pliku, a następnie kliknij przycisk Utwórz plik.
Po otwarciu nowego notesu automatycznie tworzy kod dla pierwszej komórki na podstawie informacji o subskrypcji i obszarze roboczym.
from azure.quantum import Workspace
workspace = Workspace (
resource_id = "", # Your resource_id
location = "" # Your workspace location (for example, "westus")
)
Przesyłanie obwodów w formacie QIR
Quantum Intermediate Representation (QIR) to pośrednia reprezentacja, która służy jako wspólny interfejs między językami/strukturami programowania kwantowego i targetplatformami obliczeń kwantowych. Aby uzyskać więcej informacji, zobacz Quantum Intermediate Representation (Reprezentacja pośrednia kwantowa).
Utwórz obwód QIR. Na przykład poniższy kod tworzy prosty obwód splątania.
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} """
submit_qir_job
Utwórz funkcję pomocnika, aby przesłać obwód QIR do elementu target. Należy pamiętać, że formaty danych wejściowych i wyjściowych są określane odpowiednio jakoqir.v1
imicrosoft.quantum-results.v1
.# 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 result
target Wybierz obwód QIR i prześlij go do usługi Azure Quantum. Aby na przykład przesłać obwód QIR do symulatora targetIonQ:
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]}
Przesyłanie obwodu z formatem specyficznym dla dostawcy do usługi Azure Quantum
Oprócz języków QIR, takich jak Q# lub Qiskit, można przesyłać obwody kwantowe w formatach specyficznych dla dostawcy do usługi Azure Quantum. Każdy dostawca ma własny format reprezentujący obwody kwantowe.
Przesyłanie obwodu do usługi IonQ przy użyciu formatu JSON
Utwórz obwód kwantowy przy użyciu niezależnego od języka formatu JSON obsługiwanego przez IonQ targets, zgodnie z opisem w dokumentacji interfejsu API IonQ. Na przykład poniższy przykład tworzy superpozycję między trzema kubitami:
circuit = { "qubits": 3, "circuit": [ { "gate": "h", "target": 0 }, { "gate": "cnot", "control": 0, "target": 1 }, { "gate": "cnot", "control": 0, "target": 2 }, ] }
Prześlij obwód do IonQ target. W poniższym przykładzie użyto symulatora IonQ, który zwraca
Job
obiekt.target = workspace.get_targets(name="ionq.simulator") job = target.submit(circuit)
Poczekaj, aż zadanie zostanie ukończone, a następnie pobierz wyniki.
results = job.get_results() print(results)
..... {'duration': 8240356, 'histogram': {'0': 0.5, '7': 0.5}}
Następnie można wizualizować wyniki przy użyciu biblioteki Matplotlib.
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")
Przed uruchomieniem zadania w QPU można oszacować, ile będzie kosztować uruchomienie. Aby oszacować koszt uruchamiania zadania w QPU, możesz użyć
estimate_cost
metody :target = workspace.get_targets(name="ionq.qpu") cost = target.estimate_cost(circuit, shots=500) print(f"Estimated cost: {cost.estimated_total}")
Spowoduje to wyświetlenie szacowanych kosztów w USD.
Uwaga
Aby uzyskać najbardziej aktualne szczegóły cennika, zobacz Cennik IonQ lub znajdź obszar roboczy i wyświetl opcje cennika na karcie "Dostawca" obszaru roboczego za pośrednictwem: aka.ms/aq/myworkspaces.
Przesyłanie obwodu do biblioteki PASQAL przy użyciu zestawu SDK pulsera
Aby przesłać obwód do ZESTAWU PASQAL, możesz użyć zestawu SDK pulsera do tworzenia sekwencji impulsów i przesyłania ich do zestawu PASQAL target.
Instalowanie zestawu SDK pulsera
Pulser to struktura do komponowania, symulowania i wykonywania sekwencji impulsów dla urządzeń kwantowych neutral-atom. Jest on zaprojektowany przez PASQAL jako przekazywanie w celu przesyłania eksperymentów kwantowych do ich procesorów kwantowych. Aby uzyskać więcej informacji, zobacz dokumentację pulsera.
Aby przesłać sekwencje impulsów, najpierw zainstaluj pakiety zestawu SDK pulsera:
try:
import pulser
except ImportError:
!pip -q install pulser
!pip -q install pulser-core
Tworzenie rejestru kwantowego
Najpierw załaduj wymagane importy:
import numpy as np import pulser from pprint import pprint from pulser import Pulse, Sequence, Register
QPU PASQAL składa się z neutralnych atomów uwięzionych w dobrze zdefiniowanych pozycjach w kratce. Aby zdefiniować rejestry kwantowe, należy utworzyć tablicę kubitów na daszku. Na przykład poniższy kod tworzy 4x4 kwadratową siatkę kubitów:
L = 4 square = np.array([[i, j] for i in range(L) for j in range(L)], dtype=float) square -= np.mean(square, axis=0) square *= 5 qubits = dict(enumerate(square)) reg = Register(qubits) reg.draw()
Pisanie sekwencji impulsów
Neutralne atomy są kontrolowane za pomocą impulsów laserowych. Zestaw SDK pulsera umożliwia tworzenie sekwencji impulsów, które mają być stosowane do rejestru kwantowego.
Najpierw należy skonfigurować sekwencję impulsów i zadeklarować kanały, które będą używane do kontrolowania atomów. Na przykład następujący kod deklaruje dwa kanały:
ch0
ich1
.from pulser.devices import Chadoq2 seq = Sequence(reg, Chadoq2) seq.declare_channel("ch0", "raman_local") print("Available channels after declaring 'ch0':") pprint(seq.available_channels) seq.declare_channel("ch1", "rydberg_local", initial_target=4) print("\nAvailable channels after declaring 'ch1':") pprint(seq.available_channels)
Kilka kwestii, które należy wziąć pod uwagę:
- A
Sequence
in Pulser to seria operacji, które mają być wykonywane w rejestrze kwantowym. - Kod konfiguruje sekwencję operacji do wykonania na urządzeniu
AnalogDevice
.AnalogDevice
jest wstępnie zdefiniowanym urządzeniem w pulserze, które reprezentuje komputer kwantowy fresnel1.
- A
Utwórz sekwencję impulsów. W tym celu należy utworzyć i dodać impulsy do zadeklarowanych kanałów. Na przykład poniższy kod tworzy prosty impuls i dodaje go do kanału
ch0
, a następnie tworzy złożony impuls i dodaje go do kanałuch1
.seq.target(1, "ch0") # Target qubit 1 with channel "ch0" simple_pulse = Pulse.ConstantPulse(200, 2, -10, 0) seq.add(simple_pulse, "ch0") # Add the pulse to channel "ch0" seq.delay(100, "ch1") from pulser.waveforms import RampWaveform, BlackmanWaveform duration = 1000 # Create a Blackman waveform with a duration of 1000 ns and an area of pi/2 rad amp_wf = BlackmanWaveform(duration, np.pi / 2) # Create a ramp waveform with a duration of 1000 ns and a linear sweep from -20 to 20 rad/µs detuning_wf = RampWaveform(duration, -20, 20) # Create a pulse with the amplitude waveform amp_wf, the detuning waveform detuning_wf, and a phase of 0 rad. complex_pulse = Pulse(amp_wf, detuning_wf, phase=0) complex_pulse.draw() seq.add(complex_pulse, "ch1") # Add the pulse to channel "ch1"
Obraz przedstawia prosty i złożony impuls.
Konwertowanie sekwencji na ciąg JSON
Aby przesłać sekwencje impulsów, należy przekonwertować obiekty Pulser na ciąg JSON, który może być używany jako dane wejściowe.
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)
#print(json.dumps(input_data, indent=4, sort_keys=True))
return to_send
Przesyłanie sekwencji impulsów do USŁUGI PASQAL target
Najpierw należy ustawić odpowiednie formaty danych wejściowych i wyjściowych. Na przykład poniższy kod ustawia format danych wejściowych na
pasqal.pulser.v1
, a format danych wyjściowych napasqal.pulser-results.v1
wartość .# Submit the job with proper input and output data formats def submit_job(target, seq): 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=100 # Number of shots ) print(f"Queued job: {job.id}") job.wait_until_completed() print(f"Job completed with state: {job.details.status}") result = job.get_results() return result
Uwaga
Czas wymagany do uruchomienia obwodu na QPU zależy od bieżących czasów kolejki. Średni czas kolejki dla elementu target można wyświetlić, wybierając blok Dostawcy obszaru roboczego.
Prześlij program do APLIKACJI PASQAL. Możesz na przykład przesłać program do PASQAL Emu-TN target.
target = workspace.get_targets(name="pasqal.sim.emu-tn") submit_job(target, seq)
{'0000000000000000': 59, '0000100000000000': 39, '0100000000000000': 1, '0100100000000000': 1}
Przesyłanie obwodu do quantinuum przy użyciu programu OpenQASM
Utwórz obwód kwantowy w reprezentacji OpenQASM . Na przykład poniższy przykład tworzy obwód teleportacji:
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]; """
Opcjonalnie można załadować obwód z pliku:
with open("my_teleport.qasm", "r") as f: circuit = f.read()
Prześlij obwód do kwantynauum target. W poniższym przykładzie użyto modułu sprawdzania poprawności interfejsu API Quantinuum, który zwraca
Job
obiekt.target = workspace.get_targets(name="quantinuum.sim.h1-1sc") job = target.submit(circuit, shots=500)
Poczekaj, aż zadanie zostanie ukończone, a następnie pobierz wyniki.
results = job.get_results() print(results)
........ {'c0': ['000', '000', '000', '000', '000', '000', '000', ... ]}
Następnie można wizualizować wyniki przy użyciu biblioteki Matplotlib.
import pylab as pl pl.hist(results["c0"]) pl.ylabel("Counts") pl.xlabel("Bitstring")
Patrząc na histogram, można zauważyć, że generator liczb losowych zwrócił 0 za każdym razem, co nie jest bardzo losowe. Jest to spowodowane tym, że podczas gdy moduł sprawdzania poprawności interfejsu API gwarantuje, że kod zostanie pomyślnie uruchomiony na sprzęcie Quantinuum, zwraca również wartość 0 dla każdego pomiaru kwantowego. W przypadku rzeczywistego generatora liczb losowych należy uruchomić obwód na sprzęcie kwantowym.
Przed uruchomieniem zadania w QPU można oszacować, ile będzie kosztować uruchomienie. Aby oszacować koszt uruchamiania zadania w QPU, możesz użyć
estimate_cost
metody .target = workspace.get_targets(name="quantinuum.qpu.h1-1") cost = target.estimate_cost(circuit, shots=500) print(f"Estimated cost: {cost.estimated_total}")
Spowoduje to wyświetlenie szacowanych kosztów w H-System Quantum Credit (HQCs).
Uwaga
Aby uruchomić oszacowanie kosztów względem kwantuum target, należy najpierw ponownie załadować pakiet azure-quantumPython za pomocą parametru [qiskit] i upewnić się, że masz najnowszą wersję zestawu Qiskit. Aby uzyskać więcej informacji, zobacz Aktualizowanie pakietu azure-quantumPython.
Uwaga
Aby uzyskać najbardziej aktualne szczegóły cennika, zobacz Cennik usługi Azure Quantum lub znajdź obszar roboczy i wyświetl opcje cennika na karcie "Dostawca" obszaru roboczego za pośrednictwem: aka.ms/aq/myworkspaces.
Przesyłanie obwodu do Rigetti przy użyciu Quil
Najprostszym sposobem przesyłania zadań Quil jest użycie pakietu pyquil-for-azure-quantum , ponieważ umożliwia korzystanie z narzędzi i dokumentacji biblioteki pyQuil . Bez tego pakietu narzędzie pyQuil może służyć do konstruowania programów Quil, ale nie do przesyłania ich do usługi Azure Quantum.
Można również tworzyć programy Quil ręcznie i przesyłać je bezpośrednio przy użyciu azure-quantum
pakietu.
Najpierw załaduj wymagane importy.
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_qvm
get_qvm
Użyj funkcji orget_qpu
, aby uzyskać połączenie z maszyną QVM lub QPU.qc = get_qvm() # For simulation # qc = get_qpu("Ankaa-2") for submitting to a QPU
Utwórz program Quil. Każdy prawidłowy program Quil jest akceptowany, ale odczyt musi mieć nazwę
ro
.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_shot
W tym miejscu znajduje się tablicanumpy
, dzięki czemu można użyćnumpy
metod.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] == 0
Wydrukuj wszystkie dane.
print("Data from 'ro' register:") for i, shot in enumerate(data_per_shot): print(f"Shot {i}: {shot}")
Ważne
Przesyłanie wielu obwodów w jednym zadaniu nie jest obecnie obsługiwane. Aby obejść ten problem, możesz wywołać backend.run
metodę , aby przesłać każdy obwód asynchronicznie, a następnie pobrać wyniki każdego zadania. Na przykład:
jobs = []
for circuit in circuits:
jobs.append(backend.run(circuit, shots=N))
results = []
for job in jobs:
results.append(job.result())
Powiązana zawartość
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla