Python
量子コンピュータ
量子力学
量子ゲート
QISKIT

量子コンピュータと量子計算のまとめ

量子コンピュータと量子計算のまとめ

$$
\def\bra#1{\mathinner{\left\langle{#1}\right|}}
\def\ket#1{\mathinner{\left|{#1}\right\rangle}}
\def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}\\
$$

1.はじめに

1.0リンク

初学者や数式を読みたくないという人やさらっと読みたい人向け
量子コンピュータの初歩の初歩
量子情報科学:理論系記事など
「本ブログ」

1.1注意

僕自身も勉強し始めて日が浅いため、誤っている箇所が多々あると思います。鵜呑みにはせず、詳しくは参考文献などを参照ください。誤りなどがありましたら指摘していただけると幸いです。わからない部分があると思いますがその責任は全て僕にあります。指摘していただけると助かります。
今後線形代数やテンソル積などの知識がなくても理解できるよう補足を追加して行こうと考えています。

1.2この記事でできるようになること

・量子情報の基礎と量子計算の理解。
・qiskitを使って量子ビットに対する演算の初歩の初歩ができるようになる。

1.3用意するもの

・mac pc
・python 開発環境(python 3.5以上)

1.4前提知識

・pythonの簡単なスキル
・線型代数学の知識

2.量子情報の基礎

2.1古典系と量子系

 自然科学におけるとは全宇宙のうち、考察の対象とする一部分のことを言います。ミクロな物体を扱う物理学である量子力学の効果が現れてくる系のことを量子系と呼びます。
 一方で、量子力学の効果が現れないマクロな系を古典系と呼びます。古典系のもとでの物や現象、学問を「古典○○」と呼びます。一方で量子系のもとでのものや現象、学問を「量子○○」と呼びます(古典コンピュータと量子コンピュータ など)。
 量子系で情報を処理するとき量子情報処理と呼ぶことにします。一方で古典系で情報処理をするとき古典情報処理と呼ぶことにします。古典情報処理では、情報はよく知られるように$\{0,1\}$で表現されます。例えば、情報の保存では、以下のような記憶素子が存在しています。

1.磁力のS極かN極かで0,1を対応させて情報を表現(磁気ディスク...)
2.コンデンサに十分な電荷があるかないかで0,1を対応させて情報を表現する(DRAM...)
3.電圧があるかないかで0,1を対応させて情報を表現する(レジスタ...)

など...

 計算では、レジスタから値を読み出し、電気電子回路で構成された論理回路を通して、足し算などの演算を二進数で行います。
 一方で、量子情報処理ではどうなるか...?
 それは後ほど記述するとして、まずは、情報処理の根幹のアイテム「ビット」を古典系と量子系のそれぞれに対して定義していきましょう。

2.2古典ビット

 古典系での情報(普通のコンピュータで)は古典ビットによって表現されます。古典ビットを数学的に定義してみようと思います。

(定義2.2.1 古典ビット)情報を$\mathbb{F}_2^n$の元に対応させたとき、n-古典ビット系と呼ぶ。通常$\mathbb{F}_2^n$は集合を$\{0,1\}^n$とし、加法演算は論理和、乗法演算は論理積として定義する。$\square$

難しく書きましたが、単純に0と1で情報を表現すると表現してもらって構いません。一般には、簡略してn-古典ビットは1010..11のように記述します。

(定義2.2.2 nビット系による四則演算の表現)古典情報処理において、二進数の四則演算は、$f:\mathbb{F}_2^n\times \mathbb{F}_2^n \to \mathbb{F}_2^n$として定義される。$f$はそれぞれ論理和と論理積によって定義される関数である。$\square$

このような$f$は実際の論理演算を用いて構成することができます(半加算器や全加算器などを参照)。これを見るとわかるように、基本的に古典ビットにおける論理演算はは非可逆的であることがわかります。
 上記の定義よりも例の方が簡単なので、例を見ていきます。

(例2.2.3)2+4を行うときは、以下のように0と1に置き換える。

$$010+100$$

二進数の加算は、

$$110$$

となる。$\square$

2.3量子ビット

 量子ビットの登場です。量子ビットは古典ビットとどう違うのでしょうか?
よく量子ビットは「0と1を同時に表すことができる」という説明がなされます。何も知識が無いと「古典ビットの1-ビットのような所に0,1のどちらも詰まっているみたいな感じだろうか?」などと考えてしまいます。しかしながら、数学的な性質を見てみることによって、以下の点がわかってきます。
$$1.量子ビットはベクトルである。$$
$$2.量子ビットはベクトルであるがゆえに重ね合わせることができる$$
ということが結論づけられます。今の段階では、詳しい意味がわからないと思うので、数学的に定義していくことにします。ちなみにここから量子力学独特のベクトルに関する記法ブラケットを使います。

(定義2.3.1 1-量子ビット)2次元複素ベクトル空間の単位ベクトル、すなわち
$$\left\{\ket{\psi}\mid||\psi||=1,\ket{\psi}\in \mathbb{C}^2\right\}$$
1-量子ビット系と呼ぶ。また、元を1量子ビットと呼ぶ。$\square$

集合の基礎がわかっている方の場合、上記の記号はわかると思います。ただ慣れていないような方は、下記の単位円上の点のすべてが1-量子ビットだと思ってもらえればいいです(ただし、下記の図は二次元の実数の空間であり、実際は複素数の単位円上の点となります)。

unitcircle.png

次に、同様にしてn-量子ビット系、すなわちn-古典ビット系に対応するものを用意します。

(定義2.3.2 n-量子ビット)2n次元複素テンソル積空間の単位ベクトル

$$\left\{\ket{\psi}\mid||\psi||=1,\ket{\psi}\in (\mathbb{C}^2)^{\otimes n}\right\}$$
n-量子ビット系と呼ぶ。また元をn-量子ビットと呼ぶ。$\square$

(※わからない人もいらっしゃるかと思います。テンソル積に関しては、いつかわかりやすくまとめておこうと思います。)

次に、量子ビット系において0と1はどういうものなのか記述していきます。数学的な定義をおこなう前に、前提として1-量子ビット系は$\mathbb{C}^2$上の単位ベクトルだったことを思い出しましょう。ここで$\mathbb{C}^2$の基準ベクトルを基底と言います。ここで、基底$\{\ket{\psi_i}\}$が定まると$\mathbb{C}^2$の全ての点(ベクトル)$\ket{\psi}$は、任意の基底の線型結合
$$\ket{\psi}=\sum_i\alpha_i\ket{\psi_i}$$
で書くことができます。さらに基底の中でも、それぞれの基底ベクトル$\ket{\psi_i}$が単位ベクトルであり、なおかつ直交したベクトルである場合、このような基底$\{\ket{\psi_i}\}$は正規直交基底と言います。
 これを踏まえて、1-量子ビット系、すなわち$\mathbb{C}^2$上の基底(の数ベクトル表現)を$\{\ket{0}:=(1,0),\ket{1}:=(0,1)\}$とします。通常はこの$\{\ket{0},\ket{1}\}$を用いて計算を行います。これが古典ビット系での0と1に対応します。これを1-量子ビット系における計算基底、もしくは1-計算基底と呼びます。
 より一般にはn-量子ビット系に対して、計算基底(n-計算基底)が以下のように定義されます。

(定義2.3.3 n-計算基底)$n$-量子ビット系$(\mathbb{C}_2)^{\otimes n}$の正規直交基底$\{\ket{i_1i_2...i_n}\}$を考える。ここで
$$\ket{i_1i_2...i_n}:=\ket{i_1}\otimes \cdots \otimes \ket{i_n}$$
であり、$i_k\in \{0,1\}$である。$\square$
 

次に、1-量子ビットの例を見て見ましょう。

(例2.3.4 1-量子ビットの例と基底)
以下のような重ね合わせが可能であり、これこそがまさに「0と1が同時に存在している」を表現しています。
$$\left(\frac{1}{\sqrt{2}},\frac{1}{\sqrt{2}}\right)=\frac{1}{\sqrt{2}}\left(\ket{0}+\ket{1}\right)$$
$\square$

2.4 量子状態の測定

 量子状態の測定は一般には物理量をエルミート演算子で定義し、測定値は物理量と量子状態によって定まる確率分布に従って値を得ることができます。また、さらにエルミート演算子だけでなく測定可能な状態を広げることでより広いクラスの測定を定義することができます。
しかし、ここでは簡単のために先ほど定義した計算基底による測定を定義するにとどめます。

(定義2.4.1 計算基底による測定)n-量子ビット$\ket{\psi}$に対して、計算基底$\{\ket{i_1i_2...i_n}\}$による測定を考える。測定値$i_1i_2...i_n$を得る確率は以下のように与えられる。
$$Pr(X=i_1 i_2 \cdots i_n):=|\braket{i_1 i_2 \cdots i_n}{\psi}|^2$$

ここで、$\braket{a}{b}$は$\ket{a}$と$\ket{b}$のエルミート内積である。$\square$

続いて例を見ていきましょう。

(例2.4.2 量子状態を測定してみる)以下のような1-量子ビットを考える。
$$\ket{\psi}:=\frac{1}{\sqrt{2}}(\ket{0}+\ket{1})$$
この時、計算基底による測定により、測定値$a\in \{0,1\}$を得る確率は、
$$Pr(X=a)=\frac{1}{\sqrt{2}}(\braket{a}{0}+\braket{a}{1})$$
従って、aが0の時でも1の時でも、
$$Pr(X=a)=\frac{1}{2}$$
を得る。$\square$

また、測定後には以下のような状態の変化が起こります。

(定義2.4.3 射影仮説)量子状態(量子ビット)を測定した時、量子状態は変化する。ここで、n-計算基底によって量子ビット$\ket{\psi}$測定値$a\in\{0,1\}^n$を測定した後の量子状態は、以下のように変化する。
$$\ket{\psi}\to\ket{a}$$
$\square$

 これまで見てきたように測定から得られる測定値は確率的測定後は状態が変化(しかもランダムに)
します。
 ここでは触れませんが、$n$-量子ビット系の元で$k$($<n$)-量子ビットのみに対して測定を行う部分測定という操作もあります。その場合、測定したビットのみが、上記の射影仮説を通じて状態が変化することになります。

 ここで、この節でやったことをまとめます。

$$量子状態の測定値は確率的に得られる$$
$$量子状態を測定したあとは測定値に応じて量子状態は変化する$$

2.5 量子状態の時間発展と変化

量子ビットは一般的には量子状態と呼ばれます。(有限次元の)量子ビットは、今まで見てきたように複素内積空間上の単位ベクトルとして見做すことができます。量子状態の公理として、かの有名な「シュレーディンガー方程式」から、以下のことが導かれます。

$$量子状態の時間発展はユニタリ発展である$$

意味不明だと思うので、まずは数学的な定義を見ていきましょう。

(定義2.5.1 量子状態の時間発展) 任意の量子状態$\ket{\psi}$は時間$t$を変数とするユニタリ演算子$U_t$によって、以下のように状態は変化する。
$$\ket{\psi}\to U_t\ket{\psi}$$
$\square$

さらに、次を仮定します。

(要請2.5.2 量子状態の変化) 任意の量子状態に対して、任意のユニタリ演算子を作用させることと等価な物理的操作が存在する。$\square$

これにより、任意の量子状態(量子ビット)に対して、ユニタリ演算子を作用させることが可能になりました。
 これにて、量子計算の基礎に関しては、終わりました。最後に次節で量子回路モデルを説明して、座学は終了したいと思います。

2.6量子回路モデル

 量子回路モデルは、以下のようなシチュエーションで行います。
$$n-量子ビットを用意し、初期状態とする$$
$$量子ビットに許されている操作はユニタリ演算子を作用させることと測定操作$$

2.7まとめと考察

・古典ビットと量子ビットの違い
 1-古典ビットでは、1ビットにつき2つの値を取ることができましたが、1-量子ビットでは、1ビットにつき2次元空間の単位円上のベクトル全てを取ることができます。さらに、n-古典ビットでは、合計で$2^n$個の値を取ることができましたが、n-量子ビットでは2n次元の単位円上のベクトル全てを取ることができます。
よくイメージがつかないと思うので、3-古典ビットと3量子ビットを例に、量子ビットが以下に 「自由度」を持っているかを見ていきましょう。

$\mathbb{F}_2^3$の基底は以下のように取ることができます。
$$\{(1,0,0),(0,1,0),(0,0,1)\}$$
この基底により、任意の$\mathbb{F}_2^3$の元は線型結合で表すことができます。
$$(b_1,b_2,b_3):=b_1(1,0,0)+b_2(0,1,0)+b_3(0,0,1)$$
次元は3であり、係数b_1,b_2,b_3は\{0,1\}の値しかとりません。
 一方で3-量子ビットは、はるかに大きい次元で状態を扱うことができます。3-量子ビット系$$(\mathbb{C}^2)^{\otimes 3}\simeq \mathbb{C}^8$$
であり、次元は8です。正規直交基底は、
$$\{\ket{i_1i_2i_3}\}_{i_1,i_2,i_3\in\{0,1\}}$$
となります。よって表現できる量子状態は$i:=i_1i_2i_3$とすれば
$$\ket{\psi}=\sum_ia_i\ket{i_1i_2i_3}$$
となる。ここで$a_i$は8つあり、さらに係数は(量子状態が単位円上にないといけないと言う制約はありますが)$\mathbb{C}$の値を取ることができます。したがって以下のように古典ビットと量子ビットと言うだけでもこんなスペックが違うのです!

ビットスペック表 3-古典ビット 3-量子ビット
次元(自由度) 3 8
係数 $\mathbb{F}_2$ $\mathbb{C}$

3 qiskitの導入

(更新速度も速く、技術的にも圧倒的に参考になるため、詳しくは公式ページを参照してください)
ここでは、qiskitの導入を行います。qiskitは、IBMが用意した2.6量子回路モデル型の量子回路型量子コンピュータの実機とシミュレータで実行できるSDKになります。

3.1(再度)用意するもの

mac pc
python(3.5以上)
pip,homebrewなどは導入済みでお願いします。

3.2手順

まず、qiskitをインストールします。

$pip install qiskit

次に以下のコマンドによって、全てのライブラリをインストールします。

$pip install -r requirements.txt

これで終わりです。
チュートリアルなどを行いたい場合は、公式に書いてある手順でさらにいくつかのファイルを追加する必要があります。参照お願いします。
ここに最小単位の量子計算用プログラムを作ったので、おいておきます。以下のコマンドでもダウンロードすることができます。

$git clone git@github.com:ogyogugige/qc-template_qiskit.git

3.3 qc-template_qiskitへAPIトークンをセットする。

実機で動かすためには、以下のAPItokenを手に入れる必要があります。IBM experienceにアクセスし、「sign up」から登録を行います。
登録後、右上の自分の登録名をクリックし「My Account」をクリックし、「Advanced」のページにいくと、以下の画面が出てきます。
スクリーンショット 2018-02-03 1.23.50.png
その後下の方にスクロールするとAPItokenを取得できるタブがあるので、そこでAPItokenを生成します。
その生成したあと、Qconfig.pyを開き、(qc-template_for_qiskitならば)下記の

APItoken='set your APItoken'

APItoken='aaaaaaaaaaaaaaaaaaaaaaaapitoken'

のように自分のAPItokenに書き換えます。

これにて設定は終わりです。

3.4 qc-templat_qiskitの実行と動作内容

main.pyのうち、try部分に処理内容を記述していきます。

main.py
from qiskit import QuantumProgram, QISKitError, RegisterSizeError
import Qconfig

Q_program = QuantumProgram()
if(Qconfig.get_APItoken()!=True):
    Q_program.set_api(Qconfig.APItoken, Qconfig.config["url"], verify=True,
                  hub=Qconfig.config["hub"],
                  group=Qconfig.config["group"],
                  project=Qconfig.config["project"])
backend = 'local_qasm_simulator'
try:
    # Create a Quantum Register called "qr" with 2 qubits.
    qr = Q_program.create_quantum_register("qr", 2)
    # Create a Classical Register called "cr" with 2 bits.
    cr = Q_program.create_classical_register("cr", 2)
    # Create a Quantum Circuit called "qc" involving the Quantum Register "qr"
    # and the Classical Register "cr".
    qc = Q_program.create_circuit("bell", [qr], [cr])

    # Add the H gate in the Qubit 0, putting this qubit in superposition.
    qc.h(qr[0])
    # Add the CX gate on control qubit 0 and target qubit 1, putting
    # the qubits in a Bell state
    qc.cx(qr[0], qr[1])

    # Add a Measure gate to see the state.
    qc.measure(qr, cr)

    # Compile and execute the Quantum Program in the local_qasm_simulator.
    result = Q_program.execute(["bell"], backend=backend, shots=1024, seed=1)

    # Show the results.
    print(result)
    print(result.get_data("bell"))

except QISKitError as ex:
    print('There was an error in the circuit!. Error = {}'.format(ex))
except RegisterSizeError as ex:
    print('Error in the number of registers!. Error = {}'.format(ex))

try部分で、処理を実行しています。順番に見ていくと、

qr = Q_program.create_quantum_register("qr", 2)

で、2-量子ビットを用意しています。すなわち、以下の状態です。

$$\ket{00}:=\ket{0}\otimes \ket{0}$$
ただしビットの用意のみであり、まだ量子回路は、使うことはできません。

cr = Q_program.create_classical_register("cr", 2)

ここで、2-古典ビットを用意しています。

次に、

qc = Q_program.create_circuit("bell", [qr], [cr])

ここで、"bell"と言う名前の空の量子回路を作ります。ここで、2-量子ビットと2-古典ビットを引数として渡し、量子回路qcを作ります。次に量子回路上にHadamard変換を追加します。

qc.h(qr[0])

まだ実行はされず量子回路に演算子が追加されただけですが(実行はquantumcircuit.excute()で行われる)、もし実行すれば、以下のようなユニタリ演算子Hが1ビット目にかけられます。

$$H:=\frac{1}{\sqrt{2}}\left[\array{1 & 1\\1 & -1}\right]$$
すると、以下のような計算が行われます。
$$\left(\frac{1}{\sqrt{2}}\left[\array{1 & 1\\1 & -1}\right]\otimes I\right)(\ket{0}\otimes \ket{0})$$
計算すると、
$$\frac{1}{\sqrt{2}}(\ket{00}+\ket{10})$$
が得られます。
次に以下のような演算子を量子回路に追加します。

qc.cx(qr[0], qr[1])

では、以下のようなユニタリ演算子が作用されます。これはCNOTゲートと呼ばれます。
$$C_{not}:=\left[\array{1&0&0&0\\0&1&0&0\\0&0&0&1\\0&0&1&0}\right]$$
これは、第一ビット目が1の時、2ビット目を反転させるような演算子です。従って、実行されれば以下の量子状態を得ることができます。
$$\frac{1}{\sqrt{2}}(\ket{00}+\ket{11})$$

こんな状態の量子状態(量子ビット)を最大エンタングル状態と呼びます。又の名を最大量子もつれと呼びます。
次に以下のような測定操作を量子回路に追加します。

qc.measure(qr, cr)

ここではqrを測定し、crにその測定結果を格納させるような操作です。

ここで今まで計算してきたものが測定されると測定確率は、
$$\ket{00}:\frac{1}{2},\ket{11}:\frac{1}{2}$$
となります。

それでは、お待ちかねの実行です。

result = Q_program.execute(["bell"], backend=backend, shots=1024, seed=1)

量子回路を実行します。今回の量子回路は今まで見てきたように
Hadamard行列をかける$\to$ CNOT行列をかける $\to$ 測定する
と言う回路でした。それを、1024回実行して見ます。すると...

{'counts': {'00': 512, '11': 512}}

ちょうど半分!!!!!!!

 ちなみに回数を増やすとどうなるかと言うと、4096回だと

{'counts': {'00': 2030, '11': 2066}}

少しずれる。

何回やっても結果が同じなのはなんでかわかりません。まだ、IBM-Q自体のクラウドの処理などは詳しくないので調べときます。

誤りなどありましたら、ご指摘いただけると助かります。

追記変更ログ

2017.2.4 改稿
2017.2.2 投稿

参考文献

[1]古澤明"量子コンピュータ入門"
[2]石坂 智 小川 朋宏 河内 亮周 木村 元 林 正人"量子情報科学入門"