次の方法で共有


チュートリアル:Q# を使用して量子のもつれを調査する

このチュートリアルでは、量子ビットを Q# 操作および測定し、重ね合わせとエンタングルメントの効果を示すプログラムを記述します。 特定の量子状態で 2 つの量子ビットを準備し、量子ビット Q# を操作して状態を変更する方法を学習し、重ね合わせとエンタングルメントの効果を示します。 プログラムを Q# 1 つずつ構築して、量子ビットの状態、演算、および測定を導入します。

開始する前に理解しておく必要がある主要な概念を次に示します。

  • 従来のビットが 1 つのバイナリ値 (0 または 1) を保持するのに対して、量子ビットの状態は、2 つの量子状態 (0 と 1) の重ね合わせになることができます。 可能性のある量子状態にはそれぞれ、関連付けられている確率振幅があります。
  • 量子ビットを測定すると、一定の確率で二項結果が生成され、量子ビットの状態が重ね合わせから変化します。
  • 複数の量子ビットは、互いに独立して記述できないように絡み合うことができます。 つまり、もつれたペアの 1 つの量子ビットに対して行われたことはすべて、もう一方の量子ビットに対しても行われます。

このチュートリアルで学習する内容は次のとおりです。

  • 量子ビットを目的の状態に初期化する操作を作成 Q# します。
  • 量子ビットを重ね合わせ状態にする。
  • 量子ビットのペアをもつれさせる。
  • 量子ビットを測定し、結果を観察します。

ヒント

量子コンピューティングの取り組みを加速させる場合は、Azure Quantum Web サイトのユニークな機能である Azure Quantum を使用したコードを確認してください。 ここでは、組Q#み込みのサンプルまたは独自Q#のプログラムを実行し、プロンプトから新しいQ#コードを生成し、1 回のクリックで VS Code for the Webコードを開いて実行し、コピロットに量子コンピューティングに関する質問をすることができます。

前提条件

Copilot for Azure Quantum でコード サンプルを実行するには、次のものが必要です。

  • Microsoft (MSA) メール アカウント。

Copilot の詳細については、「Azure Quantum の探索」を参照してください

量子ビットを既知の状態に初期化する

最初の手順では、量子ビットを既知の状態に初期化する Q# 演算を定義します。 この操作を呼び出して、量子ビットを古典的な状態に設定できます。つまり、測定すると、100% の時間が返 Zero されるか、100% の時間が返 One されます。 量子ビットを測定すると、型ResultがQ#返されます。これは、値ZeroOneまたは .

Azure Quantum 用の Copilot を開き、次のコードをコード エディター ウィンドウにコピーします。 [Run yet]\(まだ実行\) をクリックしないでください。このチュートリアルの後半でコードを実行します。

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

このコード例では、量子ビットの状態を変換する 2 つの標準演算である MX が紹介されています。

SetQubitState 操作は次のとおりです。

  1. 2 つのパラメーターを受け取ります。ResultdesiredZero OneQubit
  2. 測定操作 (M) を実行します。この操作では、量子ビットの状態 (Zero または One) を測定し、その結果を desired で指定された値と比較します。
  3. 測定値が比較値と一致しない場合は、X 演算が実行されます。この操作では、量子ビットの状態が反転され、測定で ZeroOne が返される確率が逆になります。 これにより、SetQubitState は常にターゲットの量子ビットを目的の状態にします。

Bell 状態をテストするテスト操作を記述する

次に、SetQubitState 演算の効果を示すために、Main という名前の別の演算を作成します。 この操作では、2 つの量子ビットを割り当て、呼び出 SetQubitState して最初の量子ビットを既知の状態に設定し、その量子ビットを測定して結果を確認します。

次のコードをコード エディター ウィンドウの操作の下に SetQubitState コピーします。

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}

コードでは、count変数とinitial変数はそれぞれに1000One設定されます。 これにより、最初の量子ビットが One に初期化され、各量子ビットが 1000 回測定されます。

Main 演算では、次の処理を行います。

  1. カウンターの変数と初期量子ビットの状態を設定します。
  2. use ステートメントを呼び出して、2 つの量子ビットを初期化します。
  3. count の回数分、ループ処理を実行します。 各ループでは、次の操作が実行されます
    1. SetQubitState を呼び出して、指定された initial 値を最初の量子ビットに設定します。
    2. SetQubitState を再度呼び出して、2 番目の量子ビットを Zero 状態に設定します。
    3. M 演算を使用して各量子ビットを測定します。
    4. One を返す各量子ビットの測定値の数を格納します。
  4. ループが完了したら、SetQubitState を再度呼び出して量子ビットを既知の状態 (Zero) にリセットし、他のユーザーが既知の状態で量子ビットを割り当てられるようにします。 ステートメントではリセットが use 必要です。
  5. 最後に、この関数を Message 使用して、結果を返す前に Copilot 出力ウィンドウに結果を出力します。

Copilot for Azure Quantum でコードを実行する

重ね合わせとエンタングルメントの手順に進む前に、ここまでのコードをテストして、量子ビットの初期化と測定を確認できます。

スタンドアロン プログラムとしてコードを実行するには、Q#Copilot のコンパイラがプログラムを開始する場所を知っている必要があります。 名前空間が指定されていないため、コンパイラは既定のエントリ ポイントを Main 操作として認識します。 詳細については、「プロジェクトと暗黙的な名前空間」を参照してください

ここまでの Q# プログラムは次のようになります。

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
        
    
    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

完全なコード サンプルをコピーして [Copilot for Azure Quantum コード] ウィンドウに貼り付け、ショット数のスライドを "1" に設定し、[実行] をクリックします。 結果はヒストグラムと結果フィールドに表示されます。

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0

量子ビットはまだ操作されていないので、初期値が保持されています。最初の量子ビットは毎回 One を返し、2 番目の量子ビットは Zero を返します。

to Zeroinitial値を変更してプログラムを再度実行すると、最初の量子ビットも毎回返されることを確認するZero必要があります。

Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0

ヒント

もう一度実行する前に、コードにテスト変更を導入するたびに、Ctrl + Z キーまたは元に戻す編集>を選択し、ファイルを保存します。

量子ビットを重ね合わせ状態にする

現在、プログラム内の量子ビットはすべて "クラシック" 状態になっています。つまり、1 または 0 です。 これは、このプログラムではこれらの量子ビットを既知の状態に初期化し、それらを操作するプロセスをまだ追加していないためであることがわかっています。 量子ビットをエンタングする前に、最初の量子ビットを重ね合わせ状態にします。ここで、量子ビットの測定値は約 50% の時間とOne約 50% の時間を返Zeroします。 概念的には、量子ビットは、測定の確率が等しいか、またはZeroOne等しいと考えることができます。

量子ビットを重ね合わせ状態にするために、Q# によって H (つまり Hadamard) 演算が提供されます。 X前の「量子ビットを初期化する」から「既知の状態」プロシージャに戻り、量子ビットを 0 から 1 (またはその逆) H に反転させます。この操作では、量子ビットが途中で等確率または等しい確率のZeroOne状態に反転します。 測定されると、重ね合わせ状態にある量子ビットは、ほぼ等しい数の ZeroOne の結果を返すはずです。

操作の初期値OneMainリセットし、操作の行を挿入して、操作のコードをH変更します。

for test in 1..count {
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        H(q1);                // Add the H operation after initialization and before measurement

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2); 
        ...

プログラムを実行すると、重ね合わせの最初の量子ビットの結果を確認できます。

Q1 - Zeros: 523            // results vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0

プログラムを実行するたびに、最初の量子ビットの結果はわずかに異なりますが、50% と 50% One Zeroに近くなりますが、2 番目の量子ビットの結果は常に残ります Zero

Q1 - Zeros: 510           
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0

最初の量子ビットを Zero に初期化すると、同様の結果が返されます。

Q1 - Zeros: 504           
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0

Note

Azure Quantum の Copilot でスライダーを移動し、ショットの数を増やすことで、重ね合わせの結果がショットの分布とわずかに異なることがわかります。

2 つの量子ビットをもつれさせる

前に説明したように、もつれた量子ビットは、互いに独立には記述できないように接続されます。 つまり、1 つの量子ビットに対して行われた操作はすべて、もつれた量子ビットに対しても行われます。 これにより、1 つの量子ビットの最終的な状態は、もう一方の量子ビットの状態を測定するだけで、測定しなくても知ることができます。 (この例では 2 つの量子ビットを使用しますが、3 つ以上の量子ビットをもつれさせることもできます)。

もつれを有効にするために、Q# によって CNOT 演算 (これは "制御された NOT" を表します) が提供されます。 2 つの量子ビットに対してこの操作を実行した結果、最初の量子ビットが One である場合には 2 番目の量子ビットが反転されます。

プログラムの H 演算の直後に CNOT 演算を追加します。 プログラム全体は次のようになっているものと思われます。

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = Zero;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
    
        H(q1);            
        CNOT(q1, q2);      // Add the CNOT operation after the H operation

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }

プログラムを実行すると、次のような内容が表示されます。

Q1 - Zeros: 502           // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498

最初の量子ビットの統計情報は変更されていないことに注意してください (測定後の確率は約 50/50 です)。ただし、2 番目の量子ビットのZeroOne測定結果は、プログラムの実行回数に関係なく、常に最初の量子ビットの測定と同じです。 CNOT 操作によって 2 つの量子ビットがエンタングル状態になり、片方に何かが起きると、もう片方にも同じことが起こるようになっています。

前提条件

ローカル開発環境でコード サンプルを開発して実行するには、

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

  1. Visual Studio Code を開き、[ファイル] > [新しいテキスト ファイル] を選んで新しいファイルを作成します。
  2. このファイルを CreateBellStates.qs として保存します。 このファイルには、プログラムのコードが Q# 含まれます。

量子ビットを既知の状態に初期化する

最初の手順では、量子ビットを既知の状態に初期化する Q# 演算を定義します。 この操作を呼び出して、量子ビットを古典的な状態に設定できます。つまり、100% の時間を返 Zero すか、100% の時間を返します OneZeroOne は、量子ビットの測定の 2 つしかない考えられる結果を表す Q# 値です。

次のコードを開 CreateBellStates.qs いてコピーします。

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

このコード例では、量子ビットの状態を変換する 2 つの標準演算である MX が紹介されています。

SetQubitState 操作は次のとおりです。

  1. 2 つのパラメーターを受け取ります。ResultdesiredZero OneQubit
  2. 測定操作 (M) を実行します。この操作では、量子ビットの状態 (Zero または One) を測定し、その結果を desired で指定された値と比較します。
  3. 測定値が比較値と一致しない場合は、X 演算が実行されます。この操作では、量子ビットの状態が反転され、測定で ZeroOne が返される確率が逆になります。 これにより、SetQubitState は常にターゲットの量子ビットを目的の状態にします。

Bell 状態をテストするテスト操作を記述する

次に、SetQubitState 演算の効果を示すために、Main という名前の別の演算を作成します。 この操作では、2 つの量子ビットを割り当て、呼び出 SetQubitState して最初の量子ビットを既知の状態に設定した後、量子ビットを測定して結果を確認します。

CreateBellStates.qs ファイルの SetQubitState 演算の後に次の演算を追加します。

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}

コードでは、count変数とinitial変数はそれぞれに1000One設定されます。 この手順では、最初の量子ビットを One 初期化し、各量子ビットを 1000 回測定します。

Main 演算では、次の処理を行います。

  1. 2 つのパラメーターを受け取ります。count (測定を実行する回数) と、initial (量子ビットを初期化するための望ましい状態) です。
  2. use ステートメントを呼び出して、2 つの量子ビットを初期化します。
  3. count の回数分、ループ処理を実行します。 各ループでは、次の操作が実行されます
    1. SetQubitState を呼び出して、指定された initial 値を最初の量子ビットに設定します。
    2. SetQubitState を再度呼び出して、2 番目の量子ビットを Zero 状態に設定します。
    3. M 演算を使用して各量子ビットを測定します。
    4. One を返す各量子ビットの測定値の数を格納します。
  4. ループが完了したら、SetQubitState を再度呼び出して量子ビットを既知の状態 (Zero) にリセットし、他のユーザーが既知の状態で量子ビットを割り当てられるようにします。 ステートメントでは、量子ビットをリセットする use 必要があります。
  5. 最後に、結果を返す前に、Message 関数を使用してコンソールにメッセージを出力します。

コードの実行

重ね合わせともつれの手順に進む前に、この時点までのコードをテストして、これらの量子ビットの初期化と測定を確認します。

コードをスタンドアロン プログラムとして実行するには、コンパイラがプログラムをQ#開始する場所を認識する必要があります。 名前空間が指定されていないため、コンパイラは既定のエントリ ポイントを Main 操作として認識します。 詳細については、「プロジェクトと暗黙的な名前空間」を参照してください

  1. CreateBellStates.qsここまでのファイルは、次のようになります。

    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Canon.*;
    
    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }
    
    operation Main() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;
    
        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
    
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
    }
    
  2. プログラムを実行する前に、ターゲット プロファイルが [無制限] に 設定されていることを確認します。 [表示 ] -> [コマンド パレット] を選択し、QIR を検索し、[Azure Quantum QIR ターゲット プロファイルを設定する] を選択Q#して、[無制限] を選択Q#します。

    Note

    ターゲット プロファイルが無制限設定されていない場合は、プログラムの実行時にエラーが発生します。

  3. プログラムを実行するには、右上の再生アイコンのドロップダウンから [ファイルの実行Q#] を選択し、操作の前Mainにあるコマンドの一覧から [実行] を選択するか、Ctrl キーを押しながら F5 キーを押します。 プログラムは、既定の Main シミュレーターで操作を実行します。

  4. 出力がデバッグ コンソールに表示されます。

    Q1 - Zeros: 0
    Q1 - Ones: 1000
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

    量子ビットはまだ操作されていないので、初期値が保持されています。最初の量子ビットは毎回 One を返し、2 番目の量子ビットは Zero を返します。

  5. to Zeroinitial値を変更してプログラムを再度実行すると、最初の量子ビットも毎回返されることを確認するZero必要があります。

    Q1 - Zeros: 1000
    Q1 - Ones: 0
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

ヒント

もう一度実行する前に、コードにテスト変更を導入するたびに、Ctrl + Z キーまたは元に戻す編集>を選択し、ファイルを保存します。

量子ビットを重ね合わせ状態にする

現在、プログラム内の量子ビットはすべて "クラシック" 状態になっています。つまり、1 または 0 です。 これは、このプログラムではこれらの量子ビットを既知の状態に初期化し、それらを操作するプロセスをまだ追加していないためであることがわかっています。 量子ビットをエンタングする前に、最初の量子ビットを重ね合わせ状態にします。ここで、量子ビットの測定値は 50% の時間と One 50% の時間を返しますZero。 概念上、量子ビットは ZeroOne の中間にあると考えることができます。

量子ビットを重ね合わせ状態にするために、Q# によって H (つまり Hadamard) 演算が提供されます。 X前の 「量子ビットの初期化」から既知の状態への操作を思い出します。これにより、量子ビットZero One が (またはその逆に) H 反転されます。この操作では、量子ビットが途中で等しい確率または確率のZeroOne状態に反転します。 測定されると、重ね合わせ状態にある量子ビットは、ほぼ等しい数の ZeroOne の結果を返すはずです。

  1. Main 演算のコードを変更して、H 演算を含めるようにします。

    for test in 1..count {
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            H(q1);                // Add the H operation after initialization and before measurement
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2); 
            ...
    
  2. これで、プログラムを実行すると、重ね合わせの状態にある最初の量子ビットの結果を確認できます。

    Q1 - Zeros: 523            // results will vary
    Q1 - Ones: 477
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  3. プログラムを実行するたびに、最初の量子ビットの結果はわずかに異なりますが、50% と 50% One Zeroに近くなりますが、2 番目の量子ビットの結果は常に残ります Zero

    Q1 - Zeros: 510           
    Q1 - Ones: 490
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  4. 最初の量子ビットを Zero に初期化すると、同様の結果が返されます。

    Q1 - Zeros: 504           
    Q1 - Ones: 496
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

2 つの量子ビットをもつれさせる

前に説明したように、もつれた量子ビットは、互いに独立には記述できないように接続されます。 つまり、1 つの量子ビットに対して行われた操作はすべて、もつれた量子ビットに対しても行われます。 これにより、1 つの量子ビットの最終的な状態は、もう一方の量子ビットの状態を測定するだけで、測定しなくても知ることができます。 (この例では 2 つの量子ビットを使用しますが、3 つ以上の量子ビットをもつれさせることもできます)。

もつれを有効にするために、Q# によって CNOT 演算 (これは "制御された NOT" を表します) が提供されます。 2 つの量子ビットに対してこの操作を実行した結果、最初の量子ビットが One である場合には 2 番目の量子ビットが反転されます。

  1. プログラムの H 演算の直後に CNOT 演算を追加します。 プログラム全体は次のようになっているものと思われます。

    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Canon.*;
    
        operation SetQubitState(desired : Result, target : Qubit) : Unit {
            if desired != M(target) {
                X(target);
            }
        }
    
    operation Main() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = Zero;
    
        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            H(q1);            
            CNOT(q1, q2);      // Add the CNOT operation after the H operation
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
    
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
    
        }
    
    
    Q1 - Zeros: 502           
    Q1 - Ones: 498       // results will vary
    Q2 - Zeros: 502
    Q2 - Ones: 498
    Result: "(502, 498, 502, 498)"
    

最初の量子ビットの統計は変化していません (測定後の Zero または One の確率は 50/50) が、2 番目の量子ビットの測定結果は、常に最初の量子ビットの測定と同じになります。 操作によって CNOT 2 つの量子ビットが絡み合い、そのうちの 1 つに何が起こっても、もう一方に起こるようにしました。

頻度ヒストグラムをプロットする

量子プログラムを複数回実行して得られた結果の分布を視覚化してみましょう。 頻度ヒストグラムは、これらの結果の確率分布を視覚化するのに役立ちます。

  1. [表示 -> コマンド パレット] を選択するか、Ctrl キーを押しながら Shift キーを押しながら P キーを押し、「ヒストグラム」と入力します。[ファイルの実行とヒストグラムQ#表示] オプションが表示されます。 前のコマンドの一覧からヒストグラムMain選択することもできます。 ヒストグラム ウィンドウを開くには、このオプションを Q# 選択します。

  2. プログラムを実行するショット数 (100 ショットなど) を入力し、Enter キーを押します。 ヒストグラムがヒストグラム ウィンドウに Q# 表示されます。

  3. ヒストグラムの各バーは、考えられる結果に対応し、その高さは結果が観察される回数を表します。 この場合、50 種類の異なる一意の結果があります。 結果ごとに、1 番目と 2 番目の量子ビットの測定結果は常に同じであることに注意してください。

    Visual Studio Code の Q# ヒストグラム ウィンドウのスクリーンショット。

    ヒント

    マウス スクロール ホイールまたはトラックパッド ジェスチャを使用して、ヒストグラムをズームできます。 拡大すると、Alt キーを押しながらスクロールしてグラフをパンできます。

  4. バーを選択すると、その結果の 割合 が表示されます。

  5. 左上 の設定アイコン を選択して、オプションを表示します。 上位 10 件の結果、上位 25 件の結果、またはすべての結果を表示できます。 また、結果を高から低、低から高に並べ替えることもできます。

    設定を表示する方法を Q# 示す Visual Studio Code のヒストグラム ウィンドウのスクリーンショット。

Q# のその他のチュートリアルを確認します。