量子プログラミング入門→量子コンピューティングサービス構築入門

量子コンピューター初心者の筆者が日々学びながら、量子コンピュータ上で量子プログラミングできるようなるまでの学習日記を記録していきます。 内容は量子コンピューター入門者向けで、専門家の方からするとおかしな内容があるかもしれません。その際はコメント等でお知らせください!

Part I. Problem Statement and Classical Algorithm解説

Deutsch-Jozsaアルゴリズム(ドイチェジョザアルゴリズム)に関するチュートリアルです。Deutsch-Jozsaアルゴリズムは量子コンピューティングの世界では非常に有名なアルゴリズムで、量子コンピューターの有益性を理解するためには良い題材です。ただ実際の世界においてはあまり有効に活用できるようなロジックではないためここでは量子コンピュータの優位性を理解することにフォーカスします。

Deutsch-JozsaのTutorialは4部に分かれています。
Part 1: 問題の定義と古典アルゴリズムについて
Part 2: 量子オラクルについて
Part 3: 量子アルゴリズムについて
Part 4: 実際にDeutsch-Jozsaを量子アルゴリズムで動かしてみる

「Part 1: 問題の定義と古典アルゴリズムについて」は
Deutsch-Jozsaが解決しようとする問題を理解し、古典コンピューターで解こうとした場合の問題点を理解します。

Deutsch–Jozsa Algorithmついて

Deutsch-Jozsaアルゴリズムとは中身のわからないブラックボックスな関数\(f(x)\)について、
1) すべての入力\(x\)に対して、常に0を返す、あるいは、常に1を返す場合、constant
2) 入力\(x\)に対して50%ずつの確率で0と1をそれぞれ返す場合balanced
と関数の性質を判定するアルゴリズムです。

古典コンピューターの場合、関数の性質を判定するのに最悪の場合、全体の51%の入力に対して総当たり的に入力を与えないと解が求まらないのに対して、量子コンピュータを使うと多項式時間で解が求まることを理解します。

Q#の基本的な文法について

この辺りからQ#の基本的な文法についてある程度知っておかないと、if文やfor/whileループの書き方なに戸惑ってしまいます。
Q#の基本的な文法についてはこちらにまとめています。


Exercise 1: Implement a classical function in Q#


Most Significant Bitが0か1かを判定する関数を作成します。

%kata E1_ClassicalFunction_Test 

function Function_MostSignificantBit (x : Int, N : Int) : Int {
    let msb = x >>> (N-1);
    return msb;
}

古典アルゴリズムについて

古典コンピュータの場合、組み合わせを求めるためにループを回す必要があり計算量が\(2^n\)のオーダーになります。実際にプログラムを書いてみて確かめてみましょう。

Exercise 2: Implement the classical algorithm!


ここでは古典コンピュータの古典的なアルゴリズムを使って関数\(f(x)\)がConstantかBalancedかを判定する処理を作ります。ループを\(2^{(n-1)}\)回まわす処理が必要で、前提条件からループが回りきらせる必要はないですが、Constantと判断するには最低でも全入力の51%\((n^{(n/2 +1)}回)\)は試す必要があります。

%kata E2_ClassicalAlgorithm_Test 

operation IsFunctionConstant_Classical (N : Int, f : (Int -> Int)) : Bool {
    mutable ret = true;
    let ret0 = f(0);
    for (i in 1 .. 1 .. (2^N - 1)) {
        let ret_i = f(i);
        if (ret0 != ret_i){
            set ret = false;
            return ret;
        }
    }
    return ret;
}

変数の代入

Q#で変数(mutableな変数)を使用する場合、mutableで宣言する必要があります。
        mutable i = 0;
        set i = 1;
mutableで変数を宣言した後にsetを使用して変数を変更することができます。

letで定義してしまうとimmutableな変数となってしまい、エラーが出ます。
        let i = 0;                                                                      Message ($"{i}");
        set i = 1;

QS6303: An immutable identifier cannot be modified.

メッセージ表示

Q#にはprint, printfやC#にあるConsole.WriteLine関数はありません。
コンソールにメッセージを表示する場合はMessage関数を使います。

準備

"Microsoft.Quantum.Diagnostics"をオープンします。
open Microsoft.Quantum.Diagnostics;

文字列の表示

文字列の表示の場合は単純にMessage関数の引数に文字列を渡します。
Message("test");

変数の値の表示

変数の値を表示する場合文字列の手前に $ を付け、表示したい変数を文字列の中で {}付きで挿入します。.
    let i = 1;
    Message($"Display i={i}");
This shows below.
Display i=1

For ループ

forループの引数の記載の方法は "start .. step .. end"で書きます。
この場合 iは初期値1 から1ずつ増加していき、10まで進みます。
    for (i in 1 .. 1 .. 5 ) {
        Message ($"{i}");
    }

実行結果はこのようになります。
1
2
3
4
5


 


チュートリアル Multi-Qubit Gates解説および解答例

Github
https://github.com/microsoft/QuantumKatas/tree/master/tutorials/MultiQubitGates

(いきなりこのページに飛んできた人で最初から勉強されたい方はこちらをご参照ください)

いよいよ基礎的な学習は最終回です。今回はMulti-Qubit Gatesということで、複数のQubitに対するオペレーションを学習していきます。

Exercise 1: Compound Gate

3Qubitに対するオペレーションを作成します。 8x8の行列で3つのQubitに対する操作を表していますが、これを3つのSingle Qubitに対する操作に分割します。

まず
- 右上のquadrant(4x4)と左下のquadrant(4x4)がゼロになっていること
- 左上のquadrant(4x4)と右下のquadrant(4x4)がiをかけた関係になっていること
に着目し
\[ Q = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix} \otimes \begin{bmatrix} 0 & -i & 0 & 0 \\ i & 0 & 0 & 0 \\ 0 & 0 & 0 & -i \\ 0 & 0 & i & 0 \end{bmatrix} \]
を導き出します。さらに
- 右上のquadrant(2x2)と左下のquadrant(4x4)がゼロになっていること
- 左上のquadrant(2x2)と右下のquadrant(4x4)が同じになっていること
から
\[ Q = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix} \otimes \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \otimes \begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix} = S \otimes I \otimes Y \]
3つのSingle Bitのオペレーションに分解することができました。

%kata T1_CompoundGate_Test

operation CompoundGate (qs : Qubit[]) : Unit is Adj {
    S(qs[0]);
    I(qs[1]);
    Y(qs[2]);
}
(参考)テンソル積の簡単なイメージ \[ \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \otimes \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} = \begin{bmatrix} 1 \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} & 2 \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} \\ 3 \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} & 4 \cdot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} \end{bmatrix} \] 

Exercise 2: Preparing a Bell state

CNOTゲートの使い方に関する学習です。CNOTゲートは2Qubitゲートで、最初のビットの状態が\(|1\rangle\)であれば、2Qubit目を反転させます。

解説にあるようにCNOTゲートは量子もつれ状態を作るのに有効です。
\[ \big(\alpha|0\rangle + \beta|1\rangle\big) \otimes |0\rangle = \alpha|00\rangle + \beta|10\rangle \] この状態にCNOTをかけると
\[ \alpha|00\rangle + \beta|11\rangle \] ができます。

ここではBell Stateを作り出すことが目的ですが、Bell Steteは不可分な量子もつれ状態ですので、1Qubitずつの操作に分解することはできません。
\[ \Phi^+ = \frac{1}{\sqrt{2}}\big(|00\rangle + |11\rangle\big) = \frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\ 0 \\ 0 \\ 1
\end{bmatrix} \]

この問題では
\[ \frac{1}{\sqrt{2}}\big(|00\rangle + |10\rangle\big) = \frac{1}{\sqrt{2}}\big(|0\rangle + |1\rangle\big) \otimes |0\rangle \] という状態を作り出しCNOTゲートを適用させます。
\( \frac{1}{\sqrt{2}}\big(|0\rangle + |1\rangle\big) \)はHゲートで作り出すことができますので、HゲートとCNOTゲートで対応できます。
%kata T2_BellState_Test

operation BellState (qs : Qubit[]) : Unit is Adj {
    H(qs[0]);
    CNOT(qs[0],qs[1]);
}

Exercise 3: Swapping two qubits

SWAPゲートも2Qubitに対する同時操作です。仕様もシンプルでチュートリアルの解答はすぐにわかりますが、使用用途がまだよくわかりません。
%kata T3_QubitSwap_Test

operation QubitSwap (qs : Qubit[], index1 : Int, index2 : Int) : Unit is Adj {
    SWAP(qs[index1], qs[index2]);
}

Exercise 4: Controlled Rotation

Controlledは指定した制御ビットの状態を見て、ターゲットビットに操作を加えるオペレーションです。オペレーションはSingle Bitのオペレーションも使用できますしSWAPのような2ビットオペレーションも使用できます。
// Apply X gate to target bit
Controlled
X([control], target);
// Apply SWAP to targets
Controlled
SWAP([control], (q1, q2));
第一引数の制御ビットを[]でくくらないといけないというのにはまりました。制御ビットは配列で複数指定できるのでそのようになっているようです。

%kata T4_ControlledRotation_Test

operation ControlledRotation (qs : Qubit[], theta : Double) : Unit is Adj {
    Controlled Rx([qs[0]], (theta, qs[1]));
}

Exercise 5: Arbitrary controls

ControlledOnBitStringは複数の制御ビットに対して任意(True or False)の判定を行い、条件が一致する場合指定されたオペレーションを実行します。
Q#の文法の説明が少なくてよくわからないですね。
%kata T5_MultiControls_Test

operation MultiControls (controls : Qubit[], target : Qubit, controlBits : Bool[]) : Unit is Adj {
     (ControlledOnBitString(controlBits, X))(controls, target);
}


チュートリアル Multi-Qubit Systems解説および解答例

Githubリンク
https://github.com/microsoft/QuantumKatas/tree/master/tutorials/MultiQubitSystems

(いきなりこのページに飛んできた人で最初から勉強されたい方はこちらをご参照ください)

前回は1Qubitの操作を学んできました、今回は複数Qubit(主に2Qubit)の操作を学習していきます。

ポイント

複数ビットになって数字の数が増えて複雑になっていますが、ここでのポイントは複数ビットの状態は単独ビットのテンソル積の状態に分割可能な場合があり、今回の学習では基本的に分割できる問題ばかりなので、まずは分割してどのような状態にすればよいかを考えていきます。(テンソル積はLinear Algebra Part 2で出てきていますのでお忘れの方はこちらで復習を。)

一般的に書くと下記のようになります。
\[ \begin{bmatrix} \alpha \color{red}\gamma \\ \alpha \color{red}\delta \\ \beta \color{red}\gamma \\ \beta \color{red}\delta \end{bmatrix} = \begin{bmatrix} \alpha \\ \beta \end{bmatrix} \otimes \begin{bmatrix} \color{red}\gamma \\ \color{red}\delta \end{bmatrix} \]


Exercise 1: Show that the state is separable

自分が悩んだポイントを補足しておきます。
\[ \frac{1}{2} \begin{bmatrix} 1 \\ i \\ -i \\ 1 \end{bmatrix} = \begin{bmatrix} ? \\ ? \end{bmatrix} \otimes \begin{bmatrix} ? \\ ? \end{bmatrix} \]
これを上記の一般式に当てはめると
\[ \begin{cases} \alpha\gamma = \frac{1}{2} \\ \alpha\delta = \frac{i}{2} \\ \beta \gamma = \frac{-i}{2} \\ \beta \delta = \frac{1}{2} \\ \end{cases} \]
となります。
さらにこれらを解いていくと \( \frac{\alpha}{\beta} = \frac{-1}{i} = i \) となります。
ここで \( |\alpha|^2 + |\beta|^2 = 1 \)を考慮すると
\[ \alpha = \frac{1}{\sqrt2}, \beta = \frac{-i}{\sqrt2}, \gamma = \frac{1}{\sqrt2}, \delta = \frac{i}{\sqrt2} \] となり解を導くことができます。 問題文には出てきませんが、Qubitの条件 \( |\alpha|^2 + |\beta|^2 = 1 \)を考慮することで解を導くことができます。

いろいろ計算が複雑ですが、ここではヒントもあるのでまずは下記の4つの活用を考えればよいと思います。
\[ \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix},   \begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 0 \\ 1 \end{bmatrix},   \begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix},  \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 0 \\ 1 \end{bmatrix} \]

Demo解説

解説を読んでるだけではわからないところも多いので、実際にDemoを動かしてみて理解を深めていきましょう。

量子ビットの配置

Qubitを配列で配置します。初期状態は|00>です。
    // This allocates an array of 2 qubits, each of them in state |0⟩.
    // The overall state of the system is |00⟩
    using (qs = Qubit[2]) {
つまり
\[ \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix} \]
という状態です。

1Qubit目の反転

qs[0]=1ビット目をXゲートで反転させます。
        // X gate changes the first qubit into state |1⟩
        // The entire system is now in state |10⟩
        X(qs[0]);
\[ \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix} \]
の状態の1ビット目を反転させるので
\[ \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1\\ 0 \\ 0 \end{bmatrix}  \]
になります。
結果は
System in state |10⟩ = |1⟩:
# wave function for qubits with ids (least to most significant): 0;1
∣0❭:	 0.000000 +  0.000000 i	 == 	                     [ 0.000000 ]                   
∣1❭:	 1.000000 +  0.000000 i	 == 	******************** [ 1.000000 ]     --- [  0.00000 rad ]
∣2❭:	 0.000000 +  0.000000 i	 == 	                     [ 0.000000 ]                   
∣3❭:	 0.000000 +  0.000000 i	 == 	                     [ 0.000000 ]        
コメントが"System in state |10⟩ = |1⟩:"になっていますが、"System in state |10⟩ = |10⟩:"のほうが正確ですかね。

アダマールゲート適用

2ビット目にアダマールゲートを適用します。
        // This changes the second qubit into state |+⟩ = (1/sqrt(2))(|0⟩ + |1⟩).
        // The entire system is now in state (1/sqrt(2))(|10⟩ + |11⟩)
        H(qs[1]);
\[ \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix}  \]
の状態の2ビット目にHゲートを適用するので2ビット目が
\( H|1\rangle = |+\rangle = \frac{1}{\sqrt{2}}\big(|0\rangle + |1\rangle\big) \)
となり
\[ \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \frac{1}{\sqrt{2}}\begin{bmatrix} 0 \\ 1 \\ 0 \\ 1 \end{bmatrix}  \]
となります。
System in state (1/sqrt(2))(|10⟩ + |11⟩) = (1/sqrt(2))(|1⟩ + |3⟩):
# wave function for qubits with ids (least to most significant): 0;1
∣0❭:	 0.000000 +  0.000000 i	 == 	                     [ 0.000000 ]                   
∣1❭:	 0.707107 +  0.000000 i	 == 	***********          [ 0.500000 ]     --- [  0.00000 rad ]
∣2❭:	 0.000000 +  0.000000 i	 == 	                     [ 0.000000 ]                   
∣3❭:	 0.707107 +  0.000000 i	 == 	***********          [ 0.500000 ]     --- [  0.00000 rad ]

1ビット目にもアダマールゲート適用

1ビット目は|1>なので|->になるので、
        // This changes the first qubit into state |-⟩ = (1/sqrt(2))(|0⟩ - |1⟩)
        // The entire system is now in state 0.5(|00⟩ + |01⟩ - |10⟩ - |11⟩)
        H(qs[0]);
\[ \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\ -1 \end{bmatrix} \otimes \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \frac{1}{2}\begin{bmatrix} 1 \\ -1 \\ 1 \\ -1 \end{bmatrix}  \]
となります。
System in state 0.5(|00⟩ + |01⟩ - |10⟩ - |11⟩) = 0.5(|0⟩ + |2⟩ - |1⟩ - |3⟩):
# wave function for qubits with ids (least to most significant): 0;1
∣0❭:	 0.500000 +  0.000000 i	 == 	******               [ 0.250000 ]     --- [  0.00000 rad ]
∣1❭:	-0.500000 +  0.000000 i	 == 	******               [ 0.250000 ] ---     [  3.14159 rad ]
∣2❭:	 0.500000 +  0.000000 i	 == 	******               [ 0.250000 ]     --- [  0.00000 rad ]
∣3❭:	-0.500000 +  0.000000 i	 == 	******               [ 0.250000 ] ---     [  3.14159 rad ]  

量子もつれの生成

ここまではQubitを分解してそれぞれのQubitの状態を変化させテンソル積で複数Qubitの状態を表してきましたが、ここではEntangle状態(分割不可)の状態を作り出します。
1ビットずつの操作ではなく2ビットまとめて操作することでEntangle状態を作り出すことができます。
        // The next lines entangle the qubits.
        // Don't worry about what exactly they do for now
        H(qs[1]);
        CNOT(qs[0], qs[1]);
CNOTゲートはのちのチュートリアルで出てくるのでここでは細かい説明を省略しますが、1ビット目の状態を見て、2ビット目を反転させる処理になります。
Entangled state 0.5(|00⟩ - |11⟩):
# wave function for qubits with ids (least to most significant): 0;1
∣0❭:	 0.707107 +  0.000000 i	 == 	***********          [ 0.500000 ]     --- [  0.00000 rad ]
∣1❭:	 0.000000 +  0.000000 i	 == 	                     [ 0.000000 ]                   
∣2❭:	 0.000000 +  0.000000 i	 == 	                     [ 0.000000 ]                   
∣3❭:	-0.707107 +  0.000000 i	 == 	***********          [ 0.500000 ] ---     [  3.14159 rad ]
この状態はExercise 2で出てきた不可分な状態(量子もつれ状態)ですね。

Exercise 3: Prepare a basis state

デモの内容が理解できれば簡単だと思います。
初期状態は分解可能なので
\( \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} =
\begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix} \) から  \( \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 0 \\ 1 \end{bmatrix} \)
を作り出します。 それぞれのビットを反転させるだけですね。
%kata T1_PrepareState1_Test

operation PrepareState1 (qs : Qubit[]) : Unit is Adj+Ctl {
    X(qs[0]);
    X(qs[1]);
}

Exercise 4: Prepare a superposition of two basis states

ヒントをみて
\[ |0\rangle \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big) = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \end{bmatrix} \]
を作り出すことを理解すればそれほど難しくありません。
2ビット目を\(|-\rangle \)にすればよいので、Xゲート、Hゲートの順に適用します。
%kata T2_PrepareState2_Test

operation PrepareState2 (qs : Qubit[]) : Unit is Adj+Ctl {
    X(qs[1]);
    H(qs[1]);
}

Exercise 5: Prepare a superposition with real amplitudes

この問題もヒントをみて
\[ \frac{1}{\sqrt2}\big(|0\rangle + |1\rangle\big) \otimes \frac{1}{\sqrt2}\big(|0\rangle - |1\rangle\big) = \frac{1}{\sqrt2} \begin{bmatrix} 1 \\ 1 \end{bmatrix} \otimes \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \end{bmatrix} \]
を作り出すことがわかれば簡単です。2ビット目は先ほどのExercise 4と同じなので1ビット目を \(|+\rangle \) にするためにHゲートを適用します。
%kata T3_PrepareState3_Test

operation PrepareState3 (qs : Qubit[]) : Unit is Adj+Ctl {
    H(qs[0]);
    X(qs[1]);
    H(qs[1]);
}

Exercise 6: Prepare a superposition with complex amplitudes

ヒントに書かれていることを導き出すのが難しいかもしれませんが、ヒントがあるのでヒントに書かれていることを実装すればよいです。それぞれ\(|+\rangle \)にSゲート、Tゲートを適用すればよいです。
%kata T4_PrepareState4_Test

operation PrepareState4 (qs : Qubit[]) : Unit is Adj+Ctl {
    H(qs[0]);
    S(qs[0]);
    H(qs[1]);
    T(qs[1]);
}


チュートリアル Single-Qubit Gates解答例

Githubリンク
https://github.com/microsoft/QuantumKatas/tree/master/tutorials/SingleQubitGates

(いきなりこのページに飛んできた人で最初から勉強されたい方はこちらをご参照ください)

このチュートリアルは実際にQ#を使ってQubitの値を操作していきます。古典コンピュータで言うAND, OR, ビットシフトみたいな位置づけだと思いますが、古典コンピュータよりもけっこう複雑ですね。

Exercise 1: The  𝑌  gate

α|0> + β|1>にYゲートを適用します。
これはそのままですね。戻り値はUnitなので何も戻す必要がありません。

%kata T1_ApplyY_Test

operation ApplyY (q : Qubit) : Unit is Adj+Ctl {
    Y(q);
}

Exercise 2: Applying a global phase  𝑖

これも実は本チュートリアルにあるDemoの動き通りですね。
XYZゲートの動きをきちんと理解しましょう。
%kata T2_GlobalPhaseI_Test

operation GlobalPhaseI (q : Qubit) : Unit is Adj+Ctl {
    X(q);
    Z(q);
    Y(q);
}

Exercise 3*: Applying a  −1  phase to  |0⟩  state

XYZゲートの動きを理解して、何を組み合わせれば目的のα=-1とβ=1を導けるかを考えます。
%kata T3_SignFlipOnZero_Test

operation SignFlipOnZero (q : Qubit) : Unit is Adj+Ctl {
    X(q);
    Z(q);
    X(q);
}

Exercise 4: Preparing a  |−⟩  state

前回のQubitで紹介しましたが\( i = \ e^{i\pi/2}  \)なので、Sゲートは\( \pi/2 \)ずつPhaseをずらしていきます。順に適用していくと |+> ⇒ |-> ⇒ |i> ⇒ |-i> ⇒ |+> という順に状態が変化します。こちらを理解していれば簡単です。
まずは|0>から|+>を作るためにHゲートを使用し、あとはシフトさせていきます。
%kata T4_PrepareMinus_Test

operation PrepareMinus (q : Qubit) : Unit is Adj+Ctl {
    H(q);
    S(q);
    S(q);
}

Exercise 5: Three-fourths phase

Phase Shiftゲートの動きを理解しましょう。
%kata T5_ThreeQuatersPiPhase_Test

operation ThreeQuatersPiPhase (q : Qubit) : Unit is Adj+Ctl {
    S(q);
    T(q);
}

理論上は下記でも同等です。
\[ e^{i\pi/4} = \frac{1}{\sqrt{2}} + \frac{i}{\sqrt{2}} \\ e^{i\pi/2} = i \\ e^{i\pi} = -1 \\ e^{2i\pi} = 1 \]
であることを考えると、Tゲート2回とSゲート1回が同等となります。
%kata T5_ThreeQuatersPiPhase_Test

operation ThreeQuatersPiPhase (q : Qubit) : Unit is Adj+Ctl {
    T(q);
    T(q);
    T(q);
}

Exercise 6: Preparing a rotated state


回転系のGateに入って少し雰囲気が変わりますが、R系のGateの定義をきちんと読めばそれほど難しくありません。|0>から目的の\( \alpha|0\rangle -i\beta|1\rangle \)を作り出すためには\( R_x() \)を使います。
今回初めてQ#での変数の代入処理が発生しますが、チュートリアルに書いてある通り、
let num = function();
という形で代入することができます。

%kata T6_PrepareRotatedState_Test

open Microsoft.Quantum.Math;

operation PrepareRotatedState (alpha : Double, beta : Double, q : Qubit) : Unit is Adj+Ctl {
    let theta = ArcTan2(beta, alpha) * 2.0;
    Rx(theta, q);
}

Exercise 7**: Preparing an arbitrary state


次は回転系のゲートの組み合わせです。R系ゲートの定義をきちんと読めば\(R_y\)と\(R_1\)の組み合わせで実現可能なことがわかります。
\( \beta = \sqrt{1 - \alpha^2} \)という書き方をしていますが、\( \alpha^2 + \beta^2 = 1 \)と同義ですよね。何かのヒントなのかもしれませんが意図が理解できてません。

%kata T7_PrepareArbitraryState_Test

open Microsoft.Quantum.Math;

operation PrepareArbitraryState (alpha : Double, beta : Double, theta : Double, q : Qubit) : Unit is Adj+Ctl {
    let theta1 = ArcTan2(beta, alpha) * 2.0;
    Ry(theta1, q);
    R1(theta, q);
}



↑このページのトップヘ