Q# を使用して重ね合わせを調べる

完了

前のユニットでは、重ね合わせとディラック表記について学習しました。 この理論で今のところ十分です。 いくつかのコードを記述して、Q# での重ね合わせを確認しましょう。

このユニットでは、量子重ね合わせを作成し、Q# で DumpMachine 関数を使用して確率を詳しく調べます。 DumpMachine 関数は、呼び出された時点で、ターゲット マシンの現在の状態に関する情報をダンプします。

新しい Q# ファイルを作成する

  1. Visual Studio Code を開きます。
  2. Visual Studio Code で、[ファイル] >、[新しいテキスト ファイル] の順に選択し、ファイルを Main.qs として保存します。
  3. [表示]、[コマンド パレット] の順に選択し、「Q#:Azure Quantum QIR ターゲット プロファイルを設定する」と入力します。 Enter キーを押します。
  4. [Q#:無制限] を選択します。

重ね合わせの使用を開始する

重ね合わせの量子ビットを使用してランダム ビットを生成する簡単なプログラムを始めましょう。 プログラムのさまざまなポイントで量子ビットの状態を確認するには、DumpMachine 関数を使います。

  1. 次のコードを Main.qs ファイルに追加します。

    import Microsoft.Quantum.Diagnostics.*;
    
    operation Main() : Result {
        use q = Qubit();
        Message("Initialized qubit:");
        DumpMachine(); // First dump
        Message(" ");
        H(q);
        Message("Qubit after applying H:");
        DumpMachine(); // Second dump
        Message(" ");
        let randomBit = M(q);
        Message("Qubit after the measurement:");
        DumpMachine(); // Third dump
        Message(" ");
        Reset(q);
        Message("Qubit after resetting:");
        DumpMachine(); // Fourth dump
        Message(" ");
        return randomBit;
    }
    

    ここでは DumpMachine を 4 回呼び出します。

    • 量子ビットが割り当てられた後。
    • 量子ビットが重ね合わされた後。
    • 量子ビットの状態が測定された後。
    • 量子ビットがリセットされた後。

    演算 MResetZMReset の 2 つの演算に分割します。 これは、測定後に状態を調べるためです。

  2. 組み込みのシミュレーターでプログラムを実行するには、Main 演算の上の [実行] をクリックするか、Ctrl + F5 キーを押します。 出力がデバッグ コンソールに表示されます。

  3. DumpMachine 関数によって、量子ビット レジスタの状態を説明する情報のテーブルが作成されます。 具体的には、各基準状態の確率振幅、確率、およびラジアン単位でのフェーズが示されます。

  4. プログラムの最後に、結果として Zero または One が表示されます。 各ステップを見てみましょう。

    1. 初期化された量子ビット:use ステートメントで割り当てられるすべての量子ビットは、状態 $|0\rangle$ で始まります。 したがって、DumpMachine では、状態 $|0\rangle$ の 1 量子ビット レジスタに対応する情報が生成されます。

      Initialized qubit:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
    2. H を適用した後の量子ビット:H を適用した後は、量子ビットを重ね合わせ状態 $|\psi\rangle=\frac1{\sqrt2} |0\rangle + \frac1{\sqrt2} |1\rangle$ で準備します。

      Qubit after applying H:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
         |1⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
      
    3. 測定後の量子ビット:結果を計測し、格納した後。これは Zero または One になります。 たとえば、結果的に生成された状態が One の場合、レジスタの状態は $|1\rangle$ に折りたたまれ、重ね合わせ状態ではなくなります。

      Qubit after the measurement:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |1⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
    4. リセット後の量子ビット:操作 Reset により、量子ビットは状態 $|0\rangle$ にリセットされます。 他の演算で使用できるように、どの Q# 演算でも、使用する量子ビットを常に状態 $|0\rangle$ のままにしておく必要があることに注意してください。

      Qubit after resetting:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      

    Note

    乱数ジェネレーターは確率論的であるため、出力が異なる場合があります。 結果の確率は決定論的ではありません。

他の種類の重ね合わせ状態を調べる

レジスタの状態を調べる方法がわかったので、量子ビットの状態を変更して重ね合わせ状態にする他の演算を確認することができます。

現在の乱数ジェネレーターでは、50% の確率で Zero または One が生成されます。 異なる確率で乱数を生成する 2 番目の例を見てみましょう。

偏りのある乱数ビット ジェネレーター

歪んだ乱数ジェネレーター、つまり、Zero を取得する確率が One を取得する確率とは異なる乱数ジェネレーターを作るとします。

たとえば、結果 Zero の確率を $P$ にし、結果 One の確率を $1-P$ にします。 そのような乱数ビット ジェネレーターを生成する有効な量子ビット状態は次のようになります。

$$|\psi\rangle=\sqrt{P}|0\rangle+\sqrt{1-P}|1\rangle$$

ここで、$\alpha=\sqrt{P}$ と $\beta=\sqrt{1-P}$ はそれぞれ、基本状態 $|0\rangle$ と $|1\rangle$ の振幅になります。

このような状態は、状態 $|0\rangle.$ の量子ビットに演算子 $R_y(2\arccos\sqrt{P})$ を順番に適用することによって得ることができます。Q# では、標準ライブラリの演算 Ry を使用することで、この結果を達成できます。

ヒント

1 量子ビット演算の背後にある数学の詳細については、1 量子ビット ゲートの Quantum Kata に関する記事を参照してください。

  1. Main.qs を次の例のように変更し、このファイルを保存します。 この例では、約 $\frac13$ となるように $\alpha$ を選択します。

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Math.*;
    
    operation Main() : Result {
        use q = Qubit();
        let P = 0.333333; // P is 1/3
        Ry(2.0 * ArcCos(Sqrt(P)), q);
        Message("The qubit is in the desired state.");
        Message("");
        DumpMachine(); // Dump the state of the qubit 
        Message("");
        Message("Your skewed random bit is:");
        let skewedrandomBit = M(q);
        Reset(q);
        return skewedrandomBit;
    }
    
  2. 組み込みのシミュレーターでプログラムを実行するには、Main 演算の上の [実行] をクリックするか、Ctrl + F5 キーを押します。 出力がデバッグ コンソールに表示されます。

  3. 演算が適用され、関連する確率が表示された後、DumpMachine によって、予想される状態がどのように表示されるかを確認できます。 Zero を取得する確率は約 33.33% であり、One を取得する確率は約 66.67% であることにご注意ください。 したがって、この乱数ジェネレーターは歪んでいます。

    The qubit is in the desired state.
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  0.5773+0.0000𝑖 |    33.3333% |   0.0000
       |1⟩ |  0.8165+0.0000𝑖 |    66.6667% |   0.0000
    
    
    Your skewed random bit is:
    Result: "One"
    

    Note

    乱数ジェネレーターは確率論的であるため、出力が異なる場合があります。 結果の確率は決定論的ではありません。

多量子ビットの重ね合わせ

次に、多くの量子ビットを含むレジスタの重ね合わせについて調べましょう。 たとえば、レジスタが 3 つの量子ビットで構成される場合、基底状態は次の 8 つになります。

$$|000\rangle、|001\rangle、|010\rangle、|011\rangle、|100\rangle、|101\rangle、|110\rangle、|111\rangle $$

したがって、任意の 3 量子ビット状態は次のように表すことができます。

$$|\psi\rangle=\alpha_0|000\rangle+\alpha_1|001\rangle+\alpha_2|010\rangle+\alpha_3|011\rangle+\alpha_4|100\rangle+\alpha_5|101\rangle+\alpha_6 |110\rangle+\alpha_7|111\rangle$$

ここで、$\alpha_i$ は、$\sum|\alpha_i|^2=1$ を満たす複素数です。

たとえば、各量子ビットに H を適用することで、一様な重ね合わせに量子ビットを配置できます。 この一様な重ね合わせを使用すると、1 量子ビットを 3 回測定するのではなく、重ね合わせ状態の 3 量子ビットを測定することによって、3 ビットの数値を生成する量子乱数ジェネレーターの異なるバージョンを作成できます。

基準 番号
$\ket{000}$ 0
$\ket{001}$ 1
$\ket{010}$ 2
$\ket{011}$ 3
$\ket{100}$ 4
$\ket{101}$ 5
$\ket{110}$ 6
$\ket{111}$ 7
  1. Main.qs を次の例のように変更し、このファイルを保存します。

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Convert.*;
    import Microsoft.Quantum.Arrays.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        let result = ForEach(M, qubits);
        Message("Measuring the qubits collapses the superposition to a basis state.");
        DumpMachine();
        ResetAll(qubits);
        return BoolArrayAsInt(ResultArrayAsBoolArray(result));
    }
    

    ここでは、次の 3 つの概念を確認します。

    • qubits 変数により、長さが 3 の Qubit 配列が表されるようになりました。
    • 演算 ApplyToEachForEach は、より少ないコードで複数の量子ビットを測定および操作するのに役立ちます。 Q# ライブラリに用意されているさまざまな種類の演算と関数を使用することで、量子プログラムをより効率的に作成できます。
    • Microsoft.Quantum.Convert ライブラリの BoolArrayAsInt 関数と ResultArrayAsBoolArray 関数を使用すると、ForEach(M, qubits) によって返されるバイナリの Result 配列を整数に変換できます。
  2. プログラムを実行するには、Main 演算の上の [実行] をクリックするか、Ctrl + F5 キーを押します。 出力がデバッグ コンソールに表示されます。

  3. DumpMachine を使用することで、3 つの量子ビットを測定する操作により、レジスタの状態が 8 つの可能な基底状態の 1 つにどのように折りたたまれるかを確認できます。 たとえば、結果が 3 の場合、レジスタの状態が $|110\rangle$ に折りたたまれたことを意味します。

    The qubit register in a uniform superposition:
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
    
    Measuring the qubits collapses the superposition to a basis state.
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |110⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    Result: "3"
    

    Note

    乱数ジェネレーターは確率論的であるため、出力が異なる場合があります。 結果の確率は決定論的ではありません。

  4. ForEach(M, qubit) 演算により、各量子ビットが順番に測定されて、状態が徐々に折りたたまれます。 各測定の後の中間状態をダンプすることもできます。 このためには、Main.qs を次の例のように変更し、このファイルを保存します。

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Measurement.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Convert.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        mutable results = [];
        for q in qubits {
            Message(" ");
            set results += [M(q)];
            DumpMachine();
        }
        Message(" ");
        Message("Your random number is: ");
        ResetAll(qubits);
        return BoolArrayAsInt(ResultArrayAsBoolArray(results));
    }
    
  5. ここでは、for ループを使用して、各量子ビットを順番に処理します。 Q# には、プログラムのフローを制御するために使用できる、for ループや if ステートメントなど、従来のフロー制御機能があります。

  6. プログラムを実行するには、Main 演算の上のコマンドの一覧で [実行] をクリックするか、Ctrl + F5 キーを押します。

  7. 連続する測定ごとの量子状態の変化、したがって各結果が得られる確率の変化を確認できます。 たとえば、結果が数字の 5 の場合、次の出力が表示されます。 各ステップについて簡単に見ていきましょう。

    1. 状態の準備: レジスタの各量子ビットに H を適用すると、一様な重ね合わせが得られます。

      The qubit register in a uniform superposition: 
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
      
    2. 1 回目の測定: 1 回目の測定では、結果は One でした。 したがって、右端の量子ビットが Zero である状態のすべての振幅は存在しなくなります。 振幅は、$|0\rangle=|000\rangle、|2\rangle=|010\rangle、|4\rangle=|100\rangle$、$|6\rangle= |110\rangle$ です。 残りの振幅は、正規化条件を満たすように増加します。

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |001⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |011⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |101⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |111⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
      
    3. 2 回目の測定: 2 回目の測定では、結果は Zero でした。 したがって、右から 2 番目 (中央) の量子ビットが One である状態の振幅はすべて消滅します。 振幅は、$|3\rangle=|011\rangle$ および $|7\rangle=|111\rangle$ です。 残りの振幅は、正規化条件を満たすように増加します。

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |001⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
       |101⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
      
    4. 3 回目の測定: 3 回目の測定では、結果は One でした。 したがって、左端の量子ビットが Zero である状態のすべての振幅が消去されます。互換性のある状態は、$|5\rangle=|101\rangle$ のみです。 この状態により、振幅確率 $1$ が得られます。

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |101⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
      
      Your random number is: 
      Result: "5"
      

    Note

    乱数ジェネレーターは確率論的であるため、出力が異なる場合があります。 結果の確率は決定論的ではありません。