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;
}
- Stel een onderbrekingspunt op de regel
H(qubit)
in door links van het regelnummer te klikken. - 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.
- 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> .
- Stap in (F11) de
H
bewerking en de broncode voor deH
bewerking wordt weergegeven. Wanneer u de bewerking doorloopt, ziet u dat de kwantumwaarde verandert wanneer de bewerking deH
qubit in superpositie plaatst. - 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 variabeleresult
weergegeven. - 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.