学習実験を構築する
このチュートリアルでは、標準的な学習実験をゼロから構築し、それを用いてシミュレーションによるノイズを含むデータからモデルを学習させる方法について解説します。
- 量子ビットの環上にゲートセットを定義する
- 2局所パウリ・リンドブラッドモデルを選択する
- 学習実験を構築する
- 回路を生成する
- ローカルシミュレーションの設定
- プログラムの実行
- データを分析する
以下の回路はローカルでシミュレーションされるため、この解説では IBM Quantum® の認証情報は必要ありません。 3つの変更により、実際のデバイスに対応するようになりました。各変更箇所には、該当する箇所に再度フラグが付けられています:
- 手順 1 : を実際のバックエンド
FakeMarrakeshに置き換えます。 - ステップ5 :この手順はスキップしてください。
- ステップ6 :…を通じて提出する
Executor。
1. 量子ビットのリング上にゲートセットを定義する
バックエンド Target とその量子ビットのサブセット(ここでは 12 量子ビットの のリング FakeMarrakesh )から QiskitGateSet を構築し、そこに 1 つのゲートを追加する。具体的には、そのリングを覆う 6 つの ゲート CZ からなる層を追加する。 デフォルトでは、ゲートセットは準備ゲートと P 測定ゲートで初期化されます M。
from qiskit_ibm_runtime.fake_provider import FakeMarrakesh
from qiskit_noise_learning.gate_sets import QiskitGateSet
backend = FakeMarrakesh()
qubit_subset = [*range(25, 30), *range(37, 39), *range(45, 50)]
cz_pairs = [(25, 26), (27, 28), (29, 38), (37, 45), (46, 47), (48, 49)]
gate_set = QiskitGateSet(backend.num_qubits, target=backend.target, qubit_subset=qubit_subset)
with gate_set.build_new_gate("cz_gate", latex_str=r"\mathrm{CZ}") as builder:
for pair in cz_pairs:
builder.circuit.cz(*pair)
list(gate_set)['M', 'P', 'cz_gate']
from qiskit_ibm_runtime import QiskitRuntimeService
backend = QiskitRuntimeService().backend("ibm_marrakesh")ゲートを呼び出して、デバイスのトポロジー上のゲートを確認 draw() してください。ゲートセットに含まれる量子ビットの環、およびそのゲートによってどのペアがもつれ合うかがわかります。
gate_set.draw()2. 2局所パウリ・リンドブラッドモデルを選択する
ノイズが持つことが許されるパウリ・リンドブラッド生成子を、. を用いて決定する PauliLindbladModel。 そのジェネレータセットを、ゲートセットの接続性に基づいて構築する―― k_local() ここでは、ユニタリゲートの接続された量子ビットペアに対して2局所パウリ演算を適用し、準備と測定には単一量子ビットのパウリ演算を用いる。
from qiskit_noise_learning.models import PauliLindbladModel
model = PauliLindbladModel.k_local(gate_set, gate_k={"cz_gate": 2, "M": 1, "P": 1})各ゲートのノイズモデルについて、未知のパラメータ数を表示します。
{name: len(generators) for name, generators in model.generators.items()}{'M': 12, 'P': 12, 'cz_gate': 144}
3. 学習実験を構築する
ビルダーの各段階を組み合わせ Experiment ることで、[ ] を組み立てます。 各段階では、それ以前の段階で記述された内容を読み込むため、順序が重要になります:
from qiskit_noise_learning.experiment_builder import (
BindFragmentDepths,
CompleteSequences,
EvenDepthVanillaPaths,
Experiment,
GenerateInstructionSequences,
IdentifyRelations,
MergeInstructionSequences,
SPAMPaths,
VanillaInstructionSequences,
)
experiment_builder = (
# Add standard vanilla learning paths and instruction sequences, and identify relations
EvenDepthVanillaPaths()
+ VanillaInstructionSequences()
+ IdentifyRelations()
# Add paths for learning SPAM, then generate and merge instruction sequences for measuring them
+ SPAMPaths()
+ GenerateInstructionSequences()
+ MergeInstructionSequences()
# Finalize by completing the instruction sequences and setting experiment depths
+ CompleteSequences()
+ BindFragmentDepths([2, 16, 32, 64])
)
experiment = experiment_builder.run(
Experiment(fidelity_model=model, shots=20, randomizations=50)
)
print(f"Number of paths: {len(experiment.paths)}")
print(f"Number of instruction sequences: {len(experiment.instruction_sequences)}")Number of paths: 156
Number of instruction sequences: 37
設計行列のランクに注目してください:
print(f"Design matrix rank: {experiment.design_matrix.rank}")Design matrix rank: 120
4. 回路を生成する
実験を でコンパイルし ExecutorCircuitGenerator、 QuantumProgram — フラグメントの深さごとに1つのパラメータ化されたテンプレート回路 — を生成します。
from qiskit_noise_learning.circuit_generator import ExecutorCircuitGenerator
circuit_generator = ExecutorCircuitGenerator(gate_set)
quantum_program = circuit_generator.generate(experiment)
print(f"Number of template circuits: {len(quantum_program.items)}")Number of template circuits: 5
検査対象の回路図を描いてください。
quantum_program.items[0].circuit.draw("mpl", idle_wires=False, fold=False)
5. ローカルシミュレーションの設定
An は、ローカルの Aer シミュレータ上でプログラムを実行 AerExecutor し、Samplomatic が各ツイールゲートの周囲に配置した障壁に、パウリ・リンドブラッドノイズを注入します。
プロトコルガイドで厳選されたノイズとは異なり、モデルの168個のジェネレータすべてに、 それぞれ独立したランダムな発生率を設定します。 このモデルのジェネレータは、すでに に組み込むべきパウリ演算子そのものであるため PauliLindbladMap、それぞれに発生率を割り当て、ゲートごとにマップを直接構築する:
import numpy as np
from qiskit.quantum_info import PauliLindbladMap
rng = np.random.default_rng(1234)
true_maps = {
name: PauliLindbladMap.from_terms(
[
PauliLindbladMap.GeneratorTerm(rate, generator)
for generator, rate in zip(generators, rng.uniform(2e-4, 1.5e-3, len(generators)))
]
)
for name, generators in model.generators.items()
}
{name: noise_map.num_qubits for name, noise_map in true_maps.items()}{'M': 156, 'P': 156, 'cz_gate': 156}
これらのマップは、モデルがクビットインデックス backendで表現されているため、デバイスと同じ幅になりますが、各マップは適用されるゲートと同じ幅になるようにしたい AerExecutor と考えており、パウリインデックスはゲートのクビットを物理的な順序で昇順に走査するようにします。 を指定して絞り込みます keep_qubits()。これにより、リング外にあるすべての要素がトレースされます:
noise_dict = {
name: noise_map.keep_qubits(qubit_subset) for name, noise_map in true_maps.items()
}
{name: noise_map.num_qubits for name, noise_map in noise_dict.items()}{'M': 12, 'P': 12, 'cz_gate': 12}
スタビライザーメソッド AerExecutor を使用してインスタンス化します。 シミュレーションデータを再現可能にする root_seed よう設定してください。
from qiskit_aer import AerSimulator
from qiskit_noise_learning.aer_executor import AerExecutor
executor = AerExecutor(
AerSimulator(method="stabilizer"), noise_dict=noise_dict, root_seed=42
)この手順は完全にスキップしてください。
6. プログラムを実行する
プログラムを実行し、結果を でフォーマットして collect()、 を作成します。これは Fit 、分析の各段階で読み書きが行われるコンテナです。
job = executor.run(quantum_program)
fit = circuit_generator.collect(job.result())from qiskit_ibm_runtime import Executor
executor = Executor(mode=backend)7. データを分析する
モデルの非負最小二乗法によるフィッティングを中心に、分析パイプラインを構築する。
from qiskit_noise_learning.analysis import (
ComputeObservables, # computes observables from raw data
CurveFitObservables, # performs exponential fitting
LeastSquaresSolve, # solves model with (nonnegative) least squares
)
analyzer = ComputeObservables() + CurveFitObservables() + LeastSquaresSolve()
fit = analyzer.run(fit)/home/kaelyn/projects/open-source/notes/qiskit-noise-learning/qiskit_noise_learning/analysis/model_solve.py:250: UserWarning: 12 of 156 row(s) of the linear system have a non-positive or non-finite uncertainty, so they carry no usable statistical weight. Positions in LinearSystemData.row_labels: 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, and 2 more.
system = LinearSystemData.from_fit(fit)
測定された観測値の平均値を、その適合された指数関数に対してプロットし、1 CZ 組につき1つのサブプロットを作成して、適合されている減衰が本当に指数関数的なものかどうかを確認する。
fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
exponential_fit=True,
)と exponential_fit を入れ替えて、同じデータを、非負最小二乗法による解から得られた率から推測される減衰量と比較 model_prediction します。
fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
model_prediction=True,
)