Logische programma's uitvoeren en debuggen

Gebruik de Microsoft Quantum Development-kit (QDK) om een logisch Q# of OpenQASM programma te compileren naar Quantum Intermediate Representation (QIR) en gebruik qdk.simulation.run_qir vervolgens om het programma uit te voeren via een qodec. Stel een ruismodel in en kies vervolgens de ingebouwde syndroomdecoder of de optionele deq decoder op circuitniveau.

Prerequisites

Voer deze taken uit voordat u begint:

In de Q# voorbeelden wordt een qodec met de naam protocol gebruikt die instructies voor de C4 code bevat. Zie Een QEC-protocol ontwikkelen en valideren om er een te maken.

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))

Controleer de qodec voordat u deze uitvoert. De runtime vertrouwt de controles, uitlezingen, vlaggen en frameformules van qodec, zodat ongeldige declaraties onjuiste logische resultaten of decoderfouten kunnen veroorzaken.

Deze werkstroom gebruikt qdk.simulation.run_qir met een qodec. De qodec tooling maakt gebruik van het afzonderlijke StimPython pakket voor het parseren van gadgetcircuits in Stim-indeling. Het roept qdk.stim.run niet aan. Op Arm64Windows of LinuxArm64 installeert u Stim vanuit de bron en start u Python of de Jupyter-kernel opnieuw voordat u een qodec uitvoert dat circuits in Stim-indeling heeft.

Koppel QIR aanroepen aan qodec instructies

Koppel elke kwantumaanroep in het QIR programma aan een instructie in de bovenste instructieset van qodec. De instructie-mnemonic moet exact overeenkomen met de naam van de QIR callee.

In de volgende tabel ziet u voorbeeldtoewijzingen:

Brongesprek Vereiste qodec mnemonic
Q# X(q) of OpenQASMx q; __quantum__qis__x__body
Q# H(q) of OpenQASMh q; __quantum__qis__h__body
Q# CNOT(a, b) of OpenQASMcx a, b; __quantum__qis__cx__body
Q# Adjoint S(q) of OpenQASMsdg q; __quantum__qis__s__adj
Q# M(q) of OpenQASMc = measure q; __quantum__qis__m__body
Q# intrinsieke operatie Foo Foo
OpenQASM intrinsieke poort of def genaamd foo foo

QIR argumenten binden aan qodec instructie-elementen in deze volgorde:

  1. Qubit-aanwijzerargumenten binden aan blokoperanden.
  2. Scalaire argumenten zijn gekoppeld aan instructieparameters.
  3. Resultaatpointerargumenten ontvangen instructieresultaten en eventuele geretourneerde vlaggen.

De compiler genereert een fout als een kwantumaanroep niet overeenkomt met een instructie in de bovenste instructieset.

Logische instructies declareren in Q#

Een qodec gebouwd op basis van de C4 code bevat aangepaste instructies zoals prepare_z_all, measure_z_all, syndromeen cx_all. Declare Q# intrinsics met dezelfde namen.

Initialiseer Q# met het adaptieve doelprofiel omdat hiervoor aangepaste meetbewerkingen zijn vereist.

from qdk import TargetProfile, qsharp

qsharp.init(target_profile=TargetProfile.Adaptive_RI)

Declareer de C4 instructies als Q# bewerkingen.

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; }
""")

In dit programma vertegenwoordigt elk Q#Qubit één gecodeerd blok. Het C4 blok heeft twee logische qubits, dus elke meetbewerking retourneert twee logische resultaten. Elke voorbereidingsbewerking retourneert één afwijzingsvlag.

Compileer een logisch Q#-experiment

Definieer een experiment met toestandsvoorbereiding en -meting (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])
}
""")

Compileer de TestSpamZ bewerking naar QIR.

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

Het QIR behoudt de aanroepen naar prepare_z_all en measure_z_all. Wanneer het programma wordt uitgevoerd, vergelijkt de qodec runtime deze namen met de bovenste instructieset en vervangt elke logische aanroep door het gadget.

Uitvoeren met de ingebouwde decoder

Bel run_qir en geef de qodec. Als decoderNone is, gebruikt de runtime de ingebouwde decoder voor minimumgewicht Pauli.

from qdk.simulation import run_qir

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

print(results[:5])

Als u een qodecwilt uitvoeren, gebruikt u deze simulatoropties:

Waarde type Behavior
None of "stabilizer" Gebruik de backend van de stabilizer
"cpu" Gebruik de back-end van de toestandsvector voor ondersteunde programma's
"gpu" Niet ondersteund door qodec

De runtime bereidt elke programma-qubit voor voor het eerste gebruik, tenzij de eerste instructie zijn blok aanmaakt. Een voorbereidingsinstructie bevat uitvoerblokken, geen invoerblokken en een actie die logical Z stabiliseert.

Decodercorrecties met één qubit Pauli en qodec frameupdates maken gebruik van een ruisloos Pauli frame, geen lawaaierige fysieke poorten.

Simulatorruis configureren

Definieer ruis bij simulatorbewerkingen, niet qodec instructienamen. De runtime vertaalt elke instructie in de onderste laag naar een of meer simulatorbewerkingen, zodat ruisinstellingen van toepassing zijn op deze bewerkingen.

In de C4 stapsgewijze handleiding worden deze toewijzingen gebruikt:

Instructie voor de onderlaag Simulatorbediening NoiseConfig veld
R Voorbereiden of opnieuw instellen op Z+ mresetz
H Hadamard h
CX Beheerde X cx
M Z-basismeting mresetz

Maak een eenvoudig 1% ruismodel:

from qdk.simulation import NoiseConfig

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

Voer het experiment uit met ruis:

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

Ruis op mresetz werkt in op de qubit na meting of voorbereiding. Er wordt geen meetbit omgezet dat de simulator al heeft opgenomen. Als u geregistreerde bitflips wilt bestuderen, gebruikt u qodec foutmodellen voor lezen en gadgetanalyse.

Mislukte controleopnamen

Gebruik on_shot_failure deze optie om te kiezen hoe de runtime reageert wanneer een qodec vlag, decoder of uitlezing geen geaccepteerde shot produceert.

Value Behavior
"discard" Laat mislukte opnamen weg uit de geretourneerde lijst. Dit is de standaardwaarde.
"raise" Stop wanneer het eerste schot mislukt.
"retry" Start de mislukte opname opnieuw op, tot max_retries extra pogingen.

Met het "discard" beleid telt het shots argument geprobeerde shots, zodat de geretourneerde lijst minder items kan bevatten dan shots.

Een vlag activeert het shot policy alleen wanneer het logische programma die vlag niet ontvangt. Als een Q#@Measurement() bewerking een extra Result voor de vlag retourneert, ontvangt het programma de vlag en beslist of het schot moet worden geweigerd.

In het TestSpamZ voorbeeld retourneert het programma de voorbereidingsvlag in de eerste array. De on_shot_failure="discard" instelling verwijdert dus geen rijen waarbij de geretourneerde vlag One is.

Decoder selecteren

Als u wilt kiezen hoe fouten worden gedecodeerd, gebruikt u de decoder parameter om een aanroepbare functie voor decoderinitialisatie door te geven voor elke gecodeerde laag.

De QDK heeft de volgende decoders:

Decoder Gebruik het om
Standaardsyndroomdecoder Leid minimale gewichtscorrecties Pauli af op basis van syndroombewijs. Gebruik decoder=None.
Frame decoder Volg ruisloze frames zonder fysieke fouten af te leiden. Gebruik prepare_frame_decoder.
deq decoder Decodeer foutmodellen op circuitniveau met deq. Gebruik prepare_deq_decoder.

De standaardconfiguratie deq gebruiken

Installeer deq en deq-runtime, en geef vervolgens prepare_deq_decoder door.

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",
)

De deq adapter gebruikt standaard relay belief propagation en een window coordinator. Als u deze instellingen wilt wijzigen, gebruikt u een runtimefactory.

Een monolithische deq runtime configureren

Als u instellingen rechtstreeks wilt kiezen deq , geeft u een runtimefactory door aan 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",
)

Retourneer een nieuwe Runtime van elke factory-aanroep. De QDK start en sluit elke runtime.

Notitie

Voor de deq adapter is het volgende vereist:

  • Eén gecodeerde laag
  • Een meetonafhankelijke Clifford uitvoeringstrace
  • De backend van de stabilizer
  • Een ruismodel zonder qubitverlies

De deq adapter biedt geen ondersteuning voor het beleid voor opnieuw uitvoeren. Niet-ondersteunde programma's veroorzaken een fout in plaats van terug te vallen op een andere decoder.

Resultaten met lage betrouwbaarheid deq afwijzen

De deq adapter retourneert een score voor elke logische uitlezing. Lagere scores geven een sterkere voorkeur aan voor de gekozen correctie. De scores zijn geen gekalibreerde faalkansen.

Als u resultaten met een lage betrouwbaarheid wilt negeren, geeft u max_readout_score op wanneer u de decoder voorbereidt, zoals in het volgende voorbeeld:

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",
)

De runtime accepteert een schot alleen wanneer elke geretourneerde logische uitlezing een score heeft op of onder de drempelwaarde. De drempelwaarde is niet van toepassing op onbewerkte vlaggen of ongebruikte tussenliggende uitlezingen.

Afwijzing op basis van score kan de logische foutsnelheid van geaccepteerde schoten verlagen. Maar het vermindert ook het aantal goedgekeurde shots en voegt decoderwerk toe.

Programma's compileren OpenQASM

Standaardbewerkingen OpenQASM gebruiken dezelfde QIR mnemonische regels als standaardbewerkingen 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)

Als u dit programma wilt uitvoeren via een qodec, moet u ervoor zorgen dat de bovenste instructieset van qodec__quantum__qis__x__body en __quantum__qis__m__body heeft, met compatibele blokoperanden en één meetresultaat.

Een OpenQASM intrinsieke poort of subroutine met de naam foo maakt gebruik van de nemonische foo. Qubit-argumenten worden gekoppeld aan blokoperanden. De float, int, en bool argumenten binden aan instructieparameters in de declaratievolgorde.

OpenQASM heeft deze beperkingen voor qodec aanroepen:

  • Aangepaste intrinsieke elementen kunnen geen QIRwaardeResult retourneren. Als u één meetresultaat wilt ophalen, gebruikt u de standaardstatement measure.
  • OpenQASM programma's kunnen geen aangepaste meetwaarden uitvoeren, verschillende resultaten ontvangen van één oproep of geretourneerde flags ontvangen. Gebruik voor deze gevallen de bewerkingen Q#@Measurement().
  • De runtime beheert eventuele vlaggen die het OpenQASM programma niet kan ontvangen, en deze vlaggen kunnen een opname weigeren.

Zie de volgende QDK notebooks voor gedetailleerde toewijzingsvoorbeelden:

Vereisten en beperkingen

Bekijk deze vereisten, beperkingen en resultaatverschillen voordat u een groot experiment uitvoert.

Vereisten:

  • Elke QIR kwantumoproep moet resulteren in een instructie in de bovenste laag qodec.
  • Controleer het protocol voordat u het uitvoert. De qodec runtime vertrouwt de vergelijkingen die u schrijft en controleert deze niet.

Limitations:

  • GPU simulatie biedt geen ondersteuning voor qodec uitvoering.
  • De standaard gadgetfoutset kan exponentieel toenemen, zodat zoekopdrachten op exacte afstand lang kunnen duren.
  • De deq en Stim pakketten hebben platformbeperkingen. Zie Installeren QDK voor foutcorrectie voor meer informatie.

Resultaatverschillen:

  • Het exacte aantal uitvoeritems kan per decoder verschillen.
  • Beleid voor weggooien en opnieuw proberen kan de geretourneerde resultaatdistributie wijzigen.

Zie de deq voor een volledig experiment met ruisveegingen, Q# decodering en afwijzing op basis van betrouwbaarheid.