논리 프로그램 실행 및 디코드

Microsoft 퀀텀 개발 키트(QDK)를 사용하여 논리 Q# 또는 OpenQASM 프로그램을 Quantum Intermediate Representation(QIR)로 컴파일하고, затем use? 노이즈 모델을 설정한 다음 기본 제공 증후군 디코더 또는 선택적 deq 회로 수준 디코더를 선택합니다.

Prerequisites

시작하기 전에 다음 작업을 완료하세요.

이 예제에서는 protocol 코드에 대한 지침이 있는 C4라는 qodec를 사용합니다. 하나를 만들려면 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의 검사, 판독값, 플래그 및 프레임 방정식을 신뢰하므로 잘못된 선언으로 인해 잘못된 논리 결과가 발생하거나 디코더 오류가 발생할 수 있습니다.

이 워크플로는 qodec와 qdk.simulation.run_qir를 함께 사용합니다. qodec 도구는 별도의 StimPython 패키지를 사용하여 Stim 형식 가젯 회로를 구문 분석합니다. qdk.stim.run를 호출하지 않습니다. Windows Arm64 또는 LinuxArm64에서 Stim-format 회로가 있는 qodec를 실행하기 전에, 소스에서 Jupyter를 설치하고 Stim 또는 Python 커널을 다시 시작합니다.

qodec 호출을 QIR 지침과 일치시키기

QIR 프로그램의 각 양자 호출을 qodec의 최상위 명령 집합에 있는 명령과 일치시키세요. 명령 니모닉은 QIR 피호출자 이름과 정확히 일치해야 합니다.

다음 표에서는 예제 매핑을 보여 줍니다.

소스 호출 필수 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. 큐비트 포인터 인수는 블록 피연산자를 바인딩합니다.
  2. 스칼라 인수는 명령 매개 변수에 바인딩됩니다.
  3. 결과 포인터 인수는 명령 결과 및 반환된 플래그를 받습니다.

양자 호출이 최상위 명령 집합의 명령과 일치하지 않으면 컴파일러에서 오류가 발생합니다.

논리 명령을 Q#에서 선언

C4 코드로 빌드된 qodec은(는) prepare_z_all, syndrome, measure_z_all 및 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])
}
""")

TestSpamZ 작업을 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 프레임을 사용합니다.

시뮬레이터 노이즈 설정

시뮬레이터 작업에 대한 노이즈를 정의하며, 명령 이름에는 적용하지 않습니다. 런타임은 각 하위 계층 명령을 하나 이상의 시뮬레이터 작업으로 변환하므로 노이즈 설정이 해당 작업에 적용됩니다.

C4 단계별 안내에서는 다음 매핑을 사용합니다.

하위 계층 지침 시뮬레이터 작동 NoiseConfig 필드
R Z+로 준비 또는 다시 설정 mresetz
H 하다마드 h
CX 제어됨 X cx
M Z-basis 측정 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 리드아웃 결함 모델 및 가젯 분석을 사용합니다.

제어 샷 실패

qodec on_shot_failure 플래그, 디코더 또는 리드아웃이 허용된 샷을 생성하지 않을 때 런타임이 응답하는 방식을 선택하는 데 사용합니다.

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 어댑터는 릴레이 빌리프 전파 및 윈도우 코디네이터를 사용합니다. 이러한 설정을 변경하려면 런타임 팩터리를 사용하세요.

모놀리식 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가 각 런타임을 시작하고 종료합니다.

Note

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를 통해 실행하려면, __quantum__qis__x__body의 최상위 명령 집합에 __quantum__qis__m__body와 qodec가 포함되어 있고 호환되는 블록 피연산자와 하나의 측정 결과가 있는지 확인합니다.

foo 내장 게이트 또는 OpenQASM라는 이름의 서브루틴은 니모닉 foo을 사용합니다. 큐비트 인수는 블록 피연산자를 바인딩합니다. int, bool 및 float 인수는 선언 순서에 따라 명령 매개 변수에 바인딩됩니다.

OpenQASM에는 qodec 호출에 대한 다음 제한 사항이 있습니다.

  • 사용자 지정 내장 함수는 QIRResult를 반환할 수 없습니다. 하나의 측정 결과를 얻으려면 표준 measure 문을 사용합니다.
  • OpenQASM 프로그램은 사용자 지정 측정을 실행하거나, 한 번의 호출에서 여러 결과를 받거나, 반환된 플래그를 받을 수 없습니다. 이러한 경우 Q#@Measurement() 작업을 사용합니다.
  • 런타임은 OpenQASM 프로그램이 받을 수 없는 모든 플래그를 제어하며, 이러한 플래그는 요청을 거부할 수 있습니다.

자세한 매핑 예제는 다음 QDK Notebook을 참조하세요.

요구 사항 및 제한 사항 검토

대규모 실험을 실행하기 전에 이러한 요구 사항, 제한 사항 및 결과 차이를 검토하세요.

요구 사항:

  • 모든 QIR 양자 호출은 최상위 계층 qodec 명령으로 해석되어야 합니다.
  • 프로토콜을 실행하기 전에 검토하십시오. 런타임은 qodec 작성한 수식을 신뢰하며 그 수식을 확인하지 않습니다.

제한 사항:

  • GPU 시뮬레이션은 qodec 실행을 지원하지 않습니다.
  • 기본 가젯 오류 집합은 기하급수적으로 증가할 수 있으므로 정확한 거리 검색에는 시간이 오래 걸릴 수 있습니다.
  • deq 및 Stim 패키지에는 플랫폼 제한이 있습니다. 자세한 내용은 오류 수정을 위해 Install QDK을 참조하세요.

결과 차이점:

  • 정확한 출력 수는 디코더에 따라 달라질 수 있습니다.
  • 폐기 및 다시 시도 정책은 반환된 결과 분포를 변경할 수 있습니다.

노이즈 스윕, 디코딩Q#, 신뢰도 기반 거부를 사용하는 전체 deq 실험에 대해서는 QEC 프로토콜 가이드를 참조하세요.