Skip to content

IR 转换 -- OriginIR 与 QASM(IR Conversion)

在 QProg、OriginIR 和 QASM 中间表示之间进行转换,实现电路互操作、序列化和调试。


问题

使用 pyqpanda3 构建的量子电路以内存中的 QProg 对象形式存在。在许多情况下,你需要将电路表示为纯文本字符串,以便存储、传输或与其他框架共享。支持两种基于文本的中间表示(Intermediate Representation, IR):

OriginIR 是 QPanda 的原生 IR 格式。它为每个 pyqpanda3 功能提供完整保真度,包括动态电路(Dynamic Circuits, QIF/QELSE/QWHILE)、自定义门定义(QGATE)、受控和求逆操作以及所有原生门类型。当需要在 pyqpanda3 生态系统内序列化和反序列化电路时使用 OriginIR。

OpenQASM 2.0 是 Qiskit、Cirq 及许多其他框架支持的行业标准量子汇编语言。当需要与非 QPanda 工具交换电路、从开源社区导入电路或导出电路用于发表时使用 QASM。

你需要在以下场景进行 IR 转换:

  • 互操作性(Interoperability)——导入在 Qiskit 等框架中编写的 QASM 电路,或将 pyqpanda3 电路导出为 QASM 给其他框架使用。
  • 持久化(Persistence)——将电路作为 OriginIR 或 QASM 文件保存到磁盘,之后无需重新运行构建代码即可加载。
  • 验证(Verification)——将电路导出为文本,目视检查门序列,或通过比较字符串表示来比较两个电路。
  • 调试(Debugging)——打印复杂 QProg 的 IR 以了解其门结构、控制流和测量操作。
  • 往返测试(Round-Trip Testing)——构建电路、导出为 IR、再导入回来,验证酉矩阵是否匹配以确认转换管道的正确性。

下图展示了 intermediate_compiler 模块支持的转换路径:


方案

intermediate_compiler 模块提供六个函数,覆盖所有转换方向:

函数方向输入输出
convert_qprog_to_originir(prog, precision)QProg -> OriginIRQProg,可选 intstr
convert_qprog_to_qasm(prog, precision)QProg -> QASMQProg,可选 intstr
convert_originir_string_to_qprog(ir_string)OriginIR 字符串 -> QProgstrQProg
convert_originir_file_to_qprog(file_path)OriginIR 文件 -> QProgstr(路径)QProg
convert_qasm_string_to_qprog(qasm_string)QASM 字符串 -> QProgstrQProg
convert_qasm_file_to_qprog(file_path)QASM 文件 -> QProgstr(路径)QProg

precision 参数(默认值:8)控制导出字符串中浮点角度值使用的小数位数。更高的精度保留更多准确性,这对往返保真度很重要。

步骤 1:将电路导出为 OriginIR 或 QASM

使用标准 pyqpanda3 API 构建 QProg,然后调用相应的转换函数:

python
from pyqpanda3.core import QProg, H, CNOT, RX, measure
from pyqpanda3.intermediate_compiler import (
    convert_qprog_to_originir,
    convert_qprog_to_qasm,
)

prog = QProg()
prog << H(0)
prog << CNOT(0, 1)
prog << RX(1, 3.14159)
prog << measure([0, 1], [0, 1])

originir_str = convert_qprog_to_originir(prog)
qasm_str = convert_qprog_to_qasm(prog)

print("=== OriginIR ===")
print(originir_str)
print("=== QASM ===")
print(qasm_str)

步骤 2:将 OriginIR 或 QASM 字符串导入为 QProg

将文本表示解析回可执行的 QProg

python
from pyqpanda3.intermediate_compiler import (
    convert_originir_string_to_qprog,
    convert_qasm_string_to_qprog,
)

originir_str = """
    QINIT 2
    CREG 2
    H q[0]
    CNOT q[0],q[1]
    MEASURE q[0],c[0]
    MEASURE q[1],c[1]
"""

prog_from_originir = convert_originir_string_to_qprog(originir_str)

步骤 3:从文件加载电路

对于存储在磁盘上的电路,使用基于文件的导入函数:

python
from pyqpanda3.intermediate_compiler import (
    convert_originir_file_to_qprog,
    convert_qasm_file_to_qprog,
)

prog = convert_originir_file_to_qprog("/path/to/circuit.txt")
prog = convert_qasm_file_to_qprog("/path/to/circuit.qasm")

步骤 4:验证往返保真度

在往返转换(先导出再导入)后,比较酉矩阵以确认没有信息丢失:

python
from pyqpanda3.quantum_info import Unitary

prog = QProg()
prog << H(0) << CNOT(0, 1)

qasm_str = convert_qprog_to_qasm(prog, precision=15)
prog2 = convert_qasm_string_to_qprog(qasm_str)

mat1 = Unitary(prog.to_circuit())
mat2 = Unitary(prog2.to_circuit())

# Compute squared distance between the two unitary matrices
diff = abs(mat1.ndarray() - mat2.ndarray()) ** 2
print(f"Round-trip error: {diff.max():.2e}")

代码

示例 1:构建 Bell 态并导出为两种格式

本示例创建 Bell 态电路并将其导出为 OriginIR 和 QASM:

python
from pyqpanda3.core import QProg, H, CNOT, measure
from pyqpanda3.intermediate_compiler import (
    convert_qprog_to_originir,
    convert_qprog_to_qasm,
)

# Build a Bell state circuit
prog = QProg()
prog << H(0)
prog << CNOT(0, 1)
prog << measure([0, 1], [0, 1])

# Export to OriginIR (QPanda's native format)
originir_str = convert_qprog_to_originir(prog)
print("OriginIR representation:")
print(originir_str)
print()

# Export to QASM 2.0 (industry standard)
qasm_str = convert_qprog_to_qasm(prog)
print("QASM representation:")
print(qasm_str)

预期 OriginIR 输出:

QINIT 2
CREG 2
H q[0]
CNOT q[0],q[1]
MEASURE q[0],c[0]
MEASURE q[1],c[1]

预期 QASM 输出:

OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0],q[1];
measure q[0] -> c[0];
measure q[1] -> c[1];

示例 2:导入 OriginIR 字符串并运行

本示例解析 OriginIR 字符串,在模拟器上运行结果电路,并打印测量计数:

python
from pyqpanda3.core import CPUQVM
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

originir_str = """
    QINIT 3
    CREG 2
    H q[2]
    H q[0]
    H q[1]
    CONTROL q[1]
    RX q[2],(-3.141593)
    ENDCONTROL
    CONTROL q[0]
    RX q[2],(-3.141593)
    RX q[2],(-3.141593)
    ENDCONTROL
    DAGGER
    H q[1]
    H q[0]
    ENDDAGGER
    MEASURE q[0],c[0]
    MEASURE q[1],c[1]
"""

prog = convert_originir_string_to_qprog(originir_str)

machine = CPUQVM()
machine.run(prog=prog, shots=1000)

counts = machine.result().get_counts()
print("Measurement counts:", counts)

示例 3:导入 QASM 字符串并运行

本示例导入用 QASM 编写的量子隐形传态电路:

python
from pyqpanda3.core import CPUQVM
from pyqpanda3.intermediate_compiler import convert_qasm_string_to_qprog

qasm_str = """
    // quantum teleportation example
    OPENQASM 2.0;
    include "qelib1.inc";
    qreg q[3];
    creg c[3];
    gate post q {
        h q;
    }
    u3(0.3,0.2,0.1) q[0];
    h q[1];
    cx q[1],q[2];
    barrier q;
    cx q[0],q[1];
    h q[0];
    measure q[0] -> c[0];
    measure q[1] -> c[1];
    if(c==1) z q[2];
    if(c==2) x q[2];
    if(c==3) y q[2];
    post q[2];
    measure q[2] -> c[2];
"""

prog = convert_qasm_string_to_qprog(qasm_str)

machine = CPUQVM()
machine.run(prog=prog, shots=1000)

counts = machine.result().get_counts()
print("Teleportation counts:", counts)

示例 4:带验证的往返转换

本示例演示完整的往返流程:构建电路、导出为 QASM、导入回来,并验证酉矩阵是否匹配。这是验证转换管道保持电路语义的常见模式。

python
from pyqpanda3.core import QProg, H, CNOT, RX, RY, RZ, CZ
from pyqpanda3.intermediate_compiler import (
    convert_qprog_to_qasm,
    convert_qasm_string_to_qprog,
    convert_qprog_to_originir,
)
from pyqpanda3.quantum_info import Unitary
import numpy as np

# Build a non-trivial circuit
prog = QProg()
prog << H(0)
prog << H(1)
prog << CNOT(0, 1)
prog << RZ(0, 1.2345)
prog << RZ(1, 2.3456)
prog << CNOT(0, 1)
prog << RX(0, 0.5678)
prog << RY(1, 0.9012)
prog << CZ(0, 1)

# Use high precision for the round-trip to avoid floating-point loss
qasm_str = convert_qprog_to_qasm(prog, precision=15)
print("Exported QASM:")
print(qasm_str)

# Import the QASM string back into a QProg
prog2 = convert_qasm_string_to_qprog(qasm_str)

# Also verify the OriginIR path
originir_str = convert_qprog_to_originir(prog, precision=15)
print("\nExported OriginIR:")
print(originir_str)

# Compare unitary matrices
mat1 = Unitary(prog.to_circuit())
mat2 = Unitary(prog2.to_circuit())

diff = np.abs(mat1.ndarray() - mat2.ndarray()) ** 2
max_error = diff.max()
print(f"\nRound-trip max squared error: {max_error:.2e}")
assert max_error < 1e-10, "Round-trip fidelity check failed!"
print("Round-trip verified successfully.")

示例 5:将电路保存到文件并加载

本示例展示如何将 OriginIR 或 QASM 字符串写入文件并读回:

python
import os
from pyqpanda3.core import QProg, H, CNOT, measure
from pyqpanda3.intermediate_compiler import (
    convert_qprog_to_originir,
    convert_qprog_to_qasm,
    convert_originir_file_to_qprog,
    convert_qasm_file_to_qprog,
)

# Build a circuit
prog = QProg()
prog << H(0)
prog << CNOT(0, 1)
prog << measure([0, 1], [0, 1])

# --- Save as OriginIR ---
originir_str = convert_qprog_to_originir(prog)
originir_path = "/tmp/bell_circuit.txt"
with open(originir_path, "w") as f:
    f.write(originir_str)
print(f"Saved OriginIR to {originir_path}")

# --- Save as QASM ---
qasm_str = convert_qprog_to_qasm(prog)
qasm_path = "/tmp/bell_circuit.qasm"
with open(qasm_path, "w") as f:
    f.write(qasm_str)
print(f"Saved QASM to {qasm_path}")

# --- Load back from files ---
prog_from_oir = convert_originir_file_to_qprog(originir_path)
prog_from_qasm = convert_qasm_file_to_qprog(qasm_path)

# Verify both loaded circuits produce the same OriginIR
print("\nOriginIR from file:")
print(convert_qprog_to_originir(prog_from_oir))
print("\nQASM from file:")
print(convert_qprog_to_qasm(prog_from_qasm))

# Clean up
os.remove(originir_path)
os.remove(qasm_path)

示例 6:处理受控和求逆操作

OriginIR 原生支持 CONTROL/ENDCONTROL 块和 DAGGER/ENDDAGGER 块。本示例演示这些在 QProg API 和 IR 之间的映射关系:

python
from pyqpanda3.core import QProg, H, RX, X
from pyqpanda3.intermediate_compiler import convert_qprog_to_originir

prog = QProg()
prog << H(0)
prog << H(1)
prog << H(2)

# Apply RX on qubit 2, controlled by qubit 1
prog << RX(2, -3.141593).control([1])

# Apply RX on qubit 2, controlled by qubit 0 (twice, effectively 2x the angle)
prog << RX(2, -3.141593).control([0])
prog << RX(2, -3.141593).control([0])

# Apply the dagger (inverse) of H(1) followed by H(0)
prog << H(1).dagger()
prog << H(0).dagger()

originir_str = convert_qprog_to_originir(prog)
print(originir_str)

输出将包含 CONTROL/ENDCONTROLDAGGER/ENDDAGGER 块:

QINIT 3
CREG 0
H q[0]
H q[1]
H q[2]
CONTROL q[1]
RX q[2],(-3.141593)
ENDCONTROL
CONTROL q[0]
RX q[2],(-3.141593)
RX q[2],(-3.141593)
ENDCONTROL
DAGGER
H q[1]
H q[0]
ENDDAGGER

示例 7:OriginIR 中的自定义门定义

OriginIR 通过 QGATE/ENDQGATE 语法支持用户定义的门。你可以定义带参数的可复用门块:

python
from pyqpanda3.core import CPUQVM
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

originir_str = """
    QINIT 2
    CREG 2

    H q
    X q[0]
    Y q[1]

    QGATE new_H a,b
    Y a
    Z b
    ENDQGATE

    QGATE new_RX a,b,(d,e)
    H a
    RX b,(PI/2+d+e)
    new_H a,b
    ENDQGATE

    new_RX q[1],q[0],(PI/2,3)
    new_RX q,(1,2)

    MEASURE q[0],c[0]
    MEASURE q[1],c[1]
"""

prog = convert_originir_string_to_qprog(originir_str)

machine = CPUQVM()
machine.run(prog=prog, shots=1000)
counts = machine.result().get_counts()
print("Counts:", counts)

上面的 QGATE 块将 new_H 定义为对两个量子比特施加 YZ 的复合门,new_RX 定义为使用 PI 作为内置常量并引用参数 de 的参数化门。

示例 8:OriginIR 中的动态电路(QIF / QWHILE)

OriginIR 支持动态电路构造——条件执行(QIF/QELSE/QELSEIF/QENDIF)和电路中途循环(QWHILE/QENDWHILE)。这些对于后续操作依赖于先前测量结果的电路至关重要:

python
from pyqpanda3.core import QProg, CPUQVM, X, Y, Z, H, measure, qif, qwhile
from pyqpanda3.intermediate_compiler import (
    convert_qprog_to_originir,
    convert_originir_string_to_qprog,
)

# Build a dynamic circuit using the pyqpanda3 API
prog = QProg()
inner_loop = QProg()
inner_loop << Y(2) << Y(1) << measure(2, 2)

if_body = QProg()
if_body << Y(0) << H(1)
if_body << qwhile([2]).loop(inner_loop)

prog << X(1)
prog << qif([1]).then(if_body).qendif()
prog << measure(0, 0)
prog << measure(1, 1)

# Export to OriginIR to see the dynamic circuit representation
originir_str = convert_qprog_to_originir(prog)
print("Dynamic circuit as OriginIR:")
print(originir_str)

# Parse it back and verify the round-trip
prog2 = convert_originir_string_to_qprog(originir_str)
originir_str2 = convert_qprog_to_originir(prog2)
print("\nRound-trip OriginIR:")
print(originir_str2)

# Run on a simulator
machine = CPUQVM()
machine.run(prog=prog, shots=100)
state = machine.result().get_state_vector()
print("\nState vector (first 4 amplitudes):")
for i, v in enumerate(state[:4]):
    print(f"  |{i:02b}>: ({v.real:.6f}, {v.imag:.6f})")

解析

OriginIR 语法概述

OriginIR 是面向行的文本 IR。每行包含一条指令或一个块分隔符。一般结构为:

QINIT <n>           -- Declare n qubits
CREG <m>            -- Declare m classical bits

<gate> q[<idx>]     -- Single-qubit gate
<gate> q[<i>],q[<j>]  -- Two-qubit gate
<gate> q[<i>],(<angle>)  -- Parameterized gate with angle in radians

头部行(Header Lines)QINITCREG)是必需的。它们声明量子比特数和经典比特数。量子比特索引范围为 [0,n1],其中 nQINIT 的值。

门指令(Gate Instructions)遵循模式 GATE_NAME target_qubit(s),(parameter(s))。例如:

OriginIR 行含义
H q[0]对量子比特 0 施加 Hadamard
X q[1]对量子比特 1 施加 Pauli-X
RX q[0],(1.570796)绕 X 轴旋转 π/2 弧度
CNOT q[0],q[1]CNOT,控制=0,目标=1
MEASURE q[0],c[0]测量量子比特 0 存入经典比特 0

控制块(Control Blocks)使用 CONTROL/ENDCONTROL

CONTROL q[0],q[1]
X q[2]
Z q[3]
ENDCONTROL

仅当量子比特 0 和 1 都处于 |1 态时才执行包含的门。

求逆块(Dagger Blocks)使用 DAGGER/ENDDAGGER 来施加包含操作的逆操作:

DAGGER
H q[0]
RX q[1],(1.570796)
ENDDAGGER

自定义门(Custom Gates)使用 QGATE/ENDQGATE 配合可选参数:

QGATE my_gate a,b,(theta,phi)
  RX a,(theta)
  RY b,(phi)
  CNOT a,b
ENDQGATE

这里 ab 是形式量子比特参数,thetaphi 是形式参数名。内置常量 PI 表示 π3.14159265358979

条件执行(Conditional Execution)使用 QIF/QELSE/QELSEIF/QENDIF

QIF c[0],c[1]
  X q[2]
QELSEIF c[2]
  Y q[2]
QELSE
  Z q[2]
QENDIF

条件检查指定的经典比特被解释为小端整数时是否等于 1。可以列出多个经典比特。

循环构造(Loop Constructs)使用 QWHILE/QENDWHILE

QWHILE c[0]
  X q[1]
  MEASURE q[1],c[0]
QENDWHILE

只要条件经典比特评估为 1,循环体就重复执行。

注释(Comments)是以 // 开头的单行注释:

H q[0]         // Apply Hadamard
// This is a full-line comment

QASM 2.0 语法概述

QASM 2.0 是 IBM 定义的标准量子汇编格式。QASM 2.0 程序的结构如下:

qasm
OPENQASM 2.0;
include "qelib1.inc";
qreg q[<n>];
creg c[<m>];
<gate> q[<i>];
<gate> q[<i>],q[<j>];
measure q[<i>] -> c[<j>];

与 OriginIR 的主要区别:

  • 头部为 OPENQASM 2.0; 后跟 include "qelib1.inc";
  • 量子比特寄存器使用 qreg q[n]; 而非 QINIT n
  • 经典寄存器使用 creg c[m]; 而非 CREG m
  • 测量语法使用 -> 而非逗号:measure q[0] -> c[0]
  • 门名称为小写:hcxczrxryrz 等。
  • QASM 通过 gate 关键字支持自定义门定义。
  • QASM 通过 if(c==<val>) 语法支持条件执行。

表示之间的门映射

下表展示常见门在 pyqpanda3、OriginIR 和 QASM 2.0 之间的映射:

pyqpanda3 APIOriginIRQASM 2.0
H(q)H q[i]h q[i]
X(q)X q[i]x q[i]
Y(q)Y q[i]y q[i]
Z(q)Z q[i]z q[i]
S(q)S q[i]s q[i]
T(q)T q[i]t q[i]
RX(q, angle)RX q[i],(angle)rx(angle) q[i]
RY(q, angle)RY q[i],(angle)ry(angle) q[i]
RZ(q, angle)RZ q[i],(angle)rz(angle) q[i]
P(q, angle)P q[i],(angle)p(angle) q[i]
CNOT(c, t)CNOT q[c],q[t]cx q[c],q[t]
CZ(c, t)CZ q[c],q[t]cz q[c],q[t]
SWAP(a, b)SWAP q[a],q[b]swap q[a],q[b]
TOFFOLI(a, b, t)TOFFOLI q[a],q[b],q[t]ccx q[a],q[b],q[t]
U1(q, lam)U1 q[i],(lam)u1(lam) q[i]
U2(q, phi, lam)U2 q[i],(phi,lam)u2(phi,lam) q[i]
U3(q, theta, phi, lam)U3 q[i],(theta,phi,lam)u3(theta,phi,lam) q[i]
CU(c, t, theta, phi, lam, gamma)CU q[c],q[t],(theta,phi,lam,gamma)cu(theta,phi,lam,gamma) q[c],q[t]
measure(q, c)MEASURE q[i],c[j]measure q[i] -> c[j]
barrier(qubits)BARRIER q[i],q[j],...barrier q[i],q[j],...

限制与格式选择

每种格式都有特定的优势和限制:

何时使用 OriginIR:

  • 序列化 pyqpanda3 电路用于存储和后续检索。
  • 包含动态控制流(QIFQWHILE)的电路。
  • 使用 RPHIISWAPSQISWAP 或其他 QPanda 原生门的电路。
  • 在 pyqpanda3 生态系统内进行完整保真度的往返转换。
  • 使用 QProg(ir_string) 快速构建电路。

何时使用 QASM 2.0:

  • 与 Qiskit、Cirq 或其他框架交换电路。
  • 从公共仓库或教科书导入电路。
  • 以广泛理解的格式发布电路。
  • 提交到接受 QASM 的量子云服务。

需要注意的主要限制:

  • QASM 2.0 不支持 QWHILE 循环。如果你将包含 qwhile 构造的电路导出为 QASM,循环结构将不会被保留。
  • 某些 QPanda 原生门(如 ISWAPRPHI)没有直接的 QASM 2.0 等价物。将这些门导出为 QASM 可能会产生错误或分解为受支持的门。
  • precision 参数影响浮点保真度。对于包含许多旋转门的电路,使用 precision=15 或更高值以确保往返准确性。
  • OriginIR 和 QASM 对 measure 语法使用不同的约定:OriginIR 使用 MEASURE q[i],c[j],而 QASM 使用 measure q[i] -> c[j]

便捷功能:QProg OriginIR 构造函数

除了 convert_originir_string_to_qprog 函数外,你还可以使用 QProg 构造函数直接从 OriginIR 字符串构造 QProg

python
from pyqpanda3.core import QProg, CPUQVM

# Direct construction from OriginIR string
prog = QProg("""
    QINIT 2
    CREG 2
    H q[0]
    CNOT q[0],q[1]
    MEASURE q[0],c[0]
    MEASURE q[1],c[1]
""")

# The program is ready to run
machine = CPUQVM()
machine.run(prog=prog, shots=1000)
counts = machine.result().get_counts()
print(counts)

类似地,QProg 实例上的 .originir() 方法无需使用模块级函数即可返回 OriginIR 字符串:

python
prog = QProg()
prog << H(0) << CNOT(0, 1)

# These two calls are equivalent:
ir1 = prog.originir()
# ir1 = convert_qprog_to_originir(prog)

print(ir1)

精度与往返保真度

默认精度 8 位小数对大多数实际电路足够。然而,在执行往返转换(先导出再导入)时,对于包含许多参数化门的电路,浮点舍入误差可能累积。原始电路和往返电路酉矩阵之间的平方矩阵距离应满足:

maxi,j|UijoriginalUijround-trip|2<ϵ

其中 ϵ 取决于精度和电路深度。对于包含 10+ 个旋转门的电路,使用 precision=15 以保持 ϵ<1010

实用的验证模式:

python
from pyqpanda3.quantum_info import Unitary
import numpy as np

def verify_round_trip(prog, precision=15, tolerance=1e-6):
    """Verify that export-import round-trip preserves circuit unitary."""
    qasm_str = convert_qprog_to_qasm(prog, precision=precision)
    prog2 = convert_qasm_string_to_qprog(qasm_str)

    mat1 = Unitary(prog.to_circuit()).ndarray()
    mat2 = Unitary(prog2.to_circuit()).ndarray()

    # Account for global phase by comparing squared distances
    diff = np.abs(mat1 - mat2) ** 2
    max_error = diff.max()

    if max_error > tolerance:
        raise AssertionError(
            f"Round-trip error {max_error:.2e} exceeds tolerance {tolerance:.2e}"
        )
    return True

电路序列化模式

常见的工作流是以编程方式构建电路、将其序列化以进行存储或传输,之后反序列化:

模式 1:OriginIR 用于内部存储(完整保真度)

python
# Serialize
originir_str = convert_qprog_to_originir(prog, precision=15)
with open("circuit_cache.txt", "w") as f:
    f.write(originir_str)

# Deserialize
prog = convert_originir_file_to_qprog("circuit_cache.txt")

模式 2:QASM 用于框架互操作性

python
# Serialize for Qiskit consumption
qasm_str = convert_qprog_to_qasm(prog, precision=15)
with open("circuit_for_qiskit.qasm", "w") as f:
    f.write(qasm_str)

# In Qiskit:
# from qiskit import QuantumCircuit
# qc = QuantumCircuit.from_qasm_file("circuit_for_qiskit.qasm")

模式 3:批量转换

当你需要在格式之间转换许多电路时,使用带错误处理的循环:

python
from pyqpanda3.intermediate_compiler import (
    convert_qasm_string_to_qprog,
    convert_qprog_to_originir,
)

qasm_circuits = ["<QASM 1>", "<QASM 2>", "<QASM 3>"]  # your QASM strings

for i, qasm_str in enumerate(qasm_circuits):
    try:
        prog = convert_qasm_string_to_qprog(qasm_str)
        originir_str = convert_qprog_to_originir(prog)
        with open(f"circuit_{i:04d}.txt", "w") as f:
            f.write(originir_str)
    except Exception as e:
        print(f"Failed to convert circuit {i}: {e}")

常见陷阱

  1. OriginIR 缺少头部行:每个 OriginIR 字符串必须以 QINITCREG 声明开头。省略它们会导致解析错误。

  2. 往返转换使用错误精度:默认精度 8 位小数可能在包含许多旋转门的电路中丢失有效数字。进行往返转换时始终使用 precision=15

  3. QASM 中不支持的门ISWAPSQISWAPRPHI 等门没有 QASM 2.0 等价物。将包含这些门的电路导出为 QASM 会失败或产生不正确结果。改用 OriginIR。

  4. 测量语法混淆:记住 OriginIR 使用 MEASURE q[i],c[j](逗号),而 QASM 使用 measure q[i] -> c[j](箭头)。

  5. QASM 中的动态电路:QASM 2.0 的 if(c==val) 语法仅支持有限形式的条件执行。包含 QWHILE 循环的复杂动态电路无法导出为 QASM。完整动态电路支持请使用 OriginIR。

  6. 门名称大小写敏感:OriginIR 门名称为大写(HCNOTRX)。QASM 门名称为小写(hcxrx)。混合使用会导致解析错误。

API 参考摘要

所有函数从 pyqpanda3.intermediate_compiler 导入:

python
from pyqpanda3.intermediate_compiler import (
    convert_originir_string_to_qprog,  # str -> QProg
    convert_originir_file_to_qprog,    # filepath -> QProg
    convert_qasm_string_to_qprog,      # str -> QProg
    convert_qasm_file_to_qprog,        # filepath -> QProg
    convert_qprog_to_originir,         # QProg -> str
    convert_qprog_to_qasm,             # QProg -> str
)

函数签名:

python
convert_qprog_to_originir(prog: QProg, precision: int = 8) -> str
convert_qprog_to_qasm(prog: QProg, precision: int = 8) -> str
convert_originir_string_to_qprog(ir_string: str) -> QProg
convert_originir_file_to_qprog(file_path: str) -> QProg
convert_qasm_string_to_qprog(qasm_string: str) -> QProg
convert_qasm_file_to_qprog(file_path: str) -> QProg

precision 参数控制导出 IR 字符串中浮点值的小数位数。它必须是非负整数。更高的值保留更多准确性,但会产生更长的字符串输出。

Released under the MIT License.