Dela via


Så här felsöker och testar du kvantkoden

Testning och felsökning är lika viktiga i kvantprogrammering som i klassisk programmering. I den Microsoft Quantum Development Kit här artikeln beskrivs hur du felsöker och testar kvantprogram med (QDK) i Visual Studio Code (VS Code) och Jupyter Notebook.

Felsöka din kvantkod

QDK innehåller flera verktyg för att felsöka koden. Om du skriver Q# eller OpenQASM-program i VS Code kan du använda VS Code-felsökningsprogrammet för att ange brytpunkter i dina program och analysera koden. QDK innehåller också en uppsättning dumpfunktioner som du kan använda för att hämta information på olika platser i programmet.

Så här använder du VS Code-felsökningsprogrammet

Med QDK-tillägget i VS Code kan du använda felsökningsprogrammet för att gå igenom koden och in i varje funktion eller åtgärd, spåra värdena för lokala variabler och följa kvantbitarnas kvanttillstånd.

I följande exempel visas hur du använder felsökningsprogrammet med ett Q# program. Fullständig information om VS Code-felsökningsprogram finns i Felsökning på VS Code-webbplatsen.

  1. I VS Code skapar och sparar du en ny .qs fil med följande kod:

    import Std.Arrays.*;
    import Std.Convert.*;
    
    operation Main() : Result {
        use qubit = Qubit();
        H(qubit);
        let result = M(qubit);
        Reset(qubit);
        return result;
    }
    
  2. På rad 6 H(qubit)klickar du till vänster om radnumret för att ange en brytpunkt. En röd cirkel visas.

  3. I det primära sidofältet väljer du felsökningsikonen för att öppna felsökningsfönstret och väljer sedan Kör och Felsök. Kontrollfältet för felsökning visas.

  4. Tryck på F5 för att starta felsökningsprogrammet och fortsätt till brytpunkten. I menyn Variabler i felsökningsfönstret expanderar du listrutan Kvanttillstånd för att se att kvantbiten har initierats i tillståndet $\ket{0}$ .

  5. Tryck på F11 för att gå in i åtgärden H . Källkoden för åtgärden H visas. Observera att kvanttillståndet ändras till en superposition när du går igenom åtgärden H .

  6. Tryck på F10 för att stega över åtgärden M . Observera att kvanttillståndet matchar antingen $\ket{0}$ eller $\ket{1}$ efter mätningen. Variabeln result visas också under Lokal.

  7. Tryck på F10 igen för att stega över åtgärden Reset . Observera att kvanttillståndet återställs till $\ket{0}$.

När du är klar med att utforska felsökningsprogrammet trycker du på *Ctrl + F5 för att avsluta felsökningsprogrammet.

Kommentar

VS Code-felsökningsprogrammet fungerar endast med Q# (.qs) och OpenQASM-filer (.qasm). Du kan inte använda VS Code-felsökningsprogrammet på Q# celler i Jupyter Notebook.

Så här felsöker du med QDK-dumpfunktioner

QDK innehåller flera Q# och Python-funktioner som dumpar information om programmets aktuella tillstånd när du anropar dessa funktioner. Använd information från dessa dumpfunktioner för att kontrollera om programmet fungerar som förväntat.

Funktionen Q#DumpMachine

DumpMachine är en Q# funktion som gör att du kan dumpa information om qubitsystemets aktuella tillstånd till konsolen när programmet körs. DumpMachine stoppar eller avbryter inte programmet under körningen.

I följande exempel anropas DumpMachine vid två tillfällen i ett Q#-program och resultaten analyseras.

  1. I VS Code skapar och sparar du en ny .qs fil med följande kod:

    import Std.Diagnostics.*;
    
    operation Main() : Unit {
        use qubits = Qubit[2];
        X(qubits[1]);
        H(qubits[1]);
        DumpMachine();
    
        R1Frac(1, 2, qubits[0]);
        R1Frac(1, 3, qubits[1]);
        DumpMachine();
    
        ResetAll(qubits);
    }
    
  2. Tryck på Ctrl + Skift + Y för att öppna felsökningskonsolen.

  3. Kör programmet genom att trycka på Ctrl + F5 . Följande utdata från DumpMachine visas i felsökningskonsolen:

    Basis | Amplitude      | Probability | Phase
    -----------------------------------------------
     |00⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
     |01⟩ | −0.7071+0.0000𝑖 |    50.0000% |  -3.1416
    
    Basis | Amplitude      | Probability | Phase
    -----------------------------------------------
     |00⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
     |01⟩ | −0.6533−0.2706𝑖 |    50.0000% |  -2.7489
    

Utdata från DumpMachine visar hur qubitsystemens tillstånd ändras efter varje uppsättning portar.

Kommentar

Utdata från DumpMachine använder big-endian-ordning.

Python-funktionen dump_machine

Funktionen dump_machine är en funktion från Python-paketet qsharp . Den här funktionen returnerar det aktuella allokerade kvantbitsantalet och en ordlista som innehåller glesa tillståndssamplituder för qubitsystemet.

I följande exempel körs samma program som i föregående DumpMachine exempel, men i en Jupyter-anteckningsbok i stället för en .qs fil.

  1. I VS Code trycker du på Ctrl + Skift + P för att öppna kommandopaletten.

  2. Ange Skapa: Ny Jupyter Notebook och tryck på Enter. En ny Jupyter Notebook-flik öppnas.

  3. I den första cellen kopierar och kör du följande kod:

    from qdk import qsharp 
    
  4. Skapa en ny kodcell och kopiera och kör sedan följande Q# kod:

    %%qsharp
    
    use qubits = Qubit[2];
    X(qubits[0]);
    H(qubits[1]);
    
  5. Skapa en ny kodcell. Kopiera och kör följande Python-kod för att visa qubittillståndet vid den här tidpunkten i programmet:

    dump = qsharp.dump_machine()
    dump
    

    Funktionen dump_machine visar följande utdata:

    Basis State
    (|𝜓₁…𝜓ₙ⟩)  Amplitude       Measurement Probability  Phase
    |10⟩       0.7071+0.0000𝑖   50.0000%                 ↑  0.0000
    |11⟩       0.7071+0.0000𝑖   50.0000%                 ↑  0.0000
    
  6. Skapa en ny kodcell och kopiera och kör sedan följande Q# kod:

    %%qsharp
    
    R1Frac(1, 2, qubits[0]);
    R1Frac(1, 3, qubits[1]);
    
  7. Skapa en ny kodcell. Kopiera och kör följande Python-kod för att visa qubittillståndet vid den här tidpunkten i programmet:

    dump = qsharp.dump_machine()
    dump
    

    Funktionen dump_machine visar följande utdata:

    Basis State
    (|𝜓₁…𝜓ₙ⟩)  Amplitude      Measurement Probability  Phase
    |10⟩       0.5000+0.5000𝑖  50.0000%                 ↗  0.7854
    |11⟩       0.2706+0.6533𝑖  50.0000%                 ↗  1.1781
    
  8. Om du vill skriva ut en förkortad version dump_machine av utdata skapar du en ny cell och kör följande Python-kod:

    print(dump)
    
  9. Om du vill hämta det totala antalet kvantbitar i systemet skapar du en ny kodcell och kör följande Python-kod:

    dump.qubit_count
    
  10. Du kan komma åt amplituderna för enskilda qubits-tillstånd som har icke-nollamlitud. Skapa till exempel en ny kodcell och kör följande Python-kod för att hämta de enskilda amplituderna för $\ket{10}$ och $\ket{11}$ tillstånd:

    print(dump[2])
    print(dump[3])
    

Funktionen dump_operation

Funktionen dump_operation är en funktion från Python-paketet qsharp.utils . Den här funktionen tar två indata: en Q# åtgärd eller åtgärdsdefinition som en sträng och antalet kvantbitar som används i åtgärden. Utdata från dump_operation är en kapslad lista som representerar kvadratmatrisen för komplexa tal som motsvarar den angivna kvantåtgärden. Matrisvärdena ligger i beräkningsbasen och varje underlista representerar en rad i matrisen.

I följande exempel används dump_operation för att visa information för ett 1-qubit- och 2-qubit-system.

  1. I VS Code trycker du på Ctrl + Skift + P för att öppna kommandopaletten.

  2. Ange Skapa: Ny Jupyter Notebook och tryck på Enter. En ny Jupyter Notebook-flik öppnas.

  3. I den första cellen kopierar och kör du följande kod:

    from qdk import qsharp
    from qsharp.utils import dump_operation
    
  4. Om du vill visa matriselementen i en port med en enda qubit anropar dump_operation du och skickar 1 för antalet kvantbitar. Kopiera och kör till exempel följande Python-kod i en ny kodcell för att hämta matriselementen för en identitetsport och en Hadamard-grind:

    res = dump_operation("qs => ()", 1)
    print("Single-qubit identity gate:\n", res)
    print()
    
    res = dump_operation("qs => H(qs[0])", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  5. Du kan också anropa funktionen qsharp.eval och sedan referera till Q#-operationen i dump_operation för att få samma resultat. Skapa till exempel en ny kodcell och kopiera och kör sedan följande Python-kod för att skriva ut matriselementen för en Hadamard-port med en enda qubit:

    qsharp.eval("operation SingleH(qs : Qubit[]) : Unit { H(qs[0]) }")
    
    res = dump_operation("SingleH", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  6. Om du vill visa matriselementen i en två-qubit-grind, anropar du dump_operation och anger 2 för antalet kvantbitar. Kopiera och kör till exempel följande Python-kod i en ny kodcell för att hämta matriselementen för en kontrollerad Ry-åtgärd där den andra qubiten är qubiten target :

    qsharp.eval ("operation ControlRy(qs : Qubit[]) : Unit { Controlled Ry([qs[0]], (0.5, qs[1])); }")
    
    res = dump_operation("ControlRy", 2)
    print("Controlled Ry rotation gate:\n", res)
    

Fler exempel på hur du testar och felsöker koden med dump_operationfinns i Testa åtgärder från QDK-exemplen.

Testa kvantkoden

QDK innehåller flera Q# funktioner och åtgärder som du kan använda för att testa koden när den körs. Du kan också skriva enhetstester för Q# program.

Uttrycket fail

Uttrycket fail avslutar omedelbart programmet. Om du vill införliva tester i koden använder du uttrycken fail i villkorssatserna.

I följande exempel används en fail -instruktion för att testa att en kvantbitsmatris innehåller exakt 3 qubits. Programmet slutar med ett felmeddelande när testet inte godkänns.

  1. I VS Code skapar och sparar du en ny .qs fil med följande kod:

    operation Main() : Unit {
        use qs = Qubit[6];
        let n_qubits = Length(qs);
    
        if n_qubits != 3 {
            fail $"The system should have 3 qubits, not {n_qubits}.";
        }  
    }
    
  2. Tryck på Ctrl + F5 för att köra programmet. Programmet misslyckas och följande utdata visas i felsökningskonsolen:

    Error: program failed: The system should have 3 qubits, not 6.
    
  3. Redigera koden från Qubit[6] till Qubit[3], spara filen och tryck sedan på Ctrl + F5 för att köra programmet igen. Programmet körs utan fel eftersom testet godkänns.

Funktionen Fact

Du kan också använda Q#Fact funktionen från Std.Diagnostics namnområdet för att testa koden. Funktionen Fact tar ett booleskt uttryck och en felmeddelandesträng. Om det booleska uttrycket är sant godkänns testet och programmet fortsätter att köras. Om det booleska uttrycket är falskt Fact avslutar du programmet och visar felmeddelandet.

Om du vill utföra samma matrislängdstest i din tidigare kod, mutter med Fact funktionen, följer du dessa steg:

  1. I VS Code skapar och sparar du en ny .qs fil med följande kod:

    import Std.Diagnostics.Fact;
    
    operation Main() : Unit {
        use qs = Qubit[6];
        let n_qubits = Length(qs);
    
        Fact(n_qubits == 3,  $"The system should have 3 qubits, not {n_qubits}.")
    }
    
  2. Tryck på Ctrl + F5 för att köra programmet. Testvillkoret i Fact godkänns inte och felmeddelandet visas i felsökningskonsolen.

  3. Redigera koden från Qubit[6] till Qubit[3], spara filen och tryck sedan på Ctrl + F5 för att köra programmet igen. Testvillkoret i Fact godkänns och programmet körs utan fel.

Skriv enhetstester med annoteringen Q#@Test()

I Q# program kan du tillämpa annoteringen @Test() på den anropsbara komponenten (funktion eller åtgärd) för att omvandla den anropsbara komponenten till ett enhetstest. Dessa enhetstester visas på menyn Testning i VS Code så att du kan dra nytta av den här VS Code-funktionen. Du kan endast göra ett anropsbart till ett enhetstest när det anropsbara inte tar några indataparametrar.

I följande exempel omsluts testkoden för matrislängd i en åtgärd och åtgärden omvandlas till ett enhetstest:

  1. I VS Code skapar och sparar du en ny .qs fil med följande kod:

    import Std.Diagnostics.Fact;
    
    @Test()
    operation TestCase() : Unit {
        use qs = Qubit[3];
        let n_qubits = Length(qs);
    
        Fact(n_qubits == 3, $"The system should have 3 qubits, not {n_qubits}.");
    }
    

    Kommentaren @Test() på raden innan åtgärdsdefinitionen TestCase omvandlar åtgärden till ett VS Code-enhetstest. En grön pil visas på åtgärdsdefinitionsraden.

  2. Välj den gröna pilen för att köra TestCase och rapportera testresultaten.

  3. Om du vill interagera med dina enhetstester i VS Code Test Explorer väljer du ikonen Testkolv i det primära sidofältet.

  4. Redigera koden från Qubit[3] till Qubit[6] och kör enhetstestet igen för att se hur testinformationen ändras.

Du kan skriva och köra Q# enhetstester i VS Code utan en startpunktsåtgärd i programmet.

Kommentar

Anropsbara filer från Std.Diagnostics namnområdet är inte kompatibla med QIR-generering, så inkludera endast enhetstester i Q# kod som du kör på simulatorer. Om du vill generera QIR från koden Q# ska du inte inkludera enhetstester i koden.

Operationerna CheckZero och CheckAllZero

Åtgärderna CheckZero och CheckAllZeroQ# kontrollerar om det aktuella tillståndet för en qubit- eller qubit-matris är $\ket{0}$. Åtgärden CheckZero tar en enda qubit och returnerar true endast när qubiten är i tillståndet $\ket{0}$ . Åtgärderna CheckAllZero tar en qubitmatris och returnerar true endast när alla kvantbitar i matrisen är i tillståndet $\ket{0}$ . Om du vill använda CheckZero och CheckAllZeroimporterar du dem från Std.Diagnostics namnområdet.

I följande exempel används båda åtgärderna. Den CheckZero testar att X åtgärden vänder den första qubiten från $\ket{0}$ till $\ket{1}$, och CheckAllZero åtgärden testar att båda qubitarna återställs till det $\ket{0}$.

I VS Code skapar och sparar du en ny .qs fil med följande kod, kör sedan programmet och undersöker utdata i felsökningskonsolen.

import Std.Diagnostics.*;

operation Main() : Unit {
    use qs = Qubit[2];
    X(qs[0]); 

    if CheckZero(qs[0]) {
        Message("X operation failed");
    }
    else {
        Message("X operation succeeded");
    }

    ResetAll(qs);

    if CheckAllZero(qs) {
        Message("Reset operation succeeded");
    }
    else {
        Message("Reset operation failed");
    }
}