チュートリアル:Q# を使用して量子のもつれを調査する
このチュートリアルでは、量子ビットを操作および測定し、重ね合わせとエンタングルメントの効果を示す Q# プログラムを記述します。 特定の量子状態で 2 つの量子ビットを準備し、 Q# で量子ビットを操作して状態を変更する方法を学習し、重ね合わせとエンタングルメントの効果を示します。 量子ビットの状態、演算、測定を導入するために、 Q# プログラムを 1 つずつ構築します。
開始する前に理解しておく必要がある主要な概念を次に示します。
- 従来のビットが 1 つのバイナリ値 (0 または 1) を保持するのに対して、量子ビットの状態は、2 つの量子状態 (0 と 1) の重ね合わせになることができます。 可能性のある量子状態にはそれぞれ、関連付けられている確率振幅があります。
- 量子ビットを測定すると、一定の確率で二項結果が生成され、量子ビットの状態が重ね合わせから変化します。
- 複数の量子ビットは、互いに独立して記述できないように絡み合うことができます。 つまり、もつれたペアの 1 つの量子ビットに対して行われたことはすべて、もう一方の量子ビットに対しても行われます。
このチュートリアルで学習する内容は次のとおりです。
- 量子ビットを目的の状態に初期化する Q# 操作を作成します。
- 量子ビットを重ね合わせ状態にする。
- 量子ビットのペアをもつれさせる。
- 量子ビットを測定し、結果を観察します。
ヒント
量子コンピューティングの取り組みを加速させる場合は、Azure Quantum Web サイトのユニークな機能である Azure Quantum を使用した Codeをご覧ください。 ここでは、組み込みの Q# サンプルまたは独自の Q# プログラムを実行し、プロンプトから新しい Q# コードを生成し、 VS Code for the Web でコードを開いて実行し ワンクリックで Copilot に量子コンピューティングに関する質問を行うことができます。
前提条件
Copilot for Azure Quantum でコード サンプルを実行するには、次のものが必要です。
- Microsoft (MSA) メール アカウント。
Copilot の詳細については、「 Explore Azure Quantum」を参照してください。
量子ビットを既知の状態に初期化する
最初の手順では、量子ビットを既知の状態に初期化する Q# 演算を定義します。 これは、量子ビットを古典的な状態に設定するために呼び出すことができます。つまり、測定すると、100% の時間 Zero
返すか、100% の時間 One
返します。 量子ビットを測定すると、 Q# 型の Result
が返されます。 Zero
または One
の値のみを持つことができます。
Azure Quantum 用の Copilot を開き 次のコードをコード エディター ウィンドウにコピーします。 まだ Run をクリックしないでください。このチュートリアルの後半でコードを実行します。
namespace Bell {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
}
このコード例では、量子ビットの状態を変換する 2 つの標準演算である M
と X
が紹介されています。
SetQubitState
操作は次のとおりです。
- 2 つのパラメーターを受け取ります。
desired
という名前の型Result
。量子ビットの状態 (Zero
またはOne
) を表し、型Qubit
。 - 測定操作 (
M
) を実行します。この操作では、量子ビットの状態 (Zero
またはOne
) を測定し、その結果をdesired
で指定された値と比較します。 - 測定値が比較値と一致しない場合は、
X
演算が実行されます。この操作では、量子ビットの状態が反転され、測定でZero
とOne
が返される確率が逆になります。 これにより、SetQubitState
は常にターゲットの量子ビットを目的の状態にします。
Bell 状態をテストするテスト操作を記述する
次に、SetQubitState
演算の効果を示すために、TestBellState
という名前の別の演算を作成します。 この操作では、2 つの量子ビットを割り当て、 SetQubitState
を呼び出して最初の量子ビットを既知の状態に設定し、その量子ビットを測定して結果を確認します。
次のコードを、 SetQubitState
操作の下にあるコード エディター ウィンドウにコピーします。
operation TestBellState() : (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
変数がそれぞれ 1000
に設定され、 One
されます。 これにより、最初の量子ビットが One
に初期化され、各量子ビットが 1000 回測定されます。
TestBellState
演算では、次の処理を行います。
- カウンターの変数と初期量子ビットの状態を設定します。
use
ステートメントを呼び出して、2 つの量子ビットを初期化します。count
の回数分、ループ処理を実行します。 各ループでは、次の操作が実行されますSetQubitState
を呼び出して、指定されたinitial
値を最初の量子ビットに設定します。SetQubitState
を再度呼び出して、2 番目の量子ビットをZero
状態に設定します。M
演算を使用して各量子ビットを測定します。One
を返す各量子ビットの測定値の数を格納します。
- ループが完了したら、
SetQubitState
を再度呼び出して量子ビットを既知の状態 (Zero
) にリセットし、他のユーザーが既知の状態で量子ビットを割り当てられるようにします。 この操作は、use
ステートメントに必須です。 - 最後に、結果を返す前に、
Message
関数を使用して結果を Copilot 出力ウィンドウに出力します。
Copilot for Azure Quantum でコードを実行する
重ね合わせとエンタングルメントの手順に進む前に、ここまでのコードをテストして、量子ビットの初期化と測定を確認できます。
スタンドアロン プログラムとしてコードを実行するには、Copilot の Q# コンパイラが の場所 プログラムを開始する必要があります。 これは、最初に実行する操作の直前に@EntryPoint()
を追加することによって、Q# ファイルで行われます。 たとえば、この場合は TestBellState
操作です。
Note
@EntryPoint()
はスタンドアロン Q# プログラムにのみ必要です。 Jupyter Notebooks で Q# プログラムを実行するとき、または Python ホスト ファイルから Q# プログラムを呼び出すときは、必須ではなく、含まれている場合はエラーがスローされます。
TestBellState
操作の直前に@EntryPoint()
を追加すると、ここまでのQ# プログラムは次のようになります。
namespace Bell {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
@EntryPoint()
operation TestBellState() : (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" に設定し、 Run をクリックします。 結果はヒストグラムと Results フィールドに表示されます。
Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0
量子ビットはまだ操作されていないので、初期値が保持されています。最初の量子ビットは毎回 One
を返し、2 番目の量子ビットは Zero
を返します。
initial
の値をZero
に変更し、プログラムをもう一度実行すると、最初の量子ビットも毎回Zero
返されることを確認する必要があります。
Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0
量子ビットを重ね合わせ状態にする
現在、プログラム内の量子ビットはすべて "クラシック" 状態になっています。つまり、1 または 0 です。 これは、このプログラムではこれらの量子ビットを既知の状態に初期化し、それらを操作するプロセスをまだ追加していないためであることがわかっています。 量子ビットをエンタングする前に、最初の量子ビットを 重ね合わせ状態に配置します。ここで量子ビットの測定値は約 50% の時間 Zero
返され、 One
約 50% の時間が返されます。 概念的には、量子ビットは、 Zero
または One
を測定する確率が等しいと考えることができます。
量子ビットを重ね合わせ状態にするために、Q# によって H
(つまり Hadamard) 演算が提供されます。 からのX
演算を思い出します。前の手順で量子ビットを既知の状態に初期化します。このプロシージャでは、量子ビットが 0 から 1 (またはその逆) に反転されました。H
操作では、量子ビットhalfwayがZero
またはOne
の確率が等しい状態に反転されます。 測定されると、重ね合わせ状態にある量子ビットは、ほぼ等しい数の Zero
と One
の結果を返すはずです。
初期値をOne
にリセットし、H
操作の行を挿入して、TestBellState
操作のコードを変更します。
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 will vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0
プログラムを実行するたび、最初の量子ビットの結果は、わずかな違いはあるものの、One
と Zero
がそれぞれ 50% に近い結果になります。一方、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
演算を追加します。 プログラム全体は次のようになっているものと思われます。
namespace Bell {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
@EntryPoint()
operation TestBellState() : (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
最初の量子ビットの統計情報は変更されていないことに注意してください (測定後、 Zero
または One
が発生する可能性はまだ約 50/50 です)。ただし、2 番目の量子ビットの測定結果は です プログラムを実行する回数に関係なく、最初の量子ビットの測定と同じです。 CNOT
操作によって 2 つの量子ビットがエンタングル状態になり、片方に何かが起きると、もう片方にも同じことが起こるようになっています。
前提条件
ローカル開発環境でコード サンプルを開発して実行するには、
- 最新バージョンの Visual Studio Code または VS Code on the Web を開きます。
- Azure Quantum 開発キット拡張機能の最新バージョン。 インストールの詳細については、「 VS Code での QDK のインストールを参照してください。
新しい Q# ファイルを作成する
- Visual Studio Code を開き、[ファイル] > [新しいテキスト ファイル] を選んで新しいファイルを作成します。
- このファイルを
CreateBellStates.qs
として保存します。 このファイルには、プログラムの Q# コードが含まれます。
量子ビットを既知の状態に初期化する
最初の手順では、量子ビットを既知の状態に初期化する Q# 演算を定義します。 これを呼び出すと、量子ビットを古典的な状態に設定できます。つまり、100% の時間 Zero
を返すか、または 100% の時間 One
を返すかのどちらかになります。 Zero
と One
は、量子ビットの測定の 2 つしかない考えられる結果を表す Q# 値です。
CreateBellStates.qs
を開き、次のコードをコピーします。
namespace Bell {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
}
このコード例では、量子ビットの状態を変換する 2 つの標準演算である M
と X
が紹介されています。
SetQubitState
操作は次のとおりです。
- 2 つのパラメーターを受け取ります。
desired
という名前の型Result
。量子ビットの状態 (Zero
またはOne
) を表し、型Qubit
。 - 測定操作 (
M
) を実行します。この操作では、量子ビットの状態 (Zero
またはOne
) を測定し、その結果をdesired
で指定された値と比較します。 - 測定値が比較値と一致しない場合は、
X
演算が実行されます。この操作では、量子ビットの状態が反転され、測定でZero
とOne
が返される確率が逆になります。 これにより、SetQubitState
は常にターゲットの量子ビットを目的の状態にします。
Bell 状態をテストするテスト操作を記述する
次に、SetQubitState
演算の効果を示すために、TestBellState
という名前の別の演算を作成します。 この操作では、2 つの量子ビットを割り当て、 SetQubitState
を呼び出して最初の量子ビットを既知の状態に設定し、その量子ビットを測定して結果を確認します。
CreateBellStates.qs
ファイルの SetQubitState
演算の後に次の演算を追加します。
operation TestBellState() : (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
変数がそれぞれ 1000
に設定され、 One
されます。 これにより、最初の量子ビットが One
に初期化され、各量子ビットが 1000 回測定されます。
TestBellState
演算では、次の処理を行います。
- 2 つのパラメーターを受け取ります。
count
(測定を実行する回数) と、initial
(量子ビットを初期化するための望ましい状態) です。 use
ステートメントを呼び出して、2 つの量子ビットを初期化します。count
の回数分、ループ処理を実行します。 各ループでは、次の操作が実行されますSetQubitState
を呼び出して、指定されたinitial
値を最初の量子ビットに設定します。SetQubitState
を再度呼び出して、2 番目の量子ビットをZero
状態に設定します。M
演算を使用して各量子ビットを測定します。One
を返す各量子ビットの測定値の数を格納します。
- ループが完了したら、
SetQubitState
を再度呼び出して量子ビットを既知の状態 (Zero
) にリセットし、他のユーザーが既知の状態で量子ビットを割り当てられるようにします。 この操作は、use
ステートメントに必須です。 - 最後に、結果を返す前に、
Message
関数を使用してコンソールにメッセージを出力します。
コードの実行
重ね合わせともつれの手順に進む前に、この時点までのコードをテストして、これらの量子ビットの初期化と測定を確認します。
これは、実行する操作の直前に@EntryPoint()
を追加することによって、Q# ファイルで行われます。 たとえば、この場合は TestBellState
操作です。
Note
@EntryPoint()
はスタンドアロン Q# プログラムにのみ必要です。 Jupyter Notebooks で Q# プログラムを実行するとき、または Python ホスト ファイルから Q# プログラムを呼び出すときは、必須ではなく、含まれている場合はエラーがスローされます。
CreateBellStates.qs
ファイルは次のようになります。namespace Bell { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; operation SetQubitState(desired : Result, target : Qubit) : Unit { if desired != M(target) { X(target); } } @EntryPoint() operation TestBellState() : (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 ); } }
プログラムを実行する前に、ターゲット プロファイルを "無制限" に設定する必要があります。 View -> コマンド パレットを選択し、QIR を検索し、Q#: Azure Quantum QIR ターゲット プロファイルを設定を選択してから、Q#: 無制限を選択します。
Note
ターゲット プロファイルが Unrestricted に設定されていない場合は、プログラムの実行時にエラーが発生します。
プログラムを実行するには、右上の再生アイコン ドロップダウンから Run Q# ファイルを選択、
@EntryPoint()
の下のコマンドの一覧から Run をクリックするか、Ctrl + F5 キーを押。 プログラムは、既定のシミュレーターで@EntryPoint()
属性でマークされた操作または関数を実行します。出力がデバッグ コンソールに表示されます。
Q1 - Zeros: 0 Q1 - Ones: 1000 Q2 - Zeros: 1000 Q2 - Ones: 0
量子ビットはまだ操作されていないので、初期値が保持されています。最初の量子ビットは毎回
One
を返し、2 番目の量子ビットはZero
を返します。initial
の値をZero
に変更し、プログラムをもう一度実行すると、最初の量子ビットも毎回Zero
返されることを確認する必要があります。Q1 - Zeros: 1000 Q1 - Ones: 0 Q2 - Zeros: 1000 Q2 - Ones: 0
ヒント
コードを再度実行する前に、コードに変更を導入するたびにファイルを保存することを思い出してください。
量子ビットを重ね合わせ状態にする
現在、プログラム内の量子ビットはすべて "クラシック" 状態になっています。つまり、1 または 0 です。 これは、このプログラムではこれらの量子ビットを既知の状態に初期化し、それらを操作するプロセスをまだ追加していないためであることがわかっています。 量子ビットをエンタングルする前に、最初の量子ビットを "重ね合わせ" 状態にします。これにより、量子ビットの測定で Zero
が返される確率が 50%、One
が返される確率が 50% になります。 概念上、量子ビットは Zero
と One
の中間にあると考えることができます。
量子ビットを重ね合わせ状態にするために、Q# によって H
(つまり Hadamard) 演算が提供されます。 からのX
操作を思い出します前の手順で量子ビットを既知の状態に初期化します。これにより、量子ビットがZero
からOne
(またはその逆) に反転されます。H
操作では、量子ビットhalfwayがZero
またはOne
の等しい確率の状態に反転されます。 測定されると、重ね合わせ状態にある量子ビットは、ほぼ等しい数の Zero
と One
の結果を返すはずです。
TestBellState
演算のコードを変更して、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 will vary Q1 - Ones: 477 Q2 - Zeros: 1000 Q2 - Ones: 0
プログラムを実行するたび、最初の量子ビットの結果は、わずかな違いはあるものの、
One
とZero
がそれぞれ 50% に近い結果になります。一方、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
2 つの量子ビットをもつれさせる
前に説明したように、もつれた量子ビットは、互いに独立には記述できないように接続されます。 つまり、1 つの量子ビットに対して行われた操作はすべて、もつれた量子ビットに対しても行われます。 これにより、1 つの量子ビットの最終的な状態は、もう一方の量子ビットの状態を測定するだけで、測定しなくても知ることができます。 (この例では 2 つの量子ビットを使用しますが、3 つ以上の量子ビットをもつれさせることもできます)。
もつれを有効にするために、Q# によって CNOT
演算 (これは "制御された NOT" を表します) が提供されます。 2 つの量子ビットに対してこの操作を実行した結果、最初の量子ビットが One
である場合には 2 番目の量子ビットが反転されます。
プログラムの
H
演算の直後にCNOT
演算を追加します。 プログラム全体は次のようになっているものと思われます。namespace Bell { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; operation SetQubitState(desired : Result, target : Qubit) : Unit { if desired != M(target) { X(target); } } @EntryPoint() operation TestBellState() : (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); 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
最初の量子ビットの統計は変化していません (測定後の Zero
または One
の確率は 50/50) が、2 番目の量子ビットの測定結果は、常に最初の量子ビットの測定と同じになります。 CNOT
操作によって 2 つの量子ビットがエンタングル状態になり、片方に何かが起きると、もう片方にも同じことが起こるようになっています。
頻度ヒストグラムをプロットする
量子プログラムを複数回実行して得られた結果の分布を視覚化してみましょう。 頻度ヒストグラムは、これらの結果の確率分布を視覚化するのに役立ちます。
View -> コマンド パレットを選択するか、Ctrl + Shift + P キーを押し、「ヒストグラム」と入力します。Q#:ファイルの実行とヒストグラムの表示オプションが表示されます。
@EntryPoint()
の下のコマンドの一覧から Histogram をクリックすることもできます。 このオプションを選択すると、 Q# ヒストグラム ウィンドウが開きます。ショットの数を入力し100 ショットなどのプログラムを実行し、Enter キーを押します。 ヒストグラムが Q# ヒストグラム ウィンドウに表示されます。
ヒストグラムの各バーは、考えられる結果に対応し、その高さは結果が観察される回数を表します。 この場合、50 種類の異なる一意の結果があります。 結果ごとに、1 番目と 2 番目の量子ビットの測定結果は常に同じであることに注意してください。
ヒント
マウス スクロール ホイールまたはトラックパッド ジェスチャを使用して、ヒストグラムをズームできます。 拡大すると、スクロール中に 'Alt' キーを押してグラフをパンできます。
バーをクリックすると、その結果の 時間 が表示されます。
左上の 設定アイコン をクリックしてオプションを表示します。 上位 10 件の結果、上位 25 件の結果、またはすべての結果を表示できます。 また、結果を高から低、低から高に並べ替えることもできます。
関連するコンテンツ
Q# のその他のチュートリアルを確認します。
- グローバーの検索アルゴリズム グローバーの検索アルゴリズムを使用する Q# プログラムを記述する方法を示します。
- 量子フーリエ変換 では、特定の量子ビットに直接対処する Q# プログラムを記述する方法について説明します。
- Quantum Katasは、量子コンピューティングとQ#プログラミングの要素を同時に教えることを目的とした、自習型のチュートリアルとプログラミング演習です。