Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dowiedz się, jak przesłać obwód kwantowy Qiskit przy użyciu zestawu Azure Quantum Development Kit (QDK). Obwody Qiskit można przesyłać do usługi Azure Quantum przy użyciu zestawu Azure Quantum Development Kit (QDK) i notesu Jupyter w programie Visual Studio Code (VS Code). Możesz również przetestować obwody przy użyciu lokalnego symulatora rozrzedzego. Zestaw QDK obsługuje wersje 1 i 2 zestawu Qiskit.
Aby uzyskać więcej informacji, zobacz Quantum circuits (Obwody kwantowe).
Wymagania wstępne
Aby uzyskać szczegółowe informacje na temat instalacji, zobacz Konfigurowanie rozszerzenia zestawu QDK.
Obszar roboczy usługi Azure Quantum w ramach subskrypcji platformy Azure. Aby utworzyć obszar roboczy, zobacz Tworzenie obszaru roboczego usługi Azure Quantum.
Środowisko Python z zainstalowanym programem Python i programem .
Program VS Code z zainstalowanym zestawem Azure Quantum Development Kit i Pythonrozszerzeniami Jupyter.
Biblioteka
qdkPython z dodatkamiazureiqiskitoraz pakietemipykernel.python -m pip install --upgrade "qdk[azure,qiskit]" ipykernel
Tworzenie nowego notesu Jupyter
- W programie VS Code otwórz menu Widok i wybierz pozycję Paleta poleceń.
- Wprowadź i wybierz Utwórz: Nowy Jupyter Notebook.
- Program VS Code wykrywa i wyświetla wersję Python oraz wybrane dla notesu środowisko wirtualne Python. Jeśli masz wiele Python środowisk, może być konieczne wybranie jądra przy użyciu selektora jądra w prawym górnym rogu. Jeśli środowisko nie zostało wykryte, zobacz Jupyter Notebooks in VS Code (Notesy Jupyter Notebooks w programie VS Code ), aby uzyskać informacje o konfiguracji.
Ładowanie wymaganych importów
W pierwszej komórce notesu uruchom następujący kod, aby załadować wymagane importy:
from qdk.azure import Workspace
from qdk.azure.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
Nawiązywanie połączenia z usługą Azure Quantum
Aby nawiązać połączenie z usługą Azure Quantum, potrzebny jest identyfikator zasobu i lokalizacja obszaru roboczego usługi Azure Quantum.
- Zaloguj się do konta platformy Azure. https://portal.azure.com
- Wybierz swój obszar roboczy usługi Azure Quantum i przejdź do obszaru Przegląd.
- Skopiuj Identyfikator zasobu i Lokalizacja.
Dodaj nową komórkę w notesie i użyj informacji o koncie, aby utworzyć Workspace obiekty i AzureQuantumProvider połączyć się z obszarem roboczym usługi Azure Quantum.
workspace = Workspace(
resource_id = "", # Add the resourceID of your workspace
location = "" # Add the location of your workspace (for example "westus")
)
provider = AzureQuantumProvider(workspace)
Wyświetlanie listy wszystkich zapleczy
Teraz możesz wydrukować wszystkie zaplecza obliczeń kwantowych, które są dostępne w obszarze roboczym:
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
Uruchamianie prostego obwodu
W nowej komórce utwórz prosty obwód Qiskit.
# 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
Wybierz element target , aby uruchomić program
Uruchamianie w symulatorze IonQ
Przed uruchomieniem obwodu na rzeczywistym sprzęcie przetestuj obwód w symulatorze. Użyj get_backend polecenia , aby utworzyć obiekt w celu nawiązania połączenia z zapleczem Backend symulatora IonQ:
simulator_backend = provider.get_backend("ionq.simulator")
Zaplecza IonQ obsługują bramy ze zdefiniowanego zestawu bram, które są kompilowane w celu optymalnego działania na sprzęcie. Jeśli obwód zawiera bramy, które nie znajdują się na tej liście, należy przeprowadzić transpilowanie do obsługiwanej gateset funkcji udostępnionej transpile przez zestaw Qiskit:
from qiskit import transpile
circuit = transpile(circuit, simulator_backend)
Funkcja transpilu zwraca nowy obiekt obwodu, w którym bramy są rozłożone na bramy obsługiwane w określonym zapleczu.
Teraz możesz uruchomić program za pośrednictwem usługi Azure Quantum i uzyskać wynik. Poniższa komórka przesyła zadanie, które uruchamia obwód z 100 strzałami:
job = simulator_backend.run(circuit, shots=8)
job_id = job.id()
print("Job id", job_id)
Job id 00000000-0000-0000-0000-000000000000
Aby poczekać na ukończenie zadania i zwrócić wyniki, uruchom polecenie:
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)
Ponieważ wynik jest typem obiektu specyficznym dla pakietu Qiskit, użyj result.get_counts i plot_histogram, aby zwizualizować wyniki. Aby przedstawić wszystkie możliwe etykiety bitów, dodaj etykiety do elementu counts.
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}
Możesz również użyć funkcji get_memory, aby wyświetlić pojedyncze dane zdjęć z danego zadania:
result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']
Uwaga
Na IonQ targets, jeśli przesyłasz zadanie z nieparzystą liczbą strzałów, liczba strzałów jest zaokrąglona w dół do najbliższej liczby parzystej. Jeśli na przykład określisz 9 zdjęć, wyniki wyświetlają dane dla 8 zdjęć.
Szacowanie kosztu zadania
Oszacuj, ile kosztuje uruchomienie zadania, zanim uruchomisz zadanie w QPU.
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.
Uruchamianie na QPU IonQ
Aby nawiązać połączenie z rzeczywistym sprzętem (jednostka procesora kwantowego (QPU)), wystarczy podać nazwę target"ionq.qpu.aria-1"get_backend metody :
qpu_backend = provider.get_backend("ionq.qpu.aria-1")
Prześlij obwód do uruchomienia w usłudze Azure Quantum, pobierz wyniki, a następnie uruchom polecenie plot_histogram , aby wykreślić wyniki.
Uwaga
Czas wymagany do uruchomienia obwodu na QPU zależy od bieżących czasów kolejki.
# 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}
Ważne
Nie można przesłać wielu obwodów w jednym zadaniu. Aby obejść ten problem, możesz wywołać metodę backend.run, 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())
Wymagania wstępne
Aby uzyskać szczegółowe informacje na temat instalacji, zobacz Konfigurowanie rozszerzenia zestawu QDK.
Środowisko Python z zainstalowanym programem Python i programem .
Program VS Code z zainstalowanym zestawem Azure Quantum Development Kit i Python rozszerzeniami.
Pakiet
qdkPython z dodatkiemqiskitijupyter.python pip install "qdk[qiskit,jupyter]"
Uruchamianie obwodu podstawowego
W programie VS Code otwórz nowy plik Python, aby utworzyć i uruchomić podstawowy obwód z wbudowanym symulatorem rzadkim z modułu qsharp.
# 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)
Aby uruchomić program, wybierz ikonę Uruchom w prawym górnym rogu i wybierz pozycję Uruchom Python plik. Dane wyjściowe zostaną wyświetlone w nowym oknie terminalu.
┌─────────────────────────┐┌─┐
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}
Generowanie QIR dla obwodu
Z tego samego obwodu można wygenerować funkcję QIR używaną do uruchamiania na sprzęcie kwantowym.
Uwaga
Aby wygenerować QIR, wszystkie rejestry muszą być mierzone. Jeśli istnieją jakiekolwiek nieużywane rejestry, zostanie zgłoszony błąd. Ponadto podczas próby wygenerowania QIR z użyciem profilu Unrestrictedtarget występuje błąd. Profil Unrestricted jest prawidłowy tylko w przypadku symulacji. Musisz użyć TargetProfile.Base, TargetProfile.Adaptive_RI lub TargetProfile.Adaptive_RIF. Możesz zastąpić target_profile w wywołaniu backend.qir(...), aby przełączyć profile.
Importowanie
QSharpErroriTargetProfilefrom qdk.qsharp import QSharpError, TargetProfileAby wygenerować QIR, zmodyfikuj dane wyjściowe:
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
Kod powinien teraz wyglądać następująco:
# 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))
Dane wyjściowe kodu powinny wyglądać następująco:
┌────────────┐ ┌─┐
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}
Nie wszystkie programy mogą być uruchamiane na całym sprzęcie. W tym miejscu, jeśli spróbujesz utworzyć targetBase profil, zostaną wyświetlone szczegółowe błędy dotyczące tego, które części programu nie są obsługiwane.
try:
backend.qir(qc, target_profile=TargetProfile.Base)
except QSharpError as e:
print(e)