├── .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 | 
36 |
37 | * Success probability of the noancilla design (length of string = 3)
38 | 
39 |
40 | * length of input string VS Number of computations (u3 + cx gates) used
41 | 
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 | "\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": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEGCAYAAABo25JHAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nO3dd3wc9Z3/8ddHXZZVbMtFrnLFNhgwGAdIoTmEFkgjQCCBOxLuUriUC4+Qg0tCOsmR5JIjAX4ppNAJJE7ooZcYkA3YuFdckLHcZNlW1+f3x4zktawytrS7lub9fDz80M7s7Mxn1tJ+9tvN3RERkfjKSHcAIiKSXkoEIiIxp0QgIhJzSgQiIjGnRCAiEnNZ6Q7gYJWWlnp5eXm6wxAR6VPmz5+/1d2HdvRcn0sE5eXlVFRUpDsMEZE+xcze6uw5VQ2JiMScEoGISMwpEYiIxJwSgYhIzCkRiIjEnBKBiEjMKRGIiMRcbBLBq+u286NHl9HSomm3RUQSxSYRvLFhJ798ZjW7G5rSHYqIyGElNomgMC8YRF1Tp0QgIpIoRokgG4BdtY1pjkRE5PASm0RQFCYClQhERPYXm0Swr2pIJQIRkUQxTAQqEYiIJIpNIijKD9sIVCIQEdlPbBKBSgQiIh2LTSLIzcokJytDJQIRkXZikwgg6Dm0q1YlAhGRRDFLBFnqNSQi0k6sEkFhXpbaCERE2olVIijKz1YbgYhIO7FKBCoRiIgcKF6JIDdbbQQiIu3EKxHkZanXkIhIO7FKBEX52dQ2NtPY3JLuUEREDhuxSgSto4t3q51ARKRNzBKB5hsSEWkvVomgSPMNiYgcIFaJQCUCEZEDxSwRqEQgItJerBJBcb7WLRYRaS9WiUAlAhGRA8UqEQzMVSIQEWkvVokgKzODgpxMNRaLiCSIVSKAoOeQ5hsSEdknholAM5CKiCSKZSJQ1ZCIyD6xSwRF+dkqEYiIJIhdIgjaCJQIRERaJTURmNlZZrbczFaZ2bUdPD/WzJ42s9fMbKGZnZPMeKB1TQJVDYmItEpaIjCzTOBm4GxgOnCJmU1vd9j1wL3uPhO4GPhlsuJpVaQSgYjIfpJZIpgNrHL3Ne7eANwNXNDuGAeKwsfFwNtJjAcISgQNzS3UNTYn+1IiIn1CMhPBKGBDwvbGcF+ibwGXmdlG4GHg6o5OZGZXmVmFmVVUVVX1KKjWqajVc0hEJJDuxuJLgNvdfTRwDvBHMzsgJne/zd1nufusoUOH9uiCReHEc6oeEhEJJDMRbALGJGyPDvcluhK4F8Dd/wnkAaVJjEkTz4mItJPMRPAqMNnMxptZDkFj8Nx2x6wHzgAws2kEiaBndT/daF2cRtNMiIgEkpYI3L0J+ALwGLCUoHfQYjP7tpmdHx72n8BnzOwN4C7gCnf3ZMUE+0oEu2pVIhARAchK5snd/WGCRuDEfd9IeLwEeHcyY2ivSCUCEZH9pLuxOOXURiAisr/YJYKCnCzM1H1URKRV7BJBRoZRmKupqEVEWsUuEUDQc0glAhGRQEwTQZZ6DYmIhGKZCII1CVQiEBGBuCYCLVcpItImlolAbQQiIvvEMhGoRCAisk8sE0GwXGUjSZ7NQkSkT4hpIsiixWFPgxanERGJaSLQfEMiIq26TQRm9sGOFovpy4ryNd+QiEirKB/wFwErzexHZjY12QGlgkoEIiL7dJsI3P0yYCawGrjdzP4ZriFcmPTokkRrEoiI7BOpysfddwH3A3cDZcCHgQVm1uFi84e71jUJNJZARCRaG8EFZvYg8AyQDcx297OBYwhWGOtzirQmgYhImygrlH0E+Km7P5e40933mtmVyQkruQpVIhARaROlamhz+yRgZjcCuPuTSYkqyfKyM8jONJUIRESIlgje38G+s3s7kFQys7bRxSIicddp1ZCZfRb4HDDRzBYmPFUIvJjswJJNaxKIiAS6aiO4E3gE+AFwbcL+GnffntSoUqBIJQIREaDrRODuvs7MPt/+CTMb3NeTQaFmIBURAbovEZwHzAccsITnHJiQxLiSrjAvi7Vb96Q7DBGRtOs0Ebj7eeHP8akLJ3WCxmKVCEREumosPq6rF7r7gt4PJ3WKlAhERICuq4Zu6uI5B07v5VhSqjAvi931TTS3OJkZ1v0LRET6qa6qhk5LZSCp1jrx3O66JooHZKc5GhGR9Omqauh0d3/KzD7S0fPu/kDywkq+ovx900woEYhInHVVNXQK8BTwwQ6ec6BvJwJNPCciAnRdNfTN8Oe/pC6c1NHEcyIigSjTUA8xs5+b2QIzm29m/2tmQ1IRXDIVta1SphKBiMRblEnn7gaqgI8CHwsf35PMoFKhsK1qSCUCEYm3KOsRlLn7dxK2v2tmFyUroFTZt1ylEoGIxFuUEsHjZnaxmWWE/z4OPJbswJKtUFVDIiJA191Ha9g3x9CXgD+FT2UAu4GvJj26JMrJyiAvO4OaeiUCEYm3rnoNFaYykHQozMtW1ZCIxF6UNgLMbBAwGchr3dd++cq+SFNRi4hE6z76aeA5gnaBG8Kf34pycjM7y8yWm9kqM7u2k2M+bmZLzGyxmd0ZPfSeK8rL1jgCEYm9KI3FXwROAN4K5x+aCezs7kVmlgncTLC+8XTgEjOb3u6YycDXgXe7+5EEbREpU5iXxS6VCEQk5qIkgjp3rwMws1x3XwYcEeF1s4FV7r7G3RsIxiNc0O6YzwA3u/sOAHffEj30ntNylSIi0RLBRjMrAf4CPGFmfwXeivC6UcCGxPOE+xJNAaaY2YtmNs/MzuroRGZ2lZlVmFlFVVVVhEtHU5SvNgIRkW4bi939w+HDb5nZ00Ax8GgvXn8ycCowGnjOzGa4+35VT+5+G3AbwKxZs7yXrq1eQyIiRO81dBzwHoJxBS+GVT3d2QSMSdgeHe5LtBF42d0bgbVmtoIgMbwaJa6eKszNor6phYamFnKyohSORET6nyi9hr4B/B4YApQCvzOz6yOc+1VgspmNN7Mc4GJgbrtj/kJQGsDMSgmqitZEjr6HWtckUDuBiMRZlBLBpcAxCQ3GPwReB77b1YvcvcnMvkDQ3TQT+K27LzazbwMV7j43fO5MM1sCNAPXuPu2Q7+dg1OYsCbBkIG5qbqsiMhhJUoieJtgIFlduJ3LgVU8HXL3h4GH2+37RsJjB74S/ks5rUkgItL1XEO/IGgTqAYWm9kT4fb7gVdSE15yFWqVMhGRLksEFeHP+cCDCfufSVo0KbZvcRqVCEQkvrqadO73rY/Dxt4p4ebysJdPn7dvTQKVCEQkvrptIzCzUwl6Da0jmJJ6jJld3h8mnStSG4GISKTG4puAM919OYCZTQHuAo5PZmCpMFBtBCIikaaYyG5NAgDuvgLITl5IqZOZYQzMzVKJQERiLUqJoMLMfs2+FcouZV9Dcp+nNQlEJO6iJILPAp8H/iPcfh74ZdIiSjHNQCoicddlIgjXFPitu18K/CQ1IaVWYV6Weg2JSKx12Ubg7s3AuLD7aL9UmJdFTb1KBCISX1GqhtYAL5rZXGBP60537xclhKL8bNZs3dP9gSIi/VSURLA6/JcBFCY3nNQLqoZUIhCR+IqyMM0NAGZWFGx6TdKjSqHCvGxq6ppwd8ws3eGIiKRclPUIZpnZImAhsMjM3jCzPj+YrFVhXhZNLU5dY0u6QxERSYsoA8p+C3zO3cvdvZygK+nvkhpVCmniORGJuyiJoNndn2/dcPcXgH7T37Jt4jklAhGJqSiNxc+a2a0E8ws5cBHwTLiOMe6+IInxJd2+ief6TW4TETkoURLBMeHPb7bbP5MgMZzeqxGl2KCCYIjEtt0NaY5ERCQ9ovQaOi0VgaTLyJI8AN7eWZvmSERE0iNKG0G/VlqQS05WhhKBiMRW7BNBRoYxsjiPTUoEIhJTsU8EACNL8lUiEJHYijKg7EIzKwwfX29mD7T2GOovgkRQl+4wRETSIkqJ4L/dvcbM3gPMAX4D/Cq5YaXWyJJ83qmpo7FZo4tFJH4iDSgLf54L3ObuDwH9alrqUSV5uMPmapUKRCR+oiSCTeGAsouAh80sN+Lr+oyRJfmAupCKSDxF+UD/OPAY8AF33wkMBq5JalQp1pYIqpUIRCR+oowsLgMecvd6MzsVOBr4Q1KjSrGRxa0lAlUNiUj8RCkR/BloNrNJwG3AGODOpEaVYvk5mQwuyNFYAhGJpSiJoMXdm4CPAL9w92sISgn9ysiSPLURiEgsRUkEjWZ2CfAp4O/hvuzkhZQeI4s1qExE4ilKIvgX4CTge+6+1szGA39MblipN2pQPpt21OLu6Q5FRCSluk0E7r4E+BqwINxe6+43JjuwVBtVks+ehmZ21WpdAhGJlyhTTHwQeB14NNw+1szmJjuwVGvtQqoGYxGJmyhVQ98CZgM7Adz9dWBCEmNKCw0qE5G4itRY7O7V7fb1u0l52hao0aAyEYmZKAPKFpvZJ4BMM5sM/AfwUnLDSr3SglxyMjNUNSQisROlRHA1cCRQTzCQrBr4UjKDSoeMDKOsJE+ji0UkdqL0Gtrr7te5+wnhv+vdPdKnpZmdZWbLzWyVmV3bxXEfNTM3s1kHE3xv01gCEYmjKL2GnjCzkoTtQWb2WITXZQI3A2cD04FLzGx6B8cVAl8EXj6YwJNBK5WJSBxFqRoqDWcdBcDddwDDIrxuNrDK3de4ewNwN3BBB8d9B7gRSHudzKiSPN7ZpQVqRCReIs01ZGZjWzfMbBwQZfjtKGBDwvbGcF+bcMnLMeFiN50ys6vMrMLMKqqqqiJc+tCMLMmnxeGdXWnPSSIiKROl19B1wAtm9ixgwHuBq3p6YTPLAH4CXNHdse5+G8HMp8yaNStpc0DsG0tQx+hBA5J1GRGRw0q3icDdHw2/uZ8Y7vqSu2+NcO5NBFNWtxod7mtVCBwFPGNmACOAuWZ2vrtXRAm+t40apEFlIhI/URqLP0wwqOzv7v53oMnMPhTh3K8Ck81svJnlABcDbVNTuHu1u5e6e7m7lwPzgLQlAdi3QI3GEohInERpI/hm4sjisOH4m929KFzD4AsEy1wuBe5198Vm9m0zO/9QA06m1gVqVCIQkTiJ0kbQUbKI8jrc/WHg4Xb7vtHJsadGOWeyaYEaEYmbKCWCCjP7iZlNDP/9BJif7MDSZWRxvqqGRCRWok4x0QDcE/6rBz6fzKDSaWSJFqgRkXiJ0mtoD9Dp9BD9TdsCNXVNFOf3uxU5RUQO0G0iMLOn6WAAmbufnpSI0ixxXQIlAhGJgyiNvl9NeJwHfBTot+s5tq1LsLOWaWVFaY5GRCT5olQNtW8YftHMXklSPGk3SiuViUjMRKkaGpywmQEcDxQnLaI0Kx2YS3amsUnrEohITESpGppP0EZgBFVCa4ErkxlUOmVkGGVal0BEYiRK1dD4VARyOBmldQlEJEY6HUdgZieY2YiE7U+Z2V/N7Oftqov6HS1QIyJx0tWAslsJBpJhZu8Dfgj8gWDN4tuSH1r6jCrJY/OuOpq0QI2IxEBXiSDT3beHjy8CbnP3P7v7fwOTkh9a+rQtUFNTn+5QRESSrstEYGatbQhnAE8lPBdp0rm+aqS6kIpIjHT1gX4X8KyZbQVqgecBzGwSQfVQv6VEICJx0mkicPfvmdmTQBnwuO+bhS2DYCK6fqt1dPHGHUoEItL/dVnF4+7zOti3InnhHB4G5GQxaEC2SgQiEgtRpqGOJXUhFZG4UCLoRJAINM2EiPR/SgSd0OhiEYkLJYJOjCzJo6a+iV11jekORUQkqZQIOjGqZACgLqQi0v8pEXQicYEaEZH+TImgE60L1GzSWAIR6eeUCDpROjCX0oE5vLpuR7pDERFJKiWCTmRkGKdPHcbTy7fQqFlIRaQfUyLowpxpw6mpa+LVtdu7P1hEpI9SIujCeyaXkpOVwRNL30l3KCIiSaNE0IUBOVm8Z1Ip/1j6Dvvm3BMR6V+UCLoxZ9pwNmyvZeWW3ekORUQkKZQIunHGtGEAPLFE1UMi0j8pEXRjeFEeR48u5h9qJxCRfkqJIII504bz+oadVGkNYxHph5QIIpgzbTju8PSyLekORUSk1ykRRDCtrJCRxXnqRioi/ZISQQRmxpzpw3l+ZRV1jc3pDkdEpFcpEUQ0Z9pw6hpbeGn11nSHIiLSq5QIInrXhMEMzM3iiSVqJxCR/kWJIKLcrEzeN6WUJ5e+Q0uLRhmLSP+R1ERgZmeZ2XIzW2Vm13bw/FfMbImZLTSzJ81sXDLj6ak504azpaaeRZuq0x2KiEivSVoiMLNM4GbgbGA6cImZTW932GvALHc/Grgf+FGy4ukNpx0xjAyDJ9V7SET6kWSWCGYDq9x9jbs3AHcDFyQe4O5Pu/vecHMeMDqJ8fTYoIIcZpUP5omlaicQkf4jmYlgFLAhYXtjuK8zVwKPdPSEmV1lZhVmVlFVVdWLIR68OdOGsbRyFxt37O3+YBGRPuCwaCw2s8uAWcCPO3re3W9z91nuPmvo0KGpDa6dOdOGA/CkSgUi0k8kMxFsAsYkbI8O9+3HzOYA1wHnu/thP5nPhKEDmTRsIHe9sp5m9R4SkX4gmYngVWCymY03sxzgYmBu4gFmNhO4lSAJ9Jmv2F+eM4Vlm2u485X16Q5FRKTHkpYI3L0J+ALwGLAUuNfdF5vZt83s/PCwHwMDgfvM7HUzm9vJ6Q4r58wYwYkTBnPT48vZsach3eGIiPSI9bUlGGfNmuUVFRXpDoNlm3dx7s9f4JLZY/juh2akOxwRkS6Z2Xx3n9XRc4dFY3FfNHVEEZ88cRx3vryexW9rgJmI9F1KBD3w5TlTKM7P5oa5S7S4vYj0WUoEPVA8IJtrPjCVV9ZtZ+4bb6c7HBGRQ6JE0EMXnTCGo0YV8YOHl7Gnvind4YiIHDQlgh7KzDBuOP9INu+q4+anV6U7HBGRg6ZE0AuOHzeYj8wcxa+fX8u6rXvSHc5ho6m5he3qXity2FMi6CVfO3sq2ZnGfz24iL0Nh38V0UurtnLqj5/mpseXU9/UO8tvtrQ4Syt38ZsX1vLp37/KzG8/wXHfeYJbn13dK+fvqZYW5/75Gzn9pmf42T9WqIFfJKRxBL3o7lfW8/UHFzFlWCG3fPJ4xpcWpDukDt3z6nque/BNivOz2bangSOGF/I/Fx7DjNHFkV6/p76JyupaKqvrqNxZR2V1HSu21DBv9Ta2hSWA8iEDOHlSKVt21fOPpe/w9bOn8m+nTEzmbXXpxVVb+d5DS1lSuYsRRXls3lXHJ08cxw3nH0lGhqUtrrhYtaUGM2Pi0IHpDiW2uhpHkJXqYPqzi2ePpawkny/e/Rrn/+IF/ufjx/CBI0ekO6w2LS3Ojx5bzi3Prua9k0u5+dLjqFi3na8/sIgP/fJFPnvKRK4+YxK5WZn7va6qpp5HF2/mkUWVLNpUTU3dgSWeUSX5nHLEUE6eWMpJE4cwqiQfCKqHvnTP6/zgkWUAKU8GK96p4QcPL+Xp5VWMKsnn55fM5LwZZdz42DJufXYNO2sbuenCY8jJSn7h+M1N1Xz/4aUU5GZx3tFlnDFtOANz+96fYFVNPS+v3cZ7Jw2leEB2l8dW1zZy46PLuPPlYDqWd40fzKUnjuMDRw4/4PdM0kclgiTYuGMvn7tjAQs3VvPvp0zkq2dOISvz4D9o3J0dextZu3U3a6r2sG7bHtZu3cOkYYV87tSJ5GVH/0OqbWjmy/e8zqOLN/OJd43lhvOPJDuMqXpvI995aAn3z9/YVjoYUZzHo4s38/DCSl5eu40WhwlDC3j3xFJGluQzsiSPEUV5jCzJZ1hRbpd/1K3J4O8LK7n27Kn8ewqSwd6GJr770FLufmU9BblZXH36JD51Uvl+79ktz67mh48s45QpQ7nlsuPJz0nOB1NDUwv/99RKbn5mNYMG5JCZAe/sqicnK4NTpgzl3BllnDFtGIV52bS0OFv31LeVtCqra8nLzuTDM0cd1P93MizfXMNvXljDX15/m4amFgbmZnHZieO48j3jGVqYu9+x7s5Diyq54W9L2La7nn9993hKC3O58+X1rN++lyEFOVw4awyfmD2WsUMGpOmO4qWrEoESQZLUNzVzw9+WcOfL6zl54hB+fslMCvOy2Fy97w+8srqOLbvq2VPfRG1jM3WNLdQ1NlPX2MzehmY27aylurax7ZxZGUZZSR4bttcycWgBP77wGI4bO6jbWLbsquPTf6hg0aZqrjtnGle+ZzxmB1aHPLXsHb7+wCK27m7A3WlxmDi0gHNnlHHO0WUcMbyww9dF0dTcwpfvfYO/vfF20pNBQ1MLn/5DBS+srOLyk8v5j9MnM6ggp8Nj735lPf/14CJmjh3Eby8/odtvuAfrzU3VfPW+N1i2uYaPzBzFNz44naK8bBas38HfF1byyJuVbUlh6MBcttTU0dh84N/k8KJcvnD6ZC6aNabXSy/rt+1l+Ts1lBXnMaI4j8EDctqqy9ydZ1dU8ZsX1vL8yq3kZWfwseNHc+b0Edw3fyMPLXyb7MwMLpk9lqveN4GRJfls3LGXb/x1MU8t28KMUcX84CMzOGpUUO3Y0uI8v2ord8x7i38sfQcHZpcP5r2TSzl5UilHjyo+pC9NnVm0sZpr7n+DusZmLj+5nAtnjTnoUlhDUwtPLdvCAws2Mm/NNq44uZwvv39Kt38L9U3N/M9jy1laWcPUEYVMKytiWlkRk4YNTEkJtD0lgjS6r2ID1//lTdyhobnlgOcL87IYmJtFfnYmudmZ5GdnkJedSV52JmXFeYwvLWDC0ALGlw5k9KB8sjMzeH5lFV+7fyGbd9XxmfdO4Mvvn9Lht8Vtu4MqnZufWsXO2kb+9+KZvH/68C7jra5t5FfPrCYn03r84d9eKpJBc4vzH3e9xkOLKrnxozO46ISx3b7mkUWVfPHu15kwtICfXXws4wYX9Lh00NDUwi+eWskvn1nNkIIcvv/hGczp4L1vaXEWrN/Bw4s2s31PPWUl+ZQV51FW3Pozj5VbdnPT48t5dd0ORg/K54tnTObDM0ft94G5ubqOl1Zv5cVV21j8djXnzijj306Z2OUHjrvz+5fW8YNHllHftO93MyczgxFhUti2u57VVXsYVpjL5SeX84nZY/dLqmu37uFXz6zigQWbMIMzpg7n2RVVmMF/nnkEl580rtMP9srqWu5+ZQOPLd7Mss01AAzMzeJd4wdz0sQhnDJlKJOHFx70ew/B78Etz67mp0+sYGhhLiNL8pn/1g4K87K4ZPZYLj+5vK36srP3ZuHGah5YsJG5b7zNjr2NDC3MZcrwgby4ahsfPGYkP/7Y0Z2W0rbU1PHZPy1g/ls7mDqikLVb97S9x9mZxqRhhZQPGdBh+1R2hjFp2MC2xFFWnNcrf4NKBGm2+O1q7p+/kcEDchhRHFSnjAj/yAfkHFodcU1dI99/eBl3vbJ+v9JB64f/w4sq+efqoEpn0rCB/OyiY9u+laVTYjKYVlbEcWNLOG7sII4bN4jyIQN69Avv7vzXg4u465UNXHfOND7zvgmRX/vCyq1c9ccK9jYEPahKBmS3fRiPKM5jQmkBJ04YwvSyok4bl92d1VW7eXLpFu6fv5GVW3bzkeNG8c3zjuxxScPdeW7lVm56fDkLN1YzYWgBnzxxHKurdvPS6m2sqQq6LQ8akE15aQGvrd/J5GED+f5HZnBC+eADzrdlVx3X3L+QZ1dUcdoRQ/n8aZPYtqeByp21VO4KOgFsrq4D4OLZYzjv6JFdJpWNO/Zy23NruH/+Rk6eOIQbLjiqyw/a9rbtrmfemu28tHor/1y9jTVhN+xzjy7jax+YelDVRxu27+Ur977Oq+t2cN7RZXzvQzMoHpDNa+t38JsX1vLIm5sBOPuoEZx11Aj21Dexc28jO/Y2snNvAzv2NrBqy25WV+0hJyuDM6cP56PHj+a9k0rJzDBufW4NP3xkGceNLeG2T82idOD+1WILN+7k3/44nx17G/ifC4/hvKNH0tTcwtqte1hSuYullTUsqdzFpk5WOaxrbGHTztq27ZIB2UwbESSF848dybFjSiK/F4mUCPqxF1Zu5Wt/XkhldS1Hjy5h4cadQX1+aQHnzCjjnBllTCvrvW/1vaGpuYVfv7CWF1Zu5fUNO9kdjsgeXJDDzDEljB6UT15OJnlZQcmotZRUXlrA7PLBnX4Q//CRZdzy7Go+f9pErvnA1IOOa/22vVS8tb2t6m5fNV5d23iIkgHZnDRhCCdPHMLJk0oZPSifl9ds56llW3hq2RbWbw/+uKeXFfGV90/psBTQE+7O40ve4SePr2D5OzUU5GQye/xg3j0paKSfNiJIVE8v28L1f3mTTTtruWT2WK49a2pbMnr0zc18/YGF1DY2c92507nsXWMPq98P2FdauO25NTS1tHD5SeVcffrkLhOqu/Pga5v4xl8XY8B3PnQUFxw78oB727Szlt+/tI67Xl5PTcJsADmZGZQMyKZkQDbDi/La/n6K8w+85qNvVvKle16ndGAuv73iBKaEJZe/vLaJr/15IaUDc7ntU8dz5MhD+/JVU9fIss01LK3cxdLKXSx5exfLNtfwvQ/P4GPHH9rS7koE/VxNXSM/enQ5C9bv4LQjhh2WH/6daW5xVm6p4bX1O1nw1g5e27CTqpp66hqb96uuaDW+tIBPzB7Lx44fvV8Vxa+eWc2Njy7jkyeO49sXHNnr9/7OrqDq5aVV23hp9ba2b2yZGUZzi5OblcF7JpVy+rRhnHbEMEYexLfhQ9Hc4qzbtoexgwe0Nfq3t7ehiZ8+sYLfvLCWwQW5XHfuVOat3s49FRs4alQRP7toJpOGHd7dOd/ZVcdPHl/BvfM3UJSXzdWnT+KTJ40jNyuTmrpG1m3dy5qtu1m7dQ/z39rB8yu3Mnv8YH7y8WMYPajrUsTu+ibe2raH4vxsBg3IYUBO5kH93ryxYSef/kMFdQ3N/OITM/nn6m3c+twaZo8fzK8uPY4h7UoKPdXc4jS1tBxybyslAumTWlqc+qYWahubqW1s5pW127hj3noq3tpBTlYG580o49ITx7J8827+68FFXHDsSH768WOTPi7A3Vm/fS8vrtrGW9v28K4JgzlpQmnSeh311Jubqvn6A4tYtAkKXI0AAApnSURBVKkaM/jcqRP54hlT0tJgeaiWVu7iB48s47kVVQwrzMUJurG2Mgu6MF/6rnFc9b4JZKZobMimnbVcefurbW0cl504lm+cd+Rh+d4qEUi/smzzLu6Yt54HX9vUVq10+tRh3PrJ4zv9dhx3zS3OAws2MmHoQI4f131Ps8PVsyuq+NO8txg8IIfy0oK2zhRjBw9IW/fa3fVNfP/hpRwzujhS54R0USKQfmlPfRNz33ibVVt2c80Hjkh7P3uRw5lGFku/VJAbdAUUkZ5ROVpEJOaUCEREYk6JQEQk5pQIRERiTolARCTmlAhERGJOiUBEJOaUCEREYq7PjSw2syrgrUN8eSmwtRfD6Qt0z/Gge46HntzzOHcf2tETfS4R9ISZVXQ2xLq/0j3Hg+45HpJ1z6oaEhGJOSUCEZGYi1siuC3dAaSB7jkedM/xkJR7jlUbgYiIHChuJQIREWlHiUBEJOb6ZSIws7PMbLmZrTKzazt4PtfM7gmff9nMylMfZe+KcM9fMbMlZrbQzJ40s3HpiLM3dXfPCcd91MzczPp8V8Mo92xmHw//rxeb2Z2pjrG3RfjdHmtmT5vZa+Hv9znpiLO3mNlvzWyLmb3ZyfNmZj8P34+FZnZcjy/q7v3qH5AJrAYmADnAG8D0dsd8DrglfHwxcE+6407BPZ8GDAgffzYO9xweVwg8B8wDZqU77hT8P08GXgMGhdvD0h13Cu75NuCz4ePpwLp0x93De34fcBzwZifPnwM8AhhwIvByT6/ZH0sEs4FV7r7G3RuAu4EL2h1zAfD78PH9wBlmZimMsbd1e8/u/rS77w035wGjUxxjb4vy/wzwHeBGoC6VwSVJlHv+DHCzu+8AcPctKY6xt0W5ZweKwsfFwNspjK/XuftzwPYuDrkA+IMH5gElZlbWk2v2x0QwCtiQsL0x3NfhMe7eBFQDQ1ISXXJEuedEVxJ8o+jLur3nsMg8xt0fSmVgSRTl/3kKMMXMXjSzeWZ2VsqiS44o9/wt4DIz2wg8DFydmtDS5mD/3rulxetjxswuA2YBp6Q7lmQyswzgJ8AVaQ4l1bIIqodOJSj1PWdmM9x9Z1qjSq5LgNvd/SYzOwn4o5kd5e4t6Q6sr+iPJYJNwJiE7dHhvg6PMbMsguLktpRElxxR7hkzmwNcB5zv7vUpii1ZurvnQuAo4BkzW0dQlzq3jzcYR/l/3gjMdfdGd18LrCBIDH1VlHu+ErgXwN3/CeQRTM7WX0X6ez8Y/TERvApMNrPxZpZD0Bg8t90xc4HLw8cfA57ysBWmj+r2ns1sJnArQRLo6/XG0M09u3u1u5e6e7m7lxO0i5zv7hXpCbdXRPnd/gtBaQAzKyWoKlqTyiB7WZR7Xg+cAWBm0wgSQVVKo0ytucCnwt5DJwLV7l7ZkxP2u6ohd28ysy8AjxH0OPituy82s28DFe4+F/gNQfFxFUGjzMXpi7jnIt7zj4GBwH1hu/h6dz8/bUH3UMR77lci3vNjwJlmtgRoBq5x9z5b2o14z/8J/D8z+zJBw/EVffmLnZndRZDMS8N2j28C2QDufgtBO8g5wCpgL/AvPb5mH36/RESkF/THqiERETkISgQiIjGnRCAiEnNKBCIiMadEICISc0oEckjM7LpwdsuFZva6mb0r3P9rM5t+iOcs72zGxd5iZiVm9rlkXuNwYGa7D/L4283sYx3sn2VmPw8fX2Fm/xc+/ncz+1TC/pG9EbekR78bRyDJFw7jPw84zt3rw4FLOQDu/um0Bte9EoLZZ3/Z2yc2s0x3b07YzgrnsurudZGOa/caI+j+ndRpFMIBeAcMwgv7s7e6AniTPj7ZW5ypRCCHogzY2jpNhbtvdfe3AczsmdZpHMxst5l9z8zeCCdAGx7unxhuLzKz73b07dXMMs3sx2b2aljq+LeOAunsXGY20IJ1FxaEz7XOWPlDYGJYivlxeOw1Cde5oZPrnGlm/wzPd5+ZDQz3rzOzG81sAXBheP8/M7MK4IthKecp27cOxNjwdbeb2S1m9jLwo3bXusLM/hqea6WZfTPcX27BvPx/IPjgHWNml4T396aZ3djuPD8NS21PmtnQcN9nwnt9w8z+bGYDEl4yx8wqzGyFmZ0XHn+qmf29g/fjW2b21bAUMQu4I3xPzzWzvyQc934ze7Cj91QOH0oEcigeJ/gQWmFmvzSzziawKwDmufsxBGsCfCbc/7/A/7r7DIK5cTpyJcHQ+ROAE4DPmNn4Do7r7Fx1wIfd/TiCtRhuCr9FXwusdvdj3f0aMzuTYC6e2cCxwPFm9r7EC4QlnuuBOeH5KoCvJByyzd2Pc/e7w+0cd5/l7jcBvwB+7+5HA3cAP0943WjgZHdPPFer2cBHgaMJEkzrHEmTgV+6+5FAI8EU26eHsZ9gZh8KjysgGHl7JPAswehUgAfc/YTw/2Rp+D63Kg+vey5wi5nldRDXftz9/vD9uNTdjyUY9Tq1NfEQjHr9bXfnkfRSIpCD5u67geOBqwjmdLnHzK7o4NAGoPXb5HyCDxqAk4D7wsedraB1JsF8Kq8DLxNME97R5GmdncuA75vZQuAfBNP0Du/kOmcSLOayAJjawXVOJFjw5MUwnsuBxBXe7ml3fOL2SQlx/RF4T8Jz9yVWJbXzhLtvc/da4IGE170VzkEPQYJ8xt2rwqqlOwgWNQFoSYjjTwmvP8rMnjezRcClwJEJ17zX3VvcfSXB/ERTO4mtU+HUDn8kmBa6hOD++/qU5/2e2gjkkIQfYM8QzO65iODD8fZ2hzUmzPnSzMH9vhlwtbs/tt9Os+8RfGMl/AbamUuBocDx7t5owQykHX3DNeAH7n5rN7E84e6XdPL8nm62O9PVce3nfmndjnruzs53O/Ahd38jTN6nRrjmwfod8DeCUtl9B9v+IamnEoEcNDM7wswSvzUfC7x1EKeYR1DtAZ1P+PcY8Fkzyw6vOcXMCtz9urBapzUJdHauYmBLmAROY983+BqCKaoTr/OvCXX+o8xsWAfxvtvMJoXHFJjZlIj3+lJCXJcCz0d83fvNbLCZ5QMfAl7s4JhXgFPMrNTMMgnm5X82fC6DYGZdgE8AL4SPC4HK8H29tN35LjSzDDObSLA05PKIse73nobtRW8TVKf9LuI5JI1UIpBDMRD4RVj0byKYBfGqg3j9l4A/mdl1wKMEK8S192uCqqQFYd1+FcEHYtRz3QH8LSytVADLANx9mwWrd70JPBK2E0wD/hlcht3AZUDbVN3uXhV+e77LzHLD3dcTzPXfnauB35nZNeE9RJ0p8hXgzwTtCH9y9wozK088wN0rLVjM/WmCUstD7v7X8Ok9wGwzuz68l4vC/f9NUNVWFf5MTIrrw+sWAf/u7nUWbQXX2wnaFGqBk8LqrDuAoe6+NOL9Shpp9lFJubCnSq27u5ldDFzi7h2tN5zScx0uwqQzy92/kO5YDpUF4w1ec/ffpDsW6Z5KBJIOxwP/F37T3wn862FyLukFZjafoETyn+mORaJRiUBEJObUWCwiEnNKBCIiMadEICISc0oEIiIxp0QgIhJz/x85az3WZecaCQAAAABJRU5ErkJggg==\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": "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\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 |
--------------------------------------------------------------------------------