├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── content
├── lab_1
│ ├── lab1-es.ipynb
│ ├── lab1-ja.ipynb
│ ├── lab1-ko.ipynb
│ ├── lab1.ipynb
│ └── resources
│ │ ├── circuitRx.png
│ │ └── sketch-1.png
├── lab_2
│ ├── lab2-es.ipynb
│ ├── lab2-ja.ipynb
│ ├── lab2-ko.ipynb
│ └── lab2.ipynb
├── lab_3
│ ├── lab3-es.ipynb
│ ├── lab3-ja.ipynb
│ ├── lab3-ko.ipynb
│ ├── lab3.ipynb
│ └── resources
│ │ ├── step1-circuit.png
│ │ └── step2-circuit.png
├── lab_4
│ ├── lab4-es.ipynb
│ ├── lab4-ja.ipynb
│ ├── lab4-ko.ipynb
│ └── lab4.ipynb
└── lab_5
│ ├── lab5-es.ipynb
│ ├── lab5-ja.ipynb
│ ├── lab5-ko.ipynb
│ └── lab5.ipynb
└── solutions
├── lab_1
├── lab1_solution.ipynb
└── resources
│ ├── circuitRx.png
│ └── sketch-1.png
├── lab_2
└── lab2_solution.ipynb
├── lab_3
├── lab3_solution.ipynb
└── resources
│ ├── step1-circuit.png
│ └── step2-circuit.png
├── lab_4
└── lab4_solution.ipynb
└── lab_5
└── lab5_solution.ipynb
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # poetry
98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102 | #poetry.lock
103 |
104 | # pdm
105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106 | #pdm.lock
107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108 | # in version control.
109 | # https://pdm.fming.dev/#use-with-ide
110 | .pdm.toml
111 |
112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113 | __pypackages__/
114 |
115 | # Celery stuff
116 | celerybeat-schedule
117 | celerybeat.pid
118 |
119 | # SageMath parsed files
120 | *.sage.py
121 |
122 | # Environments
123 | .env
124 | .venv
125 | env/
126 | venv/
127 | ENV/
128 | env.bak/
129 | venv.bak/
130 |
131 | # Spyder project settings
132 | .spyderproject
133 | .spyproject
134 |
135 | # Rope project settings
136 | .ropeproject
137 |
138 | # mkdocs documentation
139 | /site
140 |
141 | # mypy
142 | .mypy_cache/
143 | .dmypy.json
144 | dmypy.json
145 |
146 | # Pyre type checker
147 | .pyre/
148 |
149 | # pytype static type analyzer
150 | .pytype/
151 |
152 | # Cython debug symbols
153 | cython_debug/
154 |
155 | # PyCharm
156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158 | # and can be added to the global gitignore or merged into this file. For a more nuclear
159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160 | #.idea/
161 |
162 |
163 | .DS_Store
164 |
165 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct for Participation
2 |
3 | The IBM Quantum Challenge Spring 2023 and the Qiskit Community team are committed to maintaining the highest level of enjoyment, accessibility, and inclusivity by maintaining an environment of respect, empathy, and compassion for others. In order to support that, we ask that each participant review the Qiskit Community Code of Conduct before the event, and be familiar with our community standards to join us in maintaining a safe and welcoming event for all.
4 |
5 | We have zero tolerance for any type of harassment, and welcome each and every attendee as you support these values and make this hackathon and the Qiskit Community a friendly and open space for everyone.
6 |
7 | [Click here to Review Qiskit Community Code of Conduct](https://github.com/Qiskit/qiskit/blob/master/CODE_OF_CONDUCT.md#our-pledge)
8 |
9 | *As this event is a challenge, sharing solutions/answers is strictly forbidden and can lead to potential disqualification from the event. We encourage you to ask questions in the dedicated Discord channel if you need additional guidance.*
10 |
11 | ## IBM Quantum Challenge Spring 2023 Event Values
12 |
13 | - **Be Engaged:** Connect with each other & have FUN!
14 | - **Be Inclusive:** Use shared language, be empathetic, & be aware of cultures and backgrounds
15 | - **Be Respectful:** Respect each other, & use respectful language
16 | - **Be Positive:** Assume the best intentions, & have forward-looking outlook
17 | - **Be Honest:** To ensure a positive learning experience for everyone, do not share the answers to the exercises with any participant or publicly within the Slack channel. We are all here to learn & have fun together!
18 | - **Be You!!!** Share about yourself and your goals, be real, be genuine, & let yourself be comfortable
19 |
20 | Throughout the event, in the case that you may encounter any offensive behavior or violations of the Qiskit Community Code of Conduct, we encourage you to report the violation by submitting [this form](https://airtable.com/shrl5mEF4Eun1aIDm). All reports are treated with the strictest level of confidentiality, and we have an absolute zero-tolerance policy on any form of retaliation.
21 |
22 | The events team, admins, and moderators are all here to support the event and community - so please feel comfortable reaching out directly with any questions, concerns, or reports as well.
23 |
24 | This community continues to be open, friendly, and welcoming, and with your support, we will be able to maintain that throughout this event, and also in the years to come. Thank you!
25 |
--------------------------------------------------------------------------------
/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 | # IBM Quantum Challenge Spring 2023
2 |
3 | [](https://opensource.org/licenses/Apache-2.0)
4 |
5 | The IBM Quantum Challenge is back with a new challenge: run dynamic circuits on a 127-qubit processor.
6 |
7 | ## Introduction
8 |
9 | Welcome to the IBM Quantum Spring Challenge. Every year, IBM Quantum releases a public challenge as part of our ongoing global education efforts. The Spring Challenge is free to participate in, and is meant to give participants a deeper understanding of a specific quantum topic. This year’s Challenge focuses on Dynamic Circuits, a technology that makes it easier to run more advanced quantum algorithms.
10 |
11 | This event will feature 5 Labs, each with exercises and tutorial content to get you started using Dynamic Circuits. We’re also thrilled to showcase the most advanced IBM Quantum hardware—IBM Quantum will allow all registered participants to run circuits on a 127-qubit IBM Quantum Eagle processor. Downloading the files from GitHub will NOT give you access to the hardware. Only users registered through [the IBM Quantum Challenge website](https://quantum-computing.ibm.com) will have access to the real hardware.
12 |
13 | The IBM Quantum Challenge is exactly that: a challenge. Some labs will be relatively easy, while others should put your knowledge to the test. We hope this experience will turbocharge your exploration of IBM Quantum hardware and software, while providing an opportunity to network with members of the IBM Quantum and Qiskit community.
14 |
15 | ## Challenge content
16 |
17 | - [Lab 1: Intro to Dynamic Circuits](./content/lab_1/lab1.ipynb)
18 | - [Lab 2: Quantum Teleportation](./content/lab_2/lab2.ipynb)
19 | - [Lab 3: Iterative Phase Estimation](./content/lab_3/lab3.ipynb)
20 | - [Lab 4: Quantum Error Correction](./content/lab_4/lab4.ipynb)
21 | - [Lab 5: Using a 127-qubit System](./content/lab_5/lab5.ipynb)
22 |
23 | ## Challenge solution examples
24 |
25 | - [Lab 1 Solution](./solutions/lab_1/lab1_solution.ipynb)
26 | - [Lab 2 Solution](./solutions/lab_2/lab2_solution.ipynb)
27 | - [Lab 3 Solution](./solutions/lab_3/lab3_solution.ipynb)
28 | - [Lab 4 Solution](./solutions/lab_4/lab4_solution.ipynb)
29 | - [Lab 5 Solution](./solutions/lab_5/lab5_solution.ipynb)
30 |
31 | # [Event Code of Conduct](./CODE_OF_CONDUCT.md)
32 |
33 | # [FAQ / Wiki](https://github.com/qiskit-community/ibm-quantum-challenge-spring-2023/wiki)
34 |
35 | # Collaborators
36 |
37 | Thank you! to everyone who helped make this challenge possible and a great success.
38 |
39 | - Alexandre Alemany Orfila
40 | - Anne Gebbie
41 | - Brian Ingmanson
42 | - Iman Elsayed
43 | - James Weaver
44 | - Kallie Ferguson
45 | - Kevin Sung
46 | - Kifumi Numata
47 | - Marcel Pfaffhauser
48 | - Marco Facchini
49 | - Maria Esperanza Molina Canizares
50 | - Matthew Stypulkoski
51 | - Serena Godwin
52 | - Sophy Shin
53 | - va barbosa
54 | - Vishal Sharathchandra Bajpe
55 | - Yuri Kobayashi
56 |
--------------------------------------------------------------------------------
/content/lab_1/lab1-ja.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "tags": []
7 | },
8 | "source": [
9 | "# IBM Quantum Challenge: Spring 2023"
10 | ]
11 | },
12 | {
13 | "cell_type": "markdown",
14 | "metadata": {},
15 | "source": [
16 | "## 始めの一歩"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "metadata": {},
22 | "source": [
23 | "IBM Quantum Challenge: Spring 2023へようこそ!\n",
24 | "\n",
25 | "今回のIBM Quantum ChallengeではDynamic circuitsに取り組んでいただきます。あなたは現在、このChallengeの最初のLabにいます。この最初のLabで作業する中でいくつかのExerciseを完了させます。この入門編では、Exerciseの解き方について簡単に説明します。以前のChallengeに参加したことがある方でもこの資料を見直す事をお勧めします。\n",
26 | "\n",
27 | "すべてのLabは、チュートリアルコンテンツ、事前に書かれたコードブロック、およびあなたにQiskitコードを埋めていただく必要があるExerciseのコードブロックが混ざっています。Exerciseを完了するためには、コメント行 _\"### Your code goes here ###\"_ の下に必要なコードを入力する必要があります。\n",
28 | "\n",
29 | "初めてChallengeに参加する方に、覚えておいていただきたい重要なこととして、新たにコードを追加していない場合でも、すべてのコードセルを実行する必要があります。そうすることで、Graderを実行して回答を提出するときにすべてが最新であることが確認されます。"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {
35 | "tags": []
36 | },
37 | "source": [
38 | "### サンプル問題\n",
39 | "\n",
40 | "下のセルでは、1つの量子ビットと1つの古典ビットを持つ回路を構築しています。あなたの最初の仕事は、量子ビットにアダマールゲートを実行、測定し、結果を古典ビットに格納することです。既にコードは用意してあります。あなたに必要なことは、両方の行の先頭にある`#`を取り除くことだけです。"
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": null,
46 | "metadata": {
47 | "tags": []
48 | },
49 | "outputs": [],
50 | "source": [
51 | "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
52 | "\n",
53 | "qr = QuantumRegister(1)\n",
54 | "cr = ClassicalRegister(1)\n",
55 | "qc = QuantumCircuit(qr, cr)\n",
56 | "\n",
57 | "####### your code goes here #######\n",
58 | "\n",
59 | "# qc.h(qr[0])\n",
60 | "# qc.measure(qr[0], cr[0])\n",
61 | "\n",
62 | "\n",
63 | "qc.draw(\"mpl\")"
64 | ]
65 | },
66 | {
67 | "cell_type": "markdown",
68 | "metadata": {},
69 | "source": [
70 | "よくできました!各Exerciseの後、あなたが書いたものが正しいかどうかを判断する必要があります。それは、Graderのセルを実行するとわかります。\n",
71 | "\n",
72 | "試してみましょう。次のセルで、変数 `answer_0` に整数値を設定してください。この整数が1〜5の間であれば、Grader は正しい答えを見つけたことを祝福するメッセージを返します。それ以外の数値を入力した場合は、逆のメッセージが表示されます。\n",
73 | "\n",
74 | "答えを好きなように設定し、Grader セルを実行して結果を見てみましょう。違う数字で何度か試してみるのも面白いでしょう。"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": null,
80 | "metadata": {},
81 | "outputs": [],
82 | "source": [
83 | "answer_0: int\n",
84 | "answer_0 = 500\n",
85 | "\n",
86 | "##### Hint: Remember to run this cell after changing your value ###"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": null,
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "# Grader Cell: Run this to submit your answer\n",
96 | "\n",
97 | "from qc_grader.challenges.spring_2023 import grade_ex1a\n",
98 | "\n",
99 | "grade_ex1a(answer_0)"
100 | ]
101 | },
102 | {
103 | "cell_type": "markdown",
104 | "metadata": {},
105 | "source": [
106 | "これで、このChallengeを始める準備は万端です。がんばって、そして楽しんでください!"
107 | ]
108 | },
109 | {
110 | "cell_type": "markdown",
111 | "metadata": {},
112 | "source": [
113 | "# Dynamic Circuits入門 と 成功するまでの繰り返し"
114 | ]
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {},
119 | "source": [
120 | "## はじめに"
121 | ]
122 | },
123 | {
124 | "cell_type": "markdown",
125 | "metadata": {},
126 | "source": [
127 | "[Qiskitテキストブック](https://ja.learn.qiskit.org/course/ch-algorithms/quantum-circuits)によると以下のように表現されています。\n",
128 | ">_「量子回路とは、量子データ(量子ビットなど)に対するコヒーレントな量子演算と、リアルタイム同時古典計算で構成される計算ルーチンのことです。量子回路は、量子ゲート 、測定 、リセットの順序立てられたシーケンスであり、これらはすべてリアルタイム古典計算のデータを使用した条件付ゲートが作用することがあります。」_\n",
129 | "\n",
130 | "\n",
131 | "\n",
132 | "この定義の最後の部分はあまり聞き慣れないかもしれませんが、これは動的回路(Dynamic circuits)に関係するものです。通常量子回路の話をするときは、明示的に言わないまでも静的な量子回路を指しています。では、Dynamic circuitsとは何でしょうか?\n",
133 | "\n",
134 | "**Dynamic circuits**とは、量子回路の途中で測定が行われ、その測定結果をもとに回路内の量子ゲートを条件付けることができる回路です。このように、古典的な測定結果をもとに将来の量子演算を条件付ける機能を古典フィードフォワードと呼びます。\n",
135 | "\n",
136 | "なぜ古典フィードフォワードが必要なのでしょうか?例を挙げましょう: Qiskitの条件付きリセット操作を考えてみましょう。[`reset`](https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.reset.html)操作を使ったことがある人なら聞き覚えがあるかもしれません。リセット操作は初期状態に関係なく量子ビットをゼロ状態にリセットする非ユニタリー操作ですが、条件付きリセット操作はすでに測定された量子ビットに対して実行され、測定値から判断して量子ビットが1状態にある場合にのみビットフリップXゲートを適用してゼロ状態にリセットします。条件付きリセットは、すでに測定された量子ビットをリセットする方法としてより速く、よりエラーの少ない方法となり得ます。"
137 | ]
138 | },
139 | {
140 | "cell_type": "markdown",
141 | "metadata": {},
142 | "source": [
143 | "
\n",
144 | "
\n",
145 | ""
146 | ]
147 | },
148 | {
149 | "cell_type": "markdown",
150 | "metadata": {},
151 | "source": [
152 | "別の言い方をすればDynamic circuitsとは、if文やwhileループなどの制御フローを含む量子回路で、述語は過去の量子ビット測定結果から計算され、条件演算は量子ゲートを含みます。"
153 | ]
154 | },
155 | {
156 | "cell_type": "markdown",
157 | "metadata": {},
158 | "source": [
159 | "## Hello Dynamic Circuit World"
160 | ]
161 | },
162 | {
163 | "cell_type": "markdown",
164 | "metadata": {},
165 | "source": [
166 | "IBM Quantumハードウェアはすでに回路途中の測定とリセットをサポートしていました。しかし古典フィードフォワードのサポートを追加するには、制御システムと関連するソフトウェアスタックを大幅に再設計する必要がありました。Dynamic circuitsの完全なサポートは、昨年(2022年)になってから導入されました。\n",
167 | "\n",
168 | "QiskitではDynamic circuitをプログラミングするための構文が何度か取り入れられていますが、まだ完全なサポートは実装されていません。現在のところは、Dynamic circuitの全機能にアクセスするにはOpenQASM3で書かれたプログラムを提出するしかないのです。とはいえ、今回のチャレンジではQiskitで現在利用可能な機能を使って取り組んでいただきます。\n",
169 | "\n",
170 | "Qiskitの以前のバージョンでは[`c_if()`](https://qiskit.org/documentation/stubs/qiskit.circuit.Instruction.c_if.html)命令が使われていましたが、この構文は今後非推奨となる予定です。というのもQuantumCircuitクラスにはより柔軟な[`if_test()`](https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.if_test.html)メソッドがあり、今回のチャレンジではこちらを主に使用します。\n",
171 | "\n",
172 | "手始めに、この機能を使った簡単な例を確認しましょう。次の手順で、条件付きリセット回路を作ることにします。\n",
173 | "\n",
174 | "1. 1量子ビットと2古典ビットで回路を初期化する。($q_{0}$、$b_{0}$、$b_{1}$)\n",
175 | "2. $q_{0}$にアダマールゲートを適用する。\n",
176 | "3. その量子ビットを測定し、その結果を$b_{0}$に保存する。\n",
177 | "4. $b_{0}$が1の場合`if_test`ブロックを開始する。\n",
178 | "5. `if_test`ブロックの中で条件を満たした場合に行う操作を指定する。(今回は$q_{0}$を0状態に反転させます。)\n",
179 | "6. 再度$q_0$を$b_{1}$に測定し、常に結果が0となることを確認する。"
180 | ]
181 | },
182 | {
183 | "cell_type": "code",
184 | "execution_count": null,
185 | "metadata": {},
186 | "outputs": [],
187 | "source": [
188 | "from qiskit import QuantumCircuit\n",
189 | "from qiskit.circuit import QuantumRegister, ClassicalRegister\n",
190 | "\n",
191 | "qr = QuantumRegister(1)\n",
192 | "cr = ClassicalRegister(2)\n",
193 | "qc = QuantumCircuit(qr, cr)\n",
194 | "\n",
195 | "# unpack the qubit and classical bits from the registers\n",
196 | "(q0,) = qr\n",
197 | "b0, b1 = cr\n",
198 | "\n",
199 | "# apply Hadamard\n",
200 | "qc.h(q0)\n",
201 | "# measure\n",
202 | "qc.measure(q0, b0)\n",
203 | "\n",
204 | "# begin if test block. the contents of the block are executed if b0 == 1\n",
205 | "with qc.if_test((b0, 1)):\n",
206 | " # if the condition is satisfied (b0 == 1), then flip the bit back to 0\n",
207 | " qc.x(q0)\n",
208 | "# finally, measure q0 again\n",
209 | "qc.measure(q0, b1)\n",
210 | "\n",
211 | "qc.draw(output=\"mpl\", idle_wires=False)"
212 | ]
213 | },
214 | {
215 | "cell_type": "markdown",
216 | "metadata": {},
217 | "source": [
218 | "回路ができたので何度か動かしてみて常に期待通りの出力が得られるかどうか確認してみましょう。最初の測定は0でも1でも構いませんが、2回目の測定は必ず0になるはずです。"
219 | ]
220 | },
221 | {
222 | "cell_type": "code",
223 | "execution_count": null,
224 | "metadata": {},
225 | "outputs": [],
226 | "source": [
227 | "from qiskit_aer import AerSimulator\n",
228 | "\n",
229 | "# initialize the simulator\n",
230 | "backend_sim = AerSimulator()\n",
231 | "\n",
232 | "# run the circuit\n",
233 | "reset_sim_job = backend_sim.run(qc)\n",
234 | "# get the results\n",
235 | "reset_sim_result = reset_sim_job.result()\n",
236 | "# retrieve the bitstring counts\n",
237 | "reset_sim_counts = reset_sim_result.get_counts()\n",
238 | "\n",
239 | "print(f\"Counts: {reset_sim_counts}\")"
240 | ]
241 | },
242 | {
243 | "cell_type": "markdown",
244 | "metadata": {},
245 | "source": [
246 | "期待通り最初のビットは0になったり1になったりしますが、2番目のビットは常に0です。(Qiskitはリトルエンディアンのビット順を採用しているので、右端のビットが1番目のビット、左端のビットが最後のビットになることを思い出してください。)"
247 | ]
248 | },
249 | {
250 | "cell_type": "code",
251 | "execution_count": null,
252 | "metadata": {},
253 | "outputs": [],
254 | "source": [
255 | "from qiskit.visualization import *\n",
256 | "\n",
257 | "# plot histogram\n",
258 | "plot_histogram(reset_sim_counts)"
259 | ]
260 | },
261 | {
262 | "cell_type": "markdown",
263 | "metadata": {},
264 | "source": [
265 | "これで、初めてのDynamic circuitを作る準備ができました!"
266 | ]
267 | },
268 | {
269 | "cell_type": "markdown",
270 | "metadata": {},
271 | "source": [
272 | "### **Exercise 1**"
273 | ]
274 | },
275 | {
276 | "cell_type": "markdown",
277 | "metadata": {},
278 | "source": [
279 | "レベルを上げましょう。最初の課題は2量子ビット回路を設計することです。この場合$q_{0}$の値によって$q_{1}$に異なる動作をさせることが目的となります。$q_{0}$の測定値が0なら$q_{1}$に$X$ゲートを適用します。1であれば代わりに$q_{1}$にアダマールゲートを適用します。\n",
280 | "\n",
281 | "$q_{0}$の値をランダムにするために、まずアダマールゲートを適用します。次に、$q_{0}$を測定して$b_{0}$に書き込みます。そうすると、動的なマジックが起こるはずです。最後に$q_{1}$を測定します。"
282 | ]
283 | },
284 | {
285 | "cell_type": "markdown",
286 | "metadata": {},
287 | "source": [
288 | "このExerciseでは [`if_test()`](https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.if_test.html) のドキュメントを読むことをお勧めします。"
289 | ]
290 | },
291 | {
292 | "cell_type": "code",
293 | "execution_count": null,
294 | "metadata": {},
295 | "outputs": [],
296 | "source": [
297 | "qr = QuantumRegister(2)\n",
298 | "cr = ClassicalRegister(2)\n",
299 | "qc = QuantumCircuit(qr, cr)\n",
300 | "\n",
301 | "q0, q1 = qr\n",
302 | "b0, b1 = cr\n",
303 | "\n",
304 | "qc.h(q0)\n",
305 | "qc.measure(q0, b0)\n",
306 | "\n",
307 | "####### your code goes here #######\n",
308 | "\n",
309 | "\n",
310 | "qc.measure(q1, b1)\n",
311 | "qc.draw(output=\"mpl\", idle_wires=False)"
312 | ]
313 | },
314 | {
315 | "cell_type": "markdown",
316 | "metadata": {},
317 | "source": [
318 | "オプションで、次のセルを実行して回路が期待通りに動作するかをチェックすることができます。\n",
319 | ">Tip:回路を実行する前に起こりうる結果を考えて見てください。"
320 | ]
321 | },
322 | {
323 | "cell_type": "code",
324 | "execution_count": null,
325 | "metadata": {},
326 | "outputs": [],
327 | "source": [
328 | "backend_sim = AerSimulator()\n",
329 | "\n",
330 | "job_1 = backend_sim.run(qc)\n",
331 | "result_1 = job_1.result()\n",
332 | "counts_1 = result_1.get_counts()\n",
333 | "\n",
334 | "print(f\"Counts: {counts_1}\")"
335 | ]
336 | },
337 | {
338 | "cell_type": "code",
339 | "execution_count": null,
340 | "metadata": {},
341 | "outputs": [],
342 | "source": [
343 | "# Submit your circuit\n",
344 | "\n",
345 | "from qc_grader.challenges.spring_2023 import grade_ex1b\n",
346 | "\n",
347 | "grade_ex1b(qc)"
348 | ]
349 | },
350 | {
351 | "cell_type": "markdown",
352 | "metadata": {},
353 | "source": [
354 | "## 成功するまで繰り返す"
355 | ]
356 | },
357 | {
358 | "cell_type": "markdown",
359 | "metadata": {},
360 | "source": [
361 | "プロセスの出力がランダムで得られる結果が望んだものでないことがあります。このような場合どうすればいいのでしょうか?もう一度やってみればいいのです!望む結果が得られる確率がゼロでない限り、プロセスを繰り返せば、最終的には期待した結果が得られることが保証されています。多くの場合ほんの数回の繰り返しで済みます。\n",
362 | "\n",
363 | "このセクションでは「成功するまで繰り返す」アイデアを用いて$R_X(\\theta)$ゲート(ただし$\\theta / \\pi$は無理数)を有限のゲートセット$\\{H,\\,X,\\,S,\\,\\text{Toffoli}\\}$から構築します。特に$\\cos\\theta = \\frac35$の場合を考えます。この構成はNielsen and Chuangの _量子コンピュータと量子通信_, 10th anniversary edition, Exercise 4.41 からの引用したもので、上で与えられた有限のゲートセットの普遍性を示しています。\n",
364 | "\n",
365 | "作り方は、3つの量子ビットに作用する回路を作ることになります。そのうちの1つはターゲット量子ビットで、このターゲット量子ビットに対して$R_X(\\theta)$ゲートを実行することが目標です。残りの2つの量子ビットは「シンドローム」量子ビットで、測定し、測定結果で操作が成功したかどうかを知ることができます。もし両方のシンドローム量子ビットが0を読み取ったら、ゲートが成功したことがわかります。そうでない場合は、量子ビットをリセットして再挑戦します。測定結果をもとに回路の繰り返しを条件付けるために、Dynamic circuitが必要になります。"
366 | ]
367 | },
368 | {
369 | "cell_type": "markdown",
370 | "metadata": {},
371 | "source": [
372 | "### Exercise 2"
373 | ]
374 | },
375 | {
376 | "cell_type": "markdown",
377 | "metadata": {},
378 | "source": [
379 | "このセクションの最初の課題は、上記の回路を返す関数を作成することです。回路のアウトプットイメージはこちらです。"
380 | ]
381 | },
382 | {
383 | "cell_type": "markdown",
384 | "metadata": {},
385 | "source": [
386 | "\n",
387 | "
\n",
388 | ""
389 | ]
390 | },
391 | {
392 | "cell_type": "markdown",
393 | "metadata": {},
394 | "source": [
395 | "簡単にできるように、必要な要素を入れた「ベース」回路を用意してあります。このLabで書く関数は、回路を入力として受け取りその場で修正するものです。新しい回路が必要なときはベースとなる回路のコピーを作ればよいのです。"
396 | ]
397 | },
398 | {
399 | "cell_type": "code",
400 | "execution_count": null,
401 | "metadata": {},
402 | "outputs": [],
403 | "source": [
404 | "controls = QuantumRegister(2, name=\"control\")\n",
405 | "target = QuantumRegister(1, name=\"target\")\n",
406 | "\n",
407 | "mid_measure = ClassicalRegister(2, name=\"mid\")\n",
408 | "final_measure = ClassicalRegister(1, name=\"final\")\n",
409 | "\n",
410 | "base = QuantumCircuit(controls, target, mid_measure, final_measure)"
411 | ]
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "metadata": {},
416 | "source": [
417 | "次のセルで、`trial`関数が以下のステップを踏んで回路を構成するようにしてください。\n",
418 | "\n",
419 | "1. 制御レジスターの各量子ビットとターゲット量子ビットにアダマールゲートを適用する。\n",
420 | "2. 制御レジスターとターゲット量子ビットの間にトフォリ(制御-制御-NOT)ゲートを適用する。これはQuantumCircuitの`ccx`メソッドを使うか、`qiskit.circuit.library`から`CCXGate`をインポートして使用することで実現できます。\n",
421 | "3. ターゲット量子ビットに$S$ゲートを適用する。\n",
422 | "4. ステップ2と同じ制御とターゲットで、別のトフォリゲートを適用する。\n",
423 | "5. 再び、制御レジスターとターゲットレジスターにアダマールゲートを適用する。\n",
424 | "6. 制御レジスターを測定して、古典レジスターに入れる。"
425 | ]
426 | },
427 | {
428 | "cell_type": "code",
429 | "execution_count": null,
430 | "metadata": {},
431 | "outputs": [],
432 | "source": [
433 | "def trial(\n",
434 | " circuit: QuantumCircuit,\n",
435 | " target: QuantumRegister,\n",
436 | " controls: QuantumRegister,\n",
437 | " measures: ClassicalRegister,\n",
438 | "):\n",
439 | " \"\"\"Probabilistically perform Rx(theta) on the target, where cos(theta) = 3/5.\"\"\"\n",
440 | "\n",
441 | " ####### your code goes here #######\n",
442 | "\n",
443 | "\n",
444 | "qc = base.copy_empty_like()\n",
445 | "trial(qc, target, controls, mid_measure)\n",
446 | "qc.draw(\"mpl\", cregbundle=False)"
447 | ]
448 | },
449 | {
450 | "cell_type": "code",
451 | "execution_count": null,
452 | "metadata": {},
453 | "outputs": [],
454 | "source": [
455 | "# Submit your circuit\n",
456 | "from qc_grader.challenges.spring_2023 import grade_ex1c\n",
457 | "\n",
458 | "grade_ex1c(qc)"
459 | ]
460 | },
461 | {
462 | "cell_type": "markdown",
463 | "metadata": {},
464 | "source": [
465 | "### Exercise 3"
466 | ]
467 | },
468 | {
469 | "cell_type": "markdown",
470 | "metadata": {},
471 | "source": [
472 | "次の作業は測定値のチェックです。制御ビットの測定値が2つとも $|0\\rangle$ の場合、適用されるゲートは$R_X(\\theta)$で、$\\cos(\\theta) = \\frac{3}{5}$です。測定値のいずれかが $|1\\rangle$ であれば、適用されるゲートは単に$X$であり失敗を示します。したがって、対象となる量子ビットのコヒーレンスを乱すことなく、測定値から正しいゲートを適用したかどうかを知ることができるのです。"
473 | ]
474 | },
475 | {
476 | "cell_type": "markdown",
477 | "metadata": {},
478 | "source": [
479 | "失敗した場合は、量子ビットをリセットしてもう一度やり直す必要があります。 失敗した場合に何が適用するかがわかっているので、一般的なハードウェアのリセットを使わなくても、この知識を使って効率的にリセットを実行することができます。2つの補助量子ビットについては、それぞれの測定値が $1$ であることを条件として、 $X$ ゲートを適用すれば良いのです。"
480 | ]
481 | },
482 | {
483 | "cell_type": "markdown",
484 | "metadata": {},
485 | "source": [
486 | "次のセルに`reset_controls`関数の中身を埋めて、次のステップで回路を変更できるようにしてください。\n",
487 | "\n",
488 | "1. `measures`レジスターの最初のビットが1の場合、最初の制御量子ビットに$X$ゲートを適用する。\n",
489 | "2. `measures`レジスターの2番目のビットが1の場合、2番目の制御量子ビットに$X$ゲートを適用する。"
490 | ]
491 | },
492 | {
493 | "cell_type": "code",
494 | "execution_count": null,
495 | "metadata": {},
496 | "outputs": [],
497 | "source": [
498 | "def reset_controls(\n",
499 | " circuit: QuantumCircuit, controls: QuantumRegister, measures: ClassicalRegister\n",
500 | "):\n",
501 | " \"\"\"Reset the control qubits if they are in |1>.\"\"\"\n",
502 | "\n",
503 | " ####### your code goes here #######\n",
504 | "\n",
505 | "\n",
506 | "qc = base.copy_empty_like()\n",
507 | "trial(qc, target, controls, mid_measure)\n",
508 | "reset_controls(qc, controls, mid_measure)\n",
509 | "qc.measure(controls, mid_measure)\n",
510 | "qc.draw(\"mpl\", cregbundle=False)"
511 | ]
512 | },
513 | {
514 | "cell_type": "code",
515 | "execution_count": null,
516 | "metadata": {},
517 | "outputs": [],
518 | "source": [
519 | "# Submit your circuit\n",
520 | "from qc_grader.challenges.spring_2023 import grade_ex1d\n",
521 | "\n",
522 | "grade_ex1d(qc)"
523 | ]
524 | },
525 | {
526 | "cell_type": "markdown",
527 | "metadata": {},
528 | "source": [
529 | "あとは、条件が満たされなかった場合に、回路の実行を繰り返すだけです。\n",
530 | "最後のExerciseでは、現在のDynamic circuitのサポートにおける2つの問題点を解決する必要があります。\n",
531 | "\n",
532 | "最初の問題は、Qiskitが現在、古典ビットに対するいかなる算術・論理演算の実行もサポートしていないことです。特に古典レジスターが特定の値を持って*いない*ことをチェックする機能はサポートしていません。現状、回路途中の測定値がビット列`00`で*ない*場合のみ、試行を繰り返す必要があります。この問題を回避するために、測定値が `00` に等しいことを条件とする if 文を作成し、空のブロックを**パス**して、**else** 分岐を使用して測定値が `00` でない場合に必要な論理を実行することになります。\n",
533 | "\n",
534 | "2つ目の問題は、現在、私たちのハードウェアがループをサポートしていないことです。そのため、真の意味で成功するまで繰り返すループを実行することができません。そこで、この問題を解決するために、試行回路を一定回数だけ繰り返すことにします。"
535 | ]
536 | },
537 | {
538 | "cell_type": "markdown",
539 | "metadata": {},
540 | "source": [
541 | "### Exercise 4\n",
542 | "\n",
543 | "以下のコードセルに、シンドローム量子ビットの測定で試行を繰り返す必要があると判断された場合に実行されるロジックを `else` ブロックに記入してください。\n",
544 | "\n",
545 | "1. ターゲット量子ビットをゼロ状態にリセットする。(すでに1の状態であることを知っていることを思い出してください)\n",
546 | "2. 回路上の `trial` 関数を再び呼び出す。"
547 | ]
548 | },
549 | {
550 | "cell_type": "code",
551 | "execution_count": null,
552 | "metadata": {},
553 | "outputs": [],
554 | "source": [
555 | "# Set the maximum number of trials\n",
556 | "max_trials = 2\n",
557 | "\n",
558 | "# Create a clean circuit with the same structure (bits, registers, etc)\n",
559 | "# as the initial base we set up.\n",
560 | "circuit = base.copy_empty_like()\n",
561 | "\n",
562 | "# The first trial does not need to reset its inputs, since the controls\n",
563 | "# are guaranteed to start in the |0> state.\n",
564 | "trial(circuit, target, controls, mid_measure)\n",
565 | "\n",
566 | "# Manually add the rest of the trials. In the future, we will be\n",
567 | "# able to use a dynamic `while` loop to do this, but for now, we\n",
568 | "# statically add each loop iteration with a manual condition check\n",
569 | "# on each one. This involves more classical synchronizations than\n",
570 | "# the while loop, but will suffice for now.\n",
571 | "for _ in range(max_trials - 1):\n",
572 | " reset_controls(circuit, controls, mid_measure)\n",
573 | " with circuit.if_test((mid_measure, 0b00)) as else_:\n",
574 | " # This is the success path, but Qiskit can't directly\n",
575 | " # represent a negative condition yet, so we have an\n",
576 | " # empty `true` block in order to use the `else` branch.\n",
577 | " pass\n",
578 | " with else_:\n",
579 | " ####### your code goes here #######\n",
580 | "\n",
581 | "\n",
582 | "# We need to measure the control qubits again to ensure we\n",
583 | "# get their final results; this is a hardware limitation.\n",
584 | "circuit.measure(controls, mid_measure)\n",
585 | "\n",
586 | "# Finally, let's measure our target, to check that we're\n",
587 | "# getting the rotation we desired.\n",
588 | "circuit.measure(target, final_measure)\n",
589 | "\n",
590 | "circuit.draw(\"mpl\", cregbundle=False)"
591 | ]
592 | },
593 | {
594 | "cell_type": "code",
595 | "execution_count": null,
596 | "metadata": {},
597 | "outputs": [],
598 | "source": [
599 | "# Submit your circuit\n",
600 | "from qc_grader.challenges.spring_2023 import grade_ex1e\n",
601 | "\n",
602 | "grade_ex1e(circuit)"
603 | ]
604 | },
605 | {
606 | "cell_type": "markdown",
607 | "metadata": {},
608 | "source": [
609 | "シミュレーター上で回路を実行しましょう。"
610 | ]
611 | },
612 | {
613 | "cell_type": "code",
614 | "execution_count": null,
615 | "metadata": {},
616 | "outputs": [],
617 | "source": [
618 | "sim = AerSimulator()\n",
619 | "job = sim.run(circuit, shots=1000)\n",
620 | "result = job.result()\n",
621 | "counts = result.get_counts()\n",
622 | "\n",
623 | "plot_histogram(counts)"
624 | ]
625 | },
626 | {
627 | "cell_type": "markdown",
628 | "metadata": {},
629 | "source": [
630 | "成功すると、結果は、2つの制御ビットの測定値が`00`の状態で終了します。うまくいかない場合は、Discord Channelに結果について投稿し、他の参加者と協力して、結果の意味や理由を理解することをお勧めします。"
631 | ]
632 | },
633 | {
634 | "cell_type": "markdown",
635 | "metadata": {},
636 | "source": [
637 | "## ハードウェア上での実行\n",
638 | "\n",
639 | "作成した回路を実際のハードウェアで動かしてみましょう!今回は、Dynamic circuit用に特別に調整された27qubitのPeekskillデバイスを使用します。しかし、実際のハードウェアで動かすのには時間がかかり、時にはエラーが発生することもあることを忘れないでください。他のChallenge参加者と渋滞の原因になるので、**このセルを何度も実行しないでください**。"
640 | ]
641 | },
642 | {
643 | "cell_type": "code",
644 | "execution_count": null,
645 | "metadata": {},
646 | "outputs": [],
647 | "source": [
648 | "from qiskit_ibm_provider import IBMProvider\n",
649 | "\n",
650 | "provider = IBMProvider()"
651 | ]
652 | },
653 | {
654 | "cell_type": "code",
655 | "execution_count": null,
656 | "metadata": {},
657 | "outputs": [],
658 | "source": [
659 | "hub = \"YOUR_HUB\"\n",
660 | "group = \"YOUR_GROUP\"\n",
661 | "project = \"YOUR_PROJECT\"\n",
662 | "\n",
663 | "backend_name = \"ibm_peekskill\"\n",
664 | "backend = provider.get_backend(backend_name, instance=f\"{hub}/{group}/{project}\")"
665 | ]
666 | },
667 | {
668 | "cell_type": "code",
669 | "execution_count": null,
670 | "metadata": {},
671 | "outputs": [],
672 | "source": [
673 | "from qiskit import transpile\n",
674 | "\n",
675 | "qc_transpiled = transpile(circuit, backend)\n",
676 | "job = backend.run(qc_transpiled, shots=1000, dynamic=True)"
677 | ]
678 | },
679 | {
680 | "cell_type": "code",
681 | "execution_count": null,
682 | "metadata": {},
683 | "outputs": [],
684 | "source": [
685 | "counts = job.result().get_counts()\n",
686 | "\n",
687 | "plot_histogram(counts)"
688 | ]
689 | },
690 | {
691 | "cell_type": "markdown",
692 | "metadata": {},
693 | "source": [
694 | "## おめでとうございます!\n",
695 | "\n",
696 | "最初のLabが終了しました!Dynamic circuitについてより深く理解できたので、次のLabに進み、応用とより高度な特性について学び始めてください。頑張ってください!"
697 | ]
698 | }
699 | ],
700 | "metadata": {
701 | "kernelspec": {
702 | "display_name": "Python 3",
703 | "language": "python",
704 | "name": "python3"
705 | },
706 | "language_info": {
707 | "codemirror_mode": {
708 | "name": "ipython",
709 | "version": 3
710 | },
711 | "file_extension": ".py",
712 | "mimetype": "text/x-python",
713 | "name": "python",
714 | "nbconvert_exporter": "python",
715 | "pygments_lexer": "ipython3",
716 | "version": "3.8.5"
717 | },
718 | "widgets": {
719 | "application/vnd.jupyter.widget-state+json": {
720 | "state": {},
721 | "version_major": 2,
722 | "version_minor": 0
723 | }
724 | }
725 | },
726 | "nbformat": 4,
727 | "nbformat_minor": 5
728 | }
729 |
--------------------------------------------------------------------------------
/content/lab_1/lab1-ko.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "dfb2ccb8",
6 | "metadata": {},
7 | "source": [
8 | "# IBM Quantum Challenge: Spring 2023"
9 | ]
10 | },
11 | {
12 | "cell_type": "markdown",
13 | "id": "f5055920",
14 | "metadata": {},
15 | "source": [
16 | "## 첫 단계"
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "id": "b4966066",
22 | "metadata": {},
23 | "source": [
24 | "IBM Quantum Challenge: Spring 2023에 오신 것을 환영합니다!\n",
25 | "\n",
26 | "이번 IBM Quantum Challenge의 주제는 동적 회로 (Dynamic Circuit) 이고 이번 챌린지의 첫 번째 랩 입니다. 이번 랩을 진행 하면서 몇 가지의 문제를 완료하셔야 합니다. 이 소개 섹션에서는 연습 문제들을 완료하는데 도움이 되는 간략한 개요를 제공합니다. 이전 챌린지를 \n",
27 | "참여 하셨다면 이 자료는 좋은 복습 자료가 될 것입니다.\n",
28 | "\n",
29 | "모든 연습 문제에는 튜토리얼 컨탠츠, 사전 작성된 코드 블록 및 사용자가 직접 Qiskit 코드를 입력해야 하는 연습 문제 코드 블록이 포함되어 있습니다. 연습 문제를 완료하는 데 필요한 코드는 _\"### Your code goes here ###\"_ 주석이 있는 줄 아래에 입력해야 합니다.\n",
30 | "\n",
31 | "새로운 코드를 작성하지 않았더라도 모든 코드 셀을 실행해야 하며, 채점자 (grader) 을 실행하여 답안을 제출할 때 모든 코드가 최신 상태로 유지되도록 해야 합니다."
32 | ]
33 | },
34 | {
35 | "cell_type": "markdown",
36 | "id": "46e89268",
37 | "metadata": {
38 | "tags": []
39 | },
40 | "source": [
41 | "### 맛보기 예제\n",
42 | "\n",
43 | "아래 셀에서 우리는 단일 큐비트와 단일 고전적 비트로 회로를 구성합니다. 첫 번째 작업은 큐비트에서 하다마드 (Hadamard) 게이트를 수행한 다음 측정하여 결과를 클래식 비트에 저장하는 것입니다. 이번 예제에서는 코드가 이미 입력되어 있으며 두 줄의 시작 부분에서 `#` 을 제거하기만 하면 됩니다."
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": null,
49 | "id": "d3195c89",
50 | "metadata": {
51 | "tags": []
52 | },
53 | "outputs": [],
54 | "source": [
55 | "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
56 | "\n",
57 | "qr = QuantumRegister(1)\n",
58 | "cr = ClassicalRegister(1)\n",
59 | "qc = QuantumCircuit(qr, cr)\n",
60 | "\n",
61 | "####### your code goes here #######\n",
62 | "\n",
63 | "# qc.h(qr[0])\n",
64 | "# qc.measure(qr[0], cr[0])\n",
65 | "\n",
66 | "\n",
67 | "qc.draw(\"mpl\")"
68 | ]
69 | },
70 | {
71 | "cell_type": "markdown",
72 | "id": "5c2a3395",
73 | "metadata": {},
74 | "source": [
75 | "잘했습니다! 각 연습문제가 끝난 후에 작성된 답안이 맞는지 확인하는 작업이 필요합니다. 이를 위해, 단순히 채점자 셀을 실행합니다.\n",
76 | "\n",
77 | "한번 실행 해 봅시다. 다음 셀에서는 변수 `answer_0`에 대한 정수 값을 설정할 것을 요청합니다. 정수가 1에서 5 사이이면 채점자가 정답이 올바르다는 Congratulation 메시지를 반환합니다. 다른 숫자를 입력하면 반대되는 메시지가 표시됩니다.\n",
78 | "\n",
79 | "원하는 대로 답을 설정한 다음 등급 셀을 실행하여 결과를 확인해봅시다. 재미 삼아 서로 다른 번호로 여러 번 시도해볼 수 있습니다."
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": null,
85 | "id": "a5100dd1",
86 | "metadata": {},
87 | "outputs": [],
88 | "source": [
89 | "answer_0: int\n",
90 | "answer_0 = 500\n",
91 | "\n",
92 | "##### Hint: Remember to run this cell after changing your value ###"
93 | ]
94 | },
95 | {
96 | "cell_type": "code",
97 | "execution_count": null,
98 | "id": "35f09765",
99 | "metadata": {},
100 | "outputs": [],
101 | "source": [
102 | "# Grader Cell: Run this to submit your answer\n",
103 | "\n",
104 | "from qc_grader.challenges.spring_2023 import grade_ex1a\n",
105 | "\n",
106 | "grade_ex1a(answer_0)"
107 | ]
108 | },
109 | {
110 | "cell_type": "markdown",
111 | "id": "a95432dc",
112 | "metadata": {},
113 | "source": [
114 | "Now you're all set to start this challenge. Good luck and have fun!"
115 | ]
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "id": "c708f5d1",
120 | "metadata": {},
121 | "source": [
122 | "이제 여러분은 이 챌린지를 시작할 준비가 되었습니다. 행운을 빌고 즐거운 양자 여행 되세요!"
123 | ]
124 | },
125 | {
126 | "cell_type": "markdown",
127 | "id": "312c9431-a3fc-4448-9001-fb9d41ea6a44",
128 | "metadata": {},
129 | "source": [
130 | "# 동적 회로 소개 및 성공할 때까지 반복하기"
131 | ]
132 | },
133 | {
134 | "cell_type": "markdown",
135 | "id": "f7212735",
136 | "metadata": {},
137 | "source": [
138 | "## 소개"
139 | ]
140 | },
141 | {
142 | "cell_type": "markdown",
143 | "id": "d3fb8748",
144 | "metadata": {},
145 | "source": [
146 | "[Qiskit textbook,](https://learn.qiskit.org/course/ch-algorithms/quantum-circuits)에 따르면\n",
147 | ">_\"양자 회로는 큐비트에 대한 결맞음 양자 연산으로 구성된 계산 루틴입니다... 이것은 양자 게이트, 측정 및 재설정의 순서가 지정된 시퀀스이며, 이 모든 것이 실시간 고전적 계산에 의해 조건적이거나 데이터를 사용할 수 있습니다\"_\n",
148 | "\n",
149 | "정의의 마지막 부분에 대해 잘 모를 수도 있지만 동적 회로와 모든 관련이 있습니다. 일반적으로 양자 회로에 대해 말할 때 우리는 명시적으로 말하지 않더라도 _정적 (static)_ 양자 회로를 말합니다. 그렇다면 동적 회로란 무엇일까요?\n",
150 | "\n",
151 | "**동적 회로**는 중간 회로 측정값을 포함하는 양자 회로이며, 측정 결과는 회로의 후반부에서 양자 게이트를 조절하는 데 사용됩니다. 고전적인 측정 결과에 대한 미래 양자 연산을 조건화하는 능력은 고전적인 피드포워드 (feedforward)로 알려져 있습니다.\n",
152 | "\n",
153 | "고전적인 피드포워드가 왜 필요할까요? 예를 들어 Qiskit에서 [`reset`](https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.reset.html) 작업을 사용해 본 적이 있으면 익숙한, 조건부 재설정 작업을 고려해 보십시다. 초기 상태에 관계없이 큐비트를 0으로 재설정하는 비 유니타리 연산이지만, 이미 측정된 큐비트에 대해 조건부 재설정 연산을 수행하여 큐비트가 측정된 값이 1인 경우에만 비트 플립 X 게이트를 적용하여 0으로 재설정합니다."
154 | ]
155 | },
156 | {
157 | "cell_type": "markdown",
158 | "id": "60ea3680",
159 | "metadata": {},
160 | "source": [
161 | "\n",
162 | "
\n",
163 | ""
164 | ]
165 | },
166 | {
167 | "cell_type": "markdown",
168 | "id": "caea194a",
169 | "metadata": {},
170 | "source": [
171 | "즉, 동적 회로란 if 문과 while 루프와 같은 제어 흐름을 포함하는 양자 회로로, 조건부는 이전의 큐비트 측정 결과로부터 계산되고 조건부 연산은 양자 게이트를 포함합니다."
172 | ]
173 | },
174 | {
175 | "cell_type": "markdown",
176 | "id": "b52cef83-0393-4aba-9df0-ff54dff0bc04",
177 | "metadata": {},
178 | "source": [
179 | "## Hello Dynamic Circuit World"
180 | ]
181 | },
182 | {
183 | "cell_type": "markdown",
184 | "id": "1291e604",
185 | "metadata": {},
186 | "source": [
187 | "IBM Quantum 하드웨어는 이미 한동안 중간 회로 측정 및 재설정 기능을 지원했습니다. 그러나 기존 피드포워드에 대한 지원을 추가하려면 제어 시스템 및 관련 소프트웨어 스택을 대폭 재설계해야 했습니다. 따라서 작년(2022년)에 부터 동적 회로에 대한 완전한 지원이 도입되었습니다.\n",
188 | "\n",
189 | "Qiskit에서는 동적 회로를 프로그래밍하기 위한 구문이 여러 번 반복되었으며, 아직 완전한 지원이 구현되지 않았습니다. 현재 동적 회로의 모든 기능에 액세스할 수 있는 유일한 방법은 OpenQASM 3로 작성된 프로그램을 제출하는 것입니다. 그럼에도 불구하고, 우리는 Qiskit에서 현재 사용 가능한 것만을 사용할 것입니다.\n",
190 | "\n",
191 | "Qiskit의 이전 버전에서는 [`c_if()`](https://qiskit.org/documentation/stubs/qiskit.circuit.Instruction.c_if.html) 명령어를 소개했지만, 이 문법은 더 유연한 QuantumCircuit의 [`if_test()`](https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.if_test.html) 메서드를 선호하는 방향으로 사용이 점차 줄어들 예정입니다. 이 메서드는 이번 챌린지에서 주로 사용할 것입니다.\n",
192 | "\n",
193 | "시작을 위해, 이 함수를 사용하는 간단한 예를 복습해봅시다. 다음 단계를 통해 조건부 reset 작업을 보여주는 회로를 만들어 보겠습니다:\n",
194 | "\n",
195 | "1. 1개의 큐비트와 2개의 고전적 비트로 회로를 초기화합니다. ($q_{0}$, $b_{0}$ 그리고 $b_{1}$)\n",
196 | "2. $q_{0}$ 에 Hadamard 게이트를 적용합니다.\n",
197 | "3. 그 큐비트를 측정하고 결과를 $b_{0}$ 에 저장합니다.\n",
198 | "4. $b_{0}$ 이 1과 같을 때 조건부로 `if_test` 블록을 시작합니다.\n",
199 | "5. `if_test` 블록에서, 조건이 충족되면 수행할 연산을 지정합니다. 이 경우, $q_{0}$ 를 0 상태로 전환하는 것입니다.\n",
200 | "6. 항상 0을 얻는지 확인하기 위해 $q_0$ 을 다시 측정하고 $b_{1}$ 에 저장합니다."
201 | ]
202 | },
203 | {
204 | "cell_type": "code",
205 | "execution_count": null,
206 | "id": "10d6953d",
207 | "metadata": {},
208 | "outputs": [],
209 | "source": [
210 | "from qiskit import QuantumCircuit\n",
211 | "from qiskit.circuit import QuantumRegister, ClassicalRegister\n",
212 | "\n",
213 | "qr = QuantumRegister(1)\n",
214 | "cr = ClassicalRegister(2)\n",
215 | "qc = QuantumCircuit(qr, cr)\n",
216 | "\n",
217 | "# unpack the qubit and classical bits from the registers\n",
218 | "(q0,) = qr\n",
219 | "b0, b1 = cr\n",
220 | "\n",
221 | "# apply Hadamard\n",
222 | "qc.h(q0)\n",
223 | "# measure\n",
224 | "qc.measure(q0, b0)\n",
225 | "\n",
226 | "# begin if test block. the contents of the block are executed if b0 == 1\n",
227 | "with qc.if_test((b0, 1)):\n",
228 | " # if the condition is satisfied (b0 == 1), then flip the bit back to 0\n",
229 | " qc.x(q0)\n",
230 | "# finally, measure q0 again\n",
231 | "qc.measure(q0, b1)\n",
232 | "\n",
233 | "qc.draw(output=\"mpl\", idle_wires=False)"
234 | ]
235 | },
236 | {
237 | "cell_type": "markdown",
238 | "id": "fa3da6a2",
239 | "metadata": {},
240 | "source": [
241 | "이제 회로가 구축되었으므로 회로를 여러 번 실행하여 항상 예상하는 결과값을 얻을 수 있는지 확인해 보겠습니다. 첫 번째 측정값은 0 또는 1일 수 있지만 두 번째 측정값은 항상 0이어야 합니다."
242 | ]
243 | },
244 | {
245 | "cell_type": "code",
246 | "execution_count": null,
247 | "id": "06a4eee8",
248 | "metadata": {},
249 | "outputs": [],
250 | "source": [
251 | "from qiskit_aer import AerSimulator\n",
252 | "\n",
253 | "# initialize the simulator\n",
254 | "backend_sim = AerSimulator()\n",
255 | "\n",
256 | "# run the circuit\n",
257 | "reset_sim_job = backend_sim.run(qc)\n",
258 | "# get the results\n",
259 | "reset_sim_result = reset_sim_job.result()\n",
260 | "# retrieve the bitstring counts\n",
261 | "reset_sim_counts = reset_sim_result.get_counts()\n",
262 | "\n",
263 | "print(f\"Counts: {reset_sim_counts}\")"
264 | ]
265 | },
266 | {
267 | "cell_type": "markdown",
268 | "id": "388ce901",
269 | "metadata": {},
270 | "source": [
271 | "예상대로 첫 번째 비트는 때때로 0이고 때로는 1이지만 두 번째 비트는 항상 0입니다 (Qiskit에서 리틀 엔디언 (little-endian) 비트 순서를 사용하므로 오른쪽 끝 비트가 첫 번째 비트이고 왼쪽 끝 비트가 마지막 비트입니다)."
272 | ]
273 | },
274 | {
275 | "cell_type": "code",
276 | "execution_count": null,
277 | "id": "439359c9",
278 | "metadata": {},
279 | "outputs": [],
280 | "source": [
281 | "from qiskit.visualization import *\n",
282 | "\n",
283 | "# plot histogram\n",
284 | "plot_histogram(reset_sim_counts)"
285 | ]
286 | },
287 | {
288 | "cell_type": "markdown",
289 | "id": "de501c69",
290 | "metadata": {},
291 | "source": [
292 | "이제 첫 번째 동적 회로를 구축할 준비가 되었습니다!"
293 | ]
294 | },
295 | {
296 | "cell_type": "markdown",
297 | "id": "f62264b8",
298 | "metadata": {},
299 | "source": [
300 | "### **연습 문제 1**"
301 | ]
302 | },
303 | {
304 | "cell_type": "markdown",
305 | "id": "da73cc7b",
306 | "metadata": {},
307 | "source": [
308 | "다음 단계로 나아가 봅시다. 첫 번째 과제는 두 큐비트 회로를 설계하는 것이 될 것입니다. 이 경우, 목표는 $q_{0}$ 의 값에 따라 $q_{1}$ 에 다르게 작용하는 것입니다. $q_{0}$ 의 측정이 0을 읽으면 $q_{1}$ 에 $X$ 게이트를 적용합시다. 1을 읽으면 대신 $q_{1}$ 에 하다마드 게이트를 적용합니다.\n",
309 | "\n",
310 | "$q_{0}$ 의 값을 무작위로 만들기 위해, 우리가 할 첫 번째 것은 해당하는 큐비트에 하다마드를 적용하는 것입니다. 다음으로, 우리는 $q_{0}$ 를 $b_{0}$ 에 측정합니다. 그 후에, 동적 마법이 일어나게 되며, 마지막으로, $q_{1}$ 이 측정됩니다."
311 | ]
312 | },
313 | {
314 | "cell_type": "markdown",
315 | "id": "fd70af27",
316 | "metadata": {},
317 | "source": [
318 | "이 연습 문제를 위해 [`if_test()`](https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.if_test.html) 문서를 읽어보시기 바랍니다."
319 | ]
320 | },
321 | {
322 | "cell_type": "code",
323 | "execution_count": null,
324 | "id": "97acd850",
325 | "metadata": {},
326 | "outputs": [],
327 | "source": [
328 | "qr = QuantumRegister(2)\n",
329 | "cr = ClassicalRegister(2)\n",
330 | "qc = QuantumCircuit(qr, cr)\n",
331 | "\n",
332 | "q0, q1 = qr\n",
333 | "b0, b1 = cr\n",
334 | "\n",
335 | "qc.h(q0)\n",
336 | "qc.measure(q0, b0)\n",
337 | "\n",
338 | "####### your code goes here #######\n",
339 | "\n",
340 | "\n",
341 | "qc.measure(q1, b1)\n",
342 | "qc.draw(output=\"mpl\", idle_wires=False)"
343 | ]
344 | },
345 | {
346 | "cell_type": "markdown",
347 | "id": "fff212ad",
348 | "metadata": {},
349 | "source": [
350 | "선택적으로 다음 셀을 실행하여 회로가 예상대로 작동하는지 확인할 수 있습니다.\n",
351 | ">팁: 실행하기 전에 회로의 예상되는 가능한 결과를 생각해 보세요."
352 | ]
353 | },
354 | {
355 | "cell_type": "code",
356 | "execution_count": null,
357 | "id": "e25f4018",
358 | "metadata": {},
359 | "outputs": [],
360 | "source": [
361 | "backend_sim = AerSimulator()\n",
362 | "\n",
363 | "job_1 = backend_sim.run(qc)\n",
364 | "result_1 = job_1.result()\n",
365 | "counts_1 = result_1.get_counts()\n",
366 | "\n",
367 | "print(f\"Counts: {counts_1}\")"
368 | ]
369 | },
370 | {
371 | "cell_type": "code",
372 | "execution_count": null,
373 | "id": "52ffa93c",
374 | "metadata": {},
375 | "outputs": [],
376 | "source": [
377 | "# Submit your circuit\n",
378 | "\n",
379 | "from qc_grader.challenges.spring_2023 import grade_ex1b\n",
380 | "\n",
381 | "grade_ex1b(qc)"
382 | ]
383 | },
384 | {
385 | "cell_type": "markdown",
386 | "id": "accf02df-d743-4550-a165-eb7fa5563b92",
387 | "metadata": {},
388 | "source": [
389 | "## 성공할 때 가지 반복하기"
390 | ]
391 | },
392 | {
393 | "cell_type": "markdown",
394 | "id": "5b636a19",
395 | "metadata": {},
396 | "source": [
397 | "때때로 진행의 결과는 무작위적이며 원하는 결과가 나오지 않을 수도 있습니다. 이런 경우에 무엇을 할 수 까요? 자, 다시 시도해 보세요! 원하는 결과가 확률이 0이 아닌 이상 과정을 반복하게 되면 원하는 결과가 나오게 됩니다. 종종, 조금의 반복만 필요할 수도 있습니다.\n",
398 | "\n",
399 | "이 섹션에서는 성공할 때까지 반복 아이디어를 사용하여 유한 게이트 세트 $\\{H,\\,X,\\,S,\\,\\text{Toffoli}\\}$에서 $R_X(\\theta)$ 게이트를 구축할 것입니다. 여기서 $\\theta / \\pi$ 는 무리수 입니다. 구체적으로, $\\cos\\theta = \\frac35$ 를 구축하게 됩니다. 이 구조는 Nielsen and Chuang, _Quantum Computation and Quantum Information_, 10th anniversary edition, Exercise 4.41 에서 수정되었으며 위에 주어진 유한 게이트 세트의 범용성을 보여줍니다.\n",
400 | "\n",
401 | "이 구조는 3개의 큐비트로 작동하는 회로를 만들게 됩니다. 큐비트 중 하나는 target 큐비트이며 우리의 목표는 이 target 큐비트에서 $R_X(\\theta)$ 를 작동하는 것 입니다. 다른 두 큐비트는 우리가 측정할 \"syndrome\" 큐비트이며 측정 결과는 우리의 작업이 성공적이었는지 여부를 알려줍니다. 두 syndrome 큐비트가 모두 0이면 게이트가 성공적으로 수행되었음을 알 수 있습니다. 그렇지 않으면 큐비트를 재설정하고 다시 시도하게 됩니다. 측정 결과에 따라 회로의 반복을 조절하려면 동적 회로가 필요합니다."
402 | ]
403 | },
404 | {
405 | "cell_type": "markdown",
406 | "id": "319aa2d5",
407 | "metadata": {},
408 | "source": [
409 | "### 연습 문제 2"
410 | ]
411 | },
412 | {
413 | "cell_type": "markdown",
414 | "id": "e744fd1b",
415 | "metadata": {},
416 | "source": [
417 | "이 섹션의 첫 번째 목표는 해당 회로를 반환하는 함수를 만드는 것입니다. 다음은 회로의 모양에 대한 이미지는 아래와 같습니다:"
418 | ]
419 | },
420 | {
421 | "cell_type": "markdown",
422 | "id": "1eaf0de0",
423 | "metadata": {},
424 | "source": [
425 | "\n",
426 | "
\n",
427 | ""
428 | ]
429 | },
430 | {
431 | "cell_type": "markdown",
432 | "id": "a0057b5c",
433 | "metadata": {},
434 | "source": [
435 | "사용자가 쉽게 사용할 수 있도록 필요한 요소를 사용하여 \"기본 (basde)\" 회로를 설정합니다. 이 실험실에서 작성할 기능은 회로를 입력으로 사용하여 제자리에서 수정합니다. 만약 새 회로가 필요하다면 기본 회로를 복사하게 됩니다."
436 | ]
437 | },
438 | {
439 | "cell_type": "code",
440 | "execution_count": null,
441 | "id": "a5587d76",
442 | "metadata": {},
443 | "outputs": [],
444 | "source": [
445 | "controls = QuantumRegister(2, name=\"control\")\n",
446 | "target = QuantumRegister(1, name=\"target\")\n",
447 | "\n",
448 | "mid_measure = ClassicalRegister(2, name=\"mid\")\n",
449 | "final_measure = ClassicalRegister(1, name=\"final\")\n",
450 | "\n",
451 | "base = QuantumCircuit(controls, target, mid_measure, final_measure)"
452 | ]
453 | },
454 | {
455 | "cell_type": "markdown",
456 | "id": "976de85c",
457 | "metadata": {},
458 | "source": [
459 | "다음 셀에서 다음 단계를 수행하여 회로를 구성하도록 'trial' 함수를 완성합시다:\n",
460 | "\n",
461 | "1. control 레지스터의 각 큐비트와 target 큐비트에 하다마드 게이트를 적용합니다.\n",
462 | "2. conrol 레지스터와 target 큐비트 사이에 Toffoli(controlled-controlled-not) 게이트를 적용합니다. 이 작업은 QuantumCircuit의 `ccx` 방법을 사용하거나 `qiskit.circuit.library`에서 `CCXGate`를 불러와 수행할 수 있습니다.\n",
463 | "3. target 큐비트에 $S$ 게이트를 적용합니다\n",
464 | "4. 2단계와 동일한 control 및 target으로 다른 Topoli 게이트를 적용합니다.\n",
465 | "5. 다시 control 레지스터와 target 레지스터에 Hadamard를 적용합니다.\n",
466 | "6. control 레지스터를 고전적 레지스터로 측정합니다."
467 | ]
468 | },
469 | {
470 | "cell_type": "code",
471 | "execution_count": null,
472 | "id": "fc47a87d",
473 | "metadata": {},
474 | "outputs": [],
475 | "source": [
476 | "def trial(\n",
477 | " circuit: QuantumCircuit,\n",
478 | " target: QuantumRegister,\n",
479 | " controls: QuantumRegister,\n",
480 | " measures: ClassicalRegister,\n",
481 | "):\n",
482 | " \"\"\"Probabilistically perform Rx(theta) on the target, where cos(theta) = 3/5.\"\"\"\n",
483 | "\n",
484 | " ####### your code goes here #######\n",
485 | "\n",
486 | "\n",
487 | "qc = base.copy_empty_like()\n",
488 | "trial(qc, target, controls, mid_measure)\n",
489 | "qc.draw(\"mpl\", cregbundle=False)"
490 | ]
491 | },
492 | {
493 | "cell_type": "code",
494 | "execution_count": null,
495 | "id": "029c1c44",
496 | "metadata": {},
497 | "outputs": [],
498 | "source": [
499 | "# Submit your circuit\n",
500 | "from qc_grader.challenges.spring_2023 import grade_ex1c\n",
501 | "\n",
502 | "grade_ex1c(qc)"
503 | ]
504 | },
505 | {
506 | "cell_type": "markdown",
507 | "id": "72855e8b",
508 | "metadata": {},
509 | "source": [
510 | "### 연습 문제 3"
511 | ]
512 | },
513 | {
514 | "attachments": {},
515 | "cell_type": "markdown",
516 | "id": "e421924e",
517 | "metadata": {},
518 | "source": [
519 | "다음 작업으로는 측정값을 확인하는 것입니다. control 비트의 두 측정 모두 $|0\\rangle$을 반환하는 경우 적용된 게이트는 $R_X(\\theta)$ 이며, 구체적으로는 $\\cos(\\theta) = \\frac{3}{5}$ 입니다. 측정값 중 하나라도 $|1\\rangle$ 이면 적용된 게이트는 단순히 $X$ 게이트이며, 오류를 나타냅니다. 따라서, 측정을 통해 target 큐비트의 결맞음을 방해하지 않고 올바른 게이트를 적용했는지 여부를 알 수 있습니다."
520 | ]
521 | },
522 | {
523 | "cell_type": "markdown",
524 | "id": "7c1a4ee1",
525 | "metadata": {},
526 | "source": [
527 | "오류가 발생하면 큐비트를 재설정하고 다시 시작해야 합니다. 오류 발생 시 무엇이 적용되는지 알고 있으므로 일반적인 하드웨어 재설정을 사용하지 않고도 이 지식을 사용하여 효율적인 재설정을 수행할 수 있습니다. 두 개의 보조 큐비트의 경우, 각각의 측정값이 $1$ 이라는 조건하에는 단지 $X$ 게이트 입니다."
528 | ]
529 | },
530 | {
531 | "cell_type": "markdown",
532 | "id": "a40077b6",
533 | "metadata": {},
534 | "source": [
535 | "다음 셀에서 `reset_controls` 함수를 입력하여 다음 단계를 수행하여 회로를 수정합니다:\n",
536 | "\n",
537 | "1. `measures` 레지스터의 첫 번째 비트가 1이면 첫 번째 control 큐비트에 $X$ 게이트를 적용합니다.\n",
538 | "2. `measures` 레지스터의 두 번째 비트가 1이면 두 번째 control 큐비트에 $X$ 게이트를 적용합니다."
539 | ]
540 | },
541 | {
542 | "cell_type": "code",
543 | "execution_count": null,
544 | "id": "73ba4506",
545 | "metadata": {},
546 | "outputs": [],
547 | "source": [
548 | "def reset_controls(\n",
549 | " circuit: QuantumCircuit, controls: QuantumRegister, measures: ClassicalRegister\n",
550 | "):\n",
551 | " \"\"\"Reset the control qubits if they are in |1>.\"\"\"\n",
552 | "\n",
553 | " ####### your code goes here #######\n",
554 | "\n",
555 | "\n",
556 | "qc = base.copy_empty_like()\n",
557 | "trial(qc, target, controls, mid_measure)\n",
558 | "reset_controls(qc, controls, mid_measure)\n",
559 | "qc.measure(controls, mid_measure)\n",
560 | "qc.draw(\"mpl\", cregbundle=False)"
561 | ]
562 | },
563 | {
564 | "cell_type": "code",
565 | "execution_count": null,
566 | "id": "e6443405",
567 | "metadata": {},
568 | "outputs": [],
569 | "source": [
570 | "# Submit your circuit\n",
571 | "from qc_grader.challenges.spring_2023 import grade_ex1d\n",
572 | "\n",
573 | "grade_ex1d(qc)"
574 | ]
575 | },
576 | {
577 | "cell_type": "markdown",
578 | "id": "6c2c844e",
579 | "metadata": {},
580 | "source": [
581 | "이제 남은 일은 조건이 충족되지 않은 회로의 실행을 반복하는 것입니다.\n",
582 | "마지막 연습 문제에서는 현재 지원하는 동적 회로에 대한 두 가지 문제를 해결해야 합니다.\n",
583 | "\n",
584 | "첫 번째 문제는 Qiskit이 현재 고전적인 비트에 대한 산술 또는 논리 연산을 수행하는 것을 지원하지 않는다는 것입니다. 특히 고전적인 레지스터에 특정 값이 *없다*는 확인을 지원하지 않습니다. 우리 상황에서는 중간 회로 측정값이 비트 문자열 `00`이 아닌 경우에만 시행을 반복해야 합니다. 이 문제를 해결하기 위해 측정값이 `00`과 동일한 것을 조건으로 하는 if 문을 만들고 빈 블록을 **pass**한 다음 **else** branch를 사용하여 측정값이 `00` 이 *아닌* 경우에 원하는 논리를 수행합니다.\n",
585 | "\n",
586 | "두 번째 문제는 현재 하드웨어가 루프를 지원하지 않는다는 것입니다. 따라서 성공할 때까지 반복 루프를 실행할 수 없습니다. 우리는 시험 회로를 횟수를 지정하고 반복함으로써 이 문제를 해결할 것입니다."
587 | ]
588 | },
589 | {
590 | "cell_type": "markdown",
591 | "id": "1a3c5b4e",
592 | "metadata": {},
593 | "source": [
594 | "### 연습 문제 4\n",
595 | "\n",
596 | "아래의 코드 셀에서 `else` 블록에 syndrome 측정 결과에 따라 시행을 반복해야 하는 경우 수행해야 하는 논리를 입력합니다:\n",
597 | "\n",
598 | "1. target 큐비트를 0 상태로 재설정합니다. 하지만 이 큐비트가 1 상태라는 것을 이미 알고 있다는 것을 기억해야 합니다.\n",
599 | "2. 회로에 'trial' 함수를 다시 호출합니다."
600 | ]
601 | },
602 | {
603 | "cell_type": "code",
604 | "execution_count": null,
605 | "id": "4be1b959",
606 | "metadata": {},
607 | "outputs": [],
608 | "source": [
609 | "# Set the maximum number of trials\n",
610 | "max_trials = 2\n",
611 | "\n",
612 | "# Create a clean circuit with the same structure (bits, registers, etc)\n",
613 | "# as the initial base we set up.\n",
614 | "circuit = base.copy_empty_like()\n",
615 | "\n",
616 | "# The first trial does not need to reset its inputs, since the controls\n",
617 | "# are guaranteed to start in the |0> state.\n",
618 | "trial(circuit, target, controls, mid_measure)\n",
619 | "\n",
620 | "# Manually add the rest of the trials. In the future, we will be\n",
621 | "# able to use a dynamic `while` loop to do this, but for now, we\n",
622 | "# statically add each loop iteration with a manual condition check\n",
623 | "# on each one. This involves more classical synchronizations than\n",
624 | "# the while loop, but will suffice for now.\n",
625 | "for _ in range(max_trials - 1):\n",
626 | " reset_controls(circuit, controls, mid_measure)\n",
627 | " with circuit.if_test((mid_measure, 0b00)) as else_:\n",
628 | " # This is the success path, but Qiskit can't directly\n",
629 | " # represent a negative condition yet, so we have an\n",
630 | " # empty `true` block in order to use the `else` branch.\n",
631 | " pass\n",
632 | " with else_:\n",
633 | " ####### your code goes here #######\n",
634 | "\n",
635 | "\n",
636 | "# We need to measure the control qubits again to ensure we\n",
637 | "# get their final results; this is a hardware limitation.\n",
638 | "circuit.measure(controls, mid_measure)\n",
639 | "\n",
640 | "# Finally, let's measure our target, to check that we're\n",
641 | "# getting the rotation we desired.\n",
642 | "circuit.measure(target, final_measure)\n",
643 | "\n",
644 | "circuit.draw(\"mpl\", cregbundle=False)"
645 | ]
646 | },
647 | {
648 | "cell_type": "code",
649 | "execution_count": null,
650 | "id": "973b441d",
651 | "metadata": {},
652 | "outputs": [],
653 | "source": [
654 | "# Submit your circuit\n",
655 | "from qc_grader.challenges.spring_2023 import grade_ex1e\n",
656 | "\n",
657 | "grade_ex1e(circuit)"
658 | ]
659 | },
660 | {
661 | "cell_type": "markdown",
662 | "id": "0f84bb06",
663 | "metadata": {},
664 | "source": [
665 | "이 회로를 시뮬레이터에 실행해봅시다."
666 | ]
667 | },
668 | {
669 | "cell_type": "code",
670 | "execution_count": null,
671 | "id": "f576413c",
672 | "metadata": {},
673 | "outputs": [],
674 | "source": [
675 | "sim = AerSimulator()\n",
676 | "job = sim.run(circuit, shots=1000)\n",
677 | "result = job.result()\n",
678 | "counts = result.get_counts()\n",
679 | "\n",
680 | "plot_histogram(counts)"
681 | ]
682 | },
683 | {
684 | "cell_type": "markdown",
685 | "id": "1971f98e",
686 | "metadata": {},
687 | "source": [
688 | "두 컨트롤의 측정이 `00` 상태로 끝난 다면 성공적인 결과입니다. 결과에 문제가 있는 경우, 결과에 대해 디스코드 채널에 게시하여 다른 참가자들과 협력하고 결과가 의미하는 바와 결과를 얻는 이유를 이해하는 것이 좋습니다."
689 | ]
690 | },
691 | {
692 | "cell_type": "markdown",
693 | "id": "17cb07ef",
694 | "metadata": {},
695 | "source": [
696 | "## 하드웨어에 실행하기\n",
697 | "\n",
698 | "우리가 만든 회로를 실제 하드웨어에서 실행해 보겠습니다! 이를 위해 동적 회로를 위해 특별히 조정된 27큐비트 Peekskill 장치를 사용할 것입니다. 하지만 실제 하드웨어에서 실행하는 데는 시간이 걸리고 오류가 발생할 수 있습니다. 이러한 셀을 반복해서 **실행하지 마십시오**. 반복 실행은 다른 모든 챌린지 참가자들의 백업의 원인이 될 수 있습니다."
699 | ]
700 | },
701 | {
702 | "cell_type": "code",
703 | "execution_count": null,
704 | "id": "f917e10b",
705 | "metadata": {},
706 | "outputs": [],
707 | "source": [
708 | "from qiskit_ibm_provider import IBMProvider\n",
709 | "\n",
710 | "provider = IBMProvider()"
711 | ]
712 | },
713 | {
714 | "cell_type": "code",
715 | "execution_count": null,
716 | "id": "691dd8d8",
717 | "metadata": {},
718 | "outputs": [],
719 | "source": [
720 | "hub = \"YOUR_HUB\"\n",
721 | "group = \"YOUR_GROUP\"\n",
722 | "project = \"YOUR_PROJECT\"\n",
723 | "\n",
724 | "backend_name = \"ibm_peekskill\"\n",
725 | "backend = provider.get_backend(backend_name, instance=f\"{hub}/{group}/{project}\")"
726 | ]
727 | },
728 | {
729 | "cell_type": "code",
730 | "execution_count": null,
731 | "id": "57735462",
732 | "metadata": {},
733 | "outputs": [],
734 | "source": [
735 | "from qiskit import transpile\n",
736 | "\n",
737 | "qc_transpiled = transpile(circuit, backend)\n",
738 | "job = backend.run(qc_transpiled, shots=1000, dynamic=True)"
739 | ]
740 | },
741 | {
742 | "cell_type": "code",
743 | "execution_count": null,
744 | "id": "7ee1c832",
745 | "metadata": {},
746 | "outputs": [],
747 | "source": [
748 | "\n",
749 | "counts = job.result().get_counts()\n",
750 | "\n",
751 | "plot_histogram(counts)"
752 | ]
753 | },
754 | {
755 | "cell_type": "markdown",
756 | "id": "6acb6b58",
757 | "metadata": {},
758 | "source": [
759 | "## 축하합니다!\n",
760 | "\n",
761 | "첫 번째 랩의 끝에 도착했습니다! 이제 동적 회로에 대해 자세히 알아보았으니 다음 실습으로 이동하여 일부 활용과 고급 속성에 대해 알아보겠습니다. 행운을 빕니다!"
762 | ]
763 | },
764 | {
765 | "cell_type": "markdown",
766 | "id": "1046d14d",
767 | "metadata": {},
768 | "source": [
769 | "Translated by: Inho Choi @Inho Choi (Slack)"
770 | ]
771 | }
772 | ],
773 | "metadata": {
774 | "kernelspec": {
775 | "display_name": "Python 3 (ipykernel)",
776 | "language": "python",
777 | "name": "python3"
778 | },
779 | "language_info": {
780 | "codemirror_mode": {
781 | "name": "ipython",
782 | "version": 3
783 | },
784 | "file_extension": ".py",
785 | "mimetype": "text/x-python",
786 | "name": "python",
787 | "nbconvert_exporter": "python",
788 | "pygments_lexer": "ipython3",
789 | "version": "3.9.0"
790 | },
791 | "widgets": {
792 | "application/vnd.jupyter.widget-state+json": {
793 | "state": {},
794 | "version_major": 2,
795 | "version_minor": 0
796 | }
797 | }
798 | },
799 | "nbformat": 4,
800 | "nbformat_minor": 5
801 | }
802 |
--------------------------------------------------------------------------------
/content/lab_1/resources/circuitRx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qiskit-community/ibm-quantum-challenge-spring-2023/d9f62cab0e8f775b03a85e387b1ace2ef0124490/content/lab_1/resources/circuitRx.png
--------------------------------------------------------------------------------
/content/lab_1/resources/sketch-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qiskit-community/ibm-quantum-challenge-spring-2023/d9f62cab0e8f775b03a85e387b1ace2ef0124490/content/lab_1/resources/sketch-1.png
--------------------------------------------------------------------------------
/content/lab_2/lab2-es.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "0ac9dd0b-210c-470e-8313-5cf7f7c57b65",
6 | "metadata": {},
7 | "source": [
8 | "# Laboratorio 2: Teleportación cuántica\n",
9 | "\n",
10 | "Bienvenido a este laboratorio sobre teleportación cuántica en el que resolverás un problema que han tenido Alice y Bob. Relájate, ¡no es un problema de relación! Alice posee un qubit en un estado desconocido $\\lvert \\psi \\rangle$ y desea transferir este estado cuántico a Bob. Sin embargo, están muy separados y carecen de medios para transferir información cuántica directamente, solo información clásica. ¿Es posible lograr su objetivo?\n",
11 | "\n",
12 | "Resulta que si Alice y Bob comparten un par de qubits entrelazados, ella puede transferir su estado de qubit a Bob enviando dos bits de información clásica. Este proceso se conoce como teleportación porque, al final, Bob poseerá |ψ⟩ y Alice ya no lo tendrá."
13 | ]
14 | },
15 | {
16 | "cell_type": "markdown",
17 | "id": "11a966b2-a7c1-4584-87b2-1b8e4277f997",
18 | "metadata": {},
19 | "source": [
20 | "## Antecedentes\n",
21 | "\n",
22 | "La teleportación cuántica es un protocolo que permite la transferencia de información cuántica de un qubit a otro mediante entrelazamiento y comunicación clásica. Fue propuesto por Charles Bennett, Gilles Brassard, Claude Crépeau, Richard Jozsa, Asher Peres y William Wootters en 1993. El proceso no transmite el qubit en sí, sino que transfiere el estado cuántico del qubit de origen al qubit de destino.\n",
23 | "\n",
24 | "El protocolo requiere tres qubits:\n",
25 | "\n",
26 | "1. El qubit a teleportar (qubit de Alice)\n",
27 | "2. La mitad de un par de qubits entrelazados (el segundo qubit de Alice)\n",
28 | "3. La otra mitad del par entrelazado (qubit de Bob)\n",
29 | "\n",
30 | "El protocolo se puede resumir en los siguientes pasos:\n",
31 | "\n",
32 | "1. Crear un par entrelazado de qubits (par de Bell) compartido entre Alice y Bob.\n",
33 | "2. Alice realiza una medición en la base de Bell en sus dos qubits.\n",
34 | "3. Alice envía los resultados clásicos de su medición a Bob.\n",
35 | "4. Bob aplica compuertas cuánticas apropiadas basadas en los resultados de medición de Alice para obtener el estado teletportado."
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "id": "a26fb942-ca66-4bea-85f5-f8f13d013d5e",
41 | "metadata": {},
42 | "source": [
43 | "## Implementación\n",
44 | "\n",
45 | "Para transferir un bit cuántico, Alice y Bob necesitan la ayuda de un tercero que les proporcione un par de qubits entrelazados. A continuación, Alice realiza ciertas operaciones en su qubit y comparte los resultados con Bob a través de un canal de comunicación clásico. Finalmente, Bob realiza una serie de operaciones por su parte para obtener con éxito el qubit de Alice. Ahora, profundicemos en cada uno de estos pasos."
46 | ]
47 | },
48 | {
49 | "cell_type": "markdown",
50 | "id": "71cdf58d-0d4d-43f0-b427-3a3ebca842f5",
51 | "metadata": {
52 | "tags": []
53 | },
54 | "source": [
55 | "Nuestro circuito cuántico constará de 3 qubits y 3 bits clásicos. Los qubits se nombrarán de la siguiente manera:\n",
56 | "- $s$: El qubit \"fuente\" que contiene el estado $\\lvert \\psi \\rangle$ que Alice desea transmitir a Bob.\n",
57 | "- $a$: El qubit que inicialmente almacenará la mitad de Alice del par de Bell entrelazado.\n",
58 | "- $b$: el qubit que inicialmente almacenará la mitad de Bob del par de Bell entrelazado.\n",
59 | "\n",
60 | "El protocolo de teleportación en sí requiere 2 bits clásicos, e incluimos un tercero para medir el estado final de Bob. Los bits clásicos se denominarán de la siguiente manera:\n",
61 | "- $c0$: El bit clásico que utiliza Alice para medir $a$.\n",
62 | "- $c1$: El bit clásico que usa Alice para medir $s$.\n",
63 | "- $c2$: El bit clásico que usa Bob para medir $b$."
64 | ]
65 | },
66 | {
67 | "cell_type": "markdown",
68 | "id": "bad695dc",
69 | "metadata": {},
70 | "source": [
71 | "### Ejercicio 1\n",
72 | "\n",
73 | "Utiliza dos qubits para generar un estado de par de Bell entrelazado $\\frac{\\lvert 00 \\rangle + \\lvert 11 \\rangle}{\\sqrt{2}}$. El qubit 𝑎 se asigna a Alice, mientras que el qubit 𝑏 se asigna a Bob.\n",
74 | "\n",
75 | "*Hint*: Este estado se puede generar utilizando una compuerta Hadamard y una compuerta CNOT."
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "execution_count": null,
81 | "id": "d9a9810a-8ec5-4e0e-823d-6865e810b34d",
82 | "metadata": {
83 | "tags": []
84 | },
85 | "outputs": [],
86 | "source": [
87 | "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
88 | "from qiskit.circuit import Qubit, Clbit\n",
89 | "\n",
90 | "\n",
91 | "def create_bell_pair(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
92 | " \"\"\"Creates a bell pair between qubits a and b.\"\"\"\n",
93 | " qc = QuantumCircuit(qr, cr)\n",
94 | " # unpack qubits\n",
95 | " # the first qubit is s but we won't be using it in this exercise\n",
96 | " _, a, b = qr\n",
97 | "\n",
98 | " ####### your code goes here #######\n",
99 | "\n",
100 | " return qc"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": null,
106 | "id": "7897fcca-e31a-4b44-9e19-16fbeb85a20d",
107 | "metadata": {
108 | "tags": []
109 | },
110 | "outputs": [],
111 | "source": [
112 | "qr = QuantumRegister(3, name=\"q\")\n",
113 | "cr = ClassicalRegister(3, name=\"c\")\n",
114 | "qc = create_bell_pair(qr, cr)\n",
115 | "\n",
116 | "qc.draw(\"mpl\")"
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": null,
122 | "id": "d00f07df-5245-47c7-858b-3ae6cbafc475",
123 | "metadata": {
124 | "tags": []
125 | },
126 | "outputs": [],
127 | "source": [
128 | "# Submit your circuit\n",
129 | "\n",
130 | "from qc_grader.challenges.spring_2023 import grade_ex2a\n",
131 | "\n",
132 | "grade_ex2a(qc)"
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "id": "b6b5ec32-e8ae-4475-a0ea-5314acf49a4f",
138 | "metadata": {},
139 | "source": [
140 | "Supongamos que Alice tiene el qubit $a$ y Bob tiene el qubit $b$ una vez que se separan. Tal vez realmente estén teniendo un problema de relación 😉."
141 | ]
142 | },
143 | {
144 | "cell_type": "markdown",
145 | "id": "6ba11110",
146 | "metadata": {},
147 | "source": [
148 | "### Ejercicio 2\n",
149 | "\n",
150 | "Realiza los siguientes pasos del protocolo:\n",
151 | "1. Alice aplica una compuerta CNOT con $s$ (el qubit que contiene $\\lvert \\psi \\rangle$) como control y $a$ como objetivo.\n",
152 | "2. Alice aplica una compuerta Hadamard a $s$."
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": null,
158 | "id": "34d7bcd6-166b-4745-8ede-f8aa1872d434",
159 | "metadata": {
160 | "tags": []
161 | },
162 | "outputs": [],
163 | "source": [
164 | "def alice_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
165 | " \"\"\"Creates Alices's gates\"\"\"\n",
166 | " qc = create_bell_pair(qr, cr)\n",
167 | " qc.barrier() # Use barrier to separate steps\n",
168 | " s, a, b = qr\n",
169 | "\n",
170 | " ####### your code goes here #######\n",
171 | "\n",
172 | " return qc"
173 | ]
174 | },
175 | {
176 | "cell_type": "code",
177 | "execution_count": null,
178 | "id": "3a5096db-1b92-45df-ac1b-52392356b543",
179 | "metadata": {
180 | "tags": []
181 | },
182 | "outputs": [],
183 | "source": [
184 | "qc = alice_gates(qr, cr)\n",
185 | "qc.draw(\"mpl\")"
186 | ]
187 | },
188 | {
189 | "cell_type": "code",
190 | "execution_count": null,
191 | "id": "66cead66-9c0e-4e7c-a196-efa456e6764b",
192 | "metadata": {
193 | "tags": []
194 | },
195 | "outputs": [],
196 | "source": [
197 | "# Submit your circuit\n",
198 | "\n",
199 | "from qc_grader.challenges.spring_2023 import grade_ex2b\n",
200 | "\n",
201 | "grade_ex2b(qc)"
202 | ]
203 | },
204 | {
205 | "cell_type": "markdown",
206 | "id": "2d45bf84-f32b-4dd9-8e73-b8ec920e8b39",
207 | "metadata": {
208 | "tags": []
209 | },
210 | "source": [
211 | "### Ejercicio 3\n",
212 | "\n",
213 | "En este paso, Alice realiza una medición en ambos qubits que posee y guarda los resultados en dos bits clásicos. Luego, le envía estos dos bits a Bob.\n",
214 | "\n",
215 | "Completa la siguiente celda de código para que Alice mida el qubit $a$ en el bit clásico $c0$ y el qubit $s$ en el bit clásico $c1$."
216 | ]
217 | },
218 | {
219 | "cell_type": "code",
220 | "execution_count": null,
221 | "id": "345bc52c-7745-46a3-90e7-a0e6a03604d5",
222 | "metadata": {
223 | "tags": []
224 | },
225 | "outputs": [],
226 | "source": [
227 | "def measure_and_send(qr: QuantumRegister, cr: ClassicalRegister):\n",
228 | " \"\"\"Measures qubits a & b and 'sends' the results to Bob\"\"\"\n",
229 | " qc = alice_gates(qr, cr)\n",
230 | " qc.barrier() # Use barrier to separate steps\n",
231 | " s, a, b = qr\n",
232 | " c0, c1, c2 = cr\n",
233 | "\n",
234 | " ####### your code goes here #######\n",
235 | "\n",
236 | " return qc"
237 | ]
238 | },
239 | {
240 | "cell_type": "code",
241 | "execution_count": null,
242 | "id": "b1c3ec5d-ce66-455c-a2fe-6cca03dd87f4",
243 | "metadata": {
244 | "tags": []
245 | },
246 | "outputs": [],
247 | "source": [
248 | "qc = measure_and_send(qr, cr)\n",
249 | "qc.draw(\"mpl\", cregbundle=False)"
250 | ]
251 | },
252 | {
253 | "cell_type": "code",
254 | "execution_count": null,
255 | "id": "76b0c0b2-ed71-4eb7-b4d9-9b725a22fccb",
256 | "metadata": {
257 | "tags": []
258 | },
259 | "outputs": [],
260 | "source": [
261 | "# Submit your circuit\n",
262 | "\n",
263 | "from qc_grader.challenges.spring_2023 import grade_ex2c\n",
264 | "\n",
265 | "grade_ex2c(qc)"
266 | ]
267 | },
268 | {
269 | "cell_type": "markdown",
270 | "id": "1fec0216-f312-430e-9940-0ab0ffd1beca",
271 | "metadata": {},
272 | "source": [
273 | "### Ejercicio 4\n",
274 | "\n",
275 | "En este paso, Bob, que ya posee el qubit $b$, agrega dinámicamente compuertas específicas al circuito en función del estado de los bits clásicos recibidos de Alice:\n",
276 | "\n",
277 | "- Si los bits son `00`, no se requiere ninguna acción.\n",
278 | "- Si son `01`, se debe aplicar una compuerta 𝑋 (también conocida como Pauli-X o compuerta bit-flip).\n",
279 | "- Para los bits `10`, se debe aplicar una compuerta 𝑍 (también conocida como Pauli-Z o compuerta de cambio de fase).\n",
280 | "- Por último, si los bits clásicos son `11`, se debe aplicar una compuerta combinada 𝑍𝑋, lo que implica aplicar las compuertas 𝑍 y 𝑋 en secuencia."
281 | ]
282 | },
283 | {
284 | "cell_type": "code",
285 | "execution_count": null,
286 | "id": "e61ddfa4-e536-46dd-b5a7-efe15f3ad617",
287 | "metadata": {
288 | "tags": []
289 | },
290 | "outputs": [],
291 | "source": [
292 | "def bob_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
293 | " \"\"\"Uses qc.if_test to control which gates are dynamically added\"\"\"\n",
294 | " qc = measure_and_send(qr, cr)\n",
295 | " qc.barrier() # Use barrier to separate steps\n",
296 | " s, a, b = qr\n",
297 | " c0, c1, c2 = cr\n",
298 | "\n",
299 | " ####### your code goes here #######\n",
300 | "\n",
301 | " return qc"
302 | ]
303 | },
304 | {
305 | "cell_type": "code",
306 | "execution_count": null,
307 | "id": "ff619db6-282a-450e-9b7c-38b2838cfdeb",
308 | "metadata": {
309 | "tags": []
310 | },
311 | "outputs": [],
312 | "source": [
313 | "qc = bob_gates(qr, cr)\n",
314 | "qc.draw(\"mpl\", cregbundle=False)"
315 | ]
316 | },
317 | {
318 | "cell_type": "code",
319 | "execution_count": null,
320 | "id": "8ab0270f-f909-4239-bb52-e36410497c21",
321 | "metadata": {
322 | "tags": []
323 | },
324 | "outputs": [],
325 | "source": [
326 | "# Submit your circuit\n",
327 | "\n",
328 | "from qc_grader.challenges.spring_2023 import grade_ex2d\n",
329 | "\n",
330 | "grade_ex2d(qc)"
331 | ]
332 | },
333 | {
334 | "cell_type": "markdown",
335 | "id": "74dc4ac1-d643-468e-a13c-509e2a12d77b",
336 | "metadata": {},
337 | "source": [
338 | "Ahora haremos que Bob mida su qubit en el bit clásico $c2$. Después de repetir todo el experimento varias veces, podemos recopilar estadísticas sobre los resultados de la medición para confirmar que la teleportación funcionó correctamente."
339 | ]
340 | },
341 | {
342 | "cell_type": "code",
343 | "execution_count": null,
344 | "id": "6223a197-48b8-4b7b-889c-4bf317793a27",
345 | "metadata": {
346 | "tags": []
347 | },
348 | "outputs": [],
349 | "source": [
350 | "teleportation_circuit = bob_gates(qr, cr)\n",
351 | "s, a, b = qr\n",
352 | "c0, c1, c2 = cr\n",
353 | "teleportation_circuit.measure(b, c2)\n",
354 | "teleportation_circuit.draw(\"mpl\")"
355 | ]
356 | },
357 | {
358 | "cell_type": "markdown",
359 | "id": "3780a15e-4a86-4d5a-af4c-8662f4462fb9",
360 | "metadata": {},
361 | "source": [
362 | "Ahora que tenemos un circuito de teleportación, ~~transmitamos al Capitán Kirk a la superficie de un planeta extraño~~ crea y teleporta un estado cuántico, y luego ejecuta el circuito en un simulador."
363 | ]
364 | },
365 | {
366 | "cell_type": "markdown",
367 | "id": "977a9fe6",
368 | "metadata": {},
369 | "source": [
370 | "### Ejercicio 5\n",
371 | "\n",
372 | "En la siguiente celda de código, construye un circuito de teleportación cuántica completo en la variable `teleport_superposition_circuit`, siguiendo los siguientes pasos:\n",
373 | "\n",
374 | "- Construye un circuito de preparación del estado. Prepara el qubit $s$ aplicando una rotación $R_x$ con ángulo $\\pi / 4$.\n",
375 | "- Combina el circuito de preparación de estado con tu circuito de teleportación construido previamente."
376 | ]
377 | },
378 | {
379 | "cell_type": "code",
380 | "execution_count": null,
381 | "id": "89fa5bdb-eb09-4fb8-9913-6fd6bb9f8ad2",
382 | "metadata": {
383 | "tags": []
384 | },
385 | "outputs": [],
386 | "source": [
387 | "import math\n",
388 | "\n",
389 | "teleport_superposition_circuit: QuantumCircuit\n",
390 | "\n",
391 | "####### your code goes here #######\n",
392 | "\n",
393 | "\n",
394 | "# Uncomment this line to draw your circuit\n",
395 | "teleport_superposition_circuit.draw(\"mpl\", cregbundle=False)"
396 | ]
397 | },
398 | {
399 | "cell_type": "code",
400 | "execution_count": null,
401 | "id": "1e0ef91c-964a-4fd6-ab52-36c859b69b13",
402 | "metadata": {
403 | "tags": []
404 | },
405 | "outputs": [],
406 | "source": [
407 | "from qiskit import transpile\n",
408 | "from qiskit_aer import AerSimulator\n",
409 | "from qiskit.visualization import plot_histogram\n",
410 | "\n",
411 | "sim = AerSimulator()\n",
412 | "transpiled_circuit = transpile(teleport_superposition_circuit, sim)\n",
413 | "\n",
414 | "# run job\n",
415 | "shots = 1000\n",
416 | "job = sim.run(transpiled_circuit, shots=shots, dynamic=True)\n",
417 | "\n",
418 | "# Get the results and display them\n",
419 | "exp_result = job.result()\n",
420 | "exp_counts = exp_result.get_counts()\n",
421 | "plot_histogram(exp_counts)"
422 | ]
423 | },
424 | {
425 | "cell_type": "markdown",
426 | "id": "80e72c0a-8a4e-4d29-92a7-022d3882552a",
427 | "metadata": {},
428 | "source": [
429 | "Calculemos la distribución solamente de la medición de Bob marginando sobre los otros bits medidos."
430 | ]
431 | },
432 | {
433 | "cell_type": "code",
434 | "execution_count": null,
435 | "id": "96a1fd3b-693b-4cd4-bb51-96f676dd1759",
436 | "metadata": {
437 | "tags": []
438 | },
439 | "outputs": [],
440 | "source": [
441 | "# trace out Bob's results on qubit 2\n",
442 | "from qiskit.result import marginal_counts\n",
443 | "\n",
444 | "bobs_counts = marginal_counts(exp_counts, [qr.index(b)])\n",
445 | "plot_histogram(bobs_counts)"
446 | ]
447 | },
448 | {
449 | "cell_type": "markdown",
450 | "id": "6a33717b",
451 | "metadata": {},
452 | "source": [
453 | "La distribución marginal debería estar algo cerca de las probabilidades ideales."
454 | ]
455 | },
456 | {
457 | "cell_type": "code",
458 | "execution_count": null,
459 | "id": "475e3774-da15-483b-9d2d-af54a8e0e568",
460 | "metadata": {
461 | "tags": []
462 | },
463 | "outputs": [],
464 | "source": [
465 | "from qc_grader.challenges.spring_2023 import grade_ex2e\n",
466 | "\n",
467 | "grade_ex2e(bobs_counts)"
468 | ]
469 | },
470 | {
471 | "cell_type": "markdown",
472 | "id": "9baa3099-7577-4bf9-9d1f-e0c54dc384b8",
473 | "metadata": {},
474 | "source": [
475 | "Ahora que estamos bastante seguros de que ~~el Capitán Kirk~~ el qubit de Alice se teleportará de manera segura, ejecutemos el circuito de teleportación cuántica en hardware real."
476 | ]
477 | },
478 | {
479 | "cell_type": "code",
480 | "execution_count": null,
481 | "id": "ca2f737c-a21f-4727-b14d-0e7e315631ba",
482 | "metadata": {
483 | "tags": []
484 | },
485 | "outputs": [],
486 | "source": [
487 | "from qiskit_ibm_provider import IBMProvider\n",
488 | "\n",
489 | "provider = IBMProvider()"
490 | ]
491 | },
492 | {
493 | "cell_type": "code",
494 | "execution_count": null,
495 | "id": "da33a9fb-6b6c-48a4-a1b0-dfca70474e22",
496 | "metadata": {
497 | "tags": []
498 | },
499 | "outputs": [],
500 | "source": [
501 | "hub = \"YOUR_HUB\"\n",
502 | "group = \"YOUR_GROUP\"\n",
503 | "project = \"YOUR_PROJECT\"\n",
504 | "\n",
505 | "backend_name = \"ibm_peekskill\"\n",
506 | "backend = provider.get_backend(backend_name, instance=f\"{hub}/{group}/{project}\")"
507 | ]
508 | },
509 | {
510 | "cell_type": "code",
511 | "execution_count": null,
512 | "id": "fe48f446-849f-46e9-b0a4-1dd5225db403",
513 | "metadata": {
514 | "tags": []
515 | },
516 | "outputs": [],
517 | "source": [
518 | "# backend.target.add_instruction(IfElseOp, name=\"if_else\") # Uncomment if necessary\n",
519 | "qc_transpiled = transpile(teleport_superposition_circuit, backend)"
520 | ]
521 | },
522 | {
523 | "cell_type": "code",
524 | "execution_count": null,
525 | "id": "cee84182-a90d-44b7-b44d-87309202cbc3",
526 | "metadata": {
527 | "tags": []
528 | },
529 | "outputs": [],
530 | "source": [
531 | "job = backend.run(qc_transpiled, shots=1000, dynamic=True)"
532 | ]
533 | },
534 | {
535 | "cell_type": "markdown",
536 | "id": "d113d086-b970-4fdc-807e-fafe7efde919",
537 | "metadata": {},
538 | "source": [
539 | "Debido a que lleva tiempo ejecutarse en el backend real, normalmente usas job_id para llamar a los trabajos (jobs) después de un tiempo.\n",
540 | "El siguiente código invoca trabajos a través de job_id y verifica el estado de ejecución. Aquí se explica cómo usarlo."
541 | ]
542 | },
543 | {
544 | "cell_type": "code",
545 | "execution_count": null,
546 | "id": "fc8458f1-43fd-48b2-a50c-65771262cbf1",
547 | "metadata": {
548 | "tags": []
549 | },
550 | "outputs": [],
551 | "source": [
552 | "retrieve_job = provider.retrieve_job(job.job_id())\n",
553 | "retrieve_job.status()"
554 | ]
555 | },
556 | {
557 | "cell_type": "markdown",
558 | "id": "a8f607a6-b2c9-46a5-a925-73105e91f698",
559 | "metadata": {},
560 | "source": [
561 | "Si tu trabajo terminó con éxito, entonces importemos los resultados."
562 | ]
563 | },
564 | {
565 | "cell_type": "code",
566 | "execution_count": null,
567 | "id": "ead9b3af-7d05-4213-9360-1343621ba3a0",
568 | "metadata": {},
569 | "outputs": [],
570 | "source": [
571 | "# Get the results and display them\n",
572 | "exp_result = retrieve_job.result()\n",
573 | "exp_counts = exp_result.get_counts()\n",
574 | "plot_histogram(exp_counts)"
575 | ]
576 | },
577 | {
578 | "cell_type": "code",
579 | "execution_count": null,
580 | "id": "88ddf3c8-732f-4825-a1b1-376bce0ab614",
581 | "metadata": {},
582 | "outputs": [],
583 | "source": [
584 | "# trace out Bob's results on qubit 2\n",
585 | "from qiskit.result import marginal_counts\n",
586 | "\n",
587 | "bobs_qubit = 2\n",
588 | "bobs_counts = marginal_counts(exp_counts, [bobs_qubit])\n",
589 | "plot_histogram(bobs_counts)"
590 | ]
591 | }
592 | ],
593 | "metadata": {
594 | "kernelspec": {
595 | "display_name": "Python 3 (ipykernel)",
596 | "language": "python",
597 | "name": "python3"
598 | },
599 | "language_info": {
600 | "codemirror_mode": {
601 | "name": "ipython",
602 | "version": 3
603 | },
604 | "file_extension": ".py",
605 | "mimetype": "text/x-python",
606 | "name": "python",
607 | "nbconvert_exporter": "python",
608 | "pygments_lexer": "ipython3",
609 | "version": "3.10.8"
610 | },
611 | "widgets": {
612 | "application/vnd.jupyter.widget-state+json": {
613 | "state": {},
614 | "version_major": 2,
615 | "version_minor": 0
616 | }
617 | }
618 | },
619 | "nbformat": 4,
620 | "nbformat_minor": 5
621 | }
622 |
--------------------------------------------------------------------------------
/content/lab_2/lab2-ja.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Lab 2: 量子テレポーテーション\n",
8 | "\n",
9 | "アリスとボブが抱えている問題を解決する量子テレポーテーションのLabへようこそ。ご安心ください、人間関係の問題ではありませんよ!アリスは未知の状態 $\\lvert \\psi \\rangle$ の量子ビットを所持しており、この量子状態をボブに転送したいと考えています。しかしながら彼らは非常に離れた場所におり、量子情報を直接転送する手段はなく、転送できるのは古典情報のみです。彼らの目標を達成することは可能でしょうか?\n",
10 | "\n",
11 | "アリスとボブがエンタングルした量子ビットのペアを共有している場合、彼女が2ビットの古典情報を送信することで、量子ビットの状態をボブに転送できることがわかっています。最終的に、ボブが $\\lvert \\psi \\rangle$ を所有し、アリスはそれを持たなくなるため、このプロセスはテレポーテーションとして知られています。"
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "metadata": {},
17 | "source": [
18 | "## 背景\n",
19 | "\n",
20 | "量子テレポーテーションは、エンタングルメントと古典通信を使用し、ある量子ビットから別の量子ビットへと量子情報の転送を可能にするプロトコルです。このプロトコルは、1993年に Charles Bennett、Gilles Brassard、Claude Crépeau、Richard Jozsa、Asher Peres および William Wootters によって提案されました。このプロセスは、量子ビット自体を送信するのではなく、ソース量子ビットからターゲット量子ビットに量子状態を転送します。\n",
21 | "\n",
22 | "プロトコルには3つの量子ビットが必要です。\n",
23 | "\n",
24 | "1. テレポートする量子ビット(アリスの量子ビット)\n",
25 | "2. エンタングルした量子ビットのペアの片方(アリスの2番目の量子ビット)\n",
26 | "3. エンタングルしたペアのもう片方(ボブの量子ビット)\n",
27 | "\n",
28 | "プロトコルは、次の手順に要約できます。\n",
29 | "\n",
30 | "1. アリスとボブの間で共有される、エンタングルした量子ビットのペア(Bellペア)を生成します。\n",
31 | "2. アリスは、自身が持つ2つの量子ビットに対しBell基底測定を実行します。\n",
32 | "3. アリスは、古典測定の結果をボブに送信します。\n",
33 | "4. ボブは、アリスの測定結果に基づいて適切な量子ゲートを適用し、テレポート状態を取得します。"
34 | ]
35 | },
36 | {
37 | "cell_type": "markdown",
38 | "metadata": {},
39 | "source": [
40 | "## 実装\n",
41 | "\n",
42 | "量子ビットを転送するためには、アリスとボブにエンタングルした量子ビットのペアを提供してくれる第三者の助けが必要です。次に、アリスは量子ビットに対して特定の操作を実行し、その結果を古典通信チャネルを介してボブと共有します。最後に、ボブは自分の側で一連の操作を実行し、アリスの量子ビットを正常に取得します。それでは、これらの各ステップについて詳しく見ていきましょう。"
43 | ]
44 | },
45 | {
46 | "cell_type": "markdown",
47 | "metadata": {},
48 | "source": [
49 | "量子回路は、3つの量子ビットと3つの古典ビットで構成されます。量子ビットは次のように命名されます。\n",
50 | "\n",
51 | "- $s$: アリスがボブに送信したい、状態 $\\lvert \\psi \\rangle$ を含む「ソース」量子ビット。\n",
52 | "- $a$: エンタングルしたBellペアのうち、アリスが持つ片方を最初に格納する量子ビット。\n",
53 | "- $b$: エンタングルしたBellペアのうち、ボブが持つもう片方を最初に格納する量子ビット。\n",
54 | "\n",
55 | "\n",
56 | "テレポーテーションプロトコル自体には2つの古典ビットが必要であり、ボブの最終状態を測定するために使用する3つ目の古典ビットも含まれます。古典ビットは次のように命名されます。\n",
57 | "\n",
58 | "- $c0$: アリスが $a$ の測定に使用する古典ビット。\n",
59 | "- $c1$: アリスが $s$ の測定に使用する古典ビット。\n",
60 | "- $c2$: ボブが $b$ の測定に使用する古典ビット。"
61 | ]
62 | },
63 | {
64 | "cell_type": "markdown",
65 | "metadata": {},
66 | "source": [
67 | "### Exercise 1\n",
68 | "\n",
69 | "2つの量子ビットを利用して、エンタングルしたBellペアの状態 $\\frac{\\lvert 00 \\rangle + \\lvert 11 \\rangle}{\\sqrt{2}}$ を生成してください。量子ビット $a$ はアリスに割り当てられ、量子ビット $b$ はボブのものです。\n",
70 | "\n",
71 | "ヒント:Bell状態はアダマールゲートとCNOTゲートを使うことで生成できます。"
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "execution_count": null,
77 | "metadata": {
78 | "tags": []
79 | },
80 | "outputs": [],
81 | "source": [
82 | "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
83 | "from qiskit.circuit import Qubit, Clbit\n",
84 | "\n",
85 | "\n",
86 | "def create_bell_pair(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
87 | " \"\"\"Creates a bell pair between qubits a and b.\"\"\"\n",
88 | " qc = QuantumCircuit(qr, cr)\n",
89 | " # unpack qubits\n",
90 | " # the first qubit is s but we won't be using it in this exercise\n",
91 | " _, a, b = qr\n",
92 | "\n",
93 | " ####### your code goes here #######\n",
94 | "\n",
95 | " return qc"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": null,
101 | "metadata": {
102 | "tags": []
103 | },
104 | "outputs": [],
105 | "source": [
106 | "qr = QuantumRegister(3, name=\"q\")\n",
107 | "cr = ClassicalRegister(3, name=\"c\")\n",
108 | "qc = create_bell_pair(qr, cr)\n",
109 | "\n",
110 | "qc.draw(\"mpl\")"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": null,
116 | "metadata": {
117 | "tags": []
118 | },
119 | "outputs": [],
120 | "source": [
121 | "# Submit your circuit\n",
122 | "\n",
123 | "from qc_grader.challenges.spring_2023 import grade_ex2a\n",
124 | "\n",
125 | "grade_ex2a(qc)"
126 | ]
127 | },
128 | {
129 | "cell_type": "markdown",
130 | "metadata": {},
131 | "source": [
132 | "アリスが量子ビット $a$ を持ち、ボブが量子ビット $b$ を持っていると仮定しましょう。彼らは本当に関係性に問題を抱えているかもしれませんね😉。"
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "metadata": {},
138 | "source": [
139 | "### Exercise 2\n",
140 | "\n",
141 | "次のプロトコルを実装してください。\n",
142 | "1. アリスが、 $s$ ($\\lvert \\psi \\rangle$ を含む量子ビット)を制御、 $a$ をターゲットとしてCNOTゲートを適用する。\n",
143 | "2. アリスが $s$ にアダマールゲートを適用する。\n"
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "execution_count": null,
149 | "metadata": {
150 | "tags": []
151 | },
152 | "outputs": [],
153 | "source": [
154 | "def alice_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
155 | " \"\"\"Creates Alices's gates\"\"\"\n",
156 | " qc = create_bell_pair(qr, cr)\n",
157 | " qc.barrier() # Use barrier to separate steps\n",
158 | " s, a, b = qr\n",
159 | "\n",
160 | " ####### your code goes here #######\n",
161 | "\n",
162 | " return qc"
163 | ]
164 | },
165 | {
166 | "cell_type": "code",
167 | "execution_count": null,
168 | "metadata": {
169 | "tags": []
170 | },
171 | "outputs": [],
172 | "source": [
173 | "qc = alice_gates(qr, cr)\n",
174 | "qc.draw(\"mpl\")"
175 | ]
176 | },
177 | {
178 | "cell_type": "code",
179 | "execution_count": null,
180 | "metadata": {
181 | "tags": []
182 | },
183 | "outputs": [],
184 | "source": [
185 | "# Submit your circuit\n",
186 | "\n",
187 | "from qc_grader.challenges.spring_2023 import grade_ex2b\n",
188 | "\n",
189 | "grade_ex2b(qc)"
190 | ]
191 | },
192 | {
193 | "cell_type": "markdown",
194 | "metadata": {
195 | "tags": []
196 | },
197 | "source": [
198 | "### Exercise 3\n",
199 | "このステップでは、アリスは所有している両方の量子ビットで測定を実行し、結果を2つの古典ビットに保存します。その後、彼女はこれら2つのビットをボブに送信します。\n",
200 | "\n",
201 | "彼女は量子ビット $a$ を古典ビット $c0$ に、量子ビット $s$ を古典ビット $c1$ に測定して入れるように以下のコードセルを完成させてください。"
202 | ]
203 | },
204 | {
205 | "cell_type": "code",
206 | "execution_count": null,
207 | "metadata": {
208 | "tags": []
209 | },
210 | "outputs": [],
211 | "source": [
212 | "def measure_and_send(qr: QuantumRegister, cr: ClassicalRegister):\n",
213 | " \"\"\"Measures qubits a & b and 'sends' the results to Bob\"\"\"\n",
214 | " qc = alice_gates(qr, cr)\n",
215 | " qc.barrier() # Use barrier to separate steps\n",
216 | " s, a, b = qr\n",
217 | " c0, c1, c2 = cr\n",
218 | "\n",
219 | " ####### your code goes here #######\n",
220 | "\n",
221 | " return qc"
222 | ]
223 | },
224 | {
225 | "cell_type": "code",
226 | "execution_count": null,
227 | "metadata": {
228 | "tags": []
229 | },
230 | "outputs": [],
231 | "source": [
232 | "qc = measure_and_send(qr, cr)\n",
233 | "qc.draw(\"mpl\", cregbundle=False)"
234 | ]
235 | },
236 | {
237 | "cell_type": "code",
238 | "execution_count": null,
239 | "metadata": {
240 | "tags": []
241 | },
242 | "outputs": [],
243 | "source": [
244 | "# Submit your circuit\n",
245 | "\n",
246 | "from qc_grader.challenges.spring_2023 import grade_ex2c\n",
247 | "\n",
248 | "grade_ex2c(qc)"
249 | ]
250 | },
251 | {
252 | "cell_type": "markdown",
253 | "metadata": {
254 | "tags": []
255 | },
256 | "source": [
257 | "### Exercise 4\n",
258 | "\n",
259 | "このステップでは、すでに量子ビット $b$ を所有しているボブが、アリスから受け取った古典ビットの状態に基づいて、回路に特定のゲートを動的に追加します。\n",
260 | "\n",
261 | "- ビットが `00` の場合、アクションは必要ありません。\n",
262 | "- ビットが `01` の場合、 $X$ ゲート(Pauli-X または ビット・フリップ・ゲートとも呼ばれます)を適用する必要があります。\n",
263 | "- ビット `10` には、 $Z$ ゲート(Pauli-Z または フェーズ・フリップ・ゲートとも呼ばれます)を適用する必要があります。\n",
264 | "- 最後に、古典ビットが `11` の場合は、 $ZX$ ゲートを適用する必要があります。これには、 $Z$ゲートと $X$ ゲートの両方を順番に適用する必要があります。"
265 | ]
266 | },
267 | {
268 | "cell_type": "code",
269 | "execution_count": null,
270 | "metadata": {
271 | "tags": []
272 | },
273 | "outputs": [],
274 | "source": [
275 | "def bob_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
276 | " \"\"\"Uses qc.if_test to control which gates are dynamically added\"\"\"\n",
277 | " qc = measure_and_send(qr, cr)\n",
278 | " qc.barrier() # Use barrier to separate steps\n",
279 | " s, a, b = qr\n",
280 | " c0, c1, c2 = cr\n",
281 | "\n",
282 | " ####### your code goes here #######\n",
283 | "\n",
284 | " return qc"
285 | ]
286 | },
287 | {
288 | "cell_type": "code",
289 | "execution_count": null,
290 | "metadata": {
291 | "tags": []
292 | },
293 | "outputs": [],
294 | "source": [
295 | "qc = bob_gates(qr, cr)\n",
296 | "qc.draw(\"mpl\", cregbundle=False)"
297 | ]
298 | },
299 | {
300 | "cell_type": "code",
301 | "execution_count": null,
302 | "metadata": {
303 | "tags": []
304 | },
305 | "outputs": [],
306 | "source": [
307 | "# Submit your circuit\n",
308 | "\n",
309 | "from qc_grader.challenges.spring_2023 import grade_ex2d\n",
310 | "\n",
311 | "grade_ex2d(qc)"
312 | ]
313 | },
314 | {
315 | "cell_type": "markdown",
316 | "metadata": {},
317 | "source": [
318 | "ここで、ボブは自分の量子ビットを測定して、古典ビット $c2$ に入れます。実験全体を複数回繰り返した後、測定結果に関する統計を収集して、テレポーテーションが正しく機能したことを確認できます。"
319 | ]
320 | },
321 | {
322 | "cell_type": "code",
323 | "execution_count": null,
324 | "metadata": {
325 | "tags": []
326 | },
327 | "outputs": [],
328 | "source": [
329 | "teleportation_circuit = bob_gates(qr, cr)\n",
330 | "s, a, b = qr\n",
331 | "c0, c1, c2 = cr\n",
332 | "teleportation_circuit.measure(b, c2)\n",
333 | "teleportation_circuit.draw(\"mpl\")"
334 | ]
335 | },
336 | {
337 | "cell_type": "markdown",
338 | "metadata": {},
339 | "source": [
340 | "テレポーテーション回路ができたので、~~カーク船長を見知らぬ惑星の地表に転送して~~ 量子状態の生成とテレポートを、シミュレーター上の回路で実行しましょう。"
341 | ]
342 | },
343 | {
344 | "cell_type": "markdown",
345 | "metadata": {},
346 | "source": [
347 | "### Exercise 5\n",
348 | "\n",
349 | "次のコードセルでは、完全な量子テレポーテーション回路を `teleport_superposition_circuit` 変数に構築します。次のステップに従ってください。\n",
350 | "\n",
351 | "- 状態を準備する回路を構築します。角度 $\\pi / 4$ の $R_x$ 回転ゲートを適用して量子ビット $s$ を準備してください。\n",
352 | "- 状態準備回路と先ほど構築したテレポーテーション回路を結合してください。"
353 | ]
354 | },
355 | {
356 | "cell_type": "code",
357 | "execution_count": null,
358 | "metadata": {
359 | "tags": []
360 | },
361 | "outputs": [],
362 | "source": [
363 | "import math\n",
364 | "\n",
365 | "teleport_superposition_circuit: QuantumCircuit\n",
366 | "\n",
367 | "####### your code goes here #######\n",
368 | "\n",
369 | "\n",
370 | "# Uncomment this line to draw your circuit\n",
371 | "teleport_superposition_circuit.draw(\"mpl\", cregbundle=False)"
372 | ]
373 | },
374 | {
375 | "cell_type": "code",
376 | "execution_count": null,
377 | "metadata": {
378 | "tags": []
379 | },
380 | "outputs": [],
381 | "source": [
382 | "from qiskit import transpile\n",
383 | "from qiskit_aer import AerSimulator\n",
384 | "from qiskit.visualization import plot_histogram\n",
385 | "\n",
386 | "sim = AerSimulator()\n",
387 | "transpiled_circuit = transpile(teleport_superposition_circuit, sim)\n",
388 | "\n",
389 | "# run job\n",
390 | "shots = 1000\n",
391 | "job = sim.run(transpiled_circuit, shots=shots, dynamic=True)\n",
392 | "\n",
393 | "# Get the results and display them\n",
394 | "exp_result = job.result()\n",
395 | "exp_counts = exp_result.get_counts()\n",
396 | "plot_histogram(exp_counts)"
397 | ]
398 | },
399 | {
400 | "cell_type": "markdown",
401 | "metadata": {},
402 | "source": [
403 | "他の測定ビットを無視して、ボブの測定値だけの分布を計算してみましょう。"
404 | ]
405 | },
406 | {
407 | "cell_type": "code",
408 | "execution_count": null,
409 | "metadata": {
410 | "tags": []
411 | },
412 | "outputs": [],
413 | "source": [
414 | "# trace out Bob's results on qubit 2\n",
415 | "from qiskit.result import marginal_counts\n",
416 | "\n",
417 | "bobs_counts = marginal_counts(exp_counts, [qr.index(b)])\n",
418 | "plot_histogram(bobs_counts)"
419 | ]
420 | },
421 | {
422 | "cell_type": "markdown",
423 | "metadata": {},
424 | "source": [
425 | "周辺分布は、理想的な確率にある程度は近いはずです。"
426 | ]
427 | },
428 | {
429 | "cell_type": "code",
430 | "execution_count": null,
431 | "metadata": {
432 | "tags": []
433 | },
434 | "outputs": [],
435 | "source": [
436 | "from qc_grader.challenges.spring_2023 import grade_ex2e\n",
437 | "\n",
438 | "grade_ex2e(bobs_counts)"
439 | ]
440 | },
441 | {
442 | "cell_type": "markdown",
443 | "metadata": {},
444 | "source": [
445 | "~~カーク船長~~ アリスの量子ビットが安全にテレポートすることがほぼ確実になったので、実際のハードウェアで量子テレポーテーション回路を実行してみましょう。"
446 | ]
447 | },
448 | {
449 | "cell_type": "code",
450 | "execution_count": null,
451 | "metadata": {
452 | "tags": []
453 | },
454 | "outputs": [],
455 | "source": [
456 | "from qiskit_ibm_provider import IBMProvider\n",
457 | "\n",
458 | "provider = IBMProvider()"
459 | ]
460 | },
461 | {
462 | "cell_type": "code",
463 | "execution_count": null,
464 | "metadata": {
465 | "tags": []
466 | },
467 | "outputs": [],
468 | "source": [
469 | "hub = \"YOUR_HUB\"\n",
470 | "group = \"YOUR_GROUP\"\n",
471 | "project = \"YOUR_PROJECT\"\n",
472 | "\n",
473 | "backend_name = \"ibm_peekskill\"\n",
474 | "backend = provider.get_backend(backend_name, instance=f\"{hub}/{group}/{project}\")"
475 | ]
476 | },
477 | {
478 | "cell_type": "code",
479 | "execution_count": null,
480 | "metadata": {
481 | "tags": []
482 | },
483 | "outputs": [],
484 | "source": [
485 | "# backend.target.add_instruction(IfElseOp, name=\"if_else\") # Uncomment if necessary\n",
486 | "qc_transpiled = transpile(teleport_superposition_circuit, backend)"
487 | ]
488 | },
489 | {
490 | "cell_type": "code",
491 | "execution_count": null,
492 | "metadata": {
493 | "tags": []
494 | },
495 | "outputs": [],
496 | "source": [
497 | "job = backend.run(qc_transpiled, shots=1000, dynamic=True)"
498 | ]
499 | },
500 | {
501 | "cell_type": "markdown",
502 | "metadata": {},
503 | "source": [
504 | "実際のバックエンドで実行するには時間がかかるため、通常はjob_idを使って時間をおいてからジョブを呼び出すことになります。以下のコードは、job_idを通してジョブを呼び出し、実行状況を確認するものです。"
505 | ]
506 | },
507 | {
508 | "cell_type": "code",
509 | "execution_count": null,
510 | "metadata": {},
511 | "outputs": [],
512 | "source": [
513 | "retrieve_job = provider.retrieve_job(job.job_id())\n",
514 | "retrieve_job.status()"
515 | ]
516 | },
517 | {
518 | "cell_type": "markdown",
519 | "metadata": {},
520 | "source": [
521 | "無事に終了したら、結果をインポートしましょう。"
522 | ]
523 | },
524 | {
525 | "cell_type": "code",
526 | "execution_count": null,
527 | "metadata": {
528 | "tags": []
529 | },
530 | "outputs": [],
531 | "source": [
532 | "# Get the results and display them\n",
533 | "exp_result = retrieve_job.result()\n",
534 | "exp_counts = exp_result.get_counts()\n",
535 | "plot_histogram(exp_counts)"
536 | ]
537 | },
538 | {
539 | "cell_type": "code",
540 | "execution_count": null,
541 | "metadata": {},
542 | "outputs": [],
543 | "source": [
544 | "# trace out Bob's results on qubit 2\n",
545 | "from qiskit.result import marginal_counts\n",
546 | "\n",
547 | "bobs_qubit = 2\n",
548 | "bobs_counts = marginal_counts(exp_counts, [bobs_qubit])\n",
549 | "plot_histogram(bobs_counts)"
550 | ]
551 | }
552 | ],
553 | "metadata": {
554 | "kernelspec": {
555 | "display_name": "Python 3",
556 | "language": "python",
557 | "name": "python3"
558 | },
559 | "language_info": {
560 | "codemirror_mode": {
561 | "name": "ipython",
562 | "version": 3
563 | },
564 | "file_extension": ".py",
565 | "mimetype": "text/x-python",
566 | "name": "python",
567 | "nbconvert_exporter": "python",
568 | "pygments_lexer": "ipython3",
569 | "version": "3.8.5"
570 | },
571 | "widgets": {
572 | "application/vnd.jupyter.widget-state+json": {
573 | "state": {},
574 | "version_major": 2,
575 | "version_minor": 0
576 | }
577 | }
578 | },
579 | "nbformat": 4,
580 | "nbformat_minor": 5
581 | }
582 |
--------------------------------------------------------------------------------
/content/lab_2/lab2-ko.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "0ac9dd0b-210c-470e-8313-5cf7f7c57b65",
6 | "metadata": {},
7 | "source": [
8 | "# Lab 2: Quantum teleportation"
9 | ]
10 | },
11 | {
12 | "cell_type": "markdown",
13 | "id": "f2f7c4d2",
14 | "metadata": {},
15 | "source": [
16 | "앨리스와 밥이 고생중인 문제를 해결할 양자 전송( Quantum Teleportation) 연구소에 오신 것을 환영합니다. 안심하세요! 두 사람의 관계에 대한 문제가 아니니까요. 앨리스는 알 수 없는 상태의 큐비트 $\\lvert \\psi \\rangle$를 가지고 있고, 이 양자 상태를 밥에게 전송하고 싶습니다. 하지만, 그들은 매우 멀리 떨어져 있고 양자 정보를 직접 전달할 적절한 수단이 없으며, 고전적인 정보만 전달할 수 있습니다. 앨리스는 목표를 달성할 수 있을 까요?\n",
17 | "\n",
18 | "앨리스와 밥이 얽힌 큐비트 쌍을 공유하게 된다면, 고전적인 두 비트의 정보를 전송하는 것으로 큐비트 상태를 밥에게 전달할 수 있다는 것이 밝혀졌습니다. 이 과정의 마지막에 밥이 $\\lvert \\psi \\rangle$를 갖게 되고, 앨리스는 더 이상 갖고 있지 않게 되기 때문에 순간이동으로 알려져 있습니다."
19 | ]
20 | },
21 | {
22 | "cell_type": "markdown",
23 | "id": "11a966b2-a7c1-4584-87b2-1b8e4277f997",
24 | "metadata": {},
25 | "source": [
26 | "## 배경지식\n",
27 | "\n",
28 | "양자 전송은 얽힘과 고전적인 통신을 사용하여 한 큐비트에서 다른 큐비트로 양자 정보를 전송할 수 있는 프로토콜이며, 1993년에 Charles Bennett, Claude Crépeau, Richard Jozsa, Asher Peres, William Wootters가 제안했다. 이 과정은 큐비트 자체를 전송하지 않으면서 소스 큐비트에서 대상 큐비트로 양자 상태를 전송합니다.\n",
29 | "\n",
30 | "이 프로토콜은 세 개의 큐비트를 필요로 합니다:\n",
31 | "\n",
32 | "1. 전송 대상 큐비트 (앨리스의 큐비트)\n",
33 | "2. 얽혀 있는 큐비트 쌍의 반쪽 (앨리스의 두번째 큐비트)\n",
34 | "3. 얽혀 있는 큐비트 쌍의 나머지 반쪽 (밥의 큐비트)\n",
35 | "\n",
36 | "프로토콜의 진행은 다음과 요약할 수 있습니다:\n",
37 | "\n",
38 | "1. 벨 쌍(Bell Pair)이라 불리는 얽힌 큐비트 쌍을 만들어서 엘리스와 밥에게 나눠줍니다.\n",
39 | "2. 앨리스가 그녀의 두개의 큐비트에 대해 벨 기저 측정 (Bell basis measurement)를 진행합니다.\n",
40 | "3. 앨리스가 측정으로 얻은 고전 비트를 밥에게 전달합니다.\n",
41 | "4. 밥이 앨리스에게 전달받은 비트 정보를 기반으로 벨 쌍의 반쪽에 적절한 양자 게이트 연산을 적용한 후 측정하여 엘리스가 전송한 양자 상태를 얻습니다."
42 | ]
43 | },
44 | {
45 | "cell_type": "markdown",
46 | "id": "a26fb942-ca66-4bea-85f5-f8f13d013d5e",
47 | "metadata": {},
48 | "source": [
49 | "## 구현\n",
50 | "\n",
51 | "양자 비트를 전송하기 위해 앨리스와 밥은 얽힌 큐비트 한 쌍을 누군가가 제공해 주어야 합니다. \u001d\n",
52 | " 다음, 앨리스는 자신의 큐비트에 대한 특정 연산을 수행하고 고전적인 통신 채널을 통해 밥과 측정 결과를 공유합니다. 최종적으로, 밥은 앨리스가 전송한 양자 상태를 얻기 위해 그가 가진 얽힌 큐비트에 일련의 연산을 수행합니다. 이제 각 단계를 자세히 살펴봅시다. "
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "id": "71cdf58d-0d4d-43f0-b427-3a3ebca842f5",
58 | "metadata": {
59 | "tags": []
60 | },
61 | "source": [
62 | "양자 회로는 3개의 큐비트와 3개의 고전적인 비트로 구성됩니다. 큐비트의 이름은 다음과 같습니다:\n",
63 | "\n",
64 | "- $s$: $\\lvert \\psi \\rangle$ 상태를 지닌 \"source\" 큐비트로, 밥에게 전달하고자 하는 대상.\n",
65 | "- $a$: 얽혀있는 큐비트 쌍 중 앨리스가 가진 반쪽의 정보를 담을 큐비트\n",
66 | "- $b$: 얽혀있는 큐비트 쌍 중 밥이 가진 반쪽의 정보를 담을 큐비트\n",
67 | "\n",
68 | "전송 프로토콜 자체는 2개의 고전적인 비트가 필요하며, 밥의 큐비트의 최종 상태를 측정하는 데 사용할 세 번째 고전 비트가 추가로 필요합니다. 고전 비트들의 이름은 다음과 같습니다:\n",
69 | "- $c0$: 앨리스가 $a$의 측정에 사용할 고전 비트\n",
70 | "- $c1$: 앨리스가 $s$의 측정에 사용할 고전 비트\n",
71 | "- $c2$: 밥이 $b$의 측정에 사용할 고전 비트"
72 | ]
73 | },
74 | {
75 | "cell_type": "markdown",
76 | "id": "bad695dc",
77 | "metadata": {},
78 | "source": [
79 | "### 연습 1\n",
80 | "\n",
81 | "큐비트 2개를 사용하여 얽힌 벨 쌍 상태 $\\frac{\\lvert 00 \\rangle + \\lvert 11 \\rangle}{\\sqrt{2}}$를 생성합니다. 큐비트 𝑎는 앨리스에게, 큐비트 𝑏는 밥에게 할당 됩니다.\n",
82 | "\n",
83 | "*힌트*: 이 상태는 하다마드 게이트와 CNOT 게이트를 사용해서 구현됩니다. "
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "execution_count": null,
89 | "id": "d9a9810a-8ec5-4e0e-823d-6865e810b34d",
90 | "metadata": {
91 | "tags": []
92 | },
93 | "outputs": [],
94 | "source": [
95 | "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
96 | "from qiskit.circuit import Qubit, Clbit\n",
97 | "\n",
98 | "\n",
99 | "def create_bell_pair(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
100 | " \"\"\"Creates a bell pair between qubits a and b.\"\"\"\n",
101 | " qc = QuantumCircuit(qr, cr)\n",
102 | " # unpack qubits\n",
103 | " # the first qubit is s but we won't be using it in this exercise\n",
104 | " _, a, b = qr\n",
105 | "\n",
106 | " ####### your code goes here #######\n",
107 | "\n",
108 | " return qc"
109 | ]
110 | },
111 | {
112 | "cell_type": "code",
113 | "execution_count": null,
114 | "id": "7897fcca-e31a-4b44-9e19-16fbeb85a20d",
115 | "metadata": {
116 | "tags": []
117 | },
118 | "outputs": [],
119 | "source": [
120 | "qr = QuantumRegister(3, name=\"q\")\n",
121 | "cr = ClassicalRegister(3, name=\"c\")\n",
122 | "qc = create_bell_pair(qr, cr)\n",
123 | "\n",
124 | "qc.draw(\"mpl\")"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": null,
130 | "id": "d00f07df-5245-47c7-858b-3ae6cbafc475",
131 | "metadata": {
132 | "tags": []
133 | },
134 | "outputs": [],
135 | "source": [
136 | "# Submit your circuit\n",
137 | "\n",
138 | "from qc_grader.challenges.spring_2023 import grade_ex2a\n",
139 | "\n",
140 | "grade_ex2a(qc)"
141 | ]
142 | },
143 | {
144 | "cell_type": "markdown",
145 | "id": "b6b5ec32-e8ae-4475-a0ea-5314acf49a4f",
146 | "metadata": {},
147 | "source": [
148 | "이제 앨리스는 $a$, 밥은 $b$를 그들이 헤어지기 전 나누어 가졌다고 가정합시다. 어쩌면 앨리스와 밥은 진짜 관계에 문제가 있는 것이었을 지도 모르겠네요 😉."
149 | ]
150 | },
151 | {
152 | "cell_type": "markdown",
153 | "id": "6ba11110",
154 | "metadata": {},
155 | "source": [
156 | "### 연습 2\n",
157 | "\n",
158 | "프로토콜의 다음 단계를 실행해 봅시다:\n",
159 | "1. 앨리스는 CNOT 게이트를 큐비트 $a$에 밥에게 전송하고 싶은 상태인 $\\lvert \\psi \\rangle$를 지닌 큐비트 $s$를 제어 큐비트로 설정하여 적용합니다. \n",
160 | "2. 앨리스는 하다마드 게이트를 $s$에 적용합니다. \n"
161 | ]
162 | },
163 | {
164 | "cell_type": "code",
165 | "execution_count": null,
166 | "id": "34d7bcd6-166b-4745-8ede-f8aa1872d434",
167 | "metadata": {
168 | "tags": []
169 | },
170 | "outputs": [],
171 | "source": [
172 | "def alice_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
173 | " \"\"\"Creates Alices's gates\"\"\"\n",
174 | " qc = create_bell_pair(qr, cr)\n",
175 | " qc.barrier() # Use barrier to separate steps\n",
176 | " s, a, b = qr\n",
177 | "\n",
178 | " ####### your code goes here #######\n",
179 | "\n",
180 | " return qc"
181 | ]
182 | },
183 | {
184 | "cell_type": "code",
185 | "execution_count": null,
186 | "id": "3a5096db-1b92-45df-ac1b-52392356b543",
187 | "metadata": {
188 | "tags": []
189 | },
190 | "outputs": [],
191 | "source": [
192 | "qc = alice_gates(qr, cr)\n",
193 | "qc.draw(\"mpl\")"
194 | ]
195 | },
196 | {
197 | "cell_type": "code",
198 | "execution_count": null,
199 | "id": "66cead66-9c0e-4e7c-a196-efa456e6764b",
200 | "metadata": {
201 | "tags": []
202 | },
203 | "outputs": [],
204 | "source": [
205 | "# Submit your circuit\n",
206 | "\n",
207 | "from qc_grader.challenges.spring_2023 import grade_ex2b\n",
208 | "\n",
209 | "grade_ex2b(qc)"
210 | ]
211 | },
212 | {
213 | "cell_type": "markdown",
214 | "id": "2d45bf84-f32b-4dd9-8e73-b8ec920e8b39",
215 | "metadata": {
216 | "tags": []
217 | },
218 | "source": [
219 | "### 연습 3\n",
220 | "\n",
221 | "이제 앨리스는 가지고 있는 두 큐비트에 대해 측정을 수행하고 결과를 두 개의 클래식 비트에 저장합니다. 이어서, 앨리스는 이 결과를 밥에게 전송합니다. \n",
222 | "\n",
223 | "이어지는 코드셀을 완성하여 앨리스는 큐비트 $a$를 고전 비트 $c0$에, 큐비트 $s$를 고전 비트 $c1$로 측정하도록 합시다.\n"
224 | ]
225 | },
226 | {
227 | "cell_type": "code",
228 | "execution_count": null,
229 | "id": "345bc52c-7745-46a3-90e7-a0e6a03604d5",
230 | "metadata": {
231 | "tags": []
232 | },
233 | "outputs": [],
234 | "source": [
235 | "def measure_and_send(qr: QuantumRegister, cr: ClassicalRegister):\n",
236 | " \"\"\"Measures qubits a & b and 'sends' the results to Bob\"\"\"\n",
237 | " qc = alice_gates(qr, cr)\n",
238 | " qc.barrier() # Use barrier to separate steps\n",
239 | " s, a, b = qr\n",
240 | " c0, c1, c2 = cr\n",
241 | "\n",
242 | " ####### your code goes here #######\n",
243 | "\n",
244 | " return qc"
245 | ]
246 | },
247 | {
248 | "cell_type": "code",
249 | "execution_count": null,
250 | "id": "b1c3ec5d-ce66-455c-a2fe-6cca03dd87f4",
251 | "metadata": {
252 | "tags": []
253 | },
254 | "outputs": [],
255 | "source": [
256 | "qc = measure_and_send(qr, cr)\n",
257 | "qc.draw(\"mpl\", cregbundle=False)"
258 | ]
259 | },
260 | {
261 | "cell_type": "code",
262 | "execution_count": null,
263 | "id": "76b0c0b2-ed71-4eb7-b4d9-9b725a22fccb",
264 | "metadata": {
265 | "tags": []
266 | },
267 | "outputs": [],
268 | "source": [
269 | "# Submit your circuit\n",
270 | "\n",
271 | "from qc_grader.challenges.spring_2023 import grade_ex2c\n",
272 | "\n",
273 | "grade_ex2c(qc)"
274 | ]
275 | },
276 | {
277 | "cell_type": "markdown",
278 | "id": "1fec0216-f312-430e-9940-0ab0ffd1beca",
279 | "metadata": {},
280 | "source": [
281 | "### 연습 4\n",
282 | "\n",
283 | "이 단계에서, 큐비트 $b$를 가지고 있는 밥은, 앨리스로 받은 고전 비트의 정보에 따라 특정한 양자 게이트를 양자 회로에 추가합니다:\n",
284 | "\n",
285 | "- 비트가 `00`이면 어떠한 양자 게이트도 추가하지 않습니다. \n",
286 | "- 비트가 `01`이면 𝑋 게이트(Pauli-X 또는 비트 플립 게이트라고도 함)를 적용 합니다. \n",
287 | "- 전달 받은 비트가 `01`이라면 𝑍 게이트(Pauli-Z 또는 위상 플립 게이트라고도 함)를 적용해야 합니다. \n",
288 | "- 마지막으로 비트가 `11`이면 𝑍 및 𝑋 게이트를 차례로 적용하는 결합된 𝑍𝑋 게이트를 적용합니다. \n"
289 | ]
290 | },
291 | {
292 | "cell_type": "code",
293 | "execution_count": null,
294 | "id": "e61ddfa4-e536-46dd-b5a7-efe15f3ad617",
295 | "metadata": {
296 | "tags": []
297 | },
298 | "outputs": [],
299 | "source": [
300 | "def bob_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
301 | " \"\"\"Uses qc.if_test to control which gates are dynamically added\"\"\"\n",
302 | " qc = measure_and_send(qr, cr)\n",
303 | " qc.barrier() # Use barrier to separate steps\n",
304 | " s, a, b = qr\n",
305 | " c0, c1, c2 = cr\n",
306 | "\n",
307 | " ####### your code goes here #######\n",
308 | "\n",
309 | " return qc"
310 | ]
311 | },
312 | {
313 | "cell_type": "code",
314 | "execution_count": null,
315 | "id": "ff619db6-282a-450e-9b7c-38b2838cfdeb",
316 | "metadata": {
317 | "tags": []
318 | },
319 | "outputs": [],
320 | "source": [
321 | "qc = bob_gates(qr, cr)\n",
322 | "qc.draw(\"mpl\", cregbundle=False)"
323 | ]
324 | },
325 | {
326 | "cell_type": "code",
327 | "execution_count": null,
328 | "id": "8ab0270f-f909-4239-bb52-e36410497c21",
329 | "metadata": {
330 | "tags": []
331 | },
332 | "outputs": [],
333 | "source": [
334 | "# Submit your circuit\n",
335 | "\n",
336 | "from qc_grader.challenges.spring_2023 import grade_ex2d\n",
337 | "\n",
338 | "grade_ex2d(qc)"
339 | ]
340 | },
341 | {
342 | "cell_type": "markdown",
343 | "id": "74dc4ac1-d643-468e-a13c-509e2a12d77b",
344 | "metadata": {},
345 | "source": [
346 | "이제 밥은 자신의 큐비트를 클래식 비트 $c2$로 측정합니다. 이 양자 회로에 대해 측정을 여러번 반복한 후 측정된 결과의 통계값을 분석하여 순간 이동이 잘 작동했는지 확인할 수 있습니다. "
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "execution_count": null,
352 | "id": "6223a197-48b8-4b7b-889c-4bf317793a27",
353 | "metadata": {
354 | "tags": []
355 | },
356 | "outputs": [],
357 | "source": [
358 | "teleportation_circuit = bob_gates(qr, cr)\n",
359 | "s, a, b = qr\n",
360 | "c0, c1, c2 = cr\n",
361 | "teleportation_circuit.measure(b, c2)\n",
362 | "teleportation_circuit.draw(\"mpl\")"
363 | ]
364 | },
365 | {
366 | "cell_type": "markdown",
367 | "id": "3780a15e-4a86-4d5a-af4c-8662f4462fb9",
368 | "metadata": {},
369 | "source": [
370 | "순간이동 회로가 완성되었으니, 이제 ~~캡틴 Kirk를 이상한 행성의 표면으로 전송~~ 양자 상태를 생성하고 순간이동한 다음 시뮬레이터에서 회로를 실행해 봅시다."
371 | ]
372 | },
373 | {
374 | "cell_type": "markdown",
375 | "id": "977a9fe6",
376 | "metadata": {},
377 | "source": [
378 | "### 연습 5\n",
379 | "\n",
380 | "다음 코드 셀에서 전체 양자 순간이동 회로를 다음의 단계로 `teleport_superposition_circuit` 라는 이름으로 작성합니다. \n",
381 | "\n",
382 | "- 상태 준비 회로를 작성합니다. 큐비트 $s$를 각도 $\\pi / 4$로 $R_x$ 회전을 적용하여 준비합니다.\n",
383 | "- 상태 준비 회로와 앞서 제작한 양자 전송 회로와 결합합니다.\n"
384 | ]
385 | },
386 | {
387 | "cell_type": "code",
388 | "execution_count": null,
389 | "id": "89fa5bdb-eb09-4fb8-9913-6fd6bb9f8ad2",
390 | "metadata": {
391 | "tags": []
392 | },
393 | "outputs": [],
394 | "source": [
395 | "import math\n",
396 | "\n",
397 | "teleport_superposition_circuit: QuantumCircuit\n",
398 | "\n",
399 | "####### your code goes here #######\n",
400 | "\n",
401 | "\n",
402 | "# Uncomment this line to draw your circuit\n",
403 | "teleport_superposition_circuit.draw(\"mpl\", cregbundle=False)"
404 | ]
405 | },
406 | {
407 | "cell_type": "code",
408 | "execution_count": null,
409 | "id": "1e0ef91c-964a-4fd6-ab52-36c859b69b13",
410 | "metadata": {
411 | "tags": []
412 | },
413 | "outputs": [],
414 | "source": [
415 | "from qiskit import transpile\n",
416 | "from qiskit_aer import AerSimulator\n",
417 | "from qiskit.visualization import plot_histogram\n",
418 | "\n",
419 | "sim = AerSimulator()\n",
420 | "transpiled_circuit = transpile(teleport_superposition_circuit, sim)\n",
421 | "\n",
422 | "# run job\n",
423 | "shots = 1000\n",
424 | "job = sim.run(transpiled_circuit, shots=shots, dynamic=True)\n",
425 | "\n",
426 | "# Get the results and display them\n",
427 | "exp_result = job.result()\n",
428 | "exp_counts = exp_result.get_counts()\n",
429 | "plot_histogram(exp_counts)"
430 | ]
431 | },
432 | {
433 | "cell_type": "markdown",
434 | "id": "80e72c0a-8a4e-4d29-92a7-022d3882552a",
435 | "metadata": {},
436 | "source": [
437 | "이제 밥의 측정 분포 결과만을 얻기 위해 다른 측정된 비트에 대해 한계화(marginalizing)합니다."
438 | ]
439 | },
440 | {
441 | "cell_type": "code",
442 | "execution_count": null,
443 | "id": "96a1fd3b-693b-4cd4-bb51-96f676dd1759",
444 | "metadata": {
445 | "tags": []
446 | },
447 | "outputs": [],
448 | "source": [
449 | "# trace out Bob's results on qubit 2\n",
450 | "from qiskit.result import marginal_counts\n",
451 | "\n",
452 | "bobs_counts = marginal_counts(exp_counts, [qr.index(b)])\n",
453 | "plot_histogram(bobs_counts)"
454 | ]
455 | },
456 | {
457 | "cell_type": "markdown",
458 | "id": "6a33717b",
459 | "metadata": {},
460 | "source": [
461 | "한계 분포(marginal distribution)은 이상적인 결과에 가까울 것입니다. "
462 | ]
463 | },
464 | {
465 | "cell_type": "code",
466 | "execution_count": null,
467 | "id": "475e3774-da15-483b-9d2d-af54a8e0e568",
468 | "metadata": {
469 | "tags": []
470 | },
471 | "outputs": [],
472 | "source": [
473 | "from qc_grader.challenges.spring_2023 import grade_ex2e\n",
474 | "\n",
475 | "grade_ex2e(bobs_counts)"
476 | ]
477 | },
478 | {
479 | "cell_type": "markdown",
480 | "id": "9baa3099-7577-4bf9-9d1f-e0c54dc384b8",
481 | "metadata": {},
482 | "source": [
483 | "이제 ~~커크 선장~~ 앨리스의 큐비트가 안전하게 전송되었다고 확인했으니, 이 양자 전송 회로를 실제 하드웨어에서 실행해 봅시다."
484 | ]
485 | },
486 | {
487 | "cell_type": "code",
488 | "execution_count": null,
489 | "id": "ca2f737c-a21f-4727-b14d-0e7e315631ba",
490 | "metadata": {
491 | "tags": []
492 | },
493 | "outputs": [],
494 | "source": [
495 | "from qiskit_ibm_provider import IBMProvider\n",
496 | "\n",
497 | "provider = IBMProvider()"
498 | ]
499 | },
500 | {
501 | "cell_type": "code",
502 | "execution_count": null,
503 | "id": "da33a9fb-6b6c-48a4-a1b0-dfca70474e22",
504 | "metadata": {
505 | "tags": []
506 | },
507 | "outputs": [],
508 | "source": [
509 | "hub = \"YOUR_HUB\"\n",
510 | "group = \"YOUR_GROUP\"\n",
511 | "project = \"YOUR_PROJECT\"\n",
512 | "\n",
513 | "backend_name = \"ibm_peekskill\"\n",
514 | "backend = provider.get_backend(backend_name, instance=f\"{hub}/{group}/{project}\")"
515 | ]
516 | },
517 | {
518 | "cell_type": "code",
519 | "execution_count": null,
520 | "id": "fe48f446-849f-46e9-b0a4-1dd5225db403",
521 | "metadata": {
522 | "tags": []
523 | },
524 | "outputs": [],
525 | "source": [
526 | "# backend.target.add_instruction(IfElseOp, name=\"if_else\") # Uncomment if necessary\n",
527 | "qc_transpiled = transpile(teleport_superposition_circuit, backend)"
528 | ]
529 | },
530 | {
531 | "cell_type": "code",
532 | "execution_count": null,
533 | "id": "cee84182-a90d-44b7-b44d-87309202cbc3",
534 | "metadata": {
535 | "tags": []
536 | },
537 | "outputs": [],
538 | "source": [
539 | "job = backend.run(qc_transpiled, shots=1000, dynamic=True)\n",
540 | "job_id = job.job_id()\n",
541 | "print(job_id)"
542 | ]
543 | },
544 | {
545 | "cell_type": "markdown",
546 | "id": "c7e47cc1",
547 | "metadata": {},
548 | "source": [
549 | "실제 백엔드에 실행하는데에는 시간이 필요하므로 일반적으로 job_id를 통해 작업을 시간이 지난 후 불러들여서 사용합니다. \n",
550 | "다음의 코드는 job_id를 통해 작업을 불러들이고 실행 상태를 점검합니다. 사용법은 다음과 같습니다."
551 | ]
552 | },
553 | {
554 | "cell_type": "code",
555 | "execution_count": null,
556 | "id": "aedeec1b",
557 | "metadata": {},
558 | "outputs": [],
559 | "source": [
560 | "retrieve_job = provider.retrieve_job(job.job_id())\n",
561 | "retrieve_job.status()"
562 | ]
563 | },
564 | {
565 | "cell_type": "markdown",
566 | "id": "13bd0ea5",
567 | "metadata": {},
568 | "source": [
569 | "작업이 완료되었다면 결과를 불러들여봅시다."
570 | ]
571 | },
572 | {
573 | "cell_type": "code",
574 | "execution_count": null,
575 | "id": "fc8458f1-43fd-48b2-a50c-65771262cbf1",
576 | "metadata": {
577 | "tags": []
578 | },
579 | "outputs": [],
580 | "source": [
581 | "# Get the results and display them\n",
582 | "exp_result = retrieve_job.result()\n",
583 | "exp_counts = exp_result.get_counts()\n",
584 | "plot_histogram(exp_counts)"
585 | ]
586 | },
587 | {
588 | "cell_type": "code",
589 | "execution_count": null,
590 | "id": "88ddf3c8-732f-4825-a1b1-376bce0ab614",
591 | "metadata": {},
592 | "outputs": [],
593 | "source": [
594 | "# trace out Bob's results on qubit 2\n",
595 | "from qiskit.result import marginal_counts\n",
596 | "\n",
597 | "bobs_qubit = 2\n",
598 | "bobs_counts = marginal_counts(exp_counts, [bobs_qubit])\n",
599 | "plot_histogram(bobs_counts)"
600 | ]
601 | }
602 | ],
603 | "metadata": {
604 | "kernelspec": {
605 | "display_name": "Python 3 (ipykernel)",
606 | "language": "python",
607 | "name": "python3"
608 | },
609 | "language_info": {
610 | "codemirror_mode": {
611 | "name": "ipython",
612 | "version": 3
613 | },
614 | "file_extension": ".py",
615 | "mimetype": "text/x-python",
616 | "name": "python",
617 | "nbconvert_exporter": "python",
618 | "pygments_lexer": "ipython3",
619 | "version": "3.9.0"
620 | },
621 | "widgets": {
622 | "application/vnd.jupyter.widget-state+json": {
623 | "state": {},
624 | "version_major": 2,
625 | "version_minor": 0
626 | }
627 | }
628 | },
629 | "nbformat": 4,
630 | "nbformat_minor": 5
631 | }
632 |
--------------------------------------------------------------------------------
/content/lab_2/lab2.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "0ac9dd0b-210c-470e-8313-5cf7f7c57b65",
6 | "metadata": {},
7 | "source": [
8 | "# Lab 2: Quantum teleportation\n",
9 | "\n",
10 | "Welcome to this lab on quantum teleportation in which you'll solve a problem that Alice and Bob have been having. Relax, it's not a relationship problem! Alice possesses a qubit in an unknown state $\\lvert \\psi \\rangle$ and she wishes to transfer this quantum state to Bob. However, they are very far apart and lack any means to transfer quantum information directly, only classical information. Is it possible to achieve their goal?\n",
11 | "\n",
12 | "It turns out that if Alice and Bob share an entangled qubit pair, she can transfer her qubit state to Bob by sending two bits of classical information. This process is known as teleportation because, at the end, Bob will possess |ψ⟩, and Alice will no longer have it."
13 | ]
14 | },
15 | {
16 | "cell_type": "markdown",
17 | "id": "11a966b2-a7c1-4584-87b2-1b8e4277f997",
18 | "metadata": {},
19 | "source": [
20 | "## Background\n",
21 | "\n",
22 | "Quantum teleportation is a protocol that allows the transfer of quantum information from one qubit to another using entanglement and classical communication. It was proposed by Charles Bennett, Gilles Brassard, Claude Crépeau, Richard Jozsa, Asher Peres, and William Wootters in 1993. The process does not transmit the qubit itself but rather transfers the quantum state from the source qubit to the target qubit.\n",
23 | "\n",
24 | "The protocol requires three qubits:\n",
25 | "\n",
26 | "1. The qubit to be teleported (Alice's qubit)\n",
27 | "2. One half of an entangled pair of qubits (Alice's second qubit)\n",
28 | "3. The other half of the entangled pair (Bob's qubit)\n",
29 | "\n",
30 | "The protocol can be summarized in the following steps:\n",
31 | "\n",
32 | "1. Create an entangled pair of qubits (Bell pair) shared between Alice and Bob.\n",
33 | "2. Alice performs a Bell basis measurement on her two qubits.\n",
34 | "3. Alice sends the classical results of her measurement to Bob.\n",
35 | "4. Bob applies appropriate quantum gates based on Alice's measurement results to obtain the teleported state."
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "id": "a26fb942-ca66-4bea-85f5-f8f13d013d5e",
41 | "metadata": {},
42 | "source": [
43 | "## Implementation\n",
44 | "\n",
45 | "In order to transfer a quantum bit, Alice and Bob require the help of a third party who provides them with a pair of entangled qubits. Next, Alice carries out certain operations on her qubit and shares the results with Bob through a classical communication channel. Finally, Bob performs a series of operations on his end to successfully obtain Alice's qubit. Now, let's delve deeper into each of these steps."
46 | ]
47 | },
48 | {
49 | "cell_type": "markdown",
50 | "id": "71cdf58d-0d4d-43f0-b427-3a3ebca842f5",
51 | "metadata": {
52 | "tags": []
53 | },
54 | "source": [
55 | "Our quantum circuit will consist of 3 qubits and 3 classical bits. The qubits will be named as follows:\n",
56 | "- $s$: The \"source\" qubit containing the state $\\lvert \\psi \\rangle$ which Alice wishes to transmit to Bob.\n",
57 | "- $a$: The qubit which will initially store Alice's half of the entangled Bell pair.\n",
58 | "- $b$: The qubit which will initially store Bob's half of the entangled Bell pair.\n",
59 | "\n",
60 | "The teleportation protocol itself requires 2 classical bits, and we include a third one to use for measuring Bob's final state. The classical bits will be named as follows:\n",
61 | "- $c0$: The classical bit that Alice uses to measure $a$.\n",
62 | "- $c1$: The classical bit that Alice uses to measure $s$.\n",
63 | "- $c2$: The classical bit that Bob uses to measure $b$."
64 | ]
65 | },
66 | {
67 | "cell_type": "markdown",
68 | "id": "bad695dc",
69 | "metadata": {},
70 | "source": [
71 | "### Exercise 1\n",
72 | "\n",
73 | "Utilize two qubits to generate an entangled Bell pair state $\\frac{\\lvert 00 \\rangle + \\lvert 11 \\rangle}{\\sqrt{2}}$. Qubit 𝑎 is allocated to Alice, while qubit 𝑏 is designated for Bob.\n",
74 | "\n",
75 | "*Hint*: This state can be generated using a Hadamard gate and a CNOT gate."
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "execution_count": null,
81 | "id": "d9a9810a-8ec5-4e0e-823d-6865e810b34d",
82 | "metadata": {
83 | "tags": []
84 | },
85 | "outputs": [],
86 | "source": [
87 | "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
88 | "from qiskit.circuit import Qubit, Clbit\n",
89 | "\n",
90 | "\n",
91 | "def create_bell_pair(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
92 | " \"\"\"Creates a bell pair between qubits a and b.\"\"\"\n",
93 | " qc = QuantumCircuit(qr, cr)\n",
94 | " # unpack qubits\n",
95 | " # the first qubit is s but we won't be using it in this exercise\n",
96 | " _, a, b = qr\n",
97 | "\n",
98 | " ####### your code goes here #######\n",
99 | "\n",
100 | " return qc"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": null,
106 | "id": "7897fcca-e31a-4b44-9e19-16fbeb85a20d",
107 | "metadata": {
108 | "tags": []
109 | },
110 | "outputs": [],
111 | "source": [
112 | "qr = QuantumRegister(3, name=\"q\")\n",
113 | "cr = ClassicalRegister(3, name=\"c\")\n",
114 | "qc = create_bell_pair(qr, cr)\n",
115 | "\n",
116 | "qc.draw(\"mpl\")"
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": null,
122 | "id": "d00f07df-5245-47c7-858b-3ae6cbafc475",
123 | "metadata": {
124 | "tags": []
125 | },
126 | "outputs": [],
127 | "source": [
128 | "# Submit your circuit\n",
129 | "\n",
130 | "from qc_grader.challenges.spring_2023 import grade_ex2a\n",
131 | "\n",
132 | "grade_ex2a(qc)"
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "id": "b6b5ec32-e8ae-4475-a0ea-5314acf49a4f",
138 | "metadata": {},
139 | "source": [
140 | "Let's assume Alice has qubit $a$ and Bob has qubit $b$ once they separate. Perhaps they really are having a relationship issue 😉."
141 | ]
142 | },
143 | {
144 | "cell_type": "markdown",
145 | "id": "6ba11110",
146 | "metadata": {},
147 | "source": [
148 | "### Exercise 2\n",
149 | "\n",
150 | "Perform the next steps of the protocol:\n",
151 | "1. Alice applies a CNOT gate with $s$ (the qubit containing $\\lvert \\psi \\rangle$) as the control and $a$ as the target.\n",
152 | "2. Alice applies a Hadamard gate to $s$."
153 | ]
154 | },
155 | {
156 | "cell_type": "code",
157 | "execution_count": null,
158 | "id": "34d7bcd6-166b-4745-8ede-f8aa1872d434",
159 | "metadata": {
160 | "tags": []
161 | },
162 | "outputs": [],
163 | "source": [
164 | "def alice_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
165 | " \"\"\"Creates Alices's gates\"\"\"\n",
166 | " qc = create_bell_pair(qr, cr)\n",
167 | " qc.barrier() # Use barrier to separate steps\n",
168 | " s, a, b = qr\n",
169 | "\n",
170 | " ####### your code goes here #######\n",
171 | "\n",
172 | " return qc"
173 | ]
174 | },
175 | {
176 | "cell_type": "code",
177 | "execution_count": null,
178 | "id": "3a5096db-1b92-45df-ac1b-52392356b543",
179 | "metadata": {
180 | "tags": []
181 | },
182 | "outputs": [],
183 | "source": [
184 | "qc = alice_gates(qr, cr)\n",
185 | "qc.draw(\"mpl\")"
186 | ]
187 | },
188 | {
189 | "cell_type": "code",
190 | "execution_count": null,
191 | "id": "66cead66-9c0e-4e7c-a196-efa456e6764b",
192 | "metadata": {
193 | "tags": []
194 | },
195 | "outputs": [],
196 | "source": [
197 | "# Submit your circuit\n",
198 | "\n",
199 | "from qc_grader.challenges.spring_2023 import grade_ex2b\n",
200 | "\n",
201 | "grade_ex2b(qc)"
202 | ]
203 | },
204 | {
205 | "cell_type": "markdown",
206 | "id": "2d45bf84-f32b-4dd9-8e73-b8ec920e8b39",
207 | "metadata": {
208 | "tags": []
209 | },
210 | "source": [
211 | "### Exercise 3\n",
212 | "\n",
213 | "In this step, Alice performs a measurement on both qubits in her possession and saves the results in two classical bits. Afterward, she sends these two bits to Bob.\n",
214 | "\n",
215 | "Complete the following code cell so that Alice measures qubit $a$ into classical bit $c0$ and qubit $s$ into classical bit $c1$."
216 | ]
217 | },
218 | {
219 | "cell_type": "code",
220 | "execution_count": null,
221 | "id": "345bc52c-7745-46a3-90e7-a0e6a03604d5",
222 | "metadata": {
223 | "tags": []
224 | },
225 | "outputs": [],
226 | "source": [
227 | "def measure_and_send(qr: QuantumRegister, cr: ClassicalRegister):\n",
228 | " \"\"\"Measures qubits a & b and 'sends' the results to Bob\"\"\"\n",
229 | " qc = alice_gates(qr, cr)\n",
230 | " qc.barrier() # Use barrier to separate steps\n",
231 | " s, a, b = qr\n",
232 | " c0, c1, c2 = cr\n",
233 | "\n",
234 | " ####### your code goes here #######\n",
235 | "\n",
236 | " return qc"
237 | ]
238 | },
239 | {
240 | "cell_type": "code",
241 | "execution_count": null,
242 | "id": "b1c3ec5d-ce66-455c-a2fe-6cca03dd87f4",
243 | "metadata": {
244 | "tags": []
245 | },
246 | "outputs": [],
247 | "source": [
248 | "qc = measure_and_send(qr, cr)\n",
249 | "qc.draw(\"mpl\", cregbundle=False)"
250 | ]
251 | },
252 | {
253 | "cell_type": "code",
254 | "execution_count": null,
255 | "id": "76b0c0b2-ed71-4eb7-b4d9-9b725a22fccb",
256 | "metadata": {
257 | "tags": []
258 | },
259 | "outputs": [],
260 | "source": [
261 | "# Submit your circuit\n",
262 | "\n",
263 | "from qc_grader.challenges.spring_2023 import grade_ex2c\n",
264 | "\n",
265 | "grade_ex2c(qc)"
266 | ]
267 | },
268 | {
269 | "cell_type": "markdown",
270 | "id": "1fec0216-f312-430e-9940-0ab0ffd1beca",
271 | "metadata": {},
272 | "source": [
273 | "### Exercise 4\n",
274 | "\n",
275 | "In this step, Bob, who is already in possession of qubit $b$, dynamically adds specific gates to the circuit based on the state of the classical bits received from Alice:\n",
276 | "\n",
277 | "- If the bits are `00`, no action is required.\n",
278 | "- If they are `01`, an 𝑋 gate (also known as a Pauli-X or a bit-flip gate) should be applied.\n",
279 | "- For bits `10`, a 𝑍 gate (also known as a Pauli-Z or a phase-flip gate) should be applied. \n",
280 | "- Lastly, if the classical bits are `11`, a combined 𝑍𝑋 gate should be applied, which involves applying both the 𝑍 and 𝑋 gates in sequence."
281 | ]
282 | },
283 | {
284 | "cell_type": "code",
285 | "execution_count": null,
286 | "id": "e61ddfa4-e536-46dd-b5a7-efe15f3ad617",
287 | "metadata": {
288 | "tags": []
289 | },
290 | "outputs": [],
291 | "source": [
292 | "def bob_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
293 | " \"\"\"Uses qc.if_test to control which gates are dynamically added\"\"\"\n",
294 | " qc = measure_and_send(qr, cr)\n",
295 | " qc.barrier() # Use barrier to separate steps\n",
296 | " s, a, b = qr\n",
297 | " c0, c1, c2 = cr\n",
298 | "\n",
299 | " ####### your code goes here #######\n",
300 | "\n",
301 | " return qc"
302 | ]
303 | },
304 | {
305 | "cell_type": "code",
306 | "execution_count": null,
307 | "id": "ff619db6-282a-450e-9b7c-38b2838cfdeb",
308 | "metadata": {
309 | "tags": []
310 | },
311 | "outputs": [],
312 | "source": [
313 | "qc = bob_gates(qr, cr)\n",
314 | "qc.draw(\"mpl\", cregbundle=False)"
315 | ]
316 | },
317 | {
318 | "cell_type": "code",
319 | "execution_count": null,
320 | "id": "8ab0270f-f909-4239-bb52-e36410497c21",
321 | "metadata": {
322 | "tags": []
323 | },
324 | "outputs": [],
325 | "source": [
326 | "# Submit your circuit\n",
327 | "\n",
328 | "from qc_grader.challenges.spring_2023 import grade_ex2d\n",
329 | "\n",
330 | "grade_ex2d(qc)"
331 | ]
332 | },
333 | {
334 | "cell_type": "markdown",
335 | "id": "74dc4ac1-d643-468e-a13c-509e2a12d77b",
336 | "metadata": {},
337 | "source": [
338 | "We will now have Bob measure his qubit into classical bit $c2$. After repeating the entire experiment multiple times, we can gather statistics on the measurement results to confirm that the teleportation worked correctly."
339 | ]
340 | },
341 | {
342 | "cell_type": "code",
343 | "execution_count": null,
344 | "id": "6223a197-48b8-4b7b-889c-4bf317793a27",
345 | "metadata": {
346 | "tags": []
347 | },
348 | "outputs": [],
349 | "source": [
350 | "teleportation_circuit = bob_gates(qr, cr)\n",
351 | "s, a, b = qr\n",
352 | "c0, c1, c2 = cr\n",
353 | "teleportation_circuit.measure(b, c2)\n",
354 | "teleportation_circuit.draw(\"mpl\")"
355 | ]
356 | },
357 | {
358 | "cell_type": "markdown",
359 | "id": "3780a15e-4a86-4d5a-af4c-8662f4462fb9",
360 | "metadata": {},
361 | "source": [
362 | "Now that we have a teleportation circuit, let's ~~beam Captain Kirk to the surface of a strange planet~~ create and teleport a quantum state, and then run the circuit on a simulator."
363 | ]
364 | },
365 | {
366 | "cell_type": "markdown",
367 | "id": "977a9fe6",
368 | "metadata": {},
369 | "source": [
370 | "### Exercise 5\n",
371 | "\n",
372 | "In the following code cell, construct a full quantum teleportation circuit into the `teleport_superposition_circuit` variable, using the following steps:\n",
373 | "\n",
374 | "- Construct a state preparation circuit. Prepare the qubit $s$ by applying an $R_x$ rotation with angle $\\pi / 4$.\n",
375 | "- Combine the state preparation circuit with your previously built teleportation circuit."
376 | ]
377 | },
378 | {
379 | "cell_type": "code",
380 | "execution_count": null,
381 | "id": "89fa5bdb-eb09-4fb8-9913-6fd6bb9f8ad2",
382 | "metadata": {
383 | "tags": []
384 | },
385 | "outputs": [],
386 | "source": [
387 | "import math\n",
388 | "\n",
389 | "teleport_superposition_circuit: QuantumCircuit\n",
390 | "\n",
391 | "####### your code goes here #######\n",
392 | "\n",
393 | "\n",
394 | "# Uncomment this line to draw your circuit\n",
395 | "teleport_superposition_circuit.draw(\"mpl\", cregbundle=False)"
396 | ]
397 | },
398 | {
399 | "cell_type": "code",
400 | "execution_count": null,
401 | "id": "1e0ef91c-964a-4fd6-ab52-36c859b69b13",
402 | "metadata": {
403 | "tags": []
404 | },
405 | "outputs": [],
406 | "source": [
407 | "from qiskit import transpile\n",
408 | "from qiskit_aer import AerSimulator\n",
409 | "from qiskit.visualization import plot_histogram\n",
410 | "\n",
411 | "sim = AerSimulator()\n",
412 | "transpiled_circuit = transpile(teleport_superposition_circuit, sim)\n",
413 | "\n",
414 | "# run job\n",
415 | "shots = 1000\n",
416 | "job = sim.run(transpiled_circuit, shots=shots, dynamic=True)\n",
417 | "\n",
418 | "# Get the results and display them\n",
419 | "exp_result = job.result()\n",
420 | "exp_counts = exp_result.get_counts()\n",
421 | "plot_histogram(exp_counts)"
422 | ]
423 | },
424 | {
425 | "cell_type": "markdown",
426 | "id": "80e72c0a-8a4e-4d29-92a7-022d3882552a",
427 | "metadata": {},
428 | "source": [
429 | "Let's compute the distribution of just Bob's measurement by marginalizing over the other measured bits."
430 | ]
431 | },
432 | {
433 | "cell_type": "code",
434 | "execution_count": null,
435 | "id": "96a1fd3b-693b-4cd4-bb51-96f676dd1759",
436 | "metadata": {
437 | "tags": []
438 | },
439 | "outputs": [],
440 | "source": [
441 | "# trace out Bob's results on qubit 2\n",
442 | "from qiskit.result import marginal_counts\n",
443 | "\n",
444 | "bobs_counts = marginal_counts(exp_counts, [qr.index(b)])\n",
445 | "plot_histogram(bobs_counts)"
446 | ]
447 | },
448 | {
449 | "cell_type": "markdown",
450 | "id": "6a33717b",
451 | "metadata": {},
452 | "source": [
453 | "The marginal distribution should be somewhat close to the ideal probabilities."
454 | ]
455 | },
456 | {
457 | "cell_type": "code",
458 | "execution_count": null,
459 | "id": "475e3774-da15-483b-9d2d-af54a8e0e568",
460 | "metadata": {
461 | "tags": []
462 | },
463 | "outputs": [],
464 | "source": [
465 | "from qc_grader.challenges.spring_2023 import grade_ex2e\n",
466 | "\n",
467 | "grade_ex2e(bobs_counts)"
468 | ]
469 | },
470 | {
471 | "cell_type": "markdown",
472 | "id": "9baa3099-7577-4bf9-9d1f-e0c54dc384b8",
473 | "metadata": {},
474 | "source": [
475 | "Now that we're fairly certain that ~~Captain Kirk~~ Alice's qubit will teleport safely, let's execute the quantum teleportation circuit on real hardware."
476 | ]
477 | },
478 | {
479 | "cell_type": "code",
480 | "execution_count": null,
481 | "id": "ca2f737c-a21f-4727-b14d-0e7e315631ba",
482 | "metadata": {
483 | "tags": []
484 | },
485 | "outputs": [],
486 | "source": [
487 | "from qiskit_ibm_provider import IBMProvider\n",
488 | "\n",
489 | "provider = IBMProvider()"
490 | ]
491 | },
492 | {
493 | "cell_type": "code",
494 | "execution_count": null,
495 | "id": "da33a9fb-6b6c-48a4-a1b0-dfca70474e22",
496 | "metadata": {
497 | "tags": []
498 | },
499 | "outputs": [],
500 | "source": [
501 | "hub = \"YOUR_HUB\"\n",
502 | "group = \"YOUR_GROUP\"\n",
503 | "project = \"YOUR_PROJECT\"\n",
504 | "\n",
505 | "backend_name = \"ibm_peekskill\"\n",
506 | "backend = provider.get_backend(backend_name, instance=f\"{hub}/{group}/{project}\")"
507 | ]
508 | },
509 | {
510 | "cell_type": "code",
511 | "execution_count": null,
512 | "id": "fe48f446-849f-46e9-b0a4-1dd5225db403",
513 | "metadata": {
514 | "tags": []
515 | },
516 | "outputs": [],
517 | "source": [
518 | "# backend.target.add_instruction(IfElseOp, name=\"if_else\") # Uncomment if necessary\n",
519 | "qc_transpiled = transpile(teleport_superposition_circuit, backend)"
520 | ]
521 | },
522 | {
523 | "cell_type": "code",
524 | "execution_count": null,
525 | "id": "cee84182-a90d-44b7-b44d-87309202cbc3",
526 | "metadata": {
527 | "tags": []
528 | },
529 | "outputs": [],
530 | "source": [
531 | "job = backend.run(qc_transpiled, shots=1000, dynamic=True)"
532 | ]
533 | },
534 | {
535 | "cell_type": "markdown",
536 | "id": "334ff2bd",
537 | "metadata": {},
538 | "source": [
539 | "Because it takes time to run on the real backend, you typically use job_id to call in jobs after a time.\n",
540 | "The following code invokes jobs through job_id and checks the execution status. Here's how to use it."
541 | ]
542 | },
543 | {
544 | "cell_type": "code",
545 | "execution_count": null,
546 | "id": "de24e832",
547 | "metadata": {},
548 | "outputs": [],
549 | "source": [
550 | "retrieve_job = provider.retrieve_job(job.job_id())\n",
551 | "retrieve_job.status()"
552 | ]
553 | },
554 | {
555 | "cell_type": "markdown",
556 | "id": "3ab20774",
557 | "metadata": {},
558 | "source": [
559 | "If your job succesfully finished, let's import results."
560 | ]
561 | },
562 | {
563 | "cell_type": "code",
564 | "execution_count": null,
565 | "id": "fc8458f1-43fd-48b2-a50c-65771262cbf1",
566 | "metadata": {
567 | "tags": []
568 | },
569 | "outputs": [],
570 | "source": [
571 | "# Get the results and display them\n",
572 | "exp_result = retrieve_job.result()\n",
573 | "exp_counts = exp_result.get_counts()\n",
574 | "plot_histogram(exp_counts)"
575 | ]
576 | },
577 | {
578 | "cell_type": "code",
579 | "execution_count": null,
580 | "id": "88ddf3c8-732f-4825-a1b1-376bce0ab614",
581 | "metadata": {},
582 | "outputs": [],
583 | "source": [
584 | "# trace out Bob's results on qubit 2\n",
585 | "from qiskit.result import marginal_counts\n",
586 | "\n",
587 | "bobs_qubit = 2\n",
588 | "bobs_counts = marginal_counts(exp_counts, [bobs_qubit])\n",
589 | "plot_histogram(bobs_counts)"
590 | ]
591 | }
592 | ],
593 | "metadata": {
594 | "kernelspec": {
595 | "display_name": "spring-challenge-2023",
596 | "language": "python",
597 | "name": "spring-challenge-2023"
598 | },
599 | "language_info": {
600 | "codemirror_mode": {
601 | "name": "ipython",
602 | "version": 3
603 | },
604 | "file_extension": ".py",
605 | "mimetype": "text/x-python",
606 | "name": "python",
607 | "nbconvert_exporter": "python",
608 | "pygments_lexer": "ipython3",
609 | "version": "3.9.15"
610 | },
611 | "widgets": {
612 | "application/vnd.jupyter.widget-state+json": {
613 | "state": {},
614 | "version_major": 2,
615 | "version_minor": 0
616 | }
617 | }
618 | },
619 | "nbformat": 4,
620 | "nbformat_minor": 5
621 | }
622 |
--------------------------------------------------------------------------------
/content/lab_3/lab3.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "attachments": {},
5 | "cell_type": "markdown",
6 | "metadata": {},
7 | "source": [
8 | "# Lab 3: Iterative phase estimation\n",
9 | "\n",
10 | "The quantum phase estimation (QPE) algorithm is one of the most important and famous quantum algorithms. It is a key subroutine of Shor's factoring algorithm, as well as algorithms for quantum simulation. The textbook version of the algorithm uses a number of auxiliary qubits which scales with the desired precision, leading to circuits that are challenging to execute on today's noisy devices with limited qubit number and connectivity.\n",
11 | "\n",
12 | "Iterative phase estimation (IPE) is a variant of QPE which requires only one auxiliary qubit. In IPE, the auxiliary qubit is repeatedly measured, with the measurement results used to guide future quantum operations. Until the introduction of dynamic circuits, such classical feed-forward was impossible to execute on IBM's quantum hardware.\n",
13 | "\n",
14 | "In this lab, we will use the recently introduced dynamic circuits capabilities to implement IPE."
15 | ]
16 | },
17 | {
18 | "attachments": {},
19 | "cell_type": "markdown",
20 | "metadata": {},
21 | "source": [
22 | "## Background\n",
23 | "\n",
24 | "Like any phase estimation algorithm, IPE is designed to solve the following problem:\n",
25 | "\n",
26 | "**Problem statement:** Given a unitary matrix $U$ and an eigenstate $|\\Psi\\rangle$ of $U$ with an unknown eigenvalue $e^{i 2\\pi \\varphi}$, estimate the value of $\\varphi$.\n",
27 | "\n",
28 | "A few important details need to be clarified in this problem statement, namely, how $U$ and $|\\Psi\\rangle$ are specified. We assume that $U$ is given as a quantum circuit implementing $U$, and in fact, we assume we have the ability to efficiently implement the operations *controlled*-$U^{2^t}$ for positive integers $t$.\n",
29 | "This is the same assumption used in the original QPE algorithm.\n",
30 | "The eigenstate is also given as a quantum circuit: we assume we have the ability to efficiently prepare $|\\Psi\\rangle$.\n",
31 | "\n",
32 | "Let's first assume for simplicity that $\\varphi$ can have an exact binary expansion, that is, it can be written as\n",
33 | "$$\n",
34 | "\\varphi = \\varphi_1/2 + \\varphi_2/4 + \\cdots + \\varphi_m/2^m = 0.\\varphi_1 \\varphi_2 \\cdots \\varphi_m\n",
35 | "$$\n",
36 | "where in the final equality we are using \"decimal\" point notation in base 2.\n",
37 | "For simplicity, suppose $U$ is a unitary operator acting on one qubit (everything we say here also applies to the case where $U$ acts on multiple qubits). Since IPE requires an auxiliary qubit, we need a system of two qubits, $q_0$ and $q_1$, where $q_0$ is the auxiliary qubit and $q_1$ represents the physical system on which $U$ operates.\n",
38 | "\n",
39 | "Now, suppose that we initialize $q_0$ in the state $|+\\rangle = \\frac{|0\\rangle + |1\\rangle}{\\sqrt{2}}$ and $q_1$ in the state $|\\Psi \\rangle$.\n",
40 | "What happens if we apply the *controlled*-$U^{2^t}$ gate, with $q_0$ being the control and $q_1$ being the target?\n",
41 | "Since $|\\Psi \\rangle$ is an eigenstate of $U$ with eigenvalue $e^{i 2\\pi \\varphi}$, we have\n",
42 | "$$\n",
43 | "\\begin{align}\n",
44 | "|+\\rangle |\\Psi \\rangle &= \\left(\\frac{|0\\rangle + |1\\rangle}{\\sqrt{2}}\\right) |\\Psi \\rangle \\\\\n",
45 | "&= \\frac{|0\\rangle |\\Psi \\rangle + |1\\rangle |\\Psi \\rangle}{\\sqrt{2}} \\\\\n",
46 | "&\\xrightarrow{\\text{controlled-}U^{2^t}} \\frac{|0\\rangle |\\Psi \\rangle + e^{i 2 \\pi 2^{t} \\varphi} |1\\rangle |\\Psi \\rangle}{\\sqrt{2}} \\\\\n",
47 | "&= \\left(\\frac{|0\\rangle + e^{i 2 \\pi 2^{t} \\varphi} |1\\rangle}{\\sqrt{2}}\\right) |\\Psi \\rangle.\n",
48 | "\\end{align}\n",
49 | "$$\n",
50 | "That is, the state of the system qubit remains unchanged, while a phase of $e^{i 2 \\pi 2^{t} \\varphi}$ has been \"kicked back\" into the state of the auxiliary qubit.\n",
51 | "\n",
52 | "Now, note that\n",
53 | "$$\n",
54 | "e^{i 2 \\pi 2^{t} \\varphi} = e^{i 2 \\pi 2^{t} (0.\\varphi_1 \\varphi_2 \\cdots \\varphi_m)}\n",
55 | "= e^{i 2 \\pi (\\varphi_1 \\cdots \\varphi_t . \\varphi_{t + 1} \\cdots \\varphi_m)}\n",
56 | "= e^{i 2 \\pi (0. \\varphi_{t + 1} \\cdots \\varphi_m)},\n",
57 | "$$\n",
58 | "where in the last equality, the whole number part of the \"decimal\" representation of the phase has disappeared because $e^{i 2\\pi n} = 1$ for any integer $n$.\n",
59 | "For example:\n",
60 | "- for $t=0$, the phase would be $e^{i 2 \\pi 2^{0} \\varphi} = e^{i 2 \\pi \\varphi} = e^{i 2 \\pi 0.\\varphi_1 \\varphi_2 ... \\varphi_m}$\n",
61 | "- for $t=1$, the phase would be $e^{i 2 \\pi 2^{1} \\varphi}= e^{i 2 \\pi \\varphi_1} e^{i 2 \\pi 0.\\varphi_2 \\varphi_3 ... \\varphi_m} = e^{i 2 \\pi 0.\\varphi_2 \\varphi_3 ... \\varphi_m}$\n",
62 | "- for $t=2$, the phase would be $e^{i 2 \\pi 2^{2} \\varphi} = e^{i 2 \\pi 0.\\varphi_3 \\varphi_4 ... \\varphi_m}$\n",
63 | "- for $t=m-1$, the phase would be $e^{i 2 \\pi 2^{m-1} \\varphi} = e^{i 2 \\pi 0.\\varphi_m}$.\n",
64 | "\n",
65 | "In the last case where $t = m - 1$, the phase is $e^{i 2 \\pi 0.\\varphi_m}$, which is equal to $1$ if $\\varphi_m = 0$ and $-1$ if $\\varphi_m = 1$.\n",
66 | "In the first case, the auxiliary qubit $q_0$ would be in the state $|+\\rangle = \\frac{|0\\rangle + |1\\rangle}{\\sqrt{2}}$, and in the second case it would be\n",
67 | "in the state $|-\\rangle = \\frac{|0\\rangle - |1\\rangle}{\\sqrt{2}}$. Therefore, measuring the qubit in the Pauli $X$ basis would distinguish these cases with a 100\\% success rate.\n",
68 | "This is done by performing a Hadamard gate on the qubit before measuring it. In the first case we would measure 0 and in the second case we would measure 1;\n",
69 | "in other words, the measured bit would be equal to $\\varphi_m$.\n",
70 | "\n",
71 | "### The algorithm\n",
72 | "\n",
73 | "In the first step of the IPE algorithm, we directly measure the least significant bit of the phase $\\varphi$, $\\varphi_m$, by initializing the 2-qubit registers as described above ( $q_0 \\rightarrow |+\\rangle$ and $q_1 \\rightarrow |\\Psi \\rangle$ ), performing a *controlled*-$U^{2^{m-1}}$ operation, and measuring $q_0$ in the Pauli $X$ basis.\n",
74 | "\n",
75 | "in the second step, we initialize the systems in the same way and apply a *controlled*-$U^{2^{m-2}}$ operation. The relative phase in $q_0$ after these operations is now $e^{i 2 \\pi 0.\\varphi_{m-1}\\varphi_{m}}= e^{i 2 \\pi 0.\\varphi_{m-1}} e^{i 2 \\pi \\varphi_m/4}$. \n",
76 | "To extract the phase bit $\\varphi_{m-1}$, first perform a phase correction by rotating around the $Z$-axis by an angle $-2 \\pi \\varphi_m/4=-\\pi \\varphi_m/2$, which results in the state of $q_0$ to be $|0\\rangle + e^{i 2 \\pi 0.\\varphi_{m-1}} | 1 \\rangle$. Perform a measurement on $q_0$ in the Pauli $X$ basis to obtain the phase bit $\\varphi_{m-1}$. \n",
77 | "\n",
78 | "Therefore, the $k$-th step of the IPE, getting $\\varphi_{m-k+1}$, consists of the register initialization ($q_0$ in $|+\\rangle$, $q_1$ in $|\\Psi\\rangle$), the application of a *controlled*-$U^{2^{m-k}}$, a rotation around $Z$ of angle $\\omega_k = -2 \\pi 0.0\\varphi_{m-k+2} ... \\varphi_m$, and a measurement of $q_0$ in the Pauli $X$ basis: a Hadamard transform to $q_0$, and a measurement of $q_0$ in the computational basis. Note that $q_1$ remains in the state $|\\Psi\\rangle$ throughout the algorithm."
79 | ]
80 | },
81 | {
82 | "attachments": {},
83 | "cell_type": "markdown",
84 | "metadata": {},
85 | "source": [
86 | "## Implementation\n",
87 | "\n",
88 | "In this lab, we will perform IPE on the single-qubit $S$-gate. The $S$ gate is given by the matrix\n",
89 | "\n",
90 | "$$ S =\n",
91 | "\\begin{pmatrix}\n",
92 | "1 & 0\\\\\n",
93 | "0 & e^{i\\pi / 2}\n",
94 | "\\end{pmatrix}$$\n",
95 | "\n",
96 | "We will use the eigenstate $|\\Psi\\rangle = |1\\rangle$, which has eigenvalue $e^{i\\pi / 2}= e^{i2\\pi \\cdot 1/4}$. So we have $\\varphi = 1/4 = 0.01 = 0.\\varphi_1 \\varphi_2$. Since $\\varphi$ can be represented exactly with 2 bits, our quantum circuit implementation will use a classical register with two bits to store the result.\n",
97 | "\n",
98 | "The controlled-$S$ gate can be implemented using the controlled phase gate, available in Qiskit as `CPhaseGate`, which can also be applied by calling the `cp` method of a `QuantumCircuit`. The controlled phase gate is parameterized by an angle $\\theta$ and has the matrix\n",
99 | "$$\n",
100 | " \\text{CPhase}(\\theta) =\n",
101 | " \\begin{pmatrix}\n",
102 | " 1 & 0 & 0 & 0 \\\\\n",
103 | " 0 & 1 & 0 & 0 \\\\\n",
104 | " 0 & 0 & 1 & 0 \\\\\n",
105 | " 0 & 0 & 0 & e^{i\\theta}\n",
106 | " \\end{pmatrix}\n",
107 | "$$"
108 | ]
109 | },
110 | {
111 | "attachments": {},
112 | "cell_type": "markdown",
113 | "metadata": {},
114 | "source": [
115 | "\n",
116 | "### Step 1\n",
117 | "\n",
118 | "In the first step of the algorithm, we measure the least significant bit of $\\varphi$.\n",
119 | "\n",
120 | "#### Exercise 1\n",
121 | "\n",
122 | "Obtain the least significant bit of $\\varphi$ by performing the following steps:\n",
123 | "1. Initialize the qubits:\n",
124 | " - Apply a Hadamard on the auxiliary qubit.\n",
125 | " - Apply an X gate on the system qubit to put it in the $|1\\rangle$ state.\n",
126 | "2. Apply a *controlled*-$S^{2}$ gate by applying a `CPhaseGate` with the appropriate angle.\n",
127 | "3. Measure the auxiliary qubit in the $X$ basis:\n",
128 | " - Apply a Hadamard gate on the auxiliary qubit.\n",
129 | " - Measure it in the computational basis.\n",
130 | "\n",
131 | "The resulting circuit should look something like this:\n",
132 | "\n",
133 | ""
134 | ]
135 | },
136 | {
137 | "cell_type": "code",
138 | "execution_count": null,
139 | "metadata": {},
140 | "outputs": [],
141 | "source": [
142 | "from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister\n",
143 | "import numpy as np\n",
144 | "\n",
145 | "\n",
146 | "def step_1_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
147 | " # qr is a quantum register with 2 qubits\n",
148 | " # cr is a classical register with 2 bits\n",
149 | "\n",
150 | " qc = QuantumCircuit(qr, cr)\n",
151 | "\n",
152 | " ####### your code goes here #######\n",
153 | "\n",
154 | " return qc\n",
155 | "\n",
156 | "\n",
157 | "qr = QuantumRegister(2, \"q\")\n",
158 | "cr = ClassicalRegister(2, \"c\")\n",
159 | "qc = QuantumCircuit(qr, cr)\n",
160 | "qc = step_1_circuit(qr, cr)\n",
161 | "qc.draw(\"mpl\")"
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "execution_count": null,
167 | "metadata": {},
168 | "outputs": [],
169 | "source": [
170 | "# Submit your circuit\n",
171 | "\n",
172 | "from qc_grader.challenges.spring_2023 import grade_ex3a\n",
173 | "\n",
174 | "grade_ex3a(qc)"
175 | ]
176 | },
177 | {
178 | "attachments": {},
179 | "cell_type": "markdown",
180 | "metadata": {},
181 | "source": [
182 | "### Step 2\n",
183 | "\n",
184 | "In the first step, we measured the least significant bit $\\varphi_2$. In the second (and final) step, we extract the next bit $\\varphi_1$, which will involve applying a phase correction to cancel out the phase contribution from $\\varphi_2$. The phase correction depends on the value of the classical register holding $\\varphi_2$. We need dynamic circuits to perform this classical feedback! The phase correction can be applied using `PhaseGate` or by directly calling the `p` method of a QuantumCircuit.\n",
185 | "\n",
186 | "#### Exercise 2\n",
187 | "\n",
188 | "In this exercise, we begin with the circuit from Step 1, which you should have constructed in Exercise 1.\n",
189 | "\n",
190 | "Obtain the next bit of $\\varphi$ by performing the following steps:\n",
191 | "1. Reset and re-initialize the auxiliary qubit.\n",
192 | "2. Apply the controlled unitary gate.\n",
193 | "3. Measure the auxiliary qubit in the $X$ basis.\n",
194 | "\n",
195 | "The resulting circuit should look something like this:\n",
196 | "\n",
197 | ""
198 | ]
199 | },
200 | {
201 | "cell_type": "code",
202 | "execution_count": null,
203 | "metadata": {},
204 | "outputs": [],
205 | "source": [
206 | "def step_2_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
207 | " # qr is a quantum register with 2 qubits\n",
208 | " # cr is a classical register with 2 bits\n",
209 | "\n",
210 | " # begin with the circuit from Step 1\n",
211 | " qc = step_1_circuit(qr, cr)\n",
212 | "\n",
213 | " ####### your code goes here #######\n",
214 | "\n",
215 | " return qc\n",
216 | "\n",
217 | "\n",
218 | "qr = QuantumRegister(2, \"q\")\n",
219 | "cr = ClassicalRegister(2, \"c\")\n",
220 | "qc = QuantumCircuit(qr, cr)\n",
221 | "qc = step_2_circuit(qr, cr)\n",
222 | "qc.draw(\"mpl\")"
223 | ]
224 | },
225 | {
226 | "cell_type": "code",
227 | "execution_count": null,
228 | "metadata": {},
229 | "outputs": [],
230 | "source": [
231 | "# Submit your circuit\n",
232 | "\n",
233 | "from qc_grader.challenges.spring_2023 import grade_ex3b\n",
234 | "\n",
235 | "grade_ex3b(qc)"
236 | ]
237 | },
238 | {
239 | "attachments": {},
240 | "cell_type": "markdown",
241 | "metadata": {},
242 | "source": [
243 | "## Run on simulator\n",
244 | "\n",
245 | "Now that we have the complete circuit, let's first run it on a local simulator."
246 | ]
247 | },
248 | {
249 | "cell_type": "code",
250 | "execution_count": null,
251 | "metadata": {},
252 | "outputs": [],
253 | "source": [
254 | "from qiskit_aer import AerSimulator\n",
255 | "\n",
256 | "sim = AerSimulator()\n",
257 | "job = sim.run(qc, shots=1000)\n",
258 | "result = job.result()\n",
259 | "counts = result.get_counts()\n",
260 | "counts"
261 | ]
262 | },
263 | {
264 | "attachments": {},
265 | "cell_type": "markdown",
266 | "metadata": {},
267 | "source": [
268 | "If your circuit is correct, you should have gotten the bitstring `01` with 100% probability. This value corresponds to the phase written in binary as $\\varphi = 0.01 = 1/4$. Indeed, this is the correct phase!"
269 | ]
270 | },
271 | {
272 | "attachments": {},
273 | "cell_type": "markdown",
274 | "metadata": {},
275 | "source": [
276 | "### Exercise 3\n",
277 | "\n",
278 | "Construct an IPE circuit to estimate the phase of the T gate, whose matrix is given by\n",
279 | "\n",
280 | "$$ T =\n",
281 | "\\begin{pmatrix}\n",
282 | "1 & 0\\\\\n",
283 | "0 & e^{i\\pi / 4}\n",
284 | "\\end{pmatrix}$$\n",
285 | "\n",
286 | "How many bits are needed to represent the phase in this case?"
287 | ]
288 | },
289 | {
290 | "cell_type": "code",
291 | "execution_count": null,
292 | "metadata": {},
293 | "outputs": [],
294 | "source": [
295 | "from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister\n",
296 | "import numpy as np\n",
297 | "\n",
298 | "\n",
299 | "def t_gate_ipe_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
300 | " # qr is a quantum register with 2 qubits\n",
301 | " # cr is a classical register with 3 bits\n",
302 | "\n",
303 | " qc = QuantumCircuit(qr, cr)\n",
304 | "\n",
305 | " ####### your code goes here #######\n",
306 | "\n",
307 | " return qc\n",
308 | "\n",
309 | "\n",
310 | "qr = QuantumRegister(2, \"q\")\n",
311 | "cr = ClassicalRegister(3, \"c\")\n",
312 | "qc = QuantumCircuit(qr, cr)\n",
313 | "qc = t_gate_ipe_circuit(qr, cr)\n",
314 | "qc.draw(\"mpl\")"
315 | ]
316 | },
317 | {
318 | "cell_type": "code",
319 | "execution_count": null,
320 | "metadata": {},
321 | "outputs": [],
322 | "source": [
323 | "from qiskit_aer import AerSimulator\n",
324 | "\n",
325 | "sim = AerSimulator()\n",
326 | "job = sim.run(qc, shots=1000)\n",
327 | "result = job.result()\n",
328 | "counts = result.get_counts()\n",
329 | "counts"
330 | ]
331 | },
332 | {
333 | "cell_type": "code",
334 | "execution_count": null,
335 | "metadata": {},
336 | "outputs": [],
337 | "source": [
338 | "# Submit your circuit\n",
339 | "\n",
340 | "from qc_grader.challenges.spring_2023 import grade_ex3c\n",
341 | "\n",
342 | "grade_ex3c(qc)"
343 | ]
344 | },
345 | {
346 | "attachments": {},
347 | "cell_type": "markdown",
348 | "metadata": {},
349 | "source": [
350 | "### When the phase does not have an exact binary expansion\n",
351 | "\n",
352 | "Let's consider the case when the phase does not have an exact binary expansion, for example, $\\varphi = 1/3$.\n",
353 | "In this case, the single-qubit gate has the unitary\n",
354 | "\n",
355 | "$$ U =\n",
356 | "\\begin{pmatrix}\n",
357 | "1 & 0\\\\\n",
358 | "0 & e^{i2\\pi / 3}\n",
359 | "\\end{pmatrix}\n",
360 | "$$\n",
361 | "\n",
362 | "The angle $\\varphi = 1/3$ does not have an exact finite binary expansion. In contrast, it has the infinite binary expansion\n",
363 | "\n",
364 | "$$\n",
365 | "1/3 = 0.010101\\ldots\n",
366 | "$$\n",
367 | "\n",
368 | "In practice we work with a fixed number of bits of precision, so our goal is to obtain the closest value that can be represented with those bits. In the following example, we will use two bits of precision. In this case, the closest value is $0.01 = 1/4$. Because this value does not represent the exact phase, there is some probability that we will obtain a different, less precise result.\n",
369 | "\n",
370 | "In the following code cells, we construct and simulate an IPE circuit to measure the phase of this gate."
371 | ]
372 | },
373 | {
374 | "cell_type": "code",
375 | "execution_count": null,
376 | "metadata": {},
377 | "outputs": [],
378 | "source": [
379 | "from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister\n",
380 | "import numpy as np\n",
381 | "\n",
382 | "\n",
383 | "def u_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
384 | " # qr is a quantum register with 2 qubits\n",
385 | " # cr is a classical register with 2 bits\n",
386 | "\n",
387 | " qc = QuantumCircuit(qr, cr)\n",
388 | "\n",
389 | " # Initialization\n",
390 | " q0, q1 = qr\n",
391 | " qc.h(q0)\n",
392 | " qc.x(q1)\n",
393 | "\n",
394 | " # Apply control-U operator as many times as needed to get the least significant phase bit\n",
395 | " u_angle = 2 * np.pi / 3\n",
396 | " k = 1\n",
397 | " cphase_angle = u_angle * 2**k\n",
398 | " qc.cp(cphase_angle, q0, q1)\n",
399 | "\n",
400 | " # Measure the auxiliary qubit in x-basis into the first classical bit\n",
401 | " qc.h(q0)\n",
402 | " c0, c1 = cr\n",
403 | " qc.measure(q0, c0)\n",
404 | "\n",
405 | " # Reset and re-initialize the auxiliary qubit\n",
406 | " qc.reset(q0)\n",
407 | " qc.h(q0)\n",
408 | "\n",
409 | " # Apply phase correction conditioned on the first classical bit\n",
410 | " with qc.if_test((c0, 1)):\n",
411 | " qc.p(-np.pi / 2, q0)\n",
412 | "\n",
413 | " # Apply control-U operator as many times as needed to get the next phase bit\n",
414 | " k = 0\n",
415 | " cphase_angle = u_angle * 2**k\n",
416 | " qc.cp(cphase_angle, q0, q1)\n",
417 | "\n",
418 | " # Measure the auxiliary qubit in x-basis into the second classical bit\n",
419 | " qc.h(q0)\n",
420 | " qc.measure(q0, c1)\n",
421 | "\n",
422 | " return qc\n",
423 | "\n",
424 | "\n",
425 | "qr = QuantumRegister(2, \"q\")\n",
426 | "cr = ClassicalRegister(2, \"c\")\n",
427 | "qc = QuantumCircuit(qr, cr)\n",
428 | "qc = u_circuit(qr, cr)\n",
429 | "qc.draw(\"mpl\")"
430 | ]
431 | },
432 | {
433 | "cell_type": "code",
434 | "execution_count": null,
435 | "metadata": {},
436 | "outputs": [],
437 | "source": [
438 | "from qiskit_aer import AerSimulator\n",
439 | "\n",
440 | "sim = AerSimulator()\n",
441 | "job = sim.run(qc, shots=1000)\n",
442 | "result = job.result()\n",
443 | "counts = result.get_counts()\n",
444 | "print(counts)\n",
445 | "success_probability = counts[\"01\"] / counts.shots()\n",
446 | "print(f\"Success probability: {success_probability}\")"
447 | ]
448 | },
449 | {
450 | "attachments": {},
451 | "cell_type": "markdown",
452 | "metadata": {},
453 | "source": [
454 | "As you can see, this time, we are not guaranteed to obtain the desired result. A natural question to ask is: How can we boost the success probability?\n",
455 | "\n",
456 | "One way that the algorithm fails is that the first measured bit is incorrect. In this case, the phase correction applied before measuring the second bit is also incorrect, causing the rest of the bits to be likely incorrect as well. A simple way to mitigate this problem is to repeat the measurement of the first few bits several times and take a majority vote to increase the likelihood that we measure the bit correctly. Implementing this procedure within a single circuit requires performing arithmetic on the measured outcomes. Due to a temporary limitation in Qiskit, it is currently not possible to perform arithmetic on measured bits and condition future circuit operations on the results. So, here we will measure each bit using separate circuits.\n",
457 | "\n",
458 | "The following code cells construct and simulate an IPE circuit for measuring just the first bit of the phase."
459 | ]
460 | },
461 | {
462 | "cell_type": "code",
463 | "execution_count": null,
464 | "metadata": {},
465 | "outputs": [],
466 | "source": [
467 | "from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister\n",
468 | "import numpy as np\n",
469 | "\n",
470 | "\n",
471 | "def u_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
472 | " # qr is a quantum register with 2 qubits\n",
473 | " # cr is a classical register with 1 bits\n",
474 | "\n",
475 | " qc = QuantumCircuit(qr, cr)\n",
476 | "\n",
477 | " # Initialization\n",
478 | " q0, q1 = qr\n",
479 | " qc.h(q0)\n",
480 | " qc.x(q1)\n",
481 | "\n",
482 | " # Apply control-U operator as many times as needed to get the least significant phase bit\n",
483 | " u_angle = 2 * np.pi / 3\n",
484 | " k = 1\n",
485 | " cphase_angle = u_angle * 2**k\n",
486 | " qc.cp(cphase_angle, q0, q1)\n",
487 | "\n",
488 | " # Measure the auxiliary qubit in x-basis\n",
489 | " qc.h(q0)\n",
490 | " (c0,) = cr\n",
491 | " qc.measure(q0, c0)\n",
492 | "\n",
493 | " return qc\n",
494 | "\n",
495 | "\n",
496 | "qr = QuantumRegister(2, \"q\")\n",
497 | "cr = ClassicalRegister(1, \"c\")\n",
498 | "qc = QuantumCircuit(qr, cr)\n",
499 | "qc = u_circuit(qr, cr)\n",
500 | "qc.draw(\"mpl\")"
501 | ]
502 | },
503 | {
504 | "cell_type": "code",
505 | "execution_count": null,
506 | "metadata": {},
507 | "outputs": [],
508 | "source": [
509 | "job = sim.run(qc, shots=15)\n",
510 | "result = job.result()\n",
511 | "counts = result.get_counts()\n",
512 | "print(counts)"
513 | ]
514 | },
515 | {
516 | "attachments": {},
517 | "cell_type": "markdown",
518 | "metadata": {},
519 | "source": [
520 | "Hopefully, the correct bit was measured more often than not.\n",
521 | "\n",
522 | "### Exercise 4\n",
523 | "\n",
524 | "Examine the counts dictionary from the output of the last code cell. What is the correct value for the first bit? Was it measured more often than not? If not, rerun the last code cell until it is. Then, write some code in the code cell below that sets the variable `step1_bit` equal to the value of the bit that was measured the majority of the time."
525 | ]
526 | },
527 | {
528 | "cell_type": "code",
529 | "execution_count": null,
530 | "metadata": {},
531 | "outputs": [],
532 | "source": [
533 | "step1_bit: int\n",
534 | "\n",
535 | "####### your code goes here #######\n",
536 | "\n",
537 | "print(step1_bit)"
538 | ]
539 | },
540 | {
541 | "cell_type": "code",
542 | "execution_count": null,
543 | "metadata": {},
544 | "outputs": [],
545 | "source": [
546 | "# Submit your result\n",
547 | "\n",
548 | "from qc_grader.challenges.spring_2023 import grade_ex3d\n",
549 | "\n",
550 | "grade_ex3d(step1_bit)"
551 | ]
552 | },
553 | {
554 | "attachments": {},
555 | "cell_type": "markdown",
556 | "metadata": {},
557 | "source": [
558 | "### Exercise 5\n",
559 | "\n",
560 | "Now construct the circuit to measure the second bit of the phase. Replace the first stage of the circuit with one which simply sets the auxiliary bit to the value we measured above, so that we always measure the correct value for the first bit of the phase."
561 | ]
562 | },
563 | {
564 | "cell_type": "code",
565 | "execution_count": null,
566 | "metadata": {},
567 | "outputs": [],
568 | "source": [
569 | "from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister\n",
570 | "import numpy as np\n",
571 | "\n",
572 | "\n",
573 | "def u_circuit(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
574 | " # qr is a quantum register with 2 qubits\n",
575 | " # cr is a classical register with 2 bits\n",
576 | "\n",
577 | " qc = QuantumCircuit(qr, cr)\n",
578 | "\n",
579 | " ####### your code goes here #######\n",
580 | "\n",
581 | " return qc\n",
582 | "\n",
583 | "\n",
584 | "qr = QuantumRegister(2, \"q\")\n",
585 | "cr = ClassicalRegister(2, \"c\")\n",
586 | "qc = QuantumCircuit(qr, cr)\n",
587 | "qc = u_circuit(qr, cr)\n",
588 | "qc.draw(\"mpl\")"
589 | ]
590 | },
591 | {
592 | "cell_type": "code",
593 | "execution_count": null,
594 | "metadata": {},
595 | "outputs": [],
596 | "source": [
597 | "# Submit your result\n",
598 | "\n",
599 | "from qc_grader.challenges.spring_2023 import grade_ex3e\n",
600 | "\n",
601 | "grade_ex3e(qc)"
602 | ]
603 | },
604 | {
605 | "cell_type": "code",
606 | "execution_count": null,
607 | "metadata": {},
608 | "outputs": [],
609 | "source": [
610 | "from qiskit_aer import AerSimulator\n",
611 | "\n",
612 | "sim = AerSimulator()\n",
613 | "job = sim.run(qc, shots=1000)\n",
614 | "result = job.result()\n",
615 | "counts = result.get_counts()\n",
616 | "print(counts)\n",
617 | "success_probability = counts[\"01\"] / counts.shots()\n",
618 | "print(f\"Success probability: {success_probability}\")"
619 | ]
620 | },
621 | {
622 | "attachments": {},
623 | "cell_type": "markdown",
624 | "metadata": {},
625 | "source": [
626 | "Now, the success probability is much higher than before!"
627 | ]
628 | },
629 | {
630 | "attachments": {},
631 | "cell_type": "markdown",
632 | "metadata": {},
633 | "source": [
634 | "## Run on hardware\n",
635 | "\n",
636 | "In the final part of this lab, we will run some circuits on real hardware! The code cells below initialize and run the circuit you created in Exercise 2 to measure the phase of the $S$ gate. Because current quantum hardware suffers from noise, the results will not be as good as what you got on the simulator. Feel free to try running the other circuits you created in this lab, though be aware that larger circuits, like the one from Exercise 3 for measuring the phase of the $T$ gate, will suffer from even more noise."
637 | ]
638 | },
639 | {
640 | "cell_type": "code",
641 | "execution_count": null,
642 | "metadata": {},
643 | "outputs": [],
644 | "source": [
645 | "from qiskit_ibm_provider import IBMProvider\n",
646 | "\n",
647 | "provider = IBMProvider()"
648 | ]
649 | },
650 | {
651 | "cell_type": "code",
652 | "execution_count": null,
653 | "metadata": {},
654 | "outputs": [],
655 | "source": [
656 | "hub = \"YOUR_HUB\"\n",
657 | "group = \"YOUR_GROUP\"\n",
658 | "project = \"YOUR_PROJECT\"\n",
659 | "\n",
660 | "backend_name = \"ibm_peekskill\"\n",
661 | "backend = provider.get_backend(backend_name, instance=f\"{hub}/{group}/{project}\")"
662 | ]
663 | },
664 | {
665 | "cell_type": "code",
666 | "execution_count": null,
667 | "metadata": {},
668 | "outputs": [],
669 | "source": [
670 | "from qiskit import transpile\n",
671 | "\n",
672 | "qr = QuantumRegister(2, \"q\")\n",
673 | "cr = ClassicalRegister(2, \"c\")\n",
674 | "qc = QuantumCircuit(qr, cr)\n",
675 | "qc = step_2_circuit(qr, cr)\n",
676 | "qc_transpiled = transpile(qc, backend)"
677 | ]
678 | },
679 | {
680 | "cell_type": "code",
681 | "execution_count": null,
682 | "metadata": {},
683 | "outputs": [],
684 | "source": [
685 | "job = backend.run(qc_transpiled, shots=1000, dynamic=True)\n",
686 | "job_id = job.job_id()\n",
687 | "print(job_id)"
688 | ]
689 | },
690 | {
691 | "cell_type": "code",
692 | "execution_count": null,
693 | "metadata": {},
694 | "outputs": [],
695 | "source": [
696 | "retrieve_job = provider.retrieve_job(job_id)\n",
697 | "retrieve_job.status()"
698 | ]
699 | },
700 | {
701 | "cell_type": "code",
702 | "execution_count": null,
703 | "metadata": {},
704 | "outputs": [],
705 | "source": [
706 | "from qiskit.tools.visualization import plot_histogram\n",
707 | "\n",
708 | "counts = retrieve_job.result().get_counts()\n",
709 | "plot_histogram(counts)"
710 | ]
711 | },
712 | {
713 | "attachments": {},
714 | "cell_type": "markdown",
715 | "metadata": {},
716 | "source": [
717 | "This lab was adapted from the [Qiskit Textbook lab](https://learn.qiskit.org/course/ch-labs/lab-6-iterative-phase-estimation-algorithm) on iterative phase estimation as well as material from the [dynamic circuits documentation](https://quantum-computing.ibm.com/services/resources/docs/resources/manage/systems/dynamic-circuits/Getting-started-with-Dynamic-Circuits)."
718 | ]
719 | }
720 | ],
721 | "metadata": {
722 | "kernelspec": {
723 | "display_name": "Python 3 (ipykernel)",
724 | "language": "python",
725 | "name": "python3"
726 | },
727 | "language_info": {
728 | "codemirror_mode": {
729 | "name": "ipython",
730 | "version": 3
731 | },
732 | "file_extension": ".py",
733 | "mimetype": "text/x-python",
734 | "name": "python",
735 | "nbconvert_exporter": "python",
736 | "pygments_lexer": "ipython3",
737 | "version": "3.9.0"
738 | },
739 | "vscode": {
740 | "interpreter": {
741 | "hash": "c2040b9df22fb8e6f552d9b589c97ff536ffe03a0da1ea2949f78b5a0e303bb6"
742 | }
743 | },
744 | "widgets": {
745 | "application/vnd.jupyter.widget-state+json": {
746 | "state": {},
747 | "version_major": 2,
748 | "version_minor": 0
749 | }
750 | }
751 | },
752 | "nbformat": 4,
753 | "nbformat_minor": 4
754 | }
755 |
--------------------------------------------------------------------------------
/content/lab_3/resources/step1-circuit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qiskit-community/ibm-quantum-challenge-spring-2023/d9f62cab0e8f775b03a85e387b1ace2ef0124490/content/lab_3/resources/step1-circuit.png
--------------------------------------------------------------------------------
/content/lab_3/resources/step2-circuit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qiskit-community/ibm-quantum-challenge-spring-2023/d9f62cab0e8f775b03a85e387b1ace2ef0124490/content/lab_3/resources/step2-circuit.png
--------------------------------------------------------------------------------
/solutions/lab_1/resources/circuitRx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qiskit-community/ibm-quantum-challenge-spring-2023/d9f62cab0e8f775b03a85e387b1ace2ef0124490/solutions/lab_1/resources/circuitRx.png
--------------------------------------------------------------------------------
/solutions/lab_1/resources/sketch-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qiskit-community/ibm-quantum-challenge-spring-2023/d9f62cab0e8f775b03a85e387b1ace2ef0124490/solutions/lab_1/resources/sketch-1.png
--------------------------------------------------------------------------------
/solutions/lab_2/lab2_solution.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "0ac9dd0b-210c-470e-8313-5cf7f7c57b65",
6 | "metadata": {},
7 | "source": [
8 | "# Lab 2: Quantum teleportation\n",
9 | "\n",
10 | "Welcome to this lab on quantum teleportation in which you'll solve a problem that Alice and Bob have been having. Relax, it's not a relationship problem! Alice possesses a qubit in an unknown state $\\lvert \\psi \\rangle$ and she wishes to transfer this quantum state to Bob. However, they are very far apart and lack any means to transfer quantum information directly, only classical information. Is it possible to achieve their goal?\n",
11 | "\n",
12 | "It turns out that if Alice and Bob share an entangled qubit pair, she can transfer her qubit state to Bob by sending two bits of classical information. This process is known as teleportation because, at the end, Bob will possess |ψ⟩, and Alice will no longer have it."
13 | ]
14 | },
15 | {
16 | "cell_type": "markdown",
17 | "id": "11a966b2-a7c1-4584-87b2-1b8e4277f997",
18 | "metadata": {},
19 | "source": [
20 | "## Background\n",
21 | "\n",
22 | "Quantum teleportation is a protocol that allows the transfer of quantum information from one qubit to another using entanglement and classical communication. It was proposed by Charles Bennett, Gilles Brassard, Claude Crépeau, Richard Jozsa, Asher Peres, and William Wootters in 1993. The process does not transmit the qubit itself but rather transfers the quantum state from the source qubit to the target qubit.\n",
23 | "\n",
24 | "The protocol requires three qubits:\n",
25 | "\n",
26 | "1. The qubit to be teleported (Alice's qubit)\n",
27 | "2. One half of an entangled pair of qubits (Alice's second qubit)\n",
28 | "3. The other half of the entangled pair (Bob's qubit)\n",
29 | "\n",
30 | "The protocol can be summarized in the following steps:\n",
31 | "\n",
32 | "1. Create an entangled pair of qubits (Bell pair) shared between Alice and Bob.\n",
33 | "2. Alice performs a Bell basis measurement on her two qubits.\n",
34 | "3. Alice sends the classical results of her measurement to Bob.\n",
35 | "4. Bob applies appropriate quantum gates based on Alice's measurement results to obtain the teleported state."
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "id": "a26fb942-ca66-4bea-85f5-f8f13d013d5e",
41 | "metadata": {},
42 | "source": [
43 | "## Implementation\n",
44 | "\n",
45 | "In order to transfer a quantum bit, Alice and Bob require the help of a third party who provides them with a pair of entangled qubits. Next, Alice carries out certain operations on her qubit and shares the results with Bob through a classical communication channel. Finally, Bob performs a series of operations on his end to successfully obtain Alice's qubit. Now, let's delve deeper into each of these steps."
46 | ]
47 | },
48 | {
49 | "attachments": {},
50 | "cell_type": "markdown",
51 | "id": "71cdf58d-0d4d-43f0-b427-3a3ebca842f5",
52 | "metadata": {
53 | "tags": []
54 | },
55 | "source": [
56 | "Our quantum circuit will consist of 3 qubits and 3 classical bits. The qubits will be named as follows:\n",
57 | "- $s$: The \"source\" qubit containing the state $\\lvert \\psi \\rangle$ which Alice wishes to transmit to Bob.\n",
58 | "- $a$: The qubit which will initially store Alice's half of the entangled Bell pair.\n",
59 | "- $b$: The qubit which will initially store Bob's half of the entangled Bell pair.\n",
60 | "\n",
61 | "The teleportation protocol itself requires 2 classical bits, and we include a third one to use for measuring Bob's final state. The classical bits will be named as follows:\n",
62 | "- $c0$: The classical bit that Alice uses to measure $a$.\n",
63 | "- $c1$: The classical bit that Alice uses to measure $s$.\n",
64 | "- $c2$: The classical bit that Bob uses to measure $b$."
65 | ]
66 | },
67 | {
68 | "attachments": {},
69 | "cell_type": "markdown",
70 | "id": "bad695dc",
71 | "metadata": {},
72 | "source": [
73 | "### Exercise 1\n",
74 | "\n",
75 | "Utilize two qubits to generate an entangled Bell pair. Qubit 𝑎 is allocated to Alice, while qubit 𝑏 is designated for Bob."
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "execution_count": null,
81 | "id": "d9a9810a-8ec5-4e0e-823d-6865e810b34d",
82 | "metadata": {
83 | "tags": []
84 | },
85 | "outputs": [],
86 | "source": [
87 | "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
88 | "from qiskit.circuit import Qubit, Clbit\n",
89 | "\n",
90 | "\n",
91 | "def create_bell_pair(qr: QuantumRegister, cr: ClassicalRegister) -> QuantumCircuit:\n",
92 | " \"\"\"Creates a bell pair between qubits a and b.\"\"\"\n",
93 | " qc = QuantumCircuit(qr, cr)\n",
94 | " # unpack qubits\n",
95 | " # the first qubit is s but we won't be using it in this exercise\n",
96 | " s, a, b = qr\n",
97 | "\n",
98 | " # ENTER YOUR CODE BELOW EACH COMMENT\n",
99 | " # Put qubit a into state |+>\n",
100 | " qc.h(a)\n",
101 | " # CNOT with a as control and b as target\n",
102 | " qc.cx(a, b)\n",
103 | " # ENTER YOUR CODE ABOVE\n",
104 | "\n",
105 | " return qc # For the grader"
106 | ]
107 | },
108 | {
109 | "cell_type": "code",
110 | "execution_count": null,
111 | "id": "7897fcca-e31a-4b44-9e19-16fbeb85a20d",
112 | "metadata": {
113 | "tags": []
114 | },
115 | "outputs": [],
116 | "source": [
117 | "qr = QuantumRegister(3, name=\"q\")\n",
118 | "cr = ClassicalRegister(3, name=\"c\")\n",
119 | "qc = create_bell_pair(qr, cr)\n",
120 | "\n",
121 | "qc.draw(\"mpl\")"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "execution_count": null,
127 | "id": "d00f07df-5245-47c7-858b-3ae6cbafc475",
128 | "metadata": {
129 | "tags": []
130 | },
131 | "outputs": [],
132 | "source": [
133 | "# Submit your circuit\n",
134 | "\n",
135 | "from qc_grader.challenges.spring_2023 import grade_ex2a\n",
136 | "\n",
137 | "grade_ex2a(qc)"
138 | ]
139 | },
140 | {
141 | "attachments": {},
142 | "cell_type": "markdown",
143 | "id": "b6b5ec32-e8ae-4475-a0ea-5314acf49a4f",
144 | "metadata": {},
145 | "source": [
146 | "Let's assume Alice has qubit $a$ and Bob has qubit $b$ once they separate. Perhaps they really are having a relationship issue 😉."
147 | ]
148 | },
149 | {
150 | "attachments": {},
151 | "cell_type": "markdown",
152 | "id": "6ba11110",
153 | "metadata": {},
154 | "source": [
155 | "### Exercise 2\n",
156 | "\n",
157 | "In this step, Alice applies a CNOT gate to qubit $a$, with $s$ (the qubit containing $\\lvert \\psi \\rangle$, the state she intends to send to Bob) as the control. Following this, Alice applies a Hadamard gate to $s$."
158 | ]
159 | },
160 | {
161 | "cell_type": "code",
162 | "execution_count": null,
163 | "id": "34d7bcd6-166b-4745-8ede-f8aa1872d434",
164 | "metadata": {
165 | "tags": []
166 | },
167 | "outputs": [],
168 | "source": [
169 | "def alice_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
170 | " \"\"\"Creates Alices's gates\"\"\"\n",
171 | " qc = create_bell_pair(qr, cr)\n",
172 | " qc.barrier() # Use barrier to separate steps\n",
173 | " s, a, b = qr\n",
174 | "\n",
175 | " # ENTER YOUR CODE BELOW EACH COMMENT\n",
176 | " # CNOT with source as control and a as target\n",
177 | " qc.cx(s, a)\n",
178 | " # Apply Hadamard on qubit s\n",
179 | " qc.h(s)\n",
180 | " # ENTER YOUR CODE ABOVE\n",
181 | "\n",
182 | " return qc # For the grader"
183 | ]
184 | },
185 | {
186 | "cell_type": "code",
187 | "execution_count": null,
188 | "id": "3a5096db-1b92-45df-ac1b-52392356b543",
189 | "metadata": {
190 | "tags": []
191 | },
192 | "outputs": [],
193 | "source": [
194 | "qc = alice_gates(qr, cr)\n",
195 | "qc.draw(\"mpl\")"
196 | ]
197 | },
198 | {
199 | "cell_type": "code",
200 | "execution_count": null,
201 | "id": "66cead66-9c0e-4e7c-a196-efa456e6764b",
202 | "metadata": {
203 | "tags": []
204 | },
205 | "outputs": [],
206 | "source": [
207 | "# Submit your circuit\n",
208 | "\n",
209 | "from qc_grader.challenges.spring_2023 import grade_ex2b\n",
210 | "\n",
211 | "grade_ex2b(qc)"
212 | ]
213 | },
214 | {
215 | "attachments": {},
216 | "cell_type": "markdown",
217 | "id": "2d45bf84-f32b-4dd9-8e73-b8ec920e8b39",
218 | "metadata": {
219 | "tags": []
220 | },
221 | "source": [
222 | "### Exercise 3\n",
223 | "\n",
224 | "In this step, Alice performs a measurement on both qubits in her possession and saves the results in two classical bits. Afterward, she sends these two bits to Bob. She will measure qubit $a$ into classical bit $c0$ and qubit $s$ into classical bit $c1$."
225 | ]
226 | },
227 | {
228 | "cell_type": "code",
229 | "execution_count": null,
230 | "id": "345bc52c-7745-46a3-90e7-a0e6a03604d5",
231 | "metadata": {
232 | "tags": []
233 | },
234 | "outputs": [],
235 | "source": [
236 | "def measure_and_send(qr: QuantumRegister, cr: ClassicalRegister):\n",
237 | " \"\"\"Measures qubits a & b and 'sends' the results to Bob\"\"\"\n",
238 | " qc = alice_gates(qr, cr)\n",
239 | " qc.barrier() # Use barrier to separate steps\n",
240 | " s, a, b = qr\n",
241 | " c0, c1, c2 = cr\n",
242 | "\n",
243 | " # ENTER YOUR CODE BELOW EACH COMMENT\n",
244 | " # Measure qubit a into classical bit 0\n",
245 | " qc.measure(a, c0)\n",
246 | " # Measure qubit s into classical bit 1\n",
247 | " qc.measure(s, c1)\n",
248 | " # ENTER YOUR CODE ABOVE\n",
249 | "\n",
250 | " return qc # For the grader"
251 | ]
252 | },
253 | {
254 | "cell_type": "code",
255 | "execution_count": null,
256 | "id": "b1c3ec5d-ce66-455c-a2fe-6cca03dd87f4",
257 | "metadata": {
258 | "tags": []
259 | },
260 | "outputs": [],
261 | "source": [
262 | "qc = measure_and_send(qr, cr)\n",
263 | "qc.draw(\"mpl\", cregbundle=False)"
264 | ]
265 | },
266 | {
267 | "cell_type": "code",
268 | "execution_count": null,
269 | "id": "76b0c0b2-ed71-4eb7-b4d9-9b725a22fccb",
270 | "metadata": {
271 | "tags": []
272 | },
273 | "outputs": [],
274 | "source": [
275 | "# Submit your circuit\n",
276 | "\n",
277 | "from qc_grader.challenges.spring_2023 import grade_ex2c\n",
278 | "\n",
279 | "grade_ex2c(qc)"
280 | ]
281 | },
282 | {
283 | "attachments": {},
284 | "cell_type": "markdown",
285 | "id": "1fec0216-f312-430e-9940-0ab0ffd1beca",
286 | "metadata": {},
287 | "source": [
288 | "### Exercise 4\n",
289 | "\n",
290 | "In this step, Bob, who is already in possession of qubit $b$, dynamically adds specific gates to the circuit based on the state of the classical bits received from Alice:\n",
291 | "\n",
292 | "If the bits are `00`, no action is required. If they are `01`, an 𝑋 gate (also known as a Pauli-X or a bit-flip gate) should be applied. For bits `10`, a 𝑍 gate (also known as a Pauli-Z or a phase-flip gate) should be applied. Lastly, if the classical bits are `11`, a combined 𝑍𝑋 gate should be applied, which involves applying both the 𝑍 and 𝑋 gates in sequence. Please note that this information transfer occurs solely through classical means."
293 | ]
294 | },
295 | {
296 | "cell_type": "code",
297 | "execution_count": null,
298 | "id": "e61ddfa4-e536-46dd-b5a7-efe15f3ad617",
299 | "metadata": {
300 | "tags": []
301 | },
302 | "outputs": [],
303 | "source": [
304 | "# This function takes a QuantumCircuit (qc), integer (qubit)\n",
305 | "# and ClassicalRegisters (crz & crx) to decide which gates to apply\n",
306 | "def bob_gates(qr: QuantumRegister, cr: ClassicalRegister):\n",
307 | " \"\"\"Uses qc.if_test to control which gates are dynamically added\"\"\"\n",
308 | " qc = measure_and_send(qr, cr)\n",
309 | " qc.barrier() # Use barrier to separate steps\n",
310 | " s, a, b = qr\n",
311 | " c0, c1, c2 = cr\n",
312 | "\n",
313 | " # ENTER YOUR CODE BELOW EACH COMMENT\n",
314 | " # Add an X gate to the qubit wire if c0 measures 1\n",
315 | " with qc.if_test((c0, 1)):\n",
316 | " qc.x(b)\n",
317 | " # Add a Z gate to the qubit wire if c1 measures 1\n",
318 | " with qc.if_test((c1, 1)):\n",
319 | " qc.z(b)\n",
320 | " # ENTER YOUR CODE ABOVE\n",
321 | "\n",
322 | " return qc # For the grader"
323 | ]
324 | },
325 | {
326 | "cell_type": "code",
327 | "execution_count": null,
328 | "id": "ff619db6-282a-450e-9b7c-38b2838cfdeb",
329 | "metadata": {
330 | "tags": []
331 | },
332 | "outputs": [],
333 | "source": [
334 | "qc = bob_gates(qr, cr)\n",
335 | "qc.draw(\"mpl\", cregbundle=False)"
336 | ]
337 | },
338 | {
339 | "cell_type": "code",
340 | "execution_count": null,
341 | "id": "8ab0270f-f909-4239-bb52-e36410497c21",
342 | "metadata": {
343 | "tags": []
344 | },
345 | "outputs": [],
346 | "source": [
347 | "# Submit your circuit\n",
348 | "\n",
349 | "from qc_grader.challenges.spring_2023 import grade_ex2d\n",
350 | "\n",
351 | "grade_ex2d(qc)"
352 | ]
353 | },
354 | {
355 | "attachments": {},
356 | "cell_type": "markdown",
357 | "id": "74dc4ac1-d643-468e-a13c-509e2a12d77b",
358 | "metadata": {},
359 | "source": [
360 | "We will now have Bob measure his qubit into classical bit $c2$. After repeating the entire experiment multiple times, we can gather statistics on the measurement results to confirm that the teleportation worked correctly."
361 | ]
362 | },
363 | {
364 | "cell_type": "code",
365 | "execution_count": null,
366 | "id": "6223a197-48b8-4b7b-889c-4bf317793a27",
367 | "metadata": {
368 | "tags": []
369 | },
370 | "outputs": [],
371 | "source": [
372 | "teleportation_circuit = bob_gates(qr, cr)\n",
373 | "s, a, b = qr\n",
374 | "c0, c1, c2 = cr\n",
375 | "teleportation_circuit.measure(b, c2)\n",
376 | "teleportation_circuit.draw(\"mpl\")"
377 | ]
378 | },
379 | {
380 | "attachments": {},
381 | "cell_type": "markdown",
382 | "id": "3780a15e-4a86-4d5a-af4c-8662f4462fb9",
383 | "metadata": {},
384 | "source": [
385 | "Now that we have a teleportation circuit, let's ~~beam Captain Kirk to the surface of a strange planet~~ create and teleport a quantum state, and then run the circuit on a simulator."
386 | ]
387 | },
388 | {
389 | "attachments": {},
390 | "cell_type": "markdown",
391 | "id": "977a9fe6",
392 | "metadata": {},
393 | "source": [
394 | "### Exercise 5\n",
395 | "\n",
396 | "In the following code cell, construct a full quantum teleportation circuit into the `teleport_superposition_circuit` variable. Prepare the qubit $s$ by applying an $R_x$ rotation with angle $\\pi / 4$."
397 | ]
398 | },
399 | {
400 | "cell_type": "code",
401 | "execution_count": null,
402 | "id": "89fa5bdb-eb09-4fb8-9913-6fd6bb9f8ad2",
403 | "metadata": {
404 | "tags": []
405 | },
406 | "outputs": [],
407 | "source": [
408 | "import math\n",
409 | "\n",
410 | "teleport_superposition_circuit: QuantumCircuit\n",
411 | "\n",
412 | "########## your code goes here #######\n",
413 | "\n",
414 | "# Create a circuit that has the same structure as our teleportation circuit\n",
415 | "state_prep = QuantumCircuit(qr, cr)\n",
416 | "\n",
417 | "# Prepare the qubit\n",
418 | "state_prep.rx(math.pi / 4, s)\n",
419 | "\n",
420 | "# Put a barrier across all of the wires\n",
421 | "state_prep.barrier()\n",
422 | "# Add the teleportation circuit to the superposition circuit\n",
423 | "teleport_superposition_circuit = state_prep.compose(teleportation_circuit)\n",
424 | "\n",
425 | "teleport_superposition_circuit.draw(\"mpl\", cregbundle=False)"
426 | ]
427 | },
428 | {
429 | "cell_type": "code",
430 | "execution_count": null,
431 | "id": "1e0ef91c-964a-4fd6-ab52-36c859b69b13",
432 | "metadata": {
433 | "tags": []
434 | },
435 | "outputs": [],
436 | "source": [
437 | "from qiskit import transpile\n",
438 | "from qiskit_aer import AerSimulator\n",
439 | "from qiskit.visualization import plot_histogram\n",
440 | "\n",
441 | "sim = AerSimulator()\n",
442 | "transpiled_circuit = transpile(teleport_superposition_circuit, sim)\n",
443 | "\n",
444 | "# run job\n",
445 | "shots = 1000\n",
446 | "job = sim.run(transpiled_circuit, shots=shots, dynamic=True)\n",
447 | "\n",
448 | "# Get the results and display them\n",
449 | "exp_result = job.result()\n",
450 | "exp_counts = exp_result.get_counts()\n",
451 | "plot_histogram(exp_counts)"
452 | ]
453 | },
454 | {
455 | "attachments": {},
456 | "cell_type": "markdown",
457 | "id": "80e72c0a-8a4e-4d29-92a7-022d3882552a",
458 | "metadata": {},
459 | "source": [
460 | "Let's compute the distribution of just Bob's measurement by marginalizing over the other measured bits."
461 | ]
462 | },
463 | {
464 | "cell_type": "code",
465 | "execution_count": null,
466 | "id": "96a1fd3b-693b-4cd4-bb51-96f676dd1759",
467 | "metadata": {
468 | "tags": []
469 | },
470 | "outputs": [],
471 | "source": [
472 | "# trace out Bob's results on qubit 2\n",
473 | "from qiskit.result import marginal_counts\n",
474 | "\n",
475 | "bobs_counts = marginal_counts(exp_counts, [qr.index(b)])\n",
476 | "plot_histogram(bobs_counts)"
477 | ]
478 | },
479 | {
480 | "attachments": {},
481 | "cell_type": "markdown",
482 | "id": "6a33717b",
483 | "metadata": {},
484 | "source": [
485 | "The marginal distribution should be somewhat close to the ideal probabilities."
486 | ]
487 | },
488 | {
489 | "cell_type": "code",
490 | "execution_count": null,
491 | "id": "475e3774-da15-483b-9d2d-af54a8e0e568",
492 | "metadata": {
493 | "tags": []
494 | },
495 | "outputs": [],
496 | "source": [
497 | "from qc_grader.challenges.spring_2023 import grade_ex2e\n",
498 | "\n",
499 | "grade_ex2e(bobs_counts)"
500 | ]
501 | },
502 | {
503 | "attachments": {},
504 | "cell_type": "markdown",
505 | "id": "9baa3099-7577-4bf9-9d1f-e0c54dc384b8",
506 | "metadata": {},
507 | "source": [
508 | "Now that we're fairly certain that ~~Captain Kirk~~ Alice's qubit will teleport safely, let's execute the quantum teleportation circuit on real hardware."
509 | ]
510 | },
511 | {
512 | "cell_type": "code",
513 | "execution_count": null,
514 | "id": "ca2f737c-a21f-4727-b14d-0e7e315631ba",
515 | "metadata": {
516 | "tags": []
517 | },
518 | "outputs": [],
519 | "source": [
520 | "from qiskit_ibm_provider import IBMProvider\n",
521 | "\n",
522 | "provider = IBMProvider()"
523 | ]
524 | },
525 | {
526 | "cell_type": "code",
527 | "execution_count": null,
528 | "id": "da33a9fb-6b6c-48a4-a1b0-dfca70474e22",
529 | "metadata": {
530 | "tags": []
531 | },
532 | "outputs": [],
533 | "source": [
534 | "hub = \"ibm-q-internal\"\n",
535 | "group = \"deployed\"\n",
536 | "project = \"default\"\n",
537 | "\n",
538 | "backend_name = \"ibm_peekskill\"\n",
539 | "backend = provider.get_backend(backend_name, instance=f\"{hub}/{group}/{project}\")"
540 | ]
541 | },
542 | {
543 | "cell_type": "code",
544 | "execution_count": null,
545 | "id": "fe48f446-849f-46e9-b0a4-1dd5225db403",
546 | "metadata": {
547 | "tags": []
548 | },
549 | "outputs": [],
550 | "source": [
551 | "# backend.target.add_instruction(IfElseOp, name=\"if_else\") # Uncomment if necessary\n",
552 | "qc_transpiled = transpile(teleport_superposition_circuit, backend)"
553 | ]
554 | },
555 | {
556 | "cell_type": "code",
557 | "execution_count": null,
558 | "id": "cee84182-a90d-44b7-b44d-87309202cbc3",
559 | "metadata": {
560 | "tags": []
561 | },
562 | "outputs": [],
563 | "source": [
564 | "job = backend.run(qc_transpiled, shots=1000, dynamic=True)"
565 | ]
566 | },
567 | {
568 | "cell_type": "code",
569 | "execution_count": null,
570 | "id": "fc8458f1-43fd-48b2-a50c-65771262cbf1",
571 | "metadata": {
572 | "tags": []
573 | },
574 | "outputs": [],
575 | "source": [
576 | "# Get the results and display them\n",
577 | "exp_result = job.result()\n",
578 | "exp_counts = exp_result.get_counts()\n",
579 | "plot_histogram(exp_counts)"
580 | ]
581 | },
582 | {
583 | "cell_type": "code",
584 | "execution_count": null,
585 | "id": "88ddf3c8-732f-4825-a1b1-376bce0ab614",
586 | "metadata": {},
587 | "outputs": [],
588 | "source": [
589 | "# trace out Bob's results on qubit 2\n",
590 | "from qiskit.result import marginal_counts\n",
591 | "\n",
592 | "bobs_qubit = 2\n",
593 | "bobs_counts = marginal_counts(exp_counts, [bobs_qubit])\n",
594 | "plot_histogram(bobs_counts)"
595 | ]
596 | }
597 | ],
598 | "metadata": {
599 | "kernelspec": {
600 | "display_name": "spring-challenge-2023",
601 | "language": "python",
602 | "name": "spring-challenge-2023"
603 | },
604 | "language_info": {
605 | "codemirror_mode": {
606 | "name": "ipython",
607 | "version": 3
608 | },
609 | "file_extension": ".py",
610 | "mimetype": "text/x-python",
611 | "name": "python",
612 | "nbconvert_exporter": "python",
613 | "pygments_lexer": "ipython3",
614 | "version": "3.9.15"
615 | },
616 | "widgets": {
617 | "application/vnd.jupyter.widget-state+json": {
618 | "state": {},
619 | "version_major": 2,
620 | "version_minor": 0
621 | }
622 | }
623 | },
624 | "nbformat": 4,
625 | "nbformat_minor": 5
626 | }
627 |
--------------------------------------------------------------------------------
/solutions/lab_3/resources/step1-circuit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qiskit-community/ibm-quantum-challenge-spring-2023/d9f62cab0e8f775b03a85e387b1ace2ef0124490/solutions/lab_3/resources/step1-circuit.png
--------------------------------------------------------------------------------
/solutions/lab_3/resources/step2-circuit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qiskit-community/ibm-quantum-challenge-spring-2023/d9f62cab0e8f775b03a85e387b1ace2ef0124490/solutions/lab_3/resources/step2-circuit.png
--------------------------------------------------------------------------------