Quantum Katas で始める量子コンピュータ入門 |5⟩: Superdense Coding


## 前書き

本記事では、[Quantum Katas の SuperdenseCoding](https://github.com/Microsoft/QuantumKatas/tree/master/SuperdenseCoding) について解説します。Q# や Quantum Katas って何よという方は [Quantum Katas で始める量子コンピュータ入門 |0⟩](https://qiita.com/stwhabout/items/195b93a194c24ba5fb73) をご参照ください。

これまでには [BasiGates](https://qiita.com/stwhabout/items/4bae12310a5670cab199) や [SuperPosition](https://qiita.com/stwhabout/items/f0df8cb8dd5f1062ec15)で基礎知識を培い、[Deutsch-Jozsa のアルゴリズム](https://qiita.com/stwhabout/items/1e68c6e2ee0605b3cd16) では量子コンピューターの有効性を学んできました。この SuperDense Coding （日本語だと超密度符号化などと訳されるようです）では、量子ビットの特性を活かして**量子ビットを 1 ビット送ると、受信側で古典ビット 2 ビット分の情報が復号できる**という具体的なユースケースを学んでいきます。これまでどう役に立つのかわからなかった量子コンピューターを利用した具体的な応用例が登場します。~~ただし本当に役に立つとは言っていない~~

## 超密度符号化の概要

前書きにも記載した通り、SuperDense Coding とは量子ビットを 1 ビット送れば、古典ビットが 2 ビット復号できるという方式のことを言います。ざっくり言えば以下の手順で実現されます。

1. 送信者である Alice と受信者である Bob が、量子もつれ状態（もっと言えばベル状態）となった量子ビット $q_a$ と $q_b$ を事前に共有しておく。
2. 情報の送信者である Alice は送りたい古典ビット （2 ビット） を利用して量子もつれ状態となった量子ビット $q_a$ を操作し、Bob に $q_a$ を送信する。
3. Bob は $q_a$ と事前に共有していた $q_b$ から、古典ビットを復号する。

Task も上記手順に従って進められます。それでは見ていきましょう。

## 各 Task の解説

### Task 1. Entangled pair

#### 問題

> 入力: 量子ビット $|00⟩$ 

> ゴール: ベル状態 $|\phi^+⟩ = \frac{|00⟩ + |11⟩ }{\sqrt 2}$ を作る。

#### 解説

ここはさすがに楽勝ですね。もう何度もやってきた通りです。

```cs
operation CreateEntangledPair (qs : Qubit[]) : ()
{
    body
    {
        AssertIntEqual(Length(qs), 2, "The array should have exactly 2 qubits.");
        H(qs[0]);
        CNOT(qs[0], qs[1]);
    }
}
```

超密度符号化のシチュエーションでは、この量子もつれ状態となった量子ビットのうち、片方は事前に Bob に送付されているという点に注意してください。

### Task 2. Send the message (Alice's task)

#### 問題

> 入力: 量子もつれ状態となった量子ビットのうち Alice の手元に残った $q_a$、および長さ 2 の古典ビット

> ゴール: 古典ビットに基づいて量子ビットをエンコードせよ。ヒントとして、古典ビットの状態に応じて以下の通りに量子ビットを操作すればよい。
> 
```math
\begin{align}
    [0; 0] \rightarrow &    |\phi^+⟩ = \frac{|00⟩ + |11⟩ }{\sqrt 2} \\
    [0; 1] \rightarrow &    |\psi^+⟩ = \frac{|01⟩ + |10⟩ }{\sqrt 2} \\
    [1; 0] \rightarrow &    |\phi^-⟩ = \frac{|00⟩ - |11⟩ }{\sqrt 2} \\
    [1; 1] \rightarrow &    |\psi^-⟩ = \frac{|01⟩ - |10⟩ }{\sqrt 2}
\end{align}
```

#### 解説

ヒントに思いっきり答えが書いてあるのですが、2 ビットの古典ビットにしたがって現在のベル状態 $|q_a, q_b⟩ = |\phi^+⟩ = \frac{(|00⟩ + |11⟩)}{\sqrt 2}$ を操作すればよさそうです。（ただし、$q_b$ はすでに Bob が持っているので、操作できるのは $q_a$ だけになります。）

これも過去の Kata でやった通りですね。必要であれば [SuperPosition](https://qiita.com/stwhabout/items/f0df8cb8dd5f1062ec15) を参考にしてください。
$\rm bit[1] = 1$ なら $Z$ ゲートで処理して、$\rm bit[0] = 1$ なら $X$ ゲートで処理すればよさそうですね。回答は以下となります。

```cs
operation EncodeMessageInQubit (qAlice : Qubit, message : Bool[]) : ()
{
    body
    {
        if(message[1]) {X(qAlice);}
        if(message[0]) {Z(qAlice);}
    }
}
```

Alice は上記の回路で処理した後、Bob に自分の量子ビット qAlice を送付するわけです。また、ベル状態と古典ビットの対応は送受信側で同意ができていればよいため、必ずしも $(0, 0)$ を $|\phi^+⟩$ で表現する必要はありません。

### Task 3. Decode the message (Bob's task)

#### 問題

> 入力: 事前に共有された Bob の量子ビット $q_b$ と、アリスから受信した量子ビット $q_a$

> 出力: アリスから送付された 2 古典ビットを復号し、Bool 値として出力する。

#### 解説

ここまでくれば概ね察しはついているかもしれませんが、Alice と Bob の量子ビットは 4 つのベル状態のうちいずれかをとるはずなので、これを見分ければよさそうですね。ベル状態を見分ける方法は [Measurement](https://qiita.com/stwhabout/items/d4235b0cfa2f9dffb439) でやった通り、CNOT してからアダマールすればよいのでした。

```cs
operation DecodeMessageFromQubits (qBob : Qubit, qAlice : Qubit) : Bool[]
{
    body
    {
        mutable decoded_bits = new Bool[2];

        CNOT(qAlice, qBob);
        H(qAlice);

        set decoded_bits[0] = BoolFromResult(M(qAlice));
        set decoded_bits[1] = BoolFromResult(M(qBob));

        return decoded_bits;
    }
}
```

1 量子ビットから 2 古典ビットが複合できるということで、密度が倍になったようなものですね。すごいぜ量子コンピューター！

### Task 4. Superdense coding protocol end-to-end

#### 問題

> 入力: 長さ ２ の古典ビット

> ゴール: 量子もつれ状態となった量子ビットを作り、古典ビットに応じてエンコード/デコードする。

#### 解説

これまでの 3 つの Task の総括で、状態の準備、エンコード、デコードをまとめて行うタスクです。
これまでの内容をコピペしてももちろんいいのですが、既に作成した関数を呼び出すほうが楽ちんです。


```cs
operation SuperdenseCodingProtocol (message : Bool[]) : Bool[]
{
    body
    {
        mutable decoded_bits = new Bool[2];
        using(qs = Qubit[2]){
            // Task 1, 量子もつれを作る
            CreateEntangledPair(qs);

            // Task 2, 古典ビットに従ったエンコード実施
            EncodeMessageInQubit(qs[0], message);

            // Task 3, デコードして古典ビットを復号
            set decoded_bits = DecodeMessageFromQubits(qs[1], qs[0]);

            ResetAll(qs);
        }
        return decoded_bits;
    }
}
``` 


## 超密度符号化は本当に使えるのか？

割とわかりやすく有効そうな超密度符号化ですが、これって本当に動作するんでしょうか。上記の超密度符号化を用いて具体的な通信に応用する場合、例えば以下のような方式が考えられます。

1. Alice と Bob は通信を行わない夜間帯などに、通信したいデータ量 $a$ ビットの半分程度の $x=a/2$ 量子ビットを量子もつれ状態にして共有しておく。
2. 通信時、Alice は古典ビットをもとに量子ビット $x_i$ を操作し、Bob に送信する。
3. Bob は量子ビットから古典ビットを復号する。

素人目にも

1. 量子ビットをそれほど長い時間保持しておくのは現実的ではないのでは
2. 量子ビットと古典ビットの送受信を同系列に扱ってしまっている、量子ビットはそう簡単に送付できるものではなさそう
3. 事前に大量の量子ビットを共有しなければいけないので、その送付も大変
4. 事前共有が必要なので、通信相手が限定される
5. 量子エンコード・デコードの処理を行う遅延が、通信効率の改善を上回るように思えない
6. お金的な意味では超大変そう

といった問題点が思いつきます。（いずれも根拠まで調べられていませんが。）例えば超機密性/超緊急度の高い 2 点の組織間で採算度外視でなら実用的か・・・みたいな妄想もしましたが、であれば回線増設したり専用線引いたほうがよっぽどいいですよね。。。

新しい技術は得てして否定されやすいものではあるので、超密度符号化も私のような素人の懸念をさっくりと払拭していただきたいものですね。

## まとめ

この Kata は比較的短かったですが、超密度符号化という具体的なユースケースについて学びました。次回は決めていませんが、残りのどれかでお会いしましょう。