Отправка канала с помощью Qiskit в Azure Quantum
Узнайте, как отправить квантовый канал Qiskit с помощью azure-quantum
Python пакета. Каналы Qiskit можно отправить в Azure Quantum с помощью записной книжки Azure Quantum, которая имеет встроенный azure-quantum
Python пакет или на локальном компьютере. Вы также можете протестировать каналы с помощью локального разреженного симулятора.
Дополнительные сведения см. в разделе Квантовые цепи.
Необходимые компоненты
Дополнительные сведения об установке см. в разделе Настройка расширения QDK.
Рабочая область Azure Quantum по подписке Azure. Сведения о создании рабочей области см. в статье Создание рабочей области Azure Quantum.
Среда сPythonустановленной Python программой Pip.
VS Code с установленными расширениями Jupyter для Azure Quantum Development KitPython и Jupyter.
Пакет Azure Quantum
azure-quantum
Python с тегом [qiskit].python -m pip install --upgrade azure-quantum[qiskit] qsharp ipykernel
Внимание
Убедитесь, что у вас установлена последняя версия Qiskit. Дополнительные сведения см. в статье Python Azure-Quantum.
Примечание.
Если ядро Python Jupyter
ipykernel
не обнаружено, VS Code предложит установить его.
Создание новой записной книжки Jupyter Notebook
- В VS Code выберите > команд view и нажмите кнопку Create: New Jupyter Notebook.
- В правом верхнем углу VS Code обнаружит и отобразит версию виртуальной PythonPython среды, выбранной для записной книжки. Если у вас несколько Python сред, может потребоваться выбрать ядро с помощью средства выбора ядра в правом верхнем углу. Если среда не обнаружена, сведения о настройке см . в записных книжках Jupyter Notebook в VS Code .
Загрузка необходимых объектов импорта
В первой ячейке записной книжки выполните следующий код, чтобы загрузить необходимые импорты:
import azure.quantum
from azure.quantum import Workspace
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from azure.quantum.qiskit import AzureQuantumProvider
Подключение к службе Azure Quantum
Чтобы подключиться к службе Azure Quantum, вам потребуется идентификатор ресурса и расположение рабочей области Azure Quantum.
Вход в учетную запись Azure, https://portal.azure.com
Выберите рабочую область Azure Quantum и перейдите к обзору.
Скопируйте параметры в полях.
Добавьте новую ячейку в записную книжку и используйте сведения об учетной записи для создания Workspace
и AzureQuantumProvider
подключения объектов к рабочей области 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)
Вывод списка всех серверных компонентов
Теперь можно распечатать все серверные компоненты квантовых вычислений, доступные в рабочей области.
print("This workspace's targets:")
for backend in provider.backends():
print("- " + backend.name())
This workspace's targets:
- ionq.qpu
- ionq.qpu.aria-1
- ionq.simulator
- microsoft.estimator
- quantinuum.hqs-lt-s1
- quantinuum.hqs-lt-s1-apival
- quantinuum.hqs-lt-s2
- quantinuum.hqs-lt-s2-apival
- quantinuum.hqs-lt-s1-sim
- quantinuum.hqs-lt-s2-sim
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-9q-3
- rigetti.qpu.ankaa-3
Выполнение простой цепи
Сначала создайте простую цепь 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
Выберите программу target для запуска
Запуск в симуляторе IonQ
Прежде чем работать на реальном оборудовании, давайте протестируем канал в симуляторе. Используется get_backend
для создания Backend
объекта для подключения к серверной части симулятора IonQ:
simulator_backend = provider.get_backend("ionq.simulator")
Серверная часть IonQ поддерживает шлюзы из определенного набора шлюзов, которые компилируются для оптимального выполнения на оборудовании. Если канал содержит шлюзы, которые не указаны в этом списке, необходимо транспилировать в поддерживаемую gateset
функцию, предоставляемую transpile
Qiskit:
from qiskit import transpile
circuit = transpile(circuit, simulator_backend)
Функция транспиля возвращает новый объект канала, в котором шлюзы разложены в шлюзы, поддерживаемые на указанной серверной части.
Теперь можно запустить программу через службу Azure Quantum и получить результат. Следующая ячейка отправляет задание, которое запускает цепь со 100 снимками:
job = simulator_backend.run(circuit, shots=8)
job_id = job.id()
print("Job id", job_id)
Job id 00000000-0000-0000-0000-000000000000
Чтобы дождаться завершения задания и вернуть результаты, выполните:
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)
Так как результатом будет собственный объект пакета Qiskit, можно использовать result.get_counts
и plot_histogram
Qiskit для визуализации результатов. Чтобы гарантировать представление всех возможных меток в виде последовательности битов, добавьте их в 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}
Вы также можете использовать функцию get_memory()
для отображения отдельных данных снимка из задания.
result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']
Примечание.
При отправке задания с нечетным числом снимков IonQ targetsрезультаты будут округляться до следующего четного числа. Например, если указать 9 снимков, результаты будут отображать данные для 8 выстрелов.
Оценка стоимости задания
Перед выполнением задания на ЦП необходимо оценить, сколько стоит выполнить.
Актуальные сведения о ценах см. в статье Цены на IonQ, или найдите рабочую область и просмотрите параметры ценообразования на вкладке "Поставщик" с помощью команды: aka.ms/aq/myworkspaces.
Выполнение на QPU IonQ
Чтобы подключиться к реальному оборудованию ( QPU ), просто укажите имя target"ionq.qpu.aria-1"
get_backend
метода:
qpu_backend = provider.get_backend("ionq.qpu.aria-1")
Отправьте канал для запуска в Azure Quantum, получите результаты и запустите plot_histogram
, чтобы отобразить результаты.
Примечание.
Время, необходимое для выполнения цепи на QPU, может отличаться в зависимости от времени в текущей очереди.
# 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}
Внимание
Отправка нескольких цепей в одном задании в настоящее время не поддерживается. В качестве обходного решения можно вызвать метод backend.run
для асинхронной отправки каждой цепи, а затем получить результаты каждого задания. Например:
jobs = []
for circuit in circuits:
jobs.append(backend.run(circuit, shots=N))
results = []
for job in jobs:
results.append(job.result())
Необходимые компоненты
- Учетная запись Azure с активной подпиской. Если у вас нет учетной записи Azure, зарегистрируйтесь бесплатно и зарегистрируйтесь для подписки с оплатой по мере использования.
- Рабочая область Azure Quantum. Дополнительные сведения см. в статье Создание рабочей области Azure Quantum.
Создание записной книжки в рабочей области
- Войдите на портал Azure и выберите рабочую область, созданную на предыдущем шаге.
- В левой колонке выберите Записные книжки.
- Щелкните Мои записные книжки и щелкните Добавить новую.
- Введите имя файла, например Qiskit.ipynb, и щелкните Создать файл.
При открытии новой записной книжки он автоматически создает код для первой ячейки на основе сведений о подписке и рабочей области.
from azure.quantum import Workspace
workspace = Workspace (
resource_id = "", # Add your resource_id
location = "" # Add your workspace location (for example, "westus")
)
Примечание.
Если не указано иное, следует выполнять ячейки в порядке их создания, чтобы избежать проблем компиляции.
Щелкните треугольный значок воспроизведения слева от ячейки, чтобы выполнить размещенный в ней код.
Загрузка необходимых объектов импорта
Сначала необходимо импортировать несколько дополнительных модулей.
Щелкните + Код, чтобы добавить новую ячейку, а затем добавьте и выполните следующий код:
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from azure.quantum.qiskit import AzureQuantumProvider
Подключение к службе Azure Quantum
Затем создайте объект с помощью AzureQuantumProvider
объекта из предыдущей Workspace
ячейки для подключения к рабочей области Azure Quantum. Добавьте новую ячейку со следующим кодом:
provider = AzureQuantumProvider(workspace)
Настройка простой цепи
В новой ячейке создайте объект circuit
. В этом примере используется простой квантовый генератор случайных битов. Добавьте следующий код для определения и отображения цепи:
# 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
Список всех targets
Теперь вы можете отобразить все квантовые вычисления targetsили серверные серверы, доступные в рабочей области. Добавьте новую ячейку и выполните следующую строку:
print("This workspace's targets:")
for backend in provider.backends():
print("- " + backend.name())
This workspace's targets:
- ionq.simulator
- ionq.qpu.aria-1
- microsoft.estimator
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-9q-3
- rigetti.qpu.ankaa-3
Выберите программу target для запуска
Для проверки кода перед запуском на реальном квантовом оборудовании можно применить квантовый симулятор IonQ ionq.simulator
.
Добавьте новую ячейку и создайте объект для представления квантового симулятора targetIonQ:
# Get IonQ quantum simulator target:
simulator_backend = provider.get_backend("ionq.simulator")
Запуск в симуляторе IonQ
Чтобы запустить канал на симуляторе, добавьте следующий код. В этом примере используется run
метод отправки target задания, а затем отслеживается состояние задания.
# Submit the circuit to run on Azure Quantum
job = simulator_backend.run(circuit, shots=8)
job_id = job.id()
print("Job id", job_id)
После успешного выполнения задания получите результаты задания и отобразите их:
# Get the job results:
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)
Так как типом result
будет собственный объект пакета Qiskit, можно использовать result.get_counts
и plot_histogram
Qiskit для визуализации результатов. Чтобы гарантировать представление всех возможных меток в виде последовательности битов, добавьте их в 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}
Вы также можете использовать функцию get_memory()
для отображения отдельных данных снимка из задания.
result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']
Примечание.
При отправке задания с нечетным числом снимков IonQ targetsрезультаты будут округляться до следующего четного числа. Например, если указать 9 снимков, результаты будут отображать данные для 8 выстрелов.
Оценка стоимости задания
Перед выполнением задания на фактическом квантовом оборудовании или квантовой единице обработки (QPU) необходимо оценить, сколько стоит выполнить.
Актуальные сведения о ценах можно узнать на странице цен IonQ или найдите свою рабочую область и посмотрите в колонке Поставщики для рабочей области.
Выполнение на QPU IonQ
После успешного запуска задания на симуляторе IonQ и оценки стоимости QPU время запуска канала на оборудовании.
Примечание.
Время, необходимое для выполнения цепи на QPU, отличается в зависимости от времени в текущей очереди. Среднее время target очереди можно просмотреть, выбрав колонку "Поставщики " рабочей области.
Используйте тот же метод run
и операции, которые вы ранее применяли для проверяющего элемента управления API, чтобы отправить и отобразить задание:
# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)
По завершении задания получите результаты задания, как и раньше, и отобразите их на диаграмме:
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 910b5ac8-98cd-11ec-b3ba-00155d5528cf
Job Status: job has successfully run
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='Job id 54e8c740-98d9-11ec-b382-00155d957f5d', 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}
Внимание
Отправка нескольких цепей в одном задании в настоящее время не поддерживается. В качестве обходного решения можно вызвать метод backend.run
для асинхронной отправки каждой цепи, а затем получить результаты каждого задания. Например:
jobs = []
for circuit in circuits:
jobs.append(backend.run(circuit, shots=N))
results = []
for job in jobs:
results.append(job.result())
Необходимые компоненты
Дополнительные сведения об установке см. в разделе Настройка расширения QDK.
Среда сPythonустановленной Python программой Pip.
VS Code с установленным пакетом средств разработки Azure Quantum и Python расширениями.
Пакет Azure Quantum
qsharp
Python с тегамиqiskit
иwidget
тегами.python pip install "qsharp[qiskit,widgets]>=1.9"
Запуск базового канала
В VS Code откройте новый Python файл для определения и запуска базового канала с помощью встроенного разреженного симулятора в пакете Qsharp.
# load the required imports
from qiskit.circuit.random import random_circuit
from qsharp.interop.qiskit import QSharpBackend
# 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)
Чтобы запустить программу, щелкните значок "Выполнить" в правом верхнем углу и выберите "Выполнить Python файл". Выходные данные отображаются в новом окне терминала.
┌─────────────────────────┐┌─┐
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 для цепи
С помощью этого же канала можно создать QIR, который используется для запуска на квантовом оборудовании.
Примечание.
При создании QIR все регистры должны быть измерены. Если есть неиспользуемые регистры, возникает ошибка. Кроме того, при попытке создать QIR, если для профиля задано значение Unrestricted
возникает ошибка. Профиль Unrestricted
действителен только для моделирования. Необходимо использовать targetProfile.Base или TargetProfile.Adaptive_RI
.
target_profile
можно переопределить в вызове backend.qir(...)
для переключения профилей.
Импорт
QSharpError
иTargetProfile
from qsharp import QSharpError, TargetProfile
Изменение выходных данных для создания QIR
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
Теперь код должен выглядеть следующим образом:
# load the required imports
from qiskit.circuit.random import random_circuit
from qsharp.interop.qiskit import QSharpBackend
from qsharp import QSharpError, TargetProfile
# 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))
с выходными данными:
┌────────────┐ ┌─┐
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}
Не все программы могут выполняться на всех оборудованиях. Здесь можно попытаться target профиль Base
, но мы получим подробные ошибки о том, какие части программы не поддерживаются.
try:
backend.qir(qc, target_profile=TargetProfile.Base)
except QSharpError as e:
print(e)