Scala
DSL
量子コンピュータ
ブラケット
ScalaDay 4

Scalaでも量子計算がしたい! 〜のでブラケット演算のDSLを作ってます〜

量子コンピュータの話題がアツいですね!
MicrosoftのYouTube PVでは「10億の並行宇宙で走るコンピュータによって解くべき問題とは?」なんて煽り文句まで飛びだして、おまえは何を言っているんだ感ありますが、実際、従来のコンピュータとは計算モデルからして異なるものです。

たとえば、アダマールゲートという回路があるのですが、これはブラケット記法を使うと次のように表せます。

\newcommand{\bra}[1]{\left\langle #1 \right|}
\newcommand{\ket}[1]{\left| #1 \right\rangle}
\newcommand{\bracket}[2]{\left\langle #1 \middle| #2 \right\rangle}
H = \frac{\ket{0}\bra{0} + \ket{0}\bra{1} + \ket{1}\bra{0} - \ket{1}\bra{1}}{\sqrt{2}}

$\bra{\ \ }$ がブラで、 $\ket{\ \ }$ がケット、二人掛け合わせてブラケット $\bracket{\ \ }{\ \ }$ ってなもんで、

\bracket{0}{0} = 1 \\
\bracket{1}{1} = 1 \\
\bracket{0}{1} = 0 \\
\bracket{1}{0} = 0

異なる基底を掛けるとゼロになって消えちゃいます。ばよえ〜ん
さて、先ほどのアダマールゲートに量子ビット $\ket{1}$ を適用してみますと、

\begin{align}
H \ket{1}
&= \frac{\ket{0}\bracket{0}{1} + \ket{0}\bracket{1}{1} + \ket{1}\bracket{0}{1} - \ket{1}\bracket{1}{1}}{\sqrt{2}} \\
&= \frac{\ket{0} - \ket{1}}{\sqrt{2}}
\end{align}

となって、めでたく量子ビット $\ket{0}$ と $\ket{1}$ の重ね合わせ状態になります。
重ね合わせ、それはロマン。あるいは、猫が生きている宇宙と猫が死んでいる宇宙が同時に存在する、なんて日本語でおkな説明をされるやつです。やりましたね。

さて、 $1$ 量子ビットの計算であれば $2$ 個の基底で表現できるのですが、 $n$ 量子ビットの計算となると $2^n$ 個の基底が必要となり、式もどんどん複雑になって手計算やってられっかという気持ちになります。
目の前に量子コンピュータがあればソレに計算させればいいじゃんという話もあるのですが、量子状態は確率的にしか測定できないお茶目なやつなので、やはり量子回路組む前にブラケット記法でゴリゴリ計算しておきたいところではあります。
ということで、普通の古典計算機でコーディングしちゃう? わけなのですが、私たちは数式っぽく書きたい…でしょう?

となると、シンタックスに自由がありつつ、硬めの計算もできる言語が良さそうです。こんなこともあろうかと、オブジェクト指向で関数型なスクリプト言語Scalaを使えば——

 
これが、

H = \frac{\ket{0}\bra{0} + \ket{0}\bra{1} + \ket{1}\bra{0} - \ket{1}\bra{1}}{\sqrt{2}}

こうなって、

val h = ( |(0).> * <(0).| + |(0).> * <(1).| + |(1).> * <(0).| - |(1).> * <(1).| ) / √(2)

こうじゃ( ^ω^)

> println(h * |(1).>)

+0.7071 |0> -0.7071 |1>

 

え、丸括弧とドットが余分ですって。ま、マクロを使ってみては?
ともかく、このくらいで良しとする人生ならば、ブラとケットの定義は簡単です。わぁいケースクラス あかりケースクラス大好き。

case class <(i: Int) extends AnyVal {
  def | = SparseMatrix(Map(0 -> Map(i -> 1)))
}

case class |(i: Int) extends AnyVal {
  def > = SparseMatrix(Map(i -> Map(0 -> 1)))
}

Scalaって、クラス名とか関数名に < | > 使えるんですね。
コンパイル通ってビビりました(ぉぃ

さて、実は。ブラやケットは行列でも表すことができて、されば SparseMatrix を実装すればってなもんで、それは Map[Int, Map[Int, Complex]] をラップすれば良さそうで、Hey Yo、行列は行列でも複素行列なので Complex も必要で、その値は 0.1 + 0.2 i みたいに書きたくって、行列の演算は足し算や掛け算だけじゃなくてクロネッカー積なるものも欲しく、はたまた行列を安全に計算するためには Seq[Seq[Complex]] で長さも型情報に埋めこんだ方がいいなんて話もあって、量子回路の適用はパイプラインでやりたい気もしてきて、アーッお客様困ります要望が多すぎて実装がアーッ、でもScalaなら?

……という話を、ScalaMatsuri 2018でしたい、です! ので応募しました。
なんと今年は参加者の投票はもちろんのこと、下記リンク先のセッションページをSNSでシェアしてもらうことでも、発表確率が高まっていく仕組みです。 \カワイイ/

量子コンピュータをScalaでかわいくシミュレーションしてみよう♪