{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 含参量子线路的等价性检查\n",
    "\n",
    "[![下载Notebook](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.5.0/resource/_static/logo_notebook.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.5.0/mindquantum/zh_cn/advanced/mindspore_equivalence_checking_of_PQC.ipynb) \n",
    "[![下载样例代码](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.5.0/resource/_static/logo_download_code.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.5.0/mindquantum/zh_cn/advanced/mindspore_equivalence_checking_of_PQC.py) \n",
    "[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.5.0/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/r2.5.0/docs/mindquantum/docs/source_zh_cn/advanced/equivalence_checking_of_PQC.ipynb)\n",
    "\n",
    "## 概述\n",
    "\n",
    "在量子设备上运行含参量子线路之前,需要将其编译成由该设备支持的量子门集组成的新线路。于是,需要对编译前后的两个线路进行等价性检查。论文Equivalence Checking of Parameterized Quantum Circuits中提出了一种基于ZX演算的含参量子线路等价性检查方法,本文尝试在MindSpore Quantum架构中复现论文中的方法。\n",
    "\n",
    "论文链接:https://doi.org/10.1145/3566097.3567932"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 引入相关库\n",
    "from mindquantum.core.circuit import Circuit\n",
    "import numpy as np\n",
    "from mindquantum.core.gates import H, CNOT, RX, RZ\n",
    "from mindquantum.core.circuit import dagger"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第一步\n",
    "\n",
    "准备量子线路\n",
    "\n",
    "以Qiskit线路库中的TwoLocal线路为例。TwoLocal线路是由旋转层和纠缠层交替组成的含参线路,旋转层即作用在所有量子比特上的单量子门,纠缠层根据纠缠策略使用双量子门将量子比特纠缠起来。\n",
    "\n",
    "构造一个作用在127位量子比特上、由三组旋转层和纠缠层交替组成、纠缠策略为循环纠缠的TwoLocal线路,共包含508个参数。旋转层是作用在每一个量子比特上的含参[RX](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RX.html)门;循环纠缠层是由最后一个量子比特控制第一个量子比特的[CNOT](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.CNOTGate.html)门,以及依次由前一个量子比特控制后一个量子比特的[CNOT](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.CNOTGate.html)门。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 每一组旋转层和纠缠层的组合就是一层ansatz线路\n",
    "def build_ansatz(n_qubits, depth):\n",
    "    circ = Circuit()    # 初始化量子线路\n",
    "\n",
    "    for i in range(depth):\n",
    "        for j in range(n_qubits):\n",
    "            circ += RX(f'theta{i*n_qubits+j}').on(j)    # 每个量子比特上一个RX门\n",
    "        circ += CNOT.on(0, n_qubits-1)    # 最后一个量子比特和第一个量子比特上一个CNOT门\n",
    "        for j in range(n_qubits-1):\n",
    "            circ += CNOT.on(j+1, j)    # 相邻两个量子比特上一个CNOT门,CNOT门作用在第j+1位,且受第j位控制\n",
    "\n",
    "    for j in range(n_qubits):\n",
    "        circ += RX(f'theta{depth*n_qubits+j}').on(j)    # 每个量子比特上一个RX门\n",
    "\n",
    "    return circ"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"476.8\" height=\"200.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"476.8\" height=\"200.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><text x=\"20.0\" y=\"100.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q1: </text><text x=\"20.0\" y=\"160.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q2: </text><line x1=\"48.8\" x2=\"456.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"456.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"456.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta0 </text><rect x=\"72.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta1 </text><rect x=\"72.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta2 </text><circle cx=\"192.8\" cy=\"160.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"40.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"172.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"178.8\" x2=\"206.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"252.8\" cy=\"40.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"252.8\" x2=\"252.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"232.8\" y=\"80.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"238.8\" x2=\"266.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"252.8\" x2=\"252.8\" y1=\"86.0\" y2=\"114.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"312.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"292.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"298.8\" x2=\"326.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"292.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"332.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"332.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta3 </text><rect x=\"352.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"392.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"392.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta4 </text><rect x=\"352.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"392.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"392.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta5 </text></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x7f09d84ffeb0>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 作用在3个量子比特上的一层ansatz线路示例\n",
    "build_ansatz(3, 1).svg()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ff0000; text-decoration-color: #ff0000; font-weight: bold\">                                       Circuit Summary                                       </span>\n",
       "╭───────────────────────┬───────────────────────────────────────────────────────────────────╮\n",
       "│<span style=\"font-weight: bold\"> </span><span style=\"color: #3b3b95; text-decoration-color: #3b3b95; font-weight: bold\">Info</span><span style=\"font-weight: bold\">                  </span>│<span style=\"font-weight: bold\"> </span><span style=\"color: #3b3b95; text-decoration-color: #3b3b95; font-weight: bold\">value</span><span style=\"font-weight: bold\">                                                             </span>│\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Number of qubit</span>       │ 127                                                               │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Total number of gate</span>  │ 889                                                               │\n",
       "│ Barrier               │ 0                                                                 │\n",
       "│ Noise Channel         │ 0                                                                 │\n",
       "│ Measurement           │ 0                                                                 │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Parameter gate</span>        │ 508                                                               │\n",
       "│ 508 ansatz parameters │ <span style=\"color: #48c9b0; text-decoration-color: #48c9b0\">theta0, theta1, theta2, theta3, theta4, theta5, theta6, theta7, </span>  │\n",
       "│                       │ <span style=\"color: #48c9b0; text-decoration-color: #48c9b0\">theta8, theta9...</span>                                                 │\n",
       "╰───────────────────────┴───────────────────────────────────────────────────────────────────╯\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1;38;2;255;0;0m                                       Circuit Summary                                       \u001b[0m\n",
       "╭───────────────────────┬───────────────────────────────────────────────────────────────────╮\n",
       "│\u001b[1m \u001b[0m\u001b[1;38;2;59;59;149mInfo\u001b[0m\u001b[1m                 \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1;38;2;59;59;149mvalue\u001b[0m\u001b[1m                                                            \u001b[0m\u001b[1m \u001b[0m│\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mNumber of qubit\u001b[0m       │ 127                                                               │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mTotal number of gate\u001b[0m  │ 889                                                               │\n",
       "│ Barrier               │ 0                                                                 │\n",
       "│ Noise Channel         │ 0                                                                 │\n",
       "│ Measurement           │ 0                                                                 │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mParameter gate\u001b[0m        │ 508                                                               │\n",
       "│ 508 ansatz parameters │ \u001b[38;2;72;201;176mtheta0, theta1, theta2, theta3, theta4, theta5, theta6, theta7, \u001b[0m  │\n",
       "│                       │ \u001b[38;2;72;201;176mtheta8, theta9...\u001b[0m                                                 │\n",
       "╰───────────────────────┴───────────────────────────────────────────────────────────────────╯\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 初始线路共3层,作用在127个量子比特上\n",
    "n_qubits = 127\n",
    "depth = 3\n",
    "circ1 = build_ansatz(n_qubits, depth)\n",
    "circ1.summary()    # 总结初始线路"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来对初始量子线路进行编译。\n",
    "\n",
    "假设编译前的量子门集为:[H](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.HGate.html)、[CNOT](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.CNOTGate.html)、[RZ](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RZ.html)、[RX](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RX.html);编译后的量子门集为:[H](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.HGate.html)、[CNOT](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.CNOTGate.html)、[RZ](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RZ.html)。编译规则是[H](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.HGate.html)、[CNOT](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.CNOTGate.html)、[RZ](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RZ.html)门保持不变,将[RX](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RX.html)门编译成[H](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.HGate.html)、[RZ](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RZ.html)、[H](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.HGate.html)的组合。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compile_circuit(circ):\n",
    "    circ_compiled = Circuit()\n",
    "\n",
    "    for gate in circ:    # 遍历初始线路中的量子门\n",
    "        # H,CNOT,RZ门保持不变\n",
    "        if gate.name == 'H' or gate.name == 'CNOT' or gate.name == 'RZ':\n",
    "            circ_compiled += gate\n",
    "        elif gate.name == 'RX':    # RX门经过编译变成H*RZ*H\n",
    "            circ_compiled += H.on(gate.obj_qubits)\n",
    "            circ_compiled += RZ(gate.coeff).on(gate.obj_qubits)\n",
    "            circ_compiled += H.on(gate.obj_qubits)\n",
    "\n",
    "    return circ_compiled"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"716.8\" height=\"200.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"716.8\" height=\"200.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><text x=\"20.0\" y=\"100.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q1: </text><text x=\"20.0\" y=\"160.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q2: </text><line x1=\"48.8\" x2=\"696.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"696.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"696.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"92.8\" y=\"40.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"132.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"172.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"172.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta0 </text><rect x=\"232.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"252.8\" y=\"40.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"72.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"92.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"132.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"172.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"172.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta1 </text><rect x=\"232.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"252.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"72.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"92.8\" y=\"160.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"132.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"172.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"172.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta2 </text><rect x=\"232.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"252.8\" y=\"160.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><circle cx=\"312.8\" cy=\"160.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"40.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"292.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"298.8\" x2=\"326.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"372.8\" cy=\"40.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"372.8\" x2=\"372.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"352.8\" y=\"80.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"358.8\" x2=\"386.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"372.8\" x2=\"372.8\" y1=\"86.0\" y2=\"114.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"432.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"432.8\" x2=\"432.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"412.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"418.8\" x2=\"446.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"432.8\" x2=\"432.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"412.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"432.8\" y=\"40.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"472.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"512.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"512.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta3 </text><rect x=\"572.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"592.8\" y=\"40.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"472.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"492.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"532.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"572.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"572.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta4 </text><rect x=\"632.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"652.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"472.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"492.8\" y=\"160.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"532.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"572.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"572.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta5 </text><rect x=\"632.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"652.8\" y=\"160.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x7f09d84f23d0>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 一层ansatz线路编译后生成的线路示例,可以看到,所有RX门都根据编译规则发生了变化\n",
    "compile_circuit(build_ansatz(3, 1)).svg()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ff0000; text-decoration-color: #ff0000; font-weight: bold\">                                       Circuit Summary                                       </span>\n",
       "╭───────────────────────┬───────────────────────────────────────────────────────────────────╮\n",
       "│<span style=\"font-weight: bold\"> </span><span style=\"color: #3b3b95; text-decoration-color: #3b3b95; font-weight: bold\">Info</span><span style=\"font-weight: bold\">                  </span>│<span style=\"font-weight: bold\"> </span><span style=\"color: #3b3b95; text-decoration-color: #3b3b95; font-weight: bold\">value</span><span style=\"font-weight: bold\">                                                             </span>│\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Number of qubit</span>       │ 127                                                               │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Total number of gate</span>  │ 1905                                                              │\n",
       "│ Barrier               │ 0                                                                 │\n",
       "│ Noise Channel         │ 0                                                                 │\n",
       "│ Measurement           │ 0                                                                 │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Parameter gate</span>        │ 508                                                               │\n",
       "│ 508 ansatz parameters │ <span style=\"color: #48c9b0; text-decoration-color: #48c9b0\">theta0, theta1, theta2, theta3, theta4, theta5, theta6, theta7, </span>  │\n",
       "│                       │ <span style=\"color: #48c9b0; text-decoration-color: #48c9b0\">theta8, theta9...</span>                                                 │\n",
       "╰───────────────────────┴───────────────────────────────────────────────────────────────────╯\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1;38;2;255;0;0m                                       Circuit Summary                                       \u001b[0m\n",
       "╭───────────────────────┬───────────────────────────────────────────────────────────────────╮\n",
       "│\u001b[1m \u001b[0m\u001b[1;38;2;59;59;149mInfo\u001b[0m\u001b[1m                 \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1;38;2;59;59;149mvalue\u001b[0m\u001b[1m                                                            \u001b[0m\u001b[1m \u001b[0m│\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mNumber of qubit\u001b[0m       │ 127                                                               │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mTotal number of gate\u001b[0m  │ 1905                                                              │\n",
       "│ Barrier               │ 0                                                                 │\n",
       "│ Noise Channel         │ 0                                                                 │\n",
       "│ Measurement           │ 0                                                                 │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mParameter gate\u001b[0m        │ 508                                                               │\n",
       "│ 508 ansatz parameters │ \u001b[38;2;72;201;176mtheta0, theta1, theta2, theta3, theta4, theta5, theta6, theta7, \u001b[0m  │\n",
       "│                       │ \u001b[38;2;72;201;176mtheta8, theta9...\u001b[0m                                                 │\n",
       "╰───────────────────────┴───────────────────────────────────────────────────────────────────╯\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 编译初始线路\n",
    "circ2 = compile_circuit(circ1)\n",
    "circ2.summary()    # 总结编译线路"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "最后构造完整的量子线路。\n",
    "\n",
    "根据量子线路的可逆性可知,若两个线路功能等价,那么将一个线路作用到量子比特上,再将另一个线路的逆线路作用到量子比特上,最终得到的量子态与两次作用之前的量子态等价。于是,完整的量子线路由编译后的线路和初始线路的逆线路组成。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ff0000; text-decoration-color: #ff0000; font-weight: bold\">                                       Circuit Summary                                       </span>\n",
       "╭───────────────────────┬───────────────────────────────────────────────────────────────────╮\n",
       "│<span style=\"font-weight: bold\"> </span><span style=\"color: #3b3b95; text-decoration-color: #3b3b95; font-weight: bold\">Info</span><span style=\"font-weight: bold\">                  </span>│<span style=\"font-weight: bold\"> </span><span style=\"color: #3b3b95; text-decoration-color: #3b3b95; font-weight: bold\">value</span><span style=\"font-weight: bold\">                                                             </span>│\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Number of qubit</span>       │ 127                                                               │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Total number of gate</span>  │ 2794                                                              │\n",
       "│ Barrier               │ 0                                                                 │\n",
       "│ Noise Channel         │ 0                                                                 │\n",
       "│ Measurement           │ 0                                                                 │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ <span style=\"font-weight: bold\">Parameter gate</span>        │ 1016                                                              │\n",
       "│ 508 ansatz parameters │ <span style=\"color: #48c9b0; text-decoration-color: #48c9b0\">theta507, theta506, theta505, theta504, theta503, theta502, </span>      │\n",
       "│                       │ <span style=\"color: #48c9b0; text-decoration-color: #48c9b0\">theta501, theta500, theta499, theta498...</span>                         │\n",
       "╰───────────────────────┴───────────────────────────────────────────────────────────────────╯\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1;38;2;255;0;0m                                       Circuit Summary                                       \u001b[0m\n",
       "╭───────────────────────┬───────────────────────────────────────────────────────────────────╮\n",
       "│\u001b[1m \u001b[0m\u001b[1;38;2;59;59;149mInfo\u001b[0m\u001b[1m                 \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1;38;2;59;59;149mvalue\u001b[0m\u001b[1m                                                            \u001b[0m\u001b[1m \u001b[0m│\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mNumber of qubit\u001b[0m       │ 127                                                               │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mTotal number of gate\u001b[0m  │ 2794                                                              │\n",
       "│ Barrier               │ 0                                                                 │\n",
       "│ Noise Channel         │ 0                                                                 │\n",
       "│ Measurement           │ 0                                                                 │\n",
       "├───────────────────────┼───────────────────────────────────────────────────────────────────┤\n",
       "│ \u001b[1mParameter gate\u001b[0m        │ 1016                                                              │\n",
       "│ 508 ansatz parameters │ \u001b[38;2;72;201;176mtheta507, theta506, theta505, theta504, theta503, theta502, \u001b[0m      │\n",
       "│                       │ \u001b[38;2;72;201;176mtheta501, theta500, theta499, theta498...\u001b[0m                         │\n",
       "╰───────────────────────┴───────────────────────────────────────────────────────────────────╯\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 完整线路\n",
    "circ1_inv = dagger(circ1)    # dagger()将量子线路左右逆转,得到初始线路的逆线路\n",
    "circ_all = circ1_inv + circ2    # 完整线路=初始线路的逆线路+编译后的线路\n",
    "circ_all.summary()    # 总结完整线路"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第二步\n",
    "\n",
    "将完整的量子线路转换成ZX图。\n",
    "\n",
    "含参量子线路等价性检查方法基于ZX演算实现,需要将量子线路转换成ZX图。\n",
    "\n",
    "量子门是ZX图中的顶点,分为3种颜色,[H](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.HGate.html)门表示成黄色顶点,[RX](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RX.html)门表示成含参的红色顶点,[RZ](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.RZ.html)门表示成含参的绿色顶点,[CNOT](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.CNOTGate.html)门的受控位表示成红色顶点,控制位表示成绿色顶点,受控位与控制位的顶点互为邻居。同一个量子比特上相邻两个量子门的顶点互为邻居。\n",
    "\n",
    "先定义顶点类和图类。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 顶点类\n",
    "class Vertex:\n",
    "    def __init__(self, name, color, qubit, neighbor, phase=0.0):\n",
    "        self.name = name    # 量子门顶点的序号\n",
    "        self.color = color    # 量子门顶点的颜色\n",
    "        self.phase = phase   # 含参量子门的参数\n",
    "        self.qubit = qubit     # 作用在哪个量子比特上\n",
    "        self.neighbor = neighbor    # 顶点之间的邻居关系"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 图类\n",
    "class Graph:\n",
    "    def __init__(self):\n",
    "        self.vertices = {}    # 初始图,空\n",
    "        self.count = 0    # 顶点总数,只增不减,也用于给新顶点命名\n",
    "\n",
    "    # 新增边\n",
    "    def add_edge(self, from_vertex, to_vertex):    # 添加一条从起点到终点的边\n",
    "        self.vertices[from_vertex].neighbor.append(to_vertex)\n",
    "\n",
    "    # 新增顶点\n",
    "    def add_vertex(self, color, qubit, neighbor, phase=0.0):\n",
    "        name = self.count\n",
    "        self.count += 1\n",
    "        # 添加从新顶点到相邻顶点的边\n",
    "        self.vertices[name] = Vertex(name, color, qubit, neighbor, phase)\n",
    "        for v in neighbor:    # 再添加从相邻顶点到新顶点的边\n",
    "            self.add_edge(v, name)\n",
    "\n",
    "    # 打印图信息\n",
    "    def print(self):\n",
    "        print(\"==================graph message==================\")\n",
    "        for v in self.vertices.values():\n",
    "            print(v.name, '\\t', v.neighbor, '\\t', v.color, '\\t', v.phase)\n",
    "        print('\\n')\n",
    "\n",
    "    # 删除自身的环\n",
    "    # 省略了ZX图的无环规则(本文中,所有“无环”均指不存在单条边构成的环)\n",
    "    def clear(self):\n",
    "        for v in self.vertices.values():\n",
    "            while v.name in v.neighbor:\n",
    "                # 将本顶点从自己的邻居中删除\n",
    "                self.vertices[v.name].neighbor.remove(v.name)\n",
    "\n",
    "    # 删除顶点\n",
    "    def delete_vertex(self, name):\n",
    "        for v in self.vertices.values():\n",
    "            while name in v.neighbor:    # 删除终点是该顶点的边\n",
    "                self.vertices[v.name].neighbor.remove(name)\n",
    "        self.vertices.pop(name)    # 删除起点是该顶点的边\n",
    "\n",
    "    # 两个电路是否等价\n",
    "    def equiv(self):\n",
    "        if not self.vertices:    # 等价的两个电路,经过ZX演算化简后,图中无顶点\n",
    "            print(\"Equivalent!\")\n",
    "        else:\n",
    "            print(\"Not sure!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来将量子线路绘制成ZX图。\n",
    "\n",
    "遍历线路中的所有量子门,并依次将其绘制成ZX图中的顶点。若当前量子比特上暂无量子门,则当前的量子门暂无邻居;若当前量子比特上已有量子门,则当前的量子门与该量子比特上最后一个量子门互为邻居;[CNOT](https://www.mindspore.cn/mindquantum/docs/zh-CN/r0.10/core/gates/mindquantum.core.gates.CNOTGate.html)门在绘制时就添加了控制位与受控位顶点之间的邻居关系。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def draw_graph(circ):\n",
    "    g = Graph()    # 初始化一个空图\n",
    "    last_name = [-1] * circ.n_qubits    # last_name保存每个量子比特上当前的最后一个顶点\n",
    "    for gate in circ:    # 遍历线路中的所有量子门\n",
    "        if gate.name == 'H':    # H门绘制成黄色顶点\n",
    "            if last_name[gate.obj_qubits[0]] != -1:    # 当前量子比特上已有顶点\n",
    "                g.add_vertex('yellow', gate.obj_qubits[0],\n",
    "                             [last_name[gate.obj_qubits[0]]])\n",
    "            else:    # 当前量子比特上暂无顶点\n",
    "                g.add_vertex('yellow', gate.obj_qubits[0], [])\n",
    "            last_name[gate.obj_qubits[0]] = g.count-1    # 更新当前量子比特上最后一个顶点为新增顶点\n",
    "        if gate.name == 'RX':    # RX门绘制成红色顶点\n",
    "            if last_name[gate.obj_qubits[0]] != -1:\n",
    "                g.add_vertex('red', gate.obj_qubits[0],\n",
    "                             [last_name[gate.obj_qubits[0]]], gate.coeff)\n",
    "            else:\n",
    "                g.add_vertex('red', gate.obj_qubits[0], [], gate.coeff)\n",
    "            last_name[gate.obj_qubits[0]] = g.count-1\n",
    "        if gate.name == 'RZ':    # RZ门绘制成绿色顶点\n",
    "            if last_name[gate.obj_qubits[0]] != -1:\n",
    "                g.add_vertex('green', gate.obj_qubits[0],\n",
    "                             [last_name[gate.obj_qubits[0]]], gate.coeff)\n",
    "            else:\n",
    "                g.add_vertex('green', gate.obj_qubits[0], [], gate.coeff)\n",
    "            last_name[gate.obj_qubits[0]] = g.count-1\n",
    "        if gate.name == 'CNOT':    # CNOT门要分别绘制控制位顶点和受控位顶点\n",
    "            # 绘制控制位顶点,绿色\n",
    "            if last_name[gate.obj_qubits[1]] != -1:\n",
    "                g.add_vertex('green', gate.obj_qubits[1],\n",
    "                             [last_name[gate.obj_qubits[1]]])\n",
    "            else:\n",
    "                g.add_vertex('green', gate.obj_qubits[1], [])\n",
    "            last_name[gate.obj_qubits[1]] = g.count-1\n",
    "            # 绘制受控位顶点,红色\n",
    "            if last_name[gate.obj_qubits[0]] != -1:\n",
    "                g.add_vertex('red', gate.obj_qubits[0],\n",
    "                             [last_name[gate.obj_qubits[0]], g.count-1])\n",
    "            else:\n",
    "                g.add_vertex('red', gate.obj_qubits[0], [g.count-1])\n",
    "            last_name[gate.obj_qubits[0]] = g.count-1\n",
    "    return g"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "最后,将第一步构造好的完整量子线路绘制成ZX图。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "g = draw_graph(circ_all)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第三步\n",
    "\n",
    "化简ZX图。\n",
    "\n",
    "ZX演算由ZX图和化简规则组成,根据化简规则,对ZX图中的顶点和邻居关系进行化简。\n",
    "\n",
    "以下列出部分规则,具体实现过程即图和顶点的相关操作,只举例说明,不再一一赘述。\n",
    "\n",
    "规则1:不与其他量子比特上的顶点相邻的、参数为0的红色或绿色顶点可以删除。\n",
    "\n",
    "![equivalence checking of PQC rule 1](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.5.0/docs/mindquantum/docs/source_zh_cn/images/equivalence_checking_of_PQC_rule_1.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def rule_1(g: Graph):\n",
    "    for v1 in list(g.vertices.keys()):    # ZX演算过程中,图中的顶点会发生增减,用list()获取最初的所有顶点\n",
    "        if v1 not in g.vertices.keys():    # 判断当前顶点在化简过程中有没有被删除\n",
    "            continue    # 已被删除,略过\n",
    "        v1 = g.vertices[v1]\n",
    "        # 顶点参数为0\n",
    "        if v1.phase == 0 or list(v1.phase.values()) == [0.0]*len(list(v1.phase.values())):\n",
    "            flag = True    # 用于判断当前顶点是否与其他量子比特上的顶点相关,如果相关,暂时不能删除\n",
    "            for v2 in v1.neighbor:\n",
    "                v2 = g.vertices[v2]\n",
    "                if v2.qubit != v1.qubit:    # 与其他量子比特上的顶点相关\n",
    "                    flag = False\n",
    "                    break\n",
    "            if flag:    # 与其他量子比特上的顶点无关\n",
    "                for v2 in v1.neighbor:\n",
    "                    v2 = g.vertices[v2]\n",
    "                    v2.neighbor.extend(v1.neighbor)    # 将前一个顶点与后一个顶点相连,略过当前顶点\n",
    "                    g.clear()    # 清除化简过程中可能产生的环\n",
    "                g.delete_vertex(v1.name)    # 删除该顶点"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "规则2:相邻的、相同颜色的红色或绿色顶点可以合并。\n",
    "\n",
    "![equivalence checking of PQC rule 2](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.5.0/docs/mindquantum/docs/source_zh_cn/images/equivalence_checking_of_PQC_rule_2.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def rule_2(g: Graph):\n",
    "    for v1 in list(g.vertices.keys()):\n",
    "        if v1 not in g.vertices.keys():\n",
    "            continue\n",
    "        v1 = g.vertices[v1]\n",
    "        if v1.color == 'red' or v1.color == 'green':    # 红色或绿色顶点\n",
    "            for v2 in v1.neighbor:    # 相邻\n",
    "                v2 = g.vertices[v2]\n",
    "                if v2.color == v1.color:    # 相同颜色\n",
    "                    v2.phase = v2.phase + v1.phase    # 参数相加\n",
    "                    v2.neighbor.extend(v1.neighbor)    # 合并两个顶点\n",
    "                    g.clear()\n",
    "                    for v3 in v1.neighbor:    # 更新合并顶点后的邻居关系\n",
    "                        v3 = g.vertices[v3]\n",
    "                        v3.neighbor.append(v2.name)\n",
    "                        g.clear()\n",
    "                    g.delete_vertex(v1.name)    # 删除已被合并的顶点"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "规则3:所有邻居都是黄色顶点的绿色顶点,可以变成红色顶点,并删除相邻的黄色顶点。\n",
    "\n",
    "![equivalence checking of PQC rule 3](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.5.0/docs/mindquantum/docs/source_zh_cn/images/equivalence_checking_of_PQC_rule_3.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def rule_3(g: Graph):\n",
    "    for v1 in list(g.vertices.keys()):\n",
    "        if v1 not in g.vertices.keys():\n",
    "            continue\n",
    "        v1 = g.vertices[v1]\n",
    "        if v1.color == 'green':\n",
    "            flag = True    # 用于判断是否所有邻居都是黄色\n",
    "            for v2 in v1.neighbor:\n",
    "                v2 = g.vertices[v2]\n",
    "                if v2.color != 'yellow':    # 不满足所有邻居都是黄色\n",
    "                    flag = False\n",
    "                    break\n",
    "            if flag:    # 所有邻居都是黄色\n",
    "                v1.color = 'red'    # 变成红色\n",
    "                v1_neighbor = list(v1.neighbor)\n",
    "                for v2 in v1_neighbor:    # 删除这些黄色顶点\n",
    "                    v2 = g.vertices[v2]\n",
    "                    v1.neighbor.extend(v2.neighbor)\n",
    "                    g.clear()\n",
    "                    for v3 in v2.neighbor:\n",
    "                        v3 = g.vertices[v3]\n",
    "                        v3.neighbor.append(v1.name)\n",
    "                        g.clear()\n",
    "                    g.delete_vertex(v2.name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "规则 4:相邻的、存在两条边的红绿顶点,可以删除这两条边。\n",
    "\n",
    "![equivalence checking of PQC rule 4](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.5.0/docs/mindquantum/docs/source_zh_cn/images/equivalence_checking_of_PQC_rule_4.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def rule_4(g: Graph):\n",
    "    for v1 in list(g.vertices.keys()):\n",
    "        if v1 not in g.vertices.keys():\n",
    "            continue\n",
    "        v1 = g.vertices[v1]\n",
    "        if v1.color == 'green':\n",
    "            for v2 in v1.neighbor:\n",
    "                v2 = g.vertices[v2]\n",
    "                # 红绿顶点,且两顶点间有两条边\n",
    "                if v2.color == 'red' and v2.neighbor.count(v1.name) == 2:\n",
    "                    while v2.name in g.vertices[v1.name].neighbor:    # 删除相连的边\n",
    "                        v1.neighbor.remove(v2.name)\n",
    "                    while v1.name in g.vertices[v2.name].neighbor:\n",
    "                        v2.neighbor.remove(v1.name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来利用以上规则对ZX图进行循环化简,若某轮循环中没有删除任何顶点,则认为化简结束。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def simplify(g: Graph):\n",
    "    temp = []    # 用于对比本轮循环是否有顶点被删除\n",
    "    while temp != list(g.vertices.keys()):    # 如果本轮循环没有删除任何顶点,则认为化简结束,退出循环\n",
    "        temp = list(g.vertices.keys())\n",
    "        rule_3(g)\n",
    "        rule_2(g)\n",
    "        rule_4(g)\n",
    "        rule_1(g)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "完整线路规模较大,可以先构造一个作用在三个量子比特上的单层线路进行测试。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1096.8\" height=\"200.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"1096.8\" height=\"200.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><text x=\"20.0\" y=\"100.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q1: </text><text x=\"20.0\" y=\"160.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q2: </text><line x1=\"48.8\" x2=\"1076.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"1076.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"1076.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta5 </text><rect x=\"72.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta4 </text><rect x=\"72.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta3 </text><circle cx=\"192.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"172.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"178.8\" x2=\"206.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"252.8\" cy=\"40.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"252.8\" x2=\"252.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"232.8\" y=\"80.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"238.8\" x2=\"266.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"252.8\" x2=\"252.8\" y1=\"86.0\" y2=\"114.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"312.8\" cy=\"160.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"40.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"292.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"298.8\" x2=\"326.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"352.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"392.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"392.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta2 </text><rect x=\"352.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"392.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"392.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta1 </text><rect x=\"352.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"392.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"392.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta0 </text><rect x=\"452.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"472.8\" y=\"40.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"512.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"552.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"552.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta0 </text><rect x=\"612.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"632.8\" y=\"40.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"452.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"472.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"512.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"552.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"552.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta1 </text><rect x=\"612.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"632.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"452.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"472.8\" y=\"160.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"512.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"552.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"552.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta2 </text><rect x=\"612.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"632.8\" y=\"160.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><circle cx=\"692.8\" cy=\"160.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"692.8\" x2=\"692.8\" y1=\"40.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"672.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"678.8\" x2=\"706.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"692.8\" x2=\"692.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"752.8\" cy=\"40.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"752.8\" x2=\"752.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"732.8\" y=\"80.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"738.8\" x2=\"766.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"752.8\" x2=\"752.8\" y1=\"86.0\" y2=\"114.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"812.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"812.8\" x2=\"812.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"792.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"798.8\" x2=\"826.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"812.8\" x2=\"812.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"792.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"812.8\" y=\"40.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"852.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"892.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"892.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta3 </text><rect x=\"952.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"972.8\" y=\"40.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"852.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"872.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"912.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"952.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"952.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta4 </text><rect x=\"1012.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"1032.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"852.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"872.8\" y=\"160.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"912.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"952.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"952.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta5 </text><rect x=\"1012.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"1032.8\" y=\"160.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x7f097cccdaf0>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_circ1 = build_ansatz(3, 1)\n",
    "test_circ1_inv = dagger(test_circ1)\n",
    "test_circ2 = compile_circuit(test_circ1)\n",
    "\n",
    "test_circ_all = test_circ1_inv + test_circ2\n",
    "\n",
    "test_circ_all.svg()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================graph message==================\n",
      "0 \t [4] \t red \t -theta5\n",
      "1 \t [3] \t red \t -theta4\n",
      "2 \t [5] \t red \t -theta3\n",
      "3 \t [1, 4, 6] \t green \t 0.0\n",
      "4 \t [0, 3, 7] \t red \t 0.0\n",
      "5 \t [2, 6, 8] \t green \t 0.0\n",
      "6 \t [3, 5, 10] \t red \t 0.0\n",
      "7 \t [4, 8, 9] \t green \t 0.0\n",
      "8 \t [5, 7, 11] \t red \t 0.0\n",
      "9 \t [7, 18] \t red \t -theta2\n",
      "10 \t [6, 15] \t red \t -theta1\n",
      "11 \t [8, 12] \t red \t -theta0\n",
      "12 \t [11, 13] \t yellow \t 0.0\n",
      "13 \t [12, 14] \t green \t theta0\n",
      "14 \t [13, 22] \t yellow \t 0.0\n",
      "15 \t [10, 16] \t yellow \t 0.0\n",
      "16 \t [15, 17] \t green \t theta1\n",
      "17 \t [16, 24] \t yellow \t 0.0\n",
      "18 \t [9, 19] \t yellow \t 0.0\n",
      "19 \t [18, 20] \t green \t theta2\n",
      "20 \t [19, 21] \t yellow \t 0.0\n",
      "21 \t [20, 22, 26] \t green \t 0.0\n",
      "22 \t [14, 21, 23] \t red \t 0.0\n",
      "23 \t [22, 24, 27] \t green \t 0.0\n",
      "24 \t [17, 23, 25] \t red \t 0.0\n",
      "25 \t [24, 26, 30] \t green \t 0.0\n",
      "26 \t [21, 25, 33] \t red \t 0.0\n",
      "27 \t [23, 28] \t yellow \t 0.0\n",
      "28 \t [27, 29] \t green \t theta3\n",
      "29 \t [28] \t yellow \t 0.0\n",
      "30 \t [25, 31] \t yellow \t 0.0\n",
      "31 \t [30, 32] \t green \t theta4\n",
      "32 \t [31] \t yellow \t 0.0\n",
      "33 \t [26, 34] \t yellow \t 0.0\n",
      "34 \t [33, 35] \t green \t theta5\n",
      "35 \t [34] \t yellow \t 0.0\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 将测试线路绘制成ZX图\n",
    "test_g = draw_graph(test_circ_all)\n",
    "test_g.print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "化简之前:\n",
      "Not sure!\n",
      "化简之后:\n",
      "Equivalent!\n"
     ]
    }
   ],
   "source": [
    "# 化简测试线路\n",
    "print(\"化简之前:\")\n",
    "test_g.equiv()\n",
    "\n",
    "simplify(test_g)\n",
    "\n",
    "print(\"化简之后:\")\n",
    "test_g.equiv()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "化简功能测试通过,最后就可以化简完整线路的ZX图,化简结果显示编译前后的两个线路是等价的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "化简之前:\n",
      "Not sure!\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "化简之后:\n",
      "Equivalent!\n"
     ]
    }
   ],
   "source": [
    "# 化简完整线路\n",
    "print(\"化简之前:\")\n",
    "g.equiv()\n",
    "\n",
    "simplify(g)    # 化简\n",
    "\n",
    "print(\"化简之后:\")\n",
    "g.equiv()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第四\n",
    "\n",
    "若ZX演算无法确定则实例化参数。\n",
    "\n",
    "对于两个不等价的线路,ZX演算不能直接给出不等价的判定结果。这时,需要对线路中的参数进行实例化,判断实例化之后的两个线路是否等价。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"376.8\" height=\"200.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"376.8\" height=\"200.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><text x=\"20.0\" y=\"100.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q1: </text><text x=\"20.0\" y=\"160.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q2: </text><line x1=\"48.8\" x2=\"356.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"356.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"356.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"92.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"72.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta0 </text><circle cx=\"152.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"152.8\" x2=\"152.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"132.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"138.8\" x2=\"166.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"152.8\" x2=\"152.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"192.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"232.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"232.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta1 </text><circle cx=\"212.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"212.8\" x2=\"212.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"192.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"198.8\" x2=\"226.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"212.8\" x2=\"212.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"312.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"292.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"298.8\" x2=\"326.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"252.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"292.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"292.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta2 </text></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x7f09db55a370>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 构造反例线路:ZX演算化简后无法确定、实际上不等价的两个线路\n",
    "neq_circ1 = Circuit()\n",
    "neq_circ1 += H.on(1)\n",
    "neq_circ1 += RX(f'theta{0}').on(2)\n",
    "neq_circ1 += CNOT.on(0, 1)\n",
    "neq_circ1 += RZ(f'theta{1}').on(0)\n",
    "neq_circ1 += CNOT.on(2, 1)\n",
    "neq_circ1 += CNOT.on(0, 1)\n",
    "neq_circ1 += RX(f'theta{2}').on(2)\n",
    "\n",
    "neq_circ1.svg()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"536.8\" height=\"200.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"536.8\" height=\"200.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><text x=\"20.0\" y=\"100.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q1: </text><text x=\"20.0\" y=\"160.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q2: </text><line x1=\"48.8\" x2=\"516.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"516.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"516.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"92.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"72.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta0 </text><circle cx=\"152.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"152.8\" x2=\"152.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"132.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"138.8\" x2=\"166.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"152.8\" x2=\"152.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"192.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"232.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"232.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta1 </text><circle cx=\"212.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"212.8\" x2=\"212.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"192.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"198.8\" x2=\"226.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"212.8\" x2=\"212.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"312.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"292.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"298.8\" x2=\"326.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"312.8\" x2=\"312.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"252.8\" y=\"140.0\" width=\"240.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"372.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"372.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta0 + theta1 + theta2 </text></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x7f097cde4880>"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "neq_circ2 = Circuit()\n",
    "neq_circ2 += H.on(1)\n",
    "neq_circ2 += RX(f'theta{0}').on(2)\n",
    "neq_circ2 += CNOT.on(0, 1)\n",
    "neq_circ2 += RZ(f'theta{1}').on(0)\n",
    "neq_circ2 += CNOT.on(2, 1)\n",
    "neq_circ2 += CNOT.on(0, 1)\n",
    "neq_circ2 += RX({f'theta{0}': 1, f'theta{1}': 1, f'theta{2}': 1}).on(2)\n",
    "\n",
    "neq_circ2.svg()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"816.8\" height=\"200.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"816.8\" height=\"200.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><text x=\"20.0\" y=\"100.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q1: </text><text x=\"20.0\" y=\"160.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q2: </text><line x1=\"48.8\" x2=\"796.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"796.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"796.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"112.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta2 </text><circle cx=\"92.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"92.8\" x2=\"92.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"72.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"78.8\" x2=\"106.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"92.8\" x2=\"92.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"192.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"172.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"178.8\" x2=\"206.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"132.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"172.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"172.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta1 </text><circle cx=\"252.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"252.8\" x2=\"252.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"232.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"238.8\" x2=\"266.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"252.8\" x2=\"252.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"232.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"272.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"272.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >-theta0 </text><rect x=\"292.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"312.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"352.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#5e7ce0\" fill-opacity=\"1\" /><text x=\"372.8\" y=\"100.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >H </text><rect x=\"332.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"372.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"372.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta0 </text><circle cx=\"432.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"432.8\" x2=\"432.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"412.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"418.8\" x2=\"446.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"432.8\" x2=\"432.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"472.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"512.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RZ </text><text x=\"512.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta1 </text><circle cx=\"492.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"492.8\" x2=\"492.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"472.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"478.8\" x2=\"506.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"492.8\" x2=\"492.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"592.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"592.8\" x2=\"592.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"572.8\" y=\"20.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"578.8\" x2=\"606.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"592.8\" x2=\"592.8\" y1=\"26.0\" y2=\"54.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"532.8\" y=\"140.0\" width=\"240.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"652.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"652.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >theta0 + theta1 + theta2 </text></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x7f097cdec6d0>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "neq_circ1_inv = dagger(neq_circ1)\n",
    "neq_circ_all = neq_circ1_inv + neq_circ2    # 构造完整反例线路\n",
    "neq_circ_all.svg()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "化简之前:\n",
      "Not sure!\n",
      "化简之后:\n",
      "Not sure!\n"
     ]
    }
   ],
   "source": [
    "# 将反例线路绘制成ZX图并进行化简\n",
    "neq_g = draw_graph(neq_circ_all)\n",
    "print(\"化简之前:\")\n",
    "neq_g.equiv()\n",
    "\n",
    "simplify(neq_g)\n",
    "\n",
    "print(\"化简之后:\")\n",
    "neq_g.equiv()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于反例线路,ZX演算化简之后,ZX图中仍有未删掉的顶点,于是ZX演算无法确定其等价性,需要实例化参数进行验证。\n",
    "\n",
    "实例化参数步骤分为两步:\n",
    "\n",
    "第一步,根据映射函数实例化参数,直接比较实例化之后两个线路的矩阵形式是否等价,若不等价则停止;\n",
    "\n",
    "第二步,若映射函数实例化未得到不等价的结果,则随机实例化参数,再直接比较实例化之后两个线路的矩阵形式是否等价,若不等价则最终判定两个线路不等价,否则,最终判定两个线路等价。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 映射函数实例化参数\n",
    "def map_para(n, r):\n",
    "    para = {}\n",
    "    for i in range(n):\n",
    "        para[f'theta{i}'] = (2*np.pi/((i+1)*r)-np.pi)\n",
    "    return para\n",
    "\n",
    "\n",
    "# 随机实例化参数\n",
    "def random_para(n):\n",
    "    para = {}\n",
    "    for i in range(n):\n",
    "        para[f'theta{i}'] = (np.random.uniform(np.pi, -np.pi))\n",
    "    return para"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 实例化参数验证两个线路是否等价,验证r轮\n",
    "def verify_by_para(circ1, circ2, r):\n",
    "    n = len(list(set(circ1.params_name+circ2.params_name)))    # 线路中一共n个参数\n",
    "    flag = True    # 记录前r-1轮验证是否有结果\n",
    "    for i in range(r-1):    # 前r-1轮指定参数\n",
    "        para = map_para(n, i+1)\n",
    "\n",
    "        # 直接比较两个实例化之后的线路的矩阵形式是否等价\n",
    "        if np.array_equal(circ1.matrix(para), circ2.matrix(para)):\n",
    "            continue\n",
    "        else:\n",
    "            print('Not equivalent!')    # 在任一情况下两个线路的矩阵不等价,即表示这两个线路不等价\n",
    "            flag = False    # 验证已有结果,结束\n",
    "            break\n",
    "\n",
    "    if flag:    # 前r-1轮没有结果,最后一轮随机参数\n",
    "        para = random_para(n)\n",
    "        if np.array_equal(circ1.matrix(para), circ2.matrix(para)):\n",
    "            print('Equivalent!')\n",
    "        else:\n",
    "            print('Not equivalent!')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "用实例化参数的方法去验证两个反例线路的等价性,结果为不等价。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Not equivalent!\n"
     ]
    }
   ],
   "source": [
    "verify_by_para(neq_circ1, neq_circ2, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 最后:将以上过程合并成一个完整的功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def ZXcalculus(circ1, circ2):\n",
    "    circ1_inv = dagger(circ1)    # 将原始线路左右逆转\n",
    "    circ = circ1_inv + circ2    # 构造完整线路\n",
    "    g = draw_graph(circ)    # 将完整线路绘制成ZX图\n",
    "    print(\"化简之前:\")\n",
    "    g.equiv()\n",
    "    simplify(g)    # 根据ZX演算规则进行化简\n",
    "    print(\"化简之后:\")\n",
    "    if not g.vertices:    # 化简得到两个线路等价的结果\n",
    "        g.equiv()\n",
    "    else:    # 化简未能得到结果,需要实例化参数进行验证\n",
    "        g.equiv()\n",
    "        print(\"实例化参数验证:\")\n",
    "        verify_by_para(circ1, circ2, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<table border=\"1\">\n",
       "  <tr>\n",
       "    <th>Software</th>\n",
       "    <th>Version</th>\n",
       "  </tr>\n",
       "<tr><td>mindquantum</td><td>0.9.11</td></tr>\n",
       "<tr><td>scipy</td><td>1.9.3</td></tr>\n",
       "<tr><td>numpy</td><td>1.23.5</td></tr>\n",
       "<tr>\n",
       "    <th>System</th>\n",
       "    <th>Info</th>\n",
       "</tr>\n",
       "<tr><td>Python</td><td>3.8.17</td></tr><tr><td>OS</td><td>Linux x86_64</td></tr><tr><td>Memory</td><td>16.62 GB</td></tr><tr><td>CPU Max Thread</td><td>16</td></tr><tr><td>Date</td><td>Tue Jan  2 17:38:24 2024</td></tr>\n",
       "</table>\n"
      ],
      "text/plain": [
       "<mindquantum.utils.show_info.InfoTable at 0x7f097cce6430>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from mindquantum.utils.show_info import InfoTable\n",
    "\n",
    "InfoTable('mindquantum', 'scipy', 'numpy')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MindSpore",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}