IBMは現在クラウドで量子コンピュータを利用できるサービス「IBM Quantum」を提供しています。一部のシステムについては無償で一般公開されており、誰でも量子計算を試す事できます。
本記事では、IBMが提供している量子コンピュータ用のSDK(ソフトウェア開発キット) 「Qiskit」を用いて、IBM Quantumにアクセスする方法等について説明します。これから量子計算を学ぶ方(もちろん私も含みます)を対象とした内容になります。
(※)量子コンピューティングについては、IBMの以下の記事がとても参考になります。
https://www.ibm.com/jp-ja/topics/quantum-computing
qiskitのインストール
Qiita内にはqiskitのインストールに関する詳細な解説記事が既にあります。
https://qiita.com/hiro949/items/268141289cbd47c27f6a
https://qiita.com/K-K-K-K/items/8bebc4a2556561308ccb
https://qiita.com/ool/items/e80c1266cda68984a103
https://qiita.com/taka2_kiara/items/796ddfb04dc974e2eb7d
但し、IBM Quantum systemにアクセスする際、以前使われていた「qiskit-ibmq-provider」は現在では非推奨となっています。そこで、現在推奨されている 「qiskit-ibm-provider」への移行をふまえ、qiskitのインストールを紹介してみたいと思います。
(※)qiskit-ibm-providerへの移行ガイドは以下が参考になります。
https://github.com/Qiskit/qiskit-ibm-provider/blob/main/docs/tutorials/Migration_Guide_from_qiskit-ibmq-provider.ipynb
qiskitはpython3.7以降をサポートしています。今回はAnacondaを利用し、Anacondaに含まれるcondaコマンドで仮想環境を作り、そこにqiskitをインストールすることにします。
conda create -n qiita python=3.9 # 仮想環境の名前をqiita
conda activate qiita
pip install qiskit[all]
pip install qiskit-ibm-provider
私の環境はLinux Mint 20.2 x86_64でしたが、特に問題なく必要なライブラリ群がインストールされました。
インストールされたqiskitのバージョンは
import qiskit
qiskit.__qiskit_version__
で確認することが出来ます。
(※)2023/5時点でのqiskitのバージョン(meta package version)は、0.43.0となっています。
https://qiskit.org/documentation/release_notes.html
IBM Quantumのアカウント作成
1. アカウント作成
https://quantum-computing.ibm.com/ にアクセスします。続いて、Sign in to IBM Quantumの下方にある「Create an IBMid account」をクリックして、IBMidを作成します。
(※)アカウント作成はこちらの記事も参考になるかも知れません。
https://qiita.com/kifumi/items/7ac33ab7939d2dd796d0
2. トークンの取得
IBMidが作成されると、IBM Quantumにサインインできます。サインインすると、実機にアクセスする際の認証に必要なAPI tokenが「****」 で表示されているので、これをコピーします。
APIトークンは、IBMProviderクラスにあるsave_account()メソッドを用いて、ディスク内に保存できます。
from qiskit_ibm_provider import IBMProvider
IBMProvider.save_account(token='MY_API_TOKEN', overwrite=True)
APIトークンは一度保存すれば、次回以降は必要ありません。
これでIBM Quantum systemにアクセスする準備が出来ました。
クラウド上でIBM Quantum systemの確認
サインインができれば、既にwebブラウザ上で視覚的に量子回路を構築することが可能です。また、アプリケーションのプロトタイプの作成や、利用できるComputer resourcesも確認できます。サインイン後、webページの左上にある四角ボタン(Application switcher)があることが分かります。
例えば以下の操作、
左上ボタン(Application switcher) → Computer resources → Your resources
とクリックしていくと、現在のアカウントで利用できる実機(リソース)情報の一覧が取得できます。また、各リソースをクリックすると、リソースの量子ビットのレイアウトや量子ビットのエラーの詳細情報を閲覧できます。
pythonでシステムの確認
クラウド上での操作はグラフィカルで直観的にわかりやすいですが、 Qiskitはpython環境で実行されるため、
pythonでIBM Qunatum systemのリソース情報も確認できると便利です。
1. IBMProviderのインスタンス化
APIトークンを保存すれば、IBMProviderクラスをインスタンス化するだけで、保存したアカウントとデフォルトのプロジェクトを読み込むことができます。また、IBM Quantumのサービスへのアクセスは、割り当てられたIBM Quantum instancesによって制御されます。IBM Quantum instancesは、ハブ(hub)/グループ(group)/プロジェクト(project)という階層的な組織で定義されます。 一般公開されているインスタンスは ibm-q/open/main です。
from qiskit_ibm_provider import IBMProvider
hub = "ibm-q"
group = "open"
project = "main"
provider = IBMProvider(instance=f"{hub}/{group}/{project}")
2. 利用できるバックエンドの表示
利用可能な量子コンピュータリソースは、IBMProviderクラスのbackends()メソッドを用いて取得できます。
provider.backends()
一般公開用のIBM Quantum instancesのバックエンドには、量子コンピュータ実機以外に、実機を模擬したシミュレータ(ibmq_qasm_simulatorなど)も含まれています。実機の情報のみ取得したい場合、
provider.backends(operational=True, simulator=False)
とします。現在、以下の量子コンピュータがバックエンドとして利用可能であることが分かります。
[<IBMBackend('ibmq_quito')>,
<IBMBackend('ibm_lagos')>,
<IBMBackend('ibm_perth')>,
<IBMBackend('ibmq_jakarta')>,
<IBMBackend('ibmq_lima')>,
<IBMBackend('ibmq_belem')>,
<IBMBackend('ibmq_manila')>,
<IBMBackend('ibm_nairobi')>]
3. バックエンドの取得
IBMProviderクラスのget_backend()メソッドを用いると各実機リソースをバックエンドとして取得できます。
'ibmq_lima'の場合を以下に示します。
backend = provider.get_backend('ibmq_lima')
取得したリソースのエラーマップや量子ビットのレイアウトの情報は、qiskitのvisualizationモジュールを使うことで可視化できます
from qiskit.visualization import plot_gate_map, plot_error_map, plot_circuit_layout
display(plot_error_map(backend))
4. バックエンドの詳細を確認
このままでは見づらく、また情報も少ないので、各バックエンドの詳細情報を見やすく表示したいと思います。IBMBackendクラスのメソッドを参考[※]にすると、バックエンドの詳細な情報を取得することができます。
[※]https://qiskit.org/ecosystem/ibm-provider/stubs/qiskit_ibm_provider.IBMBackend.html#qiskit_ibm_provider.IBMBackend
例えば各バックエンドの情報を表示する以下のような関数を考えることが出来ます。
def backends_detail(provider):
available_backends = provider.backends(
operational=True,
filters=lambda b: b.configuration(
).n_qubits > 1 and not b.configuration().simulator)
print("{0:17}{1:<9}{2:<14}{3:<10}{4:<11}{5:<9}{6:<9}".format(
"Backend name", "#Qubits", "Pending jobs", "Max exp.", "Max shots",
"Version", "Processor"))
print("{0:17}{1:<9}{2:<14}{3:<10}{4:<11}{5:<9}{6:<9}".format(
"--------------", "-------", "------------", "--------",
"---------", "-------", "---------"))
for i in available_backends:
backend = provider.get_backend(str(i.name))
print("{0:17}{1:<9}{2:<14}{3:<10}{4:<11}{5:<9}{6:<9}".format(
backend.name,
backend.configuration().n_qubits,
backend.status().pending_jobs,
backend.configuration().max_experiments,
backend._configuration.max_shots,
backend.configuration().backend_version,
backend.configuration().processor_type['family']))
先ほどのコードとまとめると
from qiskit_ibm_provider import IBMProvider
hub = "ibm-q"
group = "open"
project = "main"
provider = IBMProvider(instance=f"{hub}/{group}/{project}")
backends_detail(provider)
となります。実行すると、
Backend name #Qubits Pending jobs Max exp. Max shots Version Processor
-------------- ------- ------------ -------- --------- ------- ---------
ibm_perth 7 100 300 100000 1.2.7 Falcon
ibmq_quito 5 3 300 100000 1.1.41 Falcon
ibmq_belem 5 1 300 100000 1.2.8 Falcon
ibmq_manila 5 11 300 100000 1.2.3 Falcon
ibm_lagos 7 158 900 100000 1.3.3 Falcon
ibm_nairobi 7 189 300 100000 1.3.3 Falcon
ibmq_jakarta 7 35 300 100000 1.4.0 Falcon
ibmq_lima 5 1 300 100000 1.0.48 Falcon
と出力されます。利用可能なリソース情報の一覧が得られました。
一覧の中の#Qubitsは量子ビットの数、Pending jobs は現在の待ち行列数です。
IBM Quantum systemへジョブを投入する
最期にGHZ状態を生成する量子回路をqiskitで作り、それを計算するジョブをIBM Quantum systemに投入してみます。ジョブの投入に関しては、以下の記事を参考にしています。
https://qiskit.org/documentation/locale/ja_JP/intro_tutorial1.html
GHZ状態は、5量子ビットの場合、例えば以下の量子回路で生成されます。
from qiskit import QuantumCircuit, transpile
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
qc = QuantumCircuit(5,5)
qc.h(1)
qc.cx(1,2)
qc.cx(1,0)
qc.cx(2,3)
qc.cx(3,4)
qc.measure([0,1,2,3,4], [0,1,2,3,4])
qc.draw('mpl')
上記の量子回路を量子コンピュータで実行させる前に、シミュレータで確認します。
# simulator
simulator = AerSimulator()
compiled_circuit = transpile(qc, simulator)
job = simulator.run(compiled_circuit, shots=1000)
result = job.result()
counts = result.get_counts(compiled_circuit)
print(counts)
plot_histogram(counts)
ここではshots=1000として、1000回の観測を実施しました。
結果は以下のようになりました。正しく全ての量子ビットがエンタングルしているようです。
次に実機を用いて同じ量子計算を実施したいと思います。実機へジョブを投入する場合は、上記のコードでsimulatorを実機のbackendに変更するだけです。ここでは仮にbackendにibmq_limaを選択します。
# IBM Quantum system
backend = provider.get_backend('ibmq_lima')
compiled_circuit = transpile(qc, backend)
job = backend.run(compiled_circuit, shots=1000)
job_id = job.job_id()
print(job_id)
コードに間違いが無ければ、ジョブがibmq_limaへ投入されます。もし多くの待ち行列が発生している場合は、job_idを用いて後日に結果を回収することができます。ジョブのstatusは
retrieve_job = provider.retrieve_job(job_id)
retrieve_job.status()
にて確認可能です。計算が無事終了すると、
<JobStatus.DONE: 'job has successfully run'>
と表示されます。job_id情報から、計算結果を以下のように回収します。
retrieve_job = provider.retrieve_job(job_id)
result = retrieve_job.result()
counts = result.get_counts(compiled_circuit)
print(counts)
plot_histogram(counts)
結果は以下のようになりました。シミュレータの結果と違って少し他の状態も観測されています。特に'01111'が誤って多く観測されているようです。つまり、本来"1"であるはずの5番目の量子ビットが"0"になっています。(qiskitはlittle endian表示ですので、左から右へ、量子ビット番号の大きい順に量子ビットを並べます) これらは実機の量子ビットのエラーや量子ビットのレイアウトなどに関係しているかもしれません。
まとめ
今回、qiskitを用いたIBM Quantum systemへのアクセスを説明しました。何かしら参考になれば幸いに思います。初学者ですので、間違いなどありましたらご指摘下さると幸いです。今後はqiskit runtimeについても記事を書ければと思います。