qdk.ec와 Microsoft 퀀텀 개발 키트(QDK)의 qodec 모듈을 사용하여 양자 오류 수정(QEC) 코드를 정의하고 이를 실행 가능한 프로토콜로 전환합니다. 이 문서에서는 오류 코드를 정의하고, 베이스라인 qodec을 구축하고, 선언의 유효성을 검사하고, 가젯 거리를 계산하고, 프로토콜을 저장합니다.
이 문서의 예제에서는 $[[4,2,2]]$ C4 코드를 사용합니다. 이 코드는 4개의 물리적 큐비트에 두 개의 논리 큐비트를 저장하고 단일 물리적 Pauli 오류를 감지합니다.
Prerequisites
시작하기 전에 다음 작업을 완료하세요.
- 오류 수정을 위해 QDK를 설치합니다.
- Python 3.11 이상 환경을 사용합니다.
-
qodec
Stim 파서를 사용할 수 있는지 확인합니다.
Linux
Arm64 또는 WindowsArm64에서는 Stim를 소스에서 설치한 다음,
build_qodec를 호출하기 전에 Jupyter 또는 Python 커널을 다시 시작합니다.
코드를 정의하세요
qodec.Code 각 논리 큐비트에 대해 코드 안정기와 하나의 논리 X 및 Z 대표 요소를 사용하여 개체를 만듭니다.
import qodec
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"],
)
qodec 패키지는 Pauli 문자열에 스파스 표기법을 사용합니다. 각 용어에는 Pauli 문자와 물리적 큐비트 레이블이 있습니다. 예를 들어, X_0 X_2 연산은 물리적 큐비트 0과 2에 X를 적용합니다.
코드 정의는 고정된 수학적 객체입니다. 인코딩된 상태를 준비, 보존 또는 측정하는 회로는 포함되지 않습니다.
코드 분석
코드 연산자의 스냅샷을 검사하려면 스냅샷을 생성합니다CodeProfile.
from qdk import ec
profile = ec.CodeProfile(c4)
print("Physical support:", sorted(profile.support))
print("Physical qubits:", profile.length)
print("Logical qubits:", profile.logical_qubit_count)
print("Stabilizers:", profile.stabilizers)
print("Logical X operators:", profile.x)
print("Logical Z operators:", profile.z)
나중에 원래 qodec.Code 개체를 변경하는 경우 프로필이 변경되지 않습니다.
코드 거리 계산
0 증후군으로 비 사소한 논리적 효과를 일으키는 허용되는 물리적 오류의 최소 수를 찾으려면 다음을 호출합니다 distance.
distance = profile.distance()
print("Code distance:", distance)
error = distance.witness.product
syndrome = profile.syndrome_of(error)
logical_effect = profile.logical_effect_of(error)
print("Witness:", error)
print("Syndrome:", sorted(syndrome))
print("Logical effect:", logical_effect)
assert distance.value == 2
assert profile.is_logical(error)
기본적으로 검색은 각 단일 큐비트 X, Y 또는 Z 오류에 비용 1을 할당합니다. 반환된 Distance에는 임의의 유한한 상한에 대한 인증된 범위와 증명이 포함됩니다.
완전한 정확 일치 검색 비용이 너무 많이 드는 경우 distance_bounds을 사용하세요.
bounds = profile.distance_bounds(upper_bound=4)
print("Distance bounds:", bounds)
print("Lower bound:", bounds.lower_bound)
print("Upper bound:", bounds.upper_bound)
기본 솔버는 HiGHS입니다. 다른 솔버를 사용하려면 solver="enumeration"을(를) 설정하거나 MWPF을(를) 설치하고 solver="mwpf"을(를) 설정하세요.
기준선 만들기 qodec
A qodec 는 인코딩된 지침을 실행하는 방법을 설명합니다. 명령 집합, 코드, 레이어, 가젯, 회로, 체크 및 판독 방정식이 있습니다.
build_qodec 코드에서 2계층 프로토콜을 만들려면 C4을 사용합니다.
protocol = ec.build_qodec(
c4,
strategy="bare-css/v1",
strict=False,
)
이 예제에서는 bare-css/v1를 사용하여 플래그 큐비트 없이 간단한 프로토콜을 검사할 수 있도록 합니다.
Caution
이 bare-css/v1 전략은 내결함성 회로를 약속하지 않습니다. 시끄러운 실험에 프로토콜을 사용하기 전에 각 가젯의 거리를 계산하세요.
빌더에서 다음 논리적 지침을 만들려고 합니다.
prepare_z_allprepare_x_allsyndromemeasure_z_allmeasure_x_allh_allcx_all
_all 접미사는 명령이 블록의 모든 논리 큐비트에서 작동한다는 것을 의미합니다. 예를 들어 cx_all는 두 블록에 있는 해당 논리 큐비트 사이에 CNOT를 적용합니다.
모든 코드가 모든 후보 명령을 지원하는 것은 아닙니다. 기본값인 를 사용하면 빌더에서 후보를 빌드하고 확인할 수 없을 때 오류가 발생합니다.
strict=False가 있는 경우, 빌더는 지원되는 지침을 유지하고 누락을 protocol.metadata["qdk.ec"]["build"]["omitted"]에 기록합니다.
논리 계층 및 해당 가젯을 검사합니다.
logical_layer = protocol.layers[0]
print("Instructions:")
for mnemonic in logical_layer.instruction_set.instructions:
print(" -", mnemonic)
print("Gadgets:")
for mnemonic in logical_layer.gadgets:
print(" -", mnemonic)
두 번째 계층에는 생성된 회로에서 사용하는 물리적 Stim 명령 집합이 포함됩니다.
가젯 검사하기
논리 명령어는 계약을 선언합니다. 그것의 가젯은 계약을 구현하는 회로를 제공합니다.
prepare_z_all 가젯을 검사합니다.
gadget = logical_layer.gadgets["prepare_z_all"]
gadget_profile = ec.GadgetProfile(gadget)
print("Declared objective:")
print(gadget_profile.objective)
print("Computed action:")
print(gadget_profile.action)
회로에서 계산된 동작을 선언된 명령어 목표와 비교합니다.
objective = gadget_profile.objective
assert objective is not None
if gadget_profile.action.is_equivalent_to(objective):
print("The gadget implements its declared instruction.")
else:
print(objective.why_not_equivalent_to(gadget_profile.action))
A GadgetProfile 는 입력의 스냅샷을 생성하므로 나중에 변경 내용을 반영하지 않습니다. 가젯을 편집한 후 새 프로필을 만듭니다.
프로토콜 감사하기
qodec를 사용하여 전체 audit를 확인합니다.
report = ec.audit(protocol)
print(report)
검사에서 오류 또는 경고를 찾지 못하면 다음이 출력됩니다.
audit: ok
감사는 다음 영역을 확인합니다.
- 코드 대수
- 명령 및 계층 구조
- 회로 호출 및 매개 변수 바인딩
- 가젯 동작
- 수식 확인 및 판독식
- 수식에 플래그 지정
- 입력 및 출력 프레임 관계
- 참조 범위 및 프로토콜 완전성
특정 심각도에 따라 작업하려면 보고서 모음을 사용합니다.
if report.errors:
for diagnostic in report.errors:
print(diagnostic)
raise ValueError("The qodec has audit errors.")
if report.warnings:
for diagnostic in report.warnings:
print(diagnostic)
report.ok 값은 보고서에 오류가 없음을 의미합니다. 경고는 해당 속성을 변경하지 않습니다.
누락된 수식 도출
qodec 임시 가젯 또는 filled 검사나 정확한 시뮬레이션으로 도출할 수 있는 논리적 판독 수식을 생략하는 경우에 사용합니다.
다음 예제에서는 프로토콜의 불완전한 복사본을 만듭니다.
draft = qodec.Qodec.loads(protocol.dumps())
draft_gadgets = draft.layers[0].gadgets
draft_gadgets["measure_x_all"].readouts = []
draft_gadgets["cx_all"].checks = []
print(ec.audit(draft))
지원되는 수식을 입력한 다음 결과를 검토합니다.
completed = ec.filled(draft)
print(ec.audit(completed))
함수는 filled 새 가젯을 반환하거나 qodec를 반환하며, 입력은 변경하지 않습니다. 검사 항목, 관찰 가능한 판독 방정식 및 프레임 관계를 파생합니다. 노이즈리스 시뮬레이션은 플래그가 감지해야 하는 오류를 식별할 수 없으므로 플래그 바인딩을 유지합니다.
원래 프로토콜에 이미 검증된 직접 수식이 있으면 filled는 가능하면 이를 유지합니다.
가젯 오류 분석하기
오류가 없는 감사 작업은 잡음 없는 일관성을 증명합니다. 내결함성을 증명하지는 않습니다.
GadgetProfile.distance를 호출하여 선언된 모든 검사 및 플래그가 0으로 유지되는 동안 논리 오류를 발생시키는 허용되는 회로 오류의 최소 수를 찾습니다. 결합된 고장은 또한 각 출력이 해당 코드 공간 내에 남아 있도록 해야 합니다.
protocol = completed
for mnemonic, gadget in sorted(protocol.layers[0].gadgets.items()):
result = ec.GadgetProfile(gadget).distance()
witness = result.witness if result.upper_bound is not None else "none"
print(f"{mnemonic}: distance={result}, witness={witness}")
기본 고장 모델에는 각 회로 호출 작업 후 다음 이벤트가 포함됩니다.
- 호출이 영향을 미치는 큐비트의 오류
- 호출이 생성하는 판독 비트의 비트 반전
- 이러한 오류의 상관된 조합
상관 관계가 있는 다중 큐비트 오류가 있는 경우에도 한 호출의 각 이벤트는 1의 비용이 듭니다.
코드는 가젯 중 하나에 거리 1이 있는데도 거리 2를 가질 수 있습니다. 예를 들어 단일 회로 오류는 ancilla를 통해 퍼져 감지되지 않은 논리적 오류를 만들 수 있습니다. 확인 또는 플래그 회로를 추가한 다음, 새 GadgetProfile을 만들고 거리를 다시 계산합니다.
특정 결함 검사
FaultEvent.after를 사용하여 0부터 시작하는 회로 호출 인덱스를 기준으로 오류를 정의합니다.
gadget = protocol.layers[0].gadgets["syndrome"]
profile = ec.GadgetProfile(gadget)
fault = ec.FaultEvent.after(0, ec.Pauli("X_0"))
(effect,) = profile.effects_of([fault])
print("Fault:", fault)
print("Changed quantities:", effect)
A FaultEffect에는 변경된 검사, 논리 판독값 및 출력 프레임 기호가 포함될 수 있습니다. 기본 회로 수준 모델이 하드웨어 가정과 일치하지 않는 경우 명시적 결함 집합을 사용합니다.
result = profile.distance(faults=[fault])
print(result)
기본 오류 집합이 각 호출의 적용 범위에 따라 기하급수적으로 증가하기 때문에 정확한 가젯 검색에는 시간이 오래 걸릴 수 있습니다. 검색을 제한해야 하는 경우 upper_bound, 명시적 오류 집합 또는 distance_bounds를 사용합니다.
프로토콜 저장하기
저장하기 전에 마지막 qodec 검토하세요.
report = ec.audit(protocol)
if report.errors or report.warnings:
raise ValueError(str(report))
프로토콜을 단일 YAML 번들로 저장한 다음 다시 로드하여 원본과 일치하는지 확인합니다.
from pathlib import Path
output_directory = Path("qodec-output")
output_directory.mkdir(exist_ok=True)
saved_path = protocol.save(str(output_directory), single_file=True)
loaded = qodec.Qodec.load(saved_path)
assert loaded == protocol
print("Saved qodec:", saved_path)
단일 파일 번들은 매니페스트, 코드 정의, 명령 집합, 가젯 및 회로 원본을 한 YAML 파일에 저장하므로 쉽게 공유하고 다시 로드할 수 있습니다.
프로토콜을 실행하세요
qodec가 감사를 통과하고 거리 요구 사항을 충족한 후 논리 프로그램을 Quantum Intermediate Representation(QIR)로 컴파일하고 프로토콜을 통해 실행합니다. 논리 프로그램 실행 및 디코딩을 참조하세요.
플래그 회로를 추가하고 논리적 오류 비율을 비교하는 전체 예제는 GitHub 리포지토리의 QDK를 참조하세요.