Megosztás a következőn keresztül:


A kvantumkód hibakeresése és tesztelése

A klasszikus programozáshoz hasonlóan elengedhetetlen annak ellenőrzése, hogy a kvantumprogramok a kívánt módon működnek-e, és hogy képesek legyenek-e a helytelen viselkedés diagnosztizálására. Ez a cikk az Azure Quantum Development Kit által a kvantumprogramok teszteléséhez és hibakereséséhez kínált eszközöket ismerteti.

A Q# program hibakeresése

Az Azure Quantum Development Kit (QDK) Visual Studio Code bővítmény tartalmaz egy hibakeresőt Q# programokhoz. Beállíthat töréspontokat, végiglépkedhet a kódon és az egyes függvényeken vagy műveleteken, és nemcsak a helyi változókat, hanem a qubitek kvantumállapotát is nyomon követheti.

Feljegyzés

A VS Code hibakereső csak Q# (.qs) fájlokkal működik, és nem működik a Jupyter Notebook Q# celláival. A Jupyter Notebook-cellák teszteléséhez lásd a kód tesztelése.

Az alábbi példa a hibakereső alapvető funkcióit mutatja be. A VS Code hibakeresőinek használatával kapcsolatos teljes körű információkért lásd a hibakeresést.

A VS Code-ban hozzon létre és mentsen egy új .qs-fájlt a következő kóddal:

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. Állítson be egy töréspontot a H(qubit) sorban, ha a sorszám bal oldalára kattint.
  2. A hibakereső panel megnyitásához válassza a hibakereső ikont, majd válassza a Futtatás és hibakeresés lehetőséget. A hibakereső vezérlők a képernyő tetején jelennek meg.
  3. A hibakeresés megkezdéséhez válassza az F5 lehetőséget, és folytassa a törésponttal. a hibakereső Változók paneljén bontsa ki a Quantum State kategóriát. Láthatja, hogy a qubit a |0> állapotban lett inicializálva.
  4. Lépjen be (F11) a H műveletbe, és megjelenik a H művelet forráskódja. A művelet során figyelje meg a kvantumérték változásait, mivel a H művelet a qubitet szuperpozícióba helyezi.
  5. Az (F10) billentyű lenyomásakor a M műveletnél a kvantumérték a mérés eredményeként vagy |0> vagy |1> állapotra dől el, és megjelenik a klasszikus változó result értéke.
  6. Amikor túllépsz a műveleten, a qubit alaphelyzetbe áll |0> értékre.

A kód tesztelése

Bár a VS Code Q# hibakeresője nem érhető el a Jupyter Notebook Q# cellákban, az Azure QDK olyan kifejezéseket és függvényeket biztosít, amelyek segíthetnek a kód hibaelhárításában.

Hibakifejezés

A fail kifejezés teljes egészében befejezi a számítást, egy végzetes hibának felel meg, amely leállítja a programot.

Tekintse meg ezt az egyszerű példát, amely egy paraméter értékét érvényesíti:

# 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 │     }   
   ╰────

Itt a fail kifejezés megakadályozza, hogy a program érvénytelen adatokkal fusson tovább.

Fact() függvény

Az előző példában bemutatott viselkedést a Fact() függvény használatával is megvalósíthatja a Microsoft.Quantum.Diagnostics névtérből. A Fact() függvény kiértékel egy adott klasszikus feltételt, és kivételt ad, ha hamis.

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() függvény

DumpMachine() egy Q# függvény, amely lehetővé teszi, hogy a target gép aktuális állapotával kapcsolatos információkat megjelenítsen a konzolon, és folytassa a program futtatását.

Feljegyzés

Az Azure Quantum Development Kit kiadásával a DumpMachine() függvény most már big-endian rendezést használ a kimenetéhez.

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() függvény

dump_machine egy Python-függvény, amely visszaadja az aktuálisan lefoglalt qubitek számát, és egy Python-szótárt a ritka állapot-amplitúdókkal, amelyet elemezhetsz. A Jupyter Notebookban bármelyik függvény használatával a hibakeresőhöz hasonló módon végiglépkedhet a műveletein. Az előző példaprogram használata:

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() és CheckAllZero() műveletek

CheckZero() és CheckAllZero()Q# műveletek, amelyek ellenőrizhetik, hogy a qubit vagy a qubitek tömbjének aktuális állapota $\ket{0}$-e. CheckZero() true ad vissza, ha a qubit $\ket{0}$ állapotban van, és false, ha bármilyen más állapotban van. CheckAllZero() true ad vissza, ha a tömb összes qubitje $\ket{0}$ állapotban van, és false, hogy a qubitek más állapotban vannak-e.

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() függvény

dump_operation egy Python-függvény, amely egy műveletet vagy műveletdefiníciót, valamint számos használandó qubitet használ, és a művelet kimenetét jelképező összetett számok négyzetes mátrixát adja vissza.

Te importálsz dump_operationqsharp.utils-ból.

import qsharp
from qsharp.utils import dump_operation

Ez a példa egy egy qubites identitáskapu és a Hadamard-kapu mátrixát nyomtatja ki.

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)]]

Függvényt vagy műveletet is definiálhat qsharp.eval() használatával, majd hivatkozhat rá dump_operation. A korábban képviselt egyetlen qubit a következőként is ábrázolható:

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

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

Ez a példa egy Controlled Ry kaput használ a második qubit elforgatásához

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)]]

Az alábbi kód meghatározza Q# műveletet ApplySWAP, és a mátrixot a két qubites identitásművelettel együtt nyomtatja ki.

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)]]

A dump_operation() használatával végzett tesztelési műveletekre további példák találhatók a QDK-tesztelési műveleteinek mintalapján.