次の方法で共有


量子コードをデバッグしてテストする方法

テストとデバッグは、従来のプログラミングと同じように、量子プログラミングでも重要です。 この記事では、Visual Studio Code (VS Code) と Jupyter Notebook の Azure Quantum Development Kit (QDK) を使用して量子プログラムをデバッグおよびテストする方法について説明します。

量子コードをデバッグする

QDK には、コードをデバッグするためのツールがいくつか用意されています。 VS Code で Q# または OpenQASM プログラムを記述する場合は、VS Code デバッガーを使用してプログラムにブレークポイントを設定し、コードを分析できます。 QDK には、プログラム内のさまざまなポイントで情報を取得するために使用できるダンプ関数のセットも用意されています。

VS Code デバッガーの使用方法

VS Code の QDK 拡張機能を使用すると、デバッガーを使用してコードをステップ実行し、各関数または操作をステップ実行し、ローカル変数の値を追跡し、量子ビットの量子状態に従うことができます。

次の例では、 Q# プログラムでデバッガーを使用する方法を示します。 VS Code デバッガーの詳細については、「VS Code Web サイトでの デバッグ 」を参照してください。

  1. VS Code で、次のコードを使用して新しい .qs ファイルを作成して保存します。

    import Std.Arrays.*;
    import Std.Convert.*;
    
    operation Main() : Result {
        use qubit = Qubit();
        H(qubit);
        let result = M(qubit);
        Reset(qubit);
        return result;
    }
    
  2. 6 行目 H(qubit)、行番号の左側をクリックしてブレークポイントを設定します。 赤い円が表示されます。

  3. プライマリ サイド バーで、デバッガー アイコンを選択してデバッガー ウィンドウを開き、[ 実行とデバッグ] を選択します。 デバッガー コントロール バーが表示されます。

  4. F5 キーを押してデバッガーを起動し、ブレークポイントに進みます。 デバッガー ウィンドウの [変数 ] メニューで、[ Quantum State ] ドロップダウンを展開して、量子ビットが $\ket{0}$ 状態で初期化されていることを確認します。

  5. F11 キーを押して、H操作にステップ インします。 H操作のソース コードが表示されます。 をステップ実行する際に、Hが重ね合わせに変わることに注目してください。

  6. F10 キーを押して、M操作をステップ オーバーします。 量子状態は、測定後に $\ket{0}$ または $\ket{1}$ のいずれかに解決されることに注意してください。 result変数は、[ローカル] にも表示されます。

  7. もう一度 F10 キーを押して、 Reset 操作をステップ オーバーします。 Quantum 状態が $\ket{0}$ にリセットされていることに注意してください。

デバッガーの探索が完了したら、*Ctrl + F5 キー を押してデバッガーを終了します。

Note

VS Code デバッガーは、 Q# (.qs) ファイルと OpenQASM (.qasm) ファイルでのみ動作します。 Jupyter Notebook の Q# セルで VS Code デバッガーを使用することはできません。

QDK ダンプ関数を使用してデバッグする方法

QDK には、これらの関数を呼び出すときにプログラムの現在の状態に関する情報をダンプするいくつかの Q# および Python 関数が用意されています。 これらのダンプ関数の情報を使用して、プログラムが期待どおりに動作するかどうかを確認します。

Q# DumpMachine関数

DumpMachine は、プログラムの実行時に量子ビット システムの現在の状態に関する情報をコンソールにダンプできる Q# 関数です。 DumpMachine は、実行時にプログラムを停止または中断しません。

次の例では、DumpMachine プログラム内の 2 つのポイントでQ#を呼び出し、出力を探索します。

  1. VS Code で、次のコードを使用して新しい .qs ファイルを作成して保存します。

    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. Ctrl + Shift + Y キーを押してデバッグ コンソールを開きます。

  3. Ctrl + F5 キーを押してプログラムを実行します。 DumpMachineには、からの次の出力が表示されます。

    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
    

DumpMachineからの出力は、ゲートの各セットの後に量子ビット システムの状態がどのように変化するかを示しています。

Note

DumpMachineからの出力では、ビッグ エンディアンの順序が使用されます。

Python dump_machine 関数

dump_machine関数は、qsharp Python パッケージの関数です。 この関数は、現在割り当てられている量子ビット数と、量子ビット システムのスパース状態振幅を含むディクショナリを返します。

次の例では、前の DumpMachine の例と同じプログラムを実行しますが、 .qs ファイルではなく Jupyter Notebook で実行します。

  1. VS Code で、 Ctrl + Shift + P キー を押して コマンド パレットを開きます。

  2. 「作成: 新しい Jupyter Notebook」と入力し、Enter キーを押します。 新しい Jupyter Notebook タブが開きます。

  3. 最初のセルで、次のコードをコピーして実行します。

    from qdk import qsharp 
    
  4. 新しいコード セルを作成し、次の Q# コードをコピーして実行します。

    %%qsharp
    
    use qubits = Qubit[2];
    X(qubits[0]);
    H(qubits[1]);
    
  5. 新しいコード セルを作成します。 次の Python コードをコピーして実行し、プログラムのこの時点の量子ビットの状態を表示します。

    dump = qsharp.dump_machine()
    dump
    

    dump_machine関数には、次の出力が表示されます。

    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. 新しいコード セルを作成し、次の Q# コードをコピーして実行します。

    %%qsharp
    
    R1Frac(1, 2, qubits[0]);
    R1Frac(1, 3, qubits[1]);
    
  7. 新しいコード セルを作成します。 次の Python コードをコピーして実行し、プログラムのこの時点の量子ビットの状態を表示します。

    dump = qsharp.dump_machine()
    dump
    

    dump_machine関数には、次の出力が表示されます。

    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. dump_machine出力の省略版を出力するには、新しいセルを作成し、次の Python コードを実行します。

    print(dump)
    
  9. システム内の量子ビットの合計数を取得するには、新しいコード セルを作成し、次の Python コードを実行します。

    dump.qubit_count
    
  10. 0 以外の振幅を持つ個々の量子ビット状態の振幅にアクセスできます。 たとえば、新しいコード セルを作成し、次の Python コードを実行して、$\ket{10}$ 状態と $\ket{11}$ 状態の個々の振幅を取得します。

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

dump_operation 関数

dump_operation関数は、qsharp.utils Python パッケージの関数です。 この関数は、2 つの入力を受け取ります。 Q# 操作または操作定義を文字列として使用し、操作で使用される量子ビットの数を指定します。 dump_operationからの出力は、指定された量子演算に対応する複素数の平方行列を表す入れ子になったリストです。 行列の値は計算基準であり、各サブリストは行列の行を表します。

次の例では、 dump_operation を使用して、1 量子ビットおよび 2 量子ビット システムの情報を表示します。

  1. VS Code で、 Ctrl + Shift + P キー を押して コマンド パレットを開きます。

  2. 「作成: 新しい Jupyter Notebook」と入力し、Enter キーを押します。 新しい Jupyter Notebook タブが開きます。

  3. 最初のセルで、次のコードをコピーして実行します。

    from qdk import qsharp
    from qsharp.utils import dump_operation
    
  4. 単一量子ビット ゲートの行列要素を表示するには、 dump_operation 呼び出し、量子ビット数に対して 1 を渡します。 たとえば、新しいコード セルで次の Python コードをコピーして実行し、ID ゲートと Hadmard ゲートのマトリックス要素を取得します。

    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. qsharp.eval関数を呼び出し、Q#でdump_operation操作を参照して同じ結果を取得することもできます。 たとえば、新しいコード セルを作成し、次の Python コードをコピーして実行して、単一量子ビット Hadmard ゲートのマトリックス要素を出力します。

    qsharp.eval("operation SingleH(qs : Qubit[]) : Unit { H(qs[0]) }")
    
    res = dump_operation("SingleH", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  6. 2 量子ビット ゲートの行列要素を表示するには、 dump_operation 呼び出し、量子ビット数に対して 2 を渡します。 たとえば、新しいコード セルで次の Python コードをコピーして実行し、2 番目の量子ビットが target 量子ビットである、制御された Ry 操作のマトリックス要素を取得します。

    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)
    

dump_operationを使用してコードをテストおよびデバッグする方法の他の例については、QDK サンプルからのテスト操作を参照してください。

量子コードをテストする

QDK には、コードの実行時にテストするために使用できる Q# 関数と操作がいくつか用意されています。 Q# プログラムの単体テストを記述することもできます。

fail

fail式は、プログラムをすぐに終了します。 コードにテストを組み込むには、条件ステートメント内の fail 式を使用します。

次の例では、 fail ステートメントを使用して、量子ビット配列に正確に 3 量子ビットが含まれていることをテストします。 テストに合格しなかった場合、プログラムはエラー メッセージで終了します。

  1. VS Code で、次のコードを使用して新しい .qs ファイルを作成して保存します。

    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. Ctrl + F5 キーを押してプログラムを実行します。 プログラムが失敗し、 デバッグ コンソールに次の出力が表示されます。

    Error: program failed: The system should have 3 qubits, not 6.
    
  3. Qubit[6]からQubit[3]にコードを編集し、ファイルを保存し、Ctrl キーを押しながら F5 キーを押してプログラムをもう一度実行します。 テストに合格したため、プログラムはエラーなしで実行されます。

Fact 関数

Q#名前空間のFactStd.Diagnostics関数を使用して、コードをテストすることもできます。 Fact関数は、ブール式とエラー メッセージ文字列を受け取ります。 ブール式が true の場合、テストは成功し、プログラムは引き続き実行されます。 ブール式が false の場合、 Fact はプログラムを終了し、エラー メッセージを表示します。

同じ配列長のテストを以前のコードで行うには、Fact 関数を使用して次の手順に従います。

  1. VS Code で、次のコードを使用して新しい .qs ファイルを作成して保存します。

    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. Ctrl + F5 キーを押してプログラムを実行します。 Factのテスト条件に合格せず、デバッグ コンソールにエラー メッセージが表示されます。

  3. Qubit[6]からQubit[3]にコードを編集し、ファイルを保存し、Ctrl キーを押しながら F5 キーを押してプログラムをもう一度実行します。 Factのテスト条件に合格し、プログラムがエラーなしで実行されます。

Q#注釈を使用して@Test()単体テストを書く

Q# プログラムでは、@Test()注釈を呼び出し可能 (関数または操作) に適用して、呼び出し可能な注釈を単体テストに変換できます。 これらの単体テストは VS Code の [テスト ] メニューに表示されるので、この VS Code 機能を利用できます。 呼び出し可能なものを単体テストに変換できるのは、その呼び出し可能なものが入力パラメーターを取らない場合のみです。

次の例では、配列の長さのテスト コードを操作でラップし、その操作を単体テストに変換します。

  1. VS Code で、次のコードを使用して新しい .qs ファイルを作成して保存します。

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

    @Test()操作定義の前の行にあるTestCase注釈は、操作を VS Code の単体テストに変換します。 操作定義行に緑色の矢印が表示されます。

  2. 緑色の矢印を選択して TestCase 実行し、テスト結果を報告します。

  3. VS Code テスト エクスプローラーでユニット テストを操作するには、プライマリ サイド バーの [テスト ] Flask アイコンを選択します。

  4. Qubit[3]からコードを編集してQubit[6]し、単体テストをもう一度実行して、テスト情報がどのように変化するかを確認します。

プログラムでエントリ ポイント操作を行わずに、VS Code で Q# 単体テストを記述して実行できます。

Note

Std.Diagnostics名前空間からの呼び出し可能ファイルは QIR の生成と互換性がないため、シミュレーターで実行するQ#コードにのみ単体テストを含めます。 Q# コードから QIR を生成する場合は、コードに単体テストを含めないでください。

CheckZero操作とCheckAllZero操作

CheckZero操作とCheckAllZeroQ#操作では、量子ビット配列または量子ビット配列の現在の状態が $\ket{0}$ であるかどうかを確認します。 CheckZero操作は、1 つの量子ビットを受け取り、量子ビットが $\kettrue$ 状態の場合にのみ{0}を返します。 CheckAllZero演算は量子ビット配列を受け取り、配列内のすべての量子ビットが $\kettrue$ 状態の場合にのみ{0}を返します。 CheckZeroCheckAllZeroを使用するには、Std.Diagnostics名前空間からインポートします。

次の例では、両方の操作を使用します。 CheckZeroX操作が最初の量子ビットを $\ket{0}$ 状態から $\ket{1}$ 状態に反転し、CheckAllZero操作が両方の量子ビットを $\ket{0}$ 状態にリセットすることをテストします。

VS Code で、次のコードを使用して新しい .qs ファイルを作成して保存し、プログラムを実行し、 デバッグ コンソールで出力を確認します。

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