Qiskit環境構築  [uv/poetry共通] (5) IBM Quantum量子コンピュータ実機での量子回路実行

# 概要
　・qiskit2.0でも動きます。
　・Windows11/WSL2でのQiskit環境構築手順は需要がありそうなので記載します。
　・IBM Community Japanの2024年ナレッジモール研究に参加した際に使用したQiskit環境の構築手順となります。
　　[IBM Community Japan / ナレッジモール研究](http://qiita.com/)
　・Qiitaの書き方がまだわかっておらず練習を兼ねているため、今後も修正をしていきます。

 # 本ドキュメントの範囲
 　　 (0) シミュレータ実行と実機実行の違い
 　　 (1) IBM Quantum Platformでのアカウント登録/API Token取得
 　　 (2) API Token登録
 　　 (3) ライブラリのimport
 　　 (4) 量子回路の作成
 　　 (5) 量子回路の実機(IBM Quantum Platform)実行
 　　 (6) 実行結果の取得
 　　 (7) 実行結果を確率分布図で確認

# (0) シミュレータ実行と実機実行の違い
シミュレータ実行と異なり、実機の実行では以下が異なります。
・IBM Quantum PlatformのAPI Tokenが必要になる。
・QiskitでAPI Tokenを登録する必要がある。
・実機での実行前にpass managerで回路の最適化を行う。
　(シミュレータで最適化を行う場合はtraspileを使用する。)
・backendとして実機を選択する必要がある。

# (1) IBM Quantum Platformでのアカウント登録/API Token取得
[IBM Quantum Platform](https://quantum.ibm.com/)のサイトで、ユーザーアカウントを登録してAPI Tokenを取得します。
API Tokenはログオン後、画面の右上に表示されています。
![ibm1_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/ff5c42f3-43ee-27a7-853c-0e79249a3bb1.png)

# (2) API Token登録
API Token登録用のコードは専用のコードを1つ作っておくと便利です。
&lt;your_token&gt;の個所をAPI Tokenに置き換えたうえでコードを実行します。
&lt;&gt;の部分は不要です。
★コードをgithubなどで公開された場所にアップロードしないように気を付けてください。
```python: loadApiToken_IBMQ.ipynb (API Token登録)
# import
from qiskit_ibm_runtime import QiskitRuntimeService

# API Tokenを設定
QiskitRuntimeService.save_account(
    channel='ibm_quantum',
    overwrite=True,
    set_as_default=True,
    token='<your_token>')

# QiskitRuntimeServiceインスタンス生成
# IBM Quantum Platformを使用する場合はchannel='ibm_quantum'
service = QiskitRuntimeService(channel=('ibm_quantum'))
```
# [これより、量子回路の実行を行います。]
# (3) ライブラリのimport
シミュレータでのqiskit.primitivesが、
実機で実行するためのqiskit_ibm_runtimeと
回路の最適化を行う generate_preset_pass_managerに置き換わります。

```python: CNOT_IBMQ.ipynb : ライブラリのimport
# ライブラリのimport
# 量子回路作成のために必要
from qiskit import QuantumCircuit   

# IBMQ実機での実行に必要     
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler 

# passManager(IBMQ実機での量子回路最適化で使用)
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

# 確率分布を表示するために必要
from qiskit.visualization import plot_distribution        
```
実行イメージ
![exec_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/eb354e17-bdb0-86eb-cfbc-e0ecd3c90cc3.png)

# (4) 量子回路の作成
量子回路はシミュレータ実行時のものと同一です。
量子ビットq0とq1がもつれます。
```python: CNOT_IBMQ.ipynb : 量子回路の作成
# 量子回路の初期化
circuit = QuantumCircuit(2) # 量子ビット2個 古典ビット2個を準備

# 量子回路の組み立て
circuit.h(0)    # アダマールゲートを適用
circuit.cx(0,1) # CNOTゲートを適用

# 測定
circuit.measure_all() # すべての量子ビットを測定する。()

# 量子回路の素描
circuit.draw(output="mpl") # 量子回路をmpl形式で表示   
```
実行イメージ
![exec_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/6bfaa00a-c35d-e3e9-4fd9-15a79af94297.png)
![aefb67db-3326-4990-a189-a7540bbdc96d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/0147ab46-04ef-eb35-289e-7367f5b19891.png)

# (5) 量子回路の実機(IBM Quantum Platform)実行
  インスタンス生成 -> backend設定 -> passManager -> 量子回路の実行の順で実施します。
  処理待ちとなることが多いため、job idを出力することで状態確認の際に使用します。
  
```python: CNOT_IBMQ.ipynb : 量子回路の実行
#--- 量子回路の実行(IBM Quantum)
# QiskitRuntimeServiceインスタンス生成
service = QiskitRuntimeService()

# 下記は参考のため記載。実行しなくてもよい
# アカウントで利用可能なバックエンドのリスト
# API TOKEN登録時にchannel=('ibm_quantum')を設定しているので
# 利用可能な実機のリストが出力される。
print(f'accessible backends : {service.backends()}')

# backend設定
# service.least_busyを使うことで、処理能力的に一番余裕のある実機が選ばれる。
backend = service.least_busy(operational=True, simulator=False)
print(f'#------')
print(f'Selected in-use backend : {backend}')

#---passManagerによる量子回路の最適化
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circ = pm.run(circuit)

# IBM Quantum : JOB(1)
# 量子回路の実行
sampler = Sampler(backend)
job = sampler.run([isa_circ])

# IBM Quantum : JOB(2)
# job idの出力
job_id = job.job_id()
print(f'#------')
print("job id:", job_id)
```
実行イメージ
アクセス可能な実機が ibm_brisbane、ibm_kyiv、ibm_sherbrookeの3台あり、
job id: cy70k1mnrmz00085pcp0がアサインされ、ibm_kyivで実行されていることがわかります。
![exec_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/79871b28-7594-b068-9131-7be51b78a7a3.png)

下記のコードを実行するとJOBの状態を確認できます。
　PENDING：処理の順番待ちで未実行。
　RUNNING：実行中
　DONE　  ：完了
一度にすべてのコードを実行してしまうと、処理が返ってこなくなることが多いので、
コード実行はここまでにとどめておいて、状態確認を何度も繰り返し実行することで
JOBがDONEになるまで待つのもありです。

```python: CNOT_IBMQ.ipynb : JOB処理状態の確認
# IBM Quantum : JOB(3)
# JOB処理状態の確認
job.status()
```
![running.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/cc4b0a0c-6e6d-0dd5-fb8a-c34d91f893df.png)![done.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/aaf1032b-d0c0-7269-d5e7-d6fd1974172b.png)

# [IBM Quantum PlatformでのJOB状態確認]
IBM Quantum PlatformでもJOBの状態を確認することができます。
IBM Quantum Platform -> Dashboard -> Recent workloadsでJOBの実行状態を確認できます。
job id: cy70k1mnrmz00085pcp0のStatusが"In progress"となっておりibm_kyivで実行中です。
![ibm1_004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/1fdb4552-db2b-2c3c-eb8f-7957796abe7b.png)

該当JOBの行をクリックすると詳細のページが表示されます。
その他、いろいろと面白い情報があるので触ってみてください。
![ibm1_005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/0a6400a4-6cd8-03ef-248e-3331a1f00cce.png)

# (6) 実行結果の取得
qiskit_ibm_runtime / Sampler実行結果の取得はシミュレータのPrimitiveResult形式で一緒です。
```python: CNOT_IBMQ.ipynb : 実行結果の取得
# IBM Quantum : JOB(4)
# 実行結果の取得
result = job.result()                           # PrimitiveResult形式の結果を取得
counts = result[0].data.meas.get_counts()       # PrimitiveResultから回路実行結果を抽出
print(counts)                                   # 結果をテキスト表示:measure_all()の場合、'meas'で結果を取得
```
![exec_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/0cbe58b0-8e78-9aad-f8b4-48e5100e78fc.png)

# (7) 実行結果を確率分布図で確認
確率分布図を出力するコードはシミュレータと一緒です。
理論上では量子ビットq0とq1がもつれているため、出力は00か11になるはずですが、
実機のノイズにより01、10のパターンが少しだけ含まれています。
```python: CNOT_IBMQ.ipynb : 確率分布図
# 確率分布を表示   
plot_distribution(counts)
```
![df44c0bf-c435-45cb-9432-48055f8b2171.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/24dc2621-72f1-4d22-b5b5-a3f69cce1c13.png)

# [実行結果の保存/再取得]
実機での実行結果はしばらくの間IBM Quantumにて自動保存されているので、
JOBIDをキーにして実行結果を再取得できます。
これにより、Python kernel再起動をまたいで実行結果を取得できたり、
90日前の実施結果を取得したりできます。
また、パソコンのディスクに実行結果を保存することができます。
python3.13.2、qiskit2.0の環境では下記のリンクのコードそのまま使えました

https://quantum.cloud.ibm.com/docs/en/guides/save-jobs

# [その他]
```python: CNOT_IBMQ.ipynb : その他
# Qiskitバージョン情報
import qiskit
print(f'qiskit version : {qiskit.__version__}')

# Pythonおよび実行環境情報
import sys, platform
print(f'python version : {sys.version}')
print(f'platform : {platform.uname()}')
```
実行イメージ
![version.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760084/eec66c65-df95-bc81-87c5-8af1d86899f8.png)

## 続きます。
Qiskit環境構築
【uv版】
[(1) Linuxの導入/設定](https://qiita.com/reconcat/items/f30839f3c09600e2a6b2)
[(2) uvの導入/Python仮想環境の作成 ](https://qiita.com/reconcat/items/37a4273547ddd0f6006a)
[(3) vscodeからのPython仮想環境接続](https://qiita.com/reconcat/items/79e1ec4ca9989a08dcd0)

【poetry版】
[(1) Linuxの導入/設定](https://qiita.com/reconcat/items/78ca5bf02fda616d6561)
[(2) Python仮想環境の作成](https://qiita.com/reconcat/items/76507b2743a9f3c40d43)
[(3) vscodeからのPython仮想環境接続](https://qiita.com/reconcat/items/ad4cb6f7c9c273f0ae3f)

【uv/poetry共通】
[(4) シミュレータでの量子回路実行](https://qiita.com/reconcat/items/360d93adddc99a98a3c3)
[(5) IBMQ実機での量子回路実行](https://qiita.com/reconcat/items/4c50c67342d226cb5d7f)
[(6) メンテナンス](https://qiita.com/reconcat/items/50fde8ebf740995f9d7c)