メインコンテンツへスキップ
このプロジェクトはベータ版です。バグを見つけましたか?GitHub Issueを開く。質問やアイデアがありますか?Discussionsで質問する — フィードバックをお待ちしています!
このページの翻訳品質はいかがですか?

最初のマネージド・ワークフローをデプロイする

パッケージのバージョン

このページのコードは、次の要件を使用して開発されました。 これらのバージョン、またはそれ以降のバージョンの使用を推奨します。

qiskit[all]~=2.6.1
qiskit-serverless~=0.38.0

このページでは、ワークフローをアップロードして実行し、その結果を取得します。サンプルのワークフローは、Qiskit Circuitを最適化してシミュレーションします。古典ハードウェア上でCircuitをシミュレーションするため、QPU時間は使用しません。

始める前に、クライアントパッケージをインストールして認証してください。

AIスキルの利用(任意)

AIアシスタントの支援を受けて独自のコードをデプロイするには、Qiskit Function templatesリポジトリにあるAIスキルを使用してください。

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"qiskit": "qiskit", "qiskit_ibm_catalog": "qiskit-ibm-catalog", "qiskit_serverless": "qiskit-serverless"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")

ワークフローを書く​

フォルダー構造を作成する​

マネージド・ワークフローは、1つのエントリーポイント・ファイルを持つPythonファイルのフォルダーです。マネージド・ワークフローは、フォルダー内のすべて(最大50 MB)をアップロードし、エントリーポイントをスクリプトとして実行します。ワークフローはフォルダー全体をアップロードするため、deploy.ipynbなどのローカルファイルはフォルダーの外に置いてください。次のレイアウトを作成します。

hello_world_project/
├── deploy.ipynb # Your local notebook: upload and run the workflow
└── source_files/ # The working directory that you upload
└── hello_world.py # The entrypoint

hello worldのエントリーポイントを書く​

エントリーポイントはCircuitを読み取り、それを最適化してシミュレーションし、カウントと2 Qubit深さを保存します。次のコードをsource_files/hello_world.pyとして保存します。

備考

このページをノートブックとして読んでいる場合、hello_world.pyのコードセルは%%writefileマジックコマンドで始まります。このセルを実行すると、コードを実行する代わりに、コードがファイルに保存されます。

# This cell is hidden from users. It creates the working directory.
from pathlib import Path

Path("./source_files").mkdir(exist_ok=True)
%%writefile ./source_files/hello_world.py
from qiskit.primitives import StatevectorSampler
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_serverless import Job, get_arguments, save_result, update_status

# Read the arguments that you pass to run()
arguments = get_arguments()
circuit = arguments["circuit"]
shots = arguments.get("shots", 1024)

# Optimize the circuit. Printed text goes to the job's logs.
update_status(Job.OPTIMIZING_HARDWARE)
pass_manager = generate_preset_pass_manager(
optimization_level=1, basis_gates=["cz", "rz", "sx", "x"]
)
isa_circuit = pass_manager.run(circuit)
two_qubit_depth = isa_circuit.depth(lambda instruction: instruction.operation.num_qubits == 2)
print(f"Two-qubit depth after optimization: {two_qubit_depth}", flush=True)

# Simulate the circuit and return the counts
sampler = StatevectorSampler(seed=1234)
pub_result = sampler.run([isa_circuit], shots=shots).result()[0]
save_result({"counts": pub_result.data.meas.get_counts(), "two_qubit_depth": two_qubit_depth})
Writing ./source_files/hello_world.py

エントリーポイントは、qiskit_serverlessの3つの関数を使用します。

  • get_arguments()は、run()に渡したキーワード引数を辞書として返します。各値は、JSONシリアライズ可能であるか、QuantumCircuitのようにクライアントがエンコードできるオブジェクトである必要があります。エンコードされたオブジェクトは、渡したものと同じオブジェクトとして届きます。

  • update_status(Job.OPTIMIZING_HARDWARE)は、詳細ステータスをRUNNING: OPTIMIZING_FOR_HARDWAREに設定します。これはジョブの実行中に確認できます。update_status()で進捗を報告するを参照してください。

  • save_result()は、後でjob.result()で読み取れるJSONシリアライズ可能な値を保存します。このワークフローは、カウントを辞書として、最適化されたCircuitの2 Qubit深さを整数として返します。

2 Qubit深さなど、ワークフローが標準出力に書き込んだものはすべて、ジョブのログに送られます。タイムスタンプとログレベルを追加するには、loggingモジュールを使用します。ログの書き込みとエラー処理を参照してください。

ワークフローをアップロードする​

ローカルのノートブックで、hello_world_projectフォルダーから次のコードを実行します。このコードは、保存済みのアカウントで接続し、ワークフローを定義してアップロードします。entrypointはワークフローが実行するファイル、working_dirはアップロードするフォルダーです。

from qiskit_ibm_catalog import ManagedWorkflow, ManagedWorkflowClient

client = ManagedWorkflowClient()

hello_world = ManagedWorkflow(
title="hello-world",
entrypoint="hello_world.py",
working_dir="./source_files/",
)

hello_world = client.upload(hello_world)

入力を指定してワークフローを実行する​

hello_worldへの入力として渡す、3 QubitのGHZ Circuitを構築します。

from qiskit import QuantumCircuit

circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure_all()

Circuitとショット数をキーワード引数としてhello_worldを実行します。引数名は、エントリーポイントがget_arguments()で読み取るキーと一致します。

job = hello_world.run(circuit=circuit, shots=1024)
print(job.job_id)
54705348-5117-44b7-935b-e6986ef182fa

run()は、ワークフローがジョブをキューに入れた後にJobを返します。ジョブが実行されるのを待ちません。Pythonセッションを閉じた後も、ジョブはクラウド上で継続します。後でもう一度見つけるには、client.jobs()で最近のジョブを一覧表示します。

ステータス、結果、ログを取得する​

run()を呼び出した直後は、通常、ステータスはQUEUEDです。

job.status()
'QUEUED'

ステータスは、QUEUEDからINITIALIZING、RUNNING、そしてDONEへと変化します。

job.result()は、ジョブが終了するまで待機し、ワークフローがsave_result()に渡した値を返します。

job.result()
{'counts': {'111': 514, '000': 510}, 'two_qubit_depth': 2}
# This cell is hidden from users. It checks the result.
assert set(_["counts"]) <= {"000", "111"} # noqa: F821
assert sum(_["counts"].values()) == 1024 # noqa: F821
from qiskit.visualization import plot_histogram

plot_histogram(job.result()["counts"])

Output of the previous code cell

ジョブの実行中にログを読み取ることができます。ワークフローは、約15秒ごとに新しい行をアップロードします。ログには、ワークフローが出力した行が含まれます。

print(job.logs())
Two-qubit depth after optimization: 2
# This cell is hidden from users. It checks the logs.
assert "Two-qubit depth after optimization" in job.logs()

ワークフローを更新する​

ワークフローを変更するには、そのファイルを編集し、同じtitleで再度upload()を呼び出します。新しいアップロードは以前のものを置き換え、すでに開始されたジョブには影響しません。

arguments_schemaやsizes_mapなどのフィールドは、新しいアップロードで省略した場合、保存されている値が保持されます。

次のステップ​

推奨事項