├── .gitignore ├── Grover_s_Algorithm.pdf ├── LICENSE ├── README.md ├── requirements.txt └── src ├── 5_ ancilla.png ├── 5_noancilla.png ├── Demo_phase&modified_vs_boolean.ipynb ├── Different Designs Comparison ├── Quantum cost of Walid's & Omar's circuit.ipynb ├── Reduce_circuits_depth.ipynb ├── Results.ipynb ├── ancilla_success_prob.png ├── computations.png ├── d2_d3.png └── noancilla_success_prob.png ├── Grover ├── __init__.py ├── diffuser.py ├── grover.py ├── main.ipynb ├── oracle.py ├── test_grover.py └── utils.py └── phase&modified_grover.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .huskyrc.json 3 | out 4 | log.log 5 | **/node_modules 6 | *.pyc 7 | *.vsix 8 | **/.vscode/.ropeproject/** 9 | **/testFiles/**/.cache/** 10 | *.noseids 11 | .nyc_output 12 | .vscode-test 13 | __pycache__ 14 | npm-debug.log 15 | **/.mypy_cache/** 16 | !yarn.lock 17 | coverage/ 18 | cucumber-report.json 19 | **/.vscode-test/** 20 | **/.vscode test/** 21 | **/.vscode-smoke/** 22 | **/.venv*/ 23 | port.txt 24 | precommit.hook 25 | pythonFiles/experimental/ptvsd/** 26 | pythonFiles/lib/** 27 | debug_coverage*/** 28 | languageServer/** 29 | languageServer.*/** 30 | bin/** 31 | obj/** 32 | .pytest_cache 33 | tmp/** 34 | .python-version 35 | .vs/ 36 | test-results.xml 37 | xunit-test-results.xml 38 | build/ci/performance/performance-results.json 39 | !build/ 40 | debug*.log 41 | ptvsd*.log 42 | pydevd*.log 43 | nodeLanguageServer/** 44 | nodeLanguageServer.*/** 45 | .vscode 46 | **/.vscode 47 | */.vscode 48 | */__pycache__ 49 | **/__pycache__ 50 | .ipynb_checkpoints 51 | */.ipynb_checkpoints 52 | **/.ipynb_checkpoints -------------------------------------------------------------------------------- /Grover_s_Algorithm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melsayed-7/Grover-s-Algorithm-QOSF/4f29158582c87ca0c0bf289eeddab52e90858360/Grover_s_Algorithm.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Grover's Algorithm 2 | 3 | This project is the result of the 3-months [QOSF](https://qosf.org/) mentorship progam. 4 | 5 | The project is the exploration of the designs of Grover's algorithm (ancilla and non-ancilla qubits). Also, we have done complexity analysis of each design on different qubit-number designs to see how the complexity changes by increasing the number of qubits of the length code of the element to be searched for. 6 | 7 | 8 | ## Getting Started 9 | open the terminal 10 | ``` 11 | git clone https://github.com/moustafa-7/Grover-s-Algorithm-QOSF.git 12 | ``` 13 | ``` 14 | cd Grover-s-Algorithm-QOSF 15 | ``` 16 | installing all dependencies 17 | ``` 18 | pip install -r requirements.txt 19 | ``` 20 | 21 | 22 | ### How to use 23 | 24 | check the file [src/Grover/main.ipynb](https://github.com/moustafa-7/Grover-s-Algorithm-QOSF/blob/master/src/Grover/main.ipynb) to see examples and how to use 25 | 26 | 27 | ## Running the tests 28 | navigate to **src/Grover** and then run this command 29 | ``` 30 | python3 grover.py 31 | ``` 32 | 33 | ## Some plots 34 | * Success probability of the ancilla design (length of string = 3) 35 | ![image](src/Different%20Designs%20Comparison/ancilla_success_prob.png) 36 | 37 | * Success probability of the noancilla design (length of string = 3) 38 | ![image](src/Different%20Designs%20Comparison/noancilla_success_prob.png) 39 | 40 | * length of input string VS Number of computations (u3 + cx gates) used 41 | ![image](src/Different%20Designs%20Comparison/computations.png) 42 | 43 | 44 | 45 | 46 | ## Authors 47 | 48 | The project was done by: 49 | * **Omar Ali** s-omar.hussein@zewailcity.edu.eg 50 | * [**Walid El Maouaki**](https://github.com/walid-mk) 51 | * [**Moustafa Elsayed**](https://github.com/moustafa-7) 52 | 53 | under the supervision of [**Dr. Yuval Sanders**](https://researchers.mq.edu.au/en/persons/yuval-sanders/publications/). 54 | 55 | ## License 56 | Apache License 2.0
57 | This project is licensed under the Apache License - see the [LICENSE.md](https://github.com/moustafa-7/Grover-s-Algorithm-QOSF/blob/master/LICENSE) file for details 58 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | qiskit 2 | unittest -------------------------------------------------------------------------------- /src/5_ ancilla.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melsayed-7/Grover-s-Algorithm-QOSF/4f29158582c87ca0c0bf289eeddab52e90858360/src/5_ ancilla.png -------------------------------------------------------------------------------- /src/5_noancilla.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melsayed-7/Grover-s-Algorithm-QOSF/4f29158582c87ca0c0bf289eeddab52e90858360/src/5_noancilla.png -------------------------------------------------------------------------------- /src/Different Designs Comparison/Quantum cost of Walid's & Omar's circuit.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Find the number of gates and calculate the quantum cost of the circuit + a general Grover's algorithm code.\n", 8 | "Here I intend to compare two code **Walid's** code and **Omar's** code on Grover's algorithm for searching a string of binary numbers by calculating the quantum cost of both circuits." 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 6, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "import sys, os\n", 18 | "sys.path.append(os.path.abspath(os.path.join('..', 'Grover')))" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 7, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "from qiskit import *\n", 28 | "from grover import *" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "### String to be found is '01011001'" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 8, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "data": { 45 | "text/plain": [ 46 | "" 47 | ] 48 | }, 49 | "execution_count": 8, 50 | "metadata": {}, 51 | "output_type": "execute_result" 52 | } 53 | ], 54 | "source": [ 55 | "################################## OMAR'S CODE ##################################\n", 56 | "circuit=QuantumCircuit(16,8)\n", 57 | "a=[0,1,2,3,4,5,6,7,15]\n", 58 | "b=[0,1,2,3,4,5,6,7]\n", 59 | "circuit.x(15)\n", 60 | "circuit.h(a)\n", 61 | "i=0\n", 62 | "while i<12:\n", 63 | " i=i+1\n", 64 | " #oracle\n", 65 | " circuit.x([1,2,5,7])\n", 66 | " circuit.ccx(0,1,8)\n", 67 | " x=2\n", 68 | " y=8\n", 69 | " z=9\n", 70 | " while x<8:\n", 71 | " circuit.ccx(x,y,z)\n", 72 | " x=x+1\n", 73 | " y=y+1\n", 74 | " z=z+1\n", 75 | " circuit.cx(14,15)\n", 76 | " while x>2:\n", 77 | " x=x-1\n", 78 | " y=y-1\n", 79 | " z=z-1\n", 80 | " circuit.ccx(x,y,z)\n", 81 | " circuit.ccx(0,1,8)\n", 82 | " circuit.x([1,2,5,7])\n", 83 | "\n", 84 | " #grover diffusion operator\n", 85 | " circuit.h(b)\n", 86 | " circuit.x(b)\n", 87 | " circuit.ccx(0,1,8)\n", 88 | " x=2\n", 89 | " y=8\n", 90 | " z=9\n", 91 | " while x<8:\n", 92 | " circuit.ccx(x,y,z)\n", 93 | " x=x+1\n", 94 | " y=y+1\n", 95 | " z=z+1\n", 96 | " circuit.cx(14,15)\n", 97 | " while x>2:\n", 98 | " x=x-1\n", 99 | " y=y-1\n", 100 | " z=z-1\n", 101 | " circuit.ccx(x,y,z)\n", 102 | " circuit.ccx(0,1,8) \n", 103 | " circuit.x(b)\n", 104 | " circuit.h(b)\n", 105 | "\n", 106 | "circuit.measure(b,b)" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "### -Number of gate:\n", 114 | "**Use the `count_ops()` method to harvest the number of operations in the circuit.**" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 9, 120 | "metadata": {}, 121 | "outputs": [ 122 | { 123 | "data": { 124 | "text/plain": [ 125 | "OrderedDict([('ccx', 336), ('x', 289), ('h', 201), ('cx', 24), ('measure', 8)])" 126 | ] 127 | }, 128 | "execution_count": 9, 129 | "metadata": {}, 130 | "output_type": "execute_result" 131 | } 132 | ], 133 | "source": [ 134 | "########### Count the operators ###########\n", 135 | "circuit.count_ops()" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "### -Quantum Cost:\n", 143 | "The quantum cost of a circuit is the number of primitive quantum gates needed to implement the circuit.\n", 144 | "\n", 145 | "* First let's discover the quantum cost of each gate that will be used in our circuit; which are `cx`, `ccx`, `x`, and `h` gates. To do so, we must rely on the `decompose()`method to break down our gates." 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 6, 151 | "metadata": {}, 152 | "outputs": [ 153 | { 154 | "data": { 155 | "image/png": "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\n", 156 | "text/plain": [ 157 | "
" 158 | ] 159 | }, 160 | "execution_count": 6, 161 | "metadata": {}, 162 | "output_type": "execute_result" 163 | } 164 | ], 165 | "source": [ 166 | "cost=QuantumCircuit(3)\n", 167 | "cost.cx(0,1)\n", 168 | "cost.barrier()\n", 169 | "cost.x(0)\n", 170 | "cost.barrier()\n", 171 | "cost.h(0)\n", 172 | "cost.barrier()\n", 173 | "cost.ccx(0,1,2)\n", 174 | "cost.decompose().draw('mpl')" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "And voila!\n", 182 | "\n", 183 | "$\\rightarrow$ The quantum cost of these gates are:\n", 184 | "\n", 185 | "* Control Gate `cx` = $1$.\n", 186 | "* Not Gate `x` = $1$.\n", 187 | "* Hadamard Gate `h` = $1$.\n", 188 | "* Toffoli Gate `ccx` = $15$.\n", 189 | "\n", 190 | "**Each quantum computer model may have a different cost for a given quantum gate.**\n", 191 | "\n", 192 | "As seen above There are in *Omar's* circuit: \n", 193 | "\n", 194 | "* $336$ Toffoli Gate `ccx`.\n", 195 | "* $289$ Not Gate `x`.\n", 196 | "* $201$ Hadamard Gate `h`.\n", 197 | "* $24$ Control Gate `cx`.\n", 198 | "\n", 199 | "$\\rightarrow$ **Hence the quantum cost of that Omar's circuit is:**$$Quantum\\;Cost = 15\\times336 + 1\\times289 + 1\\times201 + 1\\times24 = 5554.$$\n", 200 | "\n", 201 | "Actually, let us decompose the circuit to the primitive gates (elementary gates), like the rotation gates U3 and the CNOT gate, then calculate the cost.\n", 202 | "\n", 203 | "Any unitary operation can be replaced by a combination of controlled-NOT (CNOT) and single qubit gate, like U1,2,3 gates.\n", 204 | "\n", 205 | "By using `qiskit.transpiler` and importing `PassManager`, we can decompose this circuit into U3 (`u3`) gates and CNOT (`cx`) gates using the qiskit tool `Unroller` program, as seen below:" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 10, 211 | "metadata": {}, 212 | "outputs": [ 213 | { 214 | "data": { 215 | "text/plain": [ 216 | "OrderedDict([('u3', 3514), ('cx', 2040), ('measure', 8)])" 217 | ] 218 | }, 219 | "execution_count": 10, 220 | "metadata": {}, 221 | "output_type": "execute_result" 222 | } 223 | ], 224 | "source": [ 225 | "from qiskit.transpiler import PassManager\n", 226 | "from qiskit.transpiler.passes import Unroller\n", 227 | "pass_ = Unroller(['u3', 'cx'])\n", 228 | "pm = PassManager(pass_)\n", 229 | "new_circuit = pm.run(circuit) \n", 230 | "new_circuit.count_ops()" 231 | ] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "metadata": {}, 236 | "source": [ 237 | "Then, we remark that there are:\n", 238 | "\n", 239 | "* $3514$ U3 Gate `u3`.\n", 240 | "* $2040$ Ctrolled Gate `cx`.\n", 241 | "\n", 242 | "$\\rightarrow$ Therefore, the quantum cost of that circuit in this case is:$$Quantum\\;Cost = 3514 + 2040= 5554.$$\n", 243 | "\n", 244 | "Which is equal to what we achieved above." 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "metadata": {}, 250 | "source": [ 251 | "Whereas, the CNOT gate is the most expensive gate to implement, wherein the current NISQ devises, the noise introduced implementing the CX gate is heavier.\n", 252 | "\n", 253 | "Consequently, we may weigh CX gates more than a single-qubit gate for the cost evaluation.\n", 254 | "\n", 255 | "**The lesser the quantum cost, the better the circuit.**\n", 256 | "\n", 257 | "This leads me to write a code that has three advantageous characteristics compared to the above one and outperforms on it, [(see the code test)](https://github.com/moustafa-7/Grover-s-Algorithm-QOSF/blob/master/src/Grover/main.ipynb):\n", 258 | "\n", 259 | "* It's a general code that accepts as input any string of a binary number to search for.\n", 260 | "\n", 261 | "* The boolean oracle and diffuser operator are carried out in two different ways:\n", 262 | "\n", 263 | " 1- An `'ancilla'` circuit; this one uses two-control Toffoli gates, thus the oracle will depends on ancillary qubits to be implemented, and its peculiarity lies in the diffuser operator, compared to Omar's one its gets rid of two Toffoli gates and uses instead two Hadamard gates, which is an advantage since the former is too expensive to implement.\n", 264 | " \n", 265 | " 2- An `'noancilla'` circuit, uses multiple-control Toffoli gates instead of two-control Toffoli gates in both oracle and diffuser parts.\n", 266 | " \n", 267 | "Let's see the difference between those circuits at the level of the quantum cost:" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 11, 273 | "metadata": {}, 274 | "outputs": [], 275 | "source": [ 276 | "################################## WALID'S CODE ##################################" 277 | ] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": {}, 282 | "source": [ 283 | "#### Same procedure to get the quantum cost:\n", 284 | "Let's evaluate the `ancilla` circuit first:" 285 | ] 286 | }, 287 | { 288 | "cell_type": "code", 289 | "execution_count": 13, 290 | "metadata": {}, 291 | "outputs": [ 292 | { 293 | "data": { 294 | "text/plain": [ 295 | "OrderedDict([('ccx', 312),\n", 296 | " ('x', 288),\n", 297 | " ('h', 216),\n", 298 | " ('cx', 24),\n", 299 | " ('u2', 9),\n", 300 | " ('measure', 8),\n", 301 | " ('u3', 1)])" 302 | ] 303 | }, 304 | "execution_count": 13, 305 | "metadata": {}, 306 | "output_type": "execute_result" 307 | } 308 | ], 309 | "source": [ 310 | "ancilla_circuit, *_ =grover_itera(['01011001'], 'ancilla')\n", 311 | "ancilla_circuit.decompose().count_ops()" 312 | ] 313 | }, 314 | { 315 | "cell_type": "markdown", 316 | "metadata": {}, 317 | "source": [ 318 | "* $312$ Toffoli Gate `ccx`.\n", 319 | "* $289$ Not Gate `x`= `u3(pi,0,pi)`.\n", 320 | "* $225$ Hadamard Gate `h`=`u2(0,pi)`.\n", 321 | "* $24$ Control Gate `cx`.\n", 322 | "\n", 323 | "$\\rightarrow$**Therefore, the cost of Walid's circuit is:**$$Quantum\\;Cost = 15\\times312 + 1\\times289 + 1\\times225 + 1\\times24 = 5218.$$\n", 324 | "\n", 325 | "$\\Rightarrow$ **As we can see the cost has been decreased, this is due to the decrease of the costly two-qubits Toffoli gate.**\n", 326 | "\n", 327 | "Without assessing the cost in the case of elementary gates, it turns out to be the same. However, this will be interesting in the case of `noancilla` circuit:" 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": 16, 333 | "metadata": {}, 334 | "outputs": [ 335 | { 336 | "data": { 337 | "text/plain": [ 338 | "OrderedDict([('u3', 14314), ('cx', 13728), ('measure', 8)])" 339 | ] 340 | }, 341 | "execution_count": 16, 342 | "metadata": {}, 343 | "output_type": "execute_result" 344 | } 345 | ], 346 | "source": [ 347 | "noancilla_circuit, *_ =grover_itera(['01011001'], 'noancilla')\n", 348 | "# to elementary gates: u3 and cx\n", 349 | "new_circuit = pm.run(noancilla_circuit) \n", 350 | "new_circuit.count_ops()" 351 | ] 352 | }, 353 | { 354 | "cell_type": "markdown", 355 | "metadata": {}, 356 | "source": [ 357 | "So, there are: \n", 358 | "\n", 359 | "* $14314$ U3 Gate `u3`.\n", 360 | "* $13728$ Ctrolled Gate `cx`.\n", 361 | "\n", 362 | "$\\rightarrow$ **The cost is large:**$$Quantum\\;Cost = 14314 + 13728= 28042.$$\n", 363 | "\n", 364 | "$\\Rightarrow$ **This leads to the conclusion that if you don't want to pay off on the number of qubits (circuit width), you are going to do so in the number of gates used (circuit depth)!**\n", 365 | "\n", 366 | "Definitely there are many ways to implement Grover's circuit to come up with better ones; for instance, using the phase oracle reduces the number of qubits used. Hence Walid's code still under development." 367 | ] 368 | } 369 | ], 370 | "metadata": { 371 | "kernelspec": { 372 | "display_name": "Python 3", 373 | "language": "python", 374 | "name": "python3" 375 | }, 376 | "language_info": { 377 | "codemirror_mode": { 378 | "name": "ipython", 379 | "version": 3 380 | }, 381 | "file_extension": ".py", 382 | "mimetype": "text/x-python", 383 | "name": "python", 384 | "nbconvert_exporter": "python", 385 | "pygments_lexer": "ipython3", 386 | "version": "3.7.6" 387 | } 388 | }, 389 | "nbformat": 4, 390 | "nbformat_minor": 4 391 | } 392 | -------------------------------------------------------------------------------- /src/Different Designs Comparison/Reduce_circuits_depth.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## I will reduce the `ancilla` & `noancilla` depth of Walid's circuits, not in terms of gates but in terms of the parallel implementation" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "import sys, os\n", 17 | "sys.path.append(os.path.abspath(os.path.join('..', 'Grover')))" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 12, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "from qiskit import *\n", 27 | "from grover import *" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "### There are two factors that contribute to the circuit depth:\n", 35 | "#### **1- The number of gates:**\n", 36 | "The depth of a circuit is the number of time steps required, assuming that gates acting on distinct bits can operate simultaneously (that is, the depth is the maximum length of a\n", 37 | "directed path from the input to the output of the circuit)[[1](http://www.theory.caltech.edu/~preskill/ph219/chap5_13.pdf)]. It's the maximum of the wire depths.\n", 38 | "\n", 39 | "*Example:* Let's suppose the following circuit and extract its depth:" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 13, 45 | "metadata": {}, 46 | "outputs": [ 47 | { 48 | "name": "stdout", 49 | "output_type": "stream", 50 | "text": [ 51 | "The detpth of that circuit equal: 4\n" 52 | ] 53 | }, 54 | { 55 | "data": { 56 | "image/png": "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\n", 57 | "text/plain": [ 58 | "
" 59 | ] 60 | }, 61 | "execution_count": 13, 62 | "metadata": {}, 63 | "output_type": "execute_result" 64 | } 65 | ], 66 | "source": [ 67 | "d1=QuantumCircuit(2,2)\n", 68 | "d1.x(1)\n", 69 | "d1.h(0)\n", 70 | "d1.x(0)\n", 71 | "d1.h(1)\n", 72 | "d1.h(1)\n", 73 | "d1.measure([0,1],[0,1])\n", 74 | "print('The detpth of that circuit equal:', d1.depth())\n", 75 | "d1.draw('mpl')" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "$\\rightarrow$ As can be seen, The first wire has depth 3 (the measurement is counted) and the second has depth 4. The circuit depth is 4, the maximum of the wire depths." 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "#### **2- Levels of a circuit:** \n", 90 | "This is another aspect that could lead to the increase or decrease of the circuit depth, **and this is what makes an issue in my code, which I will discuss below.**\n", 91 | "\n", 92 | "A level is defined as a subsequence of commuting gates that can be applied in parallel, whereby all gates of a certain level are executed within the same time unit. The gates of the next level are executed once all gates of the preceding level have been completed. A level compaction helps increase the parallelization of the circuit implementation and, therefore, not only optimizes the runtime of the circuit but also helps decrease the decoherence effects by shortening the overall execution time[[2](https://arxiv.org/abs/quant-ph/0604001)]. That increases the robustness and accuracy of the algorithm implementation, so if we could get a minimum number of circuit levels would be optimal!\n", 93 | "\n", 94 | "**Now let me address the main point, I added some barriers to the circuit in my code, and it was meant from them to provide a pleasant visualization of what the algorithm output, where they help me to distinguish the oracle from the diffuser part. But where I didn't pay attention is in the * Levels of a circuit * notion, and to explain why the `barrier` matter, I will show you how this gate can increase the depth of a circuit. I am going to use two circuits `d2` & `d3` where the former has no barriers whereas the latter does:**" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "* d2 circuit (no barriers)" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 14, 107 | "metadata": {}, 108 | "outputs": [ 109 | { 110 | "name": "stdout", 111 | "output_type": "stream", 112 | "text": [ 113 | "The detpth of the circuit d2 equal: 2\n" 114 | ] 115 | }, 116 | { 117 | "data": { 118 | "image/png": "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\n", 119 | "text/plain": [ 120 | "
" 121 | ] 122 | }, 123 | "execution_count": 14, 124 | "metadata": {}, 125 | "output_type": "execute_result" 126 | } 127 | ], 128 | "source": [ 129 | "d2=QuantumCircuit(3)\n", 130 | "d2.x(0)\n", 131 | "d2.h(0)\n", 132 | "d2.h(1)\n", 133 | "d2.x(2)\n", 134 | "d2.h(2)\n", 135 | "print('The detpth of the circuit d2 equal:', d2.depth())\n", 136 | "d2.draw('mpl')" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "* d3 circuit (with barriers)" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 15, 149 | "metadata": {}, 150 | "outputs": [ 151 | { 152 | "name": "stdout", 153 | "output_type": "stream", 154 | "text": [ 155 | "The detpth of the circuit d3 equal: 5\n" 156 | ] 157 | }, 158 | { 159 | "data": { 160 | "image/png": "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\n", 161 | "text/plain": [ 162 | "
" 163 | ] 164 | }, 165 | "execution_count": 15, 166 | "metadata": {}, 167 | "output_type": "execute_result" 168 | } 169 | ], 170 | "source": [ 171 | "d3=QuantumCircuit(3)\n", 172 | "d3.x(0)\n", 173 | "d3.h(0)\n", 174 | "d3.barrier()\n", 175 | "d3.h(1)\n", 176 | "d3.barrier()\n", 177 | "d3.x(2)\n", 178 | "d3.h(2)\n", 179 | "print('The detpth of the circuit d3 equal:', d3.depth())\n", 180 | "d3.draw('mpl')" 181 | ] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": {}, 186 | "source": [ 187 | "$\\rightarrow$ **Therefore, the number of levels in the d3 circuit increases to $5$ so that the depth is equal to $5$, as opposed to the d2 circuit with only two levels (depth=$2$). See figure:**\n", 188 | "\n", 189 | "\"drawing\"\n", 190 | "\n", 191 | "This shows that the functionality of adding barrier not just serves for a nice visualization but also prevent parallelization if needed (consequently expands the circuit depth).\n", 192 | "\n", 193 | "And let me illustrate how the depth decreases by running the code before and after committing (get rid of barriers) for both types of circuits `ancilla` & `noancilla`:" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "* ***Before committing: `ancilla` circuit*** (with barriers)" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 16, 206 | "metadata": {}, 207 | "outputs": [ 208 | { 209 | "name": "stdout", 210 | "output_type": "stream", 211 | "text": [ 212 | "The circuit depth before a commit for ancilla circuit: 387\n" 213 | ] 214 | } 215 | ], 216 | "source": [ 217 | "r1, *_ = grover(['10001111'], \"ancilla\")\n", 218 | "print('The circuit depth before a commit for ancilla circuit: ',r1.decompose().depth())" 219 | ] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "metadata": {}, 224 | "source": [ 225 | "* ***After committing: `ancilla` circuit*** (no barriers)" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": 17, 231 | "metadata": {}, 232 | "outputs": [ 233 | { 234 | "name": "stdout", 235 | "output_type": "stream", 236 | "text": [ 237 | "The circuit depth after a commit for ancilla circuit: 386\n" 238 | ] 239 | } 240 | ], 241 | "source": [ 242 | "r2, *_ = grover(['10001111'], \"ancilla\")\n", 243 | "print('The circuit depth after a commit for ancilla circuit: ',r2.decompose().depth())" 244 | ] 245 | }, 246 | { 247 | "cell_type": "markdown", 248 | "metadata": {}, 249 | "source": [ 250 | "There is a one-unit reduction in circuit depth which is not a big deal. But more interestingly is the case of `noancilla` circuit.\n", 251 | "* ***Before committing: `noancilla` circuit*** (with barriers)" 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": 18, 257 | "metadata": {}, 258 | "outputs": [ 259 | { 260 | "name": "stdout", 261 | "output_type": "stream", 262 | "text": [ 263 | "The circuit depth before a commit for noancilla circuit: 123\n" 264 | ] 265 | } 266 | ], 267 | "source": [ 268 | "w1, *_ = grover(['10001111'], \"noancilla\")\n", 269 | "print('The circuit depth before a commit for noancilla circuit: ',w1.decompose().depth())" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "* ***After doing a commit: `noancilla` circuit*** (no barriers)" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 19, 282 | "metadata": {}, 283 | "outputs": [ 284 | { 285 | "name": "stdout", 286 | "output_type": "stream", 287 | "text": [ 288 | "The circuit depth after a commit for noancilla circuit: 99\n" 289 | ] 290 | } 291 | ], 292 | "source": [ 293 | "w2, *_ = grover(['10001111'], \"noancilla\")\n", 294 | "print('The circuit depth after a commit for noancilla circuit: ',w2.decompose().depth())" 295 | ] 296 | }, 297 | { 298 | "cell_type": "markdown", 299 | "metadata": {}, 300 | "source": [ 301 | "**As we can easily remark that the noancilla circuit depth difference is now 24 units less than before. And there you go, we prevent errors by simply deleting barriers! :)**\n", 302 | "\n", 303 | "$\\Rightarrow$ **To sum up, in order to run our algorithm in the current NISQ devices we must reduce the depth as much as possible!**" 304 | ] 305 | }, 306 | { 307 | "cell_type": "markdown", 308 | "metadata": {}, 309 | "source": [ 310 | "

\n", 311 | "\tSource:\n", 312 | "

\n", 313 | "\n", 314 | "\n", 315 | "[1] [Preskill, J. (2015, July). Lecture Notes for Ph219/CS219: Quantum Information and Computation Chapter 5.](http://www.theory.caltech.edu/~preskill/ph219/chap5_13.pdf)\n", 316 | "\n", 317 | "[2] [Maslov, D., Dueck, G., Miller, D., & Negrevergne, C. (2008, February 27). Quantum Circuit Simplification and Level Compaction.](https://arxiv.org/abs/quant-ph/0604001)" 318 | ] 319 | } 320 | ], 321 | "metadata": { 322 | "kernelspec": { 323 | "display_name": "Python 3.6.9 64-bit", 324 | "language": "python", 325 | "name": "python36964bitb01e47b67c9742acbdc6a4069f1d02c9" 326 | }, 327 | "language_info": { 328 | "codemirror_mode": { 329 | "name": "ipython", 330 | "version": 3 331 | }, 332 | "file_extension": ".py", 333 | "mimetype": "text/x-python", 334 | "name": "python", 335 | "nbconvert_exporter": "python", 336 | "pygments_lexer": "ipython3", 337 | "version": "3.6.9" 338 | } 339 | }, 340 | "nbformat": 4, 341 | "nbformat_minor": 4 342 | } 343 | -------------------------------------------------------------------------------- /src/Different Designs Comparison/Results.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "import matplotlib.pyplot as plt\n", 11 | "from qiskit.transpiler import PassManager\n", 12 | "from qiskit.transpiler.passes import Unroller\n", 13 | "\n", 14 | "import sys, os\n", 15 | "sys.path.append(os.path.abspath(os.path.join('..', 'Grover')))\n", 16 | "\n", 17 | "from grover import *" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 3, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "error_probs = np.linspace(0,1)\n" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 6, 32 | "metadata": {}, 33 | "outputs": [ 34 | { 35 | "data": { 36 | "text/plain": [ 37 | "Text(0, 0.5, 'Success probability')" 38 | ] 39 | }, 40 | "execution_count": 6, 41 | "metadata": {}, 42 | "output_type": "execute_result" 43 | }, 44 | { 45 | "data": { 46 | "image/png": "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\n", 47 | "text/plain": [ 48 | "
" 49 | ] 50 | }, 51 | "metadata": { 52 | "needs_background": "light" 53 | }, 54 | "output_type": "display_data" 55 | } 56 | ], 57 | "source": [ 58 | "succes_prob = []\n", 59 | "for err in error_probs:\n", 60 | " test, noise_model, basis_gates = grover(['111'], 'noancilla',err)\n", 61 | " simulator = Aer.get_backend('qasm_simulator')\n", 62 | " count = execute(test,simulator,basis_gates=basis_gates,\n", 63 | " noise_model=noise_model).result().get_counts()\n", 64 | " \n", 65 | " succes_prob.append(count['111']/1024)\n", 66 | "\n", 67 | "plt.plot(error_probs, succes_prob)\n", 68 | "plt.xlabel('Single-gate error probability')\n", 69 | "plt.ylabel('Success probability')" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 7, 75 | "metadata": {}, 76 | "outputs": [ 77 | { 78 | "data": { 79 | "text/plain": [ 80 | "Text(0, 0.5, 'Success probability')" 81 | ] 82 | }, 83 | "execution_count": 7, 84 | "metadata": {}, 85 | "output_type": "execute_result" 86 | }, 87 | { 88 | "data": { 89 | "image/png": "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\n", 90 | "text/plain": [ 91 | "
" 92 | ] 93 | }, 94 | "metadata": { 95 | "needs_background": "light" 96 | }, 97 | "output_type": "display_data" 98 | } 99 | ], 100 | "source": [ 101 | "succes_prob = []\n", 102 | "for err in error_probs:\n", 103 | " test, noise_model, basis_gates = grover(['111'], 'ancilla',err)\n", 104 | " simulator = Aer.get_backend('qasm_simulator')\n", 105 | " count = execute(test,simulator,basis_gates=basis_gates,\n", 106 | " noise_model=noise_model).result().get_counts()\n", 107 | " \n", 108 | " succes_prob.append(count['111']/1024)\n", 109 | "\n", 110 | "plt.plot(error_probs, succes_prob)\n", 111 | "plt.xlabel('Single-gate error probability')\n", 112 | "plt.ylabel('Success probability')" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 8, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [ 121 | "elements = []\n", 122 | "for i in range(2,20):\n", 123 | " elements.append('1'*i)" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 9, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "pass_ = Unroller(['u3', 'cx'])\n", 133 | "pm = PassManager(pass_)\n", 134 | "ops_count = []\n", 135 | "for element in elements:\n", 136 | " test, noise_model, basis_gates = grover([element], 'ancilla')\n", 137 | " circuit = pm.run(test)\n", 138 | " ops_count.append(circuit.count_ops())\n" 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": 10, 144 | "metadata": {}, 145 | "outputs": [ 146 | { 147 | "data": { 148 | "text/plain": [ 149 | "[OrderedDict([('u3', 23), ('cx', 7), ('measure', 2)]),\n", 150 | " OrderedDict([('u3', 141), ('cx', 76), ('measure', 3)]),\n", 151 | " OrderedDict([('u3', 330), ('cx', 186), ('measure', 4)]),\n", 152 | " OrderedDict([('u3', 599), ('cx', 344), ('measure', 5)]),\n", 153 | " OrderedDict([('u3', 1136), ('cx', 660), ('measure', 6)]),\n", 154 | " OrderedDict([('u3', 1833), ('cx', 1072), ('measure', 7)]),\n", 155 | " OrderedDict([('u3', 3226), ('cx', 1896), ('measure', 8)]),\n", 156 | " OrderedDict([('u3', 5247), ('cx', 3094), ('measure', 9)]),\n", 157 | " OrderedDict([('u3', 8712), ('cx', 5150), ('measure', 10)]),\n", 158 | " OrderedDict([('u3', 13593), ('cx', 8050), ('measure', 11)]),\n", 159 | " OrderedDict([('u3', 21414), ('cx', 12700), ('measure', 12)]),\n", 160 | " OrderedDict([('u3', 33243), ('cx', 19738), ('measure', 13)]),\n", 161 | " OrderedDict([('u3', 50816), ('cx', 30200), ('measure', 14)]),\n", 162 | " OrderedDict([('u3', 77833), ('cx', 46292), ('measure', 15)]),\n", 163 | " OrderedDict([('u3', 118206), ('cx', 70350), ('measure', 16)]),\n", 164 | " OrderedDict([('u3', 178371), ('cx', 106216), ('measure', 17)]),\n", 165 | " OrderedDict([('u3', 268556), ('cx', 159996), ('measure', 18)]),\n", 166 | " OrderedDict([('u3', 402165), ('cx', 239696), ('measure', 19)])]" 167 | ] 168 | }, 169 | "execution_count": 10, 170 | "metadata": {}, 171 | "output_type": "execute_result" 172 | } 173 | ], 174 | "source": [ 175 | "ops_count" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 19, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "counts = []\n", 185 | "for i in range(len(ops_count)):\n", 186 | " counts.append(ops_count[i]['u3'] + ops_count[i]['cx'])" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 22, 192 | "metadata": {}, 193 | "outputs": [ 194 | { 195 | "data": { 196 | "text/plain": [ 197 | "Text(0, 0.5, 'number of u3 and cnot gates combined')" 198 | ] 199 | }, 200 | "execution_count": 22, 201 | "metadata": {}, 202 | "output_type": "execute_result" 203 | }, 204 | { 205 | "data": { 206 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZcAAAEGCAYAAACpXNjrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nO3dd5xV1b3//9dnZuhtaIJSBAR7QRwR61ejQTQF0+wRy5WbmERTbhJTrkaT/G7KjSaWaDSaoNcSo1GJQZEYjRgFHBAFJDgjSi9DG/rUz++PvQ5sxikbOGfOmZn38/HYj7P32mvv9eEwzIe999prmbsjIiKSTnnZDkBERFofJRcREUk7JRcREUk7JRcREUk7JRcREUm7gmwHkCv69OnjQ4YMyXYYIiItyuzZs9e5e9+65UouwZAhQyguLs52GCIiLYqZLamvXLfFREQk7ZRcREQk7ZRcREQk7ZRcREQk7ZRcREQk7ZRcREQk7ZRcREQk7ZRcRETaqA/WbeO2FxexdvPOtJ9byUVEpI16aeEa7vhHKVW16Z/XS8lFRKSNml6yjkP6dmFAYae0n1vJRUSkDdpZVcPMD9Zz+oiPDAuWFg2OLWZm32zsQHe/Lf3hiIhIc5i9ZCM7q2o5fUSfjJy/sYEru4XPw4ATgclh+1PArIxEIyIizeLVkjLa5RtjhvXOyPkbTC7ufguAmb0KjHL3LWH7R8DfMhKNiIg0i9dK1jFqcE+6dMjM4PhJnrn0Aypj25WhTEREWqB1WytYsHIzZxyamectkGw+l4eAWWb2dNi+AJiUsYhERCSj/lW6DoDThmfmeQskSC7u/lMzex44PRRd5e5vZSwiERHJqFffW0dh53YcPaBHxtpI2hW5M7DZ3X8DLDezoRmLSEREMsbdea20jFOH9yE/zzLWTpPJxcxuBr4LfC8UtQP+L8nJzazQzJ40s3+b2UIzO9nMepnZNDMrCZ89Q10zszvMrNTM3jGzUbHzTAj1S8xsQqz8BDObF465w8wslNfbhohIW1eyditrNldwRoa6IKckuXL5DPBpYBuAu69kdzflpvwGeMHdDweOAxYCNwIvufsI4KWwDXAeMCIsE4F7IEoUwM3AScBo4OZYsrgHuDZ23LhQ3lAbIiJt2qvvlQFwWoZenkxJklwq3d0BBzCzLklObGY9gDOABwDcvdLdNwHj2d0hYBJRBwFC+UMemQEUmtmBwLnANHff4O4bgWnAuLCvu7vPCPE9VOdc9bUhItKmTS9Zx7AMDfkSlyS5PGFmvyP6ZX8t8Hfg/gTHDQXKgD+Y2Vtm9vuQmPq5+6pQZzW7uzUPAJbFjl8eyhorX15POY20sQczm2hmxWZWXFZWluCPJCLSclVUR0O+nJHhqxZIkFzc/X+BJ4GniN7Wv8nd70xw7gJgFHCPux9PdFttj9tT8SuiTGmsDXe/z92L3L2ob9/Mf9kiItk0+8PMDvkSl+jVTHefRnQ7am8sB5a7+8yw/SRRclljZge6+6pwa2tt2L8CGBQ7fmAoWwGcWaf8lVA+sJ76NNKGiEib9WrJOgryjJMyNORLXJLeYp8Nva7KzWyzmW0xs81NHefuq4FlZnZYKDobeJdojLJUj68JwLNhfTJwReg1NgYoD7e2pgJjzaxneJA/Fpga9m02szGhl9gVdc5VXxsiIm3W9JIyRh3ck64ZGvIlLkkLvwA+5e4L9+H8XwMeMbP2wGLgKqKE9oSZXQMsAS4MdacA5wOlwPZQF3ffYGY/Bt4M9W519w1h/Trgj0An4PmwAPysgTZERNqk9WHIl/8ae2iztJckuazZx8SCu88FiurZdXY9dR34SgPneRB4sJ7yYuDoesrX19eGiEhb9VoY8iVT87fUlSS5FJvZn4BngIpUobv/JWNRiYhIWk0vyfyQL3FJkkt3ottUY2NlDii5iIi0AO7O9JIyTj0ks0O+xCUZuPKq5ghEREQyozQM+dIcXZBTGpvm+Dvu/gszu5N63hNx9+szGpmIiKTFqyVhiP1cSC5E44ABFDdHICIikhnTS8oY1rcLA3t2brY2G5vm+K/hcxKAmXWPNqPpjkVEJPdVVNcwY/F6Lioa1HTlNEryEmWRmc0D3gHmm9nbZnZC5kMTEZH9tXvIl+Yd4ipJb7EHgevcfTqAmZ0G/AE4NpOBiYjI/pteGg35MuaQzA/5EpdkVOSaVGIBcPfXgOrMhSQiIunSnEO+xDXWWyw1E+Q/w5D7jxH1GruIaOBIERHJYeu3VjB/xWa+9fHmGfIlrrFU9qs62zfH1jM6TL6IiOy/XUO+HNr8U4o01lvsrOYMRERE0uu1knX06NSOY5ppyJe4Jm/CmVkh0XD2Q+L19RKliEjuioZ8Wcdpw5tvyJe4JE94pgAzgHlAbWbDERGRdChdu5XVm3c265AvcUmSS0d3/2bGIxERkbTJxpAvcUm6Ij9sZtea2YFm1iu1ZDwyERHZZ6+VlDGsT/MO+RKX5MqlEvgl8AN29xJzYFimghIRkX0XDfmygQuLBmYthiTJ5VvAcHdfl+lgRERk/81espEdVTXNPuRLXJLbYqk57UVEpAWYXpKdIV/ikly5bAPmmtnL7DnNsboii4jkoNdK1jFqcPMP+RKXpOVnwiIiIjlu/dYK5q8s55vnNP+QL3FJpjmeZGbtgVSki9y9KrNhiYjIvvjX++txz86QL3FJ5nM5EygB7gZ+C7xnZmckObmZfWhm88xsrpkVh7JeZjbNzErCZ89QbmZ2h5mVmtk7sYEzMbMJoX6JmU2IlZ8Qzl8ajrXG2hARae2mv1eWtSFf4pI80P8VMNbd/5+7nwGcC9y+F22c5e4j3b0obN8IvOTuI4CXwjbAecCIsEwE7oEoURANmnkSMBq4OZYs7gGujR03rok2RERaLXfntdJ1nDq8d1aGfIlLklzaufui1Ia7vwe02482xwOTwvok4IJY+UMemQEUmtmBRMlsmrtvcPeNwDRgXNjX3d1nuLsDD9U5V31tiIi0Wu+XbWVV+c6sdkFOSZJcis3s92Z2ZljuB4oTnt+BF81stplNDGX93H1VWF8N9AvrA4BlsWOXh7LGypfXU95YG3sws4lmVmxmxWVlZQn/SCIiuenV98KQL8OzM+RLXJLeYl8GvgKkuh5PJ3r2ksRp7r7CzA4AppnZv+M73d3NLKNzwzTWhrvfB9wHUFRUpDlqRKRFmx6GfBnUKztDvsQluXIpAH7j7p91988CdwD5SU7u7ivC51rgaaJnJmvCLS3C59pQfQUwKHb4wFDWWPnAespppA0RkVYpNeRLtgaqrCtJcnkJ6BTb7gT8vamDzKyLmXVLrQNjgfnAZCDV42sC8GxYnwxcEXqNjQHKw62tqcBYM+sZHuSPBaaGfZvNbEzoJXZFnXPV14aISKs0Z8mmrA/5Epd0yP2tqQ1332pmSa65+gFPh97BBcCj7v6Cmb0JPGFm1wBLgAtD/SnA+ewebuaq0N4GM/sx8Gaod6u7bwjr1wF/JEp4z4cF4GcNtCEi0ipNLymLhnwZlhuD1ica/sXMRrn7HIjeLQF2NHWQuy8GjqunfD1wdj3lTvRsp75zPQg8WE95MXB00jZERFqr6WHIl24d96czb/okSS5fB/5sZisBA/oDF2U0KhERSWzDtkrmryznG1ke8iUuyfAvb5rZ4cBhoUjDv4iI5JB/la6LhnzJkYf5kOzKhZBM5mc4FhER2QfTS8ro3rGAYwcWZjuUXZL0FhMRkRzl7kwvWcdpI/pkfciXOCUXEZEW7P2ybawq38lpw3OjC3JKklGRTw3vqWBml5vZbWZ2cOZDExGRpkwviYauyqXnLZDsyuUeYLuZHQd8C3ifaJBIERHJsukl6xiaI0O+xCVJLtXhHZTxwF3ufjfQLbNhiYhIUyqra5mxeH3OXbVAst5iW8zse8AXgdPNLI/9G3JfRETSYM7SjWyvzJ0hX+KSXLlcBFQAV7v7aqIBIn+Z0ahERKRJ00vKyM+hIV/imkwuIaE8BXQIReuIRjgWEZEsioZ8KcyZIV/ikvQWuxZ4EvhdKBoAPJPJoEREpHEbt1Uyb0V5Tt4Sg2S3xb4CnApsBnD3EuCATAYlIiKN+9f7uTfkS1yS5FLh7pWpDTMrIJq+WEREsmT6e+tybsiXuCTJ5Z9m9n2gk5l9HPgz8NfMhiUiIg2Jhnwp49ThuTXkS1yS5HIjUAbMA/4TmOLuP8hoVCIi0qDStVtZWb4zZ5+3QLL3XL7m7r8B7k8VmNkNoUxERJrZk3OWk59nnH1E7j7+TnLlMqGesivTHIeIiCRQWV3Lk8XLOeeIA+jXvWO2w2lQg1cuZnYJcCkw1Mwmx3Z1AzbUf5SIiGTS1AWrWb+tkktPyu3xgxu7LfY6sAroA/wqVr4FeCeTQYmISP0embmEQb06cfrw3OyCnNJgcnH3JcAS4OTmC0dERBpSunYrMxZv4DvjDiMvR3uJpSR5Q3+Mmb1pZlvNrNLMasxsc3MEJyIiuz02aykFecYXThiU7VCalOSB/l3AJUAJ0An4D+DupA2YWb6ZvWVmz4XtoWY208xKzexPZtY+lHcI26Vh/5DYOb4XyheZ2bmx8nGhrNTMboyV19uGiEhLtbOqhqfmLOfco/vTt1uHpg/IskTTHLt7KZDv7jXu/gdg3F60cQOwMLb9c+B2dx8ObASuCeXXABtD+e2hHmZ2JHAxcFRo97chYeUTJbnzgCOBS0LdxtoQEWmRnp+/ik3bq7hs9OBsh5JIkuSyPfzPf66Z/cLMvpHwOMxsIPAJ4Pdh24CPEQ2ECTAJuCCsjw/bhP1nh/rjgcfdvcLdPwBKgdFhKXX3xWF4mseB8U20ISLSIj0yYylD+3Th5EN6ZzuURJIkiS8C+cBXgW3AIOBzCc//a+A7QG3Y7g1scvfqsL2caJRlwucygLC/PNTfVV7nmIbKG2tjD2Y20cyKzay4rKws4R9JRKR5vbdmC8VLNnLp6MFE/3/OfU2+oR96jQHsAG5JemIz+ySw1t1nm9mZ+xZeZrn7fcB9AEVFRRqMU0Ry0qMzl9I+P4/PnTAw26Ek1mRyMbN5fHQU5HKgGPiJu69v4NBTgU+b2flAR6A78Bug0MwKwpXFQGBFqL+C6KpoeRh5uQewPlaeEj+mvvL1jbQhItKi7KiMHuSfd0x/enVpOX2TktwWex74G3BZWP5KlFhWA39s6CB3/567D3T3IUQP5P/h7pcBLwOfD9UmAM+G9cnsHmrm86G+h/KLQ2+yocAIYBbwJjAi9AxrH9qYHI5pqA0RkRblr++sZMvOai7L8Tfy60oycOU57j4qtj3PzOa4+ygzu3wf2vwu8LiZ/QR4C3gglD8APGxmpUTDy1wM4O4LzOwJ4F2gGviKu9cAmNlXgalEz4QedPcFTbQhItKiPDJzKcMP6MqJQ3pmO5S9kiS55JvZaHefBWBmJxL9Mofol32T3P0V4JWwvpiop1fdOjuBLzRw/E+Bn9ZTPgWYUk95vW2IiLQkC1aW8/ayTdz8qSNbzIP8lCTJ5T+AB82sa9jeAlxjZl2A/8lYZCIibdyjM5fSoSCPzx7fch7kpyTpLfYmcIyZ9Qjb5bHdT2QqMBGRtmxrRTXPvLWCTx57ED06t8t2OHstyZUL8JGkIiIiGTR57kq2VdZw2ZiW8UZ+XYnetBcRkebj7jwycwmH9+/G8YMKsx3OPkkyKvJHRkirr0xERNLjneXlLFi5mcvGHNziHuSnJLlyeSNhmYiIpMGjM5fSuX0+F4w8KNuh7LPGpjnuTzQmVyczOx5Ipc/uQOdmiE1EpM3ZvLOKyW+vZPzIg+jWseU9yE9p7IH+ucCVRMOn3BYr3wJ8P4MxiYi0Wc+8tYIdVTUt7o38uhqb5ngSMMnMPufuTzVjTCIibZK78+jMpRwzoAfHDOyR7XD2S5JnLi+Z2W2poenN7Fepd15ERCR95izdyL9Xb+HSk1pm9+O4JMnlAaJbYReGZTPwh0wGJSLSFj0ycyldOxTw6eNa7oP8lCQvUR7i7vHJwW4xs7mZCkhEpC3atL2S595ZxYVFA+nSIfH77TkryZXLDjM7LbVhZqcSTRwmIiJp8tScFVRW13Lp6Jb9ID8lSXr8EvBQeM5iRMPhX5nJoERE2pLoQf4Sjh9cyJEHdc92OGmRZODKt4HjzKx72N6c8ahERNqQmR9s4P2ybfzy88dmO5S0STLNcQfgc8AQoCA1FIG735rRyERE2ohHZy6le8cCPnlsy3+Qn5LkttizQDkwG6jIbDgiIm3L+q0VPD9/FZeddDCd2uc3fUALkSS5DHT3cRmPRESkDXpy9nKqapzLWsG7LXFJeou9bmbHZDwSEZE2prbWeWzWUkYP6cWIft2yHU5aJblyOQ240sw+ILotZoC7e+t58iQikgWvv7+eD9dv5+vnHJrtUNIuSXI5L+NRiIi0QY/OWkLPzu0Yd3T/bIeSdkluix0IbHD3Je6+BNgINPlNmFlHM5tlZm+b2QIzuyWUDzWzmWZWamZ/MrP2obxD2C4N+4fEzvW9UL7IzM6NlY8LZaVmdmOsvN42RERyxdotO3lxwRo+f8JAOrZrPQ/yU5Ikl3uArbHtraGsKRXAx9z9OGAkMM7MxgA/B2539+FEieqaUP8aYGMovz3Uw8yOBC4GjgLGAb81s3wzywfuJrqyOhK4JNSlkTZERHLCn4uXU13rXDK6dT3IT0mSXMzdPbXh7rUke/nS3T2VlNqFxYGPAU+G8knABWF9fNgm7D/bopdqxgOPu3uFu38AlAKjw1Lq7ovdvRJ4HBgfjmmoDRGRrKsJD/JPOaQ3w/p2zXY4GZEkuSw2s+vNrF1YbgAWJzl5uMKYC6wFpgHvA5vcvTpUWU402yXhcxlA2F8O9I6X1zmmofLejbQhIpJ1r5aUsXzjjlYxtH5DkiSXLwGnACuIflGfBExMcnJ3r3H3kUSzWY4GDt/HODPCzCam5qkpKyvLdjgi0kY8OnMpfbq2Z+yRre9BfkqS21triZ557DN332RmLwMnA4VmVhCuLAYSJS3C5yBguZkVAD2A9bHylPgx9ZWvb6SNunHdB9wHUFRU5PXVERFJp1XlO/jHv9cy8YxhtC9I8v/7liljfzIz62tmhWG9E/BxYCHwMvD5UG0C0fAyAJPDNmH/P8KznsnAxaE32VBgBDALeBMYEXqGtSdKgJPDMQ21ISKSVX96cxk1tc4lJ7beW2KQ7D2XfXUgMCn06soDnnD358zsXeBxM/sJ8BbRTJeEz4fNrJRoWP+LAdx9gZk9AbwLVANfcfcaADP7KjAVyAcedPcF4VzfbaANEZGsqa6p5U9vLuOMQ/syuHfnbIeTURbrCNamFRUVeXFxcbbDEJFW7KE3PuSmZxdw/xVFfPzIftkOJy3MbLa7F9Utb/DKxcy+2dgJ3f22dAQmItIWlG2p4JdTF3HKIb0554gDsh1OxjV2Wyw1itphwIlEzz4APkX0zENERBL6n+cXsrOqhlvHH01qXqzWrMHk4u6p4VpeBUa5+5aw/SPgb80SnYhIKzDrgw38Zc4KvnzmIQw/oHW+NFlXkt5i/YDK2HZlKBMRkSZU1dTy38/MZ0BhJ772seHZDqfZJOkt9hAwy8yeDtsXsHuYFhERacSk1z9k0Zot3Hv5CXRun8kOurklyUuUPzWzF4jmdQG4yt3fymxYIiIt35rNO/n130s487C+nHtU27rhkzSNzgVWpeqb2WB3X5qxqEREWoGf/G0hlTW13PLpo9rEQ/y4JpOLmX0NuBlYA9QQZqIENBOliEgD/lW6jr++vZIbzh7Bwb27ZDucZpfkyuUG4DB3X5/pYEREWoPK6lpuenY+g3t15stnHpLtcLIiSXJZRjT8vYiIJPD71xbzftk2/nDlia1ylskkkiSXxcArZvY3otklAb2hLyJSnxWbdnDnS6WMPbIfZx3e+t/Eb0iS5LI0LO3DIiIiDbj1rwtwnJs+dWTTlVuxJF2Rb2mOQEREWrqXF61l6oI1fPvcwxjYs3WPetyUJL3F+gLfAY4COqbK3f1jGYxLRKRF2VlVw48mL2BY3y5ce/qwbIeTdUmGf3kE+DcwFLgF+JBooi4REQnu/ef7LFm/nR+PP7pVzzCZVJJvoLe7PwBUufs/3f1qQFctIiLBkvXb+O0r7/PJYw/k1OF9sh1OTkjyQL8qfK4ys08AK4FemQtJRKTlcHd+NHkB7fKMH36ibT/Ej0uSXH5iZj2AbwF3At2Bb2Q0KhGRFuLFd9fw8qIyfviJI+jfo2PTB7QRSXqLPRdWy4GzMhuOiEjLsb2ymlv/+i6H9evGhFOGZDucnNJ2xn8WEUmzu/5RyopNO3jiP0+mXb4e4sfp2xAR2Qela7dy//TFfHbUAEYP1WPoupRcRET2krtz8+T5dGyXz/fOOyLb4eSkBpOLRS40sy+E9bPN7A4zu87MmkxKZjbIzF42s3fNbIGZ3RDKe5nZNDMrCZ89Y+3dYWalZvaOmY2KnWtCqF9iZhNi5SeY2bxwzB0WJkxoqA0RkXR47p1V/Kt0Pd8+9zD6duuQ7XByUmNJ4m7gQuCLwMPAl4henjwDuD3BuauBb7n7kcAY4CtmdiRwI/CSu48AXgrbAOcBI8IyEbgHokRBNJ/MScBo4OZYsrgHuDZ23LhQ3lAbIiL7ZWtFNT/527scPaA7l510cLbDyVmNPdA/3d2PMbN2wGrgQHevNLPHgDlNndjdVxHNXom7bzGzhcAAYDxwZqg2CXgF+G4of8jdHZhhZoVmdmCoO83dNwCY2TRgnJm9AnR39xmh/CHgAuD5RtoQEdkvv572Hmu3VHDv5SeQn9e2ZpfcG41duVQDuHsV8Ka7V4btaqB2bxoxsyHA8cBMoF9IPBAlrdTE0gOI5o5JWR7KGitfXk85jbRRN66JZlZsZsVlZWV780cSkTbo36s384fXP+TiEwdx/GDdbW9MY8lltZl1BXD31O0mzKw/UJm0gXCOp4Cvu/vm+L5wleJ7FfFeaqwNd7/P3Yvcvahv376ZDENEWjh356ZnFtC9YwHfOffwbIeT8xpMLu5+nrtvrWfXFuCTSU4ebqk9BTzi7n8JxWvC7S7C59pQvgIYFDt8YChrrHxgPeWNtSEisk/+MmcFsz7cwHfHHU7PLpraqilJen2dEV+AE4Am03boufUAsLDOrJWTgVSPrwnAs7HyK0KvsTFAebi1NRUYa2Y9w4P8scDUsG+zmY0JbV1R51z1tSEistdWbtrB/zdlIccPLuTCokFNHyCJ3tD/dmy9I1GPrdk0PTLyqUQ9zeaZ2dxQ9n3gZ8ATZnYNsISoRxrAFOB8oBTYDlwF4O4bzOzH7B7m/9bUw33gOuCPQCeiB/nPh/KG2hAR2SubtldyxYOzqKyu5eefO5Y8PcRPxKJHEntxgNkg4Nfu/rnMhJQdRUVFXlxcnO0wRCSH7Kis4fIHZjJveTmTrh7NyYf0znZIOcfMZrt7Ud3yfRlbbDmgV1JFpFWrrqnla4/NYc7Sjdx96Sgllr2UZJrjO9nd2yoPGEmC91xERFoqd+cHT8/n7wvXcuv4ozj/mAOzHVKLk+TKJX6vqBp4zN3/laF4RESy7rZp7/Gn4mV89azhXHHykGyH0yIlmc9lUnMEIiKSCx5+40Pu/EcpFxUN4ltjD812OC2WRkUWEQmmzFvFTZMXcM4RB/DTzxxNGAtX9oGSi4gI8Mb76/n643M5flAhd14yigJN/rVfGhty/+HweUPzhSMi0vzeXbmZiQ8VM7h3Zx688kQ6tc/PdkgtXmOp+QQzOwi4Orwd3yu+NFeAIiKZtGzDdib8YRZdOhTw0NWjKeysoV3SobEH+vcSzYUyjOiN/PjNRw/lIiIt1vqtFUx4cBYVVTU8+eVTOKiwU7ZDajUaG7jyDnc/AnjQ3Ye5+9DYosQiIi3a9spqrp5UzIpNO3jgyhM5tF+3bIfUqiTpivxlMzsOOD0Uveru72Q2LBGRzKmqqeW6R+Ywb/km7r38BE4cojv96ZZkVOTrgUeAA8LyiJl9LdOBiYhkgrtz41PzeGVRGT/9zDGMPap/tkNqlZK8of8fwEnuvg3AzH4OvAHcmcnAREQy4ecvLOKpOcv5xjmHcsnowdkOp9VK0pHbgJrYdg17PtwXEWkRHnztA+795/tcdtJgrj97eLbDadWSXLn8AZhpZk+H7QuIJgETEWkxJr+9klufe5dxR/Xn1vF6+z7TkjzQv83MXgFOC0VXuftbGY1KRCSNXitZx7eemMvoob349cUjydeEXxmXaD4Xd5+DhtkXkRZo/opy/vPhYg7p25X7ryiiYzu9fd8cNHiOiLRaLy9ayxcfmElh5/ZMuno0PTq1y3ZIbca+zEQpIpLTqmpq+d+pi/jdq4s5vH837r38BPp175jtsNqURpOLmeUDf3f3s5opHhGR/bJsw3auf/wt3lq6icvHDOaHnzhSt8KyoNHk4u41ZlZrZj3cvby5ghIR2RcvzF/Fd558B3e4+9JRfOJYTU+cLUlui20F5pnZNGBbqtDdr89YVCIie2FnVQ3/M2Uhk95YwrEDe3DXJaMY3LtztsNq05I80P8L8N/Aq0SjI6eWRpnZg2a21szmx8p6mdk0MysJnz1DuZnZHWZWambvmNmo2DETQv0SM5sQKz/BzOaFY+6w0Gm9oTZEpHX6YN02PnfP60x6YwnXnDaUJ790ihJLDmgyubj7JOAJYIa7T0otCc79R2BcnbIbgZfcfQTRcP43hvLzgBFhmQjcA1GiAG4GTgJGAzfHksU9wLWx48Y10YaItDLPzl3BJ++YzopNO/j9FUX89yePpH2BOsHmgiQDV34KmAu8ELZHmtnkpo5z91eBDXWKxwOpxDSJ6G3/VPlDHpkBFJrZgcC5wDR33+DuG4FpwLiwr7u7z3B3Bx6qc6762hCRVmJHZQ3fffIdbnh8Lkcc2J0p15/OOUf2y3ZYEpPkmcuPiK4aXgFw97lmtq/zufRz91VhfTWQ+mkYACyL1VseyhorX15PeWNtfISZTSS6UmLwYA1gJ9ISvLdmC199dA4la7fylbMO4RvnHKr57nNQkuRS5e7ldcbhqd3fht3dzcz39zz704a73wfcB1BUVJTRWERk/+wFAUsAABFNSURBVLg7fy5ezk2T59O1QwGTrhrNGYf2zXZY0oAkyWWBmV0K5JvZCOB64PV9bG+NmR3o7qvCra21oXwFMChWb2AoWwGcWaf8lVA+sJ76jbUhIi3U1opqfvj0PJ6Zu5JTDunNry8ayQF6KTKnJbmW/BpwFFABPAZsBr6+j+1NBlI9viYAz8bKrwi9xsYA5eHW1lRgrJn1DA/yxwJTw77NZjYm9BK7os656mtDRFqg+SvK+dSdrzH57ZV88+OH8vA1JymxtABJRkXeDvwgTBLm7r4lyYnN7DGiq44+ZracqNfXz4AnzOwaYAlwYag+BTgfKAW2A1eFtjeY2Y+BN0O9W9091UngOqIeaZ2A58NCI22ISAvi7jw8Ywk/eW4hPbu047Frx3DSsN7ZDksSsqizVSMVzE4EHgS6haJy4Gp3b/Jdl5akqKjIi4uLsx2GiBBdrfzqxUW8vKiMMw/ry6++cBy9u3bIdlhSDzOb7e5FdcuTPHN5ALjO3aeHE51GNIHYsekNUUTauuIPN3DXy6W8sqiMbh0L+OEnjuDqU4eSp/lXWpwkyaUmlVgA3P01M6vOYEwi0oa4O/8qXc9dL5cwY/EGenVpz7fPPYwvnnww3TtqiPyWqsHkEhuC5Z9m9juih/kOXER450VEZF+5Oy8tXMtdL5cyd9km+nXvwH9/8kguGT2Izu01G0hL19jf4K/qbN8cW9c7ISKyT2pqnefnr+Kuf5Ty79VbGNizEz/9zNF8/oSBdCjQ0PitRYPJRXO4iEg6VdXU8uzclfz2lVIWl21jWN8u/OoLx/HpkQfRTm/YtzpNXnuaWSHReyRD4vU15L6IJLGzqoYnZy/n3n++z/KNOzjiwO7cfekoxh3dn3w9qG+1ktzYnALMAOaRhmFfRKRt2F5ZzaMzl3Lfq4tZu6WCkYMKueXTR/Gxww+gznBS0golSS4d3f2bGY9ERFqF8h1V/N+MJTzw2gds2FbJycN6c/tFIznlkN5KKm1IkuTysJldCzxHNAQMEL09n7GoRKRF2bitkmkL1/DC/NW8VrKOyppazjysL189azhFQ3plOzzJgiTJpRL4JfADdvcSc2Bfh90XkVagbEsFUxes5oX5q3lj8Xpqap0BhZ244uSDueD4ARw9oEe2Q5QsSpJcvgUMd/d1mQ5GRHLbqvIdvDB/Nc/PX82bH27AHYb26cLEM4Zx3tH9OWZAD936EiBZckkNJikibdDS9dt5fv4qnp+/mrnLNgFwWL9uXP+xEZx3TH8O69dNCUU+Ikly2QbMNbOX2fOZi7oii7RSpWu38sL8VUyZt5p3V20G4JgBPfj2uYdx3tH9Gda3a5YjlFyXJLk8ExYRaaV2VtWwYGU5/1xUxvPzV1OydisAowYX8oPzj2Dc0f0Z1KtzlqOUliTJfC6TmiMQEWketbXOB+u3MXfpJuYui5aFqzZTXevkGYwe2ovLxxzFuUf1p38PTcol+ybJG/ofUM9YYu6u3mIiLcD6rRW7ksjcZZt4e9kmNu+MBjbv2qGAYwf2YOIZwxg5qJATDu6peVMkLZLcFotPAtMR+AKgjusiOSh1e2vusvKQTDaybMMOAPIMDuvfnU8cexDHDypk5OBCDunbVUOwSEYkuS22vk7Rr81sNnBTZkISkaZUVteyctMOlmzYztIN23lv9ZY9bm8BHNijIyMHFXL5SQczclAhxwzsoaHspdkkuS02KraZR3Qlo59QkQxyd8p3VLFkfZQ8lm7YzrIN23dtryrfQW3sZnWX9vkcO7CQa8PtrZGDCunXXc9LJHuSJIn4vC7VwIfAhRmJRqQN2VlVw9rNFSzZsK3eBLJl554Tvvbp2p7BvTpz4pCeDO41gEG9OnNw7y4M7tWZA7p10FTAklOS3BbTvC4iCbk7G7dXUbalgrItFazdsjO2Hn2Wba1g7eadux6qp7TPz2Ngz04M7t2ZEw7uyeBenUMC6cygnp3p0kE3DKTlSHJbrAPwOT46n8utmQtLJPuqamrZVlHNlp3RsrWimq0VVWzZWc3mHVW7EkU8cazbWkFVzUcnau3YLo8DunXkgG4dGHFAV045pDd9u3agX/eOuxJIv+4d9XBdWo0k/xV6FigHZhN7Qz/Xmdk44DdAPvB7d/9ZlkOSDHF3qmqcHVU17KyqYUdlze71XWW17AjbW3dGSWLrzmq2VFSH7d0JZEvYv7Oq8emLzKB3lw707RYth/brFq137cAB3aPPvt06cED3jnRpn68hUqRNSZJcBrr7uIxHkkZmlg/cDXwcWA68aWaT3f3d7EbWvNydWodad2rd8V3ru/fVrYOza7umNlqqd33WUlsL1bW1e5TvWa92j/LqWqe6Jjq2qsaprqltsKyqpjaUR/uqa0JZ2FdRtTtB7KyTSGo/erHQqPw8o2uHArp2KKBbx+izT9f2DOnTZY+y1Hq03Y6uobx7xwJ6dWlPgabnFalXkuTyupkd4+7zMh5N+owGSt19MYCZPQ6MB9KeXL7/9DxmLl6/+y3T6Pcz7h4+U8XRL3eP/RKM19m1P7W9a9/uJFB3Xyph7GovrKfKc50ZtMvLoyDfKMgz2uWn1usv69gujz5d29OpfT4d20VLp9TSPp8OBXl0ar+7rGP7fDoW5Ncpy6Nbh3Z0bJenKwmRDEqSXE4Drgxv6lcABri7H5vRyPbPAGBZbHs5cFLdSmY2EZgIMHjw4H1rqLATh/fvDhZ9MeG8GNEvz7plUT0j9Xttd72oLFp2H5+3a932qJe3Rz3b1ZYZ5IcT5YXjU3V3r4fz1qkTP8aI/ndfkG/k5+VRkBcdX5Bn5Idf/Pl5Rr7tWSc/tqSOSSWIXYkkJAs9XxBpvZIkl/MyHkWWuPt9wH0ARUVF+/R//a+cNTytMYmItAZJuiIvaY5A0mwFMCi2PTCUiYhIM2itTyPfBEaY2VAzaw9cDEzOckwiIm1Gq3wry92rzeyrwFSirsgPuvuCLIclItJmtMrkAuDuU4Ap2Y5DRKQtaq23xUREJIuUXEREJO2UXEREJO2UXEREJO3MW8I4Ic3AzMqATL7T0wdYl8HzZ4JizryWFi8o5ubSUmI+2N371i1UcmkmZlbs7kXZjmNvKObMa2nxgmJuLi0x5jjdFhMRkbRTchERkbRTcmk+92U7gH2gmDOvpcULirm5tMSYd9EzFxERSTtduYiISNopuYiISNopuaSRmQ0ys5fN7F0zW2BmN9RT50wzKzezuWG5KRux1onpQzObF+Iprme/mdkdZlZqZu+Y2ahsxBliOSz23c01s81m9vU6dbL+HZvZg2a21szmx8p6mdk0MysJnz0bOHZCqFNiZhOyHPMvzezf4e/9aTMrbODYRn+GmjnmH5nZitjf//kNHDvOzBaFn+sbsxjvn2Kxfmhmcxs4Nivf8T6L5l7Xko4FOBAYFda7Ae8BR9apcybwXLZjrRPTh0CfRvafDzxPNJPyGGBmtmMOceUDq4le4sqp7xg4AxgFzI+V/QK4MazfCPy8nuN6AYvDZ8+w3jOLMY8FCsL6z+uLOcnPUDPH/CPgvxL87LwPDAPaA2/X/bfaXPHW2f8r4KZc+o73ddGVSxq5+yp3nxPWtwALgQHZjSotxgMPeWQGUGhmB2Y7KOBs4H3PwdlS3f1VYEOd4vHApLA+CbignkPPBaa5+wZ33whMA8ZlLNCY+mJ29xfdvTpsziCa1TVnNPA9JzEaKHX3xe5eCTxO9PeTUY3Fa2YGXAg8luk4moOSS4aY2RDgeGBmPbtPNrO3zex5MzuqWQOrnwMvmtlsM5tYz/4BwLLY9nJyI2leTMP/EHPtOwbo5+6rwvpqoF89dXL1uwa4mugKtj5N/Qw1t6+GW3kPNnD7MRe/59OBNe5e0sD+XPuOG6XkkgFm1hV4Cvi6u2+us3sO0W2c44A7gWeaO756nObuo4DzgK+Y2RnZDqgpYfrqTwN/rmd3Ln7He/DoPkeLeQ/AzH4AVAOPNFAll36G7gEOAUYCq4huNbUEl9D4VUsufcdNUnJJMzNrR5RYHnH3v9Td7+6b3X1rWJ8CtDOzPs0cZt2YVoTPtcDTRLcM4lYAg2LbA0NZNp0HzHH3NXV35OJ3HKxJ3U4Mn2vrqZNz37WZXQl8ErgsJMWPSPAz1GzcfY2717h7LXB/A7Hk1PdsZgXAZ4E/NVQnl77jJJRc0ijcM30AWOjutzVQp3+oh5mNJvo7WN98UX4kni5m1i21TvQAd36dapOBK0KvsTFAeez2TrY0+L+8XPuOYyYDqd5fE4Bn66kzFRhrZj3D7ZyxoSwrzGwc8B3g0+6+vYE6SX6Gmk2d54GfaSCWN4ERZjY0XAVfTPT3ky3nAP929+X17cy17ziRbPcoaE0LcBrRrY53gLlhOR/4EvClUOerwAKi3ikzgFOyHPOwEMvbIa4fhPJ4zAbcTdS7Zh5QlOWYuxAlix6xspz6jokS3yqgiuh+/jVAb+AloAT4O9Ar1C0Cfh879mqgNCxXZTnmUqJnE6mf53tD3YOAKY39DGUx5ofDz+k7RAnjwLoxh+3ziXp0vt9cMdcXbyj/Y+rnN1Y3J77jfV00/IuIiKSdbouJiEjaKbmIiEjaKbmIiEjaKbmIiEjaKbmIiEjaKblIq2NmWzNwzpHx0XXDyLv/tR/n+4KZLTSzl+uUH2RmT+5PrA20t0f8CeoXmtl1TdR5ff8jk9ZKyUUkmZFE70WkyzXAte5+VrzQ3Ve6++fT2E7K3sZfCNSbXMLb5Lj7KWmIS1opJRdp1czs22b2ZhjE8JZQNiRcNdxv0bw7L5pZp7DvxFB3bpjLZH54g/tW4KJQflE4/ZFm9oqZLTaz6xto/5IwB8d8M/t5KLuJ6IXbB8zsl3XqD0nN9WFmV5rZX8zsBYvmdvlFrN5WM7s9xP+SmfUN5a+YWVFY7xPmAGko/tS5jjKzWWHfO2Y2AvgZcEjsezjTzKab2WTg3VQM4fPM0O6TFs398khshITzQ9lsi+YEem7f/ialxcn2W5xatKR7AbaGz7HAfUQjDOQBzxHNpzGEaBDGkaHeE8DlYX0+cHJY/xlh3g3gSuCuWBs/Al4HOgB9iEYMaFcnjoOApUBfoAD4B3BB2PcK9Yx0EGKLt7kY6AF0BJYAg8I+JxrrC+CmVGzx84a4Pqwv/jpt3hk7V3ugUzyOUH4msA0YWs/3fCZQTjQ+Vx7wBlHy7Ej0dv/QUO8xcmwuIy2ZW3TlIq3Z2LC8RTRS8uHAiLDvA3dPzfg3Gxhi0SyL3dz9jVD+aBPn/5u7V7j7OqJBKOsOoX8i8Iq7l3k0J8ojRMltb7zk7uXuvpPoiuHgUF7L7kEO/4/ol/m+egP4vpl9l2g06R0N1Jvl7h80sm+5R4NFziVKTocDi2PHtIp5SiQZJRdpzQz4H3cfGZbh7v5A2FcRq1dDdGWxt9JxjnS1kRrHqZrd/647JmnA3R8lmr5gBzDFzD7WQNVtaYhT2gglF2nNpgJXWzS/DmY2wMwOaKiyu28CtpjZSaHo4tjuLURTV++NWcD/C88+8olGcv7nXp6jIXlA6sH/pcBrYf1D4ISwHu8Y0GD8ZjaM6ArjDqKRmo9trP5eWAQMs2jiPICLGq4qrY2Si7Ra7v4i0a2tN8xsHvAkTf/CvAa438zmEo2+XB7KXyZ6gP+RB+KNtL8KuDEc+zYw293rG2Z/X2wDRoeH/x8jemAP8L/Al83sLaJnLimNxX8hMD/8mY8mmtJ6PfCv0BHhl+yDcHvtOuAFM5tNlLDKGz9KWguNiiwSY2ZdPUw0ZmY3Eg3XfkOWw/oIM9vq7l2zHUdTUt9n6D12N1Di7rdnOy7JPF25iOzpE+F/9/OJ5jT/SbYDauGuDVdEC4h6vf0uy/FIM9GVi4iIpJ2uXEREJO2UXEREJO2UXEREJO2UXEREJO2UXEREJO3+f4SSicMEeZi3AAAAAElFTkSuQmCC\n", 207 | "text/plain": [ 208 | "
" 209 | ] 210 | }, 211 | "metadata": { 212 | "needs_background": "light" 213 | }, 214 | "output_type": "display_data" 215 | } 216 | ], 217 | "source": [ 218 | "plt.plot(range(2,20),counts)\n", 219 | "plt.xlabel('length of input string')\n", 220 | "plt.ylabel('number of u3 and cnot gates combined')" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": null, 226 | "metadata": {}, 227 | "outputs": [], 228 | "source": [ 229 | "pass_ = Unroller(['u3', 'cx'])\n", 230 | "pm = PassManager(pass_)\n", 231 | "ops_count_2 = []\n", 232 | "for element in elements:\n", 233 | " test, noise_model, basis_gates = grover([element], 'noancilla')\n", 234 | " circuit = pm.run(test)\n", 235 | " ops_count_2.append(circuit.count_ops())\n" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": null, 241 | "metadata": {}, 242 | "outputs": [], 243 | "source": [ 244 | "ops_count_2" 245 | ] 246 | } 247 | ], 248 | "metadata": { 249 | "kernelspec": { 250 | "display_name": "Python 3.6.9 64-bit", 251 | "language": "python", 252 | "name": "python36964bitb01e47b67c9742acbdc6a4069f1d02c9" 253 | }, 254 | "language_info": { 255 | "codemirror_mode": { 256 | "name": "ipython", 257 | "version": 3 258 | }, 259 | "file_extension": ".py", 260 | "mimetype": "text/x-python", 261 | "name": "python", 262 | "nbconvert_exporter": "python", 263 | "pygments_lexer": "ipython3", 264 | "version": "3.6.9" 265 | } 266 | }, 267 | "nbformat": 4, 268 | "nbformat_minor": 2 269 | } 270 | -------------------------------------------------------------------------------- /src/Different Designs Comparison/ancilla_success_prob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melsayed-7/Grover-s-Algorithm-QOSF/4f29158582c87ca0c0bf289eeddab52e90858360/src/Different Designs Comparison/ancilla_success_prob.png -------------------------------------------------------------------------------- /src/Different Designs Comparison/computations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melsayed-7/Grover-s-Algorithm-QOSF/4f29158582c87ca0c0bf289eeddab52e90858360/src/Different Designs Comparison/computations.png -------------------------------------------------------------------------------- /src/Different Designs Comparison/d2_d3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melsayed-7/Grover-s-Algorithm-QOSF/4f29158582c87ca0c0bf289eeddab52e90858360/src/Different Designs Comparison/d2_d3.png -------------------------------------------------------------------------------- /src/Different Designs Comparison/noancilla_success_prob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melsayed-7/Grover-s-Algorithm-QOSF/4f29158582c87ca0c0bf289eeddab52e90858360/src/Different Designs Comparison/noancilla_success_prob.png -------------------------------------------------------------------------------- /src/Grover/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melsayed-7/Grover-s-Algorithm-QOSF/4f29158582c87ca0c0bf289eeddab52e90858360/src/Grover/__init__.py -------------------------------------------------------------------------------- /src/Grover/diffuser.py: -------------------------------------------------------------------------------- 1 | from qiskit import * 2 | from qiskit.circuit.library.standard_gates import XGate 3 | 4 | 5 | def diffuser(list_values:list, circuit_type:str): 6 | n=len(list_values[0]) 7 | assert n>=2, 'Length of input should be greater or equal to 2.' 8 | 9 | if (circuit_type=='noancilla' or n==2): 10 | 11 | q1=QuantumRegister(n, "q") 12 | a1=QuantumCircuit(q1) 13 | 14 | a1.h(q1[[*range(n)]]) 15 | a1.x(q1[[*range(n)]]) 16 | a1.h(q1[n-1]) 17 | 18 | gate = XGate().control(n-1) 19 | a1.append(gate, q1) 20 | 21 | elif circuit_type=='ancilla': 22 | r = 0 23 | pn = r + 2 24 | jn = r 25 | kn= r+1 26 | q1=QuantumRegister(n*2, "q") 27 | a1=QuantumCircuit(q1) 28 | 29 | ######### Apply Hadamard and X gates. 30 | a1.h(q1[[*range(n)]]) 31 | a1.x(q1[[*range(n)]]) 32 | a1.h(q1[n-1]) # Apply Hadamrd gate on the left of the target qubit n. 33 | ######### 34 | 35 | a1.ccx(q1[r],q1[r+1],q1[r+n]) 36 | for i in range(n-3): 37 | a1.ccx(q1[pn],q1[n+jn],q1[n+kn]) 38 | if i=2, 'Length of input should be greater or equal to 2.' 14 | assert len(set(map(len, list_values))) == 1, 'The values on your list should have the same length.' 15 | assert len(set(list_values)) == len(list_values), 'You should not have a duplicate string value in your list.' 16 | 17 | if (circuit_type == 'noancilla' or n==2): 18 | q1=QuantumRegister(n+1, "q") 19 | a1=QuantumCircuit(q1) 20 | a1.append(oracle(list_values, circuit_type), [*range(n+1)]) # Add oracle. 21 | a1.append(diffuser(list_values, circuit_type), [*range(n)]) # Add diffuser. 22 | 23 | elif circuit_type =='ancilla': 24 | q1=QuantumRegister(n*2, "q") 25 | a1=QuantumCircuit(q1) 26 | a1.append(oracle(list_values, circuit_type), [*range(n*2)]) 27 | a1.append(diffuser(list_values, circuit_type), [*range(n*2)]) 28 | 29 | return a1 30 | 31 | 32 | 33 | ##################### GROVER'S CIRCUIT ##################### 34 | def grover(list_values:list, circuit_type: str, prob_1 = 0, prob_2 = 0): 35 | 36 | n = len(list_values[0]) 37 | N = len(list_values) 38 | assert n>=2, 'Length of input should be greater or equal to 2.' 39 | assert len(set(map(len, list_values))) == 1, 'The values on your list should have the same length.' 40 | assert len(set(list_values)) == len(list_values), 'You should not have a duplicate string value in your list.' 41 | 42 | number_iterations = int((math.pi/4)*math.sqrt(math.pow(2,n)/N)) 43 | 44 | circuit=initialize(list_values, circuit_type) 45 | 46 | ############### COMBINE: BALANCED STATE + ORACLE + DIFFUSER ############### 47 | # Iterate: (oracle+diffuser) + (oracle+diffuser) + ... . 48 | for i in range(number_iterations): 49 | circuit=circuit.combine(grover_unit(list_values, circuit_type)) 50 | 51 | circuit.measure([*range(n)],[*range(n)]) # Measure the n qubits. 52 | 53 | noise_model, basis_gates = noise(prob_1, prob_2) 54 | 55 | return circuit, noise_model, basis_gates 56 | 57 | -------------------------------------------------------------------------------- /src/Grover/oracle.py: -------------------------------------------------------------------------------- 1 | from qiskit import * 2 | from qiskit.circuit.library.standard_gates import XGate 3 | 4 | 5 | def oracle(list_values:list, circuit_type:str): 6 | n=len(list_values[0]) # Number of elements in one string. 7 | assert n>=2, 'Length of input should be greater or equal to 2.' 8 | assert len(set(map(len, list_values))) == 1, 'The values on your list should have the same length.' 9 | 10 | if (circuit_type == 'noancilla' or n==2): 11 | q1=QuantumRegister(n+1, "q") 12 | a1=QuantumCircuit(q1) 13 | ##a1.barrier() 14 | for element in list_values: 15 | ############ If an element in string equal 0 then apply X Gate on the left of the control dot. 16 | for i in range(n): 17 | if element[::-1][i] == '0': 18 | a1.x(q1[i]) 19 | ############ 20 | # Apply n-1 qubits control Toffoli gate. 21 | gate = XGate().control(n) 22 | a1.append(gate, q1) 23 | ############ If an element in string equal 0 then apply X Gate on the right of the control dot. 24 | for i in range(n): 25 | if element[::-1][i] == '0': 26 | a1.x(q1[i]) 27 | ############ 28 | ##a1.barrier() 29 | 30 | elif circuit_type=='ancilla': 31 | r = 0 32 | pn = r + 2 33 | jn = r 34 | kn= r+1 35 | 36 | q1=QuantumRegister(n*2, "q") 37 | a1=QuantumCircuit(q1) 38 | ##a1.barrier() 39 | 40 | for element in list_values: 41 | ############ 42 | for i in range(n): 43 | if element[::-1][i] == '0': 44 | a1.x(q1[i]) 45 | 46 | ############ 47 | # Apply n-1 qubits control Toffoli gate using 2-qubits control Toffoli gates. 48 | a1.ccx(q1[r],q1[r+1],q1[r+n]) 49 | for i in range(n-2): 50 | a1.ccx(q1[pn],q1[n+jn],q1[n+kn]) 51 | if i=2, 'Length of input should be greater or equal to 2.' 13 | assert len(set(map(len, list_values))) == 1, 'The values on your list should have the same length.' 14 | 15 | if (circuit_type == 'noancilla' or n==2): 16 | q1=QuantumRegister(n, "q") 17 | a1=QuantumCircuit(q1) 18 | #a1.barrier() 19 | for element in list_values: 20 | ############ If an element in string equal 0 then apply X Gate on the left of the control dot. 21 | for i in range(n): 22 | if element[::-1][i] == '0': 23 | a1.x(q1[i]) 24 | ############ 25 | # Apply n-1 qubits control Toffoli gate. 26 | gate = ZGate().control(n-1) 27 | a1.append(gate, q1) 28 | ############ If an element in string equal 0 then apply X Gate on the right of the control dot. 29 | for i in range(n): 30 | if element[::-1][i] == '0': 31 | a1.x(q1[i]) 32 | ############ 33 | #a1.barrier() 34 | 35 | elif circuit_type=='ancilla': 36 | if n==3: 37 | q1=QuantumRegister(4, "q") 38 | a1=QuantumCircuit(q1) 39 | for element in list_values: 40 | ############ 41 | for i in range(n): 42 | if element[::-1][i] == '0': 43 | a1.x(q1[i]) 44 | ############ 45 | a1.ccx(0,1,3) 46 | a1.cz(3,2) 47 | a1.ccx(0,1,3) 48 | ############ 49 | for i in range(n): 50 | if element[::-1][i] == '0': 51 | a1.x(q1[i]) 52 | ############ 53 | else: 54 | pn,jn,kn=2,0,1 55 | q1=QuantumRegister(n+(n-3), "q") 56 | a1=QuantumCircuit(q1) 57 | #a1.barrier() 58 | for element in list_values: 59 | ############ 60 | for i in range(n): 61 | if element[::-1][i] == '0': 62 | a1.x(q1[i]) 63 | ############ 64 | # Apply n-1 qubits control Toffoli gate using 2-qubits control Toffoli gates. 65 | a1.ccx(q1[0],q1[1],q1[n]) 66 | for i in range(n-4): 67 | a1.ccx(q1[pn],q1[n+jn],q1[n+kn]) 68 | if i=2, 'Length of input should be greater or equal to 2.' 97 | 98 | if (circuit_type=='noancilla' or n==2): 99 | q1=QuantumRegister(n, "q") 100 | a1=QuantumCircuit(q1) 101 | a1.rx(np.pi/2, q1[[*range(n)]]) 102 | a1=a1.combine(phase_oracle(['1'*n], 'noancilla')) 103 | a1.rx(-np.pi/2, q1[[*range(n)]]) 104 | 105 | elif circuit_type=='ancilla': 106 | if n==3: 107 | q1=QuantumRegister(4, "q") 108 | a1=QuantumCircuit(q1) 109 | a1.rx(np.pi/2, q1[[*range(n)]]) 110 | a1=a1.combine(phase_oracle(['1'*n], 'ancilla')) 111 | a1.rx(-np.pi/2, q1[[*range(n)]]) 112 | 113 | else: 114 | 115 | q1=QuantumRegister(n+(n-3), "q") 116 | a1=QuantumCircuit(q1) 117 | a1.rx(np.pi/2, q1[[*range(n)]]) 118 | a1=a1.combine(phase_oracle(['1'*n], 'ancilla')) 119 | a1.rx(-np.pi/2, q1[[*range(n)]]) 120 | return a1 121 | ############################# AA= ORACLE + DIFFUSER CIRCUIT ############################# 122 | def phase_amplitude_amplification(list_values:list, circuit_type:str): 123 | n=len(list_values[0]) 124 | assert n>=2, 'Length of input should be greater or equal to 2.' 125 | assert len(set(map(len, list_values))) == 1, 'The values on your list should have the same length.' 126 | assert len(set(list_values)) == len(list_values), 'You should not have a duplicate string value in your list.' 127 | 128 | if (circuit_type == 'noancilla' or n==2): 129 | a1=phase_oracle(list_values, circuit_type) # Add oracle. 130 | a1=a1.combine(phase_diffuser(list_values, circuit_type)) # Add diffuser. 131 | elif circuit_type =='ancilla': 132 | if n==3: 133 | a1=phase_oracle(list_values, circuit_type) 134 | a1=a1.combine(phase_diffuser(list_values, circuit_type)) 135 | else: 136 | a1=phase_oracle(list_values, circuit_type) 137 | a1=a1.combine(phase_diffuser(list_values, circuit_type)) 138 | return a1 139 | ##################### PREPARE THE CIRCUIT WITH BALANCED STATE ##################### 140 | def preparation(list_values:list, circuit_type:str): 141 | import numpy as np 142 | n=len(list_values[0]) 143 | 144 | if (circuit_type == 'noancilla' or n==2): 145 | q=QuantumRegister(n, "q") 146 | c=ClassicalRegister(n, "c") 147 | a=QuantumCircuit(q,c) 148 | a.rx(np.pi/2 ,q[[*range(n)]]) 149 | 150 | elif circuit_type =='ancilla': 151 | if n==3: 152 | q=QuantumRegister(4, "q") 153 | else: 154 | q=QuantumRegister(n+(n-3), "q") 155 | c=ClassicalRegister(n, "c") 156 | a=QuantumCircuit(q,c) 157 | a.rx(np.pi/2 ,q[[*range(n)]]) 158 | 159 | return a 160 | ##################### GROVER'S CIRCUIT ##################### 161 | def phase_grover(list_values:list, circuit_type: str, number_iterations: int): 162 | n=len(list_values[0]) 163 | assert n>=2, 'Length of input should be greater or equal to 2.' 164 | assert len(set(map(len, list_values))) == 1, 'The values on your list should have the same length.' 165 | assert len(set(list_values)) == len(list_values), 'You should not have a duplicate string value in your list.' 166 | 167 | circuit=preparation(list_values, circuit_type) 168 | 169 | ############### COMBINE: BALANCED STATE + ORACLE + DIFFUSER ############### 170 | # Iterate: (oracle+diffuser) + (oracle+diffuser) + ... . 171 | for i in range(number_iterations): 172 | circuit=circuit.combine(phase_amplitude_amplification(list_values, circuit_type)) 173 | 174 | circuit.measure([*range(n)],[*range(n)]) # Measure the n qubits. 175 | 176 | return circuit 177 | 178 | --------------------------------------------------------------------------------