Microsoft Quantum Development Kit および量子プログラミング言語Q#の解説

## Microsoft Quantum Development Kitって？
+ Microsoftの量子プログラミング用のフレームワーク
+ 今週(12/12)リリース
+ 後半のスライドは長いのでスライドモードで見ない方がいいかも

---

## 内容物
量子プログラミングを行うための環境一揃い

+ 量子プログラミング言語 Q#
+ シミュレータ
+ デバッグ（Visual Studio拡張）

（量子コンピュータの実物はまだ）

---

## 量子プログラミング言語 Q# 
量子コンピュータのコントローラ用言語と考えると分かりやすい
![図.png](https://qiita-image-store.s3.amazonaws.com/0/11714/736a8e13-059f-5fd9-1f8a-0d00ab263468.png)

--- 

## 量子プログラミング言語 Q# 
量子ビットを操作する量子デバイスに（古典コンピュータの）コントローラを接続して制御する
![図.png](https://qiita-image-store.s3.amazonaws.com/0/11714/736a8e13-059f-5fd9-1f8a-0d00ab263468.png)

---  

## 量子プログラミング言語 Q# 
コントローラは量子デバイスに対し，命令を送ったり測定結果を受け取ったりする
![図.png](https://qiita-image-store.s3.amazonaws.com/0/11714/736a8e13-059f-5fd9-1f8a-0d00ab263468.png)

---

## 量子プログラミング言語 Q# 
コントローラの動作をプログラムすることで量子プログラミングする→Q#
（『量子プログラミングの基礎』における古典的制御を持つ量子プログラム）
![図.png](https://qiita-image-store.s3.amazonaws.com/0/11714/736a8e13-059f-5fd9-1f8a-0d00ab263468.png)

---

## 簡単なQ#のプログラム

```csharp
namespace Quantum.Bell
{
    open Microsoft.Quantum.Primitive;
    open Microsoft.Quantum.Canon;

    operation MakeBellState(x: Qubit, y: Qubit) : ()
    {
        body
        {
            H(x);
            CNOT(x, y);
        }
    }
}
```

+ C#とF#の合いの子
+ `operation`で量子操作を定義する．`function`を使えば古典的な関数も定義できる．
+ `body`の中に量子操作を書く．
+ 型は後置（`Qubit`が量子ビット型，戻り値型が空のタプル型`()`）
+ `H(x)`, `CNOT(x, y)`と量子ビットに量子ゲートを作用させる
+ この量子操作はベル状態（`|00> + |11>`）という2つの量子ビットが重ね合わさった状態を作る

---

## 少し複雑なQ#のプログラム

```csharp
namespace Quantum.Bell
{
    open Microsoft.Quantum.Primitive;
    open Microsoft.Quantum.Canon;

    operation MeasureBellState(count: Int) : (Int, Int, Int)
    {
        body
        {
            // カウンタ変数の初期化
            mutable zero = 0;  // 測定して0が出た回数
            mutable one = 0;   // 測定して1が出た回数
            mutable match = 0; // 両方の測定が同じ値を返した回数

            // count分試行を繰り返す
            for (step in 1..count)
            {
                // |0>で初期化された量子ビットを2つ確保
                using (qubits = Qubit[2])
                {
                    // 各量子ビットを変数に束縛
                    let x = qubits[0];
                    let y = qubits[1];

                    // 2つの量子ビットをベル状態(|00> + |11>)にする
                    MakeBellState(x, y);

                    // それぞれの量子ビットを{ |0>, |1> }の基底で測定
                    let xResult = M(x);
                    let yResult = M(y);

                    // |0> が出たとき
                    if (xResult == Zero)
                    {
                        set zero = zero + 1;
                    }
　　　　　　　　　　　// |1> が出たとき
                    else 
                    {
                        set one = one + 1;
                    }

                    // それぞれの量子ビットから同じ測定結果が得られたとき
                    if (xResult == yResult)
                    {
                        set match = match + 1;
                    }

                    // 量子ビットの解放前に|0>にリセットする
                    if (xResult == One)
                    {
                        X(x);
                    }
                    if (yResult == One)
                    {
                        X(y);
                    }
                }   
            }

            return (zero, one, match);
        }
    }
}
```

+ 変数宣言は`let`（不変）と`mutable`（可変）
+ 変数の方は初期化子から推論
+ 繰り返しは`for`文と`repeat..until`文
+ `using`文でクリーンな（`|0>`で初期化された）量子ビットの確保を行う
    + 量子デバイスに量子ビットを確保するように指示すると考えよう
    + 繰り返し使えるようにするため，使用した量子ビットは解放（`using`文の終了）前に`|0>`にリセットする必要がある
+ `MakeBellState(x, y);`で1スライド前の量子操作を呼び出し，ベル状態を作っている
+ `M(x)`，`M(y)`が測定操作
    + デバイスに測定を指示し，結果を受け取る
    + 測定結果は`Result`型で`Int`ではない
+ その後の`if`文で測定結果に応じて`zero`, `one`, `match`を更新
    + `mutable`変数の変更には`set`文を使う
+ `return`で`zero`, `one`, `match`の3要素からなるタプルを返している

---

## シミュレーション

+ Q#で書いた量子プログラムを.NET上でシミュレーションすることができる
    + 公式ではC#かF#を使っている
    + VB.NETも使える

---

## シミュレーションコード

```csharp
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;

namespace Quantum.Bell
{
    class Driver
    {
        static void Main(string[] args)
        {
            using (var sim = new QuantumSimulator())
            {
                var (zero, one, match) = MeasureBellState.Run(sim, 100).Result;
                System.Console.WriteLine($"zero : {zero}");
                System.Console.WriteLine($"one  : {one}");
                System.Console.WriteLine($"match: {match}");
            }
        }
    }
}
```

+ `QuantumSimulator`がシミュレータの.NETクラス
+ Q#の`operation`は同名の.NETクラスにコンパイルされ，`Run`メソッドにシミュレータと引数を渡すことで実行できる

--- 

## 実行結果

![2017-12-13_22h10_16.png](https://qiita-image-store.s3.amazonaws.com/0/11714/bcad59a3-fd2c-6970-ec8c-fa7dc02c22f3.png)

+ `M(x)`によってベル状態`|00> + |11>`から`|00>`と`|11>`のどちらか片方が選びだされ，測定結果は`0`と`1`がそれぞれ50%ずつ出てくる
    + 出力の`zero`と`one`の比率も大体50:50
+ 一方，`|00>`と`|11>`のどちらにせよ1ビット目（`x`）と2ビット目（`y`）の値は等しい
    + `match`は必ず100になる

---

## デバッグ（Visual Studio拡張）
+ Q#はVisual Studioにシンタックスハイライトがある
+ アサーション用の関数がある
+ ユニットテストが書けるらしい
+ Visual Studioのデバッガに対応
    + ブレークポイントをQ#内に挟める
    + ステップ実行できる
    + 量子ビットの中身を見たりとかは現状無理そう
    + 古典アルゴリズム部分のデバッグはできる

---

## デバッガのスクリーンショット

![2017-12-13_22h19_46.png](https://qiita-image-store.s3.amazonaws.com/0/11714/5e9f809b-6594-351c-265a-5667e8dde10b.png)

---

量子プログラミングやっていきましょう！
===