Q# を使用して重ね合わせを調べる
前のユニットでは、重ね合わせとディラック表記について学習しました。 この理論で今のところ十分です。 いくつかのコードを記述して、Q# での重ね合わせを確認しましょう。
このユニットでは、量子重ね合わせを作成し、Q# で DumpMachine
関数を使用して確率を詳しく調べます。 DumpMachine
関数は、呼び出された時点で、ターゲット マシンの現在の状態に関する情報をダンプします。
新しい Q# ファイルを作成する
- Visual Studio Code を開きます。
- Visual Studio Code で、[ファイル] >、[新しいテキスト ファイル] の順に選択し、ファイルを Main.qs として保存します。
- [表示]、[コマンド パレット] の順に選択し、「Q#:Azure Quantum QIR ターゲット プロファイルを設定する」と入力します。 Enter キーを押します。
- [Q#:無制限] を選択します。
重ね合わせの使用を開始する
重ね合わせの量子ビットを使用してランダム ビットを生成する簡単なプログラムを始めましょう。 プログラムのさまざまなポイントで量子ビットの状態を確認するには、DumpMachine
関数を使います。
次のコードを 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 回呼び出します。- 量子ビットが割り当てられた後。
- 量子ビットが重ね合わされた後。
- 量子ビットの状態が測定された後。
- 量子ビットがリセットされた後。
演算
MResetZ
をM
とReset
の 2 つの演算に分割します。 これは、測定後に状態を調べるためです。組み込みのシミュレーターでプログラムを実行するには、
Main
演算の上の [実行] をクリックするか、Ctrl + F5 キーを押します。 出力がデバッグ コンソールに表示されます。DumpMachine
関数によって、量子ビット レジスタの状態を説明する情報のテーブルが作成されます。 具体的には、各基準状態の確率振幅、確率、およびラジアン単位でのフェーズが示されます。プログラムの最後に、結果として
Zero
またはOne
が表示されます。 各ステップを見てみましょう。初期化された量子ビット:
use
ステートメントで割り当てられるすべての量子ビットは、状態 $|0\rangle$ で始まります。 したがって、DumpMachine
では、状態 $|0\rangle$ の 1 量子ビット レジスタに対応する情報が生成されます。Initialized qubit: DumpMachine: Basis | Amplitude | Probability | Phase ----------------------------------------------- |0⟩ | 1.0000+0.0000𝑖 | 100.0000% | 0.0000
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
測定後の量子ビット:結果を計測し、格納した後。これは
Zero
またはOne
になります。 たとえば、結果的に生成された状態がOne
の場合、レジスタの状態は $|1\rangle$ に折りたたまれ、重ね合わせ状態ではなくなります。Qubit after the measurement: DumpMachine: Basis | Amplitude | Probability | Phase ----------------------------------------------- |1⟩ | 1.0000+0.0000𝑖 | 100.0000% | 0.0000
リセット後の量子ビット:操作
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 に関する記事を参照してください。
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; }
組み込みのシミュレーターでプログラムを実行するには、
Main
演算の上の [実行] をクリックするか、Ctrl + F5 キーを押します。 出力がデバッグ コンソールに表示されます。演算が適用され、関連する確率が表示された後、
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 |
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
配列が表されるようになりました。- 演算
ApplyToEach
とForEach
は、より少ないコードで複数の量子ビットを測定および操作するのに役立ちます。 Q# ライブラリに用意されているさまざまな種類の演算と関数を使用することで、量子プログラムをより効率的に作成できます。 Microsoft.Quantum.Convert
ライブラリのBoolArrayAsInt
関数とResultArrayAsBoolArray
関数を使用すると、ForEach(M, qubits)
によって返されるバイナリのResult
配列を整数に変換できます。
プログラムを実行するには、
Main
演算の上の [実行] をクリックするか、Ctrl + F5 キーを押します。 出力がデバッグ コンソールに表示されます。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
乱数ジェネレーターは確率論的であるため、出力が異なる場合があります。 結果の確率は決定論的ではありません。
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)); }
ここでは、
for
ループを使用して、各量子ビットを順番に処理します。 Q# には、プログラムのフローを制御するために使用できる、for
ループやif
ステートメントなど、従来のフロー制御機能があります。プログラムを実行するには、
Main
演算の上のコマンドの一覧で [実行] をクリックするか、Ctrl + F5 キーを押します。連続する測定ごとの量子状態の変化、したがって各結果が得られる確率の変化を確認できます。 たとえば、結果が数字の 5 の場合、次の出力が表示されます。 各ステップについて簡単に見ていきましょう。
状態の準備: レジスタの各量子ビットに
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
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
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
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
乱数ジェネレーターは確率論的であるため、出力が異なる場合があります。 結果の確率は決定論的ではありません。