Prev Tutorial: Quantum Circuit Transpiler
Next Tutorial: OpenQASM
Overview
OriginIR is an intermediate representation of quantum programs based on QPanda, playing a crucial role in supporting various features of QPanda.
The main components of OriginIR include quantum bits, classical registers, quantum logic gates, transpose conjugate operations, control qubit operations, QIf, QWhile, and classical expressions.
- Note
- Currently, the new release of QPanda3 has the following updates compared to the older version of QPanda2 regarding the OriginIR module:
- First, QPanda3's OriginIR interface for translating QProg supports program comment parsing.
- Second, the OriginIR part of QPanda3 only supports operations such as applying quantum bit and register, quantum logic gate, transposing conjugate (DAGGER), adding control bit (CONTROL), BARRIER, and measurement, but not operations such as quantum conditional judgment (QIF), quantum cyclic control (QWHILE), classical expressions, RESET, and QGATE.
- Finally, when executing large quantum program translations, compared to QPanda2's translation interface, QPanda3's translation interface is executed about 4.5 times more efficiently (located in Ubuntu 22.04 environment).
def convert_originir_to_qprog(file_path: str, machine: QuantumMachine) -> list
def convert_originir_str_to_qprog(ir_str: str, machine: QuantumMachine) -> list
def convert_originir_file_to_qprog(file_path: str) -> QProg
def convert_originir_string_to_qprog(ir_str: str) -> QProg
Quantum Bit
OriginIR uses QINIT
to allocate quantum bits, with the format being QINIT
followed by a space and the total number of classical registers. An example is as follows:
- Note
- Except for comments,
QINIT
must appear on the first line of the OriginIR program.
When using quantum bits, OriginIR represents a specific quantum bit as q[i]
, where i
is the quantum bit index. The i
can be an unsigned integer constant, a variable, or an expression using c[i]
as a substitute. An example is as follows:
q[1], q[c[0]], q[c[1] + c[2] + c[3]]
Classical Register
OriginIR uses CREG
to allocate classical registers, with the format being CREG
followed by a space and the total number of classical registers. An example is as follows:
When using classical registers, OriginIR represents a specific classical register as c[i]
, where i
is the classical register index. Here, i
must be an unsigned integer constant. An example is as follows:
Quantum Logic Gate
OriginIR categorizes quantum logic gates into the following types:
- Single-gate without parameters: The keywords include
H
, T
, S
, X
, Y
, Z
, X1
, Y1
, Z1
, and I
, representing single quantum logic gates with no parameters. The format for usage is "quantum logic gate keyword + space + target quantum bit". An example is as follows:
- Single-gate with one parameter: The keywords include
RX
, RY
, RZ
, U1
, and P
, representing single quantum logic gates with one parameter. The format for usage is "quantum logic gate keyword + space + target quantum bit + comma + (rotation angle)". An example is as follows:
- Single-gate with two parameters: The keywords include
U2
and RPHI
, representing single quantum logic gates with two parameters. The format for usage is "quantum logic gate keyword + space + target quantum bit + comma + (two rotation angles)". An example is as follows: U2 q[0],(1.570796,-3.141593)
- Single-gate with three parameters: The keyword includes
U3
, representing a single quantum logic gate with three parameters. The format for usage is "quantum logic gate keyword + space + target quantum bit + comma + (three rotation angles)". An example is as follows: U3 q[0],(1.570796,4.712389,1.570796)
- Single-gate with four parameters: The keyword includes
U4
, representing a single quantum logic gate with four parameters. The format for usage is "quantum logic gate keyword + space + target quantum bit + comma + (four rotation angles)". An example is as follows: U4 q[1],(3.141593,4.712389,1.570796,-3.141593)
- Two-gate without parameters: The keywords include
CNOT
, CZ
, ISWAP
, and SWAP
, representing two quantum logic gates with no parameters. The format for usage is "quantum logic gate keyword + space + control qubit + comma + target qubit". An example is as follows:
- Two-gate with one parameter: The keywords include
CP
,CR
,RXX
, RYY
, RZZ
, and RZX
, representing two quantum logic gates with one parameter. The format for usage is "quantum logic gate keyword + space + control qubit + comma + target qubit + comma + (rotation angle)". An example is as follows:
- Two-gate with four parameters: The keyword includes
CU
, representing a two quantum logic gate with four parameters. The format for usage is "quantum logic gate keyword + space + control qubit + comma + target qubit + comma + (four rotation angles)". An example is as follows: CU q[1],q[3],(3.141593,4.712389,1.570796,-3.141593)
- Three-gate without parameters: The keyword includes
TOFFOLI
, representing a three quantum logic gate with no parameters. The format for usage is "quantum logic gate keyword + space + control qubit 1 + comma + control qubit 2 + comma + target qubit". An example is as follows:
- Note
- It is important to note that for all single-gate operations, the target quantum bit can be either an entire array of quantum bits or a single quantum bit. When it is an entire array of quantum bits, for example: When the size of the quantum bit array is 3, it is equivalent to:
Transpose Conjugate Operation
In OriginIR, you can perform a transpose conjugate operation on one or more quantum logic gates. OriginIR uses the DAGGER
and ENDDAGGER
keywords to define the scope of the transpose conjugate operation. Each DAGGER
must have a matching ENDDAGGER
. The example is as follows:
DAGGER
H q[0]
CNOT q[0],q[1]
ENDDAGGER
Adding Control Bit Operation
OriginIR can add control qubits to one or more quantum logic gates using the CONTROL
and ENDCONTROL
keywords to define the range for adding control qubits. The CONTROL
is followed by a space and the list of control qubits. Here's an example:
CONTROL q[2],q[3]
H q[0]
CNOT q[0],q[1]
ENDCONTROL
MEASURE
In OriginIR, MEASURE
represents a measurement operation on the specified quantum bit, with the result stored in the specified classical register. MEASURE
is followed by a space, the target quantum bit, a comma, and the target classical register. Here's an example:
If the number of requested quantum qubits and classical registers is the same, q
can be used to represent all quantum qubits, and c
can be used to represent all classical bits. Here's an example:
If the number of quantum qubits and classical bits is both 3, it is equivalent to:
MEAUSRE q[0],c[0]
MEAUSRE q[1],c[1]
MEAUSRE q[2],c[2]
BARRIER
The BARRIER
operation in OriginIR is used to block the qubits involved in the operation, preventing optimization and execution during the process. The format is BARRIER
followed by a space and the target qubits. The target qubits can be a whole array of qubits or individual/multiple qubits. Here’s an example:
BARRIER q
BARRIER q[0]
BARRIER q[0],q[1],q[2]
OriginIR Program Example
Here is an example of an OriginIR quantum program that characterizes the OPE algorithm:
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]
CR q[0],q[1],(1.570796)
H q[0]
ENDDAGGER
MEASURE q[0],c[0]
MEASURE q[1],c[1]
OriginIR Conversion Tool
QPanda provides a set of OriginIR conversion tools, mainly used to translate quantum programs between QProg and OriginIR. OriginIR is an intermediate representation (IR) used to represent the information of quantum programs. QProg is a container class for quantum programming and represents the highest-level unit of a quantum program. Below, we will provide a detailed introduction to the interface definitions and usage of these conversion tools.
- Translate the instruction set string in OriginIR format into a QProg object.
- Translate the instruction set file in OriginIR format into a QProg object.
- Translate the QProg object into an instruction set string in OriginIR format.
OriginIR String Translated to QProg
The compilation module of QPanda defines convert_originir_string_to_qprog for translating the OriginIR instruction set string into a QProg object.
Below is a simple interface call example to demonstrate the process of converting an OriginIR instruction set string into a quantum program (QProg):
Python
if __name__ == "__main__":
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]
// CR q[0],q[1],(1.570796)
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=1)
res_lis = machine.result().get_state_vector()
print("Result(stv) of running qprog:\n")
for val in res_lis:
print("(", val.real, ",", val.imag, ")")
print(draw_qprog(prog, PIC_TYPE.TEXT, {}, param_show=True))
The output is as follows:
Result(stv) of running qprog:
( 3.6742350925920025e-07 , -0.7071067811864525 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 3.6742350925920025e-07 , -0.7071067811864525 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
┌─┐ ┌──────────────┐ ┌──────────────┐ ┌─┐
q_0: |0>─┤H├ ──────────────── ┤0 ├ ┤0 ├ ─┤M├───
├─┤ ┌──────────────┐ │ │ │ QCircuit_2 │ └╥┘┌─┐
q_1: |0>─┤H├ ┤0 ├ ┤ QCircuit_1 ├ ┤1 ├ ──╫─┤M├
├─┤ │ QCircuit_0 │ │ │ └──────────────┘ ║ └╥┘
q_2: |0>─┤H├ ┤1 ├ ┤1 ├ ──────────────── ──╫──╫─
└─┘ └──────────────┘ └──────────────┘ ║ ║
c : / ══════════════════════════════════════════════════════════╩══╩═
0 1
- Note
- For operation types that are not supported, errors may occur during the conversion of OriginIR into a quantum program.
OriginIR File Translated to QProg
The compilation module of QPanda defines convert_originir_file_to_qprog for translating the OriginIR instruction set file into a QProg object.
Below is a simple interface call example to demonstrate the process of converting an OriginIR instruction set file into a quantum program (QProg):
Python
"""sample_originir.txt
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]
// CR q[0],q[1],(1.570796)
H q[0]
ENDDAGGER
MEASURE q[0],c[0]
MEASURE q[1],c[1]
"""
if __name__ == "__main__":
originir_file_path = "Test/Compiler/OriginIR/OriginIRToQProg/sample_originir.txt"
prog = convert_originir_file_to_qprog(originir_file_path)
machine = CPUQVM()
machine.run(prog=prog, shots=1)
res_lis = machine.result().get_state_vector()
print("Result(stv) of running qprog:\n")
for val in res_lis:
print("(", val.real, ",", val.imag, ")")
print(draw_qprog(prog, PIC_TYPE.TEXT, {}, param_show=True))
The output is as follows:
Result(stv) of running qprog:
( 3.6742350925920025e-07 , -0.7071067811864525 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 3.6742350925920025e-07 , -0.7071067811864525 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
┌─┐ ┌──────────────┐ ┌──────────────┐ ┌─┐
q_0: |0>─┤H├ ──────────────── ┤0 ├ ┤0 ├ ─┤M├───
├─┤ ┌──────────────┐ │ │ │ QCircuit_2 │ └╥┘┌─┐
q_1: |0>─┤H├ ┤0 ├ ┤ QCircuit_1 ├ ┤1 ├ ──╫─┤M├
├─┤ │ QCircuit_0 │ │ │ └──────────────┘ ║ └╥┘
q_2: |0>─┤H├ ┤1 ├ ┤1 ├ ──────────────── ──╫──╫─
└─┘ └──────────────┘ └──────────────┘ ║ ║
c : / ══════════════════════════════════════════════════════════╩══╩═
0 1
- Note
- For operation types that are not supported, errors may occur during the conversion of OriginIR into a quantum program.
QProg Translated to OriginIR String
The compilation module of QPanda defines convert_qprog_to_originir for translating a QProg object into an OriginIR instruction set string.
Below is a simple interface call example to demonstrate the process of converting a quantum program (QProg) into an OriginIR instruction set string:
Python
if __name__ == "__main__":
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]
// CR q[0],q[1],(1.570796)
H q[0]
ENDDAGGER
MEASURE q[0],c[0]
MEASURE q[1],c[1]
"""
prog = QProg(originir_str, False)
machine = CPUQVM()
machine.run(prog=prog, shots=1)
res_lis = machine.result().get_state_vector()
print("Result(stv) of running qprog:\n")
for val in res_lis:
print("(", val.real, ",", val.imag, ")")
print("\n")
print(draw_qprog(prog, PIC_TYPE.TEXT, {}, param_show=True))
convert_str = convert_qprog_to_originir(prog)
print(convert_str)
The output is as follows:
Result(stv) of running qprog:
( 3.6742350925920025e-07 , -0.7071067811864525 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 3.6742350925920025e-07 , -0.7071067811864525 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
( 0.0 , 0.0 )
┌─┐ ┌──────────────┐ ┌──────────────┐ ┌─┐
q_0: |0>─┤H├ ──────────────── ┤0 ├ ┤0 ├ ─┤M├───
├─┤ ┌──────────────┐ │ │ │ QCircuit_2 │ └╥┘┌─┐
q_1: |0>─┤H├ ┤0 ├ ┤ QCircuit_1 ├ ┤1 ├ ──╫─┤M├
├─┤ │ QCircuit_0 │ │ │ └──────────────┘ ║ └╥┘
q_2: |0>─┤H├ ┤1 ├ ┤1 ├ ──────────────── ──╫──╫─
└─┘ └──────────────┘ └──────────────┘ ║ ║
c : / ══════════════════════════════════════════════════════════╩══╩═
0 1
QINIT 3
CREG 2
H q[2]
H q[0]
H q[1]
CONTROL q[1]
RX q[2],(-3.14159)
ENDCONTROL
CONTROL q[0]
RX q[2],(-3.14159)
RX q[2],(-3.14159)
ENDCONTROL
DAGGER
H q[1]
H q[0]
ENDDAGGER
MEASURE q[0],c[0]
MEASURE q[1],c[1]