{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Qiskitチュートリアルのチュートリアル\n",
"\n",
"この記事は[量子コンピュータ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/quantum)の5日目の記事です。\n",
"昨日は@stwhaboutさんの「[Quantum Katas で始める量子コンピュータ入門 |6⟩: Simon's Algorithm](https://qiita.com/stwhabout/items/04105d054b739914d478)」でした。\n",
"明日は宇津木健さんが「[2018年の量子コンピュータ関連のニュースに一言ずつ!]()」書いてくれる予定です。\n",
"\n",
"\n",
"こんにちは、京都大学大学院で量子情報・量子コンピュータの研究をしている博士課程学生の[濵村一航](https://qinfo.tech)と申します。\n",
"この記事ではIBMの量子コンピュータ向けライブラリであるQiskitについて紹介していきます。\n",
"\n",
"最初に僕とQiskitについて書きます。\n",
"IBMの量子コンピュータは、クラウドで利用可能になった2016年から使用していましたが、僕がQiskitというライブラリに出会ったのは今年のIBM東京基礎研究所でインターンでのことでした。\n",
"インターンでがっつりコードを読んだりプルリクを出したりしました。\n",
"インターン終了後もちょこちょこなんかしています。\n",
"(最近忙しくてちょっと活動力低下中)\n",
"\n",
"\n",
"そんな形で関わっているQiskitを[Qiskit Tutorials](https://github.com/Qiskit/qiskit-tutorial)というチュートリアルを紹介する形で書いていこうと思います。\n",
"この記事は、言うなればQiskit Tutorialsのチュートリアルです。\n",
"ちなみに、Qiskit Tutorialsは[Binder](https://mybinder.org/v2/gh/Qiskit/qiskit-tutorial/master?filepath=index.ipynb)から環境構築なしで試すことも出来ます。\n",
"\n",
"## 2018年のQiskit\n",
"\n",
"2018年はQiskitにとっても大きな飛躍の年でした。\n",
"最も目に付きやすいのはその名前の変更です。\n",
"以前は「Quantum Information Software Kit」を略して「QISKit」だったのですが、「Qiskit」になりました。\n",
"また、ライブラリが分割され、コアライブラリも「Qiskit SDK」から「Qiskit Core」、そして現在の「Qiskit Terra」となっています。\n",
"この「Terra」のリリースとほぼ同時に応用向けのライブラリである「QISKit ACQUA」(現在の「Aqua」)がリリースされました。\n",
"このAquaは化学やAI、最適化問題などへの量子コンピュータの応用をサポートしています。\n",
"もちろん、名前の変更だけでなくて、中身も大きく進化しています。\n",
"後方互換性を壊すような変更も入ったので古い解説記事のコードは動かなくなっています。\n",
"したがって、2018年の最後に現在の最新のQiskitの使い方を解説しておくのは意味があるのではないかと感じたので、Advent Calendarに参加して記事を書くことにしました。\n",
"\n",
"## Qiskit Terraについて\n",
"\n",
"冒頭でも述べましたが、Qiskitは量子コンピュータ用のライブラリです。\n",
"現在はQiskit Terra, Aquaがリリースされています。\n",
"今後はさらに量子誤り訂正や量子トモグラフィをサポートしたIgnis、高品質で高性能なシミュレータをサポートするAerがリリースされる予定です。\n",
"詳細は公式による記事[Qiskit and its Fundamental Elements\n",
"](https://medium.com/qiskit/qiskit-and-its-fundamental-elements-bcd7ead80492)にあるので、ここでの紹介はこのくらいにしておきます。\n",
"\n",
"Qiskit TerraはQiskitの中心ともいえるライブラリです。\n",
"例えば、量子コンピュータで実行する操作のレシピを表した量子回路を作成し、その量子回路を量子コンピュータやシミュレータに投げて実行することが出来ます。\n",
"ではまず量子回路を実際に作成してみましょう。\n",
"[Quantum Circuits](https://github.com/Qiskit/qiskit-tutorial/blob/master/qiskit/terra/QuantumCircuits.ipynb)を参考にしています。\n",
"今回はQiskit Terraの執筆当時の最新版のQiskit Terra 0.6.1を使用しています。\n",
"\n",
"最初に`state`という状態を準備する回路と`meaurement`という測定を表す回路を書いてみます。\n",
"量子回路は`+`演算子で連結することが出来ます。"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister\n",
"\n",
"q = QuantumRegister(2)\n",
"c = ClassicalRegister(2)\n",
"state = QuantumCircuit(q, c)\n",
"\n",
"state.x(q[1])\n",
"state.h(q[0])\n",
"state.cx(q[0], q[1])\n",
"\n",
"measurement = QuantumCircuit(q, c)\n",
"measurement.measure(q, c);"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"%config InlineBackend.figure_format = 'svg'\n",
"from qiskit.tools.visualization import matplotlib_circuit_drawer, qx_color_scheme\n",
"\n",
"#いい感じのスタイルを設定しています\n",
"style = qx_color_scheme()\n",
"style['compress'] = True\n",
"style['cregbundle'] = True\n",
"style['plotbarrier'] = True\n",
"circuit_drawer = lambda circuit: matplotlib_circuit_drawer(circuit, style=style)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"circuit = state + measurement\n",
"circuit_drawer(circuit)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"なかなか、いい感じの量子回路図を書くことが出来ます。\n",
"これは内部的には`matplotlib`を用いて量子回路を描画しています。\n",
"実はQiskit 0.7以降ではアスキーアートで回路を表示する機能が導入され、さらに便利になる予定です。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"実際に量子回路をシミュレータで計算して、結果を見てみましょう。\n",
"結果を可視化する部分はチュートリアルの[Ploting Data in Qiskit\n",
"](https://github.com/Qiskit/qiskit-tutorial/blob/master/qiskit/basics/plotting_data_in_qiskit.ipynb)が参考になります。"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"from qiskit import Aer\n",
"from qiskit import execute\n",
"from qiskit.tools.visualization import plot_histogram\n",
"\n",
"backend = Aer.get_backend('qasm_simulator')\n",
"job = execute(circuit, backend)\n",
"result = job.result()\n",
"counts = result.get_counts(circuit)\n",
"\n",
"plot_histogram(counts)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"この結果をみると、`01`と`10`がほぼ同じくらいの確率で出ていることが分かります。\n",
"\n",
"測定(上の量子回路図でいうピンクの箱)はその直前の量子状態の一部の情報しか引き出せません。\n",
"測定したときの量子状態がどんな状態だったのかが気になりますかもしれません。\n",
"この場合は`statevector_simulator`を使います。\n",
"`qasm_simulator`は量子コンピュータのシミュレーションが出来て、`statevector_simulator`は状態ベクトルという現実では出来ないような情報をシミュレートするものだと思ってください。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"from qiskit.tools.visualization import plot_histogram, plot_state\n",
"\n",
"backend = Aer.get_backend('statevector_simulator')\n",
"result = execute(state, backend).result()\n",
"state_vec = result.get_statevector(state)\n",
"plot_state(state_vec, method='city')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"状態ベクトルの要素は複素数なので実部と虚部があります。\n",
"せっかくなので他の状態の可視化もみてみましょう。"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"The 0th eigenvalue = 0.9999999999999999\n"
]
},
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"