Skip to content

动态线路

动态线路(Dynamic Circuits)实现了量子程序中的经典控制流。pyqpanda3 通过 qifqelseifqelseqwhile 结构支持线路中途测量和条件执行。


什么是动态线路?

传统量子线路是由门操作序列后接测量组成的静态结构。动态线路引入了经典控制流:

  • 条件执行:仅在满足测量条件时才施加门操作
  • 循环:基于测量结果重复执行操作
  • 中途测量:在执行过程中测量量子比特,而非仅在最后测量

qif - 条件分支

qif 结构基于经典比特值实现经典的 if-then-else 逻辑。

基本 If-Then

当需要根据测量结果有条件地施加门操作时,使用 qif

python
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 分支来处理:

python
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 串联多个条件:

python
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 结构在满足经典条件时重复执行循环体。

基本循环

python
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:重复直到成功

使用动态线路重复执行操作,直到获得期望的测量结果:

python
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:中途测量与条件门

执行测量并有条件地施加修正操作:

python
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:基于奇偶校验的错误检测

使用动态线路通过奇偶校验测量进行错误检测:

python
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:自适应相位估计

使用动态线路进行迭代相位估计:

python
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)利用纠缠和经典通信将未知的量子态从一个量子比特传输到另一个量子比特。动态线路在其中至关重要,因为修正操作依赖于中途测量的结果。

量子隐形传态协议的工作流程如下:

  1. Alice 和 Bob 共享一个纠缠的 Bell 对 (|Φ+=12(|00+|11))
  2. Alice 对她的量子比特和未知态执行 Bell 测量
  3. Alice 将两个经典比特发送给 Bob
  4. Bob 根据测量结果施加修正操作
|ψ|Φ+=12a,b{0,1}|a,bXbZa|ψ
python
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)X
(1, 0)Z
(1, 1)ZX

修正完成后,量子比特 2 将精确持有原始状态 |ψ。在没有噪声的情况下,隐形传态的保真度是完美的,这由不可克隆定理保证——原始量子比特 0 上的状态在测量过程中被破坏了。


量子纠错示例

三量子比特重复码(3-qubit repetition code)可以保护单个逻辑量子比特免受比特翻转(X)错误的影响。其编码映射为:

|0L=|000,|1L=|111

伴随式提取(syndrome extraction)使用两个辅助量子比特来检测哪个数据量子比特(如果有)经历了比特翻转。伴随式 (s1,s2) 可以唯一标识错误位置。

python
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())

伴随式解码表

伴随式比特 (s1,s2) 标识了哪个量子比特经历了比特翻转:

s1s2错误位置修正操作
00恒等操作
10量子比特 0X0
11量子比特 1X1
01量子比特 2X2

重复码的最小汉明距离为 d=3,可以纠正最多 t=(d1)/2=1 个比特翻转错误。该编码无法纠正相位翻转(Z)错误。要同时防止这两种错误,需要使用 9 量子比特的 Shor 码或 7 量子比特的 Steane 码。


迭代相位估计

迭代相位估计(Iterative Phase Estimation,IPE)从最低有效位开始,逐位确定酉算子 U 的特征值 e2πiϕ 的相位 ϕ。与标准 QPE 需要大量辅助量子比特不同,IPE 仅使用一个辅助量子比特和重复测量。

每次迭代 k 的关键线路公式为:

Prob(mk=0)=1+cos(2π(2kϕδk))2

其中 δk 是前几次迭代累积的相位修正。

python
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}")

逐步说明

每次迭代 k(从 k=n1k=0)执行以下步骤:

  1. 准备:将辅助量子比特初始化为 |+,目标量子比特初始化为特征态 |ψ
  2. 受控 U2k:施加酉算子 U2k 次幂,由辅助比特控制
  3. 相位修正:基于之前测量的比特施加 Z 旋转,以消除它们的贡献
  4. 测量:测量辅助量子比特以提取 ϕ 的第 k
  5. 重建:所有迭代完成后,ϕ0.b1b2bn(二进制小数形式)

精度随着 n 的增大而提高。使用 n 位时,分辨率为 Δϕ=2n


使用动态线路进行态验证

态验证(State Verification)确认量子系统在制备后是否处于目标状态。动态线路支持自适应测量策略,比完整态层析更高效。

Bell 态验证

Bell 态 |Φ+=12(|00+|11) 应产生完全关联的测量结果。我们可以使用条件检查来验证这一点。

python
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 态 |GHZn=12(|0n+|1n),所有量子比特应当完全关联。我们通过检查相邻量子比特之间的奇偶性来验证。

python
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 中进行动态线路编程时可复用的模式。

模式:测量后修正

最常见的动态线路模式:测量一个量子比特,然后有条件地施加修正门。

python
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

python
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 语句的多结果分支结构:

python
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)

模式:多阶段前馈

在多阶段量子算法中,一个阶段的测量结果传递到下一阶段的条件操作中。

python
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 时,此模式非常有用。

python
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。字符串表示会显示门序列和控制流结构。

python
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:先不使用动态功能运行

在添加条件逻辑之前,先验证线路的静态部分是否产生预期结果。采用增量构建方式。

python
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:检查经典比特初始化

一个常见的错误是在条件中引用经典比特之前没有对其进行测量。经典比特可能具有未定义或默认值。

python
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 时持续运行。确保循环体最终会改变测量值以终止循环。

python
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:对比预期结果与实际计数

运行后,将测量统计结果与理论预测进行比较。对于正确实现的动态线路,计数应该与预期分布一致。

python
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 循环体未更新条件比特确保循环体重新测量受条件约束的量子比特
缺少 qendifqif 未正确终止每个 qif 都必须以 .qendif().qelse() 结束

动态线路构建规则

规则 1:分支使用 QProg

所有分支体必须是 QProg 对象,而非 QCircuit 对象:

python
# 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() 结束:

python
# 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:先测量再使用条件

条件中使用的经典比特必须在条件语句之前通过测量赋值:

python
# 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:嵌套条件

可以通过将条件语句包含在分支程序中来实现嵌套条件:

python
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

python
core.qif(cbits: list[int]) -> QIf

创建一个条件结构,检查所有指定的经典比特是否为 1。

参数:

参数类型说明
cbitslist[int]要检查的经典比特地址列表(AND 条件)

返回值: 带有 .then() 方法的 QIf 对象

QIf.then

python
QIf.then(branch: QProg) -> QIfThen

设置 if 分支程序。

QIfThen.qelse

python
QIfThen.qelse(else_branch: QProg) -> QProg

添加 else 分支并返回完整的条件结构。

QIfThen.qelseif

python
QIfThen.qelseif(cbits: list[int]) -> QElseif

添加另一个待检查的条件。

QIfThen.qendif

python
QIfThen.qendif() -> QProg

结束条件结构(无 else 分支)。

qwhile

python
core.qwhile(cbits: list[int]) -> QWhile

创建一个 while 循环,在所有指定经典比特为 1 时重复执行。

QWhile.loop

python
QWhile.loop(loop_body: QProg) -> QProg

设置循环体程序。


限制

  1. 后端支持:并非所有模拟器都支持动态线路。CPUQVM 完全支持动态线路。
  2. 条件类型:仅支持经典比特等于 1 的判断(不支持比较运算符)。
  3. 不可重复使用测量结果:在同一个条件分支内,已用于条件的经典比特不应再次被测量。
  4. 循环终止:使用 while 循环时需谨慎——确保循环体能够改变条件以防止无限循环。

下一步

Released under the MIT License.