量子コンピューティング向け言語Q#の問題集 QuantumKatas Measurements Task 1.10 ベル状態の識別
Task 1.10は、4つのベル状態を識別する問題です。
解答1
// Task 1.10. Distinguish four Bell states // Input: two qubits (stored in an array) which are guaranteed to be in one of the four Bell states: // |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2) // |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2) // |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2) // |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2) // Output: 0 if qubits were in |Φ⁺⟩ state, // 1 if they were in |Φ⁻⟩ state, // 2 if they were in |Ψ⁺⟩ state, // 3 if they were in |Ψ⁻⟩ state. // The state of the qubits at the end of the operation does not matter. operation BellState (qs : Qubit[]) : Int { CNOT(qs[0], qs[1]); H(qs[0]); let q0 = M(qs[0]); let q1 = M(qs[1]); if (q0 == Zero && q1 == Zero) { return 0; } elif (q0 == One && q1 == Zero) { return 1; } elif (q0 == Zero && q1 == One) { return 2; } else { return 3; } }
解答2
// Task 1.10. Distinguish four Bell states // Input: two qubits (stored in an array) which are guaranteed to be in one of the four Bell states: // |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2) // |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2) // |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2) // |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2) // Output: 0 if qubits were in |Φ⁺⟩ state, // 1 if they were in |Φ⁻⟩ state, // 2 if they were in |Ψ⁺⟩ state, // 3 if they were in |Ψ⁻⟩ state. // The state of the qubits at the end of the operation does not matter. operation BellState (qs : Qubit[]) : Int { CNOT(qs[0], qs[1]); Ry(PI() / 2.0, qs[0]); let q0 = M(qs[0]); let q1 = M(qs[1]); if (q0 == Zero && q1 == Zero) { return 1; } elif (q0 == One && q1 == Zero) { return 0; } elif (q0 == Zero && q1 == One) { return 3; } else { return 2; } }
CNOT(qs[0], qs[1]);
は(Controlled X)([qs[0]], qs[1]);
と同じ。
量子コンピューティング向け言語Q#の問題集 QuantumKatas Superposition Task 15
Superposition Task 15は2日くらい悩んでやっとテストが通った。
Task 15は、次の入力状態からゴール状態を作る問題。
- 入力状態: N個の量子ビットの状態|0...0> (Nは2の冪乗とは限らない)
- ゴール状態: W stateという状態、すなわち、 (|10...0> + |010...0> + ... + |0...1>)/sqrt(N)
以下の写真の方針で考えました。
解答
// Task 15**. W state on arbitrary number of qubits // Input: N qubits in |0...0⟩ state (N is not necessarily a power of 2). // Goal: create a W state (https://en.wikipedia.org/wiki/W_state) on these qubits. // W state is an equal superposition of all basis states on N qubits of Hamming weight 1. // Example: for N = 3, W state is (|100⟩ + |010⟩ + |001⟩) / sqrt(3). operation WState_Arbitrary (qs : Qubit[]) : Unit { let N = Length(qs); Ry(2.0 * ArcCos(Sqrt(ToDouble(N - 1) / ToDouble(N))), qs[0]); for (i in 0..N-2) { (ControlledOnInt(0, Ry))(qs[0..i], (2.0 * ArcCos(Sqrt(ToDouble(N-i-2)/ToDouble(N-i-1))), qs[i+1])); } }
QuantumKatas Superposition Task 14
// And関数を使うためにimport open Microsoft.Quantum.Extensions.Bitwise; // Task 14**. W state on 2ᵏ qubits // Input: N = 2ᵏ qubits in |0...0⟩ state. // Goal: create a W state (https://en.wikipedia.org/wiki/W_state) on these qubits. // W state is an equal superposition of all basis states on N qubits of Hamming weight 1. // Example: for N = 4, W state is (|1000⟩ + |0100⟩ + |0010⟩ + |0001⟩) / 2. operation WState_PowerOfTwo (qs : Qubit[]) : Unit { // Hint: you can use Controlled modifier to perform arbitrary controlled gates. let N = Length(qs); let k = Floor(Lg(ToDouble(N))); using (qk = Qubit[k]) { ApplyToEach(H, qk); for (i in 0..N-1) { (ControlledOnInt(i, X))(qk, qs[i]); } for (i in 0..N-1) { for (j in 0..k-1) { if (And(i, Floor(PowD(2.0, ToDouble(j)))) > 0) { (ControlledOnInt(1, X))([qs[i]], qk[j]); } } } } }
QuantumKatas Superposition Task 12
量子コンピューティングの問題集Microsoft/QuantumKatasでは、Q#プログラムを完成させてユニットテストを実行することにより、問題を解いていくことができます。
今回は、解くのに時間がかかった問題Superposition Task 12
について、紹介します。
ユニットテストの実行方法は以下です。(参考: Microsoft Quantum Development Kitのインストール(Linux))
$ cd QuantumKatas/Superposition $ dotnet test
Task 12
- 入力
- N個の量子ビットの状態|0...0>
- 2つのBool型配列
- ゴール
- 状態|0...0>から2つのBool型配列が表す等確率の重ね合わせ状態を作る
- 例) Bool型配列が[false, true, false]と[false, false, true]のとき、(|010> + |001>) / sqrt(2) を作る
- 前提条件
- 2つのBool型配列の要素数はどちらもN
- 2つのBool型配列は、少なくとも1要素は異なる
方針
- 最初の量子ビットにアダマールゲートを作用させ、を作る
- 上で作ったのは2つの状態の重ね合わせ。すなわち、0番目の量子ビットが|0>の状態Aと|1>の状態Bの重ね合わせ。状態Aに配列bits1、状態Bに配列bits2を設定する。
- 1番目〜N-1番目の量子ビットをbits1, bits2の要素に応じて反転させる(|0>を|1>にする)。ここで、0番目の量子ビットの状態を判別のために使う。
- 最後に残った0番目の量子ビットを設定する。bits1とbits2は、0番目が異なる場合と、1番目〜N-1番目のどれかが異なる場合があることを考慮する。
解答(テストは通った)
// Task 12. Superposition of two bit strings // Inputs: // 1) N qubits in |0...0⟩ state // 2) two bit string represented as Bool[]s // Goal: create an equal superposition of two basis states given by the bit strings. // // Bit values false and true correspond to |0⟩ and |1⟩ states. // Example: for bit strings [false, true, false] and [false, false, true] // the qubit state required is (|010⟩ + |001⟩) / sqrt(2). // You are guaranteed that the both bit strings have the same length as the qubit array, // and that the bit strings will differ in at least one bit. operation TwoBitstringSuperposition (qs : Qubit[], bits1 : Bool[], bits2 : Bool[]) : Unit { mutable diffIndex = 0; H(qs[0]); for (i in 1..Length(qs)-1) { if (bits1[i] != bits2[i]) { set diffIndex = i; } if (bits1[i]) { (ControlledOnInt(0, X))([qs[0]], qs[i]); } if (bits2[i]) { (ControlledOnInt(1, X))([qs[0]], qs[i]); } } if (diffIndex == 0) { if (bits1[0]) { X(qs[0]); } } else { if (bits1[0]) { if (bits1[diffIndex]) { (ControlledOnInt(1, X))([qs[diffIndex]], qs[0]); } else { (ControlledOnInt(0, X))([qs[diffIndex]], qs[0]); } } if (not bits2[0]) { if (bits2[diffIndex]) { (ControlledOnInt(1, X))([qs[diffIndex]], qs[0]); } else { (ControlledOnInt(0, X))([qs[diffIndex]], qs[0]); } } } }
ControlledOnInt関数
上記コードではControlledOnInt関数を使いました。
例えば、以下は量子ビットq1, q2, q3が全て状態|1>のとき量子ビットq4にゲートXを作用させます。
(ControlledOnInt(1, X))([q1, q2, q3], q4);
改良版 (2019/3/31追記)
もっと簡単にできました。ポイントは、状態を識別するための量子ビットを確保して、最後に確保した量子ビットを元に戻すことです。 こちらの記事を参考にさせていただきました。 Microsoft Q# Coding Contest - Winter 2019 - その2 - 純粋関数型雑記帳
operation TwoBitstringSuperposition (qs : Qubit[], bits1 : Bool[], bits2 : Bool[]) : Unit { using (indicator = Qubit()) { H(indicator); for (i in 0..Length(qs)-1) { if (bits1[i]) { (ControlledOnInt(0, X))([indicator], qs[i]); } if (bits2[i]) { (ControlledOnInt(1, X))([indicator], qs[i]); } } (ControlledOnBitString(bits2, X))(qs, indicator); } }
Q#のQuickstartをやってみた
ファイル構成
Bell.qs
namespace Bell { open Microsoft.Quantum.Canon; open Microsoft.Quantum.Primitive; // q1を状態desiredにセットする operation Set (desired: Result, q1: Qubit) : Unit { // q1の状態を測定(Measurement) let current = M(q1); if (desired != current) { // セットしたい状態と異なる状態ならば反転 X(q1); } } // countは測定回数。initialはqubits[0]の初期状態。 operation BellTest (count: Int, initial: Result) : (Int, Int, Int) { mutable numOnes = 0; mutable agree = 0; // 2個のQubitを使う using (qubits = Qubit[2]) { for (test in 1..count) { // qubits[0]を状態initialにセット Set(initial, qubits[0]); // qubits[1]を|0>にセット Set(Zero, qubits[1]); // Hはアダマールゲート? H(qubits[0]); // CNOTゲート? CNOT(qubits[0], qubits[1]); let res = M(qubits[0]); if (M(qubits[1]) == res) { set agree = agree + 1; } // Count the number of ones we saw: if (res == One) { set numOnes = numOnes + 1; } } Set(Zero, qubits[0]); Set(Zero, qubits[1]); } // Return number of times we saw a |0> and number of times we saw a |1> return (count - numOnes, numOnes, agree); } }
Driver.cs
using System; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Simulation.Simulators; namespace Bell { class Driver { static void Main(string[] args) { using (var qsim = new QuantumSimulator()) { // Try initial values Result[] initials = new Result[] { Result.Zero, Result.One }; foreach (Result initial in initials) { var res = BellTest.Run(qsim, 1000, initial).Result; var (numZeros, numOnes, agree) = res; System.Console.WriteLine($"Init:{initial,-4} 0s={numZeros,-4} 1s={numOnes,-4} agree={agree,-4}"); } } System.Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } } }
実行
$ dotnet run Init:Zero 0s=508 1s=492 agree=1000 Init:One 0s=470 1s=530 agree=1000 Press any key to continue...
やっていることは、たぶん以下だと思う。
- 量子ビットを2つ(qubits[0], qubits[1])使う。
- qubits[0]の初期状態を|0>として、1000回測定した。qubits[0]は|0>が508回、|1>が492回測定された。qubits[0]とqubits[1]は1000回全ての測定で同じ状態だった。
- qubits[0]の初期状態を|1>として、1000回測定した。qubits[0]は|0>が470回、|1>が530回測定された。qubits[0]とqubits[1]は1000回全ての測定で同じ状態だった。
|0>と|1>の測定回数は実行ごとに変わった。 ゲートHやゲートCNOTが何なのか、不勉強なため、まだわかっていない。
量子コンピューティングのチュートリアル QuantumKatas をやってみようかなぁ。
C++メモ
コンパイルエラー
$ clang++ test.cpp test.cpp:18:6: error: non-const lvalue reference to type 'C' cannot bind to a temporary of type 'C' C &c = test(); ^ ~~~~~~ 1 error generated.
上のコンパイルエラーになるソース
#include <cstdio> class C { public: C() {} void hello() { puts("hello"); } }; C test() { return C(); } int main(int argc, char* argv[]) { C &c = test(); c.hello(); return 0; }
const参照に変更するとコンパイルできる。C::hello()
にもconstを付ける。
#include <cstdio> class C { public: C() {} void hello() const { puts("hello"); } }; C test() { return C(); } int main(int argc, char* argv[]) { const C &c = test(); c.hello(); return 0; }
また、右辺値参照に変更してもコンパイルできる。
#include <cstdio> class C { public: C() {} void hello() { puts("hello"); } }; C test() { return C(); } int main(int argc, char* argv[]) { C &&c = test(); c.hello(); return 0; }
Microsoft Quantum Development Kitのインストール
環境
$ lsb_release -d Description: Ubuntu 18.04.2 LTS
参照サイト
https://docs.microsoft.com/en-us/quantum/install-guide/command-line?view=qsharp-preview
手順
参照サイトに書いてあるとおりにインストールします。
- .NET Core SDK 2.0以上(Build Appsの方)を.NET downloads pageからインストール
$ dotnet new -i Microsoft.Quantum.ProjectTemplates
を実行
これですべてのインストールが完了。
動作確認
参照サイトに書いてあるとおりに動作確認してみる。
$ git clone https://github.com/Microsoft/Quantum.git $ cd Quantum/Samples/src/Teleportation/ $ dotnet run Round 0: Sent True, got True. Teleportation successful!! Round 1: Sent False, got False. Teleportation successful!! Round 2: Sent True, got True. Teleportation successful!! Round 3: Sent False, got False. Teleportation successful!! Round 4: Sent False, got False. Teleportation successful!! Round 5: Sent True, got True. Teleportation successful!! Round 6: Sent True, got True. Teleportation successful!! Round 7: Sent True, got True. Teleportation successful!!
テレポーテーションのシミュレーションをしているのかなぁ。