IR Conversion -- OriginIR and QASM
Convert between QProg, OriginIR, and QASM intermediate representations for circuit interoperability, serialization, and debugging.
Problem
Quantum circuits built with pyqpanda3 exist as in-memory QProg objects. In many situations you need to represent a circuit as a plain-text string so that it can be stored, transmitted, or shared with other frameworks. Two text-based intermediate representations (IRs) are supported:
OriginIR is QPanda's native IR format. It provides full fidelity for every pyqpanda3 feature, including dynamic circuits (QIF/QELSE/QWHILE), custom gate definitions (QGATE), controlled and daggered operations, and all native gate types. Use OriginIR when you need to serialize and deserialize circuits within the pyqpanda3 ecosystem.
OpenQASM 2.0 is the industry-standard quantum assembly language supported by Qiskit, Cirq, and many other frameworks. Use QASM when you need to exchange circuits with non-QPanda tools, import circuits from the open-source community, or export circuits for publication.
You need IR conversion when:
- Interoperability -- Import a circuit authored in Qiskit via QASM, or export a pyqpanda3 circuit for use in another framework.
- Persistence -- Save a circuit to disk as an OriginIR or QASM file, then load it later without re-running the construction code.
- Verification -- Export a circuit to text, visually inspect the gate sequence, or compare two circuits by comparing their string representations.
- Debugging -- Print the IR of a complex
QProgto understand its gate structure, control flow, and measurement operations. - Round-trip testing -- Build a circuit, export it to IR, import it back, and verify the unitary matrices match to confirm correctness of the conversion pipeline.
The following diagram shows the conversion paths supported by the intermediate_compiler module:
Solution
The intermediate_compiler module provides six functions that cover all conversion directions:
| Function | Direction | Input | Output |
|---|---|---|---|
convert_qprog_to_originir(prog, precision) | QProg -> OriginIR | QProg, optional int | str |
convert_qprog_to_qasm(prog, precision) | QProg -> QASM | QProg, optional int | str |
convert_originir_string_to_qprog(ir_string) | OriginIR str -> QProg | str | QProg |
convert_originir_file_to_qprog(file_path) | OriginIR file -> QProg | str (path) | QProg |
convert_qasm_string_to_qprog(qasm_string) | QASM str -> QProg | str | QProg |
convert_qasm_file_to_qprog(file_path) | QASM file -> QProg | str (path) | QProg |
The precision parameter (default: 8) controls the number of decimal places used for floating-point angle values in the exported string. A higher precision preserves more accuracy, which is important for round-trip fidelity.
Step 1: Export a circuit to OriginIR or QASM
Build a QProg using the standard pyqpanda3 API, then call the appropriate conversion function:
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)Step 2: Import an OriginIR or QASM string into a QProg
Parse a text representation back into an executable QProg:
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)Step 3: Load a circuit from a file
For circuits stored on disk, use the file-based import functions:
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")Step 4: Verify round-trip fidelity
After a round-trip conversion (export then import), compare the unitary matrices to confirm no information was lost:
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}")Code
Example 1: Build a Bell State and Export to Both Formats
This example creates a Bell state circuit and exports it to both OriginIR and QASM:
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)Expected OriginIR output:
QINIT 2
CREG 2
H q[0]
CNOT q[0],q[1]
MEASURE q[0],c[0]
MEASURE q[1],c[1]Expected QASM output:
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];Example 2: Import an OriginIR String and Run It
This example parses an OriginIR string, runs the resulting circuit on a simulator, and prints the measurement counts:
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)Example 3: Import a QASM String and Run It
This example imports a quantum teleportation circuit written in QASM:
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)Example 4: Round-Trip Conversion with Verification
This example demonstrates a full round-trip: build a circuit, export to QASM, import back, and verify that the unitary matrices match. This is a common pattern for validating that the conversion pipeline preserves circuit semantics.
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.")Example 5: Saving Circuits to Files and Loading Them
This example shows how to write an OriginIR or QASM string to a file and read it back:
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)Example 6: Working with Controlled and Daggered Operations
OriginIR natively supports CONTROL/ENDCONTROL blocks and DAGGER/ENDDAGGER blocks. This example demonstrates how these map between the QProg API and the IR:
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)The output will contain CONTROL/ENDCONTROL and DAGGER/ENDDAGGER blocks:
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]
ENDDAGGERExample 7: Custom Gate Definitions in OriginIR
OriginIR supports user-defined gates via the QGATE/ENDQGATE syntax. You can define reusable gate blocks with parameters:
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)The QGATE block above defines new_H as a composite of Y and Z on two qubits, and new_RX as a parameterized gate that uses PI as a built-in constant and references parameters d and e.
Example 8: Dynamic Circuits (QIF / QWHILE) in OriginIR
OriginIR supports dynamic circuit constructs -- conditional execution (QIF/QELSE/QELSEIF/QENDIF) and mid-circuit loops (QWHILE/QENDWHILE). These are essential for circuits where subsequent operations depend on earlier measurement results:
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})")Explanation
OriginIR Syntax Overview
OriginIR is a line-oriented, text-based IR. Each line contains a single instruction or a block delimiter. The general structure is:
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 radiansHeader lines (QINIT and CREG) are required. They declare the number of qubits and classical bits. The qubit index range is QINIT value.
Gate instructions follow the pattern GATE_NAME target_qubit(s),(parameter(s)). For example:
| OriginIR Line | Meaning |
|---|---|
H q[0] | Hadamard on qubit 0 |
X q[1] | Pauli-X on qubit 1 |
RX q[0],(1.570796) | Rotation around X axis by |
CNOT q[0],q[1] | CNOT with control=0, target=1 |
MEASURE q[0],c[0] | Measure qubit 0 into classical bit 0 |
Control blocks use CONTROL/ENDCONTROL:
CONTROL q[0],q[1]
X q[2]
Z q[3]
ENDCONTROLThis applies the enclosed gates only when both qubit 0 and qubit 1 are in the
Dagger blocks use DAGGER/ENDDAGGER to apply the inverse of the enclosed operations:
DAGGER
H q[0]
RX q[1],(1.570796)
ENDDAGGERCustom gates use QGATE/ENDQGATE with optional parameters:
QGATE my_gate a,b,(theta,phi)
RX a,(theta)
RY b,(phi)
CNOT a,b
ENDQGATEHere a and b are formal qubit arguments, and theta and phi are formal parameter names. The built-in constant PI represents
Conditional execution uses QIF/QELSE/QELSEIF/QENDIF:
QIF c[0],c[1]
X q[2]
QELSEIF c[2]
Y q[2]
QELSE
Z q[2]
QENDIFThe condition checks whether the specified classical bits, when interpreted as a little-endian integer, equal 1. Multiple classical bits can be listed.
Loop constructs use QWHILE/QENDWHILE:
QWHILE c[0]
X q[1]
MEASURE q[1],c[0]
QENDWHILEThe loop body executes repeatedly as long as the condition classical bit evaluates to 1.
Comments are single-line comments beginning with //:
H q[0] // Apply Hadamard
// This is a full-line commentQASM 2.0 Syntax Overview
QASM 2.0 is the standard quantum assembly format defined by IBM. A QASM 2.0 program has this structure:
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>];Key differences from OriginIR:
- The header is
OPENQASM 2.0;followed byinclude "qelib1.inc";. - Qubit registers use
qreg q[n];instead ofQINIT n. - Classical registers use
creg c[m];instead ofCREG m. - The measurement syntax uses
->instead of a comma:measure q[0] -> c[0]. - Gate names are lowercase:
h,cx,cz,rx,ry,rz, etc. - QASM supports custom gate definitions via the
gatekeyword. - QASM supports conditional execution via
if(c==<val>)syntax.
Gate Mapping Between Representations
The following table shows how common gates map between pyqpanda3, OriginIR, and QASM 2.0:
| pyqpanda3 API | OriginIR | QASM 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],... |
Limitations and Format Selection
Each format has specific strengths and limitations:
When to use OriginIR:
- Serializing pyqpanda3 circuits for storage and later retrieval.
- Circuits with dynamic control flow (
QIF,QWHILE). - Circuits using
RPHI,ISWAP,SQISWAP, or other QPanda-native gates. - Full-fidelity round-trips within the pyqpanda3 ecosystem.
- Quick circuit construction using
QProg(ir_string).
When to use QASM 2.0:
- Exchanging circuits with Qiskit, Cirq, or other frameworks.
- Importing circuits from public repositories or textbooks.
- Publishing circuits in a widely understood format.
- Submitting to quantum cloud services that accept QASM.
Key limitations to be aware of:
- QASM 2.0 does not support
QWHILEloops. If you export a circuit containing aqwhileconstruct to QASM, the loop structure will not be preserved. - Some QPanda-native gates (e.g.,
ISWAP,RPHI) do not have direct QASM 2.0 equivalents. Exporting these gates to QASM may produce an error or decompose them into supported gates. - The
precisionparameter affects floating-point fidelity. For circuits with many rotation gates, useprecision=15or higher to ensure round-trip accuracy. - OriginIR and QASM use different conventions for the
measuresyntax: OriginIR usesMEASURE q[i],c[j]while QASM usesmeasure q[i] -> c[j].
Convenience: QProg OriginIR Constructor
In addition to the convert_originir_string_to_qprog function, you can also construct a QProg directly from an OriginIR string using the QProg constructor:
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)Similarly, the .originir() method on a QProg instance returns the OriginIR string without needing the module-level function:
prog = QProg()
prog << H(0) << CNOT(0, 1)
# These two calls are equivalent:
ir1 = prog.originir()
# ir1 = convert_qprog_to_originir(prog)
print(ir1)Precision and Round-Trip Fidelity
The default precision of 8 decimal places is sufficient for most practical circuits. However, when performing round-trip conversion (export then import), floating-point rounding can accumulate errors for circuits with many parameterized gates. The squared matrix distance between the original and round-tripped circuit unitaries should satisfy:
where precision=15 to keep
A practical verification pattern:
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 TrueCircuit Serialization Patterns
A common workflow is to build circuits programmatically, serialize them for storage or transfer, and deserialize them later:
Pattern 1: OriginIR for internal storage (full fidelity)
# 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")Pattern 2: QASM for framework interoperability
# 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")Pattern 3: Batch conversion
When you have many circuits to convert between formats, use a loop with error handling:
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}")Common Pitfalls
Missing header lines in OriginIR: Every OriginIR string must begin with
QINITandCREGdeclarations. Omitting them causes a parse error.Wrong precision for round-trips: The default precision of 8 decimal places may lose significant digits in circuits with many rotation gates. Always use
precision=15for round-trip conversions.Unsupported gates in QASM: Gates like
ISWAP,SQISWAP, andRPHIhave no QASM 2.0 equivalent. Exporting circuits containing these gates to QASM will fail or produce incorrect results. Use OriginIR instead.Measurement syntax confusion: Remember that OriginIR uses
MEASURE q[i],c[j](comma), while QASM usesmeasure q[i] -> c[j](arrow).Dynamic circuits in QASM: The QASM 2.0
if(c==val)syntax supports only a limited form of conditional execution. Complex dynamic circuits withQWHILEloops cannot be exported to QASM. Use OriginIR for full dynamic circuit support.Gate name case sensitivity: OriginIR gate names are uppercase (
H,CNOT,RX). QASM gate names are lowercase (h,cx,rx). Mixing the two causes parse errors.
API Reference Summary
All functions are imported from pyqpanda3.intermediate_compiler:
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
)Function signatures:
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) -> QProgThe precision parameter controls the number of decimal places for floating-point values in the exported IR string. It must be a non-negative integer. Higher values preserve more accuracy at the cost of longer string output.