Delen via


Fouten opsporen en uw kwantumcode testen

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.

Fouten opsporen in 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. Zie Uw code testen voor het testen van Jupyter Notebook-cellen.

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

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 onderbrekingspunt op de regel H(qubit) in 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 besturingselementen voor het foutopsporingsprogramma worden boven aan het scherm weergegeven.
  3. Selecteer F5 om foutopsporing te starten en door te gaan naar het onderbrekingspunt. Vouw in het deelvenster Variabelen voor foutopsporing de categorie Kwantumstatus uit. U kunt zien dat de qubit is geïnitialiseerd in de status |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 bewerking de H qubit in superpositie plaatst.
  5. Wanneer u de M bewerking stapt (F10), wordt de kwantumwaarde omgezet in |0> of |1> als gevolg van de meting en wordt de waarde van de klassieke variabele result weergegeven.
  6. Wanneer u de Reset bewerking uitvoert, 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 wordt uitgevoerd 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 bepaalde 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 Azure Quantum Development Kitmaakt 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-woordenlijst met sparse-statusamplitudes 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() bewerkingen die Q# kunnen controleren of de huidige status van een qubit- of qubitmatrix $\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 ApplySWAP gedefinieerd Q# en wordt de matrix afgedrukt naast die van de twee-qubitidentiteitsbewerking.

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 vindt dump_operation() u op de voorbeeldpagina Testbewerkingen in de QDK.