RISC-Vの量子計算拡張

こんにちは｜こんばんは。カエルのアイコンで活動しております @kyamaz です。
本稿は、[量子コンピュータ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/quantum)の17日目（2018年12月17日）のエントリ記事です。

##### わずか１年前の話し

2017年3月「Google Plans to Demonstrate the Supremacy of Quantum Computing[*](https://spectrum.ieee.org/computing/hardware/google-plans-to-demonstrate-the-supremacy-of-quantum-computing)」にあるように、Google は2017年末までに、49量子ビットの量子コンピューターチップを開発し、世の中にお披露目するとしていました。
ちょうど去年（2017年）の今ごろ、私たちがこの[アドベントカレンダー2017](https://qiita.com/advent-calendar/2017/quantum)の枠が埋まらなくて必死でエントリを書き繋いでいたときも、Google の掲げた目標を信じて、期待しながら待ちわびていたのを思い出します。しかし、その夢は叶わず、遂に49量子ビットのチップは2017年末までにはリリースされませんでした。
その裏側には、...

IBM が、2017年10月にarXivに投稿した「Breaking the 49-Qubit Barrier in the Simulation of Quantum Circuits[*](https://arxiv.org/abs/1710.05867)」により、それまで「量子コンピューターを古典コンピューターでシミュレートできない限界値」が49量子ビットであると考えられていたことに異論を唱えたことを皮切りに、IBMと中国の研究チーム[^4]による限界値の引き上げがあったことも影響があったかもしれません。

そして、2018年に入って Google 自らがその限界値のハードルを上げて、72量子ビットを開発することを公表しました。そのあと間もなく 2018年3月には「Google Takes Aim at Quantum Supremacy with 72-Qubit Chip[*](https://www.top500.org/news/google-takes-aim-at-quantum-supremacy-with-72-qubit-chip/)」という記事がでて、72量子ビットのチップが製造されたと発表されたのです。これを機に量子コンピューターの凄さがアピールされ、さらに熱を帯びると思われました。しかしながら、その後は目を見張る（つまり、いわゆる量子超越性“quantum supremacy”を示す）成果が学会等で発表されることもなく[^1]、2018年が終わろうとしております。

72量子ビットの量子コンピューターチップ「BristleCone」には、少し期待外れに終わったこの２年間でした。ただ裏を返せば、Google をもってしても高精度の量子コンピューターの開発は困難であることを物語っています。または未来に楽しみが残ったともいえます。近い将来のどこかで、皆さんとともに “_量子コンピューターが量子超越性を達成した_” というニュースリリースに触れられる日を楽しみにしたいと思います。

そんな中、既にIBMやRigetti、アリババが NISQ[^2] 世代の量子コンピューターをクラウドサービス[^3]として私たちに提供しています。今私たちが使えるこれらの量子コンピューターは、量子計算をするにはノイズが多くて、役立つ量子アルゴリズムを動かせる程の精度も規模もないものです。それでも、私たちが書いたプログラムで、量子コンピューターに計算させることができるのは、ITエンジニアにとっては幸せな環境が整ってきていると思います。

そこで、私たちITエンジニアは、来たる量子コンピューターを利用する時代に向けて色々と技術を習得したいと思うでしょう。しかし、現在の量子コンピューターは既にある学べる技術ではなく、これから「技術を創造する」段階にあるのです。本日は、そんな未成熟な量子コンピューターの話しをしたいと思います。

**_注意事項_**
_本記事は、未だ一般的ではない技術について筆者の独自の見解で書かれており、量子コンピューターに関する提案として掲載します。どちらかというと筆者が運営しているコミュニティ活動で取り組んでいる技術面での悩みを打ち明けた内容になっております。
今後の量子コンピューター関連の方向性の一つとして「こんな考え方もあるのかなぁ？」とご覧いただくのがよいと思います。もし、本記事で取り上げる課題をより良い形で解決して頂けるエンジニアさんがいらっしゃれば嬉しいです。_
なお、本記事の対象は、次のような方を想定しております。

- 量子コンピューターや量子プログラミングに興味がある方
- コンピューターアーキテクチャの知識がある方
- 量子コンピューターの仕組みや計算方法をなんとなくご存知の方

---
さて、だいぶ前置きが長くなりましたが、本題をはじめます。宜しくお願いします。

日経BP社から出版されました「RISC-V原典 オープンアーキテクチャのススメ[*](https://www.amazon.co.jp/dp/4822292819/)」や CQ出版の Interface誌で 2018年2月号から「オープンソースCPU「RISC-V」の研究[*](http://msyksphinz.hatenablog.com/entry/2017/12/27/020000)」というタイトルで特集が組まれたりしましたので、今年（2018年）に入って「<font color="red">RISC-V（リスク ファイブ）</font>」という言葉を知った方も多いと思います。

そこで、[WikiにあるRISC-V](https://ja.wikipedia.org/wiki/RISC-V) の情報を見ながら、その特徴を整理してみましょう。

* RISCアーキテクチャの設計思想に基づくシンプルな命令セット・アーキテクチャ (ISA)
* ISAは、ハードウェアとソフトウェアの中間に存在するコンピューターの中心的役割
* 非営利団体「RISC-V Foundation」が管理しているオープンな標準仕様
* オープンソースライセンスであるBSDライセンス下で提供することを目指している
* “基本命令”とそれに付随する“拡張命令”によって構成される

ここで「“基本命令”とそれに付随する“拡張命令”」について補足しておきましょう。“基本命令”の種類は、次の4種類が定義されています。

   - RV32I（32ビット・アドレッシング、整数命令）
   - RV32E（32ビット・アドレッシング、組み込み向け命令）
   - RV64I（64ビット・アドレッシング、整数命令）
   - RV128I（128ビット・アドレッシング、整数命令）

この基本命令セットにそれぞれ、拡張命令が付随的に定義されていて、記号では M、A、F、D、Q、L、C、B、J、T、P、V、N で表されています。例えば、"F"は単精度浮動小数点命令、"D"は倍精度浮動小数点命令、"V"はベクター拡張という具合に、拡張される計算命令の特徴に応じた命令群が定義されています。

詳しくは、RISC-V Foundationのウェブサイト「[riscv.org](https://riscv.org/)」に、ISAの仕様書が掲載されています。2018年12月現在の最新版は、ユーザレベルISA が Ver.2.2、特権レベルISA が Ver.1.10 です。

<font color="red">この RISC-V の定義は Haskell で書かれています。</font>
Interface誌で記事を執筆された msyksphinz さんもご自身のブログ「[FPGA開発日記](http://msyksphinz.hatenablog.com/)」で取り上げられており、そのエントリ「[RISC-V仕様のFormal表現いろいろ](http://msyksphinz.hatenablog.com/entry/2018/05/12/040000)」に詳しく書かれております。正式な定義は、riscv-semantic (https://github.com/mit-plv/riscv-semantics) に実装があり、MIT Programming Languages & Verification Group から公開されています。

この MIT に習って、以降では Haskell を扱いたいと思います。ただ、本家の MIT の定義を取りあげるのは少し難しいので、本稿では亜流ではありますが Hackage に登録されている [riscv-isa](https://hackage.haskell.org/package/riscv-isa) を使って本題の量子計算拡張の話しを進めたいと思います。

それでは詳しく踏み込んでみましょう。この`riscv-isa`には、32ビット・アドレッシング、整数命令である`RiscV.RV32I`が定義されております。ここに、量子計算拡張を追加することを考えましょう。拡張ですから、前述の“拡張命令”としてその拡張部分だけを議論していけばよさそうです。まずは、この拡張の記号を考えましょう。量子を示すのに都合がよさそうなQuantumの頭文字「Q」は「４倍浮動小数点」として予約されていますので使えません。そこで量子計算に欠かせない「ユニタリ」を表す「U」の記号を当てるのが良さそうです。本稿では、量子計算拡張は「U」として提案しましょう。

## RISC-Vの量子計算拡張「U」を考える
さて、`RiscV.RV32IU`の定義にとりかかります。
量子計算の基本に立ち返ります。量子計算プロセッサー（Quantum Processing Unit：QPU）の量子計算の基本となる要素は次の３つになります。

||QPUによる量子計算の基本３要素|
|:--|:--|
|（１）|「量子ビットを準備して初期化する」|
|（２）|「ユニタリ演算子を準備して量子ビットに作用する」|
|（３）|「量子ビットを測定する」|

この３要素を拡張命令として定義できれば、量子計算拡張が叶うはずです。慌てずに一つずつ定義していきます。

### 量子レジスタ
まず最初に「量子ビットを準備して初期化する」を考えます。RISC-Vでは、扱うビット長に応じてアーキテクチャを考えるようになっており、例えば`RV32I`であれば、32ビットを一塊りとして１つのレジスタとして考えます。これと同じように、量子計算拡張でもある個数の量子ビットを塊りとしてみて、それを「量子レジスタ」と呼びます。この量子レジスタは、いくつかの量子ビットが集まっていますので、この個数に応じて、種類があると考えても良さそうです。ここでは、RISC-Vのビット数に合わせた個数の３２量子ビット[^5]が１量子レジスタであるとして`RV32IU`を定義しておきます。Haskellの定義は、古典レジスタと同様に、次のようになります。（実際のコードでは、古典レジスタもビット数は明示されないで定義されています。量子レジスタもそれに習い、量子ビット長はコード内にはでてきません。）

```
data QRegister
  = Q0
  | Q1
--| Q2 | Q3 | Q4 | ... とRV32IUに必要とする数だけ QRegister を定義します
  deriving (Show, Eq, Ord)
```

この量子レジスタは、どれくらいの数が必要かはわかりませんが、定義するだけであれば、ある程度の個数だけ定義することができます。この量子レジスタの個数も`RV32IU`の仕様には関わってきますが、ここでは `Q0` と `Q1` の２つの量子レジスタがあるQPUを想定しておきます。
なお、レジスタを考えるときに、古典コンピューターでは「レジスタのビット数」と「レジスタの個数」がその計算能力がスケールするための重要なファクターでした。量子コンピューターでもこの考え方は恐らく同じように当てはまると思います。しかし、量子ビットのデバイス実装は困難なもので、当面は多くの量子ビットを搭載しているモデルを考えない方がよいかもしれません。例えば総数で６４個の量子ビットが搭載されたデバイスができたとすると、それを３２量子ビットの量子レジスタを２個として使うか、６４量子ビットの量子レジスタを１つとして使うかはアーキテクチャ設計では重要です。ただし、より役立つ量子アルゴリズムを動作させるには、６４量子ビットの量子レジスタを１つの方が嬉しいと思われます。量子計算拡張「U」では、そういった量子プログラミングや量子アルゴリズムの都合も加味した設計が求められることになるでしょう。
これで量子ビットは準備できましたが、それを「初期化する」操作も必要です。「初期化する」操作は、次の量子レジスタに対する演算命令と並べておくことにします。（もう少し吟味するべきですが）仮に「QLEAR」とでもしておきます。

### ユニタリ演算を表す命令セット
次に「ユニタリ演算子を準備して量子ビットに作用する」を考えます。ユニタリ演算子は量子ビットに作用するので、１つの量子レジスタに作用することを考えればよいでしょう。１量子レジスタに対する命令セットとして`QRegisterInstr`型を定義します。この引数は、対象となる`QRegister`とユニタリ演算子`QOpecode`と演算子の制御のために対象のビット位置などを表す古典レジスタ`CSRegister`があれば、ひとまず十分だと思います。そこで、`QRegisterInstr`の定義は次のようにします。

```
data QRegisterInstr =
  QInstr !QOpcode
         !CSRegister   -- Control and Status Classical Register
         !QRegister
  deriving (Show, Eq, Ord)
```

任意のユニタリ行列を考えるときに、Solovay-Kitaevの定理[^6]という性質を使うと、必要な演算子の数を抑えられます。この定理を使うと、任意のユニタリ行列を近似的に表せる必要最低限の量子ゲートは、アダマールゲート、π/8 ゲート、制御NOTゲートの３つでよいことになります。そこで、ユニタリ演算子である`QOpecode`は、前出の`QLEAR`に加え、この３つのゲートを定義します。

```
data QOpcode
  = QLEAR   -- 量子ビットの初期化
  | HADAM   -- アダマール(Hadamard)ゲート
  | TGATE   -- π/8 ゲート（またの名は Tゲート）
  | CNOT    -- 制御NOTゲート（２量子ビット演算）
  deriving (Show, Eq, Ord)
```
ただし、Solovay-Kitaevの定理[^6]に従って任意のユニタリ行列が、上記の３つのゲートに分解できるとしても、その分解された量子ゲート数は非常に多くなる可能性があります。演算子の数を軽減するためには、必要最低限の種類を提供するだけよりは、他のユニタリ操作も使えるように定義しておいた方がよいかもしれません。候補としては、次のような１〜３量子ビット演算までの量子ゲート操作があると良いかもしれません。（これらを追加すると制御用のビット数も足らない可能性もあり、それに応じて`CSRegister`の引数を増やす必要があるかもしれません。）

```
data QOpcode
  = QLEAR
  | HADAM
  | TGATE
  | CNOT    -- ここまでの３つ(HADM,TGATE,CNOT)があれば十分？
  | PAULIX  -- パウリ演算子、Xゲート
  | PAULIY  --              Yゲート
  | PAULIZ  --              Zゲート
  | ROTX    -- X軸回転ゲート
  | ROTY    -- Y軸回転ゲート
  | ROTZ    -- Z軸回転ゲート
  | PHASE   -- 位相ゲート
  | SWAP    -- SWAPゲート（２量子ビット演算）
  | CPHASE  -- 制御位相ゲート（２量子ビット演算）
  | CSWAP   -- 制御SWAPゲート（３量子ビット演算）
  | TOFF    -- Toffoliゲート（３量子ビット演算）
  deriving (Show, Eq, Ord)
```
ここで原点に立ち返ってみると、RISC-V の古典的なISAの定義では、ビットに対しての演算命令よりも複数のレジスタに対する演算命令が主に定義されています。量子計算拡張を考えると、`RV32IU`でも複数の量子レジスタに対する量子演算命令を主に考えたくなります。しかし、現時点では、量子ビットに対する演算命令しか考えられていないです。例えば、古典レジスタと同様に、量子拡張でも加算器 ADD が２つの量子レジスタで定義もできます。量子計算拡張では、２量子レジスタ間の量子演算`QRegisterQRegisterInstr`型を定義することも可能なのでしょう。ただ、それがどのような具体的な計算となり、果たして量子計算の特性を生かして役に立つ計算となるか。それを吟味するには、まだ時期尚早なのかもしれません。ですから本稿では、命令セットの拡張は量子ビット演算のみに留めておきます。

### 測定を表す命令セット
最後に、量子計算の基本３要素の「量子ビットを測定する」です。
測定は、上記の`QRegisterInstr`として同じように扱うことはできません。なぜなら、`QRegister`内を測定すると、その値が確定してしまいます。その確定した値を読み出して、古典レジスタ`Register`へ情報を移す必要があるからです。つまり、`QRegisterInstr`とは違う`QMeasurementInstr`型を定義することを考えなければなりません。測定も恐らく制御レジスタを使うでしょうから、引数に`CSRegister`も含めて次のような定義とします。

```
data QMeasurementInstr =
  MEASURE !CSRegister   -- Control and Status Classical Register
          !QRegister
          !Register
  deriving (Show, Eq, Ord)
```

この定義も一概にこれで良いのかは悩ましく、下記のように`CSQRType`とタイプを表す識別子を追加した方がよいかもしれません。この方が「測定」だけでない他の操作を扱えるため、汎用性がありそうです。この辺りどのような定義がよいかも、今後の検討が必要になってくることでしょう。

```
-- | Control and Status QRegister instruction type
data CSQRType
  = MeasureOneQubit
  | MeasureAll
  deriving (Show, Eq, Ord)

-- | Control and Status QRegister Instructions
data CSQRInstr
  = CSQRInstr !CSQRType
              !CSRegister   -- Control and Status Classical Register
              !QRegister
              !Register
  deriving (Show, Eq, Ord)
```
以上で量子計算の基本３要素の定義ができました。

#### 終わりに
皆さんと悩みながら見てきた通り、QPUを扱うためのコンピューターアーキテクチャは、現在何も決まっていないことを、感じ取って頂けたでしょうか。もし、感じ取って頂けたとすれば、本稿の目的は達成できたと思います。すなわち、現在の量子コンピューター技術は、これから「技術を創造する」段階にあります。創造する喜びを知っているエンジニアの皆さんには、このようなフワフワとした状況を楽しんで頂きながら、その技術力を試して頂く分野として「量子計算」の分野を開拓して頂けると嬉しいです。

本稿はここまでです。最後まで読んで頂きましてありがとうございます。
[量子コンピュータ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/quantum)は、昨日は |つじしん〉@tsujishin さん、明日は @ohtaman さんです。OpenQL Project を支えて頂いている仲間とリレーが続けられて嬉しいです。
（●）（●）
/""　＿＿""＼ @kyamazは、オープンソース・コミュニティを通じて、皆さんと共に新しい技術に挑戦していきたいと考えております。[^11]どうぞ宜しくお願いいたします。

May your Christmas wishes come true!
May happy Quantum Computer world has come!

[^1]: 72量子ビットの量子チップは製造されたものの、検証が続いているものと思われます。噂によると、動作が難しいのはさまざまな"defect"の存在により、わずかながら精度が目標に達していないようです。
[^2]: NISQ（Noisy Intermediate-Scale Quantum Computer）：ノイズが大きくて、50〜100量子ビット程度の中規模の量子ビットサイズな量子コンピューター
[^3]: [IBM Q Experience](https://quantumexperience.ng.bluemix.net/)、[Rigetti Quantum Cloud Services](https://www.rigetti.com/qcs)、[アリババクラウド](http://quantumcomputer.ac.cn/) で利用可能です。
[^4]: https://arxiv.org/abs/1802.06952
[^5]: 本稿では、現実の量子コンピューターがその量子ビット数を実現できているかは議論しません。もしかすると、本稿で考えているよりも少ない量子ビットを１量子レジスタとするべきかもしれません。また、ここでの量子ビットは、プログラムからノイズを気にしないで使えるべく、エラー訂正でノイズを取り除いたエラー耐性のある高精度な量子ビットを集めていることとします。
[^6]: 詳しくは、Quantum Computation and Quantum Information（Nielsen, Chuang）で勉強できます。
[^11]: オープンソース・コミュニティ「OpenQLプロジェクト」[^12]では、コミュニティのなかで議論・検討しながら「量子プログラミング言語」や「量子コンパイラ」を開発していこうという活動をしております。
[^12]: OpenQLプロジェクトは、量子コンピューターを扱うための様々なライブラリを開発するためのオープンソースプロジェクトです。量子情報、量子コンピューターに興味がある人たちが集うコミュニティを運営しております。詳しくは[connpassのサイト](https://openql.connpass.com/)をご覧ください。