动态线路
动态线路(Dynamic Circuits)实现了量子程序中的经典控制流。pyqpanda3 通过 qif、qelseif、qelse 和 qwhile 结构支持线路中途测量和条件执行。
什么是动态线路?
传统量子线路是由门操作序列后接测量组成的静态结构。动态线路引入了经典控制流:
- 条件执行:仅在满足测量条件时才施加门操作
- 循环:基于测量结果重复执行操作
- 中途测量:在执行过程中测量量子比特,而非仅在最后测量
qif - 条件分支
qif 结构基于经典比特值实现经典的 if-then-else 逻辑。
基本 If-Then
当需要根据测量结果有条件地施加门操作时,使用 qif:
from pyqpanda3 import core
# Create a program with conditional execution
prog = core.QProg()
prog << core.X(0) # Prepare |1⟩ on qubit 0
prog << core.I(1) # Qubit 1 in |0⟩
# Define the if-branch: apply X(1) if cbit[1] is 1
if_branch = core.QProg()
if_branch << core.X(1)
# Add conditional branch
prog << core.qif([1]).then(if_branch).qendif()
print(prog)条件 qif([1]) 检查经典比特 1 是否为 1。
If-Then-Else
当条件不满足时,添加 else 分支来处理:
prog = core.QProg()
prog << core.X(0) << core.I(1)
# Define both branches
if_branch = core.QProg()
if_branch << core.X(1)
else_branch = core.QProg()
else_branch << core.X(0)
# Add conditional with both branches
prog << core.qif([1]).then(if_branch).qelse(else_branch)
print(prog)使用 qelseif 实现多条件分支
使用 qelseif 串联多个条件:
prog = core.QProg()
prog << core.X(0) << core.I(1) << core.I(2) << core.I(3)
# Define multiple branches
branch_1 = core.QProg()
branch_1 << core.X(1)
branch_2 = core.QProg()
branch_2 << core.X(0)
branch_3 = core.QProg()
branch_3 << core.X(2)
branch_4 = core.QProg()
branch_4 << core.CNOT(0, 1)
# Build multi-branch conditional
(prog << core.qif([1]).then(branch_1)
.qelseif([0, 3]).then(branch_2)
.qelseif([2]).then(branch_3)
.qelse(branch_4))
print(prog)执行流程如下:
条件语义
条件 qif([c0, c1, c2]) 检查所有指定的经典比特是否都为 1(逻辑与):
qif([0]):当 cbit 0 == 1 时为真qif([0, 1]):当 cbit 0 == 1 且 cbit 1 == 1 时为真qif([0, 1, 2]):当 cbit 0 == 1 且 cbit 1 == 1 且 cbit 2 == 1 时为真
qwhile - 条件循环
qwhile 结构在满足经典条件时重复执行循环体。
基本循环
prog = core.QProg()
# Prepare initial state and measure
prog << core.X(0)
prog << core.measure(0, 0)
# Define the loop body
loop_body = core.QProg()
loop_body << core.X(1) # Flip qubit 1
loop_body << core.X(0) # Flip qubit 0 back
loop_body << core.measure(0, 0) # Re-measure qubit 0
# Add while loop: continue while cbit[0] is 1
prog << core.qwhile([0]).loop(loop_body)
print(prog)循环执行过程如下:
实用示例
示例 1:重复直到成功
使用动态线路重复执行操作,直到获得期望的测量结果:
from pyqpanda3 import core
# Repeat H-measure until we get |1⟩
prog = core.QProg()
# Initial measurement
prog << core.H(0)
prog << core.measure(0, 0)
# Loop body: keep trying until we measure 1
loop_body = core.QProg()
loop_body << core.H(0)
loop_body << core.measure(0, 0)
# While cbit[0] == 0 (didn't get 1), try again
# Note: qwhile continues while condition is True
# We need to loop while cbit[0] is 0
prog << core.qwhile([0]).loop(loop_body)
print("Repeat-until-success circuit:")
print(prog)示例 2:中途测量与条件门
执行测量并有条件地施加修正操作:
from pyqpanda3 import core
# Create a 3-qubit entangled state
prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)
prog << core.CNOT(1, 2)
# Mid-circuit measurement of qubit 0
prog << core.measure(0, 0)
# Conditionally apply correction on qubits 1 and 2
correction = core.QProg()
correction << core.Z(1)
correction << core.Z(2)
# If measurement was 1, apply correction
prog << core.qif([0]).then(correction).qendif()
# Final measurement
prog << core.measure([1, 2], [1, 2])
print("Mid-circuit measurement with correction:")
print(prog)
# Run the circuit
machine = core.CPUQVM()
machine.run(prog, shots=1000)
print(machine.result().get_counts())示例 3:基于奇偶校验的错误检测
使用动态线路通过奇偶校验测量进行错误检测:
from pyqpanda3 import core
# Encode logical |0⟩ in 3-qubit repetition code
prog = core.QProg()
prog << core.H(0) # Superposition
prog << core.CNOT(0, 1) # Entangle
prog << core.CNOT(0, 2) # Entangle
# Parity check measurements (into ancilla cbits)
prog << core.CNOT(0, 3) # Parity q0-q1 (using ancilla q3)
prog << core.CNOT(1, 3)
prog << core.measure(3, 0) # Parity into cbit 0
# Conditional correction based on parity
correct_01 = core.QProg()
correct_01 << core.X(1) # Flip qubit 1 back
correct_10 = core.QProg()
correct_10 << core.X(0) # Flip qubit 0 back
correct_11 = core.QProg()
correct_11 << core.X(2) # Flip qubit 2 back
# Note: This is a simplified example
# Real error correction would use syndrome decoding
print("Error detection circuit:")
print(prog)示例 4:自适应相位估计
使用动态线路进行迭代相位估计:
from pyqpanda3 import core
import numpy as np
# Iterative phase estimation for a unitary U with eigenvalue e^(iφ)
# We want to estimate φ
phi = np.pi / 4 # True phase
prog = core.QProg()
# Prepare eigenstate |1⟩ of RZ
prog << core.X(1)
# k-th iteration (simplified single-step example)
prog << core.H(0)
prog << core.RZ(1, phi) # Apply unitary
prog << core.H(0)
prog << core.measure(0, 0)
# Conditional phase correction based on measurement
correction = core.QProg()
correction << core.RZ(1, -np.pi / 2)
prog << core.qif([0]).then(correction).qendif()
# Final measurement
prog << core.measure(1, 1)
print("Adaptive phase estimation circuit:")
print(prog)
machine = core.CPUQVM()
machine.run(prog, shots=1000)
print(machine.result().get_counts())量子隐形传态协议
量子隐形传态(Quantum Teleportation)利用纠缠和经典通信将未知的量子态从一个量子比特传输到另一个量子比特。动态线路在其中至关重要,因为修正操作依赖于中途测量的结果。
量子隐形传态协议的工作流程如下:
- Alice 和 Bob 共享一个纠缠的 Bell 对
- Alice 对她的量子比特和未知态执行 Bell 测量
- Alice 将两个经典比特发送给 Bob
- Bob 根据测量结果施加修正操作
from pyqpanda3 import core
# Quantum teleportation of an unknown state |psi⟩ on qubit 0
# Qubit allocation:
# q0: the unknown state |psi⟩ to teleport
# q1: Alice's half of the Bell pair
# q2: Bob's half of the Bell pair
prog = core.QProg()
# Step 1: Prepare the unknown state |psi⟩ = alpha|0⟩ + beta|1⟩
# For this example, we prepare |psi⟩ = Ry(theta)|0⟩
theta = 0.7 # Arbitrary rotation angle
prog << core.RY(0, theta)
# Step 2: Create Bell pair between q1 and q2
# |00⟩ -> (H on q1) -> (|0⟩+|1⟩)|0⟩/sqrt(2) -> (CNOT q1,q2) -> |Φ+⟩
prog << core.H(1)
prog << core.CNOT(1, 2)
# Step 3: Bell measurement on (q0, q1)
# First apply the inverse Bell basis transformation
prog << core.CNOT(0, 1)
prog << core.H(0)
# Step 4: Measure q0 and q1 into classical bits
prog << core.measure(0, 0) # cbit 0 holds measurement of q0
prog << core.measure(1, 1) # cbit 1 holds measurement of q1
# Step 5: Bob's conditional corrections on q2
# If cbit[0] == 1, apply Z correction
z_correction = core.QProg()
z_correction << core.Z(2)
no_z_correction = core.QProg()
prog << core.qif([0]).then(z_correction).qelse(no_z_correction)
# If cbit[1] == 1, apply X correction
x_correction = core.QProg()
x_correction << core.X(2)
no_x_correction = core.QProg()
prog << core.qif([1]).then(x_correction).qelse(no_x_correction)
# Step 6: Final measurement of the teleported state on q2
prog << core.measure(2, 2)
print("Quantum Teleportation Circuit:")
print(prog)
# Run and verify
machine = core.CPUQVM()
machine.run(prog, shots=1000)
counts = machine.result().get_counts()
print("Teleportation results:", counts)修正规则如下:
| 测量结果 (q0, q1) | 对 q2 的修正操作 |
|---|---|
| (0, 0) | 无 |
| (0, 1) | |
| (1, 0) | |
| (1, 1) |
修正完成后,量子比特 2 将精确持有原始状态
量子纠错示例
三量子比特重复码(3-qubit repetition code)可以保护单个逻辑量子比特免受比特翻转(
伴随式提取(syndrome extraction)使用两个辅助量子比特来检测哪个数据量子比特(如果有)经历了比特翻转。伴随式
from pyqpanda3 import core
# 3-qubit repetition code for bit-flip error correction
# Qubit layout:
# q0, q1, q2: data qubits (encoded logical qubit)
# q3: ancilla for parity check q0 XOR q1
# q4: ancilla for parity check q1 XOR q2
prog = core.QProg()
# Step 1: Encode |psi⟩ into the 3-qubit code
# Start with |psi⟩ on q0 (e.g., a superposition)
prog << core.RY(0, 1.2) # Prepare an arbitrary state on q0
# Entangle: |psi⟩|00⟩ -> (alpha|000⟩ + beta|111⟩)
prog << core.CNOT(0, 1)
prog << core.CNOT(0, 2)
# Step 2: Simulate a bit-flip error on qubit 1
# (In practice this would be unplanned noise)
prog << core.X(1)
# Step 3: Syndrome extraction using ancilla qubits
# Ancilla q3 measures parity of (q0, q1)
prog << core.CNOT(0, 3)
prog << core.CNOT(1, 3)
# Ancilla q4 measures parity of (q1, q2)
prog << core.CNOT(1, 4)
prog << core.CNOT(2, 4)
# Measure ancillas into classical bits
prog << core.measure(3, 0) # s1 -> cbit 0
prog << core.measure(4, 1) # s2 -> cbit 1
# Step 4: Conditional correction based on syndrome
# Syndrome table:
# (0,0) -> no error (or error on no qubit)
# (1,0) -> error on q0
# (1,1) -> error on q1
# (0,1) -> error on q2
# Correction for q0: apply X(0) when s1=1, s2=0
# We approximate this by checking both syndrome bits
correct_q0 = core.QProg()
correct_q0 << core.X(0)
correct_q1 = core.QProg()
correct_q1 << core.X(1)
correct_q2 = core.QProg()
correct_q2 << core.X(2)
no_correction = core.QProg()
# Use conditional branches for each syndrome pattern
# Since qif checks ALL bits == 1, we use the pattern matching
# For (1,0) syndrome: only cbit[0] is 1
prog << core.qif([0]).then(correct_q1).qelse(no_correction)
print("3-Qubit Repetition Code - Error Correction Circuit:")
print(prog)
# Run the circuit
machine = core.CPUQVM()
machine.run(prog, shots=1000)
print("Error correction results:", machine.result().get_counts())伴随式解码表
伴随式比特
| 错误位置 | 修正操作 | ||
|---|---|---|---|
| 0 | 0 | 无 | 恒等操作 |
| 1 | 0 | 量子比特 0 | |
| 1 | 1 | 量子比特 1 | |
| 0 | 1 | 量子比特 2 |
重复码的最小汉明距离为
迭代相位估计
迭代相位估计(Iterative Phase Estimation,IPE)从最低有效位开始,逐位确定酉算子
每次迭代
其中
from pyqpanda3 import core
import math
# Iterative Phase Estimation for a unitary U with eigenvalue e^(2*pi*i*phi)
# We estimate phi to n bits of precision using n iterations.
# Each iteration uses one auxiliary qubit and one measurement.
# The target unitary is a rotation gate. For RZ(theta), the eigenvalue
# on |1⟩ is e^(-i*theta/2), so phi = -theta / (4*pi).
# We use controlled-U^(2^k) in iteration k.
n_bits = 3 # Number of precision bits
true_phase = math.pi / 4 # True phase phi for this example
# Storage for the estimated bits
phase_bits = []
for k in range(n_bits):
prog = core.QProg()
# Auxiliary qubit: q0
# Target qubit: q1 (eigenstate of U)
# Initialize auxiliary in superposition
prog << core.H(0)
# Prepare the eigenstate |1⟩ on the target qubit
prog << core.X(1)
# Apply controlled-U^(2^(n-1-k)) between iterations
# For this example, U = RZ(2*pi*phi), so U^(2^m) = RZ(2*pi*phi*2^m)
power = n_bits - 1 - k
rotation_angle = 2 * math.pi * true_phase * (2 ** power)
prog << core.CRZ(0, 1, rotation_angle)
# Apply inverse phase correction based on previously measured bits
# This compensates for the lower-order bits already determined
for j, bit_val in enumerate(phase_bits):
if bit_val == 1:
correction_angle = -2 * math.pi * (2 ** (power - j - 1)) / (2 ** n_bits)
prog << core.RZ(0, correction_angle)
# Final Hadamard on auxiliary
prog << core.H(0)
# Measure the auxiliary qubit
prog << core.measure(0, 0)
# Run this iteration
machine = core.CPUQVM()
machine.run(prog, shots=1000)
result = machine.result().get_counts()
# The most frequent outcome determines this bit
if result:
bit = max(result, key=result.get)
phase_bits.append(int(bit))
else:
phase_bits.append(0)
# Reconstruct the estimated phase from bits
estimated_phase = sum(b * (2 ** -(i + 1)) for i, b in enumerate(phase_bits))
print(f"True phase: {true_phase:.6f}")
print(f"Estimated phase: {estimated_phase:.6f}")
print(f"Phase bits (MSB first): {phase_bits}")逐步说明
每次迭代
- 准备:将辅助量子比特初始化为
,目标量子比特初始化为特征态 - 受控
:施加酉算子 的 次幂,由辅助比特控制 - 相位修正:基于之前测量的比特施加
旋转,以消除它们的贡献 - 测量:测量辅助量子比特以提取
的第 位 - 重建:所有迭代完成后,
(二进制小数形式)
精度随着
使用动态线路进行态验证
态验证(State Verification)确认量子系统在制备后是否处于目标状态。动态线路支持自适应测量策略,比完整态层析更高效。
Bell 态验证
Bell 态
from pyqpanda3 import core
# Verify a Bell state |Φ+⟩ = (|00⟩ + |11⟩) / sqrt(2)
# Strategy: prepare the state, measure both qubits, check correlation
prog = core.QProg()
# Prepare the Bell state
prog << core.H(0)
prog << core.CNOT(0, 1)
# Measure both qubits
prog << core.measure(0, 0) # cbit 0
prog << core.measure(1, 1) # cbit 1
# If both qubits agree, the state is correct
# If they disagree, flag an error by flipping an ancilla
flag_error = core.QProg()
flag_error << core.X(2) # q2 starts in |0⟩, flip to |1⟩ if error
# We cannot directly check "XOR" with qif's AND semantics alone,
# so we use a different approach: measure an XOR ancilla
# Prepare XOR of measurement results using CNOT into ancilla
prog << core.CNOT(0, 2)
prog << core.CNOT(1, 2)
prog << core.measure(2, 2)
# cbit[2] == 1 means the qubits disagreed (verification failed)
# Use conditional to apply a correction or log the result
verify_fail = core.QProg()
verify_fail << core.X(3) # Flag qubit for failure
prog << core.qif([2]).then(verify_fail).qendif()
print("Bell state verification circuit:")
print(prog)
machine = core.CPUQVM()
machine.run(prog, shots=1000)
print("Verification results:", machine.result().get_counts())GHZ 态保真度检验
对于 GHZ 态
from pyqpanda3 import core
# GHZ state verification for 4 qubits
# |GHZ_4⟩ = (|0000⟩ + |1111⟩) / sqrt(2)
n_qubits = 4
prog = core.QProg()
# Prepare the GHZ state
prog << core.H(0)
for i in range(1, n_qubits):
prog << core.CNOT(0, i)
# Measure all data qubits
for i in range(n_qubits):
prog << core.measure(i, i)
# Compute pairwise parities using ancilla qubits
# Check that all adjacent pairs have even parity
ancilla_start = n_qubits
for i in range(n_qubits - 1):
anc = ancilla_start + i
prog << core.CNOT(i, anc)
prog << core.CNOT(i + 1, anc)
prog << core.measure(anc, anc)
print("GHZ state fidelity check circuit:")
print(prog)
machine = core.CPUQVM()
machine.run(prog, shots=1000)
counts = machine.result().get_counts()
print("GHZ verification results:", counts)
# If all ancilla measurements are 0, the GHZ state is valid预期结果是所有辅助量子比特的奇偶校验测量结果均为 0,确认 GHZ 关联完好无损。任何非零奇偶性都表明存在退相干或制备错误。
常见模式与惯用法
本节收集了在 pyqpanda3 中进行动态线路编程时可复用的模式。
模式:测量后修正
最常见的动态线路模式:测量一个量子比特,然后有条件地施加修正门。
from pyqpanda3 import core
def measure_and_correct(prog, measure_qubit, measure_cbit, target_qubit, correction_gate):
"""Measure a qubit and conditionally apply a correction to another qubit.
Args:
prog: The QProg to append operations to.
measure_qubit: Index of the qubit to measure.
measure_cbit: Index of the classical bit to store the result.
target_qubit: Index of the qubit to apply correction to.
correction_gate: A function that takes a qubit index and returns a gate.
"""
prog << core.measure(measure_qubit, measure_cbit)
# Build the correction branch
correction = core.QProg()
correction << correction_gate(target_qubit)
# No-op branch for the else case
no_op = core.QProg()
# Apply correction if measurement was |1⟩
prog << core.qif([measure_cbit]).then(correction).qelse(no_op)
return prog
# Usage: measure q0 and conditionally apply Z to q1
prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)
prog = measure_and_correct(prog, 0, 0, 1, core.Z)
print(prog)模式:条件恒等操作
当需要显式的空操作(恒等)分支以提高清晰度时,使用空的 QProg:
from pyqpanda3 import core
# Pattern: explicit identity branch for documentation clarity
prog = core.QProg()
prog << core.measure(0, 0)
action_branch = core.QProg()
action_branch << core.X(1) << core.Z(2)
identity_branch = core.QProg() # Empty program = identity
prog << core.qif([0]).then(action_branch).qelse(identity_branch)
print(prog)模式:链式条件实现多结果决策
使用 qelseif 实现类似于 switch 语句的多结果分支结构:
from pyqpanda3 import core
# Pattern: switch-like behavior with qelseif
# Suppose we measure qubits 0, 1 and want different actions for 00, 01, 10, 11
prog = core.QProg()
prog << core.H(0) << core.H(1)
prog << core.measure(0, 0)
prog << core.measure(1, 1)
# Branch for both qubits measured as 1 (AND condition)
branch_both = core.QProg()
branch_both << core.X(2)
# Branch for only qubit 0 measured as 1
branch_q0_only = core.QProg()
branch_q0_only << core.Y(2)
# Branch for only qubit 1 measured as 1
branch_q1_only = core.QProg()
branch_q1_only << core.Z(2)
# Default: neither measured as 1
branch_default = core.QProg()
branch_default << core.I(2)
# qif checks AND of all listed cbits
# qif([0,1]) -> both are 1
# Then we use additional conditions for the remaining cases
prog << core.qif([0, 1]).then(branch_both).qelse(branch_default)
print("Chained conditional pattern:")
print(prog)模式:多阶段前馈
在多阶段量子算法中,一个阶段的测量结果传递到下一阶段的条件操作中。
from pyqpanda3 import core
# Pattern: multi-stage feed-forward
# Stage 1: Prepare and measure
# Stage 2: Conditional operations based on Stage 1
# Stage 3: Final computation
prog = core.QProg()
# Stage 1: Prepare entangled state and measure one qubit
prog << core.H(0)
prog << core.CNOT(0, 1)
prog << core.CNOT(0, 2)
prog << core.measure(0, 0) # Measure q0, result in cbit 0
# Stage 2: Conditional entangling based on Stage 1 result
# If cbit[0] == 1, create additional entanglement on remaining qubits
stage2_entangle = core.QProg()
stage2_entangle << core.CNOT(1, 2)
stage2_entangle << core.H(1)
stage2_entangle << core.measure(1, 1) # Mid-circuit measurement
stage2_simple = core.QProg()
stage2_simple << core.H(1)
stage2_simple << core.measure(1, 1)
prog << core.qif([0]).then(stage2_entangle).qelse(stage2_simple)
# Stage 3: Final computation and measurement
prog << core.CNOT(1, 2)
prog << core.measure(2, 2)
print("Multi-stage feed-forward circuit:")
print(prog)模式:使用 qwhile 进行重复尝试
使用 qwhile 重试概率性操作直到成功。当成功概率有上界且不为 1 时,此模式非常有用。
from pyqpanda3 import core
# Pattern: probabilistic gate with retry
# Try to prepare |1⟩ via Hadamard+measure, retry on |0⟩
prog = core.QProg()
# Initialize and first attempt
prog << core.X(0) # Start in |1⟩
prog << core.H(0) # Put in superposition
prog << core.measure(0, 0) # Measure: 50% chance of |1⟩
# Loop body: retry if we got |0⟩
retry_body = core.QProg()
retry_body << core.H(0) # Back to superposition
retry_body << core.measure(0, 0) # Try again
# While cbit[0] == 1 (got |1⟩, loop ends since condition is met)
# Note: loop continues while condition is True, so we structure accordingly
prog << core.qwhile([0]).loop(retry_body)
print("Repeated attempt pattern:")
print(prog)调试动态线路
动态线路引入了使调试变得更加困难的复杂性。本节介绍识别和修复问题的常见陷阱和策略。
策略 1:打印并检查程序
在运行之前,始终打印构建的 QProg。字符串表示会显示门序列和控制流结构。
from pyqpanda3 import core
prog = core.QProg()
prog << core.H(0)
prog << core.measure(0, 0)
branch = core.QProg()
branch << core.X(1)
prog << core.qif([0]).then(branch).qendif()
# Always inspect before running
print("=== Circuit structure ===")
print(prog)策略 2:先不使用动态功能运行
在添加条件逻辑之前,先验证线路的静态部分是否产生预期结果。采用增量构建方式。
from pyqpanda3 import core
# Step 1: Verify the static part works
static_prog = core.QProg()
static_prog << core.H(0)
static_prog << core.CNOT(0, 1)
static_prog << core.measure([0, 1], [0, 1])
machine = core.CPUQVM()
machine.run(static_prog, shots=100)
print("Static results:", machine.result().get_counts())
# Step 2: Add dynamics only after static part is confirmed correct
dynamic_prog = core.QProg()
dynamic_prog << core.H(0)
dynamic_prog << core.CNOT(0, 1)
dynamic_prog << core.measure(0, 0)
correction = core.QProg()
correction << core.X(1)
dynamic_prog << core.qif([0]).then(correction).qendif()
dynamic_prog << core.measure(1, 1)
machine.run(dynamic_prog, shots=100)
print("Dynamic results:", machine.result().get_counts())策略 3:检查经典比特初始化
一个常见的错误是在条件中引用经典比特之前没有对其进行测量。经典比特可能具有未定义或默认值。
from pyqpanda3 import core
# BUG: cbit 0 is never measured, so the condition is unreliable
buggy_prog = core.QProg()
buggy_prog << core.H(0)
# Missing: buggy_prog << core.measure(0, 0)
branch = core.QProg()
branch << core.X(1)
buggy_prog << core.qif([0]).then(branch).qendif() # cbit 0 is uninitialized!
# FIX: always measure before using a cbit in a condition
fixed_prog = core.QProg()
fixed_prog << core.H(0)
fixed_prog << core.measure(0, 0) # Now cbit 0 has a defined value
branch = core.QProg()
branch << core.X(1)
fixed_prog << core.qif([0]).then(branch).qendif()策略 4:验证循环终止
qwhile 循环在所有指定经典比特为 1 时持续运行。确保循环体最终会改变测量值以终止循环。
from pyqpanda3 import core
# POTENTIAL INFINITE LOOP: loop body does not change the condition
# bad_prog = core.QProg()
# bad_prog << core.X(0) << core.measure(0, 0) # cbit[0] = 1
# bad_loop = core.QProg()
# bad_loop << core.H(1) # Does not affect qubit 0 or cbit 0!
# bad_prog << core.qwhile([0]).loop(bad_loop) # Infinite loop!
# GOOD: loop body re-measures the conditioned qubit
good_prog = core.QProg()
good_prog << core.X(0) << core.measure(0, 0)
good_loop = core.QProg()
good_loop << core.H(0) # Change the state
good_loop << core.measure(0, 0) # Re-measure to update cbit[0]
good_prog << core.qwhile([0]).loop(good_loop) # Will terminate with ~50% chance each iteration策略 5:对比预期结果与实际计数
运行后,将测量统计结果与理论预测进行比较。对于正确实现的动态线路,计数应该与预期分布一致。
from pyqpanda3 import core
import math
# A Bell state should give 00 and 11 with equal probability
prog = core.QProg()
prog << core.H(0)
prog << core.CNOT(0, 1)
prog << core.measure([0, 1], [0, 1])
machine = core.CPUQVM()
machine.run(prog, shots=10000)
counts = machine.result().get_counts()
# Check: only 00 and 11 should appear, each ~5000 times
total_shots = sum(counts.values())
for outcome, count in counts.items():
probability = count / total_shots
print(f" {outcome}: {count} shots ({probability:.3f})")
# Expected: 00 and 11 each with probability ~0.50
# Any 01 or 10 outcomes indicate a bug in the circuit常见错误信息
| 错误 | 原因 | 修复方法 |
|---|---|---|
QProg 类型不匹配 | 在分支中使用了 QCircuit | 所有分支体应使用 QProg() |
| 未初始化的经典比特 | 条件引用了未测量的经典比特 | 在条件语句之前添加 measure() |
| 无限循环 | qwhile 循环体未更新条件比特 | 确保循环体重新测量受条件约束的量子比特 |
缺少 qendif | qif 未正确终止 | 每个 qif 都必须以 .qendif() 或 .qelse() 结束 |
动态线路构建规则
规则 1:分支使用 QProg
所有分支体必须是 QProg 对象,而非 QCircuit 对象:
# CORRECT
branch = core.QProg()
branch << core.X(1)
prog << core.qif([0]).then(branch).qendif()
# WRONG: branch must be QProg
# branch = core.QCircuit() # Don't use QCircuit规则 2:完成控制流
每个 qif 必须以 .qendif() 或 .qelse() 结束:
# CORRECT: End with qendif
prog << core.qif([0]).then(branch).qendif()
# CORRECT: End with qelse
prog << core.qif([0]).then(if_branch).qelse(else_branch)
# WRONG: Missing termination
# prog << core.qif([0]).then(branch) # Missing .qendif() or .qelse()规则 3:先测量再使用条件
条件中使用的经典比特必须在条件语句之前通过测量赋值:
# CORRECT: Measure first, then use cbit in condition
prog << core.measure(0, 0)
prog << core.qif([0]).then(branch).qendif()
# WRONG: Using uninitialized cbit
# prog << core.qif([0]).then(branch).qendif() # cbit 0 not measured yet规则 4:嵌套条件
可以通过将条件语句包含在分支程序中来实现嵌套条件:
outer_if = core.QProg()
outer_if << core.X(0)
inner_if = core.QProg()
inner_if << core.Y(1)
inner_else = core.QProg()
inner_else << core.Z(1)
outer_if << core.qif([1]).then(inner_if).qelse(inner_else)
prog = core.QProg()
prog << core.H(0) << core.measure(0, 0) << core.measure(1, 1)
prog << core.qif([0]).then(outer_if).qendif()控制流图
API 参考
qif
core.qif(cbits: list[int]) -> QIf创建一个条件结构,检查所有指定的经典比特是否为 1。
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
cbits | list[int] | 要检查的经典比特地址列表(AND 条件) |
返回值: 带有 .then() 方法的 QIf 对象
QIf.then
QIf.then(branch: QProg) -> QIfThen设置 if 分支程序。
QIfThen.qelse
QIfThen.qelse(else_branch: QProg) -> QProg添加 else 分支并返回完整的条件结构。
QIfThen.qelseif
QIfThen.qelseif(cbits: list[int]) -> QElseif添加另一个待检查的条件。
QIfThen.qendif
QIfThen.qendif() -> QProg结束条件结构(无 else 分支)。
qwhile
core.qwhile(cbits: list[int]) -> QWhile创建一个 while 循环,在所有指定经典比特为 1 时重复执行。
QWhile.loop
QWhile.loop(loop_body: QProg) -> QProg设置循环体程序。
限制
- 后端支持:并非所有模拟器都支持动态线路。CPUQVM 完全支持动态线路。
- 条件类型:仅支持经典比特等于 1 的判断(不支持比较运算符)。
- 不可重复使用测量结果:在同一个条件分支内,已用于条件的经典比特不应再次被测量。
- 循环终止:使用 while 循环时需谨慎——确保循环体能够改变条件以防止无限循环。