Freigeben über


Debuggen und Testen des Quantencodes

Tests und Debugging sind ebenso wichtig bei der Quantenprogrammierung wie bei der klassischen Programmierung. In diesem Artikel wird erläutert, wie Sie Ihre Quantenprogramme mit dem Azure Quantum Development Kit (QDK) in Visual Studio Code (VS Code) und Jupyter-Notizbuch debuggen und testen.

Debuggen des Quantencodes

Der QDK bietet verschiedene Tools zum Debuggen des Codes. Wenn Sie Q#- oder OpenQASM-Programme in VS Code schreiben, können Sie den VS Code-Debugger verwenden, um Haltepunkte in Ihren Programmen festzulegen und Ihren Code zu analysieren. Der QDK bietet auch eine Reihe von Dumpfunktionen, mit denen Sie Informationen an verschiedenen Stellen in Ihrem Programm abrufen können.

Anleitung zur Verwendung des VS Code-Debuggers

Mit der QDK-Erweiterung in VS Code können Sie den Debugger verwenden, um Ihren Code und jede Funktion oder jeden Vorgang zu durchlaufen, die Werte lokaler Variablen nachzuverfolgen und den Quantenzuständen der Qubits zu folgen.

Im folgenden Beispiel wird die Verwendung des Debuggers mit einem Q# Programm veranschaulicht. Vollständige Informationen zu VS-Codedebuggern finden Sie unter Debuggen auf der VS Code-Website.

  1. Erstellen und speichern Sie in VS Code eine neue .qs Datei mit dem folgenden Code:

    import Std.Arrays.*;
    import Std.Convert.*;
    
    operation Main() : Result {
        use qubit = Qubit();
        H(qubit);
        let result = M(qubit);
        Reset(qubit);
        return result;
    }
    
  2. Klicken Sie in Zeile 6 links neben der Zeilennummer, um einen Haltepunkt festzulegenH(qubit). Ein roter Kreis wird angezeigt.

  3. Wählen Sie in der primären Randleiste das Debuggersymbol aus, um den Debuggerbereich zu öffnen, und wählen Sie dann "Ausführen" und "Debuggen" aus. Die Debugger-Steuerelementleiste wird angezeigt.

  4. Drücken Sie F5, um den Debugger zu starten und weiter bis zum Haltepunkt fortzusetzen. Erweitern Sie im Menü "Variablen " des Debuggerbereichs das Dropdownmenü "Quantum State ", um zu sehen, dass das Qubit im Status "$\ket{0}$" initialisiert wurde.

  5. Drücken Sie F11 , um in den H Vorgang zu gelangen. Der Quellcode für den H Vorgang wird angezeigt. Beachten Sie, dass sich der Quantenzustand in eine Überlagerung ändert, während Sie den H Vorgang durchlaufen.

  6. Drücken Sie F10 , um den M Vorgang zu durchlaufen. Beachten Sie, dass der Quantenzustand nach der Messung in $\ket{0}$ oder $\ket{1}$ aufgelöst wird. Die result Variable wird auch unter "Lokal" angezeigt.

  7. Drücken Sie F10 erneut, um den Reset Vorgang zu durchlaufen. Beachten Sie, dass der Quantum-Zustand auf $\ket{0}$zurückgesetzt wird.

Wenn Sie mit dem Erkunden des Debuggers fertig sind, drücken Sie STRG+F5 , um den Debugger zu beenden.

Hinweis

Der VS Code-Debugger funktioniert nur mit Q# Dateien (.qs) und OpenQASM (.qasm). Sie können den VS Code-Debugger nicht für Q# Zellen im Jupyter Notebook verwenden.

So debuggen Sie mit QDK-Dumpfunktionen

Der QDK stellt mehrere Q# und Python-Funktionen bereit, die Informationen zum aktuellen Status Ihres Programms abbilden, wenn Sie diese Funktionen aufrufen. Verwenden Sie Informationen aus diesen Dumpfunktionen, um zu überprüfen, ob sich Ihr Programm wie erwartet verhält.

Die Q#DumpMachine Funktion

DumpMachine ist eine Q# Funktion, mit der Sie Informationen zum aktuellen Status des Qubit-Systems während der Ausführung des Programms auf der Konsole speichern können. DumpMachine beendet oder unterbricht Ihr Programm während der Laufzeit nicht.

Das folgende Beispiel ruft DumpMachine an zwei Stellen in einem Q#-Programm auf und untersucht die Ausgabe.

  1. Erstellen und speichern Sie in VS Code eine neue .qs Datei mit dem folgenden Code:

    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. Drücken Sie STRG+UMSCHALT+Y , um die Debugkonsole zu öffnen.

  3. Drücken Sie STRG+F5 , um Ihr Programm auszuführen. Die folgende Ausgabe von DumpMachine wird in der Debug-Konsole angezeigt:

    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
    

Die Ausgabe von DumpMachine zeigt, wie sich der Zustand der Qubit-Systeme nach jeder Gruppe von Toren ändert.

Hinweis

Die Ausgabe von DumpMachine verwendet die Big-Endian-Reihenfolge.

Die Python-Funktion dump_machine

Die dump_machine Funktion ist eine Funktion aus dem qsharp Python-Paket. Diese Funktion gibt die aktuelle zugeordnete Qubitanzahl und ein Wörterbuch zurück, das die geringen Zustandsamplituden des Qubit-Systems enthält.

Im folgenden Beispiel wird dasselbe Programm wie im vorherigen DumpMachine Beispiel ausgeführt, aber in einem Jupyter-Notizbuch anstelle einer .qs Datei.

  1. Drücken Sie in VS Code STRG+UMSCHALT+P, um die Befehlspalette zu öffnen.

  2. Geben Sie "Erstellen" ein: Neues Jupyter-Notizbuch , und drücken Sie die EINGABETASTE. Eine neue Registerkarte "Jupyter-Notizbuch" wird geöffnet.

  3. Kopieren Sie in der ersten Zelle den folgenden Code, und führen Sie den folgenden Code aus:

    from qdk import qsharp 
    
  4. Erstellen Sie eine neue Codezelle, kopieren Sie dann den folgenden Code, und führen Sie den folgenden Q# Code aus:

    %%qsharp
    
    use qubits = Qubit[2];
    X(qubits[0]);
    H(qubits[1]);
    
  5. Erstellen Sie eine neue Codezelle. Kopieren Sie den folgenden Python-Code, und führen Sie ihn aus, um den Qubit-Zustand an diesem Punkt im Programm anzuzeigen:

    dump = qsharp.dump_machine()
    dump
    

    Die dump_machine Funktion zeigt die folgende Ausgabe an:

    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. Erstellen Sie eine neue Codezelle, kopieren Sie dann den folgenden Code, und führen Sie den folgenden Q# Code aus:

    %%qsharp
    
    R1Frac(1, 2, qubits[0]);
    R1Frac(1, 3, qubits[1]);
    
  7. Erstellen Sie eine neue Codezelle. Kopieren Sie den folgenden Python-Code, und führen Sie ihn aus, um den Qubit-Zustand an diesem Punkt im Programm anzuzeigen:

    dump = qsharp.dump_machine()
    dump
    

    Die dump_machine Funktion zeigt die folgende Ausgabe an:

    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. Um eine gekürzte Version der dump_machine Ausgabe zu drucken, erstellen Sie eine neue Zelle, und führen Sie den folgenden Python-Code aus:

    print(dump)
    
  9. Um die Gesamtanzahl der Qubits im System zu erhalten, erstellen Sie eine neue Codezelle, und führen Sie den folgenden Python-Code aus:

    dump.qubit_count
    
  10. Sie können auf die Amplituden einzelner Qubits-Zustände zugreifen, die nonzero amplitude haben. Erstellen Sie beispielsweise eine neue Codezelle, und führen Sie den folgenden Python-Code aus, um die einzelnen Amplituden für den Status "$\ket{10}$" und "$\ket{11}$" abzurufen:

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

Die dump_operation-Funktion

Die dump_operation Funktion ist eine Funktion aus dem qsharp.utils Python-Paket. Diese Funktion verwendet zwei Eingaben: eine Q# Vorgangs- oder Vorgangsdefinition als Zeichenfolge und die Anzahl der qubits, die im Vorgang verwendet werden. Bei der Ausgabe von dump_operation handelt es sich um eine geschachtelte Liste, die eine quadratische Matrix von komplexen Zahlen darstellt, die der angegebenen Quantenoperation entspricht. Die Matrixwerte befinden sich in der Rechenbasis, und jede Unterliste stellt eine Zeile der Matrix dar.

Informationen für ein 1-Qubit- und ein 2-Qubit-System werden im folgenden Beispiel mit dump_operation angezeigt.

  1. Drücken Sie in VS Code STRG+UMSCHALT+P, um die Befehlspalette zu öffnen.

  2. Geben Sie "Erstellen" ein: Neues Jupyter-Notizbuch , und drücken Sie die EINGABETASTE. Eine neue Registerkarte "Jupyter-Notizbuch" wird geöffnet.

  3. Kopieren Sie in der ersten Zelle den folgenden Code, und führen Sie den folgenden Code aus:

    from qdk import qsharp
    from qsharp.utils import dump_operation
    
  4. Um die Matrixelemente eines Ein-Qubit-Gates anzuzeigen, rufen Sie dump_operation auf und übergeben Sie 1 als Anzahl der Qubits. Kopieren Sie beispielsweise den folgenden Python-Code in einer neuen Codezelle, und führen Sie diesen aus, um die Matrixelemente für ein Identitätsgater und ein Hadamard-Gate abzurufen:

    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. Sie können auch die qsharp.eval-Funktion aufrufen und anschließend auf die Q#-Operation in dump_operation verweisen, um dasselbe Ergebnis zu erhalten. Erstellen Sie beispielsweise eine neue Codezelle, kopieren Sie den folgenden Python-Code, und führen Sie ihn aus, um die Matrixelemente für ein Single-Qubit Hadamard-Gate zu drucken:

    qsharp.eval("operation SingleH(qs : Qubit[]) : Unit { H(qs[0]) }")
    
    res = dump_operation("SingleH", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  6. Um die Matrixelemente eines Zwei-Qubit-Gates anzuzeigen, rufen Sie dump_operation auf und übergeben 2 für die Anzahl der Qubits. Kopieren Sie beispielsweise den folgenden Python-Code in einer neuen Codezelle, und führen Sie ihn aus, um die Matrixelemente für einen kontrollierten Ry-Vorgang abzurufen, bei dem der zweite Qubit der target Qubit ist:

    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)
    

Weitere Beispiele zum Testen und Debuggen des Codes finden dump_operationSie unter "Testen von Vorgängen aus den QDK-Beispielen".

Testen des Quantencodes

Der QDK stellt verschiedene Q# Funktionen und Vorgänge bereit, mit denen Sie den Code während der Ausführung testen können. Sie können auch Komponententests für Q# Programme schreiben.

Der fail-Ausdruck

Der fail Ausdruck beendet sofort das Programm. Verwenden Sie die fail Ausdrücke innerhalb von bedingten Anweisungen, um Tests in Ihren Code zu integrieren.

Im folgenden Beispiel wird eine fail Anweisung verwendet, um zu testen, dass ein Qubit-Array genau 3 Qubits enthält. Das Programm endet mit einer Fehlermeldung, wenn der Test nicht bestanden wird.

  1. Erstellen und speichern Sie in VS Code eine neue .qs Datei mit dem folgenden Code:

    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. Drücken Sie STRG+F5 , um das Programm auszuführen. Ihr Programm schlägt fehl, und die folgende Ausgabe wird in der Debugkonsole angezeigt:

    Error: program failed: The system should have 3 qubits, not 6.
    
  3. Bearbeiten Sie den Code von Qubit[6] zu Qubit[3], speichern Sie die Datei, und drücken Sie dann STRG + F5, um das Programm erneut auszuführen. Das Programm wird ohne Fehler ausgeführt, da der Test bestanden wurde.

Die Fact-Funktion

Sie können die Q#Fact Funktion auch aus dem Std.Diagnostics Namespace verwenden, um Den Code zu testen. Die Fact Funktion verwendet einen booleschen Ausdruck und eine Fehlermeldungszeichenfolge. Wenn der boolesche Ausdruck "true" ist, wird der Test bestanden, und das Programm wird weiterhin ausgeführt. Wenn der boolesche Ausdruck falsch ist, Fact beendet Das Programm und zeigt die Fehlermeldung an.

Um denselben Arraylängentest aus Ihrem vorherigen Code mit der Funktion Fact auszuführen, folgen Sie diesen Schritten:

  1. Erstellen und speichern Sie in VS Code eine neue .qs Datei mit dem folgenden Code:

    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. Drücken Sie STRG+F5 , um das Programm auszuführen. Die Testbedingung in Fact schlägt fehl, und die Fehlermeldung erscheint in der Debugkonsole.

  3. Bearbeiten Sie den Code von Qubit[6] zu Qubit[3], speichern Sie die Datei, und drücken Sie dann STRG + F5, um das Programm erneut auszuführen. Die Testbedingung wird in Fact bestanden und Ihr Programm läuft ohne Fehler.

Schreiben von Q# Unittests mit der @Test() Annotation

In Q# Programmen können Sie die @Test() Anmerkung auf eine aufrufbare (Funktion oder Operation) anwenden, um die aufrufbare Funktion in einen Komponententest umzuwandeln. Diese Komponententests werden im Menü " Testen " in VS-Code angezeigt, damit Sie dieses VS-Code-Feature nutzen können. Sie können ein aufrufbares Objekt nur dann in einen Komponententest umwandeln, wenn es keine Eingabeparameter erwartet.

Im folgenden Beispiel wird der Testcode für die Arraylänge in einem Vorgang eingepackt, und dieser wird in einen Unit-Test umgewandelt.

  1. Erstellen und speichern Sie in VS Code eine neue .qs Datei mit dem folgenden Code:

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

    Die @Test() Anmerkung in der Zeile vor der Vorgangsdefinition TestCase wandelt den Vorgang in einen VS Code-Komponententest um. In der Vorgangsdefinitionszeile wird ein grüner Pfeil angezeigt.

  2. Wählen Sie den grünen Pfeil, um TestCase auszuführen und die Testergebnisse zu melden.

  3. Um mit Ihren Einheitentests im VS Code Test Explorer zu interagieren, wählen Sie das "Testing" Flask-Symbol in der primären Seitenleiste aus.

  4. Bearbeiten Sie den Code von Qubit[3] zu Qubit[6] und führen Sie den Unittest erneut aus, um zu sehen, wie sich die Testinformationen ändern.

Sie können Q# Unit-Tests in VS Code schreiben und ausführen, ohne einen Einstiegspunkt in Ihrem Programm zu benötigen.

Hinweis

Callables aus dem Std.Diagnostics Namespace sind nicht mit der QIR-Generierung kompatibel, daher sollten Sie nur Unit-Tests in Q# Code einschließen, den Sie auf Simulatoren ausführen. Wenn Sie QIR aus Ihrem Q# Code generieren möchten, schließen Sie keine Komponententests in Ihren Code ein.

Die CheckZero- und CheckAllZero-Operationen

Die Operationen CheckZero und CheckAllZeroQ# überprüfen, ob der aktuelle Zustand eines Qubits oder eines Qubit-Arrays $\ket{0}$ ist. Der CheckZero Vorgang akzeptiert einen einzelnen Qubit und gibt nur dann zurück true , wenn sich der Qubit im Zustand $\ket{0}$ befindet. Die CheckAllZero Vorgänge nehmen ein Qubitarray und geben true nur dann zurück, wenn sich alle Qubits im Array im Zustand $\ket{0}$ befinden. Um CheckZero und CheckAllZero zu verwenden, importieren Sie sie aus dem Std.Diagnostics-Namespace.

Im folgenden Beispiel werden beide Vorgänge verwendet. Die CheckZero-Tests verifizieren, dass der X-Vorgang den ersten Qubit von dem Zustand $\ket{0}$ in den Zustand $\ket{1}$ wechselt, und die CheckAllZero-Operation testet, ob beide Qubits auf den Zustand $\ket{0}$ zurückgesetzt werden.

Erstellen und speichern Sie in VS Code eine neue .qs Datei mit dem folgenden Code, führen Sie dann das Programm aus, und untersuchen Sie die Ausgabe in der Debugkonsole.

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