チュートリアル:Q# を使用して量子のもつれを調査する
このチュートリアルでは、量子ビットの操作および測定を行い、重ね合わせともつれの効果を示す、Q# プログラムの作成方法を説明します。 特定の量子状態で 2 つの量子ビットを準備し、 で量子ビット Q# を操作して状態を変更する方法を学習し、重ね合わせとエンタングルメントの影響を示します。 プログラムを Q# 1 つずつ構築して、量子ビットの状態、操作、測定を導入します。
注意
Microsoft Quantum Development Kit (クラシック QDK) は、2024 年 6 月 30 日以降サポートされなくなります。 既存の QDK 開発者の場合は、量子ソリューションの開発を続けるには、新しい Azure Quantum Development Kit (Modern QDK) に移行することをお勧めします。 詳細については、「コードをモダン QDK に移行する」を参照してくださいQ#。
開始する前に理解しておく必要がある主な概念を次に示します。
- 従来のビットが 1 つのバイナリ値 (0 または 1) を保持するのに対して、量子ビットの状態は、2 つの量子状態 (0 と 1) の重ね合わせになることができます。 可能性のある量子状態にはそれぞれ、関連付けられている確率振幅があります。
- 量子ビットを測定する行為は、一定の確率で二項結果を生成し、量子ビットの状態を重ね合わせから変化させます。
- 複数の量子ビットは、互いに独立して記述できないように絡み合うことができます。 つまり、もつれたペアの 1 つの量子ビットに対して行われたことはすべて、もう一方の量子ビットに対しても行われます。
このチュートリアルで学習する内容は次のとおりです。
- 量子ビットを目的の状態に初期化する操作を作成 Q# します。
- 量子ビットを重ね合わせ状態にする。
- 量子ビットのペアをもつれさせる。
- 量子ビットを測定し、結果を観察します。
ヒント
量子コンピューティングの取り組みを加速する場合は、Azure Quantum Web サイトのユニークな機能である Azure Quantum を使用して Code をチェックします。 ここでは、組み込みのサンプルまたは独自Q#のQ#プログラムを実行し、プロンプトから新しいQ#コードを生成し、ワンクリックで VS Code for the Web でコードを開いて実行し、コピロットに量子コンピューティングに関する質問をします。
前提条件
Copilot for Azure Quantum でコード サンプルを実行するには、次のものが必要です。
- Microsoft (MSA) メール アカウント。
Copilot の詳細については、「 Azure Quantum の探索」を参照してください。
量子ビットを既知の状態に初期化する
最初の手順では、量子ビットを既知の状態に初期化する Q# 演算を定義します。 これは、量子ビットを古典的な状態に設定するために呼び出すことができます。つまり、測定時に 100% の時間を返 Zero
すか、100% の時間を返します One
。 量子ビットを測定すると、 型が返Q#されます。これは、 または One
のZero
値のみを持Result
つことができます。
Azure Quantum 用の Copilot を開き、次のコードをコード エディター ウィンドウにコピーします。 まだ [ 実行 ] をクリックしないでください。このコードは、このチュートリアルの後半で実行します。
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 つのパラメーターを受け取ります。 という名前の型
Result
。これは、 (Zero
またはOne
) 内の量子ビットの目的の状態を表し、 型Qubit
です。desired
- 測定操作 (
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 でコードを実行する
重ね合わせとエンタングルメントの手順に進む前に、この時点までのコードをテストして、量子ビットの初期化と測定を確認できます。
コードをスタンドアロン プログラムとして実行するには、 Q# Copilot のコンパイラがプログラムを開始する 場所 を知る必要があります。 これは、最初に実行する Q# 操作の直前に を @EntryPoint()
追加することで、ファイルで行われます。 たとえば、この場合は 操作です 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" に設定し、[ 実行] をクリックします。 結果はヒストグラムと [結果 ] フィールドに表示されます。
Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0
これらの量子ビットはまだ操作されていないため、それぞれの初期値が保持されています。最初の量子ビットは毎回 One
を返し、2 番目の量子ビットは Zero
を返します。
の initial
値を に Zero
変更し、プログラムをもう一度実行すると、最初の量子ビットも毎回返されることを確認する Zero
必要があります。
Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 0
Q2 - Ones: 1000
量子ビットを重ね合わせ状態にする
現在、このプログラム内の量子ビットはすべて "古典的な" 状態にあります。つまり、1 または 0 のどちらかです。 これは、このプログラムではこれらの量子ビットを既知の状態に初期化し、それらを操作するプロセスをまだ追加していないためであることがわかっています。 量子ビットをエンタングする前に、最初の量子ビットを重ね合わせ状態にします。ここで、量子ビットの測定値は約 50% の時間とOne
約 50% の時間を返しますZero
。 概念的には、量子ビットは、 または One
のどちらかZero
を測定する確率が等しいと考えることができます。
量子ビットを重ね合わせ状態にするために、Q# によって H
(つまり Hadamard) 演算が提供されます。 「量子ビットのX
初期化」から既知の状態への操作を思い出してください。このプロシージャでは、量子ビットが 0 から 1 (またはその逆) H
に反転しました。この操作では、量子ビットが または の等しい確率Zero
One
の状態に途中で反転します。 測定されると、重ね合わせ状態にある量子ビットは、ほぼ等しい数の Zero
と One
の結果を返すはずです。
初期値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
注意
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
最初の量子ビットの統計は変更されていないことに注意してください (測定後に約 50/50 回の確率が残ります)。ただし、2 番目のZero
One
量子ビットの測定結果は、プログラムの実行回数に関係なく、常に最初の量子ビットの測定と同じです。 CNOT
操作によって 2 つの量子ビットがエンタングル状態になり、片方に何かが起きると、もう片方にも同じことが起こるようになっています。
前提条件
ローカル開発環境でコード サンプルを開発して実行するには:
- 最新バージョンの Visual Studio Code または WEB 上の VS Code を開きます。
- Azure Quantum Development Kit 拡張機能の最新バージョン。 インストールの詳細については、「 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 つのパラメーターを受け取ります。 という名前の型
Result
。これは、 (Zero
またはOne
) 内の量子ビットの目的の状態を表し、 型Qubit
です。desired
- 測定操作 (
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
関数を使用してコンソールにメッセージを出力します。
コードの実行
重ね合わせともつれの手順に進む前に、この時点までのコードをテストして、これらの量子ビットの初期化と測定を確認します。
これは、実行する操作の Q# 直前に を @EntryPoint()
追加することで、ファイル内で行われます。 たとえば、この場合は 操作です 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 );
}
}
プログラムを実行する前に、ターゲット プロファイルを [無制限] に設定する必要があります。 [表示 ] -> [コマンド パレット] を選択し、[QIR] を検索し、[: Azure Quantum QIR ターゲット プロファイルを設定する] を選択Q#し、[: unrestricted] を選択Q#します。
プログラムを実行するには、右上の再生アイコン ドロップダウンから [ファイルの実行Q#] を選択するか、Ctrl + F5 キーを押します。 プログラムは、既定のシミュレーターで 属性で @EntryPoint()
マークされた操作または関数を実行します。
注意
ターゲット プロファイルが [無制限] に設定されていない場合は、プログラムの実行時にエラーが発生します。
出力がデバッグ コンソールに表示されます。
Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0
これらの量子ビットはまだ操作されていないため、それぞれの初期値が保持されています。最初の量子ビットは毎回 One
を返し、2 番目の量子ビットは Zero
を返します。
の initial
値を に Zero
変更し、プログラムをもう一度実行すると、最初の量子ビットも毎回返されることを確認する Zero
必要があります。
Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 0
Q2 - Ones: 1000
ヒント
コードを再度実行する前に、コードに変更を導入するたびにファイルを保存することを思い出してください。
量子ビットを重ね合わせ状態にする
現在、このプログラム内の量子ビットはすべて "古典的な" 状態にあります。つまり、1 または 0 のどちらかです。 これは、このプログラムではこれらの量子ビットを既知の状態に初期化し、それらを操作するプロセスをまだ追加していないためであることがわかっています。 これらの量子ビットをもつれさせる前に、最初の量子ビットを "重ね合わせ" 状態にします。その場合、量子ビットの測定によって 50% の時間 Zero
が返され、50% の時間 One
が返されます。 概念上、量子ビットは Zero
と One
の中間にあると考えることができます。
量子ビットを重ね合わせ状態にするために、Q# によって H
(つまり Hadamard) 演算が提供されます。 X
前の 「量子ビットの初期化」から既知の状態への操作を思い出します。これにより、量子ビットが から Zero
One
(またはその逆に) H
反転されました。この操作では、量子ビットが または の等しい確率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
このプログラムを実行するたびに、最初の量子ビットの結果は多少変動しても、ほぼ 50% の One
と 50% の 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
演算を追加します。 プログラム全体は次のようになっているものと思われます。
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 つの量子ビットをもつれさせました。
頻度ヒストグラムをプロットする
量子プログラムを複数回実行して得られた結果の分布を視覚化してみましょう。 頻度ヒストグラムは、これらの結果の確率分布を視覚化するのに役立ちます。
[表示 ] -> [コマンド パレット] を選択するか、Ctrl + Shift + P キーを押し、「ヒストグラム」と入力します。これにより、[ファイルの実行とヒストグラムの表示]Q# オプションが表示されます。 ヒストグラム ウィンドウを開くには、このオプションを Q# 選択します。
100 ショット など、プログラムを実行するショットの数を入力し、 Enter キーを押します。 ヒストグラムがヒストグラム ウィンドウに Q# 表示されます。
ヒストグラムの各バーは考えられる結果に対応し、その高さは結果が観察される回数を表します。 この場合、50 の異なる一意の結果があります。 各結果について、1 番目と 2 番目の量子ビットの測定結果は常に同じであることに注意してください。
ヒント
ヒストグラムは、マウス スクロール ホイールまたはトラックパッド ジェスチャを使用してズームできます。 拡大すると、スクロール中に 'Alt' キーを押してグラフをパンできます。
バーをクリックすると、その結果の 割合 が表示されます。
左上の 設定アイコン をクリックすると、オプションが表示されます。 上位 10 件の結果、上位 25 件の結果、またはすべての結果を表示できます。 結果を高から低、低から高に並べ替えることもできます。
次のステップ
Q# のその他のチュートリアルを確認します。
- 量子乱数ジェネレーター は、重ね合わせで量子ビットから乱数を生成するプログラムを記述 Q# する方法を示します。
- グローバーの検索アルゴリズムは、グローバーの検索アルゴリズム を Q# 使用するプログラムを記述する方法を示しています。
- Quantum Fourier Transform では、特定の量子ビットに直接対処するプログラムを Q# 記述する方法について説明します。
- Quantum Katas は、量子コンピューティングとプログラミングの要素を同時に教えることを目的とした、マイペースのチュートリアルとQ#プログラミング演習です。
フィードバック
https://aka.ms/ContentUserFeedback。
近日公開予定: 2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub イシューを段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、以下を参照してください:フィードバックの送信と表示