チュートリアル: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#返されます。これは、値Zero
One
または .
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 つの標準演算である M
と X
が紹介されています。
SetQubitState
操作は次のとおりです。
- 2 つのパラメーターを受け取ります。
Result
desired
Zero
One
Qubit
- 測定操作 (
M
) を実行します。この操作では、量子ビットの状態 (Zero
またはOne
) を測定し、その結果をdesired
で指定された値と比較します。 - 測定値が比較値と一致しない場合は、
X
演算が実行されます。この操作では、量子ビットの状態が反転され、測定でZero
とOne
が返される確率が逆になります。 これにより、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
変数はそれぞれに1000
One
設定されます。 これにより、最初の量子ビットが One
に初期化され、各量子ビットが 1000 回測定されます。
Main
演算では、次の処理を行います。
- カウンターの変数と初期量子ビットの状態を設定します。
use
ステートメントを呼び出して、2 つの量子ビットを初期化します。count
の回数分、ループ処理を実行します。 各ループでは、次の操作が実行されますSetQubitState
を呼び出して、指定されたinitial
値を最初の量子ビットに設定します。SetQubitState
を再度呼び出して、2 番目の量子ビットをZero
状態に設定します。M
演算を使用して各量子ビットを測定します。One
を返す各量子ビットの測定値の数を格納します。
- ループが完了したら、
SetQubitState
を再度呼び出して量子ビットを既知の状態 (Zero
) にリセットし、他のユーザーが既知の状態で量子ビットを割り当てられるようにします。 ステートメントではリセットがuse
必要です。 - 最後に、この関数を
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 Zero
のinitial
値を変更してプログラムを再度実行すると、最初の量子ビットも毎回返されることを確認するZero
必要があります。
Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0
ヒント
もう一度実行する前に、コードにテスト変更を導入するたびに、Ctrl + Z キーまたは元に戻す編集>を選択し、ファイルを保存します。
量子ビットを重ね合わせ状態にする
現在、プログラム内の量子ビットはすべて "クラシック" 状態になっています。つまり、1 または 0 です。 これは、このプログラムではこれらの量子ビットを既知の状態に初期化し、それらを操作するプロセスをまだ追加していないためであることがわかっています。 量子ビットをエンタングする前に、最初の量子ビットを重ね合わせ状態にします。ここで、量子ビットの測定値は約 50% の時間とOne
約 50% の時間を返Zero
します。 概念的には、量子ビットは、測定の確率が等しいか、またはZero
One
等しいと考えることができます。
量子ビットを重ね合わせ状態にするために、Q# によって H
(つまり Hadamard) 演算が提供されます。 X
前の「量子ビットを初期化する」から「既知の状態」プロシージャに戻り、量子ビットを 0 から 1 (またはその逆) H
に反転させます。この操作では、量子ビットが途中で等確率または等しい確率のZero
One
状態に反転します。 測定されると、重ね合わせ状態にある量子ビットは、ほぼ等しい数の Zero
と One
の結果を返すはずです。
操作の初期値One
を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);
...
プログラムを実行すると、重ね合わせの最初の量子ビットの結果を確認できます。
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 番目の量子ビットのZero
One
測定結果は、プログラムの実行回数に関係なく、常に最初の量子ビットの測定と同じです。 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
いてコピーします。
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
このコード例では、量子ビットの状態を変換する 2 つの標準演算である M
と X
が紹介されています。
SetQubitState
操作は次のとおりです。
- 2 つのパラメーターを受け取ります。
Result
desired
Zero
One
Qubit
- 測定操作 (
M
) を実行します。この操作では、量子ビットの状態 (Zero
またはOne
) を測定し、その結果をdesired
で指定された値と比較します。 - 測定値が比較値と一致しない場合は、
X
演算が実行されます。この操作では、量子ビットの状態が反転され、測定でZero
とOne
が返される確率が逆になります。 これにより、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
変数はそれぞれに1000
One
設定されます。 この手順では、最初の量子ビットを One
初期化し、各量子ビットを 1000 回測定します。
Main
演算では、次の処理を行います。
- 2 つのパラメーターを受け取ります。
count
(測定を実行する回数) と、initial
(量子ビットを初期化するための望ましい状態) です。 use
ステートメントを呼び出して、2 つの量子ビットを初期化します。count
の回数分、ループ処理を実行します。 各ループでは、次の操作が実行されますSetQubitState
を呼び出して、指定されたinitial
値を最初の量子ビットに設定します。SetQubitState
を再度呼び出して、2 番目の量子ビットをZero
状態に設定します。M
演算を使用して各量子ビットを測定します。One
を返す各量子ビットの測定値の数を格納します。
- ループが完了したら、
SetQubitState
を再度呼び出して量子ビットを既知の状態 (Zero
) にリセットし、他のユーザーが既知の状態で量子ビットを割り当てられるようにします。 ステートメントでは、量子ビットをリセットするuse
必要があります。 - 最後に、結果を返す前に、
Message
関数を使用してコンソールにメッセージを出力します。
コードの実行
重ね合わせともつれの手順に進む前に、この時点までのコードをテストして、これらの量子ビットの初期化と測定を確認します。
コードをスタンドアロン プログラムとして実行するには、コンパイラがプログラムをQ#開始する場所を認識する必要があります。 名前空間が指定されていないため、コンパイラは既定のエントリ ポイントを Main
操作として認識します。 詳細については、「プロジェクトと暗黙的な名前空間」を参照してください。
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 ); }
プログラムを実行する前に、ターゲット プロファイルが [無制限] に 設定されていることを確認します。 [表示 ] -> [コマンド パレット] を選択し、QIR を検索し、[Azure Quantum QIR ターゲット プロファイルを設定する] を選択Q#して、[無制限] を選択Q#します。
Note
ターゲット プロファイルが無制限に設定されていない場合は、プログラムの実行時にエラーが発生します。
プログラムを実行するには、右上の再生アイコンのドロップダウンから [ファイルの実行Q#] を選択し、操作の前
Main
にあるコマンドの一覧から [実行] を選択するか、Ctrl キーを押しながら F5 キーを押します。 プログラムは、既定のMain
シミュレーターで操作を実行します。出力がデバッグ コンソールに表示されます。
Q1 - Zeros: 0 Q1 - Ones: 1000 Q2 - Zeros: 1000 Q2 - Ones: 0
量子ビットはまだ操作されていないので、初期値が保持されています。最初の量子ビットは毎回
One
を返し、2 番目の量子ビットはZero
を返します。to
Zero
のinitial
値を変更してプログラムを再度実行すると、最初の量子ビットも毎回返されることを確認するZero
必要があります。Q1 - Zeros: 1000 Q1 - Ones: 0 Q2 - Zeros: 1000 Q2 - Ones: 0
ヒント
もう一度実行する前に、コードにテスト変更を導入するたびに、Ctrl + Z キーまたは元に戻す編集>を選択し、ファイルを保存します。
量子ビットを重ね合わせ状態にする
現在、プログラム内の量子ビットはすべて "クラシック" 状態になっています。つまり、1 または 0 です。 これは、このプログラムではこれらの量子ビットを既知の状態に初期化し、それらを操作するプロセスをまだ追加していないためであることがわかっています。 量子ビットをエンタングする前に、最初の量子ビットを重ね合わせ状態にします。ここで、量子ビットの測定値は 50% の時間と One
50% の時間を返しますZero
。 概念上、量子ビットは Zero
と One
の中間にあると考えることができます。
量子ビットを重ね合わせ状態にするために、Q# によって H
(つまり Hadamard) 演算が提供されます。 X
前の 「量子ビットの初期化」から既知の状態への操作を思い出します。これにより、量子ビットZero
One
が (またはその逆に) H
反転されます。この操作では、量子ビットが途中で等しい確率または確率のZero
One
状態に反転します。 測定されると、重ね合わせ状態にある量子ビットは、ほぼ等しい数の Zero
と One
の結果を返すはずです。
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); ...
これで、プログラムを実行すると、重ね合わせの状態にある最初の量子ビットの結果を確認できます。
Q1 - Zeros: 523 // results will 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
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 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 つに何が起こっても、もう一方に起こるようにしました。
頻度ヒストグラムをプロットする
量子プログラムを複数回実行して得られた結果の分布を視覚化してみましょう。 頻度ヒストグラムは、これらの結果の確率分布を視覚化するのに役立ちます。
[表示 -> コマンド パレット] を選択するか、Ctrl キーを押しながら Shift キーを押しながら P キーを押し、「ヒストグラム」と入力します。[ファイルの実行とヒストグラムのQ#表示] オプションが表示されます。 前のコマンドの一覧からヒストグラムを
Main
選択することもできます。 ヒストグラム ウィンドウを開くには、このオプションを Q# 選択します。プログラムを実行するショットの数 (100 ショットなど) を入力し、Enter キーを押します。 ヒストグラムがヒストグラム ウィンドウに Q# 表示されます。
ヒストグラムの各バーは、考えられる結果に対応し、その高さは結果が観察される回数を表します。 この場合、50 種類の異なる一意の結果があります。 結果ごとに、1 番目と 2 番目の量子ビットの測定結果は常に同じであることに注意してください。
ヒント
マウス スクロール ホイールまたはトラックパッド ジェスチャを使用して、ヒストグラムをズームできます。 拡大すると、Alt キーを押しながらスクロールしてグラフをパンできます。
バーを選択すると、その結果の 割合 が表示されます。
左上 の設定アイコン を選択して、オプションを表示します。 上位 10 件の結果、上位 25 件の結果、またはすべての結果を表示できます。 また、結果を高から低、低から高に並べ替えることもできます。
関連するコンテンツ
Q# のその他のチュートリアルを確認します。
- グローバーの検索アルゴリズムは、グローバーの検索アルゴリズム を Q# 使用するプログラムを記述する方法を示しています。
- Quantum フーリエ変換 では、特定の量子ビットに直接対処するプログラムを Q# 記述する方法について説明します。
- Quantum Katas は、量子コンピューティングとプログラミングの要素を同時に教えることを目的とした、自習型のチュートリアルとQ#プログラミング演習です。