Sdílet prostřednictvím


Ladění a testování kvantového kódu

Stejně jako u klasického programování je nezbytné zkontrolovat, jestli kvantové programy fungují podle očekávání, a aby bylo možné diagnostikovat nesprávné chování. Tento článek popisuje nástroje, které Azure Quantum Development Kit nabízí k testování a ladění kvantových programů.

Q# Ladění programu

Rozšíření Editoru Visual Studio Code v Azure Quantum Development Kit (QDK) obsahuje ladicí program pro Q# programy. Můžete nastavit zarážky, procházet kódem a do každé funkce nebo operace a sledovat nejen místní proměnné, ale také kvantový stav qubitů.

Poznámka:

Ladicí program VS Code funguje jenom se Q# soubory (.qs) a nefunguje s buňkami Q# v poznámkovém bloku Jupyter. Informace o testování buněk poznámkového bloku Jupyter najdete v tématu Testování kódu.

Následující příklad ukazuje základní funkce ladicího programu. Úplné informace o používání ladicích programů VS Code naleznete v tématu Ladění.

Ve VS Code vytvořte a uložte nový soubor .qs s následujícím kódem:

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. Nastavte zarážku na řádku H(qubit) kliknutím nalevo od čísla řádku.
  2. Výběrem ikony ladicího programu otevřete podokno ladicího programu a vyberte Spustit a Ladit. Ovládací prvky ladicího programu se zobrazí v horní části obrazovky.
  3. Výběrem klávesy F5 spusťte ladění a pokračujte na zarážku. V podokně Proměnné ladicího programu rozbalte kategorii Kvantového stavu. Vidíte, že qubit byl inicializován ve stavu |0> .
  4. Přejděte do operace (F11) H a zobrazí se zdrojový kód operace H . Při procházení operace si všimněte změny kvantové hodnoty, protože H operace umístí qubit do superpozice.
  5. Při krokování operace (F10) M se kvantová hodnota v důsledku měření přeloží na hodnotu |0> nebo |1> a zobrazí se hodnota klasické proměnné result .
  6. Při krokování operace Reset se qubit resetuje na |0>.

Testování kódu

I když ladicí program VS Code Q# není k dispozici pro Q# buňky v poznámkovém bloku Jupyter, Sada Azure QDK poskytuje některé výrazy a funkce, které vám můžou pomoct s řešením potíží s kódem.

Výraz selhání

Výraz fail zcela ukončí výpočet, který odpovídá závažné chybě, která program zastaví.

Podívejte se na tento jednoduchý příklad, který ověřuje hodnotu parametru:

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

V této části fail výraz zabrání programu pokračovat ve spouštění s neplatnými daty.

Fact()

Pomocí funkce z oboru názvů můžete implementovat stejné chování jako v předchozím příkladu Fact() Microsoft.Quantum.Diagnostics . Funkce Fact() vyhodnotí danou klasickou podmínku a vyvolá výjimku, pokud je false.

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

DumpMachine()Q# je funkce, která umožňuje výpis informací o aktuálním stavu target počítače do konzoly a nadále spouštět program.

Poznámka:

Ve verzi Azure Quantum Development KitDumpMachine() teď funkce používá pro svůj výstup velké řazení endian.

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

dump_machine je funkce Pythonu, která vrací aktuální přidělený počet qubitů a slovník Pythonu řídkých amplitud stavu, které můžete analyzovat. Použití některé z těchto funkcí v poznámkovém bloku Jupyter umožňuje procházet operace podobně jako ladicí program. Použití předchozího ukázkového programu:

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)

Operace CheckZero() a CheckAllZero()

CheckZero() a CheckAllZero() jsou Q# operace, které můžou zkontrolovat, jestli je aktuální stav qubitu nebo pole qubitu $\ket{0}$. CheckZero() vrátí true , pokud je qubit ve stavu $\ket{0}$ a false pokud je v jiném stavu. CheckAllZero() vrátí true , pokud jsou všechny qubity v poli ve stavu $\ket{0}$ a false pokud jsou qubity v jiném stavu.

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

dump_operation je funkce Pythonu, která přebírá operaci nebo definici operace a počet qubitů, které se mají použít, a vrací druhou matici komplexních čísel představující výstup operace.

Importujete dump_operation z qsharp.utils.

import qsharp
from qsharp.utils import dump_operation

Tento příklad vytiskne matici brány identit s jedním qubitem a bránou Hadamard.

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

Můžete také definovat funkci nebo operaci pomocí qsharp.eval() a pak na ni odkazovat z dump_operation. Jeden qubit reprezentovaný dříve může být také reprezentován jako

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

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

Tento příklad používá bránu Controlled Ry k použití rotace na druhý 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)]]

Následující kód definuje operaci ApplySWAP a vytiskne Q# matici vedle operace dvou qubitů identity.

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

Další příklady testovacích operací, které se používají dump_operation() , najdete na stránce Ukázkové testovací operace v sadě QDK.