Запустить и декодировать логические программы

Используйте Microsoft Quantum Development Kit (QDK), чтобы скомпилировать логическую Q# или OpenQASM программу в Quantum Intermediate Representation (QIR), а затем используйте qdk.simulation.run_qir для запуска программы через qodec. Настройте модель шума, а затем выберите встроенный декодер синдрома или необязательный deq декодер уровня схемы.

Prerequisites

Выполните следующие задачи перед началом работы:

В Q# примерах используется qodec с именем protocol, который содержит инструкции для кода C4. Чтобы создать его, см. раздел Разработка и проверка протокола QEC.

import qodec
from qdk import ec

c4 = qodec.Code(
    "C4",
    stabilizers=["X_0 X_1 X_2 X_3", "Z_0 Z_1 Z_2 Z_3"],
    x=["X_0 X_1", "X_0 X_2"],
    z=["Z_0 Z_2", "Z_0 Z_1"],
)

protocol = ec.build_qodec(
    c4,
    strategy="bare-css/v1",
    strict=False,
)

report = ec.audit(protocol)
if report.errors or report.warnings:
    raise ValueError(str(report))

Выполните аудит qodec перед запуском. Среда выполнения доверяет проверкам, считываниям, флагам и уравнениям кадров qodec, поэтому недопустимые объявления могут привести к неправильным логическим результатам или сбоям декодирования.

Этот рабочий процесс использует qdk.simulation.run_qir с qodec. Средство qodec использует отдельный StimPython пакет для анализа схем гаджетов формата Stim. Он не вызывает qdk.stim.run. На WindowsArm64 или StimLinux установите Arm64 из исходного кода и перезапустите Python или ядро Jupyter перед запуском qodec, содержащего схемы формата Stim.

Сопоставление вызовов QIR с инструкциями qodec

Сопоставляйте каждый квантовый вызов в программе QIR с инструкцией в верхнем наборе инструкций qodec. Мнемоника инструкции должна точно соответствовать имени вызываемой функции.

В следующей таблице показаны примеры сопоставлений:

Исходный вызов Обязательная qodec мнемоника
Q# X(q) или OpenQASMx q; __quantum__qis__x__body
Q# H(q) или OpenQASMh q; __quantum__qis__h__body
Q# CNOT(a, b) или OpenQASMcx a, b; __quantum__qis__cx__body
Q# Adjoint S(q) или OpenQASMsdg q; __quantum__qis__s__adj
Q# M(q) или OpenQASMc = measure q; __quantum__qis__m__body
Q# внутренняя операция Foo Foo
OpenQASM внутренний вентиль или def именованный вентиль foo foo

QIR аргументы привязываются к qodec элементам инструкции в этом порядке:

  1. Аргументы-указатели Qubit привязываются к блок-операндам.
  2. Скалярные аргументы привязываются к параметрам инструкции.
  3. Аргументы указателя результатов получают результаты выполнения инструкций и все возвращенные флаги.

Компилятор выдает сообщение об ошибке, если квантовый вызов не соответствует инструкции в верхнеуровневом наборе инструкций.

Объявите логические инструкции в Q#

qodec, собранный из кода C4, предоставляет пользовательские инструкции, такие как prepare_z_all, measure_z_all, syndrome и cx_all. Объявите Q# встроенные операции с теми же именами.

Инициализировать Q# с помощью адаптивного целевого профиля, так как для пользовательских операций измерения требуется адаптивный целевой профиль.

from qdk import TargetProfile, qsharp

qsharp.init(target_profile=TargetProfile.Adaptive_RI)

Объявите C4 инструкции как Q# операции.

qsharp.eval("""
@Measurement()
operation prepare_z_all(block : Qubit) : Result { body intrinsic; }

@Measurement()
operation prepare_x_all(block : Qubit) : Result { body intrinsic; }

@Measurement()
operation measure_z_all(block : Qubit) : (Result, Result) { body intrinsic; }

@Measurement()
operation measure_x_all(block : Qubit) : (Result, Result) { body intrinsic; }

operation cx_all(control : Qubit, target : Qubit) : Unit { body intrinsic; }
operation syndrome(block : Qubit) : Unit { body intrinsic; }
""")

В этой программе каждый Q#Qubit представляет один закодированный блок. Блок C4 содержит два логических кубита, поэтому каждая операция измерения возвращает два логических результата. Каждая операция подготовки возвращает один флаг отклонения.

Скомпилируйте логический Q# эксперимент

Определите эксперимент подготовки состояния и измерения (SPAM).

qsharp.eval("""
operation TestSpamZ() : (Result[], Result[]) {
    use block = Qubit();
    let reject = prepare_z_all(block);
    let (left, right) = measure_z_all(block);
    ([reject], [left, right])
}
""")

Скомпилируйте операцию в QIR.

qir = str(qsharp.compile("TestSpamZ()"))

QIR сохраняет вызовы prepare_z_all и measure_z_all. При запуске qodec программы среда выполнения сопоставляет эти имена с верхним набором инструкций и заменяет каждый логический вызов своим гаджетом.

Запустите со встроенным декодером

Вызовите run_qir и передайте qodec. Если decoder равно None, среда выполнения использует встроенный декодер минимального веса Pauli.

from qdk.simulation import run_qir

results = run_qir(
    qir,
    qodec=protocol,
    type="stabilizer",
    shots=100,
    seed=42,
)

print(results[:5])

Чтобы запустить qodec, используйте следующие параметры симулятора:

Значение type Behavior
None или "stabilizer" Используйте серверную часть стабилизатора
"cpu" Использование бэкенда вектора состояния для поддерживаемых программ
"gpu" Не поддерживается с qodec

Среда выполнения подготавливает каждый кубит программы до его первого использования, если только первая инструкция не создает его блок. Инструкция подготовки содержит выходные блоки, не содержит входных блоков и действие, которое стабилизирует логический Z.

Исправления однокубитного Pauli декодировщика и qodec обновления кадров используют бесшумный Pauli кадр, а не шумные физические ворота.

Настроить шум симулятора

Определите уровень вывода при операциях симулятора, а не на именах инструкций qodec. Среда выполнения преобразует каждую инструкцию нижнего слоя в одну или несколько операций симулятора, поэтому параметры шума применяются к этим операциям.

В пошаговом C4 руководстве используются следующие сопоставления:

Инструкция нижнего слоя Работа симулятора NoiseConfig поле
R Подготовить или сбросить на Z+ mresetz
H Хадамард h
CX Контролируемый X cx
M Измерение в Z-базисе mresetz

Создайте простую модель шума 1%:

from qdk.simulation import NoiseConfig

noise = NoiseConfig()
for gate in (noise.h, noise.cx):
    gate.set_depolarizing(0.01)
noise.mresetz.x = 0.01

Выполните эксперимент с шумом:

results = run_qir(
    qir,
    qodec=protocol,
    noise=noise,
    type="stabilizer",
    shots=1000,
    seed=42,
    on_shot_failure="discard",
)

Шум на mresetz действует на кубит после измерения или подготовки. Он не переворачивает бит измерения, который симулятор уже записал. Чтобы изучить записанные инверсии битов, используйте qodec модели сбоя чтения и анализ гаджетов.

Сбои тестовых снимков

Используйте on_shot_failure для выбора того, как среда выполнения реагирует, когда флаг qodec, декодатор или результат считывания не создает принятый запуск.

Value Behavior
"discard" Опустить неудачные снимки из возвращаемого списка. Это значение является значением по умолчанию.
"raise" Остановите работу при сбое первой попытки.
"retry" Перезапустите неудачный снимок, максимум еще max_retries раз.

"discard" При использовании политики shots аргумент подсчитывает попытки выстрелов, поэтому возвращенный список может содержать меньше элементов, чемshots.

Флаг запускает политику срабатывания только в том случае, если логическая программа не получает этот флаг. Q# @Measurement() Если операция возвращает дополнительный Result элемент для флага, программа получает флаг и решает, следует ли отклонить выстрел.

В примере TestSpamZ программа возвращает флаг подготовки в первом массиве. on_shot_failure="discard" Поэтому параметр не удаляет строки, где возвращаемый флаг имеет значение One.

Выберите декодер

Чтобы выбрать способ декодирования ошибок, используйте параметр decoder для передачи вызываемого объекта подготовки декодера для каждого закодированного слоя.

QDK имеет следующие декодеры:

Дешифратор Используйте его для
Декодер синдрома по умолчанию Выведите исправления минимального веса Pauli на основе данных синдрома. Используйте decoder=None.
Декодировщик кадров Отслеживайте кадры без шума, не делая выводов о физических неисправностях. Используйте prepare_frame_decoder.
deq декодер Декодируйте модели сбоев на уровне схемы с deq. Используйте prepare_deq_decoder.

Используйте конфигурацию по умолчанию deq

Установите deq и deq-runtime, затем передайте prepare_deq_decoder.

from qdk.simulation.decoders import prepare_deq_decoder

results = run_qir(
    qir,
    qodec=protocol,
    decoder=prepare_deq_decoder,
    noise=noise,
    type="stabilizer",
    shots=1000,
    seed=42,
    on_shot_failure="discard",
)

По умолчанию адаптер deq использует алгоритм Relay Belief Propagation и координатор окон. Чтобы изменить эти параметры, используйте фабрику среды выполнения.

Настройте монолитную deq среду выполнения

Чтобы выбрать параметры deq напрямую, передайте фабрику среды выполнения в prepare_deq_decoder.

from functools import partial
from deq.runtime import Runtime
from qdk.simulation import decoders


def make_runtime(seed: int) -> Runtime:
    return Runtime(
        decoder="black-box-relay-bp",
        decoder_config={"parallel": 1, "seed": seed},
        coordinator="monolithic",
        controller="jit",
    )


results = run_qir(
    qir,
    qodec=protocol,
    decoder=partial(
        decoders.prepare_deq_decoder,
        runtime_factory=make_runtime,
    ),
    noise=noise,
    type="stabilizer",
    shots=1000,
    seed=42,
    on_shot_failure="discard",
)

Возвращать новое Runtime при каждом вызове фабрики. QDK запускает и закрывает каждую среду выполнения.

Примечание.

Для адаптера deq требуется:

  • Один закодированный слой
  • Независимая от измерения трассировка выполнения Clifford
  • Бэкенд стабилизатора
  • Модель шума без потери кубитов

Адаптер deq не поддерживает политику повторных попыток. Неподдерживаемые программы вызывают ошибку вместо того, чтобы переключиться на другой декодер.

Отклонить результаты с низким уровнем достоверности deq

Адаптер deq возвращает оценку для каждого логического вывода. Более низкие оценки указывают на более сильное предпочтение выбранного исправления. Оценки не являются калиброванными вероятностями сбоя.

Чтобы отклонить результаты низкой достоверности, передайте max_readout_score при подготовке декодера, как показано в следующем примере:

from functools import partial
from qdk.simulation import decoders

scored_decoder = partial(
    decoders.prepare_deq_decoder,
    max_readout_score=0.2,
)

results = run_qir(
    qir,
    qodec=protocol,
    decoder=scored_decoder,
    noise=noise,
    type="stabilizer",
    shots=1000,
    on_shot_failure="discard",
)

Среда выполнения принимает результат выполнения, только если каждое возвращаемое логическое чтение имеет оценку, равную или ниже порогового значения. Пороговое значение не применяется к необработанным флагам или неиспользуемым промежуточным считываниям.

Отклонение на основе оценки может снизить частоту логических ошибок для принятых измерений. Но он также уменьшает количество принятых кадров и добавляет работу декодировщику.

Компилировать OpenQASM программы

Стандартные OpenQASM операции используют те же QIR мнемонические правила, что и стандартные Q# операции.

from qdk import TargetProfile, openqasm

source = """
OPENQASM 3.0;
include "stdgates.inc";
qubit q;
bit c;
x q;
c = measure q;
"""

qir = openqasm.compile(
    source,
    target_profile=TargetProfile.Adaptive_RI,
)

print(qir)

Чтобы запустить эту программу через qodec, убедитесь, что верхний набор инструкций qodec содержит __quantum__qis__x__body и __quantum__qis__m__body, совместимые операнды блоков и один результат измерения.

Встроенный OpenQASM гейт или подпрограмма с именем foo использует мнемонику foo. Аргументы Qubit привязываются к блок-операндам. int, float и bool аргументы привязываются к параметрам инструкции в порядке объявления.

OpenQASM имеет следующие ограничения для вызовов qodec:

  • Пользовательские интринсики не могут возвращать QIRResult. Чтобы получить один результат измерения, используйте стандартный оператор measure.
  • OpenQASM программы не могут запускать пользовательские измерения, получать несколько результатов от одного вызова или получать возвращенные флаги. В таких случаях используйте операции Q#@Measurement().
  • Исполняющая среда управляет любыми флагами, которые программа OpenQASM не может получить, и эти флаги могут отклонить запрос.

Подробные примеры сопоставления см. в следующих QDK блокнотах:

Обзор требований и ограничений

Просмотрите эти требования, ограничения и различия результатов перед выполнением большого эксперимента.

Требования:

  • Каждый QIR квантовый вызов должен разрешаться в инструкцию верхнего уровня qodec .
  • Перед запуском протокола проверьте его. Среда qodec выполнения доверяет уравнениям, которые вы пишете, и не проверяет их.

Limitations:

  • GPU Моделирование не поддерживает qodec выполнение.
  • Множество неисправностей гаджета по умолчанию может увеличиваться экспоненциально, поэтому точный поиск по расстоянию может занять много времени.
  • Пакеты Stim и deq имеют ограничения по платформам. Дополнительные сведения см. в разделе Установка QDK для исправления ошибок.

Различия результатов:

  • Точное количество выходных данных может различаться в зависимости от декодера.
  • Политики отбрасывания и повторных попыток могут изменить возвращаемое распределение результатов.

Описание полного Q# эксперимента со сканированием по шуму, deq декодированием и отклонением на основе достоверности см. в пошаговом руководстве по протоколу QEC.