Delen via


Debuggen en testen van kwantumcode

Net als bij klassieke programmering is het essentieel om te kunnen controleren of kwantumprogramma's werken zoals bedoeld en om onjuist gedrag te kunnen diagnosticeren. In dit artikel worden de hulpprogramma's besproken die door Azure Quantum Development Kit worden aangeboden voor het testen en opsporen van fouten in kwantumprogramma's.

Debug uw Q# programma

De Visual Studio Code-extensie (QDK) van Azure Quantum Development Kit bevat een foutopsporingsprogramma voor Q# programma's. U kunt onderbrekingspunten instellen, uw code doorlopen en in elke functie of bewerking, en niet alleen de lokale variabelen bijhouden, maar ook de kwantumstatus van de qubits.

Notitie

Het VS Code-foutopsporingsprogramma werkt alleen met Q# (.qs)-bestanden en werkt niet met Q# cellen in een Jupyter Notebook. Voor het testen van Jupyter Notebook-cellen, zie Uw code testen.

In het volgende voorbeeld ziet u de basisfuncties van het foutopsporingsprogramma. Zie Debugging voor volledige informatie over het gebruik van VS Code-debuggers.

Maak en sla in VS Code een nieuw .qs-bestand op met de volgende code:

import Microsoft.Quantum.Arrays.*;
import Microsoft.Quantum.Convert.*;

operation Main() : Result {
    use qubit = Qubit();
    H(qubit);
    let result = M(qubit);
    Reset(qubit);
    return result;
}
  1. Stel een breakpoint in op de regel H(qubit) door links van het regelnummer te klikken.
  2. Selecteer het pictogram voor foutopsporingsprogramma om het foutopsporingsprogrammavenster te openen en selecteer Uitvoeren en fouten opsporen. De bedieningsknoppen van de debugger worden boven aan het scherm weergegeven.
  3. Selecteer F5 om foutopsporing te starten en door te gaan naar het onderbrekingspunt. Vouw in het deelvenster voor foutopsporing Variabelen de categorie Quantumtoestand uit. U kunt zien dat de qubit is geïnitialiseerd in de toestand |0>.
  4. Stap in (F11) de H bewerking en de broncode voor de H bewerking wordt weergegeven. Wanneer u de bewerking doorloopt, ziet u dat de kwantumwaarde verandert wanneer de H bewerking de qubit in superpositie plaatst.
  5. Wanneer u de M-bewerking stapt (F10), wordt de kwantumwaarde als gevolg van de meting omgezet in |0> of |1> en wordt de waarde van de klassieke variabele result weergegeven.
  6. Terwijl u over de Reset bewerking heen stapt, wordt de qubit opnieuw ingesteld op |0>.

Uw code testen

Hoewel het foutopsporingsprogramma van VS Code Q# niet beschikbaar is voor Q# cellen in een Jupyter Notebook, biedt de Azure QDK enkele expressies en functies waarmee u problemen met uw code kunt oplossen.

Expressie mislukt

De fail expressie beëindigt de berekening volledig, wat overeenkomt met een fatale fout die het programma stopt.

Bekijk dit eenvoudige voorbeeld waarmee een parameterwaarde wordt gevalideerd:

# import qsharp package to access the %%qsharp magic command
import qsharp 
// use the %%qsharp magic command to change the cell type from Python to Q#
%%qsharp 
function PositivityFact(value : Int) : Unit {
    if value <= 0 {
        fail $"{value} isn't a positive number.";
    }   
}
PositivityFact(0);
Error: program failed: 0 isn't a positive number.
Call stack:
    at PositivityFact in line_2
Qsc.Eval.UserFail

  × runtime error
  ╰─▶ program failed: 0 isn't a positive number.
   ╭─[line_2:5:1]
 5 │ 
 6 │             fail $"{value} isn't a positive number.";
   ·             ────────────────────┬───────────────────
   ·                                 ╰── explicit fail
 7 │     }   
   ╰────

Hier voorkomt de fail expressie dat het programma doorgaat met ongeldige gegevens.

De functie Fact()

U kunt hetzelfde gedrag implementeren als in het vorige voorbeeld met behulp van de Fact() functie uit de Microsoft.Quantum.Diagnostics naamruimte. De Fact() functie evalueert een gegeven klassieke voorwaarde en genereert een uitzondering als deze onwaar is.

import qsharp 
%%qsharp
function PositivityFact(value : Int) : Unit {
    Fact(value > 0, "Expected a positive number."); 
}
PositivityFact(4);
Error: program failed: Expected a positive number.
Call stack:
    at Microsoft.Quantum.Diagnostics.Fact in diagnostics.qs
    at PositivityFact in line_4
Qsc.Eval.UserFail

  × runtime error
  ╰─▶ program failed: Expected a positive number.
    ╭─[diagnostics.qs:29:1]
 29 │         if (not actual) {
 30 │             fail message;
    ·             ──────┬─────
    ·                   ╰── explicit fail
 31 │         }
    ╰────

DumpMachine() functie

DumpMachine() is een Q# functie waarmee u informatie over de huidige status van de target computer naar de console kunt dumpen en uw programma kunt blijven uitvoeren.

Notitie

Met de release van de Azure Quantum Development Kit maakt de DumpMachine() functie nu gebruik van big-endian-volgorde voor de uitvoer.

import qsharp
%%qsharp
import Microsoft.Quantum.Diagnostics.*;
operation MultiQubitDumpMachineDemo() : 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);
}
MultiQubitDumpMachineDemo();
Basis State
(|𝜓₁…𝜓ₙ⟩)	Amplitude	Measurement Probability	Phase
|00⟩	0.7071+0.0000𝑖	 50.0000%	↑	0.0000
|01⟩	−0.7071+0.0000𝑖	 50.0000%	↓	-3.1416

Basis State
(|𝜓₁…𝜓ₙ⟩)	Amplitude	Measurement Probability	Phase
|00⟩	0.7071+0.0000𝑖	 50.0000%	↑	0.0000
|01⟩	−0.6533−0.2706𝑖	 50.0000%	↙	-2.7489   

dump_machine() functie

dump_machine is een Python-functie die het huidige aantal toegewezen qubits retourneert en een Python-woordenboek met spaarzame toestandamplitudes die u kunt parseren. Door een van deze functies in een Jupyter Notebook te gebruiken, kunt u uw bewerkingen stapsgewijs doorlopen, net als een foutopsporingsprogramma. Het vorige voorbeeldprogramma gebruiken:

import qsharp 
%%qsharp
use qubits = Qubit[2];
X(qubits[0]);
H(qubits[1]);
dump = qsharp.dump_machine()
dump

Basis State
(|𝜓₁…𝜓ₙ⟩)	Amplitude	Measurement Probability	Phase
|10⟩	0.7071+0.0000𝑖	 50.0000%	↑	0.0000
|11⟩	0.7071+0.0000𝑖	 50.0000%	↑	0.0000
%%qsharp
R1Frac(1, 2, qubits[0]);
R1Frac(1, 3, qubits[1]);
dump = qsharp.dump_machine()
dump
Basis State
(|𝜓₁…𝜓ₙ⟩)	Amplitude	Measurement Probability	Phase
|10⟩	0.5000+0.5000𝑖	 50.0000%	↗	0.7854
|11⟩	0.2706+0.6533𝑖	 50.0000%	↗	1.1781    
# you can print an abbreviated version of the values
print(dump)
STATE:
|10⟩: 0.5000+0.5000𝑖
|11⟩: 0.2706+0.6533𝑖
# you can access the current qubit count
dump.qubit_count
2
# you can access individual states by their index
dump[2]
(0.5+0.5000000000000001j)
dump[3]
(0.27059805007309845+0.6532814824381883j)

CheckZero()- en CheckAllZero()-bewerkingen

CheckZero() en CheckAllZero() zijn Q# bewerkingen die kunnen controleren of de status van een qubit of qubit-array $\ket{0}$ is. CheckZero() retourneert true als de qubit de status $\ket{0}$ heeft en false of deze zich in een andere status bevindt. CheckAllZero() retourneert true als alle qubits in de matrix de status $\ket{0}$ hebben en false als de qubits een andere status hebben.

import Microsoft.Quantum.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");
    }
}

dump_operation() functie

dump_operation is een Python-functie die een bewerking of een bewerkingsdefinitie gebruikt, en een aantal qubits dat moet worden gebruikt, en retourneert een vierkante matrix met complexe getallen die de uitvoer van de bewerking vertegenwoordigen.

U importeert dump_operation van qsharp.utils.

import qsharp
from qsharp.utils import dump_operation

In dit voorbeeld wordt de matrix van een identiteitspoort met één qubit en de Hadamard-poort afgedrukt.

res = dump_operation("qs => ()", 1)
print(res)
res = dump_operation("qs => H(qs[0])", 1)
print(res)
[[(1+0j), 0j], [0j, (1+0j)]]
[[(0.707107+0j), (0.707107+0j)], [(0.707107+0j), (-0.707107-0j)]]

U kunt ook een functie of bewerking definiëren met behulp van qsharp.eval() en vervolgens ernaar verwijzen.dump_operation De enkele qubit die eerder wordt weergegeven, kan ook worden weergegeven als

qsharp.eval("operation SingleQ(qs : Qubit[]) : Unit { }")

res = dump_operation("SingleQ", 1)
print(res)
[[(1+0j), 0j], [0j, (1+0j)]]

In dit voorbeeld wordt een Controlled Ry poort gebruikt om een rotatie toe te passen op de tweede qubit

qsharp.eval ("operation ControlRy(qs : Qubit[]) : Unit {qs[0]; Controlled Ry([qs[0]], (0.5, qs[1]));}")

res = dump_operation("ControlRy", 2)
print(res)
[[(1+0j), 0j, 0j, 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, (0.968912+0j), (-0.247404+0j)], [0j, 0j, (0.247404+0j), (0.968912+0j)]]

Met de volgende code wordt de bewerking Q# gedefinieerd en wordt de matrix afgedrukt naast die van de twee-qubit identiteitsbewerking.

qsharp.eval("operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); }")

res = dump_operation("qs => ()", 2)
print(res)
res = dump_operation("ApplySWAP", 2)
print(res)
[[(1+0j), 0j, 0j, 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, (1+0j), 0j], [0j, 0j, 0j, (1+0j)]]
[[(1+0j), 0j, 0j, 0j], [0j, 0j, (1+0j), 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, 0j, (1+0j)]]

Meer voorbeelden van testbewerkingen met dump_operation() kunt u vinden op de voorbeeldpagina Testbewerkingen in de QDK.