From cbd338f848274a4fcda9542d4e2c49e905eca6d6 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 25 Feb 2024 11:00:23 +0100 Subject: [PATCH 01/41] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20checkout=20mqt-core?= =?UTF-8?q?=20to=20partial-equivalence-checking=20branch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 4 ++-- extern/mqt-core | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index b40a6f71..027eb41f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "extern/mqt-core"] path = extern/mqt-core - url = https://github.com/cda-tum/mqt-core.git - branch = main + url = https://github.com/reb-ddm/mqt-core.git + branch = partial-equivalence-checking diff --git a/extern/mqt-core b/extern/mqt-core index 0b35f3e1..c0f54319 160000 --- a/extern/mqt-core +++ b/extern/mqt-core @@ -1 +1 @@ -Subproject commit 0b35f3e1101e5a655b765bbd2b08e29009eb034a +Subproject commit c0f5431908cfdc97248807e0f3390ae46916dd67 From 3dfcf6c8fb1e66178bfed466c7cf1467c7ff5c87 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 25 Feb 2024 11:01:24 +0100 Subject: [PATCH 02/41] =?UTF-8?q?=E2=9C=85=20add=20circuits=20for=20testin?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../partialEquivalenceTest/Grover_1.qasm | 68 + .../partialEquivalenceTest/Grover_2.qasm | 70 + .../partialEquivalenceTest/add6_196_1.qasm | 245 ++ .../partialEquivalenceTest/add6_196_2.qasm | 270 ++ .../circuits/partialEquivalenceTest/bv_1.qasm | 33 + .../circuits/partialEquivalenceTest/bv_2.qasm | 66 + .../entanglement_1.qasm | 14 + .../entanglement_2.qasm | 46 + .../grover-noancilla_indep_qiskit_3.qasm | 18 + ...ancilla_nativegates_ibm_qiskit_opt0_3.qasm | 58 + ...ancilla_nativegates_ibm_qiskit_opt0_7.qasm | 3762 +++++++++++++++++ ...ancilla_nativegates_ibm_qiskit_opt1_7.qasm | 3600 ++++++++++++++++ .../period_finding_1.qasm | 398 ++ .../period_finding_2.qasm | 440 ++ .../partialEquivalenceTest/random_1.qasm | 154 + .../partialEquivalenceTest/random_2.qasm | 532 +++ 16 files changed, 9774 insertions(+) create mode 100644 test/circuits/partialEquivalenceTest/Grover_1.qasm create mode 100644 test/circuits/partialEquivalenceTest/Grover_2.qasm create mode 100644 test/circuits/partialEquivalenceTest/add6_196_1.qasm create mode 100644 test/circuits/partialEquivalenceTest/add6_196_2.qasm create mode 100644 test/circuits/partialEquivalenceTest/bv_1.qasm create mode 100644 test/circuits/partialEquivalenceTest/bv_2.qasm create mode 100644 test/circuits/partialEquivalenceTest/entanglement_1.qasm create mode 100644 test/circuits/partialEquivalenceTest/entanglement_2.qasm create mode 100644 test/circuits/partialEquivalenceTest/grover-noancilla_indep_qiskit_3.qasm create mode 100644 test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt0_3.qasm create mode 100644 test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt0_7.qasm create mode 100644 test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt1_7.qasm create mode 100644 test/circuits/partialEquivalenceTest/period_finding_1.qasm create mode 100644 test/circuits/partialEquivalenceTest/period_finding_2.qasm create mode 100644 test/circuits/partialEquivalenceTest/random_1.qasm create mode 100644 test/circuits/partialEquivalenceTest/random_2.qasm diff --git a/test/circuits/partialEquivalenceTest/Grover_1.qasm b/test/circuits/partialEquivalenceTest/Grover_1.qasm new file mode 100644 index 00000000..f7d74e5d --- /dev/null +++ b/test/circuits/partialEquivalenceTest/Grover_1.qasm @@ -0,0 +1,68 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[11]; +x q[10]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +h q[9]; +h q[10]; +mcx q[0], q[10]; +mcx q[0], q[1], q[10]; +mcx q[0], q[1], q[2], q[10]; +mcx q[0], q[1], q[2], q[3], q[10]; +mcx q[0], q[1], q[2], q[3], q[4], q[10]; +mcx q[0], q[1], q[2], q[3], q[4], q[5], q[10]; +mcx q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[10]; +mcx q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[10]; +mcx q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[10]; +mcx q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +h q[9]; +x q[0]; +x q[1]; +x q[2]; +x q[3]; +x q[4]; +x q[5]; +x q[6]; +x q[7]; +x q[8]; +x q[9]; +h q[9]; +mcx q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9]; +h q[9]; +x q[0]; +x q[1]; +x q[2]; +x q[3]; +x q[4]; +x q[5]; +x q[6]; +x q[7]; +x q[8]; +x q[9]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +h q[9]; diff --git a/test/circuits/partialEquivalenceTest/Grover_2.qasm b/test/circuits/partialEquivalenceTest/Grover_2.qasm new file mode 100644 index 00000000..10aef8f7 --- /dev/null +++ b/test/circuits/partialEquivalenceTest/Grover_2.qasm @@ -0,0 +1,70 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[12]; +x q[10]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +h q[9]; +h q[10]; +mcx q[0], q[10]; +mcx q[0], q[1], q[10]; +mcx q[0], q[1], q[2], q[10]; +mcx q[0], q[1], q[2], q[3], q[10]; +mcx q[0], q[1], q[2], q[3], q[4], q[11]; +mcx q[11], q[10]; +mcx q[5], q[11], q[10]; +mcx q[5], q[6], q[11], q[10]; +mcx q[5], q[6], q[7], q[11], q[10]; +mcx q[5], q[6], q[7], q[8], q[11], q[10]; +mcx q[5], q[6], q[7], q[8], q[9], q[11], q[10]; +mcx q[0], q[1], q[2], q[3], q[4], q[11]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +h q[9]; +x q[0]; +x q[1]; +x q[2]; +x q[3]; +x q[4]; +x q[5]; +x q[6]; +x q[7]; +x q[8]; +x q[9]; +h q[9]; +mcx q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9]; +h q[9]; +x q[0]; +x q[1]; +x q[2]; +x q[3]; +x q[4]; +x q[5]; +x q[6]; +x q[7]; +x q[8]; +x q[9]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +h q[9]; diff --git a/test/circuits/partialEquivalenceTest/add6_196_1.qasm b/test/circuits/partialEquivalenceTest/add6_196_1.qasm new file mode 100644 index 00000000..90983b6a --- /dev/null +++ b/test/circuits/partialEquivalenceTest/add6_196_1.qasm @@ -0,0 +1,245 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[19]; +creg c[19]; +h q[7]; +h q[8]; +h q[9]; +h q[10]; +h q[11]; +h q[12]; +h q[13]; +h q[14]; +h q[15]; +h q[16]; +h q[17]; +h q[18]; +mcx q[16],q[10],q[9],q[2]; +ccx q[16],q[10],q[4]; +ccx q[16],q[10],q[3]; +ccx q[17],q[11],q[5]; +ccx q[17],q[11],q[4]; +ccx q[17],q[11],q[3]; +ccx q[15],q[9],q[3]; +ccx q[15],q[9],q[2]; +ccx q[15],q[9],q[1]; +ccx q[15],q[9],q[0]; +mcx q[15],q[9],q[8],q[1]; +mcx q[15],q[9],q[8],q[0]; +mcx q[14],q[8],q[7],q[0]; +mcx q[16],q[15],q[10],q[2]; +mcx q[16],q[15],q[10],q[1]; +mcx q[16],q[15],q[14],q[10],q[1]; +mcx q[18],q[12],q[11],q[4]; +mcx q[18],q[12],q[11],q[3]; +mcx q[18],q[12],q[11],q[2]; +mcx q[18],q[12],q[11],q[1]; +mcx q[17],q[11],q[10],q[3]; +mcx q[14],q[13],q[8],q[0]; +ccx q[14],q[8],q[2]; +ccx q[14],q[8],q[1]; +ccx q[13],q[7],q[1]; +ccx q[13],q[7],q[0]; +x q[16]; +mcx q[17],q[16],q[15],q[11],q[8],q[1]; +mcx q[17],q[16],q[11],q[9],q[8],q[1]; +mcx q[17],q[16],q[11],q[3]; +mcx q[18],q[16],q[12],q[11],q[9],q[2]; +mcx q[18],q[16],q[12],q[11],q[9],q[1]; +mcx q[18],q[17],q[16],q[12],q[9],q[2]; +mcx q[18],q[17],q[16],q[12],q[9],q[1]; +x q[10]; +mcx q[18],q[15],q[14],q[12],q[11],q[10],q[7],q[0]; +mcx q[18],q[17],q[15],q[14],q[12],q[10],q[7],q[0]; +mcx q[17],q[11],q[10],q[9],q[8],q[1]; +mcx q[17],q[15],q[11],q[10],q[8],q[1]; +ccx q[16],q[10],q[4]; +x q[17]; +mcx q[18],q[17],q[12],q[4]; +mcx q[18],q[17],q[15],q[14],q[12],q[10],q[1]; +mcx q[18],q[17],q[15],q[12],q[10],q[8],q[7],q[0]; +mcx q[18],q[17],q[12],q[10],q[9],q[2]; +mcx q[18],q[17],q[12],q[10],q[9],q[1]; +mcx q[18],q[17],q[12],q[10],q[9],q[0]; +mcx q[18],q[17],q[12],q[10],q[9],q[8],q[1]; +mcx q[18],q[17],q[15],q[12],q[10],q[2]; +mcx q[18],q[17],q[15],q[12],q[10],q[1]; +mcx q[18],q[17],q[12],q[10],q[3]; +mcx q[18],q[17],q[14],q[13],q[12],q[10],q[9],q[0]; +x q[10]; +mcx q[18],q[17],q[16],q[12],q[3]; +mcx q[18],q[17],q[16],q[12],q[0]; +mcx q[18],q[17],q[16],q[15],q[12],q[2]; +mcx q[18],q[17],q[16],q[15],q[12],q[1]; +mcx q[18],q[17],q[16],q[15],q[12],q[0]; +x q[11]; +mcx q[18],q[12],q[11],q[10],q[3]; +mcx q[18],q[15],q[12],q[11],q[10],q[2]; +mcx q[18],q[15],q[12],q[11],q[10],q[1]; +x q[10]; +mcx q[18],q[12],q[11],q[10],q[9],q[2]; +mcx q[18],q[15],q[14],q[12],q[11],q[10],q[1]; +mcx q[18],q[14],q[12],q[11],q[10],q[9],q[7],q[0]; +mcx q[18],q[15],q[12],q[11],q[10],q[8],q[7],q[0]; +mcx q[18],q[15],q[13],q[12],q[11],q[10],q[8],q[0]; +mcx q[18],q[16],q[12],q[11],q[3]; +mcx q[18],q[16],q[12],q[11],q[2]; +mcx q[18],q[16],q[12],q[11],q[1]; +ccx q[17],q[11],q[5]; +x q[13]; +mcx q[15],q[14],q[13],q[9],q[0]; +mcx q[15],q[13],q[9],q[8],q[0]; +mcx q[18],q[17],q[13],q[12],q[10],q[9],q[8],q[0]; +x q[10]; +mcx q[18],q[13],q[12],q[11],q[10],q[9],q[8],q[0]; +mcx q[18],q[16],q[15],q[13],q[12],q[11],q[8],q[0]; +x q[16]; +mcx q[18],q[16],q[13],q[12],q[11],q[9],q[8],q[0]; +x q[14]; +mcx q[16],q[14],q[10],q[9],q[1]; +mcx q[15],q[14],q[9],q[1]; +x q[10]; +mcx q[18],q[17],q[15],q[14],q[13],q[12],q[10],q[0]; +mcx q[18],q[17],q[15],q[14],q[12],q[10],q[0]; +mcx q[18],q[17],q[14],q[12],q[10],q[9],q[7],q[0]; +mcx q[18],q[17],q[14],q[12],q[10],q[9],q[1]; +mcx q[18],q[14],q[12],q[11],q[10],q[9],q[1]; +x q[10]; +mcx q[16],q[14],q[13],q[10],q[9],q[0]; +mcx q[16],q[15],q[14],q[13],q[10],q[0]; +x q[16]; +mcx q[18],q[17],q[16],q[14],q[13],q[12],q[9],q[0]; +mcx q[18],q[17],q[16],q[15],q[14],q[13],q[12],q[0]; +x q[7]; +x q[10]; +mcx q[18],q[12],q[11],q[10],q[9],q[8],q[7],q[0]; +ccx q[13],q[7],q[1]; +x q[13]; +mcx q[15],q[14],q[9],q[7],q[0]; +x q[8]; +mcx q[18],q[16],q[15],q[12],q[11],q[8],q[1]; +mcx q[18],q[16],q[12],q[11],q[9],q[8],q[1]; +mcx q[18],q[17],q[16],q[12],q[9],q[8],q[1]; +mcx q[18],q[17],q[16],q[12],q[9],q[8],q[0]; +mcx q[18],q[17],q[16],q[15],q[12],q[8],q[1]; +mcx q[18],q[17],q[16],q[15],q[12],q[8],q[0]; +mcx q[18],q[17],q[15],q[13],q[12],q[10],q[8],q[0]; +mcx q[18],q[17],q[15],q[12],q[10],q[8],q[1]; +mcx q[15],q[9],q[8],q[7],q[0]; +mcx q[15],q[9],q[8],q[0]; +mcx q[18],q[16],q[15],q[12],q[11],q[8],q[7],q[0]; +mcx q[18],q[17],q[16],q[15],q[12],q[8],q[7],q[0]; +mcx q[18],q[17],q[16],q[12],q[9],q[8],q[7],q[0]; +mcx q[18],q[17],q[12],q[10],q[9],q[8],q[7],q[0]; +x q[17]; +mcx q[18],q[16],q[12],q[11],q[9],q[8],q[7],q[0]; +x q[11]; +ccx q[14],q[8],q[2]; +x q[15]; +mcx q[17],q[15],q[11],q[10],q[2]; +mcx q[17],q[15],q[11],q[10],q[7],q[0]; +mcx q[17],q[16],q[15],q[14],q[11],q[7],q[0]; +x q[7]; +mcx q[17],q[15],q[11],q[10],q[8],q[7],q[0]; +mcx q[17],q[15],q[14],q[11],q[10],q[0]; +mcx q[17],q[15],q[14],q[13],q[11],q[10],q[0]; +mcx q[17],q[16],q[15],q[11],q[2]; +x q[14]; +mcx q[17],q[15],q[14],q[11],q[10],q[1]; +mcx q[17],q[16],q[15],q[14],q[11],q[1]; +mcx q[17],q[16],q[15],q[11],q[8],q[7],q[0]; +mcx q[17],q[16],q[15],q[13],q[11],q[8],q[0]; +x q[16]; +mcx q[17],q[15],q[13],q[11],q[10],q[8],q[0]; +x q[10]; +mcx q[16],q[15],q[10],q[8],q[1]; +x q[7]; +mcx q[16],q[15],q[14],q[10],q[7],q[0]; +mcx q[17],q[15],q[14],q[11],q[10],q[7],q[0]; +mcx q[17],q[15],q[14],q[11],q[7],q[0]; +x q[13]; +mcx q[16],q[15],q[10],q[8],q[7],q[0]; +mcx q[16],q[15],q[10],q[7],q[0]; +mcx q[16],q[15],q[13],q[10],q[8],q[0]; +x q[16]; +mcx q[17],q[16],q[15],q[14],q[13],q[11],q[0]; +mcx q[17],q[16],q[15],q[13],q[11],q[0]; +x q[16]; +x q[13]; +x q[11]; +mcx q[18],q[16],q[15],q[12],q[11],q[2]; +mcx q[18],q[16],q[15],q[12],q[11],q[1]; +mcx q[18],q[15],q[14],q[13],q[12],q[11],q[10],q[0]; +mcx q[18],q[16],q[15],q[14],q[13],q[12],q[11],q[0]; +mcx q[18],q[15],q[12],q[11],q[10],q[8],q[1]; +mcx q[18],q[15],q[12],q[11],q[8],q[1]; +x q[16]; +mcx q[18],q[16],q[15],q[14],q[12],q[11],q[1]; +mcx q[18],q[16],q[15],q[14],q[12],q[11],q[0]; +mcx q[18],q[16],q[15],q[14],q[12],q[11],q[7],q[0]; +mcx q[18],q[16],q[15],q[12],q[11],q[7],q[0]; +x q[11]; +x q[17]; +mcx q[18],q[17],q[16],q[15],q[14],q[12],q[1]; +mcx q[18],q[17],q[16],q[15],q[13],q[12],q[8],q[0]; +mcx q[18],q[17],q[16],q[15],q[14],q[12],q[7],q[0]; +x q[7]; +mcx q[18],q[17],q[16],q[15],q[12],q[7],q[0]; +x q[17]; +x q[9]; +mcx q[17],q[16],q[11],q[9],q[2]; +mcx q[17],q[16],q[11],q[9],q[8],q[7],q[0]; +mcx q[17],q[16],q[11],q[9],q[7],q[0]; +mcx q[17],q[16],q[14],q[11],q[9],q[7],q[0]; +mcx q[17],q[16],q[14],q[11],q[9],q[1]; +mcx q[17],q[16],q[13],q[11],q[9],q[8],q[0]; +x q[16]; +mcx q[16],q[13],q[10],q[9],q[8],q[0]; +mcx q[16],q[10],q[9],q[8],q[1]; +mcx q[16],q[10],q[9],q[8],q[0]; +x q[8]; +ccx q[15],q[9],q[3]; +x q[7]; +mcx q[16],q[10],q[9],q[8],q[7],q[0]; +mcx q[16],q[14],q[10],q[9],q[7],q[0]; +x q[10]; +mcx q[17],q[11],q[10],q[9],q[2]; +mcx q[17],q[14],q[11],q[10],q[9],q[1]; +mcx q[17],q[14],q[11],q[10],q[9],q[0]; +mcx q[17],q[11],q[10],q[9],q[8],q[7],q[0]; +mcx q[17],q[14],q[11],q[10],q[9],q[7],q[0]; +mcx q[17],q[11],q[10],q[9],q[8],q[0]; +x q[8]; +mcx q[17],q[13],q[11],q[10],q[9],q[8],q[0]; +x q[14]; +mcx q[17],q[16],q[14],q[13],q[11],q[9],q[0]; +mcx q[17],q[14],q[13],q[11],q[10],q[9],q[0]; +mcx q[17],q[14],q[13],q[11],q[9],q[0]; +x q[14]; +x q[11]; +x q[16]; +mcx q[18],q[16],q[14],q[12],q[11],q[9],q[1]; +mcx q[18],q[16],q[14],q[12],q[11],q[9],q[0]; +mcx q[18],q[16],q[14],q[13],q[12],q[11],q[9],q[0]; +mcx q[18],q[14],q[13],q[12],q[11],q[10],q[9],q[0]; +mcx q[18],q[12],q[11],q[10],q[9],q[8],q[1]; +x q[17]; +mcx q[18],q[17],q[16],q[14],q[12],q[9],q[1]; +mcx q[18],q[17],q[16],q[13],q[12],q[9],q[8],q[0]; +x q[14]; +mcx q[18],q[16],q[14],q[12],q[11],q[9],q[7],q[0]; +mcx q[18],q[17],q[16],q[14],q[12],q[9],q[7],q[0]; +x q[12]; +cx q[12],q[6]; +ccx q[18],q[12],q[5]; +ccx q[18],q[12],q[4]; +ccx q[18],q[12],q[3]; +ccx q[18],q[12],q[2]; +ccx q[18],q[12],q[1]; +x q[18]; +cx q[18],q[6]; +cx q[18],q[5]; +cx q[18],q[4]; +cx q[18],q[3]; +cx q[18],q[2]; +cx q[18],q[1]; diff --git a/test/circuits/partialEquivalenceTest/add6_196_2.qasm b/test/circuits/partialEquivalenceTest/add6_196_2.qasm new file mode 100644 index 00000000..08e70c01 --- /dev/null +++ b/test/circuits/partialEquivalenceTest/add6_196_2.qasm @@ -0,0 +1,270 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[19]; +creg c[19]; +h q[7]; +h q[8]; +h q[9]; +h q[10]; +h q[11]; +h q[12]; +h q[13]; +h q[14]; +h q[15]; +h q[16]; +h q[17]; +h q[18]; +mcx q[16],q[10],q[9],q[2]; +ccx q[16],q[10],q[4]; +ccx q[16],q[10],q[3]; +ccx q[17],q[11],q[5]; +ccx q[17],q[11],q[4]; +ccx q[17],q[11],q[3]; +ccx q[15],q[9],q[3]; +ccx q[15],q[9],q[2]; +ccx q[15],q[9],q[1]; +ccx q[15],q[9],q[0]; +mcx q[15],q[9],q[8],q[1]; +mcx q[15],q[9],q[8],q[0]; +mcx q[14],q[8],q[7],q[0]; +mcx q[16],q[15],q[10],q[2]; +mcx q[16],q[15],q[10],q[1]; +mcx q[16],q[15],q[14],q[10],q[1]; +mcx q[18],q[12],q[11],q[4]; +mcx q[18],q[12],q[11],q[3]; +mcx q[18],q[12],q[11],q[2]; +mcx q[18],q[12],q[11],q[1]; +mcx q[17],q[11],q[10],q[3]; +mcx q[14],q[13],q[8],q[0]; +ccx q[14],q[8],q[2]; +ccx q[14],q[8],q[1]; +ccx q[13],q[7],q[1]; +ccx q[13],q[7],q[0]; +x q[16]; +mcx q[17],q[16],q[15],q[11],q[8],q[1]; +mcx q[17],q[16],q[11],q[9],q[8],q[1]; +mcx q[17],q[16],q[11],q[3]; +mcx q[18],q[16],q[12],q[11],q[9],q[2]; +mcx q[18],q[16],q[12],q[11],q[9],q[1]; +mcx q[18],q[17],q[16],q[12],q[9],q[2]; +mcx q[18],q[17],q[16],q[12],q[9],q[1]; +x q[10]; +mcx q[18],q[15],q[14],q[12],q[11],q[10],q[7],q[0]; +mcx q[18],q[17],q[15],q[14],q[12],q[10],q[7],q[0]; +mcx q[17],q[11],q[10],q[9],q[8],q[1]; +mcx q[17],q[15],q[11],q[10],q[8],q[1]; +ccx q[16],q[10],q[4]; +x q[17]; +mcx q[18],q[17],q[12],q[4]; +mcx q[18],q[17],q[15],q[14],q[12],q[10],q[1]; +mcx q[18],q[17],q[15],q[12],q[10],q[8],q[7],q[0]; +mcx q[18],q[17],q[12],q[10],q[9],q[2]; +mcx q[18],q[17],q[12],q[10],q[9],q[1]; +mcx q[18],q[17],q[12],q[10],q[9],q[0]; +mcx q[18],q[17],q[12],q[10],q[9],q[8],q[1]; +mcx q[18],q[17],q[15],q[12],q[10],q[2]; +mcx q[18],q[17],q[15],q[12],q[10],q[1]; +mcx q[18],q[17],q[12],q[10],q[3]; +mcx q[18],q[17],q[14],q[13],q[12],q[10],q[9],q[0]; +x q[10]; +mcx q[18],q[17],q[16],q[12],q[3]; +mcx q[18],q[17],q[16],q[12],q[0]; +mcx q[18],q[17],q[16],q[15],q[12],q[2]; +mcx q[18],q[17],q[16],q[15],q[12],q[1]; +mcx q[18],q[17],q[16],q[15],q[12],q[0]; +x q[11]; +mcx q[18],q[12],q[11],q[10],q[3]; +mcx q[18],q[15],q[12],q[11],q[10],q[2]; +mcx q[18],q[15],q[12],q[11],q[10],q[1]; +x q[10]; +mcx q[18],q[12],q[11],q[10],q[9],q[2]; +mcx q[18],q[15],q[14],q[12],q[11],q[10],q[1]; +mcx q[18],q[14],q[12],q[11],q[10],q[9],q[7],q[0]; +mcx q[18],q[15],q[12],q[11],q[10],q[8],q[7],q[0]; +mcx q[18],q[15],q[13],q[12],q[11],q[10],q[8],q[0]; +mcx q[18],q[16],q[12],q[11],q[3]; +mcx q[18],q[16],q[12],q[11],q[2]; +mcx q[18],q[16],q[12],q[11],q[1]; +ccx q[17],q[11],q[5]; +x q[13]; +mcx q[15],q[14],q[13],q[9],q[0]; +mcx q[15],q[13],q[9],q[8],q[0]; +mcx q[18],q[17],q[13],q[12],q[10],q[9],q[8],q[0]; +x q[10]; +mcx q[18],q[13],q[12],q[11],q[10],q[9],q[8],q[0]; +mcx q[18],q[16],q[15],q[13],q[12],q[11],q[8],q[0]; +x q[16]; +mcx q[18],q[16],q[13],q[12],q[11],q[9],q[8],q[0]; +x q[14]; +mcx q[16],q[14],q[10],q[9],q[1]; +mcx q[15],q[14],q[9],q[1]; +x q[10]; +mcx q[18],q[17],q[15],q[14],q[13],q[12],q[10],q[0]; +mcx q[18],q[17],q[15],q[14],q[12],q[10],q[0]; +mcx q[18],q[17],q[14],q[12],q[10],q[9],q[7],q[0]; +mcx q[18],q[17],q[14],q[12],q[10],q[9],q[1]; +mcx q[18],q[14],q[12],q[11],q[10],q[9],q[1]; +x q[10]; +mcx q[16],q[14],q[13],q[10],q[9],q[0]; +mcx q[16],q[15],q[14],q[13],q[10],q[0]; +x q[16]; +mcx q[18],q[17],q[16],q[14],q[13],q[12],q[9],q[0]; +mcx q[18],q[17],q[16],q[15],q[14],q[13],q[12],q[0]; +x q[7]; +x q[10]; +mcx q[18],q[12],q[11],q[10],q[9],q[8],q[7],q[0]; +ccx q[13],q[7],q[1]; +x q[13]; +mcx q[15],q[14],q[9],q[7],q[0]; +x q[8]; +mcx q[18],q[16],q[15],q[12],q[11],q[8],q[1]; +mcx q[18],q[16],q[12],q[11],q[9],q[8],q[1]; +mcx q[18],q[17],q[16],q[12],q[9],q[8],q[1]; +mcx q[18],q[17],q[16],q[12],q[9],q[8],q[0]; +mcx q[18],q[17],q[16],q[15],q[12],q[8],q[1]; +mcx q[18],q[17],q[16],q[15],q[12],q[8],q[0]; +mcx q[18],q[17],q[15],q[13],q[12],q[10],q[8],q[0]; +mcx q[18],q[17],q[15],q[12],q[10],q[8],q[1]; +mcx q[15],q[9],q[8],q[7],q[0]; +mcx q[15],q[9],q[8],q[0]; +mcx q[18],q[16],q[15],q[12],q[11],q[8],q[7],q[0]; +mcx q[18],q[17],q[16],q[15],q[12],q[8],q[7],q[0]; +mcx q[18],q[17],q[16],q[12],q[9],q[8],q[7],q[0]; +mcx q[18],q[17],q[12],q[10],q[9],q[8],q[7],q[0]; +x q[17]; +mcx q[18],q[16],q[12],q[11],q[9],q[8],q[7],q[0]; +x q[11]; +ccx q[14],q[8],q[2]; +x q[15]; +mcx q[17],q[15],q[11],q[10],q[2]; +mcx q[17],q[15],q[11],q[10],q[7],q[0]; +mcx q[17],q[16],q[15],q[14],q[11],q[7],q[0]; +x q[7]; +mcx q[17],q[15],q[11],q[10],q[8],q[7],q[0]; +mcx q[17],q[15],q[14],q[11],q[10],q[0]; +mcx q[17],q[15],q[14],q[13],q[11],q[10],q[0]; +mcx q[17],q[16],q[15],q[11],q[2]; +x q[14]; +mcx q[17],q[15],q[14],q[11],q[10],q[1]; +mcx q[17],q[16],q[15],q[14],q[11],q[1]; +mcx q[17],q[16],q[15],q[11],q[8],q[7],q[0]; +mcx q[17],q[16],q[15],q[13],q[11],q[8],q[0]; +x q[16]; +mcx q[17],q[15],q[13],q[11],q[10],q[8],q[0]; +x q[10]; +mcx q[16],q[15],q[10],q[8],q[1]; +x q[7]; +mcx q[16],q[15],q[14],q[10],q[7],q[0]; +mcx q[17],q[15],q[14],q[11],q[10],q[7],q[0]; +mcx q[17],q[15],q[14],q[11],q[7],q[0]; +x q[13]; +mcx q[16],q[15],q[10],q[8],q[7],q[0]; +mcx q[16],q[15],q[10],q[7],q[0]; +mcx q[16],q[15],q[13],q[10],q[8],q[0]; +x q[16]; +mcx q[17],q[16],q[15],q[14],q[13],q[11],q[0]; +mcx q[17],q[16],q[15],q[13],q[11],q[0]; +x q[16]; +x q[13]; +x q[11]; +mcx q[18],q[16],q[15],q[12],q[11],q[2]; +mcx q[18],q[16],q[15],q[12],q[11],q[1]; +mcx q[18],q[15],q[14],q[13],q[12],q[11],q[10],q[0]; +mcx q[18],q[16],q[15],q[14],q[13],q[12],q[11],q[0]; +mcx q[18],q[15],q[12],q[11],q[10],q[8],q[1]; +mcx q[18],q[15],q[12],q[11],q[8],q[1]; +x q[16]; +mcx q[18],q[16],q[15],q[14],q[12],q[11],q[1]; +mcx q[18],q[16],q[15],q[14],q[12],q[11],q[0]; +mcx q[18],q[16],q[15],q[14],q[12],q[11],q[7],q[0]; +mcx q[18],q[16],q[15],q[12],q[11],q[7],q[0]; +x q[11]; +x q[17]; +mcx q[18],q[17],q[16],q[15],q[14],q[12],q[1]; +mcx q[18],q[17],q[16],q[15],q[13],q[12],q[8],q[0]; +mcx q[18],q[17],q[16],q[15],q[14],q[12],q[7],q[0]; +x q[7]; +mcx q[18],q[17],q[16],q[15],q[12],q[7],q[0]; +x q[17]; +x q[9]; +mcx q[17],q[16],q[11],q[9],q[2]; +mcx q[17],q[16],q[11],q[9],q[8],q[7],q[0]; +mcx q[17],q[16],q[11],q[9],q[7],q[0]; +mcx q[17],q[16],q[14],q[11],q[9],q[7],q[0]; +mcx q[17],q[16],q[14],q[11],q[9],q[1]; +mcx q[17],q[16],q[13],q[11],q[9],q[8],q[0]; +x q[16]; +mcx q[16],q[13],q[10],q[9],q[8],q[0]; +mcx q[16],q[10],q[9],q[8],q[1]; +mcx q[16],q[10],q[9],q[8],q[0]; +x q[8]; +ccx q[15],q[9],q[3]; +x q[7]; +mcx q[16],q[10],q[9],q[8],q[7],q[0]; +mcx q[16],q[14],q[10],q[9],q[7],q[0]; +x q[10]; +mcx q[17],q[11],q[10],q[9],q[2]; +mcx q[17],q[14],q[11],q[10],q[9],q[1]; +mcx q[17],q[14],q[11],q[10],q[9],q[0]; +mcx q[17],q[11],q[10],q[9],q[8],q[7],q[0]; +mcx q[17],q[14],q[11],q[10],q[9],q[7],q[0]; +mcx q[17],q[11],q[10],q[9],q[8],q[0]; +x q[8]; +mcx q[17],q[13],q[11],q[10],q[9],q[8],q[0]; +x q[14]; +mcx q[17],q[16],q[14],q[13],q[11],q[9],q[0]; +mcx q[17],q[14],q[13],q[11],q[10],q[9],q[0]; +mcx q[17],q[14],q[13],q[11],q[9],q[0]; +x q[14]; +x q[11]; +x q[16]; +mcx q[18],q[16],q[14],q[12],q[11],q[9],q[1]; +mcx q[18],q[16],q[14],q[12],q[11],q[9],q[0]; +mcx q[18],q[16],q[14],q[13],q[12],q[11],q[9],q[0]; +mcx q[18],q[14],q[13],q[12],q[11],q[10],q[9],q[0]; +mcx q[18],q[12],q[11],q[10],q[9],q[8],q[1]; +x q[17]; +mcx q[18],q[17],q[16],q[14],q[12],q[9],q[1]; +mcx q[18],q[17],q[16],q[13],q[12],q[9],q[8],q[0]; +x q[14]; +mcx q[18],q[16],q[14],q[12],q[11],q[9],q[7],q[0]; +mcx q[18],q[17],q[16],q[14],q[12],q[9],q[7],q[0]; +x q[12]; +h q[12]; +h q[6]; +cx q[6], q[12]; +h q[12]; +h q[6]; +ccx q[18],q[12],q[5]; +ccx q[18],q[12],q[4]; +ccx q[18],q[12],q[3]; +ccx q[18],q[12],q[2]; +ccx q[18],q[12],q[1]; +x q[18]; +cx q[18], q[12]; +cx q[12], q[6]; +cx q[18], q[12]; +cx q[12], q[6]; +h q[18]; +h q[5]; +cx q[5], q[18]; +h q[18]; +h q[5]; +x q[16]; +ccx q[16], q[18], q[4]; +x q[16]; +ccx q[16], q[18], q[4]; +h q[18]; +h q[3]; +cx q[3], q[18]; +h q[18]; +h q[3]; +cx q[18], q[10]; +cx q[10], q[2]; +cx q[18], q[10]; +cx q[10], q[2]; +h q[18]; +h q[1]; +cx q[1], q[18]; +h q[18]; +h q[1]; diff --git a/test/circuits/partialEquivalenceTest/bv_1.qasm b/test/circuits/partialEquivalenceTest/bv_1.qasm new file mode 100644 index 00000000..1867a792 --- /dev/null +++ b/test/circuits/partialEquivalenceTest/bv_1.qasm @@ -0,0 +1,33 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[10]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +x q[9]; +h q[9]; +cx q[0], q[9]; +cx q[1], q[9]; +cx q[2], q[9]; +cx q[3], q[9]; +cx q[4], q[9]; +cx q[5], q[9]; +cx q[6], q[9]; +cx q[7], q[9]; +cx q[8], q[9]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; diff --git a/test/circuits/partialEquivalenceTest/bv_2.qasm b/test/circuits/partialEquivalenceTest/bv_2.qasm new file mode 100644 index 00000000..a16ae96e --- /dev/null +++ b/test/circuits/partialEquivalenceTest/bv_2.qasm @@ -0,0 +1,66 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[10]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +x q[9]; +h q[9]; +h q[0]; +h q[9]; +cx q[9], q[0]; +h q[0]; +h q[9]; +cx q[1], q[7]; +cx q[7], q[9]; +cx q[1], q[7]; +cx q[7], q[9]; +x q[6]; +ccx q[6], q[2], q[9]; +x q[6]; +ccx q[6], q[2], q[9]; +h q[3]; +h q[9]; +cx q[9], q[3]; +h q[3]; +h q[9]; +h q[4]; +h q[9]; +cx q[9], q[4]; +h q[4]; +h q[9]; +x q[1]; +ccx q[1], q[5], q[9]; +x q[1]; +ccx q[1], q[5], q[9]; +h q[6]; +h q[9]; +cx q[9], q[6]; +h q[6]; +h q[9]; +h q[7]; +h q[9]; +cx q[9], q[7]; +h q[7]; +h q[9]; +h q[8]; +h q[9]; +cx q[9], q[8]; +h q[8]; +h q[9]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; diff --git a/test/circuits/partialEquivalenceTest/entanglement_1.qasm b/test/circuits/partialEquivalenceTest/entanglement_1.qasm new file mode 100644 index 00000000..8063a66d --- /dev/null +++ b/test/circuits/partialEquivalenceTest/entanglement_1.qasm @@ -0,0 +1,14 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[10]; +h q[0]; +cx q[0], q[1]; +cx q[0], q[2]; +cx q[0], q[3]; +cx q[0], q[4]; +cx q[0], q[5]; +cx q[0], q[6]; +cx q[0], q[7]; +cx q[0], q[8]; +cx q[0], q[9]; diff --git a/test/circuits/partialEquivalenceTest/entanglement_2.qasm b/test/circuits/partialEquivalenceTest/entanglement_2.qasm new file mode 100644 index 00000000..3da96b7b --- /dev/null +++ b/test/circuits/partialEquivalenceTest/entanglement_2.qasm @@ -0,0 +1,46 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[10]; +h q[0]; +x q[2]; +ccx q[2], q[0], q[1]; +x q[2]; +ccx q[2], q[0], q[1]; +h q[0]; +h q[2]; +cx q[2], q[0]; +h q[0]; +h q[2]; +h q[0]; +h q[3]; +cx q[3], q[0]; +h q[0]; +h q[3]; +h q[0]; +h q[4]; +cx q[4], q[0]; +h q[0]; +h q[4]; +h q[0]; +h q[5]; +cx q[5], q[0]; +h q[0]; +h q[5]; +x q[5]; +ccx q[5], q[0], q[6]; +x q[5]; +ccx q[5], q[0], q[6]; +h q[0]; +h q[7]; +cx q[7], q[0]; +h q[0]; +h q[7]; +cx q[0], q[9]; +cx q[9], q[8]; +cx q[0], q[9]; +cx q[9], q[8]; +cx q[0], q[6]; +cx q[6], q[9]; +cx q[0], q[6]; +cx q[6], q[9]; diff --git a/test/circuits/partialEquivalenceTest/grover-noancilla_indep_qiskit_3.qasm b/test/circuits/partialEquivalenceTest/grover-noancilla_indep_qiskit_3.qasm new file mode 100644 index 00000000..e818fecf --- /dev/null +++ b/test/circuits/partialEquivalenceTest/grover-noancilla_indep_qiskit_3.qasm @@ -0,0 +1,18 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[2]; +qreg flag[1]; +creg meas[3]; +h q[0]; +h q[1]; +x flag[0]; +cp(pi/2) q[1],flag[0]; +cx q[1],q[0]; +cp(-pi/2) q[0],flag[0]; +cx q[1],q[0]; +cp(pi/2) q[0],flag[0]; +u2(0,0) q[0]; +u1(-pi) q[1]; +cx q[0],q[1]; +u2(-pi,-pi) q[0]; +u1(-pi) q[1]; diff --git a/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt0_3.qasm b/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt0_3.qasm new file mode 100644 index 00000000..269a58ed --- /dev/null +++ b/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt0_3.qasm @@ -0,0 +1,58 @@ +// Benchmark was created by MQT Bench on 2023-06-29 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: v1.0.0 +// Qiskit version: {'qiskit-terra': '0.24.1', 'qiskit-aer': '0.12.0', 'qiskit-ignis': None, 'qiskit-ibmq-provider': '0.20.2', 'qiskit': '0.43.1', 'qiskit-nature': '0.6.2', 'qiskit-finance': '0.3.4', 'qiskit-optimization': '0.5.0', 'qiskit-machine-learning': '0.6.1'} +// Used Gate Set: ['rz', 'sx', 'x', 'cx', 'measure'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[2]; +qreg flag[1]; +creg meas[3]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/4) q[1]; +x flag[0]; +cx q[1],flag[0]; +rz(-pi/4) flag[0]; +cx q[1],flag[0]; +rz(pi/4) flag[0]; +cx q[1],q[0]; +rz(-pi/4) q[0]; +cx q[0],flag[0]; +rz(pi/4) flag[0]; +cx q[0],flag[0]; +rz(-pi/4) flag[0]; +cx q[1],q[0]; +rz(pi/4) q[0]; +cx q[0],flag[0]; +rz(-pi/4) flag[0]; +cx q[0],flag[0]; +rz(pi/4) flag[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +x q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +x q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +cx q[0],q[1]; +x q[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +x q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; diff --git a/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt0_7.qasm b/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt0_7.qasm new file mode 100644 index 00000000..c97c98fe --- /dev/null +++ b/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt0_7.qasm @@ -0,0 +1,3762 @@ +// Benchmark was created by MQT Bench on 2023-06-29 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: v1.0.0 +// Qiskit version: {'qiskit-terra': '0.24.1', 'qiskit-aer': '0.12.0', 'qiskit-ignis': None, 'qiskit-ibmq-provider': '0.20.2', 'qiskit': '0.43.1', 'qiskit-nature': '0.6.2', 'qiskit-finance': '0.3.4', 'qiskit-optimization': '0.5.0', 'qiskit-machine-learning': '0.6.1'} +// Used Gate Set: ['rz', 'sx', 'x', 'cx', 'measure'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[6]; +qreg flag[1]; +creg meas[7]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/64) q[5]; +x flag[0]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +x q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +x q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +x q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +x q[4]; +rz(pi/32) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +x q[0]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +x q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +x q[2]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +x q[3]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +x q[4]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +x q[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/32) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/64) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +x q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +x q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +x q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +x q[4]; +rz(pi/32) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +x q[0]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +x q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +x q[2]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +x q[3]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +x q[4]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +x q[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/32) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/64) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +x q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +x q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +x q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +x q[4]; +rz(pi/32) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +x q[0]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +x q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +x q[2]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +x q[3]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +x q[4]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +x q[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/32) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/64) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +x q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +x q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +x q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +x q[4]; +rz(pi/32) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +x q[0]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +x q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +x q[2]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +x q[3]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +x q[4]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +x q[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/32) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/64) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +x q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +x q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +x q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +x q[4]; +rz(pi/32) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +x q[0]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +x q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +x q[2]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +x q[3]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +x q[4]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +x q[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/32) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/64) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +x q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +x q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +x q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +x q[4]; +rz(pi/32) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +x q[0]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +x q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +x q[2]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +x q[3]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +x q[4]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +x q[0]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/32) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +x q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; diff --git a/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt1_7.qasm b/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt1_7.qasm new file mode 100644 index 00000000..82bd2e2e --- /dev/null +++ b/test/circuits/partialEquivalenceTest/grover-noancilla_nativegates_ibm_qiskit_opt1_7.qasm @@ -0,0 +1,3600 @@ +// Benchmark was created by MQT Bench on 2023-06-29 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: v1.0.0 +// Qiskit version: {'qiskit-terra': '0.24.1', 'qiskit-aer': '0.12.0', 'qiskit-ignis': None, 'qiskit-ibmq-provider': '0.20.2', 'qiskit': '0.43.1', 'qiskit-nature': '0.6.2', 'qiskit-finance': '0.3.4', 'qiskit-optimization': '0.5.0', 'qiskit-machine-learning': '0.6.1'} +// Used Gate Set: ['rz', 'sx', 'x', 'cx', 'measure'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[6]; +qreg flag[1]; +creg meas[7]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(pi/2) q[5]; +sx q[5]; +rz(1.619883712007237) q[5]; +x flag[0]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[4]; +sx q[4]; +rz(1.6689710972195773) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(-pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(-pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(-pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(-pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(-pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(-pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(pi/2) q[0]; +sx q[0]; +rz(-pi/2) q[0]; +rz(1.6689710972195773) q[5]; +sx q[5]; +rz(-1.5217089415825567) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[4]; +sx q[4]; +rz(1.6689710972195773) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(-pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(-pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(-pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(-pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(-pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(-pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(pi/2) q[0]; +sx q[0]; +rz(-pi/2) q[0]; +rz(1.6689710972195773) q[5]; +sx q[5]; +rz(-1.5217089415825567) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[4]; +sx q[4]; +rz(1.6689710972195773) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(-pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(-pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(-pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(-pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(-pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(-pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(pi/2) q[0]; +sx q[0]; +rz(-pi/2) q[0]; +rz(1.6689710972195773) q[5]; +sx q[5]; +rz(-1.5217089415825567) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[4]; +sx q[4]; +rz(1.6689710972195773) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(-pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(-pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(-pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(-pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(-pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(-pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(pi/2) q[0]; +sx q[0]; +rz(-pi/2) q[0]; +rz(1.6689710972195773) q[5]; +sx q[5]; +rz(-1.5217089415825567) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[4]; +sx q[4]; +rz(1.6689710972195773) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(-pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(-pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(-pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(-pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(-pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(-pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(pi/2) q[0]; +sx q[0]; +rz(-pi/2) q[0]; +rz(1.6689710972195773) q[5]; +sx q[5]; +rz(-1.5217089415825567) q[5]; +cx q[5],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],flag[0]; +rz(pi/64) flag[0]; +cx q[5],q[4]; +rz(-pi/64) q[4]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[4]; +rz(pi/64) q[4]; +cx q[4],flag[0]; +rz(-pi/64) flag[0]; +cx q[4],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[3]; +rz(-pi/64) q[3]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[3]; +rz(pi/64) q[3]; +cx q[3],flag[0]; +rz(-pi/64) flag[0]; +cx q[3],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[2]; +rz(-pi/64) q[2]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[2]; +rz(pi/64) q[2]; +cx q[2],flag[0]; +rz(-pi/64) flag[0]; +cx q[2],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[1]; +rz(-pi/64) q[1]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[1]; +rz(pi/64) q[1]; +cx q[1],flag[0]; +rz(-pi/64) flag[0]; +cx q[1],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[1],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[2],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[3],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[4],q[0]; +rz(-pi/64) q[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +rz(-pi/2) q[4]; +sx q[4]; +rz(1.6689710972195773) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[0],flag[0]; +rz(-pi/64) flag[0]; +cx q[0],flag[0]; +rz(pi/64) flag[0]; +rz(-pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(-pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[4],q[5]; +rz(-pi/32) q[5]; +cx q[4],q[5]; +cx q[4],q[3]; +rz(-pi/32) q[3]; +rz(pi/32) q[5]; +cx q[3],q[5]; +rz(pi/32) q[5]; +cx q[3],q[5]; +cx q[4],q[3]; +rz(pi/32) q[3]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +rz(-pi/32) q[5]; +cx q[3],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[3],q[2]; +rz(-pi/32) q[2]; +rz(pi/32) q[5]; +cx q[2],q[5]; +rz(pi/32) q[5]; +cx q[2],q[5]; +cx q[4],q[2]; +rz(pi/32) q[2]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +rz(-pi/32) q[5]; +cx q[2],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[2],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[3],q[1]; +rz(-pi/32) q[1]; +rz(pi/32) q[5]; +cx q[1],q[5]; +rz(pi/32) q[5]; +cx q[1],q[5]; +cx q[4],q[1]; +rz(pi/32) q[1]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +rz(-pi/32) q[5]; +cx q[1],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[1],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(-pi/2) q[1]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[2],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[2]; +sx q[2]; +rz(-pi/2) q[2]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +cx q[3],q[0]; +rz(-pi/32) q[0]; +rz(pi/2) q[3]; +sx q[3]; +rz(-pi/2) q[3]; +rz(pi/32) q[5]; +cx q[0],q[5]; +rz(pi/32) q[5]; +cx q[0],q[5]; +cx q[4],q[0]; +rz(pi/32) q[0]; +rz(pi/2) q[4]; +sx q[4]; +rz(-pi/2) q[4]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(-pi/32) q[5]; +cx q[0],q[5]; +rz(pi/2) q[0]; +sx q[0]; +rz(-pi/2) q[0]; +rz(1.6689710972195773) q[5]; +sx q[5]; +rz(-pi/2) q[5]; diff --git a/test/circuits/partialEquivalenceTest/period_finding_1.qasm b/test/circuits/partialEquivalenceTest/period_finding_1.qasm new file mode 100644 index 00000000..c8e1902d --- /dev/null +++ b/test/circuits/partialEquivalenceTest/period_finding_1.qasm @@ -0,0 +1,398 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[8]; +h q[0]; +h q[1]; +h q[2]; +x q[7]; +mcx q[0], q[7]; +mcx q[0], q[7], q[4]; +mcx q[0], q[7]; +mcx q[0], q[4]; +mcx q[0], q[4], q[7]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[5]; +mcx q[0], q[4], q[6]; +mcx q[0], q[5], q[7], q[4]; +mcx q[0], q[5], q[6]; +mcx q[0], q[6], q[5]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[5], q[7]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[7], q[5]; +mcx q[0], q[4], q[5]; +mcx q[0], q[4], q[6]; +mcx q[0], q[4]; +mcx q[0], q[4], q[5]; +mcx q[0], q[6], q[7], q[4]; +mcx q[0], q[4], q[7], q[6]; +mcx q[0], q[4], q[5]; +mcx q[0], q[5], q[4]; +mcx q[0], q[6]; +mcx q[0], q[6]; +mcx q[0], q[4], q[7], q[6]; +mcx q[0], q[4], q[5]; +mcx q[0], q[4], q[6]; +mcx q[0], q[5], q[6], q[4]; +mcx q[0], q[5], q[6]; +mcx q[0], q[7], q[4], q[5]; +mcx q[0], q[5], q[6]; +mcx q[0], q[7]; +mcx q[0], q[6], q[7], q[4], q[5]; +mcx q[0], q[7]; +mcx q[0], q[6]; +mcx q[0], q[4], q[7]; +mcx q[0], q[4]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[5], q[6]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[6], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[5]; +mcx q[0], q[5], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[6]; +mcx q[0], q[4]; +mcx q[0], q[4], q[5]; +mcx q[1], q[7]; +mcx q[1], q[7], q[4]; +mcx q[1], q[7]; +mcx q[1], q[4]; +mcx q[1], q[4], q[7]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[7], q[4]; +mcx q[1], q[5], q[6]; +mcx q[1], q[6], q[5]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5], q[7]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[7], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[6], q[7], q[4]; +mcx q[1], q[4], q[7], q[6]; +mcx q[1], q[4], q[5]; +mcx q[1], q[5], q[4]; +mcx q[1], q[6]; +mcx q[1], q[6]; +mcx q[1], q[4], q[7], q[6]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[6], q[4]; +mcx q[1], q[5], q[6]; +mcx q[1], q[7], q[4], q[5]; +mcx q[1], q[5], q[6]; +mcx q[1], q[7]; +mcx q[1], q[6], q[7], q[4], q[5]; +mcx q[1], q[7]; +mcx q[1], q[6]; +mcx q[1], q[4], q[7]; +mcx q[1], q[4]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5], q[6]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[6], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[5], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[7]; +mcx q[1], q[7], q[4]; +mcx q[1], q[7]; +mcx q[1], q[4]; +mcx q[1], q[4], q[7]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[7], q[4]; +mcx q[1], q[5], q[6]; +mcx q[1], q[6], q[5]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5], q[7]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[7], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[6], q[7], q[4]; +mcx q[1], q[4], q[7], q[6]; +mcx q[1], q[4], q[5]; +mcx q[1], q[5], q[4]; +mcx q[1], q[6]; +mcx q[1], q[6]; +mcx q[1], q[4], q[7], q[6]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[6], q[4]; +mcx q[1], q[5], q[6]; +mcx q[1], q[7], q[4], q[5]; +mcx q[1], q[5], q[6]; +mcx q[1], q[7]; +mcx q[1], q[6], q[7], q[4], q[5]; +mcx q[1], q[7]; +mcx q[1], q[6]; +mcx q[1], q[4], q[7]; +mcx q[1], q[4]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5], q[6]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[6], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[5], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[4]; +mcx q[1], q[4], q[5]; +mcx q[2], q[7]; +mcx q[2], q[7], q[4]; +mcx q[2], q[7]; +mcx q[2], q[4]; +mcx q[2], q[4], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[7], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[7], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[6], q[7], q[4]; +mcx q[2], q[4], q[7], q[6]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7], q[6]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[6], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[7], q[4], q[5]; +mcx q[2], q[5], q[6]; +mcx q[2], q[7]; +mcx q[2], q[6], q[7], q[4], q[5]; +mcx q[2], q[7]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7]; +mcx q[2], q[4]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[6]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[7]; +mcx q[2], q[7], q[4]; +mcx q[2], q[7]; +mcx q[2], q[4]; +mcx q[2], q[4], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[7], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[7], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[6], q[7], q[4]; +mcx q[2], q[4], q[7], q[6]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7], q[6]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[6], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[7], q[4], q[5]; +mcx q[2], q[5], q[6]; +mcx q[2], q[7]; +mcx q[2], q[6], q[7], q[4], q[5]; +mcx q[2], q[7]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7]; +mcx q[2], q[4]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[6]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[7]; +mcx q[2], q[7], q[4]; +mcx q[2], q[7]; +mcx q[2], q[4]; +mcx q[2], q[4], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[7], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[7], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[6], q[7], q[4]; +mcx q[2], q[4], q[7], q[6]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7], q[6]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[6], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[7], q[4], q[5]; +mcx q[2], q[5], q[6]; +mcx q[2], q[7]; +mcx q[2], q[6], q[7], q[4], q[5]; +mcx q[2], q[7]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7]; +mcx q[2], q[4]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[6]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[7]; +mcx q[2], q[7], q[4]; +mcx q[2], q[7]; +mcx q[2], q[4]; +mcx q[2], q[4], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[7], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[7], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[6], q[7], q[4]; +mcx q[2], q[4], q[7], q[6]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7], q[6]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[6], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[7], q[4], q[5]; +mcx q[2], q[5], q[6]; +mcx q[2], q[7]; +mcx q[2], q[6], q[7], q[4], q[5]; +mcx q[2], q[7]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7]; +mcx q[2], q[4]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[6]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +h q[2]; +cswap q[0], q[2], q[3]; +t q[3]; +cswap q[0], q[2], q[3]; +cswap q[1], q[2], q[3]; +s q[3]; +cswap q[1], q[2], q[3]; +h q[1]; +cswap q[0], q[1], q[3]; +s q[3]; +cswap q[0], q[1], q[3]; +h q[0]; +swap q[0], q[2]; diff --git a/test/circuits/partialEquivalenceTest/period_finding_2.qasm b/test/circuits/partialEquivalenceTest/period_finding_2.qasm new file mode 100644 index 00000000..df934fd3 --- /dev/null +++ b/test/circuits/partialEquivalenceTest/period_finding_2.qasm @@ -0,0 +1,440 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[8]; +h q[0]; +h q[1]; +h q[2]; +x q[7]; +mcx q[0], q[5]; +mcx q[0], q[5], q[7]; +mcx q[0], q[5]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[5], q[7]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[7], q[5]; +mcx q[0], q[5], q[6]; +mcx q[0], q[5]; +mcx q[0], q[4], q[5]; +mcx q[0], q[4], q[6]; +mcx q[0], q[5], q[7], q[4]; +mcx q[0], q[5], q[6]; +mcx q[0], q[6], q[5]; +mcx q[0], q[5]; +mcx q[0], q[5]; +mcx q[0], q[4], q[7], q[5]; +mcx q[0], q[4], q[5]; +mcx q[0], q[4], q[6]; +mcx q[0], q[5], q[4]; +mcx q[0], q[4], q[5]; +mcx q[0], q[5], q[6], q[4]; +mcx q[0], q[7], q[4], q[5]; +mcx q[0], q[6]; +mcx q[0], q[6]; +mcx q[0], q[6]; +mcx q[0], q[7]; +mcx q[0], q[5], q[7], q[4], q[6]; +mcx q[0], q[7]; +mcx q[0], q[5], q[6]; +mcx q[0], q[6], q[5]; +mcx q[0], q[6]; +mcx q[0], q[4], q[7]; +mcx q[0], q[5]; +mcx q[0], q[5], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4]; +mcx q[0], q[4], q[6]; +mcx q[0], q[4]; +mcx q[0], q[4], q[5]; +mcx q[0], q[6], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[5], q[6]; +mcx q[0], q[4]; +mcx q[0], q[5]; +mcx q[0], q[6], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[5]; +mcx q[0], q[5], q[4]; +mcx q[0], q[5]; +mcx q[0], q[4], q[6]; +mcx q[0], q[5], q[4]; +mcx q[0], q[4]; +mcx q[0], q[4]; +mcx q[0], q[4], q[5]; +mcx q[0], q[4]; +mcx q[1], q[5]; +mcx q[1], q[5], q[7]; +mcx q[1], q[5]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5], q[7]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[7], q[5]; +mcx q[1], q[5], q[6]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[7], q[4]; +mcx q[1], q[5], q[6]; +mcx q[1], q[6], q[5]; +mcx q[1], q[5]; +mcx q[1], q[5]; +mcx q[1], q[4], q[7], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[5], q[6], q[4]; +mcx q[1], q[7], q[4], q[5]; +mcx q[1], q[6]; +mcx q[1], q[6]; +mcx q[1], q[6]; +mcx q[1], q[7]; +mcx q[1], q[5], q[7], q[4], q[6]; +mcx q[1], q[7]; +mcx q[1], q[5], q[6]; +mcx q[1], q[6], q[5]; +mcx q[1], q[6]; +mcx q[1], q[4], q[7]; +mcx q[1], q[5]; +mcx q[1], q[5], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4]; +mcx q[1], q[4], q[6]; +mcx q[1], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[6], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5], q[6]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[6], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[5], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[4]; +mcx q[1], q[4]; +mcx q[1], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[5], q[7]; +mcx q[1], q[5]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5], q[7]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[7], q[5]; +mcx q[1], q[5], q[6]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[7], q[4]; +mcx q[1], q[5], q[6]; +mcx q[1], q[6], q[5]; +mcx q[1], q[5]; +mcx q[1], q[5]; +mcx q[1], q[4], q[7], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[5], q[6], q[4]; +mcx q[1], q[7], q[4], q[5]; +mcx q[1], q[6]; +mcx q[1], q[6]; +mcx q[1], q[6]; +mcx q[1], q[7]; +mcx q[1], q[5], q[7], q[4], q[6]; +mcx q[1], q[7]; +mcx q[1], q[5], q[6]; +mcx q[1], q[6], q[5]; +mcx q[1], q[6]; +mcx q[1], q[4], q[7]; +mcx q[1], q[5]; +mcx q[1], q[5], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4]; +mcx q[1], q[4], q[6]; +mcx q[1], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[6], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5], q[6]; +mcx q[1], q[4]; +mcx q[1], q[5]; +mcx q[1], q[6], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[5]; +mcx q[1], q[5], q[4]; +mcx q[1], q[5]; +mcx q[1], q[4], q[6]; +mcx q[1], q[5], q[4]; +mcx q[1], q[4]; +mcx q[1], q[4]; +mcx q[1], q[4], q[5]; +mcx q[1], q[4]; +mcx q[2], q[5]; +mcx q[2], q[5], q[7]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[7], q[5]; +mcx q[2], q[5], q[6]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[7], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[5]; +mcx q[2], q[5]; +mcx q[2], q[4], q[7], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[6], q[4]; +mcx q[2], q[7], q[4], q[5]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[7]; +mcx q[2], q[5], q[7], q[4], q[6]; +mcx q[2], q[7]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7]; +mcx q[2], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[6]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[4]; +mcx q[2], q[4]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[5], q[7]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[7], q[5]; +mcx q[2], q[5], q[6]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[7], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[5]; +mcx q[2], q[5]; +mcx q[2], q[4], q[7], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[6], q[4]; +mcx q[2], q[7], q[4], q[5]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[7]; +mcx q[2], q[5], q[7], q[4], q[6]; +mcx q[2], q[7]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7]; +mcx q[2], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[6]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[4]; +mcx q[2], q[4]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[5], q[7]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[7], q[5]; +mcx q[2], q[5], q[6]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[7], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[5]; +mcx q[2], q[5]; +mcx q[2], q[4], q[7], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[6], q[4]; +mcx q[2], q[7], q[4], q[5]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[7]; +mcx q[2], q[5], q[7], q[4], q[6]; +mcx q[2], q[7]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7]; +mcx q[2], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[6]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[4]; +mcx q[2], q[4]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[5], q[7]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[7]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[7], q[5]; +mcx q[2], q[5], q[6]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[7], q[4]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[5]; +mcx q[2], q[5]; +mcx q[2], q[4], q[7], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[6], q[4]; +mcx q[2], q[7], q[4], q[5]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[6]; +mcx q[2], q[7]; +mcx q[2], q[5], q[7], q[4], q[6]; +mcx q[2], q[7]; +mcx q[2], q[5], q[6]; +mcx q[2], q[6], q[5]; +mcx q[2], q[6]; +mcx q[2], q[4], q[7]; +mcx q[2], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[4], q[6]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5], q[6]; +mcx q[2], q[4]; +mcx q[2], q[5]; +mcx q[2], q[6], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[5]; +mcx q[2], q[5], q[4]; +mcx q[2], q[5]; +mcx q[2], q[4], q[6]; +mcx q[2], q[5], q[4]; +mcx q[2], q[4]; +mcx q[2], q[4]; +mcx q[2], q[4], q[5]; +mcx q[2], q[4]; +h q[2]; +cswap q[0], q[2], q[3]; +t q[3]; +cswap q[0], q[2], q[3]; +cswap q[1], q[2], q[3]; +s q[3]; +cswap q[1], q[2], q[3]; +h q[1]; +cswap q[0], q[1], q[3]; +s q[3]; +cswap q[0], q[1], q[3]; +h q[0]; +swap q[0], q[2]; diff --git a/test/circuits/partialEquivalenceTest/random_1.qasm b/test/circuits/partialEquivalenceTest/random_1.qasm new file mode 100644 index 00000000..aea6900d --- /dev/null +++ b/test/circuits/partialEquivalenceTest/random_1.qasm @@ -0,0 +1,154 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[10]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +h q[9]; +ccx q[0], q[6], q[7]; +ccx q[0], q[3], q[7]; +cx q[4], q[2]; +h q[8]; +cx q[5], q[1]; +s q[5]; +h q[6]; +s q[9]; +t q[6]; +cx q[4], q[7]; +s q[4]; +t q[2]; +cx q[3], q[7]; +ccx q[6], q[0], q[9]; +h q[3]; +s q[3]; +t q[8]; +t q[3]; +t q[8]; +cx q[6], q[7]; +h q[9]; +t q[8]; +s q[3]; +cx q[3], q[0]; +h q[7]; +t q[9]; +h q[8]; +h q[2]; +cx q[9], q[5]; +ccx q[2], q[1], q[7]; +s q[3]; +t q[6]; +cx q[7], q[3]; +t q[2]; +ccx q[8], q[2], q[1]; +t q[7]; +t q[2]; +s q[2]; +cx q[5], q[6]; +s q[0]; +ccx q[0], q[5], q[3]; +h q[4]; +cx q[6], q[9]; +s q[6]; +cx q[3], q[8]; +t q[8]; +cx q[9], q[7]; +h q[2]; +cx q[7], q[6]; +s q[6]; +ccx q[9], q[5], q[8]; +cx q[7], q[2]; +ccx q[7], q[1], q[6]; +h q[0]; +cx q[8], q[1]; +h q[5]; +h q[2]; +h q[9]; +cx q[7], q[2]; +cx q[6], q[8]; +cx q[5], q[4]; +cx q[6], q[5]; +ccx q[8], q[2], q[3]; +t q[9]; +h q[3]; +ccx q[9], q[7], q[0]; +h q[4]; +cx q[3], q[4]; +h q[0]; +ccx q[8], q[1], q[4]; +s q[7]; +s q[5]; +ccx q[6], q[3], q[5]; +s q[1]; +ccx q[3], q[6], q[1]; +t q[7]; +ccx q[6], q[7], q[8]; +s q[4]; +ccx q[5], q[1], q[0]; +s q[6]; +ccx q[6], q[3], q[1]; +cx q[1], q[0]; +t q[4]; +t q[7]; +cx q[3], q[4]; +cx q[4], q[8]; +cx q[8], q[4]; +cx q[7], q[5]; +t q[4]; +cx q[7], q[9]; +cx q[1], q[8]; +t q[6]; +s q[9]; +cx q[9], q[1]; +ccx q[4], q[0], q[9]; +t q[5]; +h q[6]; +ccx q[5], q[4], q[9]; +s q[3]; +s q[4]; +h q[8]; +h q[3]; +ccx q[1], q[6], q[3]; +ccx q[9], q[7], q[0]; +cx q[3], q[5]; +ccx q[3], q[8], q[9]; +t q[0]; +ccx q[0], q[9], q[5]; +cx q[5], q[9]; +s q[2]; +h q[9]; +t q[2]; +h q[8]; +ccx q[5], q[1], q[6]; +cx q[9], q[5]; +h q[2]; +cx q[7], q[9]; +cx q[7], q[9]; +s q[5]; +cx q[5], q[8]; +ccx q[7], q[6], q[3]; +h q[6]; +s q[0]; +s q[3]; +ccx q[6], q[5], q[8]; +cx q[0], q[9]; +h q[2]; +t q[3]; +h q[9]; +s q[1]; +ccx q[5], q[2], q[4]; +h q[6]; +ccx q[6], q[1], q[5]; +s q[7]; +s q[2]; +cx q[7], q[5]; +h q[2]; +s q[9]; +cx q[2], q[8]; +cx q[1], q[6]; diff --git a/test/circuits/partialEquivalenceTest/random_2.qasm b/test/circuits/partialEquivalenceTest/random_2.qasm new file mode 100644 index 00000000..cb7d21c3 --- /dev/null +++ b/test/circuits/partialEquivalenceTest/random_2.qasm @@ -0,0 +1,532 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[10]; +h q[0]; +h q[1]; +h q[2]; +h q[3]; +h q[4]; +h q[5]; +h q[6]; +h q[7]; +h q[8]; +h q[9]; +h q[7]; +cx q[7], q[6]; +tdg q[6]; +cx q[0], q[6]; +t q[6]; +cx q[7], q[6]; +tdg q[6]; +cx q[0], q[6]; +t q[6]; +cx q[0], q[7]; +tdg q[7]; +cx q[0], q[7]; +t q[0]; +t q[7]; +h q[7]; +h q[7]; +cx q[7], q[3]; +tdg q[3]; +cx q[0], q[3]; +t q[3]; +cx q[7], q[3]; +tdg q[3]; +cx q[0], q[3]; +t q[3]; +cx q[0], q[7]; +tdg q[7]; +cx q[0], q[7]; +t q[0]; +t q[7]; +h q[7]; +cx q[4], q[2]; +h q[8]; +cx q[5], q[1]; +s q[5]; +h q[6]; +s q[9]; +t q[6]; +cx q[4], q[7]; +s q[4]; +t q[2]; +cx q[3], q[7]; +h q[9]; +cx q[9], q[0]; +tdg q[0]; +cx q[6], q[0]; +t q[0]; +cx q[9], q[0]; +tdg q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[9]; +tdg q[9]; +cx q[6], q[9]; +t q[6]; +t q[9]; +h q[9]; +h q[3]; +s q[3]; +t q[8]; +t q[3]; +t q[8]; +cx q[6], q[7]; +h q[9]; +t q[8]; +s q[3]; +cx q[3], q[0]; +h q[7]; +t q[9]; +h q[8]; +h q[2]; +cx q[9], q[5]; +h q[7]; +cx q[7], q[1]; +tdg q[1]; +cx q[2], q[1]; +t q[1]; +cx q[7], q[1]; +tdg q[1]; +cx q[2], q[1]; +t q[1]; +cx q[2], q[7]; +tdg q[7]; +cx q[2], q[7]; +t q[2]; +t q[7]; +h q[7]; +s q[3]; +t q[6]; +cx q[7], q[3]; +t q[2]; +h q[1]; +cx q[1], q[2]; +tdg q[2]; +cx q[8], q[2]; +t q[2]; +cx q[1], q[2]; +tdg q[2]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +t q[8]; +t q[1]; +h q[1]; +t q[7]; +t q[2]; +s q[2]; +cx q[5], q[6]; +s q[0]; +h q[3]; +cx q[3], q[5]; +tdg q[5]; +cx q[0], q[5]; +t q[5]; +cx q[3], q[5]; +tdg q[5]; +cx q[0], q[5]; +t q[5]; +cx q[0], q[3]; +tdg q[3]; +cx q[0], q[3]; +t q[0]; +t q[3]; +h q[3]; +h q[4]; +cx q[6], q[9]; +s q[6]; +cx q[3], q[8]; +t q[8]; +cx q[9], q[7]; +h q[2]; +cx q[7], q[6]; +s q[6]; +h q[8]; +cx q[8], q[5]; +tdg q[5]; +cx q[9], q[5]; +t q[5]; +cx q[8], q[5]; +tdg q[5]; +cx q[9], q[5]; +t q[5]; +cx q[9], q[8]; +tdg q[8]; +cx q[9], q[8]; +t q[9]; +t q[8]; +h q[8]; +cx q[7], q[2]; +h q[6]; +cx q[6], q[1]; +tdg q[1]; +cx q[7], q[1]; +t q[1]; +cx q[6], q[1]; +tdg q[1]; +cx q[7], q[1]; +t q[1]; +cx q[7], q[6]; +tdg q[6]; +cx q[7], q[6]; +t q[7]; +t q[6]; +h q[6]; +h q[0]; +cx q[8], q[1]; +h q[5]; +h q[2]; +h q[9]; +cx q[7], q[2]; +cx q[6], q[8]; +cx q[5], q[4]; +cx q[6], q[5]; +h q[3]; +cx q[3], q[2]; +tdg q[2]; +cx q[8], q[2]; +t q[2]; +cx q[3], q[2]; +tdg q[2]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[3]; +tdg q[3]; +cx q[8], q[3]; +t q[8]; +t q[3]; +h q[3]; +t q[9]; +h q[3]; +h q[0]; +cx q[0], q[7]; +tdg q[7]; +cx q[9], q[7]; +t q[7]; +cx q[0], q[7]; +tdg q[7]; +cx q[9], q[7]; +t q[7]; +cx q[9], q[0]; +tdg q[0]; +cx q[9], q[0]; +t q[9]; +t q[0]; +h q[0]; +h q[4]; +cx q[3], q[4]; +h q[0]; +h q[4]; +cx q[4], q[1]; +tdg q[1]; +cx q[8], q[1]; +t q[1]; +cx q[4], q[1]; +tdg q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[4]; +tdg q[4]; +cx q[8], q[4]; +t q[8]; +t q[4]; +h q[4]; +s q[7]; +s q[5]; +h q[5]; +cx q[5], q[3]; +tdg q[3]; +cx q[6], q[3]; +t q[3]; +cx q[5], q[3]; +tdg q[3]; +cx q[6], q[3]; +t q[3]; +cx q[6], q[5]; +tdg q[5]; +cx q[6], q[5]; +t q[6]; +t q[5]; +h q[5]; +s q[1]; +h q[1]; +cx q[1], q[6]; +tdg q[6]; +cx q[3], q[6]; +t q[6]; +cx q[1], q[6]; +tdg q[6]; +cx q[3], q[6]; +t q[6]; +cx q[3], q[1]; +tdg q[1]; +cx q[3], q[1]; +t q[3]; +t q[1]; +h q[1]; +t q[7]; +h q[8]; +cx q[8], q[7]; +tdg q[7]; +cx q[6], q[7]; +t q[7]; +cx q[8], q[7]; +tdg q[7]; +cx q[6], q[7]; +t q[7]; +cx q[6], q[8]; +tdg q[8]; +cx q[6], q[8]; +t q[6]; +t q[8]; +h q[8]; +s q[4]; +h q[0]; +cx q[0], q[1]; +tdg q[1]; +cx q[5], q[1]; +t q[1]; +cx q[0], q[1]; +tdg q[1]; +cx q[5], q[1]; +t q[1]; +cx q[5], q[0]; +tdg q[0]; +cx q[5], q[0]; +t q[5]; +t q[0]; +h q[0]; +s q[6]; +h q[1]; +cx q[1], q[3]; +tdg q[3]; +cx q[6], q[3]; +t q[3]; +cx q[1], q[3]; +tdg q[3]; +cx q[6], q[3]; +t q[3]; +cx q[6], q[1]; +tdg q[1]; +cx q[6], q[1]; +t q[6]; +t q[1]; +h q[1]; +cx q[1], q[0]; +t q[4]; +t q[7]; +cx q[3], q[4]; +cx q[4], q[8]; +cx q[8], q[4]; +cx q[7], q[5]; +t q[4]; +cx q[7], q[9]; +cx q[1], q[8]; +t q[6]; +s q[9]; +cx q[9], q[1]; +h q[9]; +cx q[9], q[0]; +tdg q[0]; +cx q[4], q[0]; +t q[0]; +cx q[9], q[0]; +tdg q[0]; +cx q[4], q[0]; +t q[0]; +cx q[4], q[9]; +tdg q[9]; +cx q[4], q[9]; +t q[4]; +t q[9]; +h q[9]; +t q[5]; +h q[6]; +h q[9]; +cx q[9], q[4]; +tdg q[4]; +cx q[5], q[4]; +t q[4]; +cx q[9], q[4]; +tdg q[4]; +cx q[5], q[4]; +t q[4]; +cx q[5], q[9]; +tdg q[9]; +cx q[5], q[9]; +t q[5]; +t q[9]; +h q[9]; +s q[3]; +s q[4]; +h q[8]; +h q[3]; +h q[3]; +cx q[3], q[6]; +tdg q[6]; +cx q[1], q[6]; +t q[6]; +cx q[3], q[6]; +tdg q[6]; +cx q[1], q[6]; +t q[6]; +cx q[1], q[3]; +tdg q[3]; +cx q[1], q[3]; +t q[1]; +t q[3]; +h q[3]; +h q[0]; +cx q[0], q[7]; +tdg q[7]; +cx q[9], q[7]; +t q[7]; +cx q[0], q[7]; +tdg q[7]; +cx q[9], q[7]; +t q[7]; +cx q[9], q[0]; +tdg q[0]; +cx q[9], q[0]; +t q[9]; +t q[0]; +h q[0]; +cx q[3], q[5]; +h q[9]; +cx q[9], q[8]; +tdg q[8]; +cx q[3], q[8]; +t q[8]; +cx q[9], q[8]; +tdg q[8]; +cx q[3], q[8]; +t q[8]; +cx q[3], q[9]; +tdg q[9]; +cx q[3], q[9]; +t q[3]; +t q[9]; +h q[9]; +t q[0]; +h q[5]; +cx q[5], q[9]; +tdg q[9]; +cx q[0], q[9]; +t q[9]; +cx q[5], q[9]; +tdg q[9]; +cx q[0], q[9]; +t q[9]; +cx q[0], q[5]; +tdg q[5]; +cx q[0], q[5]; +t q[0]; +t q[5]; +h q[5]; +cx q[5], q[9]; +s q[2]; +h q[9]; +t q[2]; +h q[8]; +h q[6]; +cx q[6], q[1]; +tdg q[1]; +cx q[5], q[1]; +t q[1]; +cx q[6], q[1]; +tdg q[1]; +cx q[5], q[1]; +t q[1]; +cx q[5], q[6]; +tdg q[6]; +cx q[5], q[6]; +t q[5]; +t q[6]; +h q[6]; +cx q[9], q[5]; +h q[2]; +cx q[7], q[9]; +cx q[7], q[9]; +s q[5]; +cx q[5], q[8]; +h q[3]; +cx q[3], q[6]; +tdg q[6]; +cx q[7], q[6]; +t q[6]; +cx q[3], q[6]; +tdg q[6]; +cx q[7], q[6]; +t q[6]; +cx q[7], q[3]; +tdg q[3]; +cx q[7], q[3]; +t q[7]; +t q[3]; +h q[3]; +h q[6]; +s q[0]; +s q[3]; +h q[8]; +cx q[8], q[5]; +tdg q[5]; +cx q[6], q[5]; +t q[5]; +cx q[8], q[5]; +tdg q[5]; +cx q[6], q[5]; +t q[5]; +cx q[6], q[8]; +tdg q[8]; +cx q[6], q[8]; +t q[6]; +t q[8]; +h q[8]; +cx q[0], q[9]; +h q[2]; +t q[3]; +h q[9]; +s q[1]; +h q[4]; +cx q[4], q[2]; +tdg q[2]; +cx q[5], q[2]; +t q[2]; +cx q[4], q[2]; +tdg q[2]; +cx q[5], q[2]; +t q[2]; +cx q[5], q[4]; +tdg q[4]; +cx q[5], q[4]; +t q[5]; +t q[4]; +h q[4]; +h q[6]; +h q[5]; +cx q[5], q[1]; +tdg q[1]; +cx q[6], q[1]; +t q[1]; +cx q[5], q[1]; +tdg q[1]; +cx q[6], q[1]; +t q[1]; +cx q[6], q[5]; +tdg q[5]; +cx q[6], q[5]; +t q[6]; +t q[5]; +h q[5]; +s q[7]; +s q[2]; +cx q[7], q[5]; +h q[2]; +s q[9]; +cx q[2], q[8]; +cx q[1], q[6]; From 3dff3786e5b24e4be51fac51def1e14693cc48a9 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 25 Feb 2024 11:53:55 +0100 Subject: [PATCH 03/41] =?UTF-8?q?=E2=9C=A8=20added=20functions=20and=20tes?= =?UTF-8?q?ts=20for=20partial=20equivalence=20checking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/checker/dd/DDPartialEquivalence.hpp | 166 +++++++++ src/CMakeLists.txt | 1 + src/checker/dd/DDPartialEquivalence.cpp | 334 +++++++++++++++++ test/test_partial_equivalence.cpp | 382 ++++++++++++++++++++ 4 files changed, 883 insertions(+) create mode 100644 include/checker/dd/DDPartialEquivalence.hpp create mode 100644 src/checker/dd/DDPartialEquivalence.cpp diff --git a/include/checker/dd/DDPartialEquivalence.hpp b/include/checker/dd/DDPartialEquivalence.hpp new file mode 100644 index 00000000..fbdcb354 --- /dev/null +++ b/include/checker/dd/DDPartialEquivalence.hpp @@ -0,0 +1,166 @@ +#include "dd/FunctionalityConstruction.hpp" +#include "dd/Package.hpp" + +namespace dd { + +template +mEdge partialEquivalenceCheckDDSubroutine(mEdge u, const Qubit m, const Qubit k, + const Qubit extra, + Package& dd) { + // add extra ancillary qubits + if (extra > 0) { + if (u.p->v + 1U + extra > dd.qubits()) { + dd.resize(u.p->v + 1U + extra); + } + u = dd.kronecker(dd.makeIdent(extra), u); + } + if (u.isTerminal()) { + return u; + } + const Qubit n = u.p->v + 1; + const Qubit d = n - k; + u = dd.setColumnsToZero(u, d); + const auto u2 = dd.shiftAllRows(u, m, d); + return dd.multiply(dd.conjugateTranspose(u), u2); +} + +/** + Checks for partial equivalence between the two circuits u1 and u2, + where the first d qubits of the circuits are the data qubits and + the first m qubits are the measured qubits. + @param u1 DD representation of first circuit + @param u2 DD representation of second circuit + @param d Number of data qubits + @param m Number of measured qubits + @return true if the two circuits u1 and u2 are partially equivalent. + **/ +template +bool partialEquivalenceCheckDD(mEdge u1, mEdge u2, const Qubit d, const Qubit m, + Package& dd) { + if (m == 0) { + return true; + } + if (u1.isTerminal() && u2.isTerminal()) { + return u1 == u2; + } + if (u1.isZeroTerminal() || u2.isZeroTerminal()) { + return false; + } + // add qubits such that u1 and u2 have the same dimension + if (u1.isTerminal()) { + auto w = u1.w; + u1 = dd.makeIdent(u2.p->v + 1); + u1.w = w; + } else if (u2.isTerminal()) { + auto w = u2.w; + u2 = dd.makeIdent(u1.p->v + 1); + u2.w = w; + } else if (u1.p->v < u2.p->v) { + u1 = dd.kronecker(dd.makeIdent(u2.p->v - u1.p->v), u1); + } else if (u1.p->v > u2.p->v) { + u2 = dd.kronecker(dd.makeIdent(u1.p->v - u2.p->v), u2); + } + + const Qubit n = u1.p->v + 1; + Qubit k = n - d; + Qubit extra{0}; + if (m > k) { + extra = m - k; + } + k = k + extra; + + const auto u1Prime = partialEquivalenceCheckDDSubroutine(u1, m, k, extra, dd); + const auto u2Prime = partialEquivalenceCheckDDSubroutine(u2, m, k, extra, dd); + + return u1Prime == u2Prime; +} + +/** + Checks for partial equivalence between the two circuits c1 and c2 + that have no ancilla qubits. + Assumption: the input and output permutations are the same. + + @param circuit1 First circuit + @param circuit2 Second circuit + @return true if the two circuits c1 and c2 are partially equivalent. + **/ +template +bool zeroAncillaePartialEquivalenceCheck(qc::QuantumComputation c1, + qc::QuantumComputation c2, + Package& dd) { + if (c1.getNqubits() != c2.getNqubits() || + c1.getGarbage() != c2.getGarbage()) { + throw std::invalid_argument( + "The circuits need to have the same number of qubits and the same " + "permutation of input and output qubits."); + } + c2.invert(); + for (auto& gate : c1) { + c2.emplace_back(gate); + } + + const auto u = buildFunctionality(&c2, dd, false, false); + + return dd.isCloseToIdentity(u, 1.0E-10, c1.getGarbage(), false); +} + +// get next garbage qubit after n +inline Qubit getNextGarbage(Qubit n, const std::vector& garbage) { + while (n < static_cast(garbage.size()) && !garbage.at(n)) { + n++; + } + return n; +} +/** + Checks for partial equivalence between the two circuits c1 and c2. + Assumption: the data qubits are all at the beginning of the input qubits and + the input and output permutations are the same. + + @param circuit1 First circuit + @param circuit2 Second circuit + @return true if the two circuits c1 and c2 are partially equivalent. + **/ +template +bool partialEquivalenceCheck(qc::QuantumComputation c1, + qc::QuantumComputation c2, Package& dd) { + const auto d1 = c1.getNqubitsWithoutAncillae(); + const auto d2 = c2.getNqubitsWithoutAncillae(); + const auto m1 = c1.getNmeasuredQubits(); + const auto m2 = c2.getNmeasuredQubits(); + if (m1 != m2 || d1 != d2) { + return false; + } + const auto n1 = static_cast(c1.getNqubits()); + const auto n2 = static_cast(c2.getNqubits()); + if (d1 == n1 && d2 == n2) { + // no ancilla qubits + return zeroAncillaePartialEquivalenceCheck(c1, c2, dd); + } + // add swaps in order to put the measured (= not garbage) qubits in the end + const auto garbage1 = c1.getGarbage(); + + auto nextGarbage = getNextGarbage(0, garbage1); + // find the first garbage qubit at the end + for (std::int64_t i = std::min(n1, n2) - 1; + i >= static_cast(m1); i--) { + if (!garbage1.at(static_cast(i))) { + // swap it to the beginning + c1.swap(static_cast(i), nextGarbage); + c2.swap(static_cast(i), nextGarbage); + ++nextGarbage; + nextGarbage = getNextGarbage(nextGarbage, garbage1); + } + } + + // partialEquivalenceCheck with dd + + const auto u1 = buildFunctionality(&c1, dd, false, false); + const auto u2 = buildFunctionality(&c2, dd, false, false); + + return partialEquivalenceCheckDD(u1, u2, static_cast(d1), + static_cast(m1), dd); +} + +std::pair +generateRandomBenchmark(size_t n, qc::Qubit d, qc::Qubit m); +} // namespace dd diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c929aedd..5e3827ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ add_library( checker/dd/DDConstructionChecker.cpp checker/dd/DDSimulationChecker.cpp checker/dd/DDAlternatingChecker.cpp + checker/dd/DDPartialEquivalence.cpp checker/dd/applicationscheme/GateCostApplicationScheme.cpp checker/dd/simulation/StateGenerator.cpp checker/zx/ZXChecker.cpp) diff --git a/src/checker/dd/DDPartialEquivalence.cpp b/src/checker/dd/DDPartialEquivalence.cpp new file mode 100644 index 00000000..fff3d02b --- /dev/null +++ b/src/checker/dd/DDPartialEquivalence.cpp @@ -0,0 +1,334 @@ +#include "checker/dd/DDPartialEquivalence.hpp" + +#include "QuantumComputation.hpp" +#include "operations/OpType.hpp" +#include "operations/StandardOperation.hpp" + +namespace dd { + +const std::vector> PRE_GENERATED_CIRCUITS_SIZE_1_1{ + {}, {}, {}, {}}; + +const std::vector> PRE_GENERATED_CIRCUITS_SIZE_1_2{ + {Z}, {Tdg}, {S}, {Sdg}}; + +const std::vector> PRE_GENERATED_CIRCUITS_SIZE_2_1{ + {}, {}, {}, {}, {X}, {X}}; + +const std::vector> PRE_GENERATED_CIRCUITS_SIZE_2_2{ + {Z}, {Tdg}, {S}, {Sdg}, {X, Z}, {Z, X}}; + +void addPreGeneratedCircuits(QuantumComputation& circuit1, + QuantumComputation& circuit2, const size_t n, + const qc::Qubit groupBeginIndex, + const qc::Qubit groupSize) { + const auto& circuits1 = groupSize == 1 ? PRE_GENERATED_CIRCUITS_SIZE_1_1 + : PRE_GENERATED_CIRCUITS_SIZE_2_1; + const auto& circuits2 = groupSize == 1 ? PRE_GENERATED_CIRCUITS_SIZE_1_2 + : PRE_GENERATED_CIRCUITS_SIZE_2_2; + const auto nrCircuits = circuits1.size(); + auto randomGenerator = circuit1.getGenerator(); + std::uniform_int_distribution randomDistribution(0, nrCircuits - 1); + + const auto randomIndex = randomDistribution(randomGenerator); + const auto x1 = circuits1[randomIndex]; + const auto x2 = circuits2[randomIndex]; + for (auto gateType : x1) { + if (gateType == X) { // add CNOT + circuit1.emplace_back(n, groupBeginIndex, + groupBeginIndex + 1, gateType); + } else { + circuit1.emplace_back(n, groupBeginIndex, gateType); + } + } + for (auto gateType : x2) { + if (gateType == X) { // add CNOT + circuit2.emplace_back(n, groupBeginIndex, + groupBeginIndex + 1, gateType); + } else { + circuit2.emplace_back(n, groupBeginIndex, gateType); + } + } +} + +void addDecomposedCcxGate(QuantumComputation& circuit, const Controls& controls, + const qc::Qubit target) { + const qc::Qubit control1 = controls.begin()->qubit; + const qc::Qubit control2 = (++controls.begin())->qubit; + circuit.h(target); + circuit.cx(control1, target); + circuit.tdg(target); + circuit.cx(control2, target); + circuit.t(target); + circuit.cx(control1, target); + circuit.tdg(target); + circuit.cx(control2, target); + circuit.t(target); + circuit.t(control1); + circuit.h(target); + circuit.cx(control2, control1); + circuit.t(control2); + circuit.tdg(control1); + circuit.cx(control2, control1); +} + +void addStandardOperationToCircuit(QuantumComputation& circuit, + const StandardOperation& op, + const bool decomposeCcx) { + if (op.getType() == X && decomposeCcx && op.getControls().size() == 2) { + // decompose toffoli gate + addDecomposedCcxGate(circuit, op.getControls(), op.getTargets()[0]); + } else { + circuit.emplace_back(op); + } +} + +std::vector +fiveDiffferentRandomNumbers(const qc::Qubit min, const qc::Qubit max, + std::mt19937_64 randomGenerator) { + std::vector numbers; + + for (qc::Qubit i = min; i < max; i++) { + numbers.emplace_back(i); + } + std::shuffle(numbers.begin(), numbers.end(), randomGenerator); + + const int64_t lengthOutputVector{ + static_cast(std::min(5UL, numbers.size()))}; + + std::vector outputVector(numbers.begin(), + numbers.begin() + lengthOutputVector); + return outputVector; +} + +StandardOperation convertToStandardOperation( + const size_t n, const size_t nrQubits, const OpType randomOpType, + const qc::Qubit randomTarget1, const qc::Qubit randomTarget2, + const fp randomParameter1, const fp randomParameter2, + const fp randomParameter3, const Controls& randomControls) { + switch (randomOpType) { + // two targets and zero parameters + case qc::SWAP: + case qc::iSWAP: + case qc::iSWAPdg: + case qc::Peres: + case qc::Peresdg: + case qc::DCX: + case qc::ECR: + if (nrQubits > 1) { + return {n, randomControls, Targets{randomTarget1, randomTarget2}, + randomOpType}; + } + break; + + // two targets and one parameter + case qc::RXX: + case qc::RYY: + case qc::RZZ: + case qc::RZX: + if (nrQubits > 1) { + return {n, randomControls, Targets{randomTarget1, randomTarget2}, + randomOpType, std::vector{randomParameter1}}; + } + break; + + // two targets and two parameters + case qc::XXminusYY: + case qc::XXplusYY: + if (nrQubits > 1) { + return {n, randomControls, Targets{randomTarget1, randomTarget2}, + randomOpType, + std::vector{randomParameter1, randomParameter2}}; + } + break; + + // one target and zero parameters + case qc::I: + case qc::H: + case qc::X: + case qc::Y: + case qc::Z: + case qc::S: + case qc::Sdg: + case qc::T: + case qc::Tdg: + case qc::V: + case qc::Vdg: + case qc::SX: + case qc::SXdg: + return {n, randomControls, randomTarget1, randomOpType}; + // one target and three parameters + case qc::U: + return { + n, randomControls, randomTarget1, randomOpType, + std::vector{randomParameter1, randomParameter2, randomParameter3}}; + // one target and two parameters + case qc::U2: + return {n, randomControls, randomTarget1, randomOpType, + std::vector{randomParameter1, randomParameter2}}; + // one target and one parameter + case qc::P: + case qc::RX: + case qc::RY: + case qc::RZ: + return {n, randomControls, randomTarget1, randomOpType, + std::vector{randomParameter1}}; + default: + return {n, randomTarget1, qc::I}; + } + return {n, randomTarget1, qc::I}; +} + +StandardOperation makeRandomStandardOperation(const size_t n, + const qc::Qubit nrQubits, + const qc::Qubit min, + std::mt19937_64 randomGenerator) { + const auto randomNumbers = + fiveDiffferentRandomNumbers(min, min + nrQubits, randomGenerator); + + // choose one of the non-compound operations, but not "None", and also + // not GPhase or I or Barrier + std::uniform_int_distribution<> randomDistrOpType(H, RZX); + auto randomOpType = static_cast(randomDistrOpType(randomGenerator)); + const qc::Qubit randomTarget1 = randomNumbers[0]; + qc::Qubit randomTarget2{min}; + if (randomNumbers.size() > 1) { + randomTarget2 = randomNumbers[1]; + }; + // choose random controls, but not more than available qubits + std::uniform_int_distribution randomDistrNrControls(0, 2); + size_t nrControls = std::min(randomNumbers.size() - 3, + randomDistrNrControls(randomGenerator)); + if (randomNumbers.size() < 3) { + nrControls = 0; + } + if (nrControls == 2) { + // otherwise toffoli gates are almost never generated + randomOpType = qc::X; + } + Controls randomControls{}; + for (size_t i = 0; i < nrControls; i++) { + randomControls.emplace(randomNumbers[i + 2]); + } + std::uniform_real_distribution randomDistrParameters(0, 2 * PI); + const fp randomParameter1 = randomDistrParameters(randomGenerator); + const fp randomParameter2 = randomDistrParameters(randomGenerator); + const fp randomParameter3 = randomDistrParameters(randomGenerator); + // const std::vector randomParameters{PI, PI_2, PI_4}; + // const fp randomParameter1 = + // randomParameters[static_cast(rand()) % + // randomParameters.size()]; + // const fp randomParameter2 = + // randomParameters[static_cast(rand()) % + // randomParameters.size()]; + // const fp randomParameter3 = + // randomParameters[static_cast(rand()) % + // randomParameters.size()]; + return convertToStandardOperation( + n, nrQubits, randomOpType, randomTarget1, randomTarget2, randomParameter1, + randomParameter2, randomParameter3, randomControls); +} + +std::pair +generateRandomBenchmark(const size_t n, const qc::Qubit d, const qc::Qubit m) { + if (d > n || m > n) { + throw std::runtime_error("The number of data or measured qubits can't be " + "bigger than the total number of qubits. n = " + + std::to_string(n) + "; d = " + std::to_string(d) + + "; m = " + std::to_string(m)); + } + + qc::QuantumComputation circuit1{n}; + qc::QuantumComputation circuit2{n}; + + auto randomGenerator = circuit1.getGenerator(); + + // 1) H gates + for (qc::Qubit i = 0U; i < d; i++) { + circuit1.h(i); + circuit2.h(i); + } + + circuit1.barrier(); + circuit2.barrier(); + + // 2) Totally equivalent subcircuits + // Generate a random subcircuit with d qubits and 3*d gates to apply + // on both circuits, but all the Toffoli gates in circuit2 are decomposed + for (qc::Qubit i = 0U; i < 3 * d; i++) { + const auto op = makeRandomStandardOperation(n, d, 0, randomGenerator); + addStandardOperationToCircuit(circuit1, op, false); + addStandardOperationToCircuit(circuit2, op, true); + } + + circuit1.barrier(); + circuit2.barrier(); + + // 3) Partially equivalent subcircuits + // Divide data qubits into groups of size 1 or 2. For each group, we apply + // pre-generated subcircuits, which are pairwise partially equivalent. + qc::Qubit groupBeginIndex = 0; + std::uniform_int_distribution randomDistrGroupSize(1, 2); + while (groupBeginIndex < d) { + qc::Qubit groupSize = 1; + if (groupBeginIndex < d - 1) { + groupSize = randomDistrGroupSize(randomGenerator); + } + + addPreGeneratedCircuits(circuit1, circuit2, n, groupBeginIndex, groupSize); + + groupBeginIndex += groupSize; + } + + circuit1.barrier(); + circuit2.barrier(); + + // 4) Arbitrary gates + // Arbitrary gates are added to data qubits that are not measured + if (d > m) { + const qc::Qubit notMQubits = d - m; + for (qc::Qubit i = 0U; i < notMQubits; i++) { + addStandardOperationToCircuit( + circuit1, + makeRandomStandardOperation(n, notMQubits, m, randomGenerator), + false); + addStandardOperationToCircuit( + circuit2, + makeRandomStandardOperation(n, notMQubits, m, randomGenerator), + false); + } + } + + circuit1.barrier(); + circuit2.barrier(); + + // 5) CNOT gates + // For each ancilla qubit, add a CNOT that has the ancilla as control qubit, + // and any data qubit as target. As ancilla qubits are initially set to 0 and + // we haven't added any other gates to the ancilla qubits until now, these + // CNOT gates do not affect the circuit. + if (d > 0) { + qc::Qubit currentDataQubit = 0; + for (qc::Qubit currentAncillaQubit = d; currentAncillaQubit < n; + currentAncillaQubit++) { + auto nextDataQubit = (currentDataQubit + 1) % d; + circuit1.cx(currentAncillaQubit, currentDataQubit); + circuit2.cx(currentAncillaQubit, nextDataQubit); + currentDataQubit = nextDataQubit; + } + } + + for (qc::Qubit i = d; i < n; i++) { + circuit1.setLogicalQubitAncillary(i); + circuit2.setLogicalQubitAncillary(i); + } + + for (qc::Qubit i = m; i < n; i++) { + circuit1.setLogicalQubitGarbage(i); + circuit2.setLogicalQubitGarbage(i); + } + + return std::make_pair(circuit1, circuit2); +} + +} // namespace dd diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index 626636f3..d050242b 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -4,8 +4,12 @@ // #include "EquivalenceCheckingManager.hpp" +#include "checker/dd/DDPartialEquivalence.hpp" +#include "dd/Package.hpp" #include "gtest/gtest.h" +#include +#include class PartialEqualityTest : public testing::Test { void SetUp() override { @@ -138,3 +142,381 @@ TEST_F(PartialEqualityTest, AlternatingCheckerGarbageNotEquivalent) { ecm.run(); EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } + +using namespace qc::literals; + +TEST(PartialEquivalenceTest, TrivialEquivalence) { + const auto nqubits = 2U; + const auto dd = std::make_unique>(nqubits); + const auto inputMatrix = + dd::CMat{{1, 1, 1, 1}, {1, -1, 1, -1}, {1, 1, -1, -1}, {1, -1, -1, 1}}; + const auto inputDD = dd->makeDDFromMatrix(inputMatrix); + + EXPECT_TRUE(partialEquivalenceCheckDD(inputDD, inputDD, 1, 1, *dd)); + EXPECT_TRUE(partialEquivalenceCheckDD(inputDD, inputDD, 2, 1, *dd)); + EXPECT_TRUE(partialEquivalenceCheckDD(inputDD, inputDD, 1, 2, *dd)); + EXPECT_TRUE(partialEquivalenceCheckDD(inputDD, inputDD, 2, 2, *dd)); + + const auto hGate = dd->makeGateDD(dd::H_MAT, 2, 1); + const auto cxGate = dd->makeGateDD(dd::X_MAT, 2, 1_pc, 0); + const auto bellMatrix = dd->multiply(cxGate, hGate); + EXPECT_FALSE(partialEquivalenceCheckDD(inputDD, bellMatrix, 1, 1, *dd)); +} + +TEST(PartialEquivalenceTest, BasicPartialEquivalenceChecking) { + const auto nqubits = 3U; + auto dd = std::make_unique>(nqubits); + // only the second qubit has differing gates in the two circuits, + // therefore they should be equivalent if we only measure the first qubit + const auto hGate = dd->makeGateDD(dd::H_MAT, 3, 1); + const auto xGate = dd->makeGateDD(dd::X_MAT, 3, 1); + const auto circuit1 = dd->multiply(xGate, hGate); + const auto circuit2 = dd->makeIdent(3); + + EXPECT_TRUE(partialEquivalenceCheckDD(circuit1, circuit2, 2, 1, *dd)); +} + +TEST(PartialEquivalenceTest, NotEquivalent) { + const auto nqubits = 2U; + const auto dd = std::make_unique>(nqubits); + // the first qubit has differing gates in the two circuits, + // therefore they should not be equivalent if we only measure the first qubit + const auto hGate = dd->makeGateDD(dd::H_MAT, nqubits, 0); + const auto xGate = dd->makeGateDD(dd::X_MAT, nqubits, 0); + const auto circuit1 = dd->multiply(xGate, hGate); + const auto circuit2 = dd->makeIdent(2); + EXPECT_FALSE(partialEquivalenceCheckDD(circuit1, circuit2, 2, 1, *dd)); +} + +TEST(PartialEquivalenceTest, ExamplePaper) { + const auto nqubits = 3U; + const auto dd = std::make_unique>(nqubits); + const auto controlledSwapGate = + dd->makeTwoQubitGateDD(dd::SWAP_MAT, nqubits, qc::Controls{1}, 0, 2); + const auto hGate = dd->makeGateDD(dd::H_MAT, nqubits, 0); + const auto zGate = dd->makeGateDD(dd::Z_MAT, nqubits, 2); + const auto xGate = dd->makeGateDD(dd::X_MAT, nqubits, 1); + const auto controlledHGate = + dd->makeGateDD(dd::H_MAT, nqubits, qc::Controls{1}, 0); + + const auto c1 = dd->multiply( + controlledSwapGate, + dd->multiply(hGate, dd->multiply(zGate, controlledSwapGate))); + const auto c2 = dd->multiply(controlledHGate, xGate); + + EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); +} + +TEST(PartialEquivalenceTest, DifferentNumberOfQubits) { + const auto nqubits = 3U; + const auto dd = std::make_unique>(nqubits); + const auto controlledSwapGate = + dd->makeTwoQubitGateDD(dd::SWAP_MAT, nqubits, qc::Controls{1}, 0, 2); + const auto hGate = dd->makeGateDD(dd::H_MAT, nqubits, 0); + const auto zGate = dd->makeGateDD(dd::Z_MAT, nqubits, 2); + const auto xGate = dd->makeGateDD(dd::X_MAT, 2, 1); + const auto controlledHGate = dd->makeGateDD(dd::H_MAT, 2, qc::Controls{1}, 0); + + const auto c1 = dd->multiply( + controlledSwapGate, + dd->multiply(hGate, dd->multiply(zGate, controlledSwapGate))); + const auto c2 = dd->multiply(controlledHGate, xGate); + + EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); + EXPECT_FALSE(partialEquivalenceCheckDD(c2, c1, 3, 3, *dd)); + EXPECT_FALSE(partialEquivalenceCheckDD(c2, dd::mEdge::zero(), 2, 1, *dd)); + EXPECT_FALSE(partialEquivalenceCheckDD(c2, dd::mEdge::one(), 2, 1, *dd)); + EXPECT_FALSE(partialEquivalenceCheckDD(dd::mEdge::one(), c1, 2, 1, *dd)); + EXPECT_TRUE( + partialEquivalenceCheckDD(dd::mEdge::one(), dd::mEdge::one(), 0, 1, *dd)); + EXPECT_TRUE( + partialEquivalenceCheckDD(dd::mEdge::one(), dd::mEdge::one(), 0, 0, *dd)); +} + +TEST(PartialEquivalenceTest, ComputeTableTest) { + const auto nqubits = 3U; + const auto dd = std::make_unique>(nqubits); + const auto controlledSwapGate = + dd->makeTwoQubitGateDD(dd::SWAP_MAT, nqubits, qc::Controls{1}, 2, 0); + const auto hGate = dd->makeGateDD(dd::H_MAT, nqubits, 0); + const auto zGate = dd->makeGateDD(dd::Z_MAT, nqubits, 2); + const auto xGate = dd->makeGateDD(dd::X_MAT, nqubits, 1); + const auto controlledHGate = + dd->makeGateDD(dd::H_MAT, nqubits, qc::Controls{1}, 0); + + const auto c1 = dd->multiply( + controlledSwapGate, + dd->multiply(hGate, dd->multiply(zGate, controlledSwapGate))); + const auto c2 = dd->multiply(controlledHGate, xGate); + + EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); + EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); + EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); + EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); + EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); +} + +TEST(PartialEquivalenceTest, MQTBenchGrover3Qubits) { + const auto dd = std::make_unique>(3); + + const qc::QuantumComputation c1{ + "./circuits/partialEquivalenceTest/" + "grover-noancilla_nativegates_ibm_qiskit_opt0_3.qasm"}; + const qc::QuantumComputation c2{ + "./circuits/partialEquivalenceTest/grover-noancilla_indep_qiskit_3.qasm"}; + + // 3 measured qubits and 3 data qubits, full equivalence + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); +} + +TEST(PartialEquivalenceTest, MQTBenchGrover7Qubits) { + const auto dd = std::make_unique>(7); + + const qc::QuantumComputation c1{ + "./circuits/partialEquivalenceTest/" + "grover-noancilla_nativegates_ibm_qiskit_opt0_7.qasm"}; + const qc::QuantumComputation c2{ + "./circuits/partialEquivalenceTest/" + "grover-noancilla_nativegates_ibm_qiskit_opt1_7.qasm"}; + + // 7 measured qubits and 7 data qubits, full equivalence + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); +} + +TEST(PartialEquivalenceTest, SliQECGrover22Qubits) { + const auto dd = std::make_unique>(12); + + const qc::QuantumComputation c1{ + "./circuits/partialEquivalenceTest/Grover_1.qasm"}; // 11 qubits, 11 data + // qubits + qc::QuantumComputation c2{ + "./circuits/partialEquivalenceTest/Grover_2.qasm"}; // 12 qubits, 11 data + // qubits + + // 11 measured qubits and 11 data qubits + c2.setLogicalQubitAncillary(11); + c2.setLogicalQubitGarbage(11); + + // adds 10 ancillary qubits -> total number of qubits is 22 + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); +} + +TEST(PartialEquivalenceTest, SliQECAdd19Qubits) { + const auto dd = std::make_unique>(19); + + // full equivalence, 19 qubits + // but this test uses algorithm for partial equivalence, not the "zero + // ancillae" version + qc::QuantumComputation c1{ + "./circuits/partialEquivalenceTest/add6_196_1.qasm"}; + qc::QuantumComputation c2{ + "./circuits/partialEquivalenceTest/add6_196_2.qasm"}; + + // just for benchmarking reasons, we only measure 8 qubits + c1.setLogicalQubitsAncillary(8, 18); + c2.setLogicalQubitsAncillary(8, 18); + c1.setLogicalQubitsGarbage(8, 18); + c2.setLogicalQubitsGarbage(8, 18); + + // doesn't add ancillary qubits -> total number of qubits is 19 + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); +} + +TEST(PartialEquivalenceTest, ExamplePaperDifferentQubitOrder) { + const auto nqubits = 3U; + auto dd = std::make_unique>(nqubits); + + qc::QuantumComputation c1{nqubits, 1}; + c1.cswap(1, 2, 0); + c1.h(2); + c1.z(0); + c1.cswap(1, 2, 0); + + qc::QuantumComputation c2{nqubits, 1}; + c2.x(1); + c2.ch(1, 2); + + c1.setLogicalQubitsGarbage(0, 1); + c2.setLogicalQubitsGarbage(0, 1); + + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); +} + +TEST(PartialEquivalenceTest, ExamplePaperDifferentQubitOrderAndNumber) { + const auto nqubits = 4U; + auto dd = std::make_unique>(nqubits); + + qc::QuantumComputation c1{nqubits, 1}; + c1.cswap(1, 2, 0); + c1.h(2); + c1.z(0); + c1.cswap(1, 2, 0); + + qc::QuantumComputation c2{3, 1}; + c2.x(1); + c2.ch(1, 2); + + c1.setLogicalQubitsGarbage(0, 1); + c1.setLogicalQubitGarbage(3); + c1.setLogicalQubitAncillary(3); + + c2.setLogicalQubitsGarbage(0, 1); + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + EXPECT_TRUE(partialEquivalenceCheck(c2, c1, *dd)); +} + +TEST(PartialEquivalenceTest, ZeroAncillaSliQEC19Qubits) { + auto dd = std::make_unique>(19); + + // full equivalence, 10 qubits + const qc::QuantumComputation c1{ + "./circuits/partialEquivalenceTest/entanglement_1.qasm"}; + const qc::QuantumComputation c2{ + "./circuits/partialEquivalenceTest/entanglement_2.qasm"}; + + // calls zeroAncillaePartialEquivalenceCheck + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + + // full equivalence, 19 qubits + const qc::QuantumComputation c3{ + "./circuits/partialEquivalenceTest/add6_196_1.qasm"}; + const qc::QuantumComputation c4{ + "./circuits/partialEquivalenceTest/add6_196_2.qasm"}; + + // calls zeroAncillaePartialEquivalenceCheck + EXPECT_TRUE(partialEquivalenceCheck(c3, c4, *dd)); + + // full equivalence, 10 qubits + const qc::QuantumComputation c5{ + "./circuits/partialEquivalenceTest/bv_1.qasm"}; + const qc::QuantumComputation c6{ + "./circuits/partialEquivalenceTest/bv_2.qasm"}; + + // calls zeroAncillaePartialEquivalenceCheck + EXPECT_TRUE(partialEquivalenceCheck(c5, c6, *dd)); +} + +TEST(PartialEquivalenceTest, ZeroAncillaSliQECRandomCircuit) { + auto dd = std::make_unique>(10); + // full equivalence, 10 qubits + const qc::QuantumComputation c1{ + "./circuits/partialEquivalenceTest/random_1.qasm"}; + const qc::QuantumComputation c2{ + "./circuits/partialEquivalenceTest/random_2.qasm"}; + + // calls buildFunctionality for c2^(-1) concatenated with c1 + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); +} + +TEST(PartialEquivalenceTest, SliQECPeriodFinding8Qubits) { + auto dd = std::make_unique>(8); + // 8 qubits, 3 data qubits + qc::QuantumComputation c1{ + "./circuits/partialEquivalenceTest/period_finding_1.qasm"}; + // 8 qubits, 3 data qubits + qc::QuantumComputation c2{ + "./circuits/partialEquivalenceTest/period_finding_2.qasm"}; + + // 3 measured qubits and 3 data qubits + + c2.setLogicalQubitsAncillary(3, 7); + c2.setLogicalQubitsGarbage(3, 7); + + c1.setLogicalQubitsAncillary(3, 7); + c1.setLogicalQubitsGarbage(3, 7); + + EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); +} + +void partialEquivalencCheckingBenchmarks(const qc::Qubit minN, + const qc::Qubit maxN, + const size_t reps, + const bool addAncilla) { + std::mt19937 gen(55); + + for (qc::Qubit n = minN; n < maxN; n++) { + std::chrono::microseconds totalTime{0}; + std::size_t totalGates{0}; + for (size_t k = 0; k < reps; k++) { + qc::Qubit d{0}; + if (addAncilla) { + std::uniform_int_distribution nrDataQubits(1, n); + d = nrDataQubits(gen); + } else { + d = n; + } + std::uniform_int_distribution nrDataQubits(1, d); + const qc::Qubit m = nrDataQubits(gen); + + const auto [c1, c2] = dd::generateRandomBenchmark(n, d, m); + + auto dd = std::make_unique>(n); + + const auto start = std::chrono::high_resolution_clock::now(); + + const bool result = dd::partialEquivalenceCheck(c1, c2, *dd); + // Get ending timepoint + const auto stop = std::chrono::high_resolution_clock::now(); + const auto duration = + std::chrono::duration_cast(stop - start); + + EXPECT_TRUE(result); + + // std::cout << "\nnumber of qubits = " << n << "; data qubits = " << d + // << "; measured qubits = " << m + // << "; number of gates = " << c2.size() << "\n"; + // std::cout << "time: " << static_cast(duration.count()) / + // 1000000. + // << " seconds\n"; + totalTime += duration; + totalGates += c2.size(); + } + std::cout << "\nnumber of qubits = " << n << "; number of reps = " << reps + << "; average time = " + << (static_cast(totalTime.count()) / + static_cast(reps) / 1000000.) + << " seconds; average number of gates = " + << (static_cast(totalGates) / static_cast(reps)) + << "\n"; + } +} + +TEST(PartialEquivalenceTest, Benchmark) { + const size_t minN = 2; + const size_t maxN = 8; + const size_t reps = 10; + std::cout << "Partial equivalence check\n"; + partialEquivalencCheckingBenchmarks(minN, maxN, reps, true); +} + +TEST(PartialEquivalenceTest, ZeroAncillaBenchmark) { + const size_t minN = 3; + const size_t maxN = 15; + const size_t reps = 10; + std::cout << "Zero-ancilla partial equivalence check\n"; + partialEquivalencCheckingBenchmarks(minN, maxN, reps, false); +} + +TEST(PartialEquivalenceTest, InvalidInput) { + const auto nqubits = 4U; + const auto dd = std::make_unique>(nqubits); + + // the circuits don't have the same number of measured qubits + qc::QuantumComputation c1{nqubits, 1}; + c1.x(1); + + qc::QuantumComputation c2{nqubits, 1}; + c2.x(1); + + c1.setLogicalQubitsGarbage(0, 1); + c1.setLogicalQubitGarbage(3); + + c2.setLogicalQubitsGarbage(0, 1); + + EXPECT_FALSE(partialEquivalenceCheck(c1, c2, *dd)); + + // now they have the same number of measured qubits but a different + // permutation of garbage qubits + c2.setLogicalQubitGarbage(2); + EXPECT_THROW(partialEquivalenceCheck(c1, c2, *dd), std::invalid_argument); +} From 512f95f2730c40a013c31e4813b3cccb6cd9f158 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 25 Feb 2024 15:53:15 +0100 Subject: [PATCH 04/41] =?UTF-8?q?=F0=9F=9A=A9=20added=20partial=20equivale?= =?UTF-8?q?nce=20flag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Configuration.hpp | 3 +- include/EquivalenceCheckingManager.hpp | 3 ++ src/mqt/qcec/configuration.py | 1 + src/mqt/qcec/pyqcec.pyi | 2 ++ src/python/bindings.cpp | 25 +++++++++++++++- test/python/test_partial_equivalence.py | 38 +++++++++++++++++++++++++ 6 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 test/python/test_partial_equivalence.py diff --git a/include/Configuration.hpp b/include/Configuration.hpp index 3da71a17..0fb66054 100644 --- a/include/Configuration.hpp +++ b/include/Configuration.hpp @@ -57,7 +57,8 @@ class Configuration { }; struct Functionality { - double traceThreshold = 1e-8; + double traceThreshold = 1e-8; + bool checkPartialEquivalence = false; }; // configuration options for the simulation scheme diff --git a/include/EquivalenceCheckingManager.hpp b/include/EquivalenceCheckingManager.hpp index 5d931dab..074f5a3c 100644 --- a/include/EquivalenceCheckingManager.hpp +++ b/include/EquivalenceCheckingManager.hpp @@ -196,6 +196,9 @@ class EquivalenceCheckingManager { void setTraceThreshold(double traceThreshold) { configuration.functionality.traceThreshold = traceThreshold; } + void setCheckPartialEquivalence(bool checkPE) { + configuration.functionality.checkPartialEquivalence = checkPE; + } // Simulation: These setting may be changed to adjust the kinds of simulations // that are performed diff --git a/src/mqt/qcec/configuration.py b/src/mqt/qcec/configuration.py index 74c1f195..f18acb2f 100644 --- a/src/mqt/qcec/configuration.py +++ b/src/mqt/qcec/configuration.py @@ -32,6 +32,7 @@ class ConfigurationOptions(TypedDict, total=False): timeout: float # Functionality trace_threshold: float + check_partial_equivalence: bool # Optimizations backpropagate_output_permutation: bool fix_output_permutation_mismatch: bool diff --git a/src/mqt/qcec/pyqcec.pyi b/src/mqt/qcec/pyqcec.pyi index d99848f7..5d092e6c 100644 --- a/src/mqt/qcec/pyqcec.pyi +++ b/src/mqt/qcec/pyqcec.pyi @@ -48,6 +48,7 @@ class Configuration: class Functionality: trace_threshold: float + check_partial_equivalence: bool def __init__(self) -> None: ... class Optimizations: @@ -132,6 +133,7 @@ class EquivalenceCheckingManager: def set_timeout(self, timeout: float = ...) -> None: ... def set_tolerance(self, tolerance: float = ...) -> None: ... def set_trace_threshold(self, threshold: float = ...) -> None: ... + def set_check_partial_equivalence(self, enable: bool = ...) -> None: ... def set_zx_checker(self, enable: bool = ...) -> None: ... def store_cex_input(self, enable: bool = ...) -> None: ... def store_cex_output(self, enable: bool = ...) -> None: ... diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index 453ece68..d9574602 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -313,6 +313,15 @@ PYBIND11_MODULE(pyqcec, m) { "Set the :attr:`trace threshold " "<.Configuration.Functionality.trace_threshold>` used for comparing " "two unitaries or functionality matrices.") + .def( + "set_check_partial_equivalence", + &EquivalenceCheckingManager::setCheckPartialEquivalence, + "enable"_a = false, + "Set whether to check for partial equivalence. Two circuits are " + "partially equivalent if, for each possible initial input state, " + "they have the same probability for each measurement outcome. " + "If set to false, the checker will output 'not equivalent' for " + "circuits that are partially equivalent but not totally equivalent. ") // Simulation .def("set_fidelity_threshold", &EquivalenceCheckingManager::setFidelityThreshold, @@ -612,7 +621,21 @@ PYBIND11_MODULE(pyqcec, m) { "while the second and third successor have weights close to zero). " "Whenever any decision diagram node differs from this structure by " "more than the configured threshold, the circuits are concluded to " - "be non-equivalent. Defaults to :code:`1e-8`."); + "be non-equivalent. Defaults to :code:`1e-8`.") + .def_readwrite( + "check_partial_equivalence", + &Configuration::Functionality::checkPartialEquivalence, + "Two circuits are partially equivalent if, for each possible initial " + "input state, they have the same probability for each measurement " + "outcome. If set to :code:`True`, a check for partial equivalence " + "will be performed in the :ref:`construction checker " + "` and in the :ref:`alternating checker " + "` (if they are enabled). If set to " + ":code:`False`, the checker will output 'not equivalent' for " + "circuits that are partially equivalent but not totally equivalent. " + "Defaults to :code:`False`."); // simulation options simulation.def(py::init<>()) diff --git a/test/python/test_partial_equivalence.py b/test/python/test_partial_equivalence.py new file mode 100644 index 00000000..8bb2cfb3 --- /dev/null +++ b/test/python/test_partial_equivalence.py @@ -0,0 +1,38 @@ +"""Tests the partial equivalence checking support of QCEC.""" + +from __future__ import annotations + +import pytest +from qiskit import QuantumCircuit + +from mqt import qcec + + +@pytest.fixture() +def original_circuit() -> QuantumCircuit: + """Fixture for a simple circuit.""" + qc = QuantumCircuit(3, 1) + qc.cswap(1, 0, 2) + qc.h(0) + qc.z(2) + qc.cswap(1, 0, 2) + qc.measure(0, 0) + return qc + + +@pytest.fixture() +def alternative_circuit() -> QuantumCircuit: + """Fixture for an alternative version of the simple circuit.""" + qc = QuantumCircuit(3, 1) + qc.x(1) + qc.cx(0, 1) + qc.ch(1, 0) + qc.measure(0, 0) + return qc + + +@pytest.mark.skip() +def test_configuration_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: + """Test if the flag for partial equivalence checking works. This test is skipped for now, because partial equivalence checking was not implemented yet.""" + result = qcec.verify(original_circuit, alternative_circuit, check_partial_equivalence=True) + assert result.equivalence == qcec.EquivalenceCriterion.equivalent From cf0f34b4a170db4c6402e092f85d25c0b70895f3 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 25 Feb 2024 17:38:12 +0100 Subject: [PATCH 05/41] =?UTF-8?q?=E2=9C=A8=20add=20PartiallyEquivalent=20e?= =?UTF-8?q?quivalence=20criterion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/EquivalenceCheckingManager.hpp | 1 + include/EquivalenceCriterion.hpp | 8 +++++++- src/python/bindings.cpp | 18 +++++++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/EquivalenceCheckingManager.hpp b/include/EquivalenceCheckingManager.hpp index 074f5a3c..65979e28 100644 --- a/include/EquivalenceCheckingManager.hpp +++ b/include/EquivalenceCheckingManager.hpp @@ -47,6 +47,7 @@ class EquivalenceCheckingManager { case EquivalenceCriterion::ProbablyEquivalent: case EquivalenceCriterion::EquivalentUpToGlobalPhase: case EquivalenceCriterion::EquivalentUpToPhase: + case EquivalenceCriterion::PartiallyEquivalent: return true; default: return false; diff --git a/include/EquivalenceCriterion.hpp b/include/EquivalenceCriterion.hpp index ba256919..d4a223e7 100644 --- a/include/EquivalenceCriterion.hpp +++ b/include/EquivalenceCriterion.hpp @@ -16,7 +16,8 @@ enum class EquivalenceCriterion { ProbablyEquivalent = 3, EquivalentUpToGlobalPhase = 4, EquivalentUpToPhase = 5, - ProbablyNotEquivalent = 6 + ProbablyNotEquivalent = 6, + PartiallyEquivalent = 7 }; inline std::string toString(const EquivalenceCriterion& criterion) noexcept { @@ -33,6 +34,8 @@ inline std::string toString(const EquivalenceCriterion& criterion) noexcept { return "equivalent_up_to_phase"; case EquivalenceCriterion::ProbablyNotEquivalent: return "probably_not_equivalent"; + case EquivalenceCriterion::PartiallyEquivalent: + return "partially_equivalent"; default: return "no_information"; } @@ -60,6 +63,9 @@ inline EquivalenceCriterion fromString(const std::string& criterion) noexcept { if ((criterion == "probably_not_equivalent") || (criterion == "6")) { return EquivalenceCriterion::ProbablyNotEquivalent; } + if ((criterion == "partially_equivalent") || (criterion == "7")) { + return EquivalenceCriterion::PartiallyEquivalent; + } std::cerr << "Unknown equivalence criterion: " << criterion << ". Defaulting to `no_information`.\n"; return EquivalenceCriterion::NoInformation; diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index d9574602..0da08d0f 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -155,6 +155,20 @@ PYBIND11_MODULE(pyqcec, m) { "whenever the :ref:`ZX-calculus checker " "` could not " "reduce the combined circuit to the identity.") + .value( + "partially_equivalent", EquivalenceCriterion::PartiallyEquivalent, + "Circuits are partially equivalent. Two circuits are partially " + "equivalent if, for each possible initial " + "input state, they have the same probability for each measurement " + "outcome. This result is obtained by the :ref:`construction checker " + "` or the :ref:`alternating checker " + "` if the flag :attr:`check_partial_equivalence " + "<.Configuration.Functionality.check_partial_equivalence>` is set to " + ":code:`True`. If it is set to :code:`False`, the checker will " + "output 'not equivalent' for " + "circuits that are partially equivalent but not totally equivalent. ") // allow construction from a string .def(py::init([](const std::string& str) -> EquivalenceCriterion { return fromString(str); @@ -317,7 +331,9 @@ PYBIND11_MODULE(pyqcec, m) { "set_check_partial_equivalence", &EquivalenceCheckingManager::setCheckPartialEquivalence, "enable"_a = false, - "Set whether to check for partial equivalence. Two circuits are " + "Set whether to :attr:`check for partial equivalence " + "<.Configuration.Functionality.check_partial_equivalence>`. Two " + "circuits are " "partially equivalent if, for each possible initial input state, " "they have the same probability for each measurement outcome. " "If set to false, the checker will output 'not equivalent' for " From 98f30e0cae693d8c470c1d222df6bde7095c28f3 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 25 Feb 2024 17:39:34 +0100 Subject: [PATCH 06/41] =?UTF-8?q?=F0=9F=90=9B=20add=20check=5Fpartial=5Feq?= =?UTF-8?q?uivalence=20to=20json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Configuration.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/Configuration.hpp b/include/Configuration.hpp index 0fb66054..d73888d9 100644 --- a/include/Configuration.hpp +++ b/include/Configuration.hpp @@ -187,8 +187,9 @@ class Configuration { par["additional_instantiations"] = parameterized.nAdditionalInstantiations; if (execution.runConstructionChecker || execution.runAlternatingChecker) { - auto& fun = config["functionality"]; - fun["trace_threshold"] = functionality.traceThreshold; + auto& fun = config["functionality"]; + fun["trace_threshold"] = functionality.traceThreshold; + fun["check_partial_equivalence"] = functionality.checkPartialEquivalence; } if (execution.runSimulationChecker) { From d6fe8420512397d298dcec01ac9a2c18155cc3ae Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Tue, 27 Feb 2024 10:09:23 +0100 Subject: [PATCH 07/41] =?UTF-8?q?=F0=9F=94=A5=20remove=20PartiallyEquivale?= =?UTF-8?q?nt=20equivalence=20criterion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/EquivalenceCheckingManager.hpp | 1 - include/EquivalenceCriterion.hpp | 8 +------- src/python/bindings.cpp | 18 +----------------- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/include/EquivalenceCheckingManager.hpp b/include/EquivalenceCheckingManager.hpp index 65979e28..074f5a3c 100644 --- a/include/EquivalenceCheckingManager.hpp +++ b/include/EquivalenceCheckingManager.hpp @@ -47,7 +47,6 @@ class EquivalenceCheckingManager { case EquivalenceCriterion::ProbablyEquivalent: case EquivalenceCriterion::EquivalentUpToGlobalPhase: case EquivalenceCriterion::EquivalentUpToPhase: - case EquivalenceCriterion::PartiallyEquivalent: return true; default: return false; diff --git a/include/EquivalenceCriterion.hpp b/include/EquivalenceCriterion.hpp index d4a223e7..ba256919 100644 --- a/include/EquivalenceCriterion.hpp +++ b/include/EquivalenceCriterion.hpp @@ -16,8 +16,7 @@ enum class EquivalenceCriterion { ProbablyEquivalent = 3, EquivalentUpToGlobalPhase = 4, EquivalentUpToPhase = 5, - ProbablyNotEquivalent = 6, - PartiallyEquivalent = 7 + ProbablyNotEquivalent = 6 }; inline std::string toString(const EquivalenceCriterion& criterion) noexcept { @@ -34,8 +33,6 @@ inline std::string toString(const EquivalenceCriterion& criterion) noexcept { return "equivalent_up_to_phase"; case EquivalenceCriterion::ProbablyNotEquivalent: return "probably_not_equivalent"; - case EquivalenceCriterion::PartiallyEquivalent: - return "partially_equivalent"; default: return "no_information"; } @@ -63,9 +60,6 @@ inline EquivalenceCriterion fromString(const std::string& criterion) noexcept { if ((criterion == "probably_not_equivalent") || (criterion == "6")) { return EquivalenceCriterion::ProbablyNotEquivalent; } - if ((criterion == "partially_equivalent") || (criterion == "7")) { - return EquivalenceCriterion::PartiallyEquivalent; - } std::cerr << "Unknown equivalence criterion: " << criterion << ". Defaulting to `no_information`.\n"; return EquivalenceCriterion::NoInformation; diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index 0da08d0f..d9574602 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -155,20 +155,6 @@ PYBIND11_MODULE(pyqcec, m) { "whenever the :ref:`ZX-calculus checker " "` could not " "reduce the combined circuit to the identity.") - .value( - "partially_equivalent", EquivalenceCriterion::PartiallyEquivalent, - "Circuits are partially equivalent. Two circuits are partially " - "equivalent if, for each possible initial " - "input state, they have the same probability for each measurement " - "outcome. This result is obtained by the :ref:`construction checker " - "` or the :ref:`alternating checker " - "` if the flag :attr:`check_partial_equivalence " - "<.Configuration.Functionality.check_partial_equivalence>` is set to " - ":code:`True`. If it is set to :code:`False`, the checker will " - "output 'not equivalent' for " - "circuits that are partially equivalent but not totally equivalent. ") // allow construction from a string .def(py::init([](const std::string& str) -> EquivalenceCriterion { return fromString(str); @@ -331,9 +317,7 @@ PYBIND11_MODULE(pyqcec, m) { "set_check_partial_equivalence", &EquivalenceCheckingManager::setCheckPartialEquivalence, "enable"_a = false, - "Set whether to :attr:`check for partial equivalence " - "<.Configuration.Functionality.check_partial_equivalence>`. Two " - "circuits are " + "Set whether to check for partial equivalence. Two circuits are " "partially equivalent if, for each possible initial input state, " "they have the same probability for each measurement outcome. " "If set to false, the checker will output 'not equivalent' for " From 2214232dc205244e91dbc827af3cffac360475d7 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Tue, 27 Feb 2024 11:07:08 +0100 Subject: [PATCH 08/41] =?UTF-8?q?=E2=9C=A8=20implemented=20partial=20equiv?= =?UTF-8?q?alence=20for=20the=20alternating=20checker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/checker/dd/DDAlternatingChecker.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/checker/dd/DDAlternatingChecker.cpp b/src/checker/dd/DDAlternatingChecker.cpp index 3a8c9136..557116b4 100644 --- a/src/checker/dd/DDAlternatingChecker.cpp +++ b/src/checker/dd/DDAlternatingChecker.cpp @@ -101,11 +101,19 @@ EquivalenceCriterion DDAlternatingChecker::checkEquivalence() { garbage[static_cast(q)] = qc1.logicalQubitIsGarbage(q) && qc2.logicalQubitIsGarbage(q); } + bool isClose{}; // if partial equivalence is being checked instead of total equivalence, it // suffices to change the last parameter of isCloseToIdentity to `false` - const bool isClose = dd->isCloseToIdentity( - functionality, configuration.functionality.traceThreshold, garbage, true); + if (configuration.functionality.checkPartialEquivalence) { + isClose = dd->isCloseToIdentity(functionality, + configuration.functionality.traceThreshold, + garbage, false); + } else { + isClose = dd->isCloseToIdentity(functionality, + configuration.functionality.traceThreshold, + garbage, true); + } if (isClose) { // whenever the top edge weight is not one, both decision diagrams are only From 372c91441f20773d0186f9e055d55b638b0b0c7d Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Tue, 27 Feb 2024 13:24:13 +0100 Subject: [PATCH 09/41] =?UTF-8?q?=E2=9C=A8=20implemented=20partial=20equiv?= =?UTF-8?q?alence=20checking=20for=20the=20construction=20checker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/checker/dd/DDConstructionChecker.hpp | 3 + include/checker/dd/TaskManager.hpp | 26 ++ src/checker/dd/DDConstructionChecker.cpp | 29 +- test/test_partial_equivalence.cpp | 451 ++++++++++--------- 4 files changed, 293 insertions(+), 216 deletions(-) diff --git a/include/checker/dd/DDConstructionChecker.hpp b/include/checker/dd/DDConstructionChecker.hpp index 10437fb9..300f4ebd 100644 --- a/include/checker/dd/DDConstructionChecker.hpp +++ b/include/checker/dd/DDConstructionChecker.hpp @@ -36,5 +36,8 @@ class DDConstructionChecker final taskManager.incRef(); taskManager.reduceAncillae(); } + + void postprocessTask( + TaskManager& task) override; }; } // namespace ec diff --git a/include/checker/dd/TaskManager.hpp b/include/checker/dd/TaskManager.hpp index 631a61e2..a349649c 100644 --- a/include/checker/dd/TaskManager.hpp +++ b/include/checker/dd/TaskManager.hpp @@ -6,6 +6,7 @@ #pragma once #include "QuantumComputation.hpp" +#include "checker/dd/DDPartialEquivalence.hpp" #include "dd/Operations.hpp" namespace ec { @@ -129,6 +130,31 @@ template class TaskManager { void decRef(DDType& state) { package->decRef(state); } void decRef() { decRef(internalState); } + /** + Reduces ancillaries and garbage according to the number of garbage and + ancillary qubits such that the matrix will be equal to another reduced matrix + iff the two underlying circuits are partially equivalent. + Assumption: the measured and data qubits are the first qubits. + **/ + void reduceForPartialEquivalence(dd::mEdge& state) { + const auto d = static_cast(qc->getNqubitsWithoutAncillae()); + const auto m = static_cast(qc->getNmeasuredQubits()); + + const dd::Qubit n = state.p->v + 1; + dd::Qubit k = n - d; + dd::Qubit extra{0}; + if (m > k) { + extra = m - k; + } + k = k + extra; + + state = partialEquivalenceCheckDDSubroutine(state, m, k, extra, *package); + } + + void reduceForPartialEquivalence() { + reduceForPartialEquivalence(internalState); + } + private: const qc::QuantumComputation* qc{}; DDPackage* package; diff --git a/src/checker/dd/DDConstructionChecker.cpp b/src/checker/dd/DDConstructionChecker.cpp index f3b40a37..685cd211 100644 --- a/src/checker/dd/DDConstructionChecker.cpp +++ b/src/checker/dd/DDConstructionChecker.cpp @@ -5,10 +5,37 @@ #include "checker/dd/DDConstructionChecker.hpp" +namespace ec { + // this function is mainly placed here in order to have an out-of-line // virtual method definition which avoids emitting the classe's vtable in // every translation unit. -void ec::DDConstructionChecker::json(nlohmann::json& j) const noexcept { +void DDConstructionChecker::json(nlohmann::json& j) const noexcept { DDEquivalenceChecker::json(j); j["checker"] = "decision_diagram_construction"; } + +void DDConstructionChecker::postprocessTask( + TaskManager& task) { + // ensure that the permutation that was tracked throughout the circuit matches + // the expected output permutation + task.changePermutation(); + if (isDone()) { + return; + } + // TODO: change permutation for partial equivalence + if (configuration.functionality.checkPartialEquivalence) { + // reduce ancillaries and garbage for partial equivalence check + task.reduceForPartialEquivalence(); + + } else { // reduce ancillaries for total equivalence check + // eliminate the superfluous contributions of ancillary qubits (this only + // has an effect on matrices) + task.reduceAncillae(); + if (isDone()) { + return; + } + } +} + +} // namespace ec diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index d050242b..ececca3f 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -11,19 +11,21 @@ #include #include -class PartialEqualityTest : public testing::Test { +class PartialEquivalenceTest : public testing::Test { void SetUp() override { - qc1 = qc::QuantumComputation(nqubits); - qc2 = qc::QuantumComputation(nqubits); - config.optimizations.fuseSingleQubitGates = false; - config.optimizations.reorderOperations = false; - config.optimizations.reconstructSWAPs = false; + qc1 = qc::QuantumComputation(nqubits, nqubits); + qc2 = qc::QuantumComputation(nqubits, nqubits); + config.optimizations.fuseSingleQubitGates = false; + config.optimizations.reorderOperations = false; + config.optimizations.reconstructSWAPs = false; config.optimizations.fixOutputPermutationMismatch = true; config.execution.runSimulationChecker = false; config.execution.runAlternatingChecker = false; config.execution.runConstructionChecker = false; config.execution.runZXChecker = false; + + config.functionality.checkPartialEquivalence = true; } protected: @@ -33,7 +35,7 @@ class PartialEqualityTest : public testing::Test { ec::Configuration config{}; }; -TEST_F(PartialEqualityTest, AlternatingCheckerGarbage) { +TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbage) { // these circuits have the same gates acting on the measured qubit // and random gates acting on the two garbage qubits qc1.cswap(1, 0, 2); @@ -56,7 +58,8 @@ TEST_F(PartialEqualityTest, AlternatingCheckerGarbage) { qc2.setLogicalQubitGarbage(2); qc2.setLogicalQubitGarbage(1); - config.execution.runAlternatingChecker = true; + config.execution.runAlternatingChecker = true; + config.functionality.checkPartialEquivalence = false; ec::EquivalenceCheckingManager ecm(qc1, qc2, config); ecm.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm.run(); @@ -64,7 +67,7 @@ TEST_F(PartialEqualityTest, AlternatingCheckerGarbage) { ec::EquivalenceCriterion::EquivalentUpToGlobalPhase); } -TEST_F(PartialEqualityTest, AlternatingCheckerGarbage2) { +TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbage2) { // measured qubit: 1 qc1.setLogicalQubitGarbage(2); qc1.setLogicalQubitGarbage(0); @@ -84,7 +87,8 @@ TEST_F(PartialEqualityTest, AlternatingCheckerGarbage2) { qc2.ry(0.1, 2); qc2.cx(2, 0); - config.execution.runAlternatingChecker = true; + config.execution.runAlternatingChecker = true; + config.functionality.checkPartialEquivalence = false; ec::EquivalenceCheckingManager ecm(qc1, qc2, config); ecm.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm.run(); @@ -92,7 +96,7 @@ TEST_F(PartialEqualityTest, AlternatingCheckerGarbage2) { ec::EquivalenceCriterion::EquivalentUpToGlobalPhase); } -TEST_F(PartialEqualityTest, AlternatingCheckerGarbageAndAncillary) { +TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageAndAncillary) { qc1.setLogicalQubitGarbage(2); qc1.setLogicalQubitGarbage(1); qc1.setLogicalQubitAncillary(2); @@ -111,7 +115,8 @@ TEST_F(PartialEqualityTest, AlternatingCheckerGarbageAndAncillary) { qc3.rz(dd::PI_4, 1); qc3.ry(0.1, 1); - config.execution.runAlternatingChecker = true; + config.execution.runAlternatingChecker = true; + config.functionality.checkPartialEquivalence = false; ec::EquivalenceCheckingManager ecm(qc1, qc3, config); ecm.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm.run(); @@ -119,10 +124,8 @@ TEST_F(PartialEqualityTest, AlternatingCheckerGarbageAndAncillary) { ec::EquivalenceCriterion::EquivalentUpToGlobalPhase); } -TEST_F(PartialEqualityTest, AlternatingCheckerGarbageNotEquivalent) { +TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent) { // example from the paper https://arxiv.org/abs/2208.07564 - // these two circuits are only partially equivalent, - // therefore the equivalence checker returns NotEquivalent qc1.cswap(1, 0, 2); qc1.h(0); qc1.z(2); @@ -136,129 +139,144 @@ TEST_F(PartialEqualityTest, AlternatingCheckerGarbageNotEquivalent) { qc2.setLogicalQubitGarbage(2); qc2.setLogicalQubitGarbage(1); + // partially equivalent circuits config.execution.runAlternatingChecker = true; ec::EquivalenceCheckingManager ecm(qc1, qc2, config); ecm.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm.run(); - EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); + + // these two circuits are only partially equivalent, + // therefore the equivalence checker returns NotEquivalent when we disable + // partial equality checking + config.functionality.checkPartialEquivalence = false; + ec::EquivalenceCheckingManager ecm2(qc1, qc2, config); + ecm2.setApplicationScheme(ec::ApplicationSchemeType::Proportional); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } using namespace qc::literals; -TEST(PartialEquivalenceTest, TrivialEquivalence) { - const auto nqubits = 2U; - const auto dd = std::make_unique>(nqubits); - const auto inputMatrix = - dd::CMat{{1, 1, 1, 1}, {1, -1, 1, -1}, {1, 1, -1, -1}, {1, -1, -1, 1}}; - const auto inputDD = dd->makeDDFromMatrix(inputMatrix); - - EXPECT_TRUE(partialEquivalenceCheckDD(inputDD, inputDD, 1, 1, *dd)); - EXPECT_TRUE(partialEquivalenceCheckDD(inputDD, inputDD, 2, 1, *dd)); - EXPECT_TRUE(partialEquivalenceCheckDD(inputDD, inputDD, 1, 2, *dd)); - EXPECT_TRUE(partialEquivalenceCheckDD(inputDD, inputDD, 2, 2, *dd)); - - const auto hGate = dd->makeGateDD(dd::H_MAT, 2, 1); - const auto cxGate = dd->makeGateDD(dd::X_MAT, 2, 1_pc, 0); - const auto bellMatrix = dd->multiply(cxGate, hGate); - EXPECT_FALSE(partialEquivalenceCheckDD(inputDD, bellMatrix, 1, 1, *dd)); +TEST_F(PartialEquivalenceTest, TrivialEquivalence) { + auto qc = qc::QuantumComputation(2); + + qc.h(1); + qc.h(0); + qc.cx(0, 1); + qc.swap(1, 0); + + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc, qc, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); + + qc.setLogicalQubitAncillary(1); + + ec::EquivalenceCheckingManager ecm2(qc, qc, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::Equivalent); + + qc.setLogicalQubitGarbage(1); + + ec::EquivalenceCheckingManager ecm3(qc, qc, config); + ecm3.run(); + EXPECT_EQ(ecm3.equivalence(), ec::EquivalenceCriterion::Equivalent); + + qc.setLogicalQubitGarbage(0); + + ec::EquivalenceCheckingManager ecm4(qc, qc, config); + ecm4.run(); + EXPECT_EQ(ecm4.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, BasicPartialEquivalenceChecking) { - const auto nqubits = 3U; - auto dd = std::make_unique>(nqubits); +TEST_F(PartialEquivalenceTest, BasicPartialEquivalenceChecking) { // only the second qubit has differing gates in the two circuits, // therefore they should be equivalent if we only measure the first qubit - const auto hGate = dd->makeGateDD(dd::H_MAT, 3, 1); - const auto xGate = dd->makeGateDD(dd::X_MAT, 3, 1); - const auto circuit1 = dd->multiply(xGate, hGate); - const auto circuit2 = dd->makeIdent(3); + qc1.h(1); + qc1.x(1); + + qc1.measure(0, 0); + qc2.measure(0, 0); + + qc1.setLogicalQubitGarbage(1); + qc2.setLogicalQubitGarbage(1); + qc1.setLogicalQubitGarbage(2); + qc2.setLogicalQubitGarbage(2); - EXPECT_TRUE(partialEquivalenceCheckDD(circuit1, circuit2, 2, 1, *dd)); + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, NotEquivalent) { - const auto nqubits = 2U; - const auto dd = std::make_unique>(nqubits); +TEST_F(PartialEquivalenceTest, ConstructionCheckerNotEquivalent) { // the first qubit has differing gates in the two circuits, // therefore they should not be equivalent if we only measure the first qubit - const auto hGate = dd->makeGateDD(dd::H_MAT, nqubits, 0); - const auto xGate = dd->makeGateDD(dd::X_MAT, nqubits, 0); - const auto circuit1 = dd->multiply(xGate, hGate); - const auto circuit2 = dd->makeIdent(2); - EXPECT_FALSE(partialEquivalenceCheckDD(circuit1, circuit2, 2, 1, *dd)); -} + qc1.h(0); + qc1.x(0); -TEST(PartialEquivalenceTest, ExamplePaper) { - const auto nqubits = 3U; - const auto dd = std::make_unique>(nqubits); - const auto controlledSwapGate = - dd->makeTwoQubitGateDD(dd::SWAP_MAT, nqubits, qc::Controls{1}, 0, 2); - const auto hGate = dd->makeGateDD(dd::H_MAT, nqubits, 0); - const auto zGate = dd->makeGateDD(dd::Z_MAT, nqubits, 2); - const auto xGate = dd->makeGateDD(dd::X_MAT, nqubits, 1); - const auto controlledHGate = - dd->makeGateDD(dd::H_MAT, nqubits, qc::Controls{1}, 0); - - const auto c1 = dd->multiply( - controlledSwapGate, - dd->multiply(hGate, dd->multiply(zGate, controlledSwapGate))); - const auto c2 = dd->multiply(controlledHGate, xGate); - - EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); -} + qc1.setLogicalQubitGarbage(1); + qc2.setLogicalQubitGarbage(1); -TEST(PartialEquivalenceTest, DifferentNumberOfQubits) { - const auto nqubits = 3U; - const auto dd = std::make_unique>(nqubits); - const auto controlledSwapGate = - dd->makeTwoQubitGateDD(dd::SWAP_MAT, nqubits, qc::Controls{1}, 0, 2); - const auto hGate = dd->makeGateDD(dd::H_MAT, nqubits, 0); - const auto zGate = dd->makeGateDD(dd::Z_MAT, nqubits, 2); - const auto xGate = dd->makeGateDD(dd::X_MAT, 2, 1); - const auto controlledHGate = dd->makeGateDD(dd::H_MAT, 2, qc::Controls{1}, 0); - - const auto c1 = dd->multiply( - controlledSwapGate, - dd->multiply(hGate, dd->multiply(zGate, controlledSwapGate))); - const auto c2 = dd->multiply(controlledHGate, xGate); - - EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); - EXPECT_FALSE(partialEquivalenceCheckDD(c2, c1, 3, 3, *dd)); - EXPECT_FALSE(partialEquivalenceCheckDD(c2, dd::mEdge::zero(), 2, 1, *dd)); - EXPECT_FALSE(partialEquivalenceCheckDD(c2, dd::mEdge::one(), 2, 1, *dd)); - EXPECT_FALSE(partialEquivalenceCheckDD(dd::mEdge::one(), c1, 2, 1, *dd)); - EXPECT_TRUE( - partialEquivalenceCheckDD(dd::mEdge::one(), dd::mEdge::one(), 0, 1, *dd)); - EXPECT_TRUE( - partialEquivalenceCheckDD(dd::mEdge::one(), dd::mEdge::one(), 0, 0, *dd)); + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } -TEST(PartialEquivalenceTest, ComputeTableTest) { - const auto nqubits = 3U; - const auto dd = std::make_unique>(nqubits); - const auto controlledSwapGate = - dd->makeTwoQubitGateDD(dd::SWAP_MAT, nqubits, qc::Controls{1}, 2, 0); - const auto hGate = dd->makeGateDD(dd::H_MAT, nqubits, 0); - const auto zGate = dd->makeGateDD(dd::Z_MAT, nqubits, 2); - const auto xGate = dd->makeGateDD(dd::X_MAT, nqubits, 1); - const auto controlledHGate = - dd->makeGateDD(dd::H_MAT, nqubits, qc::Controls{1}, 0); - - const auto c1 = dd->multiply( - controlledSwapGate, - dd->multiply(hGate, dd->multiply(zGate, controlledSwapGate))); - const auto c2 = dd->multiply(controlledHGate, xGate); - - EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); - EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); - EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); - EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); - EXPECT_TRUE(partialEquivalenceCheckDD(c1, c2, 3, 1, *dd)); +TEST_F(PartialEquivalenceTest, ConstructionCheckerGarbageNotEquivalent) { + // example from the paper https://arxiv.org/abs/2208.07564 + qc1.cswap(1, 0, 2); + qc1.h(0); + qc1.z(2); + qc1.cswap(1, 0, 2); + + qc2.x(1); + qc2.ch(1, 0); + + qc1.setLogicalQubitGarbage(2); + qc1.setLogicalQubitGarbage(1); + qc2.setLogicalQubitGarbage(2); + qc2.setLogicalQubitGarbage(1); + + // partially equivalent circuits + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); + + // these two circuits are only partially equivalent, + // therefore the equivalence checker returns NotEquivalent when we disable + // partial equality checking + config.functionality.checkPartialEquivalence = false; + ec::EquivalenceCheckingManager ecm2(qc1, qc2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } -TEST(PartialEquivalenceTest, MQTBenchGrover3Qubits) { - const auto dd = std::make_unique>(3); +TEST_F(PartialEquivalenceTest, ConstructionCheckerDifferentNumberOfQubits) { + qc1.cswap(1, 0, 2); + qc1.h(0); + qc1.z(2); + qc1.cswap(1, 0, 2); + + auto qc3 = qc::QuantumComputation(2); + + qc3.x(1); + qc3.ch(1, 0); + + qc1.setLogicalQubitGarbage(2); + qc1.setLogicalQubitGarbage(1); + qc3.setLogicalQubitGarbage(1); + + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc3, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} +TEST_F(PartialEquivalenceTest, MQTBenchGrover3Qubits) { const qc::QuantumComputation c1{ "./circuits/partialEquivalenceTest/" "grover-noancilla_nativegates_ibm_qiskit_opt0_3.qasm"}; @@ -266,12 +284,22 @@ TEST(PartialEquivalenceTest, MQTBenchGrover3Qubits) { "./circuits/partialEquivalenceTest/grover-noancilla_indep_qiskit_3.qasm"}; // 3 measured qubits and 3 data qubits, full equivalence - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + // construction checker + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); + + // alternating checker + config.execution.runConstructionChecker = false; + config.execution.runAlternatingChecker = true; + ec::EquivalenceCheckingManager ecm2(c1, c2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), + ec::EquivalenceCriterion::EquivalentUpToGlobalPhase); } -TEST(PartialEquivalenceTest, MQTBenchGrover7Qubits) { - const auto dd = std::make_unique>(7); - +TEST_F(PartialEquivalenceTest, MQTBenchGrover7Qubits) { const qc::QuantumComputation c1{ "./circuits/partialEquivalenceTest/" "grover-noancilla_nativegates_ibm_qiskit_opt0_7.qasm"}; @@ -280,12 +308,21 @@ TEST(PartialEquivalenceTest, MQTBenchGrover7Qubits) { "grover-noancilla_nativegates_ibm_qiskit_opt1_7.qasm"}; // 7 measured qubits and 7 data qubits, full equivalence - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + // construction checker + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); + + // alternating checker + config.execution.runConstructionChecker = false; + config.execution.runAlternatingChecker = true; + ec::EquivalenceCheckingManager ecm2(c1, c2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, SliQECGrover22Qubits) { - const auto dd = std::make_unique>(12); - +TEST_F(PartialEquivalenceTest, SliQECGrover22Qubits) { const qc::QuantumComputation c1{ "./circuits/partialEquivalenceTest/Grover_1.qasm"}; // 11 qubits, 11 data // qubits @@ -297,13 +334,15 @@ TEST(PartialEquivalenceTest, SliQECGrover22Qubits) { c2.setLogicalQubitAncillary(11); c2.setLogicalQubitGarbage(11); + // construction checker // adds 10 ancillary qubits -> total number of qubits is 22 - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, SliQECAdd19Qubits) { - const auto dd = std::make_unique>(19); - +TEST_F(PartialEquivalenceTest, SliQECAdd19Qubits) { // full equivalence, 19 qubits // but this test uses algorithm for partial equivalence, not the "zero // ancillae" version @@ -319,34 +358,33 @@ TEST(PartialEquivalenceTest, SliQECAdd19Qubits) { c2.setLogicalQubitsGarbage(8, 18); // doesn't add ancillary qubits -> total number of qubits is 19 - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, ExamplePaperDifferentQubitOrder) { - const auto nqubits = 3U; - auto dd = std::make_unique>(nqubits); - - qc::QuantumComputation c1{nqubits, 1}; - c1.cswap(1, 2, 0); - c1.h(2); - c1.z(0); - c1.cswap(1, 2, 0); +TEST_F(PartialEquivalenceTest, ExamplePaperDifferentQubitOrder) { + // TODO: implement qubit order change + qc1.cswap(1, 2, 0); + qc1.h(2); + qc1.z(0); + qc1.cswap(1, 2, 0); - qc::QuantumComputation c2{nqubits, 1}; - c2.x(1); - c2.ch(1, 2); + qc2.x(1); + qc2.ch(1, 2); - c1.setLogicalQubitsGarbage(0, 1); - c2.setLogicalQubitsGarbage(0, 1); + qc1.setLogicalQubitsGarbage(0, 1); + qc2.setLogicalQubitsGarbage(0, 1); - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, ExamplePaperDifferentQubitOrderAndNumber) { - const auto nqubits = 4U; - auto dd = std::make_unique>(nqubits); - - qc::QuantumComputation c1{nqubits, 1}; +TEST_F(PartialEquivalenceTest, ExamplePaperDifferentQubitOrderAndNumber) { + qc::QuantumComputation c1{4, 1}; c1.cswap(1, 2, 0); c1.h(2); c1.z(0); @@ -361,12 +399,15 @@ TEST(PartialEquivalenceTest, ExamplePaperDifferentQubitOrderAndNumber) { c1.setLogicalQubitAncillary(3); c2.setLogicalQubitsGarbage(0, 1); - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); - EXPECT_TRUE(partialEquivalenceCheck(c2, c1, *dd)); + + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, ZeroAncillaSliQEC19Qubits) { - auto dd = std::make_unique>(19); +TEST_F(PartialEquivalenceTest, AlternatingCheckerSliQEC19Qubits) { + config.execution.runAlternatingChecker = true; // full equivalence, 10 qubits const qc::QuantumComputation c1{ @@ -374,8 +415,9 @@ TEST(PartialEquivalenceTest, ZeroAncillaSliQEC19Qubits) { const qc::QuantumComputation c2{ "./circuits/partialEquivalenceTest/entanglement_2.qasm"}; - // calls zeroAncillaePartialEquivalenceCheck - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); // full equivalence, 19 qubits const qc::QuantumComputation c3{ @@ -383,8 +425,9 @@ TEST(PartialEquivalenceTest, ZeroAncillaSliQEC19Qubits) { const qc::QuantumComputation c4{ "./circuits/partialEquivalenceTest/add6_196_2.qasm"}; - // calls zeroAncillaePartialEquivalenceCheck - EXPECT_TRUE(partialEquivalenceCheck(c3, c4, *dd)); + ec::EquivalenceCheckingManager ecm2(c1, c2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::Equivalent); // full equivalence, 10 qubits const qc::QuantumComputation c5{ @@ -393,23 +436,26 @@ TEST(PartialEquivalenceTest, ZeroAncillaSliQEC19Qubits) { "./circuits/partialEquivalenceTest/bv_2.qasm"}; // calls zeroAncillaePartialEquivalenceCheck - EXPECT_TRUE(partialEquivalenceCheck(c5, c6, *dd)); + ec::EquivalenceCheckingManager ecm3(c1, c2, config); + ecm3.run(); + EXPECT_EQ(ecm3.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, ZeroAncillaSliQECRandomCircuit) { - auto dd = std::make_unique>(10); +TEST_F(PartialEquivalenceTest, AlternatingCheckerSliQECRandomCircuit) { + config.execution.runAlternatingChecker = true; // full equivalence, 10 qubits const qc::QuantumComputation c1{ "./circuits/partialEquivalenceTest/random_1.qasm"}; const qc::QuantumComputation c2{ "./circuits/partialEquivalenceTest/random_2.qasm"}; - // calls buildFunctionality for c2^(-1) concatenated with c1 - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST(PartialEquivalenceTest, SliQECPeriodFinding8Qubits) { - auto dd = std::make_unique>(8); +TEST_F(PartialEquivalenceTest, ConstructionCheckerSliQECPeriodFinding8Qubits) { + config.execution.runConstructionChecker = true; // 8 qubits, 3 data qubits qc::QuantumComputation c1{ "./circuits/partialEquivalenceTest/period_finding_1.qasm"}; @@ -425,18 +471,21 @@ TEST(PartialEquivalenceTest, SliQECPeriodFinding8Qubits) { c1.setLogicalQubitsAncillary(3, 7); c1.setLogicalQubitsGarbage(3, 7); - EXPECT_TRUE(partialEquivalenceCheck(c1, c2, *dd)); + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -void partialEquivalencCheckingBenchmarks(const qc::Qubit minN, - const qc::Qubit maxN, - const size_t reps, - const bool addAncilla) { +void partialEquivalencCheckingBenchmarks(const qc::Qubit minN, + const qc::Qubit maxN, + const size_t reps, + const bool addAncilla, + const ec::Configuration& config) { std::mt19937 gen(55); for (qc::Qubit n = minN; n < maxN; n++) { - std::chrono::microseconds totalTime{0}; - std::size_t totalGates{0}; + double totalTime{0}; + std::size_t totalGates{0}; for (size_t k = 0; k < reps; k++) { qc::Qubit d{0}; if (addAncilla) { @@ -450,17 +499,12 @@ void partialEquivalencCheckingBenchmarks(const qc::Qubit minN, const auto [c1, c2] = dd::generateRandomBenchmark(n, d, m); - auto dd = std::make_unique>(n); - - const auto start = std::chrono::high_resolution_clock::now(); + // check equivalence + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_TRUE(ecm.getResults().consideredEquivalent()); - const bool result = dd::partialEquivalenceCheck(c1, c2, *dd); - // Get ending timepoint - const auto stop = std::chrono::high_resolution_clock::now(); - const auto duration = - std::chrono::duration_cast(stop - start); - - EXPECT_TRUE(result); + const auto duration = ecm.getResults().checkTime; // std::cout << "\nnumber of qubits = " << n << "; data qubits = " << d // << "; measured qubits = " << m @@ -473,50 +517,27 @@ void partialEquivalencCheckingBenchmarks(const qc::Qubit minN, } std::cout << "\nnumber of qubits = " << n << "; number of reps = " << reps << "; average time = " - << (static_cast(totalTime.count()) / - static_cast(reps) / 1000000.) + << (totalTime / static_cast(reps) / 1000000.) << " seconds; average number of gates = " << (static_cast(totalGates) / static_cast(reps)) << "\n"; } } -TEST(PartialEquivalenceTest, Benchmark) { - const size_t minN = 2; - const size_t maxN = 8; - const size_t reps = 10; +TEST_F(PartialEquivalenceTest, Benchmark) { + config.execution.runConstructionChecker = true; + const size_t minN = 2; + const size_t maxN = 8; + const size_t reps = 10; std::cout << "Partial equivalence check\n"; - partialEquivalencCheckingBenchmarks(minN, maxN, reps, true); + partialEquivalencCheckingBenchmarks(minN, maxN, reps, true, config); } -TEST(PartialEquivalenceTest, ZeroAncillaBenchmark) { - const size_t minN = 3; - const size_t maxN = 15; - const size_t reps = 10; +TEST_F(PartialEquivalenceTest, ZeroAncillaBenchmark) { + config.execution.runAlternatingChecker = true; + const size_t minN = 3; + const size_t maxN = 15; + const size_t reps = 10; std::cout << "Zero-ancilla partial equivalence check\n"; - partialEquivalencCheckingBenchmarks(minN, maxN, reps, false); -} - -TEST(PartialEquivalenceTest, InvalidInput) { - const auto nqubits = 4U; - const auto dd = std::make_unique>(nqubits); - - // the circuits don't have the same number of measured qubits - qc::QuantumComputation c1{nqubits, 1}; - c1.x(1); - - qc::QuantumComputation c2{nqubits, 1}; - c2.x(1); - - c1.setLogicalQubitsGarbage(0, 1); - c1.setLogicalQubitGarbage(3); - - c2.setLogicalQubitsGarbage(0, 1); - - EXPECT_FALSE(partialEquivalenceCheck(c1, c2, *dd)); - - // now they have the same number of measured qubits but a different - // permutation of garbage qubits - c2.setLogicalQubitGarbage(2); - EXPECT_THROW(partialEquivalenceCheck(c1, c2, *dd), std::invalid_argument); + partialEquivalencCheckingBenchmarks(minN, maxN, reps, false, config); } From 20018913c57ee6f483b448a483119200009b7eea Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Tue, 27 Feb 2024 13:25:01 +0100 Subject: [PATCH 10/41] =?UTF-8?q?=F0=9F=94=A5=20removed=20unused=20functio?= =?UTF-8?q?ns=20in=20DDPartialEquivalence.hpp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/checker/dd/DDPartialEquivalence.hpp | 97 +++------------------ 1 file changed, 11 insertions(+), 86 deletions(-) diff --git a/include/checker/dd/DDPartialEquivalence.hpp b/include/checker/dd/DDPartialEquivalence.hpp index fbdcb354..74e54fd6 100644 --- a/include/checker/dd/DDPartialEquivalence.hpp +++ b/include/checker/dd/DDPartialEquivalence.hpp @@ -1,3 +1,5 @@ +#pragma once + #include "dd/FunctionalityConstruction.hpp" #include "dd/Package.hpp" @@ -24,86 +26,6 @@ mEdge partialEquivalenceCheckDDSubroutine(mEdge u, const Qubit m, const Qubit k, return dd.multiply(dd.conjugateTranspose(u), u2); } -/** - Checks for partial equivalence between the two circuits u1 and u2, - where the first d qubits of the circuits are the data qubits and - the first m qubits are the measured qubits. - @param u1 DD representation of first circuit - @param u2 DD representation of second circuit - @param d Number of data qubits - @param m Number of measured qubits - @return true if the two circuits u1 and u2 are partially equivalent. - **/ -template -bool partialEquivalenceCheckDD(mEdge u1, mEdge u2, const Qubit d, const Qubit m, - Package& dd) { - if (m == 0) { - return true; - } - if (u1.isTerminal() && u2.isTerminal()) { - return u1 == u2; - } - if (u1.isZeroTerminal() || u2.isZeroTerminal()) { - return false; - } - // add qubits such that u1 and u2 have the same dimension - if (u1.isTerminal()) { - auto w = u1.w; - u1 = dd.makeIdent(u2.p->v + 1); - u1.w = w; - } else if (u2.isTerminal()) { - auto w = u2.w; - u2 = dd.makeIdent(u1.p->v + 1); - u2.w = w; - } else if (u1.p->v < u2.p->v) { - u1 = dd.kronecker(dd.makeIdent(u2.p->v - u1.p->v), u1); - } else if (u1.p->v > u2.p->v) { - u2 = dd.kronecker(dd.makeIdent(u1.p->v - u2.p->v), u2); - } - - const Qubit n = u1.p->v + 1; - Qubit k = n - d; - Qubit extra{0}; - if (m > k) { - extra = m - k; - } - k = k + extra; - - const auto u1Prime = partialEquivalenceCheckDDSubroutine(u1, m, k, extra, dd); - const auto u2Prime = partialEquivalenceCheckDDSubroutine(u2, m, k, extra, dd); - - return u1Prime == u2Prime; -} - -/** - Checks for partial equivalence between the two circuits c1 and c2 - that have no ancilla qubits. - Assumption: the input and output permutations are the same. - - @param circuit1 First circuit - @param circuit2 Second circuit - @return true if the two circuits c1 and c2 are partially equivalent. - **/ -template -bool zeroAncillaePartialEquivalenceCheck(qc::QuantumComputation c1, - qc::QuantumComputation c2, - Package& dd) { - if (c1.getNqubits() != c2.getNqubits() || - c1.getGarbage() != c2.getGarbage()) { - throw std::invalid_argument( - "The circuits need to have the same number of qubits and the same " - "permutation of input and output qubits."); - } - c2.invert(); - for (auto& gate : c1) { - c2.emplace_back(gate); - } - - const auto u = buildFunctionality(&c2, dd, false, false); - - return dd.isCloseToIdentity(u, 1.0E-10, c1.getGarbage(), false); -} - // get next garbage qubit after n inline Qubit getNextGarbage(Qubit n, const std::vector& garbage) { while (n < static_cast(garbage.size()) && !garbage.at(n)) { @@ -132,10 +54,7 @@ bool partialEquivalenceCheck(qc::QuantumComputation c1, } const auto n1 = static_cast(c1.getNqubits()); const auto n2 = static_cast(c2.getNqubits()); - if (d1 == n1 && d2 == n2) { - // no ancilla qubits - return zeroAncillaePartialEquivalenceCheck(c1, c2, dd); - } + // add swaps in order to put the measured (= not garbage) qubits in the end const auto garbage1 = c1.getGarbage(); @@ -157,10 +76,16 @@ bool partialEquivalenceCheck(qc::QuantumComputation c1, const auto u1 = buildFunctionality(&c1, dd, false, false); const auto u2 = buildFunctionality(&c2, dd, false, false); - return partialEquivalenceCheckDD(u1, u2, static_cast(d1), - static_cast(m1), dd); + return true; } +/** + Generate random benchmarks for partial equivalence checking. + @param n number of qubits of the resulting circuits + @param d number of data qubits in the resulting circuits + @param m number of measured qubits in the resulting circuit + @return two circuits that are partially equivalent +**/ std::pair generateRandomBenchmark(size_t n, qc::Qubit d, qc::Qubit m); } // namespace dd From 3fcc10d8a30e15cb1115b45abf687addbce7d1d3 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Wed, 28 Feb 2024 14:41:22 +0100 Subject: [PATCH 11/41] =?UTF-8?q?=F0=9F=9A=A9=20add=20flags=20for=20moving?= =?UTF-8?q?=20data=20and=20measured=20qubits=20to=20the=20front?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Configuration.hpp | 5 ++++ include/EquivalenceCheckingManager.hpp | 11 ++++++++ src/EquivalenceCheckingManager.cpp | 38 ++++++++++++++++++++++++++ src/mqt/qcec/configuration.py | 2 ++ src/mqt/qcec/pyqcec.pyi | 4 +++ src/python/bindings.cpp | 26 +++++++++++++++++- 6 files changed, 85 insertions(+), 1 deletion(-) diff --git a/include/Configuration.hpp b/include/Configuration.hpp index d73888d9..856394fa 100644 --- a/include/Configuration.hpp +++ b/include/Configuration.hpp @@ -40,6 +40,8 @@ class Configuration { bool transformDynamicCircuit = false; bool reorderOperations = true; bool backpropagateOutputPermutation = false; + bool moveDataQubitsToFront = false; + bool moveMeasuredQubitsToFront = false; }; // configuration options for application schemes @@ -161,6 +163,9 @@ class Configuration { opt["reorder_operations"] = optimizations.reorderOperations; opt["backpropagate_output_permutation"] = optimizations.backpropagateOutputPermutation; + opt["move_data_qubits_to_front"] = optimizations.moveDataQubitsToFront; + opt["move_measured_qubits_to_front"] = + optimizations.moveMeasuredQubitsToFront; auto& app = config["application"]; if (execution.runConstructionChecker) { diff --git a/include/EquivalenceCheckingManager.hpp b/include/EquivalenceCheckingManager.hpp index 074f5a3c..c8cd18d8 100644 --- a/include/EquivalenceCheckingManager.hpp +++ b/include/EquivalenceCheckingManager.hpp @@ -131,6 +131,8 @@ class EquivalenceCheckingManager { void reconstructSWAPs(); void reorderOperations(); void backpropagateOutputPermutation(); + void runMoveDataQubitsToFront(); + void runMoveMeasuredQubitsToFront(); // Application: These settings may be changed to influence the sequence in // which gates are applied during the equivalence check @@ -252,6 +254,15 @@ class EquivalenceCheckingManager { /// still highly experimental! void fixOutputPermutationMismatch(); + /// partial equivalence checking assumes that all the data qubits are the + /// first qubits. This functions modifies the initial permutation in order to + /// bring all the data (= not ancillary) qubits to the front + void moveDataQubitsToFront(); + /// partial equivalence checking assumes that all the measured qubits are the + /// first qubits. This functions modifies the output permutation in order to + /// bring all the measured (= not garbage) qubits to the front + void moveMeasuredQubitsToFront(); + /// Run all configured optimization passes void runOptimizationPasses(); diff --git a/src/EquivalenceCheckingManager.cpp b/src/EquivalenceCheckingManager.cpp index 62c5868b..30aef2e7 100644 --- a/src/EquivalenceCheckingManager.cpp +++ b/src/EquivalenceCheckingManager.cpp @@ -96,6 +96,13 @@ void EquivalenceCheckingManager::fixOutputPermutationMismatch() { } } +void EquivalenceCheckingManager::moveDataQubitsToFront() { + // TODO +} +void EquivalenceCheckingManager::moveMeasuredQubitsToFront() { + // TODO +} + void EquivalenceCheckingManager::runOptimizationPasses() { if (qc1.empty() && qc2.empty()) { return; @@ -199,6 +206,14 @@ EquivalenceCheckingManager::EquivalenceCheckingManager( runOptimizationPasses(); } + // bring the data and measured qubits to the front + if (configuration.optimizations.moveDataQubitsToFront) { + moveDataQubitsToFront(); + } + if (configuration.optimizations.moveMeasuredQubitsToFront) { + moveMeasuredQubitsToFront(); + } + // strip away qubits that are not acted upon this->qc1.stripIdleQubits(); this->qc2.stripIdleQubits(); @@ -212,7 +227,16 @@ EquivalenceCheckingManager::EquivalenceCheckingManager( std::clog << "[QCEC] Warning: circuits have different number of primary " "inputs! Proceed with caution!\n"; } + // TODO: remove + // std::cout << "expected output permutation qc1: " << std::endl; + // for (const auto [key_, value_] : qc1.outputPermutation) { + // std::cout << key_ << "->" << value_ << std::endl; + // } + // std::cout << "expected output permutation qc2: " << std::endl; + // for (const auto [key_, value_] : qc2.outputPermutation) { + // std::cout << key_ << "->" << value_ << std::endl; + // } // try to fix a potential mismatch in the output permutations of both circuits if (configuration.optimizations.fixOutputPermutationMismatch) { fixOutputPermutationMismatch(); @@ -791,6 +815,20 @@ void EquivalenceCheckingManager::backpropagateOutputPermutation() { } } +void EquivalenceCheckingManager::runMoveDataQubitsToFront() { + if (!configuration.optimizations.moveDataQubitsToFront) { + moveDataQubitsToFront(); + configuration.optimizations.moveDataQubitsToFront = true; + } +} + +void EquivalenceCheckingManager::runMoveMeasuredQubitsToFront() { + if (!configuration.optimizations.moveMeasuredQubitsToFront) { + moveMeasuredQubitsToFront(); + configuration.optimizations.moveMeasuredQubitsToFront = true; + } +} + nlohmann::json EquivalenceCheckingManager::Results::json() const { nlohmann::json res{}; res["preprocessing_time"] = preprocessingTime; diff --git a/src/mqt/qcec/configuration.py b/src/mqt/qcec/configuration.py index f18acb2f..89458e41 100644 --- a/src/mqt/qcec/configuration.py +++ b/src/mqt/qcec/configuration.py @@ -41,6 +41,8 @@ class ConfigurationOptions(TypedDict, total=False): remove_diagonal_gates_before_measure: bool reorder_operations: bool transform_dynamic_circuit: bool + move_data_qubits_to_front: bool + move_measured_qubits_to_front: bool # Parameterized additional_instantiations: int parameterized_tolerance: float diff --git a/src/mqt/qcec/pyqcec.pyi b/src/mqt/qcec/pyqcec.pyi index 5d092e6c..422f995a 100644 --- a/src/mqt/qcec/pyqcec.pyi +++ b/src/mqt/qcec/pyqcec.pyi @@ -59,6 +59,8 @@ class Configuration: remove_diagonal_gates_before_measure: bool reorder_operations: bool transform_dynamic_circuit: bool + move_data_qubits_to_front: bool + move_measured_qubits_to_front: bool def __init__(self) -> None: ... class Parameterized: @@ -106,6 +108,8 @@ class EquivalenceCheckingManager: def disable_all_checkers(self) -> None: ... def equivalence(self) -> EquivalenceCriterion: ... def fix_output_permutation_mismatch(self) -> None: ... + def move_data_qubits_to_front(self) -> None: ... + def move_measured_qubits_to_front(self) -> None: ... def fuse_single_qubit_gates(self) -> None: ... def get_configuration(self) -> Configuration: ... def get_results(self) -> EquivalenceCheckingManager.Results: ... diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index d9574602..3595064e 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -251,6 +251,20 @@ PYBIND11_MODULE(pyqcec, m) { ":attr:`Backpropagate the output permutation " "<.Configuration.Optimizations.backpropagate_output_permutation>` " "to the input permutation.") + .def( + "move_data_qubits_to_front", + &EquivalenceCheckingManager::runMoveDataQubitsToFront, + "Partial equivalence checking assumes that all the data qubits are " + "the first qubits. This functions modifies the initial permutation " + "in order to :attr:`bring all the data (= not ancillary) qubits to " + "the front <.Configuration.Optimizations.move_data_qubits_to_front>`") + .def("move_measured_qubits_to_front", + &EquivalenceCheckingManager::runMoveMeasuredQubitsToFront, + "partial equivalence checking assumes that all the measured qubits " + "are the first qubits. This functions modifies the output " + "permutation in order to :attr:`bring all the measured (= not " + "garbage) qubits to the front " + "<.Configuration.Optimizations.move_measured_qubits_to_front>`") // Application .def("set_application_scheme", &EquivalenceCheckingManager::setApplicationScheme, @@ -569,7 +583,17 @@ PYBIND11_MODULE(pyqcec, m) { " that have been transformed to a static circuit by enabling the " ":attr:`transform_dynamic_circuit " "<.Configuration.Optimizations.transform_dynamic_circuit>` " - "optimization."); + "optimization.") + .def_readwrite("move_data_qubits_to_front", + &Configuration::Optimizations::moveDataQubitsToFront, + "Moves all data (= not ancillary) qubits to the front. " + "This is only used for partial equivalence checking. It " + "defaults to :code:`False`.") + .def_readwrite("move_measured_qubits_to_front", + &Configuration::Optimizations::moveMeasuredQubitsToFront, + "Moves all measured (= not garbage) qubits to the front. " + "This is only used for partial equivalence checking. It " + "defaults to :code:`False`."); // application options application.def(py::init<>()) From c9de553cc77a0c96d25d9f217afb682b8eecc6be Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Wed, 6 Mar 2024 14:49:08 +0100 Subject: [PATCH 12/41] =?UTF-8?q?=E2=9C=A8=20implemented=20moving=20measur?= =?UTF-8?q?ed=20qubits=20to=20front?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/EquivalenceCheckingManager.cpp | 81 +++++++++++++++++++++--- src/checker/dd/DDConstructionChecker.cpp | 2 +- test/test_partial_equivalence.cpp | 33 +++++++++- 3 files changed, 102 insertions(+), 14 deletions(-) diff --git a/src/EquivalenceCheckingManager.cpp b/src/EquivalenceCheckingManager.cpp index 30aef2e7..4b083a33 100644 --- a/src/EquivalenceCheckingManager.cpp +++ b/src/EquivalenceCheckingManager.cpp @@ -99,8 +99,78 @@ void EquivalenceCheckingManager::fixOutputPermutationMismatch() { void EquivalenceCheckingManager::moveDataQubitsToFront() { // TODO } + +// get next garbage qubit after n +qc::Qubit getNextGarbage(qc::Qubit n, const std::vector& garbage) { + while (n < static_cast(garbage.size()) && !garbage.at(n)) { + n++; + } + return n; +} + +void swapQubits(qc::Permutation& p, qc::Qubit garbage, qc::Qubit measured, + std::vector& garbageVector) { + auto mappedGarbageIt = p.find(garbage); + auto mappedGarbage = mappedGarbageIt == p.end() + ? std::nullopt + : std::optional{mappedGarbageIt->second}; + auto mappedMeasuredIt = p.find(measured); + auto mappedMeasured = + mappedMeasuredIt == p.end() + ? std::nullopt + : std::optional{mappedMeasuredIt->second}; + p.erase(measured); + p.erase(garbage); + if (mappedMeasured.has_value()) { + p.emplace(garbage, *mappedMeasured); + } + if (mappedGarbage.has_value()) { + p.emplace(measured, *mappedGarbage); + } + + // update garbage vector accordingly + auto temp = garbageVector[measured]; + garbageVector[measured] = garbageVector[garbage]; + garbageVector[garbage] = temp; +} + void EquivalenceCheckingManager::moveMeasuredQubitsToFront() { - // TODO + const auto m1 = qc1.getNmeasuredQubits(); + const auto m2 = qc2.getNmeasuredQubits(); + if (m1 != m2) { + std::cerr << "Warning! Number of measured qubit doesn't match in the two " + "circuits.\n"; + } + const auto n1 = static_cast(qc1.getNqubits()); + const auto n2 = static_cast(qc2.getNqubits()); + const auto nqubits = std::max(n1, n2); + + // modify output permutation in order to put the measured (= not garbage) + // qubits in the end + std::vector garbage(nqubits); + for (qc::Qubit q = 0U; q < nqubits; ++q) { + garbage[static_cast(q)] = + qc1.logicalQubitIsGarbage(q) && qc2.logicalQubitIsGarbage(q); + } + + auto nextGarbage = getNextGarbage(0, garbage); + + auto& permutation1 = qc1.outputPermutation; + auto& permutation2 = qc2.outputPermutation; + + // find the first garbage qubit at the end + for (std::int64_t i = std::min(n1, n2) - 1; + i >= static_cast(m1); i--) { + if (!garbage.at(static_cast(i))) { + // swap it to the beginning + swapQubits(permutation1, nextGarbage, static_cast(i), + qc1.garbage); + swapQubits(permutation2, nextGarbage, static_cast(i), + qc2.garbage); + ++nextGarbage; + nextGarbage = getNextGarbage(nextGarbage, garbage); + } + } } void EquivalenceCheckingManager::runOptimizationPasses() { @@ -227,16 +297,7 @@ EquivalenceCheckingManager::EquivalenceCheckingManager( std::clog << "[QCEC] Warning: circuits have different number of primary " "inputs! Proceed with caution!\n"; } - // TODO: remove - // std::cout << "expected output permutation qc1: " << std::endl; - // for (const auto [key_, value_] : qc1.outputPermutation) { - // std::cout << key_ << "->" << value_ << std::endl; - // } - // std::cout << "expected output permutation qc2: " << std::endl; - // for (const auto [key_, value_] : qc2.outputPermutation) { - // std::cout << key_ << "->" << value_ << std::endl; - // } // try to fix a potential mismatch in the output permutations of both circuits if (configuration.optimizations.fixOutputPermutationMismatch) { fixOutputPermutationMismatch(); diff --git a/src/checker/dd/DDConstructionChecker.cpp b/src/checker/dd/DDConstructionChecker.cpp index 685cd211..0269710b 100644 --- a/src/checker/dd/DDConstructionChecker.cpp +++ b/src/checker/dd/DDConstructionChecker.cpp @@ -23,7 +23,6 @@ void DDConstructionChecker::postprocessTask( if (isDone()) { return; } - // TODO: change permutation for partial equivalence if (configuration.functionality.checkPartialEquivalence) { // reduce ancillaries and garbage for partial equivalence check task.reduceForPartialEquivalence(); @@ -35,6 +34,7 @@ void DDConstructionChecker::postprocessTask( if (isDone()) { return; } + task.reduceGarbage(); } } diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index ececca3f..c062028d 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -364,20 +364,47 @@ TEST_F(PartialEquivalenceTest, SliQECAdd19Qubits) { EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST_F(PartialEquivalenceTest, ExamplePaperDifferentQubitOrder) { - // TODO: implement qubit order change +TEST_F(PartialEquivalenceTest, MoveMeasuredQubitsToFrontConstructionChecker) { qc1.cswap(1, 2, 0); qc1.h(2); qc1.z(0); qc1.cswap(1, 2, 0); + qc1.measure(2, 0); qc2.x(1); qc2.ch(1, 2); + qc2.h(0); + qc2.measure(2, 0); qc1.setLogicalQubitsGarbage(0, 1); qc2.setLogicalQubitsGarbage(0, 1); - config.execution.runConstructionChecker = true; + config.execution.runConstructionChecker = true; + config.optimizations.moveMeasuredQubitsToFront = true; + + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(PartialEquivalenceTest, MoveMeasuredQubitsToFrontAlternatingChecker) { + qc1.cswap(1, 2, 0); + qc1.h(2); + qc1.z(0); + qc1.cswap(1, 2, 0); + qc1.measure(2, 0); + + qc2.x(1); + qc2.ch(1, 2); + qc2.h(0); + qc2.measure(2, 0); + + qc1.setLogicalQubitsGarbage(0, 1); + qc2.setLogicalQubitsGarbage(0, 1); + + config.execution.runAlternatingChecker = true; + config.optimizations.moveMeasuredQubitsToFront = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); ecm.run(); EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); From 8b20aed823cb6708000ffb0aec0fefb31b5979bb Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Thu, 7 Mar 2024 14:44:02 +0100 Subject: [PATCH 13/41] =?UTF-8?q?=E2=9C=85=20fix=20python=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/python/test_partial_equivalence.py | 30 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/test/python/test_partial_equivalence.py b/test/python/test_partial_equivalence.py index 8bb2cfb3..08ce6893 100644 --- a/test/python/test_partial_equivalence.py +++ b/test/python/test_partial_equivalence.py @@ -22,17 +22,39 @@ def original_circuit() -> QuantumCircuit: @pytest.fixture() def alternative_circuit() -> QuantumCircuit: - """Fixture for an alternative version of the simple circuit.""" + """Fixture for a partially equivalent version of the simple circuit.""" qc = QuantumCircuit(3, 1) qc.x(1) - qc.cx(0, 1) qc.ch(1, 0) qc.measure(0, 0) return qc -@pytest.mark.skip() def test_configuration_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: - """Test if the flag for partial equivalence checking works. This test is skipped for now, because partial equivalence checking was not implemented yet.""" + """Test if the flag for partial equivalence checking works.""" + config = qcec.Configuration() + config.functionality.check_partial_equivalence = True + result = qcec.verify(original_circuit, alternative_circuit, configuration=config) + assert result.equivalence == qcec.EquivalenceCriterion.equivalent + + +def test_verify_argument_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: + """Test if the flag for partial equivalence checking works.""" result = qcec.verify(original_circuit, alternative_circuit, check_partial_equivalence=True) assert result.equivalence == qcec.EquivalenceCriterion.equivalent + + +def test_verify_argument_move_data_to_front() -> None: + """Test if the flag for moving masured qubits to the front works.""" + qc1 = QuantumCircuit(3, 1) + qc1.cswap(1, 2, 0) + qc1.h(2) + qc1.z(0) + qc1.cswap(1, 2, 0) + qc1.measure(2, 0) + qc2 = QuantumCircuit(3, 1) + qc2.x(1) + qc2.ch(1, 2) + qc2.measure(2, 0) + result = qcec.verify(qc1, qc2, check_partial_equivalence=True, move_data_qubits_to_front=True) + assert result.equivalence == qcec.EquivalenceCriterion.equivalent From a4aba7e7e0886cc70437790410fce9fdb4ffaaf1 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Thu, 7 Mar 2024 19:10:03 +0100 Subject: [PATCH 14/41] =?UTF-8?q?=E2=9C=85=20fix=20python=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/python/test_partial_equivalence.py | 28 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/test/python/test_partial_equivalence.py b/test/python/test_partial_equivalence.py index 08ce6893..d547f3eb 100644 --- a/test/python/test_partial_equivalence.py +++ b/test/python/test_partial_equivalence.py @@ -38,23 +38,35 @@ def test_configuration_pec(original_circuit: QuantumCircuit, alternative_circuit assert result.equivalence == qcec.EquivalenceCriterion.equivalent -def test_verify_argument_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: +def test_argument_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: """Test if the flag for partial equivalence checking works.""" result = qcec.verify(original_circuit, alternative_circuit, check_partial_equivalence=True) assert result.equivalence == qcec.EquivalenceCriterion.equivalent -def test_verify_argument_move_data_to_front() -> None: - """Test if the flag for moving masured qubits to the front works.""" - qc1 = QuantumCircuit(3, 1) +def test_argument_move_measured_to_front() -> None: + """Test if the flag for moving measured qubits to the front works.""" + qc1 = QuantumCircuit(3, 3) qc1.cswap(1, 2, 0) qc1.h(2) qc1.z(0) qc1.cswap(1, 2, 0) - qc1.measure(2, 0) - qc2 = QuantumCircuit(3, 1) + qc1.measure(2, 2) + + qc2 = QuantumCircuit(3, 3) qc2.x(1) qc2.ch(1, 2) - qc2.measure(2, 0) - result = qcec.verify(qc1, qc2, check_partial_equivalence=True, move_data_qubits_to_front=True) + qc2.measure(2, 2) + + result = qcec.verify( + qc1, + qc2, + check_partial_equivalence=True, + move_measured_qubits_to_front=True, + run_alternating_checker=True, + run_construction_checker=False, + run_simulation_checker=False, + run_zx_checker=False, + ) + assert result.equivalence == qcec.EquivalenceCriterion.equivalent From 9d6e2bc6b6a9f203057c2039653268f80d889bc5 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Mon, 11 Mar 2024 13:46:35 +0100 Subject: [PATCH 15/41] =?UTF-8?q?=F0=9F=93=9D=20started=20to=20write=20doc?= =?UTF-8?q?umentation=20for=20partial=20equivalence=20checking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/PartialEquivalence.ipynb | 144 +++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 docs/source/PartialEquivalence.ipynb diff --git a/docs/source/PartialEquivalence.ipynb b/docs/source/PartialEquivalence.ipynb new file mode 100644 index 00000000..4209608e --- /dev/null +++ b/docs/source/PartialEquivalence.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "77a131e6", + "metadata": {}, + "source": [ + "# Partial Equivalence Checking of Quantum Circuits\n", + "\n", + "## Partial Equivalence vs. Total Equivalence\n", + "\n", + "Different definitions of quantum circuit equivalence have been proposed, with the most commonly used being total equivalence. Two circuits are considered totally equivalent when their matrix representations are exactly the same. However, it is often sufficient to consider observational equivalence, because the only way to extract information from a quantum circuit is through measurement. Therefore, partial equivalence has been defined, which is a weaker equality than total equivalence. Two circuits are considered partially equivalent if, for each possible input state, they have the same probabilities for each measurement outcome. \n", + "\n", + "This definition is especially useful for circuits that do not measure all of their qubits at the end, or where some qubits are initialized to a certain value at the beginning. We refer to the qubits that are initialized to a certain value at the beginning of the computation *ancillary* qubits. Without loss of generality, we assume that these qubits are initially set to $|0\\rangle$. Any other initial state can be reached from the $|0\\rangle$ state by applying the appropriate gates. The remaining qubits are the qubits that hold the input state, and they are referred to as *data* qubits.\n", + "\n", + "Similarly, we differentiate between *measured* and *garbage* qubits. In order to read the output at the end of a circuit, a measurement is performed on some qubits, but not necessarily all of them. These qubits are the *measured* qubits. All qubits that are not measured are called the *garbage* qubits. Their final state doesn't influence the output we obtain from the computation. \n", + "\n", + "For a circuit $C$ we denote $P(t | \\psi, C)$ as the probability that the quantum circuit $C$ collapses to state $|t\\rangle$ upon a measurement on the measured qubits, given that the data qubits have the initial state $|\\psi\\rangle$.\n", + "\n", + "With these concepts we can provide an exact definition of partial equivalence. Two circuits $C_1$ and $C_2$ are considered partially equivalent if, for each initial state $|\\psi\\rangle$ of the data qubits and each final state $|t\\rangle$ of the measured qubits, it holds that $P(t|\\psi, C_1) = P(t|\\psi, C_2)$.\n" + ] + }, + { + "cell_type": "markdown", + "id": "b9be796e", + "metadata": {}, + "source": [ + "\n", + "## Equivalence Checking of Partially Equivalent Quantum Circuits\n", + "\n", + "Partial equivalence checking is a bit more costly than regular equivalence checking. Therefore, it is not enabled by default in QCEC. It can be activated using an option in the configuration parameters. If the option `check_partial_equivalence` is set to `True`, the equivalence checker will return `equivalent` not only for totally equivalent circuits, but also for partially equivalent circuits. The result will be `not_equivalent` if and only if the circuits are not partially equivalent.\n", + "\n", + "The following is a summary of the behaviour of each type of equivalence checker when the `check_partial_equivalence` option is set to `True`.\n", + "\n", + "1. **Construction Equivalence Checker:** The construction checker supports partial equivalence checking by using decision diagrams to calculate the measurement probabilities of the possible ouputs and it compares the results for the two circuits.\n", + "\n", + "1. **Alternating Equivalence Checker:** The alternating checker can only be used for circuits where at least one of the two does not contain ancillary qubits. It normally computes the composition of one circuit with the inverse of the other and verifies that the result is the identity matrix. When checking for partial equivalence, it suffices to verify that the result is a diagonal matrix (modulo garbage qubits). This check doesn't have a signifi\n", + "\n", + "1. **Simulation Equivalence Checker:** The simulation checker ...\n", + "\n", + "1. **ZX-Calculus Equivalence Checker:** The ZX-calculus checker doesn't directly support partial equivalence, which is not a problem for the equivalence checking workflow, given that the ZX-calculus checker cannot demonstrate non-equivalence of circuits. Therefore it will simply output 'No Information' for circuits that are partially but not totally equivalent." + ] + }, + { + "cell_type": "markdown", + "id": "977071d9", + "metadata": {}, + "source": [ + "## Using QCEC to Verify Partial Equivalent Circuits\n", + "\n", + "Consider the following quantum circuit with three qubits, which are all data qubits, but only one of them is measured." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03b73b17", + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit import QuantumCircuit\n", + "\n", + "qc_lhs = QuantumCircuit(3, 1)\n", + "qc_lhs.cswap(1, 0, 2)\n", + "qc_lhs.h(0)\n", + "qc_lhs.z(2)\n", + "qc_lhs.cswap(1, 0, 2)\n", + "qc_lhs.measure(0, 0)\n", + "\n", + "qc_lhs.draw(output=\"mpl\", style=\"iqp\")" + ] + }, + { + "cell_type": "markdown", + "id": "3b85338e", + "metadata": {}, + "source": [ + "The following circuit is not totally equivalent to the previous one. The two circuits are however partially equivalent, because they have the same probability distribution of measured values for any given initial input state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36df44b7", + "metadata": {}, + "outputs": [], + "source": [ + "qc_rhs = QuantumCircuit(3, 1)\n", + "qc_rhs.x(1)\n", + "qc_rhs.ch(1, 0)\n", + "qc_rhs.measure(0, 0)\n", + "qc_rhs.draw(output=\"mpl\", style=\"iqp\")" + ] + }, + { + "cell_type": "markdown", + "id": "8cae4862", + "metadata": {}, + "source": [ + "This equality can be proved with QCEC by using the `verify` method and setting the configuration `check_partial_equivalence` to `True`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da9fa188", + "metadata": {}, + "outputs": [], + "source": [ + "from mqt import qcec\n", + "\n", + "qcec.verify(qc_lhs, qc_rhs, check_partial_equivalence=True)" + ] + }, + { + "cell_type": "markdown", + "id": "6af54b68", + "metadata": {}, + "source": [ + "Source: The definitions and algorithm for partial equivalence are described in the paper [Partial Equivalence Checking of Quantum Circuits](https://arxiv.org/abs/2208.07564) by Tian-Fu Chen, Jie-Hong R. Jiang and Min-Hsiu Hsieh" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From b7b2f947eee83ba5dc1a5f96147f44f4741be467 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Wed, 13 Mar 2024 11:26:03 +0100 Subject: [PATCH 16/41] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20mqt-core?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 2 +- extern/mqt-core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 027eb41f..f538dfa5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "extern/mqt-core"] path = extern/mqt-core url = https://github.com/reb-ddm/mqt-core.git - branch = partial-equivalence-checking + branch = partial-equivalence-reduce-garbage diff --git a/extern/mqt-core b/extern/mqt-core index c0f54319..a6d3bc0d 160000 --- a/extern/mqt-core +++ b/extern/mqt-core @@ -1 +1 @@ -Subproject commit c0f5431908cfdc97248807e0f3390ae46916dd67 +Subproject commit a6d3bc0d19d53e142aba23bd5b1c08833ad11e0e From dc5037aa66eb262a6ec59717c4428186f637d1c8 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Wed, 13 Mar 2024 11:33:20 +0100 Subject: [PATCH 17/41] =?UTF-8?q?=F0=9F=90=9B=20fix=20bug=20in=20benchmark?= =?UTF-8?q?=20generation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/checker/dd/DDPartialEquivalence.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/checker/dd/DDPartialEquivalence.cpp b/src/checker/dd/DDPartialEquivalence.cpp index fff3d02b..ee4be1d0 100644 --- a/src/checker/dd/DDPartialEquivalence.cpp +++ b/src/checker/dd/DDPartialEquivalence.cpp @@ -85,7 +85,7 @@ void addStandardOperationToCircuit(QuantumComputation& circuit, std::vector fiveDiffferentRandomNumbers(const qc::Qubit min, const qc::Qubit max, - std::mt19937_64 randomGenerator) { + std::mt19937_64& randomGenerator) { std::vector numbers; for (qc::Qubit i = min; i < max; i++) { @@ -179,10 +179,10 @@ StandardOperation convertToStandardOperation( return {n, randomTarget1, qc::I}; } -StandardOperation makeRandomStandardOperation(const size_t n, - const qc::Qubit nrQubits, - const qc::Qubit min, - std::mt19937_64 randomGenerator) { +StandardOperation +makeRandomStandardOperation(const size_t n, const qc::Qubit nrQubits, + const qc::Qubit min, + std::mt19937_64& randomGenerator) { const auto randomNumbers = fiveDiffferentRandomNumbers(min, min + nrQubits, randomGenerator); From d5aebd5ee1bf8a73b410b3daba358bbbe88b4c83 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Wed, 13 Mar 2024 11:34:50 +0100 Subject: [PATCH 18/41] reduce garbage only for partial equivalence checking --- include/checker/dd/TaskManager.hpp | 48 +++++++++++------------- src/checker/dd/DDConstructionChecker.cpp | 19 +++++----- src/checker/dd/DDEquivalenceChecker.cpp | 4 +- 3 files changed, 33 insertions(+), 38 deletions(-) diff --git a/include/checker/dd/TaskManager.hpp b/include/checker/dd/TaskManager.hpp index a349649c..907ce42f 100644 --- a/include/checker/dd/TaskManager.hpp +++ b/include/checker/dd/TaskManager.hpp @@ -114,12 +114,31 @@ template class TaskManager { } void reduceAncillae() { reduceAncillae(internalState); } + /** + Reduces garbage qubits such that the matrix will be equal to another reduced + matrix iff the two underlying circuits are partially equivalent. + **/ void reduceGarbage(DDType& state) { if constexpr (std::is_same_v) { - state = package->reduceGarbage(state, qc->garbage); + state = package->reduceGarbage(state, qc->garbage, true); } else if constexpr (std::is_same_v) { + // version of the paper + // const auto d = static_cast(qc->getNqubitsWithoutAncillae()); + // const auto m = static_cast(qc->getNmeasuredQubits()); + + // const dd::Qubit n = state.p->v + 1; + // dd::Qubit k = n - d; + // dd::Qubit extra{0}; + // if (m > k) { + // extra = m - k; + // } + // k = k + extra; + // state = partialEquivalenceCheckDDSubroutine(state, m, k, extra, + // *package); + + // version with reduceGarbage state = package->reduceGarbage(state, qc->garbage, - static_cast(direction)); + static_cast(direction), true); } } void reduceGarbage() { reduceGarbage(internalState); } @@ -130,31 +149,6 @@ template class TaskManager { void decRef(DDType& state) { package->decRef(state); } void decRef() { decRef(internalState); } - /** - Reduces ancillaries and garbage according to the number of garbage and - ancillary qubits such that the matrix will be equal to another reduced matrix - iff the two underlying circuits are partially equivalent. - Assumption: the measured and data qubits are the first qubits. - **/ - void reduceForPartialEquivalence(dd::mEdge& state) { - const auto d = static_cast(qc->getNqubitsWithoutAncillae()); - const auto m = static_cast(qc->getNmeasuredQubits()); - - const dd::Qubit n = state.p->v + 1; - dd::Qubit k = n - d; - dd::Qubit extra{0}; - if (m > k) { - extra = m - k; - } - k = k + extra; - - state = partialEquivalenceCheckDDSubroutine(state, m, k, extra, *package); - } - - void reduceForPartialEquivalence() { - reduceForPartialEquivalence(internalState); - } - private: const qc::QuantumComputation* qc{}; DDPackage* package; diff --git a/src/checker/dd/DDConstructionChecker.cpp b/src/checker/dd/DDConstructionChecker.cpp index 0269710b..885cab44 100644 --- a/src/checker/dd/DDConstructionChecker.cpp +++ b/src/checker/dd/DDConstructionChecker.cpp @@ -23,17 +23,16 @@ void DDConstructionChecker::postprocessTask( if (isDone()) { return; } - if (configuration.functionality.checkPartialEquivalence) { - // reduce ancillaries and garbage for partial equivalence check - task.reduceForPartialEquivalence(); + // reduce ancillaries for total equivalence check + // eliminate the superfluous contributions of ancillary qubits (this only + // has an effect on matrices) + task.reduceAncillae(); - } else { // reduce ancillaries for total equivalence check - // eliminate the superfluous contributions of ancillary qubits (this only - // has an effect on matrices) - task.reduceAncillae(); - if (isDone()) { - return; - } + if (isDone()) { + return; + } + if (configuration.functionality.checkPartialEquivalence) { + // reduce garbage for partial equivalence check task.reduceGarbage(); } } diff --git a/src/checker/dd/DDEquivalenceChecker.cpp b/src/checker/dd/DDEquivalenceChecker.cpp index 1efdfda9..6f810673 100644 --- a/src/checker/dd/DDEquivalenceChecker.cpp +++ b/src/checker/dd/DDEquivalenceChecker.cpp @@ -204,7 +204,9 @@ void DDEquivalenceChecker::postprocessTask( return; } // sum up the contributions of garbage qubits - task.reduceGarbage(); + if (configuration.functionality.checkPartialEquivalence) { + task.reduceGarbage(); + } } template From fb07a5bd791a280fa5f975d57ae9582c06810b89 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Wed, 13 Mar 2024 11:46:25 +0100 Subject: [PATCH 19/41] reduce garbage only for partial equivalence checking in alternating checker --- src/checker/dd/DDAlternatingChecker.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/checker/dd/DDAlternatingChecker.cpp b/src/checker/dd/DDAlternatingChecker.cpp index 557116b4..92cc6a36 100644 --- a/src/checker/dd/DDAlternatingChecker.cpp +++ b/src/checker/dd/DDAlternatingChecker.cpp @@ -107,8 +107,7 @@ EquivalenceCriterion DDAlternatingChecker::checkEquivalence() { // suffices to change the last parameter of isCloseToIdentity to `false` if (configuration.functionality.checkPartialEquivalence) { isClose = dd->isCloseToIdentity(functionality, - configuration.functionality.traceThreshold, - garbage, false); + configuration.functionality.traceThreshold); } else { isClose = dd->isCloseToIdentity(functionality, configuration.functionality.traceThreshold, From 207a6f00d6ed8dca5887c9bf8fe46a9f0da179f8 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Wed, 13 Mar 2024 11:50:18 +0100 Subject: [PATCH 20/41] reduce garbage only for partial equivalence checking in alternating checker --- src/checker/dd/DDAlternatingChecker.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/checker/dd/DDAlternatingChecker.cpp b/src/checker/dd/DDAlternatingChecker.cpp index 92cc6a36..f10ce235 100644 --- a/src/checker/dd/DDAlternatingChecker.cpp +++ b/src/checker/dd/DDAlternatingChecker.cpp @@ -107,11 +107,11 @@ EquivalenceCriterion DDAlternatingChecker::checkEquivalence() { // suffices to change the last parameter of isCloseToIdentity to `false` if (configuration.functionality.checkPartialEquivalence) { isClose = dd->isCloseToIdentity(functionality, - configuration.functionality.traceThreshold); + configuration.functionality.traceThreshold, + garbage, false); } else { isClose = dd->isCloseToIdentity(functionality, - configuration.functionality.traceThreshold, - garbage, true); + configuration.functionality.traceThreshold); } if (isClose) { From 3e251dec93186874597e45f425da265a67bb38c9 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Wed, 13 Mar 2024 13:17:17 +0100 Subject: [PATCH 21/41] =?UTF-8?q?=E2=9C=85=20updated=20tests=20for=20parti?= =?UTF-8?q?al=20equivalence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/test_partial_equivalence.cpp | 180 +++++++++++++++++------------- 1 file changed, 102 insertions(+), 78 deletions(-) diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index c062028d..6999f8b1 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -18,12 +18,13 @@ class PartialEquivalenceTest : public testing::Test { config.optimizations.fuseSingleQubitGates = false; config.optimizations.reorderOperations = false; config.optimizations.reconstructSWAPs = false; - config.optimizations.fixOutputPermutationMismatch = true; + config.optimizations.fixOutputPermutationMismatch = false; config.execution.runSimulationChecker = false; config.execution.runAlternatingChecker = false; config.execution.runConstructionChecker = false; config.execution.runZXChecker = false; + config.execution.nthreads = 1; config.functionality.checkPartialEquivalence = true; } @@ -58,13 +59,16 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbage) { qc2.setLogicalQubitGarbage(2); qc2.setLogicalQubitGarbage(1); - config.execution.runAlternatingChecker = true; - config.functionality.checkPartialEquivalence = false; + config.execution.runAlternatingChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); - ecm.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm.run(); - EXPECT_EQ(ecm.equivalence(), - ec::EquivalenceCriterion::EquivalentUpToGlobalPhase); + EXPECT_TRUE(ecm.getResults().consideredEquivalent()); + + config.functionality.checkPartialEquivalence = false; + ec::EquivalenceCheckingManager ecm2(qc1, qc2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbage2) { @@ -78,6 +82,8 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbage2) { qc1.z(2); // measured qubit: 1 + qc1.setLogicalQubitGarbage(0); + qc1.setLogicalQubitGarbage(2); qc2.setLogicalQubitGarbage(0); qc2.setLogicalQubitGarbage(2); @@ -87,20 +93,19 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbage2) { qc2.ry(0.1, 2); qc2.cx(2, 0); - config.execution.runAlternatingChecker = true; - config.functionality.checkPartialEquivalence = false; + config.execution.runAlternatingChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); - ecm.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm.run(); - EXPECT_EQ(ecm.equivalence(), - ec::EquivalenceCriterion::EquivalentUpToGlobalPhase); + EXPECT_TRUE(ecm.getResults().consideredEquivalent()); + + config.functionality.checkPartialEquivalence = false; + ec::EquivalenceCheckingManager ecm2(qc1, qc2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageAndAncillary) { - qc1.setLogicalQubitGarbage(2); - qc1.setLogicalQubitGarbage(1); - qc1.setLogicalQubitAncillary(2); - qc1.h(0); qc1.tdg(1); qc1.s(1); @@ -115,13 +120,19 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageAndAncillary) { qc3.rz(dd::PI_4, 1); qc3.ry(0.1, 1); - config.execution.runAlternatingChecker = true; - config.functionality.checkPartialEquivalence = false; + qc1.setLogicalQubitGarbage(2); + qc1.setLogicalQubitGarbage(1); + qc1.setLogicalQubitAncillary(2); + + config.execution.runAlternatingChecker = true; ec::EquivalenceCheckingManager ecm(qc1, qc3, config); - ecm.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm.run(); - EXPECT_EQ(ecm.equivalence(), - ec::EquivalenceCriterion::EquivalentUpToGlobalPhase); + EXPECT_TRUE(ecm.getResults().consideredEquivalent()); + + config.functionality.checkPartialEquivalence = false; + ec::EquivalenceCheckingManager ecm2(qc1, qc3, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent) { @@ -156,8 +167,6 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent) { EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } -using namespace qc::literals; - TEST_F(PartialEquivalenceTest, TrivialEquivalence) { auto qc = qc::QuantumComputation(2); @@ -234,6 +243,7 @@ TEST_F(PartialEquivalenceTest, ConstructionCheckerGarbageNotEquivalent) { qc2.x(1); qc2.ch(1, 0); + qc2.h(2); qc1.setLogicalQubitGarbage(2); qc1.setLogicalQubitGarbage(1); @@ -255,6 +265,37 @@ TEST_F(PartialEquivalenceTest, ConstructionCheckerGarbageNotEquivalent) { EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } +TEST_F(PartialEquivalenceTest, SimulationCheckerGarbageNotEquivalent) { + // example from the paper https://arxiv.org/abs/2208.07564 + qc1.cswap(1, 0, 2); + qc1.h(0); + qc1.z(2); + qc1.cswap(1, 0, 2); + + qc2.x(1); + qc2.ch(1, 0); + qc2.h(2); + + qc1.setLogicalQubitGarbage(2); + qc1.setLogicalQubitGarbage(1); + qc2.setLogicalQubitGarbage(2); + qc2.setLogicalQubitGarbage(1); + + // partially equivalent circuits + config.execution.runSimulationChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::ProbablyEquivalent); + + // these two circuits are only partially equivalent, + // therefore the equivalence checker returns NotEquivalent when we disable + // partial equality checking + config.functionality.checkPartialEquivalence = false; + ec::EquivalenceCheckingManager ecm2(qc1, qc2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); +} + TEST_F(PartialEquivalenceTest, ConstructionCheckerDifferentNumberOfQubits) { qc1.cswap(1, 0, 2); qc1.h(0); @@ -283,13 +324,17 @@ TEST_F(PartialEquivalenceTest, MQTBenchGrover3Qubits) { const qc::QuantumComputation c2{ "./circuits/partialEquivalenceTest/grover-noancilla_indep_qiskit_3.qasm"}; + c1.print(std::cout); + c2.print(std::cout); // 3 measured qubits and 3 data qubits, full equivalence // construction checker config.execution.runConstructionChecker = true; ec::EquivalenceCheckingManager ecm(c1, c2, config); ecm.run(); - EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); + EXPECT_TRUE(ecm.getResults().consideredEquivalent()); + c1.print(std::cout); + c2.print(std::cout); // alternating checker config.execution.runConstructionChecker = false; config.execution.runAlternatingChecker = true; @@ -364,52 +409,6 @@ TEST_F(PartialEquivalenceTest, SliQECAdd19Qubits) { EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); } -TEST_F(PartialEquivalenceTest, MoveMeasuredQubitsToFrontConstructionChecker) { - qc1.cswap(1, 2, 0); - qc1.h(2); - qc1.z(0); - qc1.cswap(1, 2, 0); - qc1.measure(2, 0); - - qc2.x(1); - qc2.ch(1, 2); - qc2.h(0); - qc2.measure(2, 0); - - qc1.setLogicalQubitsGarbage(0, 1); - qc2.setLogicalQubitsGarbage(0, 1); - - config.execution.runConstructionChecker = true; - config.optimizations.moveMeasuredQubitsToFront = true; - - ec::EquivalenceCheckingManager ecm(qc1, qc2, config); - ecm.run(); - EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); -} - -TEST_F(PartialEquivalenceTest, MoveMeasuredQubitsToFrontAlternatingChecker) { - qc1.cswap(1, 2, 0); - qc1.h(2); - qc1.z(0); - qc1.cswap(1, 2, 0); - qc1.measure(2, 0); - - qc2.x(1); - qc2.ch(1, 2); - qc2.h(0); - qc2.measure(2, 0); - - qc1.setLogicalQubitsGarbage(0, 1); - qc2.setLogicalQubitsGarbage(0, 1); - - config.execution.runAlternatingChecker = true; - config.optimizations.moveMeasuredQubitsToFront = true; - - ec::EquivalenceCheckingManager ecm(qc1, qc2, config); - ecm.run(); - EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); -} - TEST_F(PartialEquivalenceTest, ExamplePaperDifferentQubitOrderAndNumber) { qc::QuantumComputation c1{4, 1}; c1.cswap(1, 2, 0); @@ -526,25 +525,24 @@ void partialEquivalencCheckingBenchmarks(const qc::Qubit minN, const auto [c1, c2] = dd::generateRandomBenchmark(n, d, m); - // check equivalence ec::EquivalenceCheckingManager ecm(c1, c2, config); ecm.run(); EXPECT_TRUE(ecm.getResults().consideredEquivalent()); + // if (!ecm.getResults().consideredEquivalent()) { + // std::cout << "c1:\n"; + // c1.print(std::cout); + // std::cout << "c2:\n"; + // c2.print(std::cout); + // } const auto duration = ecm.getResults().checkTime; - // std::cout << "\nnumber of qubits = " << n << "; data qubits = " << d - // << "; measured qubits = " << m - // << "; number of gates = " << c2.size() << "\n"; - // std::cout << "time: " << static_cast(duration.count()) / - // 1000000. - // << " seconds\n"; totalTime += duration; totalGates += c2.size(); } std::cout << "\nnumber of qubits = " << n << "; number of reps = " << reps << "; average time = " - << (totalTime / static_cast(reps) / 1000000.) + << (totalTime / static_cast(reps) /*/ 1000000.*/) << " seconds; average number of gates = " << (static_cast(totalGates) / static_cast(reps)) << "\n"; @@ -563,8 +561,34 @@ TEST_F(PartialEquivalenceTest, Benchmark) { TEST_F(PartialEquivalenceTest, ZeroAncillaBenchmark) { config.execution.runAlternatingChecker = true; const size_t minN = 3; - const size_t maxN = 15; + const size_t maxN = 14; const size_t reps = 10; std::cout << "Zero-ancilla partial equivalence check\n"; partialEquivalencCheckingBenchmarks(minN, maxN, reps, false, config); } + +TEST_F(PartialEquivalenceTest, ConstructionCheckerPartiallyEquivalent) { + // the first qubit has differing gates in the two circuits, + // therefore they should not be equivalent if we only measure the first qubit + qc2.h(0); + qc2.h(0); + qc2.h(1); + qc2.h(1); + qc1.tdg(0); + qc1.tdg(1); + + qc2.h(0); + qc2.h(0); + qc2.h(1); + qc2.h(1); + + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); + + config.functionality.checkPartialEquivalence = false; + ec::EquivalenceCheckingManager ecm2(qc1, qc2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); +} From 1959bc0a2789fd3d293d84bd0a54ca0ff1ca301f Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Fri, 15 Mar 2024 16:29:02 +0100 Subject: [PATCH 22/41] =?UTF-8?q?=F0=9F=94=A5=20remove=20flags=20for=20bri?= =?UTF-8?q?nging=20data=20and=20ancillary=20qubits=20to=20front?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Configuration.hpp | 5 -- include/EquivalenceCheckingManager.hpp | 11 --- src/EquivalenceCheckingManager.cpp | 99 -------------------------- src/mqt/qcec/configuration.py | 2 - src/mqt/qcec/pyqcec.pyi | 4 -- src/python/bindings.cpp | 26 +------ 6 files changed, 1 insertion(+), 146 deletions(-) diff --git a/include/Configuration.hpp b/include/Configuration.hpp index 856394fa..d73888d9 100644 --- a/include/Configuration.hpp +++ b/include/Configuration.hpp @@ -40,8 +40,6 @@ class Configuration { bool transformDynamicCircuit = false; bool reorderOperations = true; bool backpropagateOutputPermutation = false; - bool moveDataQubitsToFront = false; - bool moveMeasuredQubitsToFront = false; }; // configuration options for application schemes @@ -163,9 +161,6 @@ class Configuration { opt["reorder_operations"] = optimizations.reorderOperations; opt["backpropagate_output_permutation"] = optimizations.backpropagateOutputPermutation; - opt["move_data_qubits_to_front"] = optimizations.moveDataQubitsToFront; - opt["move_measured_qubits_to_front"] = - optimizations.moveMeasuredQubitsToFront; auto& app = config["application"]; if (execution.runConstructionChecker) { diff --git a/include/EquivalenceCheckingManager.hpp b/include/EquivalenceCheckingManager.hpp index c8cd18d8..074f5a3c 100644 --- a/include/EquivalenceCheckingManager.hpp +++ b/include/EquivalenceCheckingManager.hpp @@ -131,8 +131,6 @@ class EquivalenceCheckingManager { void reconstructSWAPs(); void reorderOperations(); void backpropagateOutputPermutation(); - void runMoveDataQubitsToFront(); - void runMoveMeasuredQubitsToFront(); // Application: These settings may be changed to influence the sequence in // which gates are applied during the equivalence check @@ -254,15 +252,6 @@ class EquivalenceCheckingManager { /// still highly experimental! void fixOutputPermutationMismatch(); - /// partial equivalence checking assumes that all the data qubits are the - /// first qubits. This functions modifies the initial permutation in order to - /// bring all the data (= not ancillary) qubits to the front - void moveDataQubitsToFront(); - /// partial equivalence checking assumes that all the measured qubits are the - /// first qubits. This functions modifies the output permutation in order to - /// bring all the measured (= not garbage) qubits to the front - void moveMeasuredQubitsToFront(); - /// Run all configured optimization passes void runOptimizationPasses(); diff --git a/src/EquivalenceCheckingManager.cpp b/src/EquivalenceCheckingManager.cpp index 4b083a33..62c5868b 100644 --- a/src/EquivalenceCheckingManager.cpp +++ b/src/EquivalenceCheckingManager.cpp @@ -96,83 +96,6 @@ void EquivalenceCheckingManager::fixOutputPermutationMismatch() { } } -void EquivalenceCheckingManager::moveDataQubitsToFront() { - // TODO -} - -// get next garbage qubit after n -qc::Qubit getNextGarbage(qc::Qubit n, const std::vector& garbage) { - while (n < static_cast(garbage.size()) && !garbage.at(n)) { - n++; - } - return n; -} - -void swapQubits(qc::Permutation& p, qc::Qubit garbage, qc::Qubit measured, - std::vector& garbageVector) { - auto mappedGarbageIt = p.find(garbage); - auto mappedGarbage = mappedGarbageIt == p.end() - ? std::nullopt - : std::optional{mappedGarbageIt->second}; - auto mappedMeasuredIt = p.find(measured); - auto mappedMeasured = - mappedMeasuredIt == p.end() - ? std::nullopt - : std::optional{mappedMeasuredIt->second}; - p.erase(measured); - p.erase(garbage); - if (mappedMeasured.has_value()) { - p.emplace(garbage, *mappedMeasured); - } - if (mappedGarbage.has_value()) { - p.emplace(measured, *mappedGarbage); - } - - // update garbage vector accordingly - auto temp = garbageVector[measured]; - garbageVector[measured] = garbageVector[garbage]; - garbageVector[garbage] = temp; -} - -void EquivalenceCheckingManager::moveMeasuredQubitsToFront() { - const auto m1 = qc1.getNmeasuredQubits(); - const auto m2 = qc2.getNmeasuredQubits(); - if (m1 != m2) { - std::cerr << "Warning! Number of measured qubit doesn't match in the two " - "circuits.\n"; - } - const auto n1 = static_cast(qc1.getNqubits()); - const auto n2 = static_cast(qc2.getNqubits()); - const auto nqubits = std::max(n1, n2); - - // modify output permutation in order to put the measured (= not garbage) - // qubits in the end - std::vector garbage(nqubits); - for (qc::Qubit q = 0U; q < nqubits; ++q) { - garbage[static_cast(q)] = - qc1.logicalQubitIsGarbage(q) && qc2.logicalQubitIsGarbage(q); - } - - auto nextGarbage = getNextGarbage(0, garbage); - - auto& permutation1 = qc1.outputPermutation; - auto& permutation2 = qc2.outputPermutation; - - // find the first garbage qubit at the end - for (std::int64_t i = std::min(n1, n2) - 1; - i >= static_cast(m1); i--) { - if (!garbage.at(static_cast(i))) { - // swap it to the beginning - swapQubits(permutation1, nextGarbage, static_cast(i), - qc1.garbage); - swapQubits(permutation2, nextGarbage, static_cast(i), - qc2.garbage); - ++nextGarbage; - nextGarbage = getNextGarbage(nextGarbage, garbage); - } - } -} - void EquivalenceCheckingManager::runOptimizationPasses() { if (qc1.empty() && qc2.empty()) { return; @@ -276,14 +199,6 @@ EquivalenceCheckingManager::EquivalenceCheckingManager( runOptimizationPasses(); } - // bring the data and measured qubits to the front - if (configuration.optimizations.moveDataQubitsToFront) { - moveDataQubitsToFront(); - } - if (configuration.optimizations.moveMeasuredQubitsToFront) { - moveMeasuredQubitsToFront(); - } - // strip away qubits that are not acted upon this->qc1.stripIdleQubits(); this->qc2.stripIdleQubits(); @@ -876,20 +791,6 @@ void EquivalenceCheckingManager::backpropagateOutputPermutation() { } } -void EquivalenceCheckingManager::runMoveDataQubitsToFront() { - if (!configuration.optimizations.moveDataQubitsToFront) { - moveDataQubitsToFront(); - configuration.optimizations.moveDataQubitsToFront = true; - } -} - -void EquivalenceCheckingManager::runMoveMeasuredQubitsToFront() { - if (!configuration.optimizations.moveMeasuredQubitsToFront) { - moveMeasuredQubitsToFront(); - configuration.optimizations.moveMeasuredQubitsToFront = true; - } -} - nlohmann::json EquivalenceCheckingManager::Results::json() const { nlohmann::json res{}; res["preprocessing_time"] = preprocessingTime; diff --git a/src/mqt/qcec/configuration.py b/src/mqt/qcec/configuration.py index 89458e41..f18acb2f 100644 --- a/src/mqt/qcec/configuration.py +++ b/src/mqt/qcec/configuration.py @@ -41,8 +41,6 @@ class ConfigurationOptions(TypedDict, total=False): remove_diagonal_gates_before_measure: bool reorder_operations: bool transform_dynamic_circuit: bool - move_data_qubits_to_front: bool - move_measured_qubits_to_front: bool # Parameterized additional_instantiations: int parameterized_tolerance: float diff --git a/src/mqt/qcec/pyqcec.pyi b/src/mqt/qcec/pyqcec.pyi index 422f995a..5d092e6c 100644 --- a/src/mqt/qcec/pyqcec.pyi +++ b/src/mqt/qcec/pyqcec.pyi @@ -59,8 +59,6 @@ class Configuration: remove_diagonal_gates_before_measure: bool reorder_operations: bool transform_dynamic_circuit: bool - move_data_qubits_to_front: bool - move_measured_qubits_to_front: bool def __init__(self) -> None: ... class Parameterized: @@ -108,8 +106,6 @@ class EquivalenceCheckingManager: def disable_all_checkers(self) -> None: ... def equivalence(self) -> EquivalenceCriterion: ... def fix_output_permutation_mismatch(self) -> None: ... - def move_data_qubits_to_front(self) -> None: ... - def move_measured_qubits_to_front(self) -> None: ... def fuse_single_qubit_gates(self) -> None: ... def get_configuration(self) -> Configuration: ... def get_results(self) -> EquivalenceCheckingManager.Results: ... diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index 3595064e..d9574602 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -251,20 +251,6 @@ PYBIND11_MODULE(pyqcec, m) { ":attr:`Backpropagate the output permutation " "<.Configuration.Optimizations.backpropagate_output_permutation>` " "to the input permutation.") - .def( - "move_data_qubits_to_front", - &EquivalenceCheckingManager::runMoveDataQubitsToFront, - "Partial equivalence checking assumes that all the data qubits are " - "the first qubits. This functions modifies the initial permutation " - "in order to :attr:`bring all the data (= not ancillary) qubits to " - "the front <.Configuration.Optimizations.move_data_qubits_to_front>`") - .def("move_measured_qubits_to_front", - &EquivalenceCheckingManager::runMoveMeasuredQubitsToFront, - "partial equivalence checking assumes that all the measured qubits " - "are the first qubits. This functions modifies the output " - "permutation in order to :attr:`bring all the measured (= not " - "garbage) qubits to the front " - "<.Configuration.Optimizations.move_measured_qubits_to_front>`") // Application .def("set_application_scheme", &EquivalenceCheckingManager::setApplicationScheme, @@ -583,17 +569,7 @@ PYBIND11_MODULE(pyqcec, m) { " that have been transformed to a static circuit by enabling the " ":attr:`transform_dynamic_circuit " "<.Configuration.Optimizations.transform_dynamic_circuit>` " - "optimization.") - .def_readwrite("move_data_qubits_to_front", - &Configuration::Optimizations::moveDataQubitsToFront, - "Moves all data (= not ancillary) qubits to the front. " - "This is only used for partial equivalence checking. It " - "defaults to :code:`False`.") - .def_readwrite("move_measured_qubits_to_front", - &Configuration::Optimizations::moveMeasuredQubitsToFront, - "Moves all measured (= not garbage) qubits to the front. " - "This is only used for partial equivalence checking. It " - "defaults to :code:`False`."); + "optimization."); // application options application.def(py::init<>()) From 9d326ef7a3b9010075b36206efe5830900e76780 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Fri, 15 Mar 2024 16:37:30 +0100 Subject: [PATCH 23/41] =?UTF-8?q?=F0=9F=94=A5=20remove=20functions=20for?= =?UTF-8?q?=20partial=20equivalence=20checking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/checker/dd/DDPartialEquivalence.hpp | 91 ------------------- .../dd/DDPartialEquivalenceBenchmarks.hpp | 17 ++++ include/checker/dd/TaskManager.hpp | 1 - src/CMakeLists.txt | 2 +- ...cpp => DDPartialEquivalenceBenchmarks.cpp} | 12 +-- test/test_partial_equivalence.cpp | 8 +- 6 files changed, 20 insertions(+), 111 deletions(-) delete mode 100644 include/checker/dd/DDPartialEquivalence.hpp create mode 100644 include/checker/dd/DDPartialEquivalenceBenchmarks.hpp rename src/checker/dd/{DDPartialEquivalence.cpp => DDPartialEquivalenceBenchmarks.cpp} (95%) diff --git a/include/checker/dd/DDPartialEquivalence.hpp b/include/checker/dd/DDPartialEquivalence.hpp deleted file mode 100644 index 74e54fd6..00000000 --- a/include/checker/dd/DDPartialEquivalence.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include "dd/FunctionalityConstruction.hpp" -#include "dd/Package.hpp" - -namespace dd { - -template -mEdge partialEquivalenceCheckDDSubroutine(mEdge u, const Qubit m, const Qubit k, - const Qubit extra, - Package& dd) { - // add extra ancillary qubits - if (extra > 0) { - if (u.p->v + 1U + extra > dd.qubits()) { - dd.resize(u.p->v + 1U + extra); - } - u = dd.kronecker(dd.makeIdent(extra), u); - } - if (u.isTerminal()) { - return u; - } - const Qubit n = u.p->v + 1; - const Qubit d = n - k; - u = dd.setColumnsToZero(u, d); - const auto u2 = dd.shiftAllRows(u, m, d); - return dd.multiply(dd.conjugateTranspose(u), u2); -} - -// get next garbage qubit after n -inline Qubit getNextGarbage(Qubit n, const std::vector& garbage) { - while (n < static_cast(garbage.size()) && !garbage.at(n)) { - n++; - } - return n; -} -/** - Checks for partial equivalence between the two circuits c1 and c2. - Assumption: the data qubits are all at the beginning of the input qubits and - the input and output permutations are the same. - - @param circuit1 First circuit - @param circuit2 Second circuit - @return true if the two circuits c1 and c2 are partially equivalent. - **/ -template -bool partialEquivalenceCheck(qc::QuantumComputation c1, - qc::QuantumComputation c2, Package& dd) { - const auto d1 = c1.getNqubitsWithoutAncillae(); - const auto d2 = c2.getNqubitsWithoutAncillae(); - const auto m1 = c1.getNmeasuredQubits(); - const auto m2 = c2.getNmeasuredQubits(); - if (m1 != m2 || d1 != d2) { - return false; - } - const auto n1 = static_cast(c1.getNqubits()); - const auto n2 = static_cast(c2.getNqubits()); - - // add swaps in order to put the measured (= not garbage) qubits in the end - const auto garbage1 = c1.getGarbage(); - - auto nextGarbage = getNextGarbage(0, garbage1); - // find the first garbage qubit at the end - for (std::int64_t i = std::min(n1, n2) - 1; - i >= static_cast(m1); i--) { - if (!garbage1.at(static_cast(i))) { - // swap it to the beginning - c1.swap(static_cast(i), nextGarbage); - c2.swap(static_cast(i), nextGarbage); - ++nextGarbage; - nextGarbage = getNextGarbage(nextGarbage, garbage1); - } - } - - // partialEquivalenceCheck with dd - - const auto u1 = buildFunctionality(&c1, dd, false, false); - const auto u2 = buildFunctionality(&c2, dd, false, false); - - return true; -} - -/** - Generate random benchmarks for partial equivalence checking. - @param n number of qubits of the resulting circuits - @param d number of data qubits in the resulting circuits - @param m number of measured qubits in the resulting circuit - @return two circuits that are partially equivalent -**/ -std::pair -generateRandomBenchmark(size_t n, qc::Qubit d, qc::Qubit m); -} // namespace dd diff --git a/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp b/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp new file mode 100644 index 00000000..ec972e27 --- /dev/null +++ b/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "dd/FunctionalityConstruction.hpp" +#include "dd/Package.hpp" + +namespace dd { + +/** + Generate random benchmarks for partial equivalence checking. + @param n number of qubits of the resulting circuits + @param d number of data qubits in the resulting circuits + @param m number of measured qubits in the resulting circuit + @return two circuits that are partially equivalent +**/ +std::pair +generateRandomBenchmark(size_t n, qc::Qubit d, qc::Qubit m); +} // namespace dd diff --git a/include/checker/dd/TaskManager.hpp b/include/checker/dd/TaskManager.hpp index 907ce42f..261f7e3e 100644 --- a/include/checker/dd/TaskManager.hpp +++ b/include/checker/dd/TaskManager.hpp @@ -6,7 +6,6 @@ #pragma once #include "QuantumComputation.hpp" -#include "checker/dd/DDPartialEquivalence.hpp" #include "dd/Operations.hpp" namespace ec { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e3827ba..ba03669d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ add_library( checker/dd/DDConstructionChecker.cpp checker/dd/DDSimulationChecker.cpp checker/dd/DDAlternatingChecker.cpp - checker/dd/DDPartialEquivalence.cpp + checker/dd/DDPartialEquivalenceBenchmarks.cpp checker/dd/applicationscheme/GateCostApplicationScheme.cpp checker/dd/simulation/StateGenerator.cpp checker/zx/ZXChecker.cpp) diff --git a/src/checker/dd/DDPartialEquivalence.cpp b/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp similarity index 95% rename from src/checker/dd/DDPartialEquivalence.cpp rename to src/checker/dd/DDPartialEquivalenceBenchmarks.cpp index ee4be1d0..ce6b85c4 100644 --- a/src/checker/dd/DDPartialEquivalence.cpp +++ b/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp @@ -1,4 +1,4 @@ -#include "checker/dd/DDPartialEquivalence.hpp" +#include "checker/dd/DDPartialEquivalenceBenchmarks.hpp" #include "QuantumComputation.hpp" #include "operations/OpType.hpp" @@ -214,16 +214,6 @@ makeRandomStandardOperation(const size_t n, const qc::Qubit nrQubits, const fp randomParameter1 = randomDistrParameters(randomGenerator); const fp randomParameter2 = randomDistrParameters(randomGenerator); const fp randomParameter3 = randomDistrParameters(randomGenerator); - // const std::vector randomParameters{PI, PI_2, PI_4}; - // const fp randomParameter1 = - // randomParameters[static_cast(rand()) % - // randomParameters.size()]; - // const fp randomParameter2 = - // randomParameters[static_cast(rand()) % - // randomParameters.size()]; - // const fp randomParameter3 = - // randomParameters[static_cast(rand()) % - // randomParameters.size()]; return convertToStandardOperation( n, nrQubits, randomOpType, randomTarget1, randomTarget2, randomParameter1, randomParameter2, randomParameter3, randomControls); diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index 6999f8b1..016a2bf6 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -4,7 +4,7 @@ // #include "EquivalenceCheckingManager.hpp" -#include "checker/dd/DDPartialEquivalence.hpp" +#include "checker/dd/DDPartialEquivalenceBenchmarks.hpp" #include "dd/Package.hpp" #include "gtest/gtest.h" @@ -529,12 +529,6 @@ void partialEquivalencCheckingBenchmarks(const qc::Qubit minN, ecm.run(); EXPECT_TRUE(ecm.getResults().consideredEquivalent()); - // if (!ecm.getResults().consideredEquivalent()) { - // std::cout << "c1:\n"; - // c1.print(std::cout); - // std::cout << "c2:\n"; - // c2.print(std::cout); - // } const auto duration = ecm.getResults().checkTime; totalTime += duration; From b2fa497226c3d936f3ace5312f437d3ce4472cc0 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Fri, 15 Mar 2024 16:55:19 +0100 Subject: [PATCH 24/41] =?UTF-8?q?=F0=9F=8E=A8=20clean=20up=20code=20and=20?= =?UTF-8?q?tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/checker/dd/DDConstructionChecker.hpp | 3 --- include/checker/dd/TaskManager.hpp | 15 ----------- src/checker/dd/DDConstructionChecker.cpp | 28 +------------------- src/checker/dd/DDEquivalenceChecker.cpp | 4 ++- test/python/test_partial_equivalence.py | 28 -------------------- test/test_partial_equivalence.cpp | 3 --- 6 files changed, 4 insertions(+), 77 deletions(-) diff --git a/include/checker/dd/DDConstructionChecker.hpp b/include/checker/dd/DDConstructionChecker.hpp index 300f4ebd..10437fb9 100644 --- a/include/checker/dd/DDConstructionChecker.hpp +++ b/include/checker/dd/DDConstructionChecker.hpp @@ -36,8 +36,5 @@ class DDConstructionChecker final taskManager.incRef(); taskManager.reduceAncillae(); } - - void postprocessTask( - TaskManager& task) override; }; } // namespace ec diff --git a/include/checker/dd/TaskManager.hpp b/include/checker/dd/TaskManager.hpp index 261f7e3e..e3bd2861 100644 --- a/include/checker/dd/TaskManager.hpp +++ b/include/checker/dd/TaskManager.hpp @@ -121,21 +121,6 @@ template class TaskManager { if constexpr (std::is_same_v) { state = package->reduceGarbage(state, qc->garbage, true); } else if constexpr (std::is_same_v) { - // version of the paper - // const auto d = static_cast(qc->getNqubitsWithoutAncillae()); - // const auto m = static_cast(qc->getNmeasuredQubits()); - - // const dd::Qubit n = state.p->v + 1; - // dd::Qubit k = n - d; - // dd::Qubit extra{0}; - // if (m > k) { - // extra = m - k; - // } - // k = k + extra; - // state = partialEquivalenceCheckDDSubroutine(state, m, k, extra, - // *package); - - // version with reduceGarbage state = package->reduceGarbage(state, qc->garbage, static_cast(direction), true); } diff --git a/src/checker/dd/DDConstructionChecker.cpp b/src/checker/dd/DDConstructionChecker.cpp index 885cab44..f3b40a37 100644 --- a/src/checker/dd/DDConstructionChecker.cpp +++ b/src/checker/dd/DDConstructionChecker.cpp @@ -5,36 +5,10 @@ #include "checker/dd/DDConstructionChecker.hpp" -namespace ec { - // this function is mainly placed here in order to have an out-of-line // virtual method definition which avoids emitting the classe's vtable in // every translation unit. -void DDConstructionChecker::json(nlohmann::json& j) const noexcept { +void ec::DDConstructionChecker::json(nlohmann::json& j) const noexcept { DDEquivalenceChecker::json(j); j["checker"] = "decision_diagram_construction"; } - -void DDConstructionChecker::postprocessTask( - TaskManager& task) { - // ensure that the permutation that was tracked throughout the circuit matches - // the expected output permutation - task.changePermutation(); - if (isDone()) { - return; - } - // reduce ancillaries for total equivalence check - // eliminate the superfluous contributions of ancillary qubits (this only - // has an effect on matrices) - task.reduceAncillae(); - - if (isDone()) { - return; - } - if (configuration.functionality.checkPartialEquivalence) { - // reduce garbage for partial equivalence check - task.reduceGarbage(); - } -} - -} // namespace ec diff --git a/src/checker/dd/DDEquivalenceChecker.cpp b/src/checker/dd/DDEquivalenceChecker.cpp index 6f810673..6bb245b4 100644 --- a/src/checker/dd/DDEquivalenceChecker.cpp +++ b/src/checker/dd/DDEquivalenceChecker.cpp @@ -200,10 +200,12 @@ void DDEquivalenceChecker::postprocessTask( // eliminate the superfluous contributions of ancillary qubits (this only has // an effect on matrices) task.reduceAncillae(); + if (isDone()) { return; } - // sum up the contributions of garbage qubits + // sum up the contributions of garbage qubits if we want to check for partial + // equivalence if (configuration.functionality.checkPartialEquivalence) { task.reduceGarbage(); } diff --git a/test/python/test_partial_equivalence.py b/test/python/test_partial_equivalence.py index d547f3eb..29056682 100644 --- a/test/python/test_partial_equivalence.py +++ b/test/python/test_partial_equivalence.py @@ -42,31 +42,3 @@ def test_argument_pec(original_circuit: QuantumCircuit, alternative_circuit: Qua """Test if the flag for partial equivalence checking works.""" result = qcec.verify(original_circuit, alternative_circuit, check_partial_equivalence=True) assert result.equivalence == qcec.EquivalenceCriterion.equivalent - - -def test_argument_move_measured_to_front() -> None: - """Test if the flag for moving measured qubits to the front works.""" - qc1 = QuantumCircuit(3, 3) - qc1.cswap(1, 2, 0) - qc1.h(2) - qc1.z(0) - qc1.cswap(1, 2, 0) - qc1.measure(2, 2) - - qc2 = QuantumCircuit(3, 3) - qc2.x(1) - qc2.ch(1, 2) - qc2.measure(2, 2) - - result = qcec.verify( - qc1, - qc2, - check_partial_equivalence=True, - move_measured_qubits_to_front=True, - run_alternating_checker=True, - run_construction_checker=False, - run_simulation_checker=False, - run_zx_checker=False, - ) - - assert result.equivalence == qcec.EquivalenceCriterion.equivalent diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index 016a2bf6..8b0d8a1b 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -5,11 +5,8 @@ #include "EquivalenceCheckingManager.hpp" #include "checker/dd/DDPartialEquivalenceBenchmarks.hpp" -#include "dd/Package.hpp" #include "gtest/gtest.h" -#include -#include class PartialEquivalenceTest : public testing::Test { void SetUp() override { From 45523517e56bb2c320707aac92ce7a735d3805ec Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Fri, 15 Mar 2024 16:56:22 +0100 Subject: [PATCH 25/41] =?UTF-8?q?=F0=9F=93=8C=20changed=20mqt-core=20versi?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 2 +- extern/mqt-core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index f538dfa5..5d08fb5e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "extern/mqt-core"] path = extern/mqt-core url = https://github.com/reb-ddm/mqt-core.git - branch = partial-equivalence-reduce-garbage + branch = test-reduce-garbage diff --git a/extern/mqt-core b/extern/mqt-core index a6d3bc0d..6b5f2e3c 160000 --- a/extern/mqt-core +++ b/extern/mqt-core @@ -1 +1 @@ -Subproject commit a6d3bc0d19d53e142aba23bd5b1c08833ad11e0e +Subproject commit 6b5f2e3c3cbb5bd02f12e526a2e0051a50ba909e From 5cea15ef8a2de33df50d19c3e8abbf738ce380e4 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Fri, 15 Mar 2024 17:33:53 +0100 Subject: [PATCH 26/41] =?UTF-8?q?=E2=9C=85=20added=20some=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/test_partial_equivalence.cpp | 64 +++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index 8b0d8a1b..ea0a5274 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -68,6 +68,29 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbage) { EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } +TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent) { + qc1.cswap(1, 0, 2); + qc1.cx(2, 0); + qc1.h(0); + qc1.tdg(1); + qc1.s(1); + qc1.z(2); + + qc2.cswap(1, 0, 2); + qc2.cx(2, 0); + qc2.h(0); + qc2.h(2); + qc2.rz(dd::PI_4, 1); + qc2.ry(0.1, 1); + qc2.cx(1, 2); + + config.execution.runAlternatingChecker = true; + + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); +} + TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbage2) { // measured qubit: 1 qc1.setLogicalQubitGarbage(2); @@ -132,7 +155,7 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageAndAncillary) { EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } -TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent) { +TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent2) { // example from the paper https://arxiv.org/abs/2208.07564 qc1.cswap(1, 0, 2); qc1.h(0); @@ -150,7 +173,6 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent) { // partially equivalent circuits config.execution.runAlternatingChecker = true; ec::EquivalenceCheckingManager ecm(qc1, qc2, config); - ecm.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm.run(); EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); @@ -159,11 +181,26 @@ TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent) { // partial equality checking config.functionality.checkPartialEquivalence = false; ec::EquivalenceCheckingManager ecm2(qc1, qc2, config); - ecm2.setApplicationScheme(ec::ApplicationSchemeType::Proportional); ecm2.run(); EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } +TEST_F(PartialEquivalenceTest, AlternatingCheckerGarbageNotEquivalent3) { + qc1.cswap(1, 0, 2); + qc1.h(0); + qc1.z(2); + qc1.cswap(1, 0, 2); + + qc2.x(1); + qc2.ch(1, 0); + + config.execution.runAlternatingChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); +} + TEST_F(PartialEquivalenceTest, TrivialEquivalence) { auto qc = qc::QuantumComputation(2); @@ -262,6 +299,27 @@ TEST_F(PartialEquivalenceTest, ConstructionCheckerGarbageNotEquivalent) { EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::NotEquivalent); } +TEST_F(PartialEquivalenceTest, ConstructionCheckerNotEquivalent2) { + // check that garbage reduction still recognizes non equivalent circuits + qc1.cswap(1, 0, 2); + qc1.h(0); + qc1.z(2); + qc1.cswap(1, 0, 2); + + qc2.x(1); + qc2.ch(1, 0); + qc2.h(2); + + qc1.setLogicalQubitGarbage(2); + qc2.setLogicalQubitGarbage(2); + // partially equivalent circuits + config.execution.runConstructionChecker = true; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); +} + TEST_F(PartialEquivalenceTest, SimulationCheckerGarbageNotEquivalent) { // example from the paper https://arxiv.org/abs/2208.07564 qc1.cswap(1, 0, 2); From b67472a81fa288c4e9bf30e97ff03d2e15154f3c Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sat, 16 Mar 2024 14:53:31 +0100 Subject: [PATCH 27/41] =?UTF-8?q?=F0=9F=93=9D=20updated=20documentation=20?= =?UTF-8?q?of=20partial=20equivalence=20checking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/PartialEquivalence.ipynb | 61 ++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/docs/source/PartialEquivalence.ipynb b/docs/source/PartialEquivalence.ipynb index 4209608e..90275931 100644 --- a/docs/source/PartialEquivalence.ipynb +++ b/docs/source/PartialEquivalence.ipynb @@ -9,15 +9,28 @@ "\n", "## Partial Equivalence vs. Total Equivalence\n", "\n", - "Different definitions of quantum circuit equivalence have been proposed, with the most commonly used being total equivalence. Two circuits are considered totally equivalent when their matrix representations are exactly the same. However, it is often sufficient to consider observational equivalence, because the only way to extract information from a quantum circuit is through measurement. Therefore, partial equivalence has been defined, which is a weaker equality than total equivalence. Two circuits are considered partially equivalent if, for each possible input state, they have the same probabilities for each measurement outcome. \n", - "\n", - "This definition is especially useful for circuits that do not measure all of their qubits at the end, or where some qubits are initialized to a certain value at the beginning. We refer to the qubits that are initialized to a certain value at the beginning of the computation *ancillary* qubits. Without loss of generality, we assume that these qubits are initially set to $|0\\rangle$. Any other initial state can be reached from the $|0\\rangle$ state by applying the appropriate gates. The remaining qubits are the qubits that hold the input state, and they are referred to as *data* qubits.\n", - "\n", - "Similarly, we differentiate between *measured* and *garbage* qubits. In order to read the output at the end of a circuit, a measurement is performed on some qubits, but not necessarily all of them. These qubits are the *measured* qubits. All qubits that are not measured are called the *garbage* qubits. Their final state doesn't influence the output we obtain from the computation. \n", - "\n", - "For a circuit $C$ we denote $P(t | \\psi, C)$ as the probability that the quantum circuit $C$ collapses to state $|t\\rangle$ upon a measurement on the measured qubits, given that the data qubits have the initial state $|\\psi\\rangle$.\n", - "\n", - "With these concepts we can provide an exact definition of partial equivalence. Two circuits $C_1$ and $C_2$ are considered partially equivalent if, for each initial state $|\\psi\\rangle$ of the data qubits and each final state $|t\\rangle$ of the measured qubits, it holds that $P(t|\\psi, C_1) = P(t|\\psi, C_2)$.\n" + "Different definitions of quantum circuit equivalence have been proposed, with the most commonly used being total equivalence. \n", + "Two circuits are considered totally equivalent when their matrix representations are exactly the same. \n", + "However, it is often sufficient to consider observational equivalence, because the only way to extract information from a quantum circuit is through measurement. \n", + "Therefore, partial equivalence has been defined, which is a weaker equality than total equivalence. \n", + "Two circuits are considered partially equivalent if, for each possible input state, they have the same probabilities for each measurement outcome. \n", + "In particular, partial equivalence doesn't consider qubits that are not measured or different phase angles for each measurement.\n", + "\n", + "This definition is especially useful for circuits that do not measure all of their qubits at the end, or where some qubits are initialized to a certain value at the beginning. \n", + "We refer to the qubits that are initialized to a certain value at the beginning of the computation *ancillary* qubits. \n", + "Without loss of generality, we assume that these qubits are initially set to $|0\\rangle$. \n", + "Any other initial state can be reached from the $|0\\rangle$ state by applying the appropriate gates. \n", + "The remaining qubits are the qubits that hold the input state, and they are referred to as *data* qubits.\n", + "\n", + "Similarly, we differentiate between *measured* and *garbage* qubits. \n", + "In order to read the output at the end of a circuit, a measurement is performed on some qubits, but not necessarily all of them. \n", + "These qubits are the *measured* qubits. All qubits that are not measured are called the *garbage* qubits. \n", + "Their final state doesn't influence the output we obtain from the computation. \n", + "\n", + "For a circuit $C$ we denote $P(t | \\psi, C)$ as the probability that the quantum circuit $C$ collapses to state $|t\\rangle$ upon a measurement on the measured qubits, \n", + "given that the data qubits have the initial state $|\\psi\\rangle$. \n", + "Two circuits $C_1$ and $C_2$ are considered partially equivalent if, for each initial state $|\\psi\\rangle$ of the data qubits and each final state $|t\\rangle$ of the measured qubits, \n", + "it holds that $P(t|\\psi, C_1) = P(t|\\psi, C_2)$.\n" ] }, { @@ -28,17 +41,32 @@ "\n", "## Equivalence Checking of Partially Equivalent Quantum Circuits\n", "\n", - "Partial equivalence checking is a bit more costly than regular equivalence checking. Therefore, it is not enabled by default in QCEC. It can be activated using an option in the configuration parameters. If the option `check_partial_equivalence` is set to `True`, the equivalence checker will return `equivalent` not only for totally equivalent circuits, but also for partially equivalent circuits. The result will be `not_equivalent` if and only if the circuits are not partially equivalent.\n", + "Partial equivalence checking is a bit more costly than regular equivalence checking. \n", + "It is necessary to reduce the contribution of garbage qubits and normalize the phase of each measurement outcome. \n", + "Therefore, it is not enabled by default in QCEC. \n", + "It can be activated using an option in the configuration parameters. \n", + "If the option `check_partial_equivalence` is set to `True`, the equivalence checker will return `equivalent` not only for totally equivalent circuits, \n", + "but also for partially equivalent circuits. The result will be `not_equivalent` if and only if the circuits are not partially equivalent. \n", + "On the other hand, if the option `check_partial_equivalence` is set to `False`, then the equivalence checker considers total equivalence modulo ancillary qubits. \n", + "This means that the garbage qubits are considered as if they were measured qubits, while ancillary qubits are set to zero, as in the partial equivalence check. \n", + "The equivalence checker will return `equivalent` for totally equivalent circuits or `equivalent_up_to_global_phase` for circuits which differ only in their global phase \n", + "and `not_equivalent` for other circuits.\n", "\n", "The following is a summary of the behaviour of each type of equivalence checker when the `check_partial_equivalence` option is set to `True`.\n", "\n", - "1. **Construction Equivalence Checker:** The construction checker supports partial equivalence checking by using decision diagrams to calculate the measurement probabilities of the possible ouputs and it compares the results for the two circuits.\n", + "1. **Construction Equivalence Checker:** The construction checker supports partial equivalence checking by using decision diagrams to calculate the nnormalized phases of the possible ouputs and then summing up the contribution of garbage qubits, in order to consider only the measurement probabilities of measured qubits. \n", + "Then it compares the reduced decision diagrams of the two circuits. \n", "\n", - "1. **Alternating Equivalence Checker:** The alternating checker can only be used for circuits where at least one of the two does not contain ancillary qubits. It normally computes the composition of one circuit with the inverse of the other and verifies that the result is the identity matrix. When checking for partial equivalence, it suffices to verify that the result is a diagonal matrix (modulo garbage qubits). This check doesn't have a signifi\n", + "1. **Alternating Equivalence Checker:** The alternating checker can only be used for circuits where at least one of the two does not contain ancillary qubits. \n", + "It normally computes the composition of one circuit with the inverse of the other and verifies that the result is the identity matrix. \n", + "When checking for partial equivalence, it suffices to verify that the result is a diagonal matrix (modulo garbage qubits). \n", "\n", - "1. **Simulation Equivalence Checker:** The simulation checker ...\n", + "1. **Simulation Equivalence Checker:** The simulation checker computes the vector representation of the result of the circuit applied to certain initial states. \n", + "The contributions of garbage qubits are summed up only when checking for partial equivalence.\n", "\n", - "1. **ZX-Calculus Equivalence Checker:** The ZX-calculus checker doesn't directly support partial equivalence, which is not a problem for the equivalence checking workflow, given that the ZX-calculus checker cannot demonstrate non-equivalence of circuits. Therefore it will simply output 'No Information' for circuits that are partially but not totally equivalent." + "1. **ZX-Calculus Equivalence Checker:** The ZX-calculus checker doesn't directly support partial equivalence, which is not a problem for the equivalence checking workflow, \n", + "given that the ZX-calculus checker cannot demonstrate non-equivalence of circuits. \n", + "Therefore it will simply output 'No Information' for circuits that are partially but not totally equivalent." ] }, { @@ -75,7 +103,8 @@ "id": "3b85338e", "metadata": {}, "source": [ - "The following circuit is not totally equivalent to the previous one. The two circuits are however partially equivalent, because they have the same probability distribution of measured values for any given initial input state." + "The following circuit is not totally equivalent to the previous one. \n", + "The two circuits are however partially equivalent, because they have the same probability distribution of measured values for any given initial input state." ] }, { @@ -117,7 +146,7 @@ "id": "6af54b68", "metadata": {}, "source": [ - "Source: The definitions and algorithm for partial equivalence are described in the paper [Partial Equivalence Checking of Quantum Circuits](https://arxiv.org/abs/2208.07564) by Tian-Fu Chen, Jie-Hong R. Jiang and Min-Hsiu Hsieh" + "Source: The definitions and example for partial equivalence are described in the paper [Partial Equivalence Checking of Quantum Circuits](https://arxiv.org/abs/2208.07564) by Tian-Fu Chen, Jie-Hong R. Jiang and Min-Hsiu Hsieh." ] } ], From 71343dbfc228826710298f1ccb67078fc46331ed Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 17 Mar 2024 10:38:46 +0100 Subject: [PATCH 28/41] =?UTF-8?q?=E2=9C=85=20fixed=20failing=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/test_equality.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_equality.cpp b/test/test_equality.cpp index 158f8afe..39528759 100644 --- a/test/test_equality.cpp +++ b/test/test_equality.cpp @@ -178,8 +178,9 @@ TEST_F(EqualityTest, AutomaticSwitchToConstructionChecker) { // run the equivalence checker ecm.run(); - // both circuits should be equivalent since their action only differs on an - // ancillary and garbage qubit + // both circuits should be partially equivalent since their action only + // differs on an ancillary and garbage qubit + ecm.setCheckPartialEquivalence(true); const auto result = ecm.equivalence(); EXPECT_EQ(result, ec::EquivalenceCriterion::Equivalent); From c4453d871b6fee7f1fa76167b141c91b3971fb24 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 17 Mar 2024 11:10:46 +0100 Subject: [PATCH 29/41] print warning when there are garbage qubits, but equivalence checking is turned off --- src/EquivalenceCheckingManager.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/EquivalenceCheckingManager.cpp b/src/EquivalenceCheckingManager.cpp index 62c5868b..d5943ffe 100644 --- a/src/EquivalenceCheckingManager.cpp +++ b/src/EquivalenceCheckingManager.cpp @@ -156,6 +156,8 @@ void EquivalenceCheckingManager::runOptimizationPasses() { void EquivalenceCheckingManager::run() { done = false; results.equivalence = EquivalenceCriterion::NoInformation; + bool garbageQubitsPresent = + qc1.getNgarbageQubits() > 0 || qc2.getNgarbageQubits() > 0; if (!configuration.anythingToExecute()) { std::clog << "Nothing to be executed. Check your configuration!\n"; @@ -179,6 +181,15 @@ void EquivalenceCheckingManager::run() { } else { checkSymbolic(); } + + if (!configuration.functionality.checkPartialEquivalence && + garbageQubitsPresent && + equivalence() == EquivalenceCriterion::NotEquivalent) { + std::clog << "[QCEC] Warning: at least one of the circuits has garbage " + "qubits, but partial equivalence checking is turned off. In " + "order to take into account the garbage qubits, set " + "checkPartialEquivalence to true.\n"; + } } EquivalenceCheckingManager::EquivalenceCheckingManager( From 29fe36dd3603c2b28d0d3feafa54d48c5a413077 Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 17 Mar 2024 11:17:29 +0100 Subject: [PATCH 30/41] =?UTF-8?q?=F0=9F=93=9D=20update=20description=20of?= =?UTF-8?q?=20python=20bindings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/python/bindings.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index d9574602..77c039f6 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -628,14 +628,12 @@ PYBIND11_MODULE(pyqcec, m) { "Two circuits are partially equivalent if, for each possible initial " "input state, they have the same probability for each measurement " "outcome. If set to :code:`True`, a check for partial equivalence " - "will be performed in the :ref:`construction checker " - "` and in the :ref:`alternating checker " - "` (if they are enabled). If set to " - ":code:`False`, the checker will output 'not equivalent' for " - "circuits that are partially equivalent but not totally equivalent. " - "Defaults to :code:`False`."); + "will be performed and the contributions of garbage qubits to the " + "circuit are ignored. If set to :code:`False`, the checker will " + "output 'not equivalent' for circuits that are partially equivalent " + "but not totally equivalent. In particular, garbage qubits will be " + "treated as if they were measured qubits. Defaults to " + ":code:`False`."); // simulation options simulation.def(py::init<>()) From 33ea4d0b66d0c3be22b556dc4892e612653ede7b Mon Sep 17 00:00:00 2001 From: Rebecca Ghidini Date: Sun, 17 Mar 2024 11:22:05 +0100 Subject: [PATCH 31/41] =?UTF-8?q?=F0=9F=8E=A8=20rename=20generateRandomBen?= =?UTF-8?q?chmarks=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/checker/dd/DDPartialEquivalenceBenchmarks.hpp | 7 +++++-- src/checker/dd/DDPartialEquivalenceBenchmarks.cpp | 3 ++- test/test_partial_equivalence.cpp | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp b/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp index ec972e27..9e317ddc 100644 --- a/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp +++ b/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp @@ -6,12 +6,15 @@ namespace dd { /** - Generate random benchmarks for partial equivalence checking. + Generate random benchmarks for partial equivalence checking. Returns pairs of +circuits which are partially equivalent, following the method described in the +paper "Partial Equivalence Checking of Quantum +Circuits" (https://arxiv.org/abs/2208.07564) in Section VI. B. @param n number of qubits of the resulting circuits @param d number of data qubits in the resulting circuits @param m number of measured qubits in the resulting circuit @return two circuits that are partially equivalent **/ std::pair -generateRandomBenchmark(size_t n, qc::Qubit d, qc::Qubit m); +generatePartiallyEquivalentCircuits(size_t n, qc::Qubit d, qc::Qubit m); } // namespace dd diff --git a/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp b/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp index ce6b85c4..68a4f2ea 100644 --- a/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp +++ b/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp @@ -220,7 +220,8 @@ makeRandomStandardOperation(const size_t n, const qc::Qubit nrQubits, } std::pair -generateRandomBenchmark(const size_t n, const qc::Qubit d, const qc::Qubit m) { +generatePartiallyEquivalentCircuits(const size_t n, const qc::Qubit d, + const qc::Qubit m) { if (d > n || m > n) { throw std::runtime_error("The number of data or measured qubits can't be " "bigger than the total number of qubits. n = " + diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index ea0a5274..4f734567 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -578,7 +578,7 @@ void partialEquivalencCheckingBenchmarks(const qc::Qubit minN, std::uniform_int_distribution nrDataQubits(1, d); const qc::Qubit m = nrDataQubits(gen); - const auto [c1, c2] = dd::generateRandomBenchmark(n, d, m); + const auto [c1, c2] = dd::generatePartiallyEquivalentCircuits(n, d, m); ec::EquivalenceCheckingManager ecm(c1, c2, config); ecm.run(); From 004f8375fcc6bc81cb603bfc440fc695d1b89390 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 14:09:06 +0100 Subject: [PATCH 32/41] =?UTF-8?q?=F0=9F=9A=A8=20unnecessary=20whitespace?= =?UTF-8?q?=20change?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- src/checker/dd/DDEquivalenceChecker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/checker/dd/DDEquivalenceChecker.cpp b/src/checker/dd/DDEquivalenceChecker.cpp index 6bb245b4..5cf3fd75 100644 --- a/src/checker/dd/DDEquivalenceChecker.cpp +++ b/src/checker/dd/DDEquivalenceChecker.cpp @@ -200,7 +200,6 @@ void DDEquivalenceChecker::postprocessTask( // eliminate the superfluous contributions of ancillary qubits (this only has // an effect on matrices) task.reduceAncillae(); - if (isDone()) { return; } From fc3cd036c2a87493d43d74d85f18a5452dc95afc Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 14:09:52 +0100 Subject: [PATCH 33/41] =?UTF-8?q?=F0=9F=8E=A8=20use=20ternary-if?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- src/checker/dd/DDAlternatingChecker.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/checker/dd/DDAlternatingChecker.cpp b/src/checker/dd/DDAlternatingChecker.cpp index f10ce235..8cc4fa3c 100644 --- a/src/checker/dd/DDAlternatingChecker.cpp +++ b/src/checker/dd/DDAlternatingChecker.cpp @@ -101,18 +101,13 @@ EquivalenceCriterion DDAlternatingChecker::checkEquivalence() { garbage[static_cast(q)] = qc1.logicalQubitIsGarbage(q) && qc2.logicalQubitIsGarbage(q); } - bool isClose{}; - - // if partial equivalence is being checked instead of total equivalence, it - // suffices to change the last parameter of isCloseToIdentity to `false` - if (configuration.functionality.checkPartialEquivalence) { - isClose = dd->isCloseToIdentity(functionality, - configuration.functionality.traceThreshold, - garbage, false); - } else { - isClose = dd->isCloseToIdentity(functionality, - configuration.functionality.traceThreshold); - } + bool isClose = + configuration.functionality.checkPartialEquivalence + ? dd->isCloseToIdentity(functionality, + configuration.functionality.traceThreshold, + garbage, false) + : dd->isCloseToIdentity(functionality, + configuration.functionality.traceThreshold); if (isClose) { // whenever the top edge weight is not one, both decision diagrams are only From d138175eaaf4da7ce76edf3bc5a69c4f127c9db5 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 14:21:35 +0100 Subject: [PATCH 34/41] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20update=20mqt-core?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- extern/mqt-core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/mqt-core b/extern/mqt-core index 6b5f2e3c..4627f7dd 160000 --- a/extern/mqt-core +++ b/extern/mqt-core @@ -1 +1 @@ -Subproject commit 6b5f2e3c3cbb5bd02f12e526a2e0051a50ba909e +Subproject commit 4627f7dd2b1dad38c5dc43aecf298a2ee021ae91 From 4995eaab546b037c8ddaeb98d065c546db4af65a Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 14:21:51 +0100 Subject: [PATCH 35/41] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20revise=20error=20mes?= =?UTF-8?q?sage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- src/EquivalenceCheckingManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/EquivalenceCheckingManager.cpp b/src/EquivalenceCheckingManager.cpp index d5943ffe..36a84634 100644 --- a/src/EquivalenceCheckingManager.cpp +++ b/src/EquivalenceCheckingManager.cpp @@ -187,8 +187,9 @@ void EquivalenceCheckingManager::run() { equivalence() == EquivalenceCriterion::NotEquivalent) { std::clog << "[QCEC] Warning: at least one of the circuits has garbage " "qubits, but partial equivalence checking is turned off. In " - "order to take into account the garbage qubits, set " - "checkPartialEquivalence to true.\n"; + "order to take into account the garbage qubits, enable partial" + " equivalence checking. Consult the documentation for more" + "information.\n"; } } From 072ddc5651b26b5c922e04a2b26243bda1db39b8 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 14:31:34 +0100 Subject: [PATCH 36/41] =?UTF-8?q?=F0=9F=9A=9A=20move=20benchmarking=20code?= =?UTF-8?q?=20to=20test=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .../dd/DDPartialEquivalenceBenchmarks.hpp | 20 -- src/CMakeLists.txt | 1 - .../dd/DDPartialEquivalenceBenchmarks.cpp | 325 ----------------- test/test_partial_equivalence.cpp | 334 +++++++++++++++++- 4 files changed, 333 insertions(+), 347 deletions(-) delete mode 100644 include/checker/dd/DDPartialEquivalenceBenchmarks.hpp delete mode 100644 src/checker/dd/DDPartialEquivalenceBenchmarks.cpp diff --git a/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp b/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp deleted file mode 100644 index 9e317ddc..00000000 --- a/include/checker/dd/DDPartialEquivalenceBenchmarks.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "dd/FunctionalityConstruction.hpp" -#include "dd/Package.hpp" - -namespace dd { - -/** - Generate random benchmarks for partial equivalence checking. Returns pairs of -circuits which are partially equivalent, following the method described in the -paper "Partial Equivalence Checking of Quantum -Circuits" (https://arxiv.org/abs/2208.07564) in Section VI. B. - @param n number of qubits of the resulting circuits - @param d number of data qubits in the resulting circuits - @param m number of measured qubits in the resulting circuit - @return two circuits that are partially equivalent -**/ -std::pair -generatePartiallyEquivalentCircuits(size_t n, qc::Qubit d, qc::Qubit m); -} // namespace dd diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba03669d..c929aedd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,6 @@ add_library( checker/dd/DDConstructionChecker.cpp checker/dd/DDSimulationChecker.cpp checker/dd/DDAlternatingChecker.cpp - checker/dd/DDPartialEquivalenceBenchmarks.cpp checker/dd/applicationscheme/GateCostApplicationScheme.cpp checker/dd/simulation/StateGenerator.cpp checker/zx/ZXChecker.cpp) diff --git a/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp b/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp deleted file mode 100644 index 68a4f2ea..00000000 --- a/src/checker/dd/DDPartialEquivalenceBenchmarks.cpp +++ /dev/null @@ -1,325 +0,0 @@ -#include "checker/dd/DDPartialEquivalenceBenchmarks.hpp" - -#include "QuantumComputation.hpp" -#include "operations/OpType.hpp" -#include "operations/StandardOperation.hpp" - -namespace dd { - -const std::vector> PRE_GENERATED_CIRCUITS_SIZE_1_1{ - {}, {}, {}, {}}; - -const std::vector> PRE_GENERATED_CIRCUITS_SIZE_1_2{ - {Z}, {Tdg}, {S}, {Sdg}}; - -const std::vector> PRE_GENERATED_CIRCUITS_SIZE_2_1{ - {}, {}, {}, {}, {X}, {X}}; - -const std::vector> PRE_GENERATED_CIRCUITS_SIZE_2_2{ - {Z}, {Tdg}, {S}, {Sdg}, {X, Z}, {Z, X}}; - -void addPreGeneratedCircuits(QuantumComputation& circuit1, - QuantumComputation& circuit2, const size_t n, - const qc::Qubit groupBeginIndex, - const qc::Qubit groupSize) { - const auto& circuits1 = groupSize == 1 ? PRE_GENERATED_CIRCUITS_SIZE_1_1 - : PRE_GENERATED_CIRCUITS_SIZE_2_1; - const auto& circuits2 = groupSize == 1 ? PRE_GENERATED_CIRCUITS_SIZE_1_2 - : PRE_GENERATED_CIRCUITS_SIZE_2_2; - const auto nrCircuits = circuits1.size(); - auto randomGenerator = circuit1.getGenerator(); - std::uniform_int_distribution randomDistribution(0, nrCircuits - 1); - - const auto randomIndex = randomDistribution(randomGenerator); - const auto x1 = circuits1[randomIndex]; - const auto x2 = circuits2[randomIndex]; - for (auto gateType : x1) { - if (gateType == X) { // add CNOT - circuit1.emplace_back(n, groupBeginIndex, - groupBeginIndex + 1, gateType); - } else { - circuit1.emplace_back(n, groupBeginIndex, gateType); - } - } - for (auto gateType : x2) { - if (gateType == X) { // add CNOT - circuit2.emplace_back(n, groupBeginIndex, - groupBeginIndex + 1, gateType); - } else { - circuit2.emplace_back(n, groupBeginIndex, gateType); - } - } -} - -void addDecomposedCcxGate(QuantumComputation& circuit, const Controls& controls, - const qc::Qubit target) { - const qc::Qubit control1 = controls.begin()->qubit; - const qc::Qubit control2 = (++controls.begin())->qubit; - circuit.h(target); - circuit.cx(control1, target); - circuit.tdg(target); - circuit.cx(control2, target); - circuit.t(target); - circuit.cx(control1, target); - circuit.tdg(target); - circuit.cx(control2, target); - circuit.t(target); - circuit.t(control1); - circuit.h(target); - circuit.cx(control2, control1); - circuit.t(control2); - circuit.tdg(control1); - circuit.cx(control2, control1); -} - -void addStandardOperationToCircuit(QuantumComputation& circuit, - const StandardOperation& op, - const bool decomposeCcx) { - if (op.getType() == X && decomposeCcx && op.getControls().size() == 2) { - // decompose toffoli gate - addDecomposedCcxGate(circuit, op.getControls(), op.getTargets()[0]); - } else { - circuit.emplace_back(op); - } -} - -std::vector -fiveDiffferentRandomNumbers(const qc::Qubit min, const qc::Qubit max, - std::mt19937_64& randomGenerator) { - std::vector numbers; - - for (qc::Qubit i = min; i < max; i++) { - numbers.emplace_back(i); - } - std::shuffle(numbers.begin(), numbers.end(), randomGenerator); - - const int64_t lengthOutputVector{ - static_cast(std::min(5UL, numbers.size()))}; - - std::vector outputVector(numbers.begin(), - numbers.begin() + lengthOutputVector); - return outputVector; -} - -StandardOperation convertToStandardOperation( - const size_t n, const size_t nrQubits, const OpType randomOpType, - const qc::Qubit randomTarget1, const qc::Qubit randomTarget2, - const fp randomParameter1, const fp randomParameter2, - const fp randomParameter3, const Controls& randomControls) { - switch (randomOpType) { - // two targets and zero parameters - case qc::SWAP: - case qc::iSWAP: - case qc::iSWAPdg: - case qc::Peres: - case qc::Peresdg: - case qc::DCX: - case qc::ECR: - if (nrQubits > 1) { - return {n, randomControls, Targets{randomTarget1, randomTarget2}, - randomOpType}; - } - break; - - // two targets and one parameter - case qc::RXX: - case qc::RYY: - case qc::RZZ: - case qc::RZX: - if (nrQubits > 1) { - return {n, randomControls, Targets{randomTarget1, randomTarget2}, - randomOpType, std::vector{randomParameter1}}; - } - break; - - // two targets and two parameters - case qc::XXminusYY: - case qc::XXplusYY: - if (nrQubits > 1) { - return {n, randomControls, Targets{randomTarget1, randomTarget2}, - randomOpType, - std::vector{randomParameter1, randomParameter2}}; - } - break; - - // one target and zero parameters - case qc::I: - case qc::H: - case qc::X: - case qc::Y: - case qc::Z: - case qc::S: - case qc::Sdg: - case qc::T: - case qc::Tdg: - case qc::V: - case qc::Vdg: - case qc::SX: - case qc::SXdg: - return {n, randomControls, randomTarget1, randomOpType}; - // one target and three parameters - case qc::U: - return { - n, randomControls, randomTarget1, randomOpType, - std::vector{randomParameter1, randomParameter2, randomParameter3}}; - // one target and two parameters - case qc::U2: - return {n, randomControls, randomTarget1, randomOpType, - std::vector{randomParameter1, randomParameter2}}; - // one target and one parameter - case qc::P: - case qc::RX: - case qc::RY: - case qc::RZ: - return {n, randomControls, randomTarget1, randomOpType, - std::vector{randomParameter1}}; - default: - return {n, randomTarget1, qc::I}; - } - return {n, randomTarget1, qc::I}; -} - -StandardOperation -makeRandomStandardOperation(const size_t n, const qc::Qubit nrQubits, - const qc::Qubit min, - std::mt19937_64& randomGenerator) { - const auto randomNumbers = - fiveDiffferentRandomNumbers(min, min + nrQubits, randomGenerator); - - // choose one of the non-compound operations, but not "None", and also - // not GPhase or I or Barrier - std::uniform_int_distribution<> randomDistrOpType(H, RZX); - auto randomOpType = static_cast(randomDistrOpType(randomGenerator)); - const qc::Qubit randomTarget1 = randomNumbers[0]; - qc::Qubit randomTarget2{min}; - if (randomNumbers.size() > 1) { - randomTarget2 = randomNumbers[1]; - }; - // choose random controls, but not more than available qubits - std::uniform_int_distribution randomDistrNrControls(0, 2); - size_t nrControls = std::min(randomNumbers.size() - 3, - randomDistrNrControls(randomGenerator)); - if (randomNumbers.size() < 3) { - nrControls = 0; - } - if (nrControls == 2) { - // otherwise toffoli gates are almost never generated - randomOpType = qc::X; - } - Controls randomControls{}; - for (size_t i = 0; i < nrControls; i++) { - randomControls.emplace(randomNumbers[i + 2]); - } - std::uniform_real_distribution randomDistrParameters(0, 2 * PI); - const fp randomParameter1 = randomDistrParameters(randomGenerator); - const fp randomParameter2 = randomDistrParameters(randomGenerator); - const fp randomParameter3 = randomDistrParameters(randomGenerator); - return convertToStandardOperation( - n, nrQubits, randomOpType, randomTarget1, randomTarget2, randomParameter1, - randomParameter2, randomParameter3, randomControls); -} - -std::pair -generatePartiallyEquivalentCircuits(const size_t n, const qc::Qubit d, - const qc::Qubit m) { - if (d > n || m > n) { - throw std::runtime_error("The number of data or measured qubits can't be " - "bigger than the total number of qubits. n = " + - std::to_string(n) + "; d = " + std::to_string(d) + - "; m = " + std::to_string(m)); - } - - qc::QuantumComputation circuit1{n}; - qc::QuantumComputation circuit2{n}; - - auto randomGenerator = circuit1.getGenerator(); - - // 1) H gates - for (qc::Qubit i = 0U; i < d; i++) { - circuit1.h(i); - circuit2.h(i); - } - - circuit1.barrier(); - circuit2.barrier(); - - // 2) Totally equivalent subcircuits - // Generate a random subcircuit with d qubits and 3*d gates to apply - // on both circuits, but all the Toffoli gates in circuit2 are decomposed - for (qc::Qubit i = 0U; i < 3 * d; i++) { - const auto op = makeRandomStandardOperation(n, d, 0, randomGenerator); - addStandardOperationToCircuit(circuit1, op, false); - addStandardOperationToCircuit(circuit2, op, true); - } - - circuit1.barrier(); - circuit2.barrier(); - - // 3) Partially equivalent subcircuits - // Divide data qubits into groups of size 1 or 2. For each group, we apply - // pre-generated subcircuits, which are pairwise partially equivalent. - qc::Qubit groupBeginIndex = 0; - std::uniform_int_distribution randomDistrGroupSize(1, 2); - while (groupBeginIndex < d) { - qc::Qubit groupSize = 1; - if (groupBeginIndex < d - 1) { - groupSize = randomDistrGroupSize(randomGenerator); - } - - addPreGeneratedCircuits(circuit1, circuit2, n, groupBeginIndex, groupSize); - - groupBeginIndex += groupSize; - } - - circuit1.barrier(); - circuit2.barrier(); - - // 4) Arbitrary gates - // Arbitrary gates are added to data qubits that are not measured - if (d > m) { - const qc::Qubit notMQubits = d - m; - for (qc::Qubit i = 0U; i < notMQubits; i++) { - addStandardOperationToCircuit( - circuit1, - makeRandomStandardOperation(n, notMQubits, m, randomGenerator), - false); - addStandardOperationToCircuit( - circuit2, - makeRandomStandardOperation(n, notMQubits, m, randomGenerator), - false); - } - } - - circuit1.barrier(); - circuit2.barrier(); - - // 5) CNOT gates - // For each ancilla qubit, add a CNOT that has the ancilla as control qubit, - // and any data qubit as target. As ancilla qubits are initially set to 0 and - // we haven't added any other gates to the ancilla qubits until now, these - // CNOT gates do not affect the circuit. - if (d > 0) { - qc::Qubit currentDataQubit = 0; - for (qc::Qubit currentAncillaQubit = d; currentAncillaQubit < n; - currentAncillaQubit++) { - auto nextDataQubit = (currentDataQubit + 1) % d; - circuit1.cx(currentAncillaQubit, currentDataQubit); - circuit2.cx(currentAncillaQubit, nextDataQubit); - currentDataQubit = nextDataQubit; - } - } - - for (qc::Qubit i = d; i < n; i++) { - circuit1.setLogicalQubitAncillary(i); - circuit2.setLogicalQubitAncillary(i); - } - - for (qc::Qubit i = m; i < n; i++) { - circuit1.setLogicalQubitGarbage(i); - circuit2.setLogicalQubitGarbage(i); - } - - return std::make_pair(circuit1, circuit2); -} - -} // namespace dd diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index 4f734567..8e35253b 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -4,10 +4,342 @@ // #include "EquivalenceCheckingManager.hpp" -#include "checker/dd/DDPartialEquivalenceBenchmarks.hpp" +#include "QuantumComputation.hpp" +#include "operations/OpType.hpp" +#include "operations/StandardOperation.hpp" #include "gtest/gtest.h" +namespace dd { + +const std::vector> PRE_GENERATED_CIRCUITS_SIZE_1_1{ + {}, {}, {}, {}}; + +const std::vector> PRE_GENERATED_CIRCUITS_SIZE_1_2{ + {Z}, {Tdg}, {S}, {Sdg}}; + +const std::vector> PRE_GENERATED_CIRCUITS_SIZE_2_1{ + {}, {}, {}, {}, {X}, {X}}; + +const std::vector> PRE_GENERATED_CIRCUITS_SIZE_2_2{ + {Z}, {Tdg}, {S}, {Sdg}, {X, Z}, {Z, X}}; + +void addPreGeneratedCircuits(QuantumComputation& circuit1, + QuantumComputation& circuit2, const size_t n, + const qc::Qubit groupBeginIndex, + const qc::Qubit groupSize) { + const auto& circuits1 = groupSize == 1 ? PRE_GENERATED_CIRCUITS_SIZE_1_1 + : PRE_GENERATED_CIRCUITS_SIZE_2_1; + const auto& circuits2 = groupSize == 1 ? PRE_GENERATED_CIRCUITS_SIZE_1_2 + : PRE_GENERATED_CIRCUITS_SIZE_2_2; + const auto nrCircuits = circuits1.size(); + auto randomGenerator = circuit1.getGenerator(); + std::uniform_int_distribution randomDistribution(0, nrCircuits - 1); + + const auto randomIndex = randomDistribution(randomGenerator); + const auto x1 = circuits1[randomIndex]; + const auto x2 = circuits2[randomIndex]; + for (auto gateType : x1) { + if (gateType == X) { // add CNOT + circuit1.emplace_back(n, groupBeginIndex, + groupBeginIndex + 1, gateType); + } else { + circuit1.emplace_back(n, groupBeginIndex, gateType); + } + } + for (auto gateType : x2) { + if (gateType == X) { // add CNOT + circuit2.emplace_back(n, groupBeginIndex, + groupBeginIndex + 1, gateType); + } else { + circuit2.emplace_back(n, groupBeginIndex, gateType); + } + } +} + +void addDecomposedCcxGate(QuantumComputation& circuit, const Controls& controls, + const qc::Qubit target) { + const qc::Qubit control1 = controls.begin()->qubit; + const qc::Qubit control2 = (++controls.begin())->qubit; + circuit.h(target); + circuit.cx(control1, target); + circuit.tdg(target); + circuit.cx(control2, target); + circuit.t(target); + circuit.cx(control1, target); + circuit.tdg(target); + circuit.cx(control2, target); + circuit.t(target); + circuit.t(control1); + circuit.h(target); + circuit.cx(control2, control1); + circuit.t(control2); + circuit.tdg(control1); + circuit.cx(control2, control1); +} + +void addStandardOperationToCircuit(QuantumComputation& circuit, + const StandardOperation& op, + const bool decomposeCcx) { + if (op.getType() == X && decomposeCcx && op.getControls().size() == 2) { + // decompose toffoli gate + addDecomposedCcxGate(circuit, op.getControls(), op.getTargets()[0]); + } else { + circuit.emplace_back(op); + } +} + +std::vector +fiveDiffferentRandomNumbers(const qc::Qubit min, const qc::Qubit max, + std::mt19937_64& randomGenerator) { + std::vector numbers; + + for (qc::Qubit i = min; i < max; i++) { + numbers.emplace_back(i); + } + std::shuffle(numbers.begin(), numbers.end(), randomGenerator); + + const int64_t lengthOutputVector{ + static_cast(std::min(5UL, numbers.size()))}; + + std::vector outputVector(numbers.begin(), + numbers.begin() + lengthOutputVector); + return outputVector; +} + +StandardOperation convertToStandardOperation( + const size_t n, const size_t nrQubits, const OpType randomOpType, + const qc::Qubit randomTarget1, const qc::Qubit randomTarget2, + const fp randomParameter1, const fp randomParameter2, + const fp randomParameter3, const Controls& randomControls) { + switch (randomOpType) { + // two targets and zero parameters + case qc::SWAP: + case qc::iSWAP: + case qc::iSWAPdg: + case qc::Peres: + case qc::Peresdg: + case qc::DCX: + case qc::ECR: + if (nrQubits > 1) { + return {n, randomControls, Targets{randomTarget1, randomTarget2}, + randomOpType}; + } + break; + + // two targets and one parameter + case qc::RXX: + case qc::RYY: + case qc::RZZ: + case qc::RZX: + if (nrQubits > 1) { + return {n, randomControls, Targets{randomTarget1, randomTarget2}, + randomOpType, std::vector{randomParameter1}}; + } + break; + + // two targets and two parameters + case qc::XXminusYY: + case qc::XXplusYY: + if (nrQubits > 1) { + return {n, randomControls, Targets{randomTarget1, randomTarget2}, + randomOpType, + std::vector{randomParameter1, randomParameter2}}; + } + break; + + // one target and zero parameters + case qc::I: + case qc::H: + case qc::X: + case qc::Y: + case qc::Z: + case qc::S: + case qc::Sdg: + case qc::T: + case qc::Tdg: + case qc::V: + case qc::Vdg: + case qc::SX: + case qc::SXdg: + return {n, randomControls, randomTarget1, randomOpType}; + // one target and three parameters + case qc::U: + return { + n, randomControls, randomTarget1, randomOpType, + std::vector{randomParameter1, randomParameter2, randomParameter3}}; + // one target and two parameters + case qc::U2: + return {n, randomControls, randomTarget1, randomOpType, + std::vector{randomParameter1, randomParameter2}}; + // one target and one parameter + case qc::P: + case qc::RX: + case qc::RY: + case qc::RZ: + return {n, randomControls, randomTarget1, randomOpType, + std::vector{randomParameter1}}; + default: + return {n, randomTarget1, qc::I}; + } + return {n, randomTarget1, qc::I}; +} + +StandardOperation +makeRandomStandardOperation(const size_t n, const qc::Qubit nrQubits, + const qc::Qubit min, + std::mt19937_64& randomGenerator) { + const auto randomNumbers = + fiveDiffferentRandomNumbers(min, min + nrQubits, randomGenerator); + + // choose one of the non-compound operations, but not "None", and also + // not GPhase or I or Barrier + std::uniform_int_distribution<> randomDistrOpType(H, RZX); + auto randomOpType = static_cast(randomDistrOpType(randomGenerator)); + const qc::Qubit randomTarget1 = randomNumbers[0]; + qc::Qubit randomTarget2{min}; + if (randomNumbers.size() > 1) { + randomTarget2 = randomNumbers[1]; + }; + // choose random controls, but not more than available qubits + std::uniform_int_distribution randomDistrNrControls(0, 2); + size_t nrControls = std::min(randomNumbers.size() - 3, + randomDistrNrControls(randomGenerator)); + if (randomNumbers.size() < 3) { + nrControls = 0; + } + if (nrControls == 2) { + // otherwise toffoli gates are almost never generated + randomOpType = qc::X; + } + Controls randomControls{}; + for (size_t i = 0; i < nrControls; i++) { + randomControls.emplace(randomNumbers[i + 2]); + } + std::uniform_real_distribution randomDistrParameters(0, 2 * PI); + const fp randomParameter1 = randomDistrParameters(randomGenerator); + const fp randomParameter2 = randomDistrParameters(randomGenerator); + const fp randomParameter3 = randomDistrParameters(randomGenerator); + return convertToStandardOperation( + n, nrQubits, randomOpType, randomTarget1, randomTarget2, randomParameter1, + randomParameter2, randomParameter3, randomControls); +} + +/** + Generate random benchmarks for partial equivalence checking. Returns pairs of +circuits which are partially equivalent, following the method described in the +paper "Partial Equivalence Checking of Quantum +Circuits" (https://arxiv.org/abs/2208.07564) in Section VI. B. + @param n number of qubits of the resulting circuits + @param d number of data qubits in the resulting circuits + @param m number of measured qubits in the resulting circuit + @return two circuits that are partially equivalent +**/ +std::pair +generatePartiallyEquivalentCircuits(const size_t n, const qc::Qubit d, + const qc::Qubit m) { + if (d > n || m > n) { + throw std::runtime_error("The number of data or measured qubits can't be " + "bigger than the total number of qubits. n = " + + std::to_string(n) + "; d = " + std::to_string(d) + + "; m = " + std::to_string(m)); + } + + qc::QuantumComputation circuit1{n}; + qc::QuantumComputation circuit2{n}; + + auto randomGenerator = circuit1.getGenerator(); + + // 1) H gates + for (qc::Qubit i = 0U; i < d; i++) { + circuit1.h(i); + circuit2.h(i); + } + + circuit1.barrier(); + circuit2.barrier(); + + // 2) Totally equivalent subcircuits + // Generate a random subcircuit with d qubits and 3*d gates to apply + // on both circuits, but all the Toffoli gates in circuit2 are decomposed + for (qc::Qubit i = 0U; i < 3 * d; i++) { + const auto op = makeRandomStandardOperation(n, d, 0, randomGenerator); + addStandardOperationToCircuit(circuit1, op, false); + addStandardOperationToCircuit(circuit2, op, true); + } + + circuit1.barrier(); + circuit2.barrier(); + + // 3) Partially equivalent subcircuits + // Divide data qubits into groups of size 1 or 2. For each group, we apply + // pre-generated subcircuits, which are pairwise partially equivalent. + qc::Qubit groupBeginIndex = 0; + std::uniform_int_distribution randomDistrGroupSize(1, 2); + while (groupBeginIndex < d) { + qc::Qubit groupSize = 1; + if (groupBeginIndex < d - 1) { + groupSize = randomDistrGroupSize(randomGenerator); + } + + addPreGeneratedCircuits(circuit1, circuit2, n, groupBeginIndex, groupSize); + + groupBeginIndex += groupSize; + } + + circuit1.barrier(); + circuit2.barrier(); + + // 4) Arbitrary gates + // Arbitrary gates are added to data qubits that are not measured + if (d > m) { + const qc::Qubit notMQubits = d - m; + for (qc::Qubit i = 0U; i < notMQubits; i++) { + addStandardOperationToCircuit( + circuit1, + makeRandomStandardOperation(n, notMQubits, m, randomGenerator), + false); + addStandardOperationToCircuit( + circuit2, + makeRandomStandardOperation(n, notMQubits, m, randomGenerator), + false); + } + } + + circuit1.barrier(); + circuit2.barrier(); + + // 5) CNOT gates + // For each ancilla qubit, add a CNOT that has the ancilla as control qubit, + // and any data qubit as target. As ancilla qubits are initially set to 0 and + // we haven't added any other gates to the ancilla qubits until now, these + // CNOT gates do not affect the circuit. + if (d > 0) { + qc::Qubit currentDataQubit = 0; + for (qc::Qubit currentAncillaQubit = d; currentAncillaQubit < n; + currentAncillaQubit++) { + auto nextDataQubit = (currentDataQubit + 1) % d; + circuit1.cx(currentAncillaQubit, currentDataQubit); + circuit2.cx(currentAncillaQubit, nextDataQubit); + currentDataQubit = nextDataQubit; + } + } + + for (qc::Qubit i = d; i < n; i++) { + circuit1.setLogicalQubitAncillary(i); + circuit2.setLogicalQubitAncillary(i); + } + + for (qc::Qubit i = m; i < n; i++) { + circuit1.setLogicalQubitGarbage(i); + circuit2.setLogicalQubitGarbage(i); + } + + return std::make_pair(circuit1, circuit2); +} + +} // namespace dd + class PartialEquivalenceTest : public testing::Test { void SetUp() override { qc1 = qc::QuantumComputation(nqubits, nqubits); From b62dc1632b4daa3b3c8d98002263f4dceda040ce Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 15:09:26 +0100 Subject: [PATCH 37/41] =?UTF-8?q?=F0=9F=8E=A8=20small=20revisions=20to=20t?= =?UTF-8?q?ests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- test/legacy/test_journal.cpp | 2 ++ test/test_partial_equivalence.cpp | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/legacy/test_journal.cpp b/test/legacy/test_journal.cpp index ed2ec9d8..e8f19113 100644 --- a/test/legacy/test_journal.cpp +++ b/test/legacy/test_journal.cpp @@ -146,6 +146,7 @@ TEST_P(JournalTestNonEQ, PowerOfSimulation) { config.execution.timeout = 60.; config.simulation.maxSims = 16U; config.application.simulationScheme = ec::ApplicationSchemeType::Sequential; + config.functionality.checkPartialEquivalence = true; for (std::uint16_t i = 0U; i < tries; ++i) { qcOriginal.import(testOriginalDir + std::get<0>(GetParam()) + ".real"); @@ -199,6 +200,7 @@ TEST_P(JournalTestNonEQ, PowerOfSimulationParallel) { config.execution.timeout = 60.; config.simulation.maxSims = 16U; config.application.simulationScheme = ec::ApplicationSchemeType::Sequential; + config.functionality.checkPartialEquivalence = true; for (std::uint16_t i = 0; i < tries; ++i) { qcOriginal.import(testOriginalDir + std::get<0>(GetParam()) + ".real"); diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index 8e35253b..b59a8891 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -209,7 +209,7 @@ makeRandomStandardOperation(const size_t n, const qc::Qubit nrQubits, nrControls = 0; } if (nrControls == 2) { - // otherwise toffoli gates are almost never generated + // otherwise Toffoli gates are almost never generated randomOpType = qc::X; } Controls randomControls{}; @@ -767,7 +767,6 @@ TEST_F(PartialEquivalenceTest, SliQECGrover22Qubits) { c2.setLogicalQubitGarbage(11); // construction checker - // adds 10 ancillary qubits -> total number of qubits is 22 config.execution.runConstructionChecker = true; ec::EquivalenceCheckingManager ecm(c1, c2, config); ecm.run(); @@ -789,7 +788,6 @@ TEST_F(PartialEquivalenceTest, SliQECAdd19Qubits) { c1.setLogicalQubitsGarbage(8, 18); c2.setLogicalQubitsGarbage(8, 18); - // doesn't add ancillary qubits -> total number of qubits is 19 config.execution.runConstructionChecker = true; ec::EquivalenceCheckingManager ecm(c1, c2, config); ecm.run(); From 636cfd33ce6e9cf8b253b3bafd056eb003b10da3 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 15:47:08 +0100 Subject: [PATCH 38/41] =?UTF-8?q?=F0=9F=93=9D=20update=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- docs/source/PartialEquivalence.ipynb | 57 ++++++++++++++++++---------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/docs/source/PartialEquivalence.ipynb b/docs/source/PartialEquivalence.ipynb index 90275931..ee5ff0fa 100644 --- a/docs/source/PartialEquivalence.ipynb +++ b/docs/source/PartialEquivalence.ipynb @@ -5,7 +5,7 @@ "id": "77a131e6", "metadata": {}, "source": [ - "# Partial Equivalence Checking of Quantum Circuits\n", + "# Partial Equivalence Checking\n", "\n", "## Partial Equivalence vs. Total Equivalence\n", "\n", @@ -17,7 +17,7 @@ "In particular, partial equivalence doesn't consider qubits that are not measured or different phase angles for each measurement.\n", "\n", "This definition is especially useful for circuits that do not measure all of their qubits at the end, or where some qubits are initialized to a certain value at the beginning. \n", - "We refer to the qubits that are initialized to a certain value at the beginning of the computation *ancillary* qubits. \n", + "We refer to the qubits that are initialized to a certain value at the beginning of the computation as *ancillary* qubits. \n", "Without loss of generality, we assume that these qubits are initially set to $|0\\rangle$. \n", "Any other initial state can be reached from the $|0\\rangle$ state by applying the appropriate gates. \n", "The remaining qubits are the qubits that hold the input state, and they are referred to as *data* qubits.\n", @@ -39,7 +39,7 @@ "metadata": {}, "source": [ "\n", - "## Equivalence Checking of Partially Equivalent Quantum Circuits\n", + "## Checking Partial Equivalence of Quantum Circuits\n", "\n", "Partial equivalence checking is a bit more costly than regular equivalence checking. \n", "It is necessary to reduce the contribution of garbage qubits and normalize the phase of each measurement outcome. \n", @@ -54,18 +54,18 @@ "\n", "The following is a summary of the behaviour of each type of equivalence checker when the `check_partial_equivalence` option is set to `True`.\n", "\n", - "1. **Construction Equivalence Checker:** The construction checker supports partial equivalence checking by using decision diagrams to calculate the nnormalized phases of the possible ouputs and then summing up the contribution of garbage qubits, in order to consider only the measurement probabilities of measured qubits. \n", + "1. **Construction Equivalence Checker:** The construction checker supports partial equivalence checking by using decision diagrams to calculate the normalized phases of the possible outputs and then summing up the contribution of garbage qubits, in order to consider only the measurement probabilities of measured qubits. \n", "Then it compares the reduced decision diagrams of the two circuits. \n", "\n", "1. **Alternating Equivalence Checker:** The alternating checker can only be used for circuits where at least one of the two does not contain ancillary qubits. \n", - "It normally computes the composition of one circuit with the inverse of the other and verifies that the result is the identity matrix. \n", - "When checking for partial equivalence, it suffices to verify that the result is a diagonal matrix (modulo garbage qubits). \n", + "It computes the composition of one circuit with the inverse of the other and verifies that the result resembles the identity. \n", + "When checking for partial equivalence, it suffices to verify that the result resembles the identity modulo garbage qubits. \n", "\n", - "1. **Simulation Equivalence Checker:** The simulation checker computes the vector representation of the result of the circuit applied to certain initial states. \n", - "The contributions of garbage qubits are summed up only when checking for partial equivalence.\n", + "1. **Simulation Equivalence Checker:** The simulation checker computes a representation of the state vector resulting from simulating the circuit with certain initial states. \n", + "Partial equivalence is enabled by summing up the contributions of garbage qubits.\n", "\n", "1. **ZX-Calculus Equivalence Checker:** The ZX-calculus checker doesn't directly support partial equivalence, which is not a problem for the equivalence checking workflow, \n", - "given that the ZX-calculus checker cannot demonstrate non-equivalence of circuits. \n", + "given that the ZX-calculus checker cannot demonstrate non-equivalence of circuits due to its incompleteness. \n", "Therefore it will simply output 'No Information' for circuits that are partially but not totally equivalent." ] }, @@ -74,7 +74,7 @@ "id": "977071d9", "metadata": {}, "source": [ - "## Using QCEC to Verify Partial Equivalent Circuits\n", + "## Using QCEC to Check for Partial Equivalence\n", "\n", "Consider the following quantum circuit with three qubits, which are all data qubits, but only one of them is measured." ] @@ -100,17 +100,16 @@ }, { "cell_type": "markdown", - "id": "3b85338e", + "id": "10fff8c7-f36c-422e-8deb-796cc7637e45", "metadata": {}, "source": [ - "The following circuit is not totally equivalent to the previous one. \n", - "The two circuits are however partially equivalent, because they have the same probability distribution of measured values for any given initial input state." + "Aditionally, consider the following circuit, which only acts on two qubits." ] }, { "cell_type": "code", "execution_count": null, - "id": "36df44b7", + "id": "d167869e-e082-4a42-9eab-112931f5c697", "metadata": {}, "outputs": [], "source": [ @@ -121,12 +120,34 @@ "qc_rhs.draw(output=\"mpl\", style=\"iqp\")" ] }, + { + "cell_type": "markdown", + "id": "3b85338e", + "metadata": {}, + "source": [ + "Then, these circuits are not totally equivalent, as can be shown using QCEC. \n", + "The library even emits a handy warning in this case that indicates that two circuits have been shown to be non-equivalent, but at least one of the circuits does not measure all its qubits (i.e., has garbage qubits) and partial equivalence checking support has not been enabled." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36df44b7", + "metadata": {}, + "outputs": [], + "source": [ + "from mqt.qcec import verify\n", + "\n", + "verify(qc_lhs, qc_rhs)" + ] + }, { "cell_type": "markdown", "id": "8cae4862", "metadata": {}, "source": [ - "This equality can be proved with QCEC by using the `verify` method and setting the configuration `check_partial_equivalence` to `True`:" + "However, both circuits are partially equivalent, because they have the same probability distribution of measured values for any given initial input state.\n", + "This equality can be proven with QCEC by enabling the `check_partial_equivalence` option:" ] }, { @@ -136,9 +157,7 @@ "metadata": {}, "outputs": [], "source": [ - "from mqt import qcec\n", - "\n", - "qcec.verify(qc_lhs, qc_rhs, check_partial_equivalence=True)" + "verify(qc_lhs, qc_rhs, check_partial_equivalence=True)" ] }, { @@ -152,7 +171,7 @@ ], "metadata": { "kernelspec": { - "display_name": "venv", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, From 21368a54bd0a6cfa0abbbd2d1d0a4961d55189d8 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 15:47:28 +0100 Subject: [PATCH 39/41] =?UTF-8?q?=F0=9F=A9=B9=20link=20new=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- docs/source/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/index.rst b/docs/source/index.rst index 29e8088a..5c09ecff 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -26,6 +26,7 @@ We appreciate any feedback and contributions to the project. If you want to cont EquivalenceChecking CompilationFlowVerification ParameterizedCircuits + PartialEquivalence Publications .. toctree:: From 645cffd1f1fd9333da0bafc82fccfec11643ac8e Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 16:37:35 +0100 Subject: [PATCH 40/41] =?UTF-8?q?=F0=9F=94=80=20switch=20back=20to=20`main?= =?UTF-8?q?`=20branch=20of=20mqt-core?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .gitmodules | 4 ++-- extern/mqt-core | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 5d08fb5e..1c485ae9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "extern/mqt-core"] path = extern/mqt-core - url = https://github.com/reb-ddm/mqt-core.git - branch = test-reduce-garbage + url = https://github.com/cda-tum/mqt-core.git + branch = main diff --git a/extern/mqt-core b/extern/mqt-core index 4627f7dd..cb35875f 160000 --- a/extern/mqt-core +++ b/extern/mqt-core @@ -1 +1 @@ -Subproject commit 4627f7dd2b1dad38c5dc43aecf298a2ee021ae91 +Subproject commit cb35875f835d0fc40f0d27dbb6d2404683240b1c From faf7d2e03d9b8a5c9c0cb87f97d804f565017d20 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Mon, 18 Mar 2024 16:46:41 +0100 Subject: [PATCH 41/41] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20fix=20whitespace=20i?= =?UTF-8?q?nconsistency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: burgholzer --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 1c485ae9..19a33270 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "extern/mqt-core"] - path = extern/mqt-core - url = https://github.com/cda-tum/mqt-core.git + path = extern/mqt-core + url = https://github.com/cda-tum/mqt-core.git branch = main