Så här felsöker och testar du kvantkoden
Precis som med klassisk programmering är det viktigt att kunna kontrollera att kvantprogram fungerar som avsett och att kunna diagnostisera felaktigt beteende. I den här artikeln beskrivs de verktyg som erbjuds av Azure Quantum Development Kit för testning och felsökning av kvantprogram.
Felsöka ditt Q# program
Tillägget Azure Quantum Development Kit (QDK) Visual Studio Code innehåller ett felsökningsprogram för Q# program. Du kan ange brytpunkter, stega igenom koden och in i varje funktion eller åtgärd och spåra inte bara de lokala variablerna, utan även kvanttillståndet för kvantbitarna.
Kommentar
VS Code-felsökningsprogrammet fungerar bara med Q# (.qs) filer och fungerar inte med Q# celler i en Jupyter Notebook. Information om hur du testar Jupyter Notebook-celler finns i Testa din kod.
I följande exempel visas de grundläggande funktionerna i felsökningsprogrammet. Fullständig information om hur du använder VS Code-felsökningsprogram finns i Felsökning.
I VS Code skapar och sparar du en ny .qs-fil med följande kod:
import Microsoft.Quantum.Arrays.*;
import Microsoft.Quantum.Convert.*;
operation Main() : Result {
use qubit = Qubit();
H(qubit);
let result = M(qubit);
Reset(qubit);
return result;
}
- Ange en brytpunkt på raden
H(qubit)
genom att klicka till vänster om radnumret. - Välj felsökningsikonen för att öppna felsökningsfönstret och välj Kör och Felsök. Felsökningskontrollerna visas överst på skärmen.
- Välj F5 för att börja felsöka och fortsätta till brytpunkten. I fönstret Variabler för felsökning expanderar du kategorin Kvanttillstånd. Du kan se att kvantbiten har initierats i tillståndet |0> .
- Stega in i (F11) åtgärden
H
och källkoden förH
åtgärden visas. När du går igenom åtgärden bör du notera att kvantvärdet ändras närH
åtgärden placerar kvantbiten i superposition. - När du kliver över (F10)
M
matchas kvantvärdet till antingen |0> eller |1> som ett resultat av mätningen, och värdet för den klassiska variabelnresult
visas. - När du kliver över åtgärden
Reset
återställs kvantbiten till |0>.
Testa koden
Även om VS Code-felsökaren Q# inte är tillgänglig för Q# celler i en Jupyter Notebook innehåller Azure QDK vissa uttryck och funktioner som kan hjälpa dig att felsöka koden.
Feluttryck
Uttrycket fail
avslutar beräkningen helt och hållet, vilket motsvarar ett allvarligt fel som stoppar programmet.
Tänk dig det här enkla exemplet som validerar ett parametervärde:
# 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 │ }
╰────
fail
Här förhindrar uttrycket att programmet fortsätter att köras med ogiltiga data.
Funktionen Fact()
Du kan implementera samma beteende som i föregående exempel med hjälp av Fact()
funktionen från Microsoft.Quantum.Diagnostics
namnområdet. Funktionen Fact()
utvärderar ett angivet klassiskt villkor och utlöser ett undantag om det är falskt.
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 │ }
╰────
Funktionen DumpMachine()
DumpMachine()
är en Q# funktion som gör att du kan dumpa information om datorns target aktuella tillstånd till konsolen och fortsätta att köra programmet.
Kommentar
Med lanseringen av Azure Quantum Development KitDumpMachine()
använder funktionen nu storslutsordning för sina utdata.
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
funktionen dump_machine()
dump_machine
är en Python-funktion som returnerar det aktuella allokerade kvantbitsantalet och en Python-ordlista med glesa tillståndssamplituder som du kan parsa. Med någon av dessa funktioner i en Jupyter Notebook kan du gå igenom dina åtgärder ungefär som ett felsökningsprogram. Använd föregående exempelprogram:
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() och CheckAllZero() åtgärder
CheckZero()
och CheckAllZero()
är Q# åtgärder som kan kontrollera om det aktuella tillståndet för en qubit- eller qubit-matris är $\ket{0}$. CheckZero()
returnerar true
om kvantbiten är i tillståndet $\ket{0}$ och false
om den är i något annat tillstånd. CheckAllZero()
returnerar true
om alla kvantbitar i matrisen är i tillståndet $\ket{0}$ och false
om kvantbitarna är i något annat tillstånd.
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");
}
}
funktionen dump_operation()
dump_operation
är en Python-funktion som tar en åtgärd eller åtgärdsdefinition och ett antal kvantbitar att använda och returnerar en kvadratmatris med komplexa tal som representerar utdata från åtgärden.
Du importerar dump_operation
från qsharp.utils
.
import qsharp
from qsharp.utils import dump_operation
Det här exemplet skriver ut matrisen för en identitetsport med en enda qubit och Hadamard-porten.
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)]]
Du kan också definiera en funktion eller åtgärd med och qsharp.eval()
sedan referera till den från dump_operation
. Den enda qubit som representeras tidigare kan också representeras som
qsharp.eval("operation SingleQ(qs : Qubit[]) : Unit { }")
res = dump_operation("SingleQ", 1)
print(res)
[[(1+0j), 0j], [0j, (1+0j)]]
I det här exemplet används en Controlled Ry
grind för att tillämpa en rotation på den andra kvantbiten
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)]]
Följande kod definierar Q# åtgärden ApplySWAP
och skriver ut dess matris tillsammans med den två qubitsidentitetsåtgärden.
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)]]
Fler exempel på teståtgärder som använder dump_operation()
finns på exempelsidan Testningsåtgärder i QDK.