メインコンテンツへスキップ

Qiskit アドオンユーティリティ

パッケージバージョン

このページのコードは、以下の要件を使用して開発されました。 これらのバージョン以降を使用することをお勧めします。

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
qiskit-addon-utils~=0.3.0
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-utils qiskit-ibm-runtime

Qiskit アドオンユーティリティパッケージは、1つ以上の Qiskit アドオンを含むワークフローを補完するための機能のコレクションです。例えば、このパッケージにはハミルトニアンの生成、Trotter 時間発展回路の作成、量子回路のスライスおよび結合を行う関数が含まれています。

インストール

Qiskit アドオンユーティリティをインストールする方法は、PyPI からのインストールとソースからのビルドの2つがあります。パッケージの依存関係を分離するために、仮想環境にインストールすることをお勧めします。

PyPI からのインストール

Qiskit アドオンユーティリティパッケージをインストールする最も簡単な方法は、PyPI を使用することです。

pip install 'qiskit-addon-utils'

ソースからのインストール

こちらをクリックして、このパッケージを手動でインストールする方法をお読みください。

このパッケージにコントリビュートしたい場合や手動でインストールしたい場合は、まずリポジトリをクローンしてください:

git clone git@github.com:Qiskit/qiskit-addon-utils.git

そして、pip 経由でパッケージをインストールします。パッケージリポジトリにあるチュートリアルを実行する予定がある場合は、ノートブックの依存関係もインストールしてください。リポジトリで開発する予定がある場合は、dev の依存関係をインストールしてください。

pip install tox jupyterlab -e '.[notebook-dependencies,dev]'

ユーティリティを使い始める

qiskit-addon-utils パッケージには、量子システムのシミュレーションのための問題生成、量子回路にゲートをより効率的に配置するためのグラフ彩色、および演算子バック伝播に役立つ回路スライシングなど、いくつかのモジュールがあります。以下のセクションでは各モジュールの概要を説明します。パッケージの API ドキュメントにも役立つ情報が掲載されています。

問題生成

qiskit_addon_utils.problem_generators モジュールの内容には以下が含まれます:

  • generate_xyz_hamiltonian() 関数:Ising 型 XYZ モデルの接続性を考慮した SparsePauliOp 表現を生成します:

H=(j,k)E(JxXjXk+JyYjYk+JzZjZk)+jV(hxXj+hyYj+hzZj)H = \sum_{(j,k)\in E} \left(J_x X_jX_k + J_yY_jY_k + J_zZ_jZ_k\right) + \sum_{j\in V} \left(h_x X_j + h_y Y_j + h_z Z_j\right)

  • generate_time_evolution_circuit() 関数:指定された演算子の時間発展をモデル化する回路を構築します。
  • 異なる Pauli 文字列の順序付けを列挙するための3種類の PauliOrderStrategy オブジェクト。これらはグラフ彩色と組み合わせて使用する際に特に有用で、generate_xyz_hamiltonian()generate_time_evolution_circuit() の両関数で引数として使用できます。

グラフ彩色

qiskit_addon_utils.coloring モジュールは、カップリングマップのエッジに色を付け、この彩色を使用して量子回路にゲートをより効率的に配置するために使用されます。エッジ彩色カップリングマップの目的は、同じ色の2つのエッジが共通のノードを共有しないようなエッジカラーのセットを見つけることです。QPU では、同じ色のエッジ(量子ビット接続)に沿ったゲートを同時に実行でき、回路の実行が高速になります。

簡単な例として、auto_color_edges() 関数を使用して、各量子ビット接続に沿って CZGate を実行するナイーブな回路のエッジ彩色を生成できます。以下のコードスニペットは、FakeSherbrooke バックエンドのカップリングマップを使用し、このナイーブな回路を作成した後、auto_color_edges() 関数を使用してより効率的な等価回路を作成します。

from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
from qiskit import QuantumCircuit
from qiskit_addon_utils.coloring import auto_color_edges
from qiskit_addon_utils.slicing import combine_slices, slice_by_depth
from collections import defaultdict

backend = FakeSherbrooke()
coupling_map = backend.coupling_map

# Create naive circuit
circuit = QuantumCircuit(backend.num_qubits)
for edge in coupling_map.graph.edge_list():
circuit.cz(edge[0], edge[1])

# Color the edges of the coupling map
coloring = auto_color_edges(coupling_map)
circuit_with_coloring = QuantumCircuit(backend.num_qubits)

# Make a reverse coloring dict in order to make the circuit
color_to_edge = defaultdict(list)
for edge, color in coloring.items():
color_to_edge[color].append(edge)

# Place edges in order of color
for edges in color_to_edge.values():
for edge in edges:
circuit_with_coloring.cz(edge[0], edge[1])

print(f"The circuit without using edge coloring has depth: {circuit.depth()}")
print(
f"The circuit using edge coloring has depth: {circuit_with_coloring.depth()}"
)
The circuit without using edge coloring has depth: 37
The circuit using edge coloring has depth: 3

スライシング

最後に、qiskit-addon-utils.slicing モジュールには、回路の「スライス」(すべての量子ビットにわたる QuantumCircuit の時間的なパーティション)を作成するための関数およびトランスパイラパスが含まれています。これらのスライスは主に演算子バック伝播に使用されます。回路をスライスする主な4つの方法は、ゲートタイプ、深さ、彩色、または Barrier 命令によるものです。これらのスライシング関数の出力は QuantumCircuit オブジェクトのリストを返します。スライスされた回路は combine_slices() 関数を使用して再結合することもできます。詳細については、モジュールの API リファレンスをお読みください。

以下は、次の回路を使用してこれらのスライスを作成する方法のいくつかの例です:

import numpy as np
from qiskit import QuantumCircuit

num_qubits = 9
qc = QuantumCircuit(num_qubits)
qc.ry(np.pi / 4, range(num_qubits))
qubits_1 = [i for i in range(num_qubits) if i % 2 == 0]
qubits_2 = [i for i in range(num_qubits) if i % 2 == 1]
qc.cx(qubits_1[:-1], qubits_2)
qc.cx(qubits_2, qubits_1[1:])
qc.cx(qubits_1[-1], qubits_1[0])
qc.rx(np.pi / 4, range(num_qubits))
qc.rz(np.pi / 4, range(num_qubits))
qc.draw("mpl", scale=0.6)

Output of the previous code cell

演算子バック伝播のために回路の構造を活用する明確な方法がない場合は、回路を指定された深さのスライスにパーティション分割できます。

# Slice circuit into partitions of depth 1
slices = slice_by_depth(qc, 1)

# Recombine slices in order to visualize the partitions together
combined_slices = combine_slices(slices, include_barriers=True)
combined_slices.draw("mpl", scale=0.6)

Output of the previous code cell

量子システムのダイナミクスをモデル化するために Trotter 回路を実行する場合など、ゲートタイプでスライスすることが有利な場合があります。

from qiskit_addon_utils.slicing import slice_by_gate_types

slices = slice_by_gate_types(qc)

# Recombine slices in order to visualize the partitions together
combined_slices = combine_slices(slices, include_barriers=True)
combined_slices.draw("mpl", scale=0.6)

Output of the previous code cell

ワークロードが実行される QPU の物理的な量子ビット接続性を利用するように設計されている場合は、エッジ彩色に基づいてスライスを作成できます。以下のコードスニペットは、回路エッジに3彩色を割り当て、エッジ彩色に基づいて回路をスライスします。(注意:これは非局所ゲートにのみ影響します。単一量子ビットゲートはゲートタイプでスライスされます。)

from qiskit_addon_utils.slicing import slice_by_coloring

# Assign a color to each set of connected qubits
coloring = {}
for i in range(num_qubits - 1):
coloring[(i, i + 1)] = i % 3
coloring[(num_qubits - 1, 0)] = 2

# Create a circuit with operations added in order of color
qc = QuantumCircuit(num_qubits)
qc.ry(np.pi / 4, range(num_qubits))
edges = [
edge for color in range(3) for edge in coloring if coloring[edge] == color
]
for edge in edges:
qc.cx(edge[0], edge[1])
qc.rx(np.pi / 4, range(num_qubits))
qc.rz(np.pi / 4, range(num_qubits))

# Create slices by edge color
slices = slice_by_coloring(qc, coloring=coloring)

# Recombine slices in order to visualize the partitions together
combined_slices = combine_slices(slices, include_barriers=True)
combined_slices.draw("mpl", scale=0.6)

Output of the previous code cell

カスタムスライシング戦略がある場合は、代わりに回路にバリアを配置してスライスする場所を指定し、slice_by_barriers 関数を使用できます。

qc = QuantumCircuit(num_qubits)
qc.ry(np.pi / 4, range(num_qubits))
qc.barrier()
qubits_1 = [i for i in range(num_qubits) if i % 2 == 0]
qubits_2 = [i for i in range(num_qubits) if i % 2 == 1]
qc.cx(qubits_1[:-1], qubits_2)
qc.cx(qubits_2, qubits_1[1:])
qc.cx(qubits_1[-1], qubits_1[0])
qc.barrier()
qc.rx(np.pi / 4, range(num_qubits))
qc.rz(np.pi / 4, range(num_qubits))
qc.draw("mpl", scale=0.6)

Output of the previous code cell

バリアが配置されると、各スライスを個別に確認できます。

from qiskit_addon_utils.slicing import slice_by_barriers

slices = slice_by_barriers(qc)
slices[0].draw("mpl", scale=0.6)

Output of the previous code cell

slices[1].draw("mpl", scale=0.6)

Output of the previous code cell

slices[2].draw("mpl", scale=0.6)

Output of the previous code cell

次のステップ

推奨事項