Skip to content

OriginIR 语法详解 ​

OriginIR 是 QPanda 的原生量子程序中间表示(Intermediate Representation, IR),是 pyqpanda3 生态内序列化、传输与调试量子程序的文本格式。本章逐条详解 OriginIR 的词法与语法:程序整体结构、QINIT/CREG 声明、各类量子门、角度表达式、DAGGER/CONTROL 修饰、QIF/QWHILE 经典控制流、MEASURE/RESET 操作、自定义门,以及常见错误对照。

如何把 OriginIR 文本转换为 QProg(以及反向转换)属于"怎么用"的问题,见 IR 转换 与 convert_originir_string_to_qprog 等 API 参考;本章只回答"语法长什么样"。


1. 语法版式总览 ​

权威语法定义 ​

OriginIR 的权威语法由 ANTLR 词法/语法文件(.g4)定义:

  • originirLexer.g4(138 行):词法规则——关键字、门名 token、数字与标识符。
  • originirParser.g4(330 行):语法规则——程序结构与各语句的产生式。

pyqpanda3 0.4.1 发行版内置的转译器(intermediate_compiler 模块)实现的是经典方言:它与 .g4 在 QINIT/CREG、门声明、MEASURE/RESET 等核心语法上完全一致,但在版本头、表达式、控制流与自定义门的写法上保留了传统形式(下文的示例全部经 convert_originir_string_to_qprog 实测通过)。双方言的差异逐条列在第 9 节。

程序结构 ​

按 .g4 的 program 规则,一个 OriginIR 程序是:

text
program: version? statement* EOF

即"可选的版本头 + 若干条语句"。每条语句属于下列种类之一(statement 规则):

语句种类语法规则示例
声明(量子比特/经典寄存器)declaration → qinit_declaration / cinit_declarationQINIT 2、CREG 4
量子门声明quantum_gate_declarationH q[0]、RX q[0],(PI/2)
测量measure_statementMEASURE q[0],c[0]
重置reset_statementRESET q[1]
经典赋值assign_statementc[0]=c[0]+1(见第 5、9 节)
屏障barrier_statementBARRIER q[0],q[1]
文件包含includestatementinclude "other.originir"(见第 9 节)
块语句blockstatementDAGGER/CONTROL/QIF/QWHILE/QGATE

最小的完整程序如下(这是全章所有例子的共同骨架):

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

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

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(prog.originir() 为往返转换:QProg 再转回 OriginIR 文本):

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

本章所有示例都遵循这一模式:OriginIR 文本 → convert_originir_string_to_qprog 解析为 QProg → 打印往返文本验证。注意往返输出中的角度参数会被求值成定点小数(见第 5 节),且 CREG 会被归一化为实际用于 MEASURE 的经典比特数(最小为 1,如本节未测量时输出 CREG 1)。


2. 头部、版本声明、注释 ​

版本头 ​

.g4 的 program 规则允许可选版本头:

text
version: ORIGINIR VersionSpecifier SEMICOLON

例如 ORIGINIR 1.0;。但 pyqpanda3 0.4.1 的转译器尚未实现版本头解析,实测报错如下(错误信息为运行时原文,下同):

text
ORIGINIR 1.0;
QINIT 2
H q[0]

运行结果:

text
Error:
	<Expected> OriginIR Statement
	<Problem> The string is invalid originir string.It's Identifier (ORIGINIR)
	<Result> Exit.

因此 0.4.1 中编写 OriginIR 程序时不要写版本头,直接从 QINIT 开始。

注释 ​

词法器支持 C++ 风格的两种注释:// 单行注释与 /* */ 块注释(LineComment/BlockComment 规则),两者都会被跳过,可出现在任意位置:

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
// line comment
/* block
   comment */
H q[0]  // trailing comment
CNOT q[0],q[1]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 2
CREG 1
H q[0]
CNOT q[0],q[1]

语句分隔 ​

0.4.1 的方言以换行分隔语句(NEWLINE 被跳过、可空行),不接受分号。.g4 要求每条语句后跟分号,但 0.4.1 实测对分号直接报错:

text
QINIT 2
H q[0];

运行结果:

text
Error:
	<Expected> OriginIR Statement
	<Problem> The string is invalid originir string.It's ;
	<Result> Exit.

关键字大小写 ​

关键字严格区分大小写(Identifier 规则为 [a-zA-Z_][a-zA-Z_0-9]*,QINIT 等关键字为大写 token)。qinit 不会被识别:

text
qinit 2
H q[0]

运行结果:

text
Error:
	<Expected> OriginIR Statement
	<Problem> The string is invalid originir string.It's Identifier (qinit)
	<Result> Exit.

3. QINIT / CREG 声明 ​

QINIT 申请量子比特,CREG 申请经典寄存器,格式均为"关键字 + 空格 + 数量":

text
qinit_declaration : QINIT_KEY Integer_Literal ;
cinit_declaration : CREG_KEY Integer_Literal ;

数量必须是非负整数(Integer_Literal: [1-9][0-9]* | '0',即无前导零)。在 0.4.1 中两者都必须位于使用之前:

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 4
CREG 4
H q[0]
H q[1]
H q[2]
H q[3]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 4
CREG 1
H q[0]
H q[1]
H q[2]
H q[3]

引用单个比特与整个比特数组 ​

  • 单个量子比特用 q[i],i 为下标(index: LBRACK Integer_Literal RBRACK,必须是整数常量,见第 9 节关于 q[c[0]] 的对照)。
  • 部分单比特门与 MEASURE 也接受裸的 q,表示整个比特数组(展开为逐比特操作):
python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 3
H q"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(H q 展开为对每个比特的 H):

text
QINIT 3
CREG 1
H q[0]
H q[1]
H q[2]

MEASURE q,c 要求量子比特总数与经典寄存器总数一致(详见第 7 节)。

常见错误:数量不匹配 ​

MEASURE q,c 的比特数与寄存器数不一致时:

text
QINIT 2
CREG 3
MEASURE q,c

运行结果:

text
Error: For "MEASURE q c", qbits' total num should be same as cbits'. Here, they are different.

未声明 CREG 就测量:

text
QINIT 1
MEASURE q[0],c[0]

运行结果:

text
add_measure_literal too little cbits is allocated

4. 单比特、双比特与三比特门 ​

quantum_gate_declaration 按"比特数 × 参数个数"把门分成 10 类。下表列出词法器中的门 token 及其所属类别(.g4 的 single_gate_without_parameter_type 等规则);官方教程列出、但 .g4 与 0.4.1 行为不一致的项(CP/RZX/RXX/RYY/RZZ/ECHO/ISWAPTHETA/NOT)见第 9 节。

类别语法规则门
单比特无参single_gate_without_parameter_typeH T S X Y Z X1 Y1 Z1 I
单比特单参single_gate_with_one_parameter_typeRX RY RZ U1 ECHO
单比特双参single_gate_with_two_parameter_typeU2 RPhi
单比特三参single_gate_with_three_parameter_typeU3
单比特四参single_gate_with_four_parameter_typeU4
双比特无参double_gate_without_parameter_typeCNOT CZ ISWAP SQISWAP SWAP
双比特单参double_gate_with_one_parameter_typeISWAPTHETA CR(0.4.1 另接受 CP RZX RXX RYY RZZ)
双比特四参double_gate_with_four_parameter_typeCU
三比特无参triple_gate_without_parameter_typeTOFFOLI

通用格式:

  • 无参门:门 q[i](单比特)或 门 q[i],q[j](双比特)/ 门 q[i],q[j],q[k](三比特);
  • 有参门:门 q[i],(p1,p2,...),参数用圆括号括起、逗号分隔(参数写法见第 5 节)。

单比特无参门 ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 3
H q[0]
X q[1]
T q[2]
I q[0]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 3
CREG 1
H q[0]
X q[1]
T q[2]
I q[0]

单比特单参门 ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 3
RX q[0],(PI/2)
RY q[1],(0.3)
RZ q[2],(-0.5)
U1 q[0],(PI)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(注意角度被求值):

text
QINIT 3
CREG 1
RX q[0],(1.57079633)
RY q[1],(0.30000000)
RZ q[2],(-0.50000000)
U1 q[0],(3.14159265)

单比特双参门(U2 / RPhi) ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
U2 q[0],(PI/2,-PI/3)
RPhi q[1],(0.5,1.5)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 2
CREG 1
U2 q[0],(1.57079633,-1.04719755)
RPhi q[1],(0.50000000,1.50000000)

单比特三参门(U3) ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 1
U3 q[0],(PI/2,PI/3,PI/4)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 1
CREG 1
U3 q[0],(1.57079633,1.04719755,0.78539816)

单比特四参门(U4) ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 1
U4 q[0],(0.1,0.2,0.3,0.4)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 1
CREG 1
U4 q[0],(0.10000000,0.20000000,0.30000000,0.40000000)

双比特无参门 ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 4
CNOT q[0],q[1]
CZ q[1],q[2]
ISWAP q[2],q[3]
SQISWAP q[0],q[3]
SWAP q[1],q[2]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 4
CREG 1
CNOT q[0],q[1]
CZ q[1],q[2]
ISWAP q[2],q[3]
SQISWAP q[0],q[3]
SWAP q[1],q[2]

双比特单参门 ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
CR q[0],q[1],(PI/4)
RZX q[0],q[1],(0.5)
RXX q[0],q[1],(0.5)
RYY q[0],q[1],(0.5)
RZZ q[0],q[1],(0.5)
CP q[0],q[1],(0.5)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(CP 在往返输出中被重新序列化为 CR,见第 9 节):

text
QINIT 2
CREG 1
CR q[0],q[1],(0.78539816)
RZX q[0],q[1],(0.50000000)
RXX q[0],q[1],(0.50000000)
RYY q[0],q[1],(0.50000000)
RZZ q[0],q[1],(0.50000000)
CR q[0],q[1],(0.50000000)

双比特四参门(CU) ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
CU q[0],q[1],(0.1,0.2,0.3,0.4)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 2
CREG 1
CU q[0],q[1],(0.10000000,0.20000000,0.30000000,0.40000000)

三比特门(TOFFOLI) ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 3
TOFFOLI q[0],q[1],q[2]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(TOFFOLI 在往返输出中反解为受控 X 块,见第 6 节的 CONTROL):

text
QINIT 3
CREG 1
CONTROL q[0],q[1]
X q[2]
ENDCONTROL

ECHO(单参门) ​

.g4 的 single_gate_with_one_parameter_type 包含 ECHO,0.4.1 同样支持:

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 1
ECHO q[0],(0.5)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 1
CREG 1
ECHO q[0],(0.50000000)

5. 表达式与常量 ​

常量 ​

constant 规则只有三类:

text
constant : Integer_Literal | Double_Literal | PI ;

即整数(无前导零)、小数(如 0.5、-3.141593)与 PI。

角度参数表达式 ​

所有带角度的门,参数都写在圆括号内:门 q[i],(expr1,expr2,...)。0.4.1 在解析时直接求值角度表达式,支持 + - * / 四则运算、圆括号与一元负号;求值结果以定点小数写入往返输出(默认 8 位小数):

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 3
RX q[0],(PI/2)
RX q[1],(1+2*3)
RX q[2],(-PI/2)
RY q[0],(2*PI/3)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(1+2*3 求值为 7,2*PI/3 求值为 2.09439510):

text
QINIT 3
CREG 1
RX q[0],(1.57079633)
RX q[1],(7.00000000)
RX q[2],(-1.57079633)
RY q[0],(2.09439510)

.g4 的 constant_expression 规则形式上只允许"常量 op 常量"(单个运算,constant_expression: constant | constant arithmetic_op constant | arithmetic_op constant),实测 0.4.1 的角度求值器比它更宽松,接受任意长度的算术链(如上面的 1+2*3、2*PI/3)。

标识符只能作为自定义门形参出现(见第 8 节);在顶层写未定义标识符(如 RX q[0],(theta))会在求值时失败。

经典表达式与赋值:0.4.1 暂不支持 ​

.g4 定义了完整的经典表达式链与赋值语句(expression → logical_or_expression → … → primary_expression,以及 assign_statement: c_KEY_declaration ASSIGN logical_or_expression),可用于 QIF/QWHILE 条件与 c[0]=c[0]+1 这类赋值。0.4.1 未实现经典表达式(官方教程亦标注"经典表达式目前暂不支持"),实测报错如下:

text
QINIT 1
CREG 2
c[0]=c[0]+1

运行结果(解析错误打印到 stderr,抛出的异常为 Unknown exception):

text
Error at line 3, column 6: Expected expression, got c.
text
Unknown exception
text
QINIT 5
CREG 5
QWHILE c[0]<5
H q[c[0]]
QENDWHILE

运行结果:

text
Error:
	<Expected> OriginIR Statement
	<Problem> The string is invalid originir string.It's <
	<Result> Exit.

0.4.1 中 QIF/QWHILE 的条件只能是"已测量的经典比特列表"形式,见第 7 节。


6. DAGGER / CONTROL 修饰 ​

DAGGER 对一组门做转置共轭(求逆),CONTROL 为一组门添加控制比特。.g4 的现行形式是块语法:

text
dagger_statement : DAGGER_KEY LBRACE statement* RBRACE ;
control_statement : CONTROL_KEY controlbit_list LBRACE statement* RBRACE ;

0.4.1 同时接受传统形式(DAGGER … ENDDAGGER、CONTROL ctrlbit_list … ENDCONTROL)与上述块形式(DAGGER { ... }、CONTROL q[i] { ... })。

传统形式 DAGGER / ENDDAGGER ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
DAGGER
H q[0]
CNOT q[0],q[1]
ENDDAGGER"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(0.4.1 往返输出时每个门单独输出一个 DAGGER 块):

text
QINIT 2
CREG 1
DAGGER
CNOT q[0],q[1]
ENDDAGGER
DAGGER
H q[0]
ENDDAGGER

块形式 DAGGER { ... } ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
DAGGER {
H q[0]
CNOT q[0],q[1]
}"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 2
CREG 1
DAGGER
CNOT q[0],q[1]
ENDDAGGER
DAGGER
H q[0]
ENDDAGGER

传统形式 CONTROL / ENDCONTROL ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 3
CONTROL q[2]
H q[0]
CNOT q[0],q[1]
ENDCONTROL"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 3
CREG 1
CONTROL q[2]
H q[0]
ENDCONTROL
CONTROL q[2]
CNOT q[0],q[1]
ENDCONTROL

多个控制比特 ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 3
CONTROL q[1],q[2]
H q[0]
ENDCONTROL"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 3
CREG 1
CONTROL q[1],q[2]
H q[0]
ENDCONTROL

切勿混用块形式与传统结束符

实测(pyqpanda3 0.4.1)DAGGER { ... } 后再接 ENDDAGGER(或 CONTROL { ... } 后再接 ENDCONTROL)会使解析器陷入死循环(无限挂起)。请使用 DAGGER { ... } 或 DAGGER ... ENDDAGGER 之一,不要同时使用。


7. QIF / QWHILE 经典控制流与 MEASURE / RESET ​

.g4 的现行语法把条件写成圆括号表达式 + 块:

text
qif_statement : QIF_KEY LPAREN expression RPAREN LBRACE statement* RBRACE qelse_statement_fragment? ;
qwhile_statement : QWHILE_KEY LPAREN expression RPAREN LBRACE statement* RBRACE ;

0.4.1 实现的是传统形式:QIF c[i],c[j] ... QENDIF 与 QWHILE c[i] ... QENDWHILE,条件为逗号分隔的经典比特列表(不能写表达式,见第 5、9 节)。

QIF / QELSE / QENDIF ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
CREG 2
X q[0]
MEASURE q[0],c[0]
QIF c[0]
Y q[1]
QELSE
Z q[1]
QENDIF
MEASURE q[1],c[1]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 2
CREG 2
X q[0]
MEASURE q[0],c[0]
QIF c[0]
Y q[1]
QELSE
Z q[1]
QENDIF
MEASURE q[1],c[1]

多条件分支:QELSEIF ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 4
CREG 4
X q[0]
QIF c[0]
Y q[1]
QELSEIF c[1]
Z q[2]
QELSE
I q[3]
QENDIF"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 4
CREG 1
X q[0]
QIF c[0]
Y q[1]
QELSEIF c[1]
Z q[2]
QELSE
I q[3]
QENDIF

多条件比特:QIF c[0],c[1] ​

条件可列出多个经典比特(官方教程的写法)。按官方教程的模型,这些比特同时为真时进入分支:

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 3
CREG 3
QIF c[0],c[1]
X q[2]
QENDIF"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 3
CREG 1
QIF c[0],c[1]
X q[2]
QENDIF

QWHILE / QENDWHILE ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
CREG 2
X q[1]
QWHILE c[1]
X q[0]
X q[1]
MEASURE q[1],c[1]
QENDWHILE
MEASURE q[0],c[0]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 2
CREG 2
X q[1]
QWHILE c[1]
X q[0]
X q[1]
MEASURE q[1],c[1]
QENDWHILE
MEASURE q[0],c[0]

QWHILE 的条件比特必须在循环开始前已通过 MEASURE 置位,且循环体必须包含改变条件比特的测量,否则循环无法结束(官方教程的写法即先 X q[1] 再在循环体内 MEASURE q[1],c[1])。

0.4.1 执行语义提示 ​

实测(pyqpanda3 0.4.1,CPUQVM):经 convert_originir_string_to_qprog 解析出的 QIF/QWHILE,在 QVM 上运行时条件分支不会触发——解析与往返转换都正常,但分支体不执行。下面的例子先把 q[0] 置 1 并测量(c[0]=1),再 QIF c[0] 对 q[0] 再施加 X,最后测量:

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

src = """QINIT 1
CREG 1
X q[0]
MEASURE q[0],c[0]
QIF c[0]
X q[0]
QENDIF
MEASURE q[0],c[0]"""

machine = CPUQVM()
machine.run(prog=convert_originir_string_to_qprog(src), shots=16)
print(machine.result().get_counts())

运行结果(若分支触发,第二次测量应为 '0';实测仍为 '1',分支未执行):

text
{'1': 16}

而用核心 API 构建的等价程序(qif 结构)分支正常执行,测量结果为 {'0': 16}。若需要在 0.4.1 中执行动态线路,请使用核心 API 的 qif/qelse/qwhile(见 动态线路 教程)。get_counts() 返回的比特串从左到右对应 c[n-1] … c[0];0.4.1 上实测,该约定对 OriginIR 解析的程序与核心 API(measure/qif)构建的程序均成立(例如 X q[1] 后接 measure([0,1],[0,1]) 返回 '10')。

MEASURE 操作 ​

MEASURE 测量量子比特并把结果写入经典寄存器(measure_statement 规则:MEASURE_KEY q_KEY_declaration COMMA c_KEY_declaration):

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 1
CREG 1
H q[0]
MEASURE q[0],c[0]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 1
CREG 1
H q[0]
MEASURE q[0],c[0]

当量子比特数与经典寄存器数相同时,可用裸的 q,c 一次测量全部(MEASURE_KEY Q_KEY COMMA C_KEY,展开为逐比特测量,见第 3 节示例);数量不一致时报错见第 3 节。

RESET 操作(语法支持,0.4.1 转换暂不支持) ​

.g4 有 reset_statement 规则(RESET_KEY q_KEY_declaration | RESET_KEY Q_KEY),0.4.1 可以解析,但转换为 QProg 时暂不支持,实测打印警告后失败(警告为运行时原文,含源码中的拼写 Warrnig):

text
QINIT 2
RESET q[1]

运行结果:

text
Compiler | BuildQProg.h | QProgNodeCollector | add_reset_literal | Warrnig: The Reset operation will be ok in future.Now, it doesn't work.Exit.
text
Caught an unknown exception!

8. 自定义门声明与作用域 ​

.g4 的现行形式是 QGATE 门名(形参列表) { 门体 }(gate_func_statement 规则);0.4.1 实现的是传统形式:

text
QGATE name qubit_formal_params,(angle_formal_params)
body (calls to built-in gates or previously defined custom gates)
ENDQGATE

门体语句同样以换行分隔、不带分号。自定义门的调用方式与内置门一致:门名 q[0],q[1] 或 门名 q[0],(角度实参),实参在调用处求值并代入门体。

基本自定义门 ​

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
QGATE new_H a,b
Y a
Z b
ENDQGATE
new_H q[0],q[1]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(自定义门调用在往返输出中被内联展开):

text
QINIT 2
CREG 1
Y q[0]
Z q[1]

带角度形参的自定义门 ​

角度形参写在圆括号内,门体内的角度表达式可引用形参(如 PI/2+b),调用时用实参求值:

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
QGATE new_RX a,(b)
RX a,(PI/2+b)
X a
ENDQGATE
new_RX q[1],(PI/4)"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果(PI/2+b = PI/2 + PI/4 = 2.35619449,实参代入后求值):

text
QINIT 2
CREG 1
RX q[1],(2.35619449)
X q[1]

门体嵌套调用自定义门 ​

门体可以调用此前定义的自定义门:

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
QGATE inner a
H a
ENDQGATE
QGATE outer a,b
inner a
X b
ENDQGATE
outer q[0],q[1]"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 2
CREG 1
H q[0]
X q[1]

用裸 q 调用自定义门 ​

当比特形参数与量子比特总数一致时,调用处可用裸 q:

python
from pyqpanda3.intermediate_compiler import convert_originir_string_to_qprog

src = """QINIT 2
QGATE new_2 a,b
H a
X b
ENDQGATE
new_2 q"""

prog = convert_originir_string_to_qprog(src)
print(prog.originir())

运行结果:

text
QINIT 2
CREG 1
H q[0]
X q[1]

实参数量不匹配 ​

调用时比特实参数与形参数不一致会报错:

text
QINIT 2
QGATE new_H a
H a
ENDQGATE
new_H q[0],q[1]

运行结果:

text
IRQProgNodeCollectorParser | parse_custom_gate_call_statement | Qubit parameter count of new_H (i.e. Custom gate) mismatch.

作用域与命名约束 ​

  • 形参名只在门体内有效(角度形参可出现在门体内的角度表达式中);门体外的语句无法引用门体形参。
  • 形参名不能与关键字冲突(.g4 注释中的原话:自定义门的形参名不能与相关关键字冲突)。
  • 0.4.1 转换自定义门时会在 stderr 打印调试信息(Custom Gate: 门名、Qbit Params: ...、Gate Operations: ...),不影响转换结果。

9. 常见错误对照(词法与语法层) ​

本节把".g4 权威语法"与"pyqpanda3 0.4.1 实测行为"逐条对照。convert_originir_string_to_qprog 对不合法文本抛出的异常信息多为运行时原文(Unknown exception 为 0.4.1 对部分解析错误的统一转译;更具体的解析错误会打印到 stderr)。所有对照以第 1 节的 .g4 词法/语法文件为权威基准。

#构造.g4(权威语法)pyqpanda3 0.4.1 实测
1ORIGINIR 1.0; 版本头program: version? statement*,支持报错 It's Identifier (ORIGINIR),勿写版本头
2include "file"includestatement,支持报错 It's EOF(0.4.1 未实现文件包含)
3语句尾分号 ;每条 statement 后必须有 SEMICOLON报错 It's ;,以换行分隔语句
4QIF (expr) { ... }qif_statement 现行形式stderr:Expected 'c', got '(',异常 Unknown exception
5QWHILE (expr) { ... }qwhile_statement 现行形式异常 Unknown exception
6QGATE name(params) { ... }gate_func_statement 现行形式stderr:Expected 'Identifier', got '(',异常 Unknown exception
7经典赋值 c[0]=c[0]+1assign_statement,支持异常 Unknown exception(经典表达式暂不支持)
8条件比较 QWHILE c[0]<5 / QIF c[0]==1expression 支持比较运算报错 It's < / It's ==,条件只能为 c[i] 列表
9下标表达式 q[c[0]]index: LBRACK Integer_Literal RBRACK,仅整数常量stderr:Expected expression, got c,异常 Unknown exception
10NOT q[0]词法器有 NOT_GATE token,但无任何 _type 规则引用它报错 It's NOT
11ISWAPTHETA q[0],q[1],(0.5)double_gate_with_one_parameter_type 含 ISWAPTHETA解析通过,转换报错 ISWAPTHETA is not supported by QGate. exit.
12RESET q[1]reset_statement,支持解析通过,转换警告 The Reset operation will be ok in future.Now, it doesn't work.Exit. 后失败
13CP / RZX / RXX / RYY / RZZ词法器仅收录 CP_GATE(同样未被任何 _type 规则引用);RZX 等无对应 token0.4.1 全部可解析执行;CP 往返输出时被序列化为 CR
14ECHO q[0],(0.5)single_gate_with_one_parameter_type 含 ECHO正常支持
15传统控制流结束符 QENDIF/QENDWHILE/ENDQGATE/ENDDAGGER/ENDCONTROL词法器有对应 token,但 parser 规则未引用(qif_statement 仅 ELSE)0.4.1 传统方言的组成部分,正常支持
16DAGGER { ... } 后接 ENDDAGGER(混用)—解析器无限挂起(实测死循环),切勿混用
17QIF c[0] 分支在 CPUQVM 上的执行—经 OriginIR 解析的分支不触发(实测);核心 API qif 构建的等价程序正常

典型错误文本(原文):

text
Error:
	<Expected> OriginIR Statement
	<Problem> The string is invalid originir string.It's Identifier (ORIGINIR)
	<Result> Exit.
text
Error:
	<Expected> OriginIR Statement
	<Problem> The string is invalid originir string.It's ;
	<Result> Exit.
text
Error at line 3, column 5: Expected 'c', got '('.
Expected(int) '132', got(int) '58'.
text
Error at line 2, column 10: Expected 'Identifier', got '('.
Expected(int) '113', got(int) '58'.
text
Error at line 3, column 5: Expected expression, got c.
text
current identifier:theta
Error: <Pos>:Statement.hpp >IdentifierExpression > getFP
text
BuildQProg | QProgNodeCollector | add_qgate |ISWAPTHETA is not supported by QGate. exit.
text
Compiler | BuildQProg.h | QProgNodeCollector | add_reset_literal | Warrnig: The Reset operation will be ok in future.Now, it doesn't work.Exit.
text
IRQProgNodeCollectorParser | parse_custom_gate_call_statement | Qubit parameter count of new_H (i.e. Custom gate) mismatch.

相关章节 ​

Released under the MIT License.