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

古典フィードフォワードと制御フロー(動的回路)

パッケージバージョン

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

qiskit[all]~=2.4.0

動的回路は強力なツールであり、量子回路の実行中にQubitを測定し、その中回路測定の結果に基づいて回路内で古典的な論理演算を実行することができます。このプロセスは_古典フィードフォワード_とも呼ばれます。動的回路を最大限に活用する方法についてはまだ初期段階ですが、量子研究コミュニティはすでにいくつかのユースケースを特定しています。例えば以下のものがあります:

if

if文は、古典ビットまたはレジスタの値に基づいて条件付きで演算を実行するために使用します。

以下の例では、QubitにHadamardゲートを適用して測定します。結果が1の場合、QubitにXゲートを適用します。これにより、Qubitを0の状態に戻します。次に、Qubitを再度測定します。結果として得られる測定結果は、100%の確率で0になるはずです。

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
circuit = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)):
circuit.x(q0)
circuit.measure(q0, c0)
circuit.draw("mpl")

# example output counts: {'0': 1024}

Output of the previous code cell

with文には代入ターゲットを指定することができます。これ自体もコンテキストマネージャーであり、格納してその後elseブロックの作成に使用できます。elseブロックは、ifブロックの内容が実行されない場合に常に実行されます。

以下の例では、2つのQubitと2つの古典ビットのレジスタを初期化します。最初のQubitにHadamardゲートを適用して測定します。結果が1の場合、2番目のQubitにHadamardゲートを適用します。それ以外の場合は、2番目のQubitにXゲートを適用します。最後に、2番目のQubitも測定します。

qubits = QuantumRegister(2)
clbits = ClassicalRegister(2)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1) = qubits
(c0, c1) = clbits

circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)) as else_:
circuit.h(q1)
with else_:
circuit.x(q1)
circuit.measure(q1, c1)

circuit.draw("mpl")

# example output counts: {'01': 260, '11': 272, '10': 492}

Output of the previous code cell

単一の古典ビットを条件とするだけでなく、複数のビットで構成される古典レジスタの値を条件とすることも可能です。

以下の例では、2つのQubitにHadamardゲートを適用して測定します。結果が01(つまり、最初のQubitが1で2番目のQubitが0)の場合、3番目のQubitにXゲートを適用します。最後に、3番目のQubitを測定します。なお、わかりやすくするために、if条件で3番目の古典ビットの状態(0)を明示的に指定しています。回路図では、条件は条件付けされている古典ビット上の丸で示されます。塗りつぶされた丸は1への条件付けを示し、輪郭のみの丸は0への条件付けを示します。

qubits = QuantumRegister(3)
clbits = ClassicalRegister(3)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1, q2) = qubits
(c0, c1, c2) = clbits

circuit.h([q0, q1])
circuit.measure(q0, c0)
circuit.measure(q1, c1)
with circuit.if_test((clbits, 0b001)):
circuit.x(q2)
circuit.measure(q2, c2)

circuit.draw("mpl")

# example output counts: {'101': 269, '011': 260, '000': 252, '010': 243}

Output of the previous code cell

古典式

Qiskitの古典式モジュールqiskit.circuit.classicalには、回路実行中に古典値に対するランタイム演算の試験的な表現が含まれています。ハードウェアの制限により、現在はQuantumCircuit.if_test()の条件のみがサポートされています。

以下の例では、パリティの計算を使用して動的回路でn-QubitのGHZ状態を作成する方法を示します。まず、隣接するQubitにn/2n/2個のBellペアを生成します。次に、ペア間のCNOTゲート層を使用してこれらのペアを結合します。その後、以前のすべてのCNOTゲートのターゲットQubitを測定し、測定された各Qubitを状態0\vert 0 \rangleにリセットします。先行するすべてのビットのパリティが奇数である測定されていないすべてのサイトにXXを適用します。最後に、測定されたQubitにCNOTゲートを適用して、測定で失われたエンタングルメントを再確立します。

パリティ計算では、構築された式の最初の要素はPythonオブジェクトmr[0]Valueノードに持ち上げることを含みます(liftは任意のオブジェクトを古典式に変換するために使用されます)。mr[1]と後続の可能な古典レジスタについては、これは必要ありません。これらはexpr.bit_xorへの入力であり、必要な持ち上げはこれらの場合に自動的に行われるためです。このような式はループやその他の構造で構築できます。

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit.classical import expr

num_qubits = 8
if num_qubits % 2 or num_qubits < 4:
raise ValueError("num_qubits must be an even integer ≥ 4")
meas_qubits = list(range(2, num_qubits, 2)) # qubits to measure and reset

qr = QuantumRegister(num_qubits, "qr")
mr = ClassicalRegister(len(meas_qubits), "m")
qc = QuantumCircuit(qr, mr)

# Create local Bell pairs
qc.reset(qr)
qc.h(qr[::2])
for ctrl in range(0, num_qubits, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])

# Glue neighboring pairs
for ctrl in range(1, num_qubits - 1, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])

# Measure boundary qubits between pairs,reset to 0
for k, q in enumerate(meas_qubits):
qc.measure(qr[q], mr[k])
qc.reset(qr[q])

# Parity-conditioned X corrections
# Each non-measured qubit gets flipped iff the parity (XOR) of all
# preceding measurement bits is 1
for tgt in range(num_qubits):
if tgt in meas_qubits: # skip measured qubits
continue
# all measurement registers whose physical qubit index < tgt
left_bits = [k for k, q in enumerate(meas_qubits) if q < tgt]
if not left_bits: # skip if list empty
continue

# build XOR-parity expression
parity = expr.lift(
mr[left_bits[0]]
) # lift the first bit to Value so it will be treated like a boolean.
for k in left_bits[1:]:
parity = expr.bit_xor(
mr[k], parity
) # calculate parity with all other bits
with qc.if_test(parity): # Add X if parity is 1
qc.x(qr[tgt])

# Re-entangle measured qubits
for ctrl in range(1, num_qubits - 1, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])
qc.draw(output="mpl", style="iqp", idle_wires=False, fold=-1)

Output of the previous code cell

次のステップ

推奨事項