注釈
このページは tutorials/circuits/1_getting_started_with_qiskit.ipynb から生成されました。
Qiskit 入門¶
ここでは、Qiskit での作業概要を説明します。Qiskit の基本パッケージは Terra です。これは、量子コンピューターのプログラミングに必要な、基本構成要素を提供します。Qiskit の基本単位は 量子回路 です。Qiskit を使用した基本的なワークフローは、 構築 と 実行 の2つのステージで構成されます。 構築 では、あなたが解きたい問題を表現するさまざまな量子回路を構築でき、 実行 では、その量子回路をさまざまなバックエンドで実行します。ジョブが実行された後、目的とする出力に応じたデータが収集され、後処理されます。
[1]:
import numpy as np
from qiskit import *
回路の基本¶
回線の構築¶
最初のプログラムに必要な基本要素は、QuantumCircuitです。まず、3つの量子ビットで構成される QuantumCircuit
を作成します。
[2]:
# Create a Quantum Circuit acting on a quantum register of three qubits
circ = QuantumCircuit(3)
レジスタで回路を作成した後、レジスタを操作するためのゲート (「演算」) を追加することができます。チュートリアルを進めていくと、さらに多くのゲートと回路が見つかります。以下は3量子ビットのGHZ状態を作る量子回路の例です。
このような状態を作成するには、3量子ビットの量子レジスターから始めます。デフォルトでは、レジスターの各量子ビットは \(|0\rangle\) に初期化されています。GHZ状態を作成するには、次のゲートを適用します:
理想的な量子コンピューターでは、この回路を実行することによって生成される状態は、上記のGHZ状態になります。
Qiskit では、以下に示すように、回路に操作を1つずつ追加することができます。
[3]:
# Add a H gate on qubit 0, putting this qubit in superposition.
circ.h(0)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 1, putting
# the qubits in a Bell state.
circ.cx(0, 1)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 2, putting
# the qubits in a GHZ state.
circ.cx(0, 2)
[3]:
<qiskit.circuit.instructionset.InstructionSet at 0x7fa0f8fc9310>
回路の可視化¶
Qiskitの QuantumCircuit.draw()
を使うことで、多くの教科書で見られるような形式に回路をプロットし、可視化することができます。
[4]:
circ.draw('mpl')
[4]:

この回路では、量子ビットが順番に配置されており、一番上が量子ビット0、一番下が量子ビット2です。回路は左から右に読みます (つまり、回路の初めに適用されたゲートが左側に表示されます)。
複数の量子ビットのシステムの状態を表現する際に Qiskit で使われるテンソル積の順番は、多くの物理の教科書で使われる順番と異なります。\(n\) 個の量子ビットがあり、\(j\) 番目の量子ビットは \(Q_{j}\) とラベル付けされていると仮定します。Qiskitでは、 \(n\) 番目の量子ビットはテンソル積の左側にあるので、基底ベクトルは、\(Q_{n-1}\otimes \cdots \otimes Q_1\otimes Q_0\) とラベル付けされます。
例えば、量子ビット0が状態0、量子ビット1が状態0、量子ビット2が状態1のとき、Qiskit はこの状態を \(|100\rangle\) と表現します。一方、多くの物理の教科書では、この状態を \(|001\rangle\) と表現します。
このラベリングの違いは、複数量子ビットの演算が行列として表現されるときの方法に影響します。例えば、Qiskit は制御 X (\(C_{X}\)) 演算において量子ビット0を制御ビット、量子ビット1をターゲットビットとするとき、以下のように表現します。
Qiskit Aer を使った回路のシミュレーション¶
Qiskit Aer は、量子回路をシミュレーションするパッケージです。シミュレーションするためのバックエンドは複数あります。以下の例にあるように Aer
の完全互換性部品として使うことのできるTerraの BasicAer
と呼ばれるベーシックな Python のみの実装もあります。
状態ベクトル・バックエンド¶
Qiskit Aer における最も一般的なバックエンドは、statevector_simulator
です。このシミュレーターは、 \(2^n\) 次元の複素ベクトルである量子状態を返します。ここで \(n\) は量子ビットの数です(ですので、ご自身のマシンで実行するには大きすぎる数にすぐ到達してしまうことに注意してください)。
状態ベクトル・シミュレーターを使って、上記の回路を実行するためには、最初に Aer をインポートしてから、バックエンドを statevector_simulator
に設定する必要があります。
[5]:
# Import Aer
from qiskit import Aer
# Run the quantum circuit on a statevector simulator backend
backend = Aer.get_backend('statevector_simulator')
バックエンドを選択したので、量子回路をコンパイルして実行します。Qiskit には、そのために execute
関数があります。execute
は、バックエンドに送信されたジョブの情報をカプセル化するオブジェクトである job
を返します。
ヒント:上記のパラメータは Jupyter で取得できます。関数にテキストカーソルを置いて、Shift+Tab を押すだけです。
[6]:
# Create a Quantum Program for execution
job = backend.run(circ)
プログラムを実行すると、二つの便利なメソッドをもったジョブ・オブジェクトが作られます: job.status()
と job.result()
です。これらは、ジョブのステータスと結果オブジェクトをそれぞれ返します。
注記:ジョブは非同期に実行されますが、result メソッドが呼び出されると同期に切り替わり、終了するのを待ってから別のタスクに進みます。
[7]:
result = job.result()
Result オブジェクトにはデータが含まれており、Qiskit は量子回路の状態ベクトルを返す result.get_statevector(circ)
メソッドを提供しています。
[8]:
outputstate = result.get_statevector(circ, decimals=3)
print(outputstate)
[0.707+0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0.707+0.j]
Qiskitは、これらの結果を見るための可視化ツールボックスも提供しています。
以下のように、状態の密度行列である \(\rho\) の実数部と虚数部をプロットする可視化関数が使えます。
[9]:
from qiskit.visualization import plot_state_city
plot_state_city(outputstate)
[9]:

ユニタリー・バックエンド¶
Qiskit Aer には、 回路のすべての要素をユニタリー演算 にする unitary_simulator
も含まれます。このバックエンドは、量子回路のゲートを表す \(2^n \times 2^n\) の行列を計算します。
[10]:
# Run the quantum circuit on a unitary simulator backend
backend = Aer.get_backend('unitary_simulator')
job = backend.run(circ)
result = job.result()
# Show the results
print(result.get_unitary(circ, decimals=3))
[[ 0.707+0.j 0.707-0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0.707+0.j -0.707+0.j]
[ 0. +0.j 0. +0.j 0.707+0.j 0.707-0.j 0. +0.j 0. +0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0.707+0.j -0.707+0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0.707+0.j 0.707-0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0.707+0.j -0.707+0.j 0. +0.j 0. +0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0.707+0.j 0.707-0.j]
[ 0.707+0.j -0.707+0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0. +0.j 0. +0.j]]
OpenQASMバックエンド¶
上記のシミュレーターは、理想的な回路から出力される状態と、回路の行列表現に関する情報を提供してくれるため便利です。 ただし、実際の実験は、各量子ビット (通常は、計算基底 \(|0\rangle, |1\rangle\)) を 測定 することで終了します。 測定なしでは、状態に関する情報を得ることができません。 測定は、量子システムに古典的なビットへの崩壊を引き起こします。
例えば、3量子ビットのGHZ状態の各量子ビットを独立に測定するとしましょう。
\(xyz\) が結果のビット列を示すとしましょう。 Qiskitで使用される量子ビットのラベリング方法では、\(x\) は量子ビット2の結果に対応し、\(y\) は量子ビット1の結果に対応し、そして、 \(z\) は量子ビット0の結果に対応します。
注記:このビット文字列の表現では最上位ビット (MSB) が左側、最下位ビット (LSB) が右側に配置されます。これは、バイナリビット文字列における標準的な順序です。そのため、同じ方法で量子ビットも並べます (最上位ビットを表す量子ビットのインデックスは0です)。これが、Qiskit が非標準的なテンソル積の順序を使用する理由です。
\(xyz\) の結果が得られる確率は、以下のように与えられることを思い出してください。
そして、GHZ状態の場合、000または111が得られる確率はどちらも1/2です。
測定を含む回路をシミュレートするためには、上記の回路に測定を追加し、異なる Aer バックエンドを使用する必要があります。
[13]:
# Create a Quantum Circuit
meas = QuantumCircuit(3, 3)
meas.barrier(range(3))
# map the quantum measurement to the classical bits
meas.measure(range(3), range(3))
# The Qiskit circuit object supports composition using
# the addition operator.
circ.add_register(meas.cregs[0])
qc = circ.compose(meas)
#drawing the circuit
qc.draw()
[13]:
┌───┐ ░ ┌─┐ q_0: ┤ H ├──■────■───░─┤M├────── └───┘┌─┴─┐ │ ░ └╥┘┌─┐ q_1: ─────┤ X ├──┼───░──╫─┤M├─── └───┘┌─┴─┐ ░ ║ └╥┘┌─┐ q_2: ──────────┤ X ├─░──╫──╫─┤M├ └───┘ ░ ║ ║ └╥┘ c: 3/═══════════════════╩══╩══╩═ 0 1 2
この回路は古典レジスタと3つの測定を追加して、量子ビットの結果を古典ビットにマッピングします。
この回路をシミュレートするためには、Qiskit Aerの qasm_simulator
を使います。この回路を実行するたびに000または111が生成されます。ビット列の分布についての統計を取るために (例えば、\(\mathrm{Pr}(000)\) を見積もるために) 、何回も回路を繰り返す必要があります。回路の繰り返し回数は execute
関数の shots
キーワードで指定できます。
[17]:
# Use Aer's qasm_simulator
backend_sim = Aer.get_backend('qasm_simulator')
# Execute the circuit on the qasm simulator.
# We've set the number of repeats of the circuit
# to be 1024, which is the default.
job_sim = backend_sim.run(transpile(qc, backend_sim), shots=1024)
# Grab the results from the job.
result_sim = job_sim.result()
result オブジェクトを取得できたら、get_counts(circuit)
関数を使用して回数を取得することができます。これにより、送信した回路の 集計 されたバイナリ結果が得られます。
[18]:
counts = result_sim.get_counts(qc)
print(counts)
{'111': 514, '000': 510}
約50%の出力ビット文字列は000です。Qiskit は、結果を表示できる関数 plot_histogram
も提供します。
[19]:
from qiskit.visualization import plot_histogram
plot_histogram(counts)
[19]:

推定された結果の確率 \(\mathrm{Pr}(000)\) と \(\mathrm{Pr}(111)\) は、カウントを集計し、ショット数 (回路が繰り返された回数) で割ることによって計算されます。 execute
関数の shots
キーワードを変更してみて、推定される確率がどのように変化するかを確認してください。
[20]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
qiskit-terra | 0.19.0.dev0+be0ed5f |
qiskit-aer | 0.8.2 |
qiskit-ignis | 0.6.0 |
qiskit-ibmq-provider | 0.16.0.dev0+4e20edc |
System information | |
Python | 3.7.7 (default, May 6 2020, 04:59:01) [Clang 4.0.1 (tags/RELEASE_401/final)] |
OS | Darwin |
CPUs | 6 |
Memory (Gb) | 32.0 |
Sat Jul 31 01:06:28 2021 EDT |
This code is a part of Qiskit
© Copyright IBM 2017, 2021.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.
[ ]: