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

回路を構築する

パッケージバージョン

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

qiskit[all]~=2.3.0

このページでは、Qiskit SDKのQuantumCircuitクラスについて詳しく見ていきます。量子回路を作成するために使用できるより高度なメソッドも含まれています。

量子回路とは何か?

シンプルな量子回路は、量子ビットのコレクションと、それらの量子ビットに作用する命令のリストです。デモンストレーションのために、次のセルは2つの新しい量子ビットを持つ新しい回路を作成し、回路のqubits属性を表示します。これは、最下位ビットq0q_0から最上位ビットqnq_nまで順番に並んだQubitsのリストです。

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
qc.qubits
[<Qubit register=(2, "q"), index=0>, <Qubit register=(2, "q"), index=1>]

複数のQuantumRegisterオブジェクトとClassicalRegisterオブジェクトを組み合わせて回路を作成できます。すべてのQuantumRegisterClassicalRegisterには名前を付けることもできます。

from qiskit.circuit import QuantumRegister, ClassicalRegister

qr1 = QuantumRegister(2, "qreg1") # Create a QuantumRegister with 2 qubits
qr2 = QuantumRegister(1, "qreg2") # Create a QuantumRegister with 1 qubit
cr1 = ClassicalRegister(3, "creg1") # Create a ClassicalRegister with 3 cbits

combined_circ = QuantumCircuit(
qr1, qr2, cr1
) # Create a quantum circuit with 2 QuantumRegisters and 1 ClassicalRegister
combined_circ.qubits
[<Qubit register=(2, "qreg1"), index=0>,
<Qubit register=(2, "qreg1"), index=1>,
<Qubit register=(1, "qreg2"), index=0>]

回路のfind_bitメソッドとその属性を使用して、量子ビットのインデックスとレジスターを見つけることができます。

desired_qubit = qr2[0]  # Qubit 0 of register 'qreg2'

print("Index:", combined_circ.find_bit(desired_qubit).index)
print("Register:", combined_circ.find_bit(desired_qubit).registers)
Index: 2
Register: [(QuantumRegister(1, 'qreg2'), 0)]

回路に命令を追加すると、回路のdata属性に命令が追加されます。次のセル出力は、dataCircuitInstructionオブジェクトのリストであり、それぞれがoperation属性とqubits属性を持つことを示しています。

qc.x(0)  # Add X-gate to qubit 0
qc.data
[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(2, "q"), index=0>,), clbits=())]

この情報を表示する最も簡単な方法は、回路の可視化を返すdrawメソッドを使用することです。量子回路を表示するさまざまな方法については、回路の可視化を参照してください。

qc.draw("mpl")

Output of the previous code cell

回路命令オブジェクトには、より基本的な命令の観点から命令を記述する「定義」回路を含めることができます。たとえば、Xゲートは、より一般的な単一量子ビットゲートであるU3ゲートの特定のケースとして定義されています。

# Draw definition circuit of 0th instruction in `qc`
qc.data[0].operation.definition.draw("mpl")

Output of the previous code cell

命令と回路は、どちらもビットと量子ビットの操作を記述するという点で似ていますが、異なる目的があります:

  • 命令は固定として扱われ、そのメソッドは通常、新しい命令を返します(元のオブジェクトを変更しません)。
  • 回路は、多くのコード行にわたって構築されるように設計されており、QuantumCircuitメソッドは多くの場合、既存のオブジェクトを変更します。

回路の深さとは何か?

量子回路のdepth()は、並列実行される量子ゲートの「レイヤー」の数の尺度であり、回路によって定義される計算を完了するために必要です。量子ゲートの実装には時間がかかるため、回路の深さは、量子コンピューターが回路を実行するのにかかる時間にほぼ対応します。したがって、回路の深さは、量子回路がデバイスで実行できるかどうかを測定するために使用される重要な量の1つです。

このページの残りの部分では、量子回路を操作する方法を説明します。

回路を構築する

QuantumCircuit.hQuantumCircuit.cxなどのメソッドは、特定の命令を回路に追加します。より一般的に回路に命令を追加するには、appendメソッドを使用します。これは、命令と、命令を適用する量子ビットのリストを取ります。サポートされている命令のリストについては、回路ライブラリAPIドキュメントを参照してください。

from qiskit.circuit.library import HGate

qc = QuantumCircuit(1)
qc.append(
HGate(), # New HGate instruction
[0], # Apply to qubit 0
)
qc.draw("mpl")

Output of the previous code cell

2つの回路を結合するには、composeメソッドを使用します。これは、別のQuantumCircuitとオプションの量子ビットマッピングのリストを受け入れます。

備考

composeメソッドは新しい回路を返し、作用する回路を変更しませんcomposeメソッドを呼び出している回路を変更するには、引数inplace=Trueを使用します。

qc_a = QuantumCircuit(4)
qc_a.x(0)

qc_b = QuantumCircuit(2, name="qc_b")
qc_b.y(0)
qc_b.z(1)

# compose qubits (0, 1) of qc_a to qubits (1, 3) of qc_b respectively
combined = qc_a.compose(qc_b, qubits=[1, 3])
combined.draw("mpl")

Output of the previous code cell

また、回路を整理するために、回路を命令にコンパイルすることもできます。to_instructionメソッドを使用して回路を命令に変換し、他の命令と同様に別の回路に追加できます。次のセルで描画される回路は、前のセルで描画される回路と機能的に同等です。

inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])
qc_a.draw("mpl")

Output of the previous code cell

回路がユニタリーである場合、to_gateメソッドを使用してGateに変換できます。Gateオブジェクトは、量子制御を追加するcontrolメソッドなど、いくつかの追加機能を持つ特定のタイプの命令です。

gate = qc_b.to_gate().control()
qc_a.append(gate, [0, 1, 3])
qc_a.draw("mpl")

Output of the previous code cell

何が起こっているかを確認するには、decomposeメソッドを使用して、各命令をその定義に展開できます。

備考

decomposeメソッドは新しい回路を返し、作用する回路を変更しません

qc_a.decompose().draw("mpl")

Output of the previous code cell

量子ビットを測定する

測定は、個々の量子ビットの状態をサンプリングし、結果を古典レジスターに転送するために使用されます。Samplerプリミティブに回路を送信する場合、測定が必要であることに注意してください。ただし、Estimatorプリミティブに送信される回路には測定を含めてはいけません。

量子ビットは、3つのメソッドを使用して測定できます: measuremeasure_allmeasure_active。測定結果を可視化する方法については、結果の可視化ページを参照してください。

  1. QuantumCircuit.measure : 最初の引数の各量子ビットを、2番目の引数として指定された古典ビットに測定します。このメソッドは、測定結果の保存場所を完全に制御できます。

  2. QuantumCircuit.measure_all : 引数を取らず、事前定義された古典ビットのない量子回路に使用できます。古典ワイヤーを作成し、測定結果を順番に保存します。たとえば、量子ビットqiq_iの測定は古典ビットmeasimeas_iに保存されます。また、測定の前にバリアを追加します。

  3. QuantumCircuit.measure_active : measure_allと似ていますが、操作がある量子ビットのみを測定します。

qc1 = QuantumCircuit(2, 2)
qc1.measure(0, 1)
qc1.draw("mpl", cregbundle=False)

Output of the previous code cell

qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)

Output of the previous code cell

qc3 = QuantumCircuit(2)
qc3.x(1)
qc3.measure_active()
qc3.draw("mpl", cregbundle=False)

Output of the previous code cell

パラメータ化された回路

多くの近期量子アルゴリズムは、量子回路の多くのバリエーションを実行することを含みます。大規模な回路の構築と最適化は計算コストが高くなる可能性があるため、Qiskitはパラメータ化された回路をサポートしています。これらの回路には未定義のパラメータがあり、その値は回路を実行する直前まで定義する必要がありません。これにより、回路の構築と最適化をメインプログラムループの外に移動できます。次のセルは、パラメータ化された回路を作成して表示します。

from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit import Parameter

angle = Parameter("angle") # undefined number

# Create and optimize circuit once
qc = QuantumCircuit(1)
qc.rx(angle, 0)
qc = generate_preset_pass_manager(
optimization_level=3, basis_gates=["u", "cx"]
).run(qc)

qc.draw("mpl")

Output of the previous code cell

次のセルは、この回路の多くのバリエーションを作成し、バリエーションの1つを表示します。

circuits = []
for value in range(100):
circuits.append(qc.assign_parameters({angle: value}))

circuits[0].draw("mpl")

Output of the previous code cell

回路の未定義パラメータのリストは、そのparameters属性で見つけることができます。

qc.parameters
ParameterView([Parameter(angle)])

パラメータ名を変更する

デフォルトでは、パラメータ化された回路のパラメータ名にはxがプレフィックスとして付けられます。たとえば、x[0]です。次の例に示すように、定義後に名前を変更できます。

from qiskit.circuit.library import z_feature_map
from qiskit.circuit import ParameterVector

# Define a parameterized circuit with default names
# For example, x[0]
circuit = z_feature_map(2)

# Set new parameter names
# They will now be prefixed by `hi` instead
# For example, hi[0]
training_params = ParameterVector("hi", 2)

# Assign parameter names to the quantum circuit
circuit = circuit.assign_parameters(parameters=training_params)
メソッド名を忘れましたか?Qiskit Code Assistantに聞いてみましょう。

次のステップ

推奨事項