Debugowanie i testowanie kodu kwantowego

Podobnie jak w przypadku programowania klasycznego, ważne jest, aby móc sprawdzić, czy programy kwantowe działają zgodnie z oczekiwaniami i aby móc diagnozować nieprawidłowe zachowanie. W tym artykule omówiono narzędzia oferowane przez platformę Azure Quantum Development Kit do testowania i debugowania programów kwantowych.

Q# Debugowanie programu

Rozszerzenie Visual Studio Code platformy Azure Quantum Development Kit (Nowoczesne zestawY QDK) zawiera debuger dla Q# programów. Możesz ustawić punkty przerwania, przejść przez kod i do każdej funkcji lub operacji i śledzić nie tylko zmienne lokalne, ale także stan kwantowy kubitów.

Uwaga

Debuger programu VS Code działa tylko z plikami Q# (qs) i nie działa z komórkami Q# w Jupyter Notebook. Aby przetestować Jupyter Notebook komórek, zobacz Testowanie kodu.

W poniższym przykładzie przedstawiono podstawowe funkcje debugera. Aby uzyskać pełne informacje na temat korzystania z debugerów programu VS Code, zobacz Debugowanie.

W programie VS Code utwórz i zapisz nowy plik qs przy użyciu następującego kodu:

namespace Sample {

    open Microsoft.Quantum.Arrays;
    open Microsoft.Quantum.Convert;

    @EntryPoint()
    operation Superposition() : Result {

        use qubit = Qubit();
        H(qubit);
        let result = M(qubit);
        Reset(qubit);
        return result;
    }
}
  1. Ustaw punkt przerwania w wierszu H(qubit) , klikając po lewej stronie numeru wiersza.
  2. Wybierz ikonę debugera, aby otworzyć okienko debugera, a następnie wybierz pozycję Uruchom i Debuguj. Kontrolki debugera są wyświetlane w górnej części ekranu.
  3. Wybierz klawisz F5, aby rozpocząć debugowanie i przejdź do punktu przerwania. W okienku Zmienne debugera rozwiń kategorię Stan kwantowy . Widać, że kubit został zainicjowany w stanie |0> .
  4. Krok do (F11) H operacji i kodu źródłowego H dla operacji jest wyświetlany. Podczas wykonywania operacji zwróć uwagę, że wartość kwantowa zmienia się, gdy H operacja umieszcza kubit w superpozycję.
  5. Po zakończeniu M operacji (F10) wartość kwantowa jest rozpoznawana jako |0> lub |1> w wyniku pomiaru, a wartość zmiennej result klasycznej jest wyświetlana.
  6. Podczas przechodzenia przez operację Reset kubit jest resetowany do |0>.

Testowanie kodu

Chociaż debuger programu VS Code Q# nie jest dostępny dla Q# komórek w Jupyter Notebook, nowoczesny zestaw QDK udostępnia pewne wyrażenia i funkcje, które mogą pomóc w rozwiązywaniu problemów z kodem.

Wyrażenie niepowodzenia

Wyrażenie fail kończy obliczenia całkowicie, co odpowiada krytycznemu błędowi, który zatrzymuje program.

Rozważmy ten prosty przykład, który weryfikuje wartość parametru:

import qsharp 
# import qsharp package to acccess the %%qsharp magic command
%%qsharp 
// use the %%qsharp magic command to change the cell type from Python to Q#

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 W tym miejscu wyrażenie uniemożliwia programowi kontynuowanie działania z nieprawidłowymi danymi.

Fact(), funkcja

Możesz zaimplementować to samo zachowanie co w poprzednim przykładzie przy użyciu Fact() funkcji z Microsoft.Quantum.Diagnostics przestrzeni nazw. Funkcja Fact() ocenia dany warunek klasyczny i zgłasza wyjątek, jeśli jest to fałsz.

import qsharp 
# import qsharp package to acccess the %%qsharp magic command
%%qsharp
// use the %%qsharp magic command to change the cell type from Python to Q#

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

DumpMachine() to Q# funkcja, która pozwala zrzucić informacje o bieżącym stanie target maszyny do konsoli i kontynuować uruchamianie programu.

Uwaga

Po wydaniu platformy Azure Quantum Development KitDumpMachine() funkcja używa teraz kolejności big-endian dla danych wyjściowych.

import qsharp
%%qsharp

open 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
|10⟩	−0.7071+0.0000𝑖	 50.0000%	↑	-3.1416

Basis State
(|𝜓ₙ…𝜓₁⟩)	Amplitude	Measurement Probability	Phase
|00⟩	0.5879−0.3928𝑖	 50.0000%	↑	-0.5890
|10⟩	−0.6935+0.1379𝑖	 50.0000%	↑	2.9452

dump_machine(), funkcja

dump_machine to funkcja języka Python, która zwraca bieżącą przydzieloną liczbę kubitów i słownik języka Python o rozrzednych amplitudach stanu, które można przeanalizować. Użycie jednej z tych funkcji w Jupyter Notebook umożliwia przechodzenie przez operacje podobnie jak debuger. Przy użyciu poprzedniego przykładowego programu:

import qsharp 
# import qsharp package to acccess the %%qsharp magic command
%%qsharp
// use the %%qsharp magic command to change the cell type from Python to Q#

use qubits = Qubit[2];
X(qubits[0]);
H(qubits[1]);
dump = qsharp.dump_machine()
dump

Basis State
(|𝜓ₙ…𝜓₁⟩)	Amplitude	Measurement Probability	Phase
|11⟩	0.7071+0.0000𝑖	 50.0000%	↑	0.0000
|01⟩	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
|11⟩	0.5879+0.3928𝑖	 50.0000%	↑	0.5890
|01⟩	0.6935+0.1379𝑖	 50.0000%	↑	0.1963
# you can print an abbreviated version of the values
print(dump)
STATE:
|11⟩: 0.5879+0.3928𝑖
|01⟩: 0.6935+0.1379𝑖
# you can access the current qubit count
dump.qubit_count
2
# you can access individal states by their index
dump[1]
(0.6935199226610738, 0.1379496896414715)
dump[3]
(0.5879378012096794, 0.3928474791935511)