Udostępnij przez


Jak debugować i testować kod kwantowy

Testowanie i debugowanie jest równie ważne w programowaniu kwantowym, jak w programowaniu klasycznym. W tym artykule omówiono sposób debugowania i testowania programów kwantowych za pomocą zestawu Azure Quantum Development Kit (QDK) w programie Visual Studio Code (VS Code) i notesie Jupyter Notebook.

Debugowanie kodu kwantowego

Zestaw QDK udostępnia kilka narzędzi do debugowania kodu. Jeśli piszesz Q# lub program OpenQASM w programie VS Code, możesz użyć debugera programu VS Code do ustawiania punktów przerwania w programach i analizowania kodu. Zestaw QDK udostępnia również zestaw funkcji zrzutu, których można użyć do uzyskiwania informacji w różnych punktach programu.

Jak używać debugera programu VS Code

Za pomocą rozszerzenia QDK w programie VS Code możesz użyć debugera, aby przejść przez kod i do każdej funkcji lub operacji, śledzić wartości zmiennych lokalnych i postępować zgodnie ze stanami kwantowymi kubitów.

W poniższym przykładzie pokazano, jak używać debuggera w Q# programie. Aby uzyskać pełne informacje na temat debugerów programu VS Code, zobacz Debugowanie w witrynie internetowej programu VS Code.

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

    import Std.Arrays.*;
    import Std.Convert.*;
    
    operation Main() : Result {
        use qubit = Qubit();
        H(qubit);
        let result = M(qubit);
        Reset(qubit);
        return result;
    }
    
  2. W wierszu 6, kliknij po lewej stronie numeru wiersza, H(qubit) aby ustawić punkt przerwania. Zostanie wyświetlone czerwone kółko.

  3. Na pasku po stronie głównej wybierz ikonę debugera, aby otworzyć okienko debugera, a następnie wybierz pozycję Uruchom i Debuguj. Zostanie wyświetlony pasek sterowania debugera.

  4. Naciśnij F5 , aby uruchomić debuger i przejść do punktu przerwania. W menu debugera Zmienne rozwiń listę rozwijaną Stan kwantowy, aby zobaczyć, że kubit został zainicjowany w stanie $\ket{0}$.

  5. Naciśnij F11 , aby przejść do H operacji. Zostanie wyświetlony kod H źródłowy operacji. Zwróć uwagę, że stan kwantowy przechodzi w stan superpozycji podczas przechodzenia przez operację H.

  6. Naciśnij F10 , aby przejść przez operację M . Zwróć uwagę, że stan kwantowy rozwiązuje się do $\ket{0}$ lub $\ket{1}$ po pomiarze. Zmienna pojawia się również result w sekcji Lokalne.

  7. Naciśnij F10 ponownie, aby przejść przez operację Reset . Zwróć uwagę, że stan kwantowy jest resetowany do $\ket{0}$.

Po zakończeniu eksplorowania debugera naciśnij *Ctrl + F5 , aby zamknąć debuger.

Uwaga

Debuger programu VS Code działa tylko z plikami Q# (.qs) i OpenQASM (.qasm). Nie można użyć debugera programu VS Code w Q# komórkach w zeszycie Jupyter.

Jak debugować za pomocą funkcji dump QDK

Zestaw QDK udostępnia kilka Q# funkcji języka Python, które zrzutują informacje o bieżącym stanie programu podczas wywoływania tych funkcji. Użyj informacji z tych funkcji zrzutu, aby sprawdzić, czy program działa zgodnie z oczekiwaniami.

Funkcja Q#DumpMachine

DumpMachine to Q# funkcja, która umożliwia zrzut informacji o bieżącym stanie systemu kubitów do konsoli podczas uruchamiania programu. DumpMachine nie zatrzymuje ani nie przerywa działania w czasie wykonywania.

Poniższy przykład wywołuje DumpMachine w dwóch punktach w programie Q# i analizuje dane wyjściowe.

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

    import Std.Diagnostics.*;
    
    operation Main() : 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);
    }
    
  2. Naciśnij Ctrl + Shift + Y , aby otworzyć konsolę debugowania.

  3. Naciśnij Ctrl + F5 , aby uruchomić program. W DumpMachine są wyświetlane następujące dane wyjściowe:

    Basis | Amplitude      | Probability | Phase
    -----------------------------------------------
     |00⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
     |01⟩ | −0.7071+0.0000𝑖 |    50.0000% |  -3.1416
    
    Basis | Amplitude      | Probability | Phase
    -----------------------------------------------
     |00⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
     |01⟩ | −0.6533−0.2706𝑖 |    50.0000% |  -2.7489
    

Dane wyjściowe z DumpMachine pokazują, jak stan systemów kubitów zmienia się po każdym zestawie bram.

Uwaga

Dane wyjściowe z DumpMachine używają kolejności big-endian.

Funkcja języka Python dump_machine

Funkcja dump_machine jest funkcją z qsharp pakietu języka Python. Ta funkcja zwraca bieżącą przydzieloną liczbę kubitów i słownik zawierający rozrzedane amplitudy stanu systemu kubitów.

Poniższy przykład uruchamia ten sam program, co w poprzednim DumpMachine przykładzie, ale w notebooku Jupyter, a nie w .qs pliku.

  1. W programie VS Code naciśnij Ctrl + Shift + P , aby otworzyć paletę poleceń.

  2. Wprowadź Create: New Jupyter Notebook i naciśnij Enter. Zostanie otwarta nowa karta notesu Jupyter Notebook.

  3. W pierwszej komórce skopiuj i uruchom następujący kod:

    from qdk import qsharp 
    
  4. Utwórz nową komórkę kodu, a następnie skopiuj i uruchom następujący Q# kod:

    %%qsharp
    
    use qubits = Qubit[2];
    X(qubits[0]);
    H(qubits[1]);
    
  5. Utwórz nową komórkę kodu. Skopiuj i uruchom następujący kod języka Python, aby wyświetlić stan kubitu w tym momencie w programie:

    dump = qsharp.dump_machine()
    dump
    

    Funkcja dump_machine wyświetla następujące dane wyjściowe:

    Basis State
    (|𝜓₁…𝜓ₙ⟩)  Amplitude       Measurement Probability  Phase
    |10⟩       0.7071+0.0000𝑖   50.0000%                 ↑  0.0000
    |11⟩       0.7071+0.0000𝑖   50.0000%                 ↑  0.0000
    
  6. Utwórz nową komórkę kodu, a następnie skopiuj i uruchom następujący Q# kod:

    %%qsharp
    
    R1Frac(1, 2, qubits[0]);
    R1Frac(1, 3, qubits[1]);
    
  7. Utwórz nową komórkę kodu. Skopiuj i uruchom następujący kod języka Python, aby wyświetlić stan kubitu w tym momencie w programie:

    dump = qsharp.dump_machine()
    dump
    

    Funkcja dump_machine wyświetla następujące dane wyjściowe:

    Basis State
    (|𝜓₁…𝜓ₙ⟩)  Amplitude      Measurement Probability  Phase
    |10⟩       0.5000+0.5000𝑖  50.0000%                 ↗  0.7854
    |11⟩       0.2706+0.6533𝑖  50.0000%                 ↗  1.1781
    
  8. Aby wydrukować skróconą wersję danych wyjściowych dump_machine , utwórz nową komórkę i uruchom następujący kod w języku Python:

    print(dump)
    
  9. Aby uzyskać całkowitą liczbę kubitów w systemie, utwórz nową komórkę kodu i uruchom następujący kod w języku Python:

    dump.qubit_count
    
  10. Można uzyskać dostęp do amplitud poszczególnych stanów kubitów, które mają amplitudę inną niżzerowa. Na przykład utwórz nową komórkę kodu i uruchom następujący kod w języku Python, aby pobrać poszczególne amplitudy dla stanów $\ket{10}$ i $\ket{11}$:

    print(dump[2])
    print(dump[3])
    

Funkcja dump_operation

Funkcja dump_operation jest funkcją z qsharp.utils pakietu języka Python. Ta funkcja przyjmuje dwa dane wejściowe: operację Q# lub definicję operacji jako ciąg i liczbę kubitów używanych w operacji. Dane wyjściowe z dump_operation programu to zagnieżdżona lista reprezentująca kwadratową macierz liczb zespolonych odpowiadających danej operacji kwantowej. Wartości macierzy znajdują się w podstawie obliczeniowej, a każda lista podrzędna reprezentuje wiersz macierzy.

W poniższym przykładzie użyto dump_operation do wyświetlania informacji dotyczących systemu 1-kubitowego i 2-kubitowego.

  1. W programie VS Code naciśnij Ctrl + Shift + P , aby otworzyć paletę poleceń.

  2. Wprowadź Create: New Jupyter Notebook i naciśnij Enter. Zostanie otwarta nowa karta notesu Jupyter Notebook.

  3. W pierwszej komórce skopiuj i uruchom następujący kod:

    from qdk import qsharp
    from qsharp.utils import dump_operation
    
  4. Aby wyświetlić elementy macierzy bramy jednokubitowej, wywołaj dump_operation i wprowadź 1 jako liczbę kubitów. Na przykład skopiuj i uruchom następujący kod w języku Python w nowej komórce kodu, aby uzyskać elementy macierzy dla bramy tożsamości i bramy hadamarda:

    res = dump_operation("qs => ()", 1)
    print("Single-qubit identity gate:\n", res)
    print()
    
    res = dump_operation("qs => H(qs[0])", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  5. Możesz również wywołać funkcję qsharp.eval, a następnie odwołać się do operacji Q# w dump_operation aby uzyskać ten sam wynik. Na przykład utwórz nową komórkę kodu, a następnie skopiuj i uruchom następujący kod w języku Python, aby wydrukować elementy macierzy dla bramy Hadamard z jednym kubitem:

    qsharp.eval("operation SingleH(qs : Qubit[]) : Unit { H(qs[0]) }")
    
    res = dump_operation("SingleH", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  6. Aby wyświetlić elementy macierzy bramy z dwoma kubitami, wywołaj dump_operation i przekaż 2 dla liczby kubitów. Na przykład skopiuj i uruchom następujący kod w języku Python w nowej komórce kodu, aby pobrać elementy macierzy dla operacji Kontrolowane Ry, gdzie drugi kubit jest kubitem target :

    qsharp.eval ("operation ControlRy(qs : Qubit[]) : Unit { Controlled Ry([qs[0]], (0.5, qs[1])); }")
    
    res = dump_operation("ControlRy", 2)
    print("Controlled Ry rotation gate:\n", res)
    

Aby uzyskać więcej przykładów testowania i debugowania kodu za pomocą dump_operation, zobacz Testowanie operacji w przykładach QDK.

Testowanie kodu kwantowego

Zestaw QDK udostępnia kilka Q# funkcji i operacji, których można użyć do testowania kodu podczas jego uruchamiania. Można również pisać testy jednostkowe dla Q# programów.

Wyrażenie fail

Wyrażenie fail natychmiast kończy program. Aby dołączyć testy do kodu, użyj fail wyrażeń wewnątrz instrukcji warunkowych.

W poniższym przykładzie użyto fail instrukcji, aby sprawdzić, czy tablica kubitów zawiera dokładnie 3 kubity. Program kończy się komunikatem o błędzie, gdy test nie przejdzie pomyślnie.

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

    operation Main() : Unit {
        use qs = Qubit[6];
        let n_qubits = Length(qs);
    
        if n_qubits != 3 {
            fail $"The system should have 3 qubits, not {n_qubits}.";
        }  
    }
    
  2. Naciśnij Ctrl + F5 , aby uruchomić program. Program kończy się niepowodzeniem i w konsoli debugowania są wyświetlane następujące dane wyjściowe:

    Error: program failed: The system should have 3 qubits, not 6.
    
  3. Edytuj kod z Qubit[6] do Qubit[3], zapisz plik, a następnie naciśnij Ctrl + F5 , aby ponownie uruchomić program. Program jest uruchamiany bez błędu, ponieważ test przebiegnie pomyślnie.

Funkcja Fact

Możesz również użyć Q#Fact funkcji z Std.Diagnostics przestrzeni nazw, aby przetestować kod. Funkcja Fact przyjmuje wyrażenie logiczne i ciąg komunikatu o błędzie en. Jeśli wyrażenie logiczne ma wartość true, test zakończy się pomyślnie, a program będzie nadal działać. Jeśli wyrażenie logiczne ma wartość false, Fact kończy program i wyświetla komunikat o błędzie.

Aby wykonać ten sam test długości tablicy w poprzednim kodzie, ale z funkcją Fact, wykonaj następujące kroki:

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

    import Std.Diagnostics.Fact;
    
    operation Main() : Unit {
        use qs = Qubit[6];
        let n_qubits = Length(qs);
    
        Fact(n_qubits == 3,  $"The system should have 3 qubits, not {n_qubits}.")
    }
    
  2. Naciśnij Ctrl + F5 , aby uruchomić program. Warunek testu w Fact nie przechodzi, a komunikat o błędzie pojawia się w Konsoli debugowania.

  3. Edytuj kod z Qubit[6] do Qubit[3], zapisz plik, a następnie naciśnij Ctrl + F5 , aby ponownie uruchomić program. Warunek testu w programie Fact kończy się pomyślnie, a program działa bez błędu.

Pisanie Q# testów jednostkowych przy użyciu adnotacji @Test()

W programach Q# można zastosować adnotację @Test() do funkcji lub operacji (wywoływalnego obiektu), aby przekształcić je w test jednostkowy. Te testy jednostek są wyświetlane w menu Testowanie w programie VS Code, aby móc korzystać z tej funkcji programu VS Code. Wywołanie można przekształcić w test jednostkowy tylko wtedy, gdy obiekt wywołujący nie pobiera parametrów wejściowych.

Poniższy przykład opakowuje kod testu długości tablicy w operacji i zamienia tę operację w test jednostkowy:

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

    import Std.Diagnostics.Fact;
    
    @Test()
    operation TestCase() : Unit {
        use qs = Qubit[3];
        let n_qubits = Length(qs);
    
        Fact(n_qubits == 3, $"The system should have 3 qubits, not {n_qubits}.");
    }
    

    Adnotacja @Test() w wierszu przed definicją TestCase operacji zamienia operację w test jednostkowy programu VS Code. Zielona strzałka jest wyświetlana w wierszu definicji operacji.

  2. Wybierz zieloną strzałkę do uruchomienia TestCase i zgłoś wyniki testu.

  3. Aby wchodzić w interakcje z testami jednostkowymi w Eksploratorze testów programu VS Code, wybierz ikonę kolby Testing na głównym pasku.

  4. Zmodyfikuj kod z Qubit[3] do Qubit[6] i ponownie uruchom test jednostkowy, aby zobaczyć, jak zmieniają się informacje testowe.

Testy jednostkowe można pisać i uruchamiać Q# w programie VS Code bez operacji punktu wejścia w programie.

Uwaga

Wywoływalne elementy z przestrzeni nazw Std.Diagnostics nie są kompatybilne z generowaniem QIR, dlatego należy uwzględniać tylko testy jednostkowe w kodzie Q#, który uruchamiasz na symulatorach. Jeśli chcesz wygenerować QIR z kodu Q#, nie uwzględniaj w nim testów jednostkowych.

Operacje CheckZero i CheckAllZero

Operacje CheckZero i CheckAllZeroQ# sprawdzają, czy bieżący stan kubitu lub tablicy kubitu to $\ket{0}$. Operacja CheckZero przyjmuje jeden kubit i zwraca tylko true wtedy, gdy kubit jest w stanie $\ket{0}$. Operacje CheckAllZero przyjmują tablicę kubitów i zwracają tylko true wtedy, gdy wszystkie kubity w tablicy mają stan $\ket{0}$. Aby użyć CheckZero i CheckAllZero, zaimportuj je z przestrzeni nazw Std.Diagnostics.

W poniższym przykładzie użyto obu operacji. Testy CheckZero sprawdzają, czy operacja X przerzuca pierwszy kubit ze stanu $\ket{0}$ na stan $\ket{1}$, a operacja CheckAllZero sprawdza, czy oba kubity są resetowane do stanu $\ket{0}$.

W programie VS Code utwórz i zapisz nowy .qs plik przy użyciu następującego kodu, a następnie uruchom program i sprawdź dane wyjściowe w konsoli debugowania.

import Std.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");
    }
}