├── algorithms ├── config_ex.py ├── media │ └── swap_hardware.png ├── README.md ├── Bell States.ipynb ├── Hamiltonian Simulation.ipynb └── Teleportation.ipynb ├── challenges └── IBM 2021 │ ├── ex5 │ ├── resources │ │ ├── ansatz.png │ │ ├── mapping.png │ │ └── workflow.png │ └── solution.ipynb │ ├── ex4 │ └── resources │ │ ├── pulse-instr.png │ │ ├── pulse-user-device-layers.png │ │ ├── transmon-energy-levels.png │ │ ├── transmon-charge-dispersion.png │ │ └── helper.py │ ├── ex1 │ └── resources │ │ └── conference-photo.jpeg │ ├── README.md │ └── ex2 │ └── solution.ipynb ├── .gitignore ├── LICENSE ├── Resources.ipynb ├── README.md └── papers └── Quantum State Preparation with Universal Gate Decompositions.ipynb /algorithms/config_ex.py: -------------------------------------------------------------------------------- 1 | IBM_KEY = "YOUR_KEY" -------------------------------------------------------------------------------- /algorithms/media/swap_hardware.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/algorithms/media/swap_hardware.png -------------------------------------------------------------------------------- /challenges/IBM 2021/ex5/resources/ansatz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/challenges/IBM 2021/ex5/resources/ansatz.png -------------------------------------------------------------------------------- /challenges/IBM 2021/ex5/resources/mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/challenges/IBM 2021/ex5/resources/mapping.png -------------------------------------------------------------------------------- /challenges/IBM 2021/ex5/resources/workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/challenges/IBM 2021/ex5/resources/workflow.png -------------------------------------------------------------------------------- /challenges/IBM 2021/ex4/resources/pulse-instr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/challenges/IBM 2021/ex4/resources/pulse-instr.png -------------------------------------------------------------------------------- /challenges/IBM 2021/ex1/resources/conference-photo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/challenges/IBM 2021/ex1/resources/conference-photo.jpeg -------------------------------------------------------------------------------- /challenges/IBM 2021/ex4/resources/pulse-user-device-layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/challenges/IBM 2021/ex4/resources/pulse-user-device-layers.png -------------------------------------------------------------------------------- /challenges/IBM 2021/ex4/resources/transmon-energy-levels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/challenges/IBM 2021/ex4/resources/transmon-energy-levels.png -------------------------------------------------------------------------------- /challenges/IBM 2021/ex4/resources/transmon-charge-dispersion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epelaaez/QuantumLibrary/HEAD/challenges/IBM 2021/ex4/resources/transmon-charge-dispersion.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore file with sensitive data 2 | config.py 3 | 4 | # Ignore folders 5 | __pycache__/ 6 | .vscode/ 7 | 8 | # Ignore generated images 9 | output_images/ 10 | 11 | # Ignore notebook checkpoints 12 | .ipynb_checkpoints/ -------------------------------------------------------------------------------- /challenges/IBM 2021/README.md: -------------------------------------------------------------------------------- 1 | # IBM Quantum Challenge 2021 2 | This folder contains the solved notebooks for all 5 exercises of the IBM Quantum Challenge 2021. Additionaly, inside each folder you can find a `solution.ipynb` file which contains **only** the solution, with the steps that I took to arrive to it. I decided to make this separate files for the solutions since the tutorial part of each notebook took a big part of them. Therefore, having the solutions by themselves makes them easier to follow. I also ensured that each `solution.ipynb` file contains everything needed to run (e.g., imports and helper functions) and understand my code; however, some prerequisites may be included in the problem notebook — I've tried to point out when this happens. 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Emilio Peláez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Algorithms 2 | 3 | In this directory you can find implementations and explanations of various quantum algorithms and protocols. These are presented both with Qiskit code and written text that go over the mathematics and intuition of what is being done. Right now, the algorithms available are: 4 | 5 | - [Bell state](https://github.com/epelaaez/QuantumLibrary/blob/master/algorithms/Bell%20States.ipynb): the most common bell state (|00⟩+|11⟩, normalized) is prepared. 6 | - [Deutsch-Jozsa](https://github.com/epelaaez/QuantumLibrary/blob/master/algorithms/Deutsch–Jozsa.ipynb): the Deutsch-Jozsa algorithm is implemented, first with 2 qubits and then generalized to *n* qubits. 7 | - [Hamiltonian simulation](https://github.com/epelaaez/QuantumLibrary/blob/master/algorithms/Hamiltonian%20Simulation.ipynb): this technique can be used to simulate physical process defined by a Hamiltonian operator. 8 | - [Phase kickback](https://github.com/epelaaez/QuantumLibrary/blob/master/algorithms/Phase%20Kickback.ipynb): the phase kickback "trick" is implemented and a small example with 2 qubits is given. 9 | - [Prime factorization](https://github.com/epelaaez/QuantumLibrary/blob/master/algorithms/Prime%20Factorization.ipynb): Shor's algorithm is used to get the prime factorization of a number; some familiarity with quantum phase estimation is assumed. 10 | - [Swap test](https://github.com/epelaaez/QuantumLibrary/blob/master/algorithms/Swap%20Test.ipynb): the swap test is implemented for 2 qubit registers and the transpiled circuit is shown to state how expensive it is to run on hardware. 11 | - [Teleportation](https://github.com/epelaaez/QuantumLibrary/blob/master/algorithms/Teleportation.ipynb): the quantum teleportation protocol is motivated briefly and then implemented on simulator and hardware. 12 | - [VQE](https://github.com/epelaaez/QuantumLibrary/blob/master/algorithms/VQE.ipynb): the mathematical background for the simulation and optimization tasks are introduced, then VQE is implemented using Qiskit's built in functions. 13 | -------------------------------------------------------------------------------- /Resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "hidden-consistency", 6 | "metadata": {}, 7 | "source": [ 8 | "# Learning Resources" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "altered-curtis", 14 | "metadata": {}, 15 | "source": [ 16 | "The following notebook contains a collection of resources of different types useful for learning quantum computing, from the very basics to more advanced topics." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "authorized-hayes", 22 | "metadata": {}, 23 | "source": [ 24 | "Books:\n", 25 | "- [Qiskit textbook](https://qiskit.org/textbook/ch-states/introduction.html)\n", 26 | "- [Quantum Computing for Everyone](https://direct.mit.edu/books/book/4186/Quantum-Computing-for-Everyone)\n", 27 | "- Quantum Computing Since Democritus\n", 28 | "- Quantum Computation and Quantum Information" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "id": "overall-armstrong", 34 | "metadata": {}, 35 | "source": [ 36 | "Research papers:\n", 37 | "- [Elementary gates for quantum computation](https://arxiv.org/abs/quant-ph/9503016)\n", 38 | "- [Gates, States, and Circuits](https://threeplusone.com/pubs/on_gates.pdf)\n", 39 | "- [On the advantages of using relative phase Toffolis with an application to multiple\n", 40 | "control Toffoli optimization](https://arxiv.org/abs/1508.03273)\n", 41 | "- [Circuit for Shor’s algorithm using 2n+3 qubits](https://arxiv.org/abs/quant-ph/0205095)\n", 42 | "- [The block-ZXZ synthesis of an arbitrary quantum circuit](https://arxiv.org/abs/1512.07240)\n", 43 | "- [Gate fidelity fluctuations and quantum process invariants](https://arxiv.org/abs/0910.1315)" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "id": "advisory-transcript", 49 | "metadata": {}, 50 | "source": [ 51 | "Conferences and events:\n", 52 | "- [Quantum Computing Education - Workforce Development](https://quantum.ieee.org/education/workforce-development)" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "id": "incorrect-calibration", 58 | "metadata": {}, 59 | "source": [ 60 | "Blogs and publications:\n", 61 | "- [Quantum Untangled](https://medium.com/quantum-untangled)" 62 | ] 63 | } 64 | ], 65 | "metadata": { 66 | "kernelspec": { 67 | "display_name": "Python 3", 68 | "language": "python", 69 | "name": "python3" 70 | }, 71 | "language_info": { 72 | "codemirror_mode": { 73 | "name": "ipython", 74 | "version": 3 75 | }, 76 | "file_extension": ".py", 77 | "mimetype": "text/x-python", 78 | "name": "python", 79 | "nbconvert_exporter": "python", 80 | "pygments_lexer": "ipython3", 81 | "version": "3.8.8" 82 | } 83 | }, 84 | "nbformat": 4, 85 | "nbformat_minor": 5 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Quantum Library 2 | 3 | By Emilio Peláez 4 | 5 | This repository contains work I have done in quantum computing using the Qiskit library in Python. Most of it consists of notebooks going through an specific algorithm or protocol in quantum computation while trying to give the best description possible and linking to useful resources to get a more in-depth view of the topic discussed. I am relatively new to the field of quantum information and quantum computation (I started in summer of 2020), so the topics covered in this repo may not be very advanced as they mostly reflect my learning process and progress. 6 | 7 | The main goal of this repo is to have a reliable library which I or anyone can access to learn or verify something about the topics covered. Therefore, anyone is welcomed to contribute to the project if they find a mistake, would like to add to an explanation, or simply thinks that something should be different. 8 | 9 | Some instructions to run this project locally and collaborate to it are included in the rest of this document in case someone wants to do so. 10 | 11 | ## Set up 12 | Once you clone the repository, you will need to create a new file called `config.py` (or change the name of the provided [`config_ex.py`](/config_ex.py) file) inside the `algorithms` folder, this is where you will store your IBM Quantum Experience API token. If you don't have an account yet, go to [IBM Quantum Experience](https://quantum-computing.ibm.com) to create one. Inside this file, just replace the following code `YOUR_KEY` with your actual key. 13 | ```python 14 | IBM_KEY = "YOUR_KEY" 15 | ``` 16 | 17 | ## Run on hardware 18 | To run the circuits on real hardware, you will need to set up your IBM account as specified above. To run the circuit you desire in a real quantum computer, just uncomment the few lines of code that are above the code that runs the simulator. You will also need to load your IBM account, which relies on your `config.py` file being correctly written, to gain access to the hardware. 19 | 20 | Note that not all circuits may be run in real hardware and some require modifications to run correctly. Those that require modifications to run correctly will make the necessary modifications when the function that builds the circuit gets the argument `hardware=True`, so you don't have to worry about modifying anything. However, I encourage you to check the code and the description of the circuit to understand the modifications made, why they are needed and how they work. The circuits that can't run in real hardware or don't need any changes won't accept the optional argument `hardware`. 21 | 22 | **Note**: running a circuit on hardware can take time depending on the computers available and their queue. The `least_busy()` function is used to choose the least busy machine, but this doesn't guarantee that it will run immediately. 23 | 24 | ## Contributing 25 | Anyone is welcome and encouraged to contribute to this project, whether you are an expert in the field or just getting started on it. To contribute, you can clone the repository in your local machine, make the changes you want to contribute in a separate branch, and then open a pull request describing the changes you made. The pull request will then be reviewed and discussed prior to merging. 26 | -------------------------------------------------------------------------------- /challenges/IBM 2021/ex4/resources/helper.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from qiskit.pulse import AcquireChannel 4 | #from qiskit.visualization import SchedStyle 5 | from qiskit.ignis.characterization.fitters import IQFitter 6 | 7 | # backend/job-specific constants 8 | scale_factor = 1e-7 9 | num_shots = 512 10 | num_spec01_freqs = 71 11 | num_rabi_amps = 71 12 | num_spec12_freqs = 71 13 | 14 | spec_range = 0.300 # GHz 15 | 16 | # SI unit conversion factors 17 | GHz = 1.0e9 # Gigahertz 18 | MHz = 1.0e6 # Megahertz 19 | kHz = 1.0e3 # kilohertz 20 | us = 1.0e-6 # microseconds 21 | ns = 1.0e-9 # nanoseconds 22 | 23 | job_params = { 24 | 'meas_level': 1, 25 | 'meas_return': 'avg', 26 | 'shots': num_shots 27 | } 28 | 29 | 30 | # Pulse visualization style 31 | #style = SchedStyle(figsize=(4, 4), 32 | # axis_font_size=8, 33 | # label_font_size=10, 34 | # title_font_size=12, 35 | # icon_font_size=8) 36 | 37 | def get_exc_chans(gv): 38 | return [AcquireChannel(i) for i in range(gv['backend_config'].n_qubits)] 39 | 40 | def get_spec01_freqs(center_freqs, qubit): 41 | center_freq = round(center_freqs[qubit], -8) # 2 significant digits 42 | return np.linspace(center_freq/GHz - spec_range/2, 43 | center_freq/GHz + spec_range/2, num_spec01_freqs) 44 | 45 | def get_rabi_amps(max_rabi_amp): 46 | return np.linspace(0, max_rabi_amp, num_rabi_amps) 47 | 48 | def get_spec12_freqs(f01, qubit): 49 | return np.linspace(f01 - spec_range/2, f01 + spec_range/2, num_spec12_freqs) 50 | 51 | # center data around 0 52 | #def center_data(values): 53 | # return np.array(values) - np.mean(values) 54 | 55 | def get_params(exp_type, gv): 56 | 57 | exp_dict = {} 58 | 59 | if exp_type == 'spec01': 60 | exp_dict = { 61 | 'experiments': gv['spec_schedules'], 62 | 'backend': gv['backend'], 63 | 'qubit_lo_freq': gv['center_frequency'], 64 | 'meas_level': 1, 65 | 'meas_return': 'avg', 66 | 'shots': num_shots 67 | } 68 | 69 | if exp_type == 'rabi': 70 | exp_dict = { 71 | 'experiments': gv['rabi_scheds'], 72 | 'backend': gv['backend'], 73 | 'qubit_lo_freq': gv['center_frequency'], 74 | 'meas_level': 1, 75 | 'meas_return': 'avg', 76 | 'shots': num_shots 77 | } 78 | 79 | if exp_type == 'spec12': 80 | exp_dict = { 81 | 'experiments': gv['spec_schedules'], 82 | 'backend': gv['backend'], 83 | 'qubit_lo_freq': gv['center_frequency'], 84 | 'meas_level': 1, 85 | 'meas_return': 'avg', 86 | 'shots': 2048 87 | } 88 | 89 | return exp_dict 90 | 91 | def sinusoid(x, A, B, drive_period, phi): 92 | return A*np.cos(2*np.pi*x/drive_period - phi) + B 93 | 94 | def fit_sinusoid(x_vals, y_vals, init_params): 95 | from scipy.optimize import curve_fit 96 | 97 | fit_params, conv = curve_fit(sinusoid, x_vals, y_vals, init_params) 98 | y_fit = sinusoid(x_vals, *fit_params) 99 | 100 | return fit_params, y_fit 101 | 102 | def lorentzian(x, A, q_freq, B, C): 103 | return (A/np.pi)*(B/((x-q_freq)**2 + B**2)) + C 104 | 105 | def fit_lorentzian(x_vals, y_vals, init_params): 106 | from scipy.optimize import curve_fit 107 | 108 | fit_params, conv = curve_fit(lorentzian, x_vals, y_vals, init_params) 109 | y_fit = lorentzian(x_vals, *fit_params) 110 | 111 | return fit_params, y_fit 112 | 113 | def get_values_from_result(exp_result, qubit): 114 | 115 | exp_values = [] 116 | for ii in range(len(exp_result.results)): 117 | exp_values.append(exp_result.results[ii].data.memory[qubit][0]) 118 | 119 | return exp_values 120 | 121 | 122 | class SpecFitter(IQFitter): 123 | """ Spectroscopy Experiment fitter""" 124 | 125 | def __init__(self, backend_result, xdata, qubits, fit_p0, fit_bounds=None): 126 | """ 127 | See BaseCalibrationFitter __init__ 128 | fit_p0 is [amp, freq, scale, offset] 129 | """ 130 | 131 | schedule_names = [] 132 | for _, xval in enumerate(xdata): 133 | schedule_names.append("Spec Pulse at %.3f GH" % xval) 134 | 135 | IQFitter.__init__(self, 'Spec', 136 | backend_result, xdata, 137 | qubits, 138 | lorentzian, 139 | fit_p0, fit_bounds, 140 | circuit_names=schedule_names, 141 | series=['z']) 142 | 143 | def spec_freq(self, qind, series='z'): 144 | return self._params[series][qind][1] 145 | 146 | def plot(self, qind, series='z', ax=None, show_plot=False): 147 | """ 148 | Plot the data and fit 149 | 150 | Args: 151 | qind (int): qubit index 152 | series (str): data series to plot (for rabi data always '0') 153 | ax (Axes): matploblib axes (if none created) 154 | show_plot (bool): do plot.show 155 | 156 | Returns: 157 | Axes: Plot axes 158 | """ 159 | 160 | fig, ax = plt.subplots(1, 1, figsize=(8,5)) 161 | 162 | ax = IQFitter.plot(self, qind, series, ax, 163 | show_plot) 164 | 165 | ax.set_ylabel("IQ Signal (au)") 166 | ax.set_xlabel("Drive Frequency") 167 | 168 | return ax 169 | -------------------------------------------------------------------------------- /algorithms/Bell States.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "mighty-engagement", 6 | "metadata": {}, 7 | "source": [ 8 | "## Imports" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 8, 14 | "id": "96a30e59-ee45-46e7-8004-389ad7b50e22", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import config\n", 19 | "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, IBMQ, Aer, execute\n", 20 | "from qiskit.visualization import plot_histogram\n", 21 | "from qiskit.providers.ibmq import least_busy" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "id": "diverse-eight", 27 | "metadata": {}, 28 | "source": [ 29 | "# Bell States" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "id": "usual-rates", 35 | "metadata": {}, 36 | "source": [ 37 | "Bell states are quantum states of two qubits that represent the maximally entangled states possible. The four Bell states form what is called the [Bell basis](https://en.wikipedia.org/wiki/Bell_state#Bell_basis), which form the maximally entangled basis for two qubits. In this circuit, the first Bell state is prepare. This state is entangled, meaning that measuring one qubit will immediately tell you the state of the other one. In this case, the states of both qubits will match 100% percent of the time. Thus, if you measure one qubit to be in the state $|0\\rangle$, you will know that the other one is in the state $|0\\rangle$ too; and the same way for $|1\\rangle$. \n", 38 | "\n", 39 | "The code used to generate this circuit is the following:" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 2, 45 | "id": "chubby-advertiser", 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "def bell_state():\n", 50 | " qreg = QuantumRegister(2, 'q')\n", 51 | " creg = ClassicalRegister(2, 'c')\n", 52 | " qc = QuantumCircuit(qreg, creg)\n", 53 | "\n", 54 | " # Create bell state itself by putting first qubit into superposition and then applying a CNOT gate between the two qubits\n", 55 | " qc.h(qreg[0])\n", 56 | " qc.cx(qreg[0], qreg[1])\n", 57 | "\n", 58 | " # Measure both qubits\n", 59 | " qc.measure(qreg[0], creg[0])\n", 60 | " qc.measure(qreg[1], creg[1])\n", 61 | "\n", 62 | " # Return circuit\n", 63 | " return qc" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 3, 69 | "id": "powerful-darkness", 70 | "metadata": {}, 71 | "outputs": [ 72 | { 73 | "data": { 74 | "text/html": [ 75 | "
┌───┐ ┌─┐ \n", 76 | "q_0: ┤ H ├──■──┤M├───\n", 77 | " └───┘┌─┴─┐└╥┘┌─┐\n", 78 | "q_1: ─────┤ X ├─╫─┤M├\n", 79 | " └───┘ ║ └╥┘\n", 80 | "c: 2/═══════════╩══╩═\n", 81 | " 0 1" 82 | ], 83 | "text/plain": [ 84 | " ┌───┐ ┌─┐ \n", 85 | "q_0: ┤ H ├──■──┤M├───\n", 86 | " └───┘┌─┴─┐└╥┘┌─┐\n", 87 | "q_1: ─────┤ X ├─╫─┤M├\n", 88 | " └───┘ ║ └╥┘\n", 89 | "c: 2/═══════════╩══╩═\n", 90 | " 0 1 " 91 | ] 92 | }, 93 | "execution_count": 3, 94 | "metadata": {}, 95 | "output_type": "execute_result" 96 | } 97 | ], 98 | "source": [ 99 | "circ = bell_state()\n", 100 | "circ.draw()" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "id": "individual-present", 106 | "metadata": {}, 107 | "source": [ 108 | "The Hadamard gate puts the first qubit into an equal superposition of states $|0\\rangle$ and $|1\\rangle$. The second gate is a CNOT, which is a controlled-not gate, meaning that it will flip the target qubit (the second one in this case) only if the control qubit (the first one) is in state $|1\\rangle$. Since our control qubit is in a superposition of $|0\\rangle$ and $|1\\rangle$, the target qubit will be flipped with the same equal probability. This also means that measuring a $|0\\rangle$ in the top qubit means that the second qubit was **not** flipped and therefore stayed in the $|0\\rangle$ state, but if we measure the first qubit to be in the $|1\\rangle$ state, we know that the second qubit was flipped and therefore is in the $|1\\rangle$ state. " 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "id": "preliminary-capture", 114 | "metadata": {}, 115 | "source": [ 116 | "And here is an histogram obtained from measuring the two qubits into classical bits. We can see that there was a 50-50 chance of getting either $|00\\rangle$ or $|11\\rangle$ (without considering noise from the quantum computer)." 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 4, 122 | "id": "laughing-comparison", 123 | "metadata": {}, 124 | "outputs": [ 125 | { 126 | "data": { 127 | "text/plain": [ 128 | "
┌─────────────┐\n", 118 | "q_0: ┤ RY(0.16854) ├\n", 119 | " └─────────────┘\n", 120 | "q_1: ───────────────\n", 121 | "" 122 | ], 123 | "text/plain": [ 124 | " ┌─────────────┐\n", 125 | "q_0: ┤ RY(0.16854) ├\n", 126 | " └─────────────┘\n", 127 | "q_1: ───────────────\n", 128 | " " 129 | ] 130 | }, 131 | "execution_count": 5, 132 | "metadata": {}, 133 | "output_type": "execute_result" 134 | } 135 | ], 136 | "source": [ 137 | "qc = QuantumCircuit(n)\n", 138 | "qc.ry(2 * np.arccos(s[0]), 0)\n", 139 | "qc.draw()" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 6, 145 | "id": "ff5b00db", 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "data": { 150 | "text/latex": [ 151 | "$\\displaystyle \\left[\\begin{matrix}0.99645\\\\0.08417\\\\0\\\\0\\end{matrix}\\right]$" 152 | ], 153 | "text/plain": [ 154 | "Matrix([\n", 155 | "[0.99645],\n", 156 | "[0.08417],\n", 157 | "[ 0],\n", 158 | "[ 0]])" 159 | ] 160 | }, 161 | "execution_count": 6, 162 | "metadata": {}, 163 | "output_type": "execute_result" 164 | } 165 | ], 166 | "source": [ 167 | "Matrix(np.round(Statevector(qc), 5))" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "id": "0d7ad276", 173 | "metadata": {}, 174 | "source": [ 175 | "Then, we apply a $\\rm CNOT$ gate to get the state $ \\sum_{i=1}^{2^k}\\alpha_i|i\\rangle |i\\rangle$." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 7, 181 | "id": "f3cdb9ff", 182 | "metadata": {}, 183 | "outputs": [ 184 | { 185 | "data": { 186 | "text/html": [ 187 | "
┌─────────────┐ \n", 188 | "q_0: ┤ RY(0.16854) ├──■──\n", 189 | " └─────────────┘┌─┴─┐\n", 190 | "q_1: ───────────────┤ X ├\n", 191 | " └───┘" 192 | ], 193 | "text/plain": [ 194 | " ┌─────────────┐ \n", 195 | "q_0: ┤ RY(0.16854) ├──■──\n", 196 | " └─────────────┘┌─┴─┐\n", 197 | "q_1: ───────────────┤ X ├\n", 198 | " └───┘" 199 | ] 200 | }, 201 | "execution_count": 7, 202 | "metadata": {}, 203 | "output_type": "execute_result" 204 | } 205 | ], 206 | "source": [ 207 | "qc.cx(0, 1)\n", 208 | "qc.draw()" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 8, 214 | "id": "13277e32", 215 | "metadata": {}, 216 | "outputs": [ 217 | { 218 | "data": { 219 | "text/latex": [ 220 | "$\\displaystyle \\left[\\begin{matrix}0.99645\\\\0\\\\0\\\\0.08417\\end{matrix}\\right]$" 221 | ], 222 | "text/plain": [ 223 | "Matrix([\n", 224 | "[0.99645],\n", 225 | "[ 0],\n", 226 | "[ 0],\n", 227 | "[0.08417]])" 228 | ] 229 | }, 230 | "execution_count": 8, 231 | "metadata": {}, 232 | "output_type": "execute_result" 233 | } 234 | ], 235 | "source": [ 236 | "Matrix(np.round(Statevector(qc), 5))" 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "id": "9d261afd", 242 | "metadata": {}, 243 | "source": [ 244 | "Now, we apply a transformation such that our state is $\\sum_{i=1}^{2^k}\\alpha_i|\\psi_i\\rangle |i\\rangle$." 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": 9, 250 | "id": "ad44bb4b", 251 | "metadata": {}, 252 | "outputs": [], 253 | "source": [ 254 | "theta = 2 * np.arccos(a[0][0][0])\n", 255 | "phi = np.real(np.log(a[0][1][0] / np.sin(np.arccos(a[0][0][0])), dtype='complex') / 1j)\n", 256 | "lamb = np.real(np.log(-a[1][0][0] / np.sin(np.arccos(a[0][0][0])), dtype='complex') / 1j)" 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": 10, 262 | "id": "0f88fda7", 263 | "metadata": {}, 264 | "outputs": [ 265 | { 266 | "data": { 267 | "text/html": [ 268 | "
┌─────────────┐ ┌───────────────┐\n", 269 | "q_0: ┤ RY(0.16854) ├──■──┤ U(4.4543,π,0) ├\n", 270 | " └─────────────┘┌─┴─┐└───────────────┘\n", 271 | "q_1: ───────────────┤ X ├─────────────────\n", 272 | " └───┘" 273 | ], 274 | "text/plain": [ 275 | " ┌─────────────┐ ┌───────────────┐\n", 276 | "q_0: ┤ RY(0.16854) ├──■──┤ U(4.4543,π,0) ├\n", 277 | " └─────────────┘┌─┴─┐└───────────────┘\n", 278 | "q_1: ───────────────┤ X ├─────────────────\n", 279 | " └───┘ " 280 | ] 281 | }, 282 | "execution_count": 10, 283 | "metadata": {}, 284 | "output_type": "execute_result" 285 | } 286 | ], 287 | "source": [ 288 | "qc.u(theta, phi, lamb, 0)\n", 289 | "qc.draw()" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": 11, 295 | "id": "fe1f5e5e", 296 | "metadata": {}, 297 | "outputs": [ 298 | { 299 | "data": { 300 | "text/latex": [ 301 | "$\\displaystyle \\left[\\begin{matrix}-0.60807\\\\-0.78941\\\\-0.06668\\\\0.05136\\end{matrix}\\right]$" 302 | ], 303 | "text/plain": [ 304 | "Matrix([\n", 305 | "[-0.60807],\n", 306 | "[-0.78941],\n", 307 | "[-0.06668],\n", 308 | "[ 0.05136]])" 309 | ] 310 | }, 311 | "execution_count": 11, 312 | "metadata": {}, 313 | "output_type": "execute_result" 314 | } 315 | ], 316 | "source": [ 317 | "Matrix(np.round(Statevector(qc), 5))" 318 | ] 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "id": "0f285a8a", 323 | "metadata": {}, 324 | "source": [ 325 | "And we do the same for the second qubit so we end up with $\\sum_{i=1}^{2^k}\\alpha_i|\\psi_i\\rangle |\\phi_i\\rangle$." 326 | ] 327 | }, 328 | { 329 | "cell_type": "code", 330 | "execution_count": 12, 331 | "id": "1c1fd981", 332 | "metadata": {}, 333 | "outputs": [], 334 | "source": [ 335 | "theta = 2 * np.arccos(b[0][0][0])\n", 336 | "phi = np.real(np.log(b[0][1][0] / np.sin(np.arccos(b[0][0][0])), dtype='complex') / 1j)\n", 337 | "lamb = np.real(np.log(-b[1][0][0] / np.sin(np.arccos(b[0][0][0])), dtype='complex') / 1j)" 338 | ] 339 | }, 340 | { 341 | "cell_type": "code", 342 | "execution_count": 13, 343 | "id": "4f2ea009", 344 | "metadata": {}, 345 | "outputs": [ 346 | { 347 | "data": { 348 | "text/html": [ 349 | "
┌─────────────┐ ┌───────────────┐\n", 350 | "q_0: ┤ RY(0.16854) ├──■──┤ U(4.4543,π,0) ├\n", 351 | " └─────────────┘┌─┴─┐├───────────────┤\n", 352 | "q_1: ───────────────┤ X ├┤ U(5.4637,π,0) ├\n", 353 | " └───┘└───────────────┘" 354 | ], 355 | "text/plain": [ 356 | " ┌─────────────┐ ┌───────────────┐\n", 357 | "q_0: ┤ RY(0.16854) ├──■──┤ U(4.4543,π,0) ├\n", 358 | " └─────────────┘┌─┴─┐├───────────────┤\n", 359 | "q_1: ───────────────┤ X ├┤ U(5.4637,π,0) ├\n", 360 | " └───┘└───────────────┘" 361 | ] 362 | }, 363 | "execution_count": 13, 364 | "metadata": {}, 365 | "output_type": "execute_result" 366 | } 367 | ], 368 | "source": [ 369 | "qc.u(theta, phi, lamb, 1)\n", 370 | "qc.draw()" 371 | ] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "id": "1c082208", 376 | "metadata": {}, 377 | "source": [ 378 | "Finally, we can verify that the final state is the same as the one we generated randomly at the start. " 379 | ] 380 | }, 381 | { 382 | "cell_type": "markdown", 383 | "id": "5c5a2d8d", 384 | "metadata": {}, 385 | "source": [ 386 | "**State generated with circuit**" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": 14, 392 | "id": "6a28b150", 393 | "metadata": {}, 394 | "outputs": [ 395 | { 396 | "data": { 397 | "text/latex": [ 398 | "$\\displaystyle \\left[\\begin{matrix}0.5843\\\\0.18108\\\\0.7036\\\\0.36159\\end{matrix}\\right]$" 399 | ], 400 | "text/plain": [ 401 | "Matrix([\n", 402 | "[ 0.5843],\n", 403 | "[0.18108],\n", 404 | "[ 0.7036],\n", 405 | "[0.36159]])" 406 | ] 407 | }, 408 | "execution_count": 14, 409 | "metadata": {}, 410 | "output_type": "execute_result" 411 | } 412 | ], 413 | "source": [ 414 | "Matrix(np.round(Statevector(qc.reverse_bits()), 5))" 415 | ] 416 | }, 417 | { 418 | "cell_type": "markdown", 419 | "id": "24af5529", 420 | "metadata": {}, 421 | "source": [ 422 | "**Randomly generated state**" 423 | ] 424 | }, 425 | { 426 | "cell_type": "code", 427 | "execution_count": 15, 428 | "id": "e94b0db9", 429 | "metadata": {}, 430 | "outputs": [ 431 | { 432 | "data": { 433 | "text/latex": [ 434 | "$\\displaystyle \\left[\\begin{matrix}0.5843\\\\0.18108\\\\0.7036\\\\0.36159\\end{matrix}\\right]$" 435 | ], 436 | "text/plain": [ 437 | "Matrix([\n", 438 | "[ 0.5843],\n", 439 | "[0.18108],\n", 440 | "[ 0.7036],\n", 441 | "[0.36159]])" 442 | ] 443 | }, 444 | "execution_count": 15, 445 | "metadata": {}, 446 | "output_type": "execute_result" 447 | } 448 | ], 449 | "source": [ 450 | "Matrix(np.round(state, 5))" 451 | ] 452 | }, 453 | { 454 | "cell_type": "markdown", 455 | "id": "ab92adab", 456 | "metadata": {}, 457 | "source": [ 458 | "As you can see, we obtained exactly what we were looking for! (Except for the fact that we had to use `qc.reverse_bits()`, but that's just because of the discrepancy between the endian used in the paper and in Qiskit.) Thus, we can put this two-qubit state generator in a single function." 459 | ] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "execution_count": 23, 464 | "id": "2b327fd4", 465 | "metadata": {}, 466 | "outputs": [], 467 | "source": [ 468 | "def two_qubit_state(state):\n", 469 | " qc = QuantumCircuit(2)\n", 470 | " \n", 471 | " # Normalize state and get Schmidt decomposition\n", 472 | " state = state / np.linalg.norm(state)\n", 473 | " a, b, s = schmidt_decomp_even(state)\n", 474 | "\n", 475 | " # Phase 1\n", 476 | " qc.ry(2 * np.arccos(s[0]), 0)\n", 477 | " \n", 478 | " # Phase 2\n", 479 | " qc.cx(0, 1)\n", 480 | " \n", 481 | " # Phase 3\n", 482 | " qc.unitary(np.block([a[0].flatten().T, a[1].flatten().T]).reshape(2, 2).T, 0)\n", 483 | " \n", 484 | " # Phase 4\n", 485 | " qc.unitary(np.block([b[0].flatten().T, b[1].flatten().T]).reshape(2, 2).T, 1)\n", 486 | " \n", 487 | " return qc" 488 | ] 489 | }, 490 | { 491 | "cell_type": "code", 492 | "execution_count": 24, 493 | "id": "5254e315", 494 | "metadata": {}, 495 | "outputs": [ 496 | { 497 | "data": { 498 | "text/html": [ 499 | "
global phase: -4.7278\n", 500 | " ┌───────────────┐ ┌───────────────────────────┐\n", 501 | "q_0: ┤ R(1.0098,π/2) ├──■──┤ U3(1.7278,4.4604,-1.1656) ├\n", 502 | " └───────────────┘┌─┴─┐└──┬─────────────────────┬──┘\n", 503 | "q_1: ─────────────────┤ X ├───┤ U3(2.1845,3.3378,0) ├───\n", 504 | " └───┘ └─────────────────────┘" 505 | ], 506 | "text/plain": [ 507 | "global phase: -4.7278\n", 508 | " ┌───────────────┐ ┌───────────────────────────┐\n", 509 | "q_0: ┤ R(1.0098,π/2) ├──■──┤ U3(1.7278,4.4604,-1.1656) ├\n", 510 | " └───────────────┘┌─┴─┐└──┬─────────────────────┬──┘\n", 511 | "q_1: ─────────────────┤ X ├───┤ U3(2.1845,3.3378,0) ├───\n", 512 | " └───┘ └─────────────────────┘ " 513 | ] 514 | }, 515 | "execution_count": 24, 516 | "metadata": {}, 517 | "output_type": "execute_result" 518 | } 519 | ], 520 | "source": [ 521 | "state = random_statevector(4).data\n", 522 | "qc = two_qubit_state(state)\n", 523 | "qc.decompose().draw()" 524 | ] 525 | }, 526 | { 527 | "cell_type": "markdown", 528 | "id": "05c41d1c", 529 | "metadata": {}, 530 | "source": [ 531 | "**State generated with circuit**" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": 25, 537 | "id": "71bf6d06", 538 | "metadata": {}, 539 | "outputs": [ 540 | { 541 | "data": { 542 | "text/latex": [ 543 | "$\\displaystyle \\left[\\begin{matrix}0.30604 + 0.3858 i\\\\0.23186 - 0.40268 i\\\\0.25725 + 0.19526 i\\\\-0.63667 + 0.17869 i\\end{matrix}\\right]$" 544 | ], 545 | "text/plain": [ 546 | "Matrix([\n", 547 | "[ 0.30604 + 0.3858*I],\n", 548 | "[ 0.23186 - 0.40268*I],\n", 549 | "[ 0.25725 + 0.19526*I],\n", 550 | "[-0.63667 + 0.17869*I]])" 551 | ] 552 | }, 553 | "execution_count": 25, 554 | "metadata": {}, 555 | "output_type": "execute_result" 556 | } 557 | ], 558 | "source": [ 559 | "circ = Statevector(qc.reverse_bits()).data\n", 560 | "Matrix(np.round(circ, 5))" 561 | ] 562 | }, 563 | { 564 | "cell_type": "markdown", 565 | "id": "d9bf2dae", 566 | "metadata": {}, 567 | "source": [ 568 | "**Randomly generated state**" 569 | ] 570 | }, 571 | { 572 | "cell_type": "code", 573 | "execution_count": 26, 574 | "id": "7ddab2fc", 575 | "metadata": {}, 576 | "outputs": [ 577 | { 578 | "data": { 579 | "text/latex": [ 580 | "$\\displaystyle \\left[\\begin{matrix}0.30604 + 0.3858 i\\\\0.23186 - 0.40268 i\\\\0.25725 + 0.19526 i\\\\-0.63667 + 0.17869 i\\end{matrix}\\right]$" 581 | ], 582 | "text/plain": [ 583 | "Matrix([\n", 584 | "[ 0.30604 + 0.3858*I],\n", 585 | "[ 0.23186 - 0.40268*I],\n", 586 | "[ 0.25725 + 0.19526*I],\n", 587 | "[-0.63667 + 0.17869*I]])" 588 | ] 589 | }, 590 | "execution_count": 26, 591 | "metadata": {}, 592 | "output_type": "execute_result" 593 | } 594 | ], 595 | "source": [ 596 | "Matrix(np.round(state, 5))" 597 | ] 598 | }, 599 | { 600 | "cell_type": "markdown", 601 | "id": "be8b0fae", 602 | "metadata": {}, 603 | "source": [ 604 | "As it is evident, we were not considering complex statevectors in the simple walkthrough before. But considering them is not too hard as you can see from the function above. Instead of calculating the angles for a $U$ gate, we can just construct the unitary matrix from the statevectors $|\\psi_i\\rangle$ and $|\\phi_i\\rangle$. Qiskit then takes care of converting that into a $U$ gate and keeps track of global phase. To make sure this works, we can run it for a large amount of times and check the state generated is equal to the expected state. " 605 | ] 606 | }, 607 | { 608 | "cell_type": "code", 609 | "execution_count": 27, 610 | "id": "4a42c2b8", 611 | "metadata": {}, 612 | "outputs": [], 613 | "source": [ 614 | "for _ in range(100):\n", 615 | " state = random_statevector(4).data\n", 616 | " qc = two_qubit_state(state)\n", 617 | " circ = Statevector(qc.reverse_bits()).data\n", 618 | " \n", 619 | " assert np.allclose(circ, state)" 620 | ] 621 | }, 622 | { 623 | "cell_type": "code", 624 | "execution_count": null, 625 | "id": "a356280a", 626 | "metadata": {}, 627 | "outputs": [], 628 | "source": [] 629 | } 630 | ], 631 | "metadata": { 632 | "kernelspec": { 633 | "display_name": "Python 3", 634 | "language": "python", 635 | "name": "python3" 636 | }, 637 | "language_info": { 638 | "codemirror_mode": { 639 | "name": "ipython", 640 | "version": 3 641 | }, 642 | "file_extension": ".py", 643 | "mimetype": "text/x-python", 644 | "name": "python", 645 | "nbconvert_exporter": "python", 646 | "pygments_lexer": "ipython3", 647 | "version": "3.8.8" 648 | } 649 | }, 650 | "nbformat": 4, 651 | "nbformat_minor": 5 652 | } 653 | -------------------------------------------------------------------------------- /algorithms/Hamiltonian Simulation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": { 5 | "image.png": { 6 | "image/png": "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" 7 | } 8 | }, 9 | "cell_type": "markdown", 10 | "id": "5e256027", 11 | "metadata": {}, 12 | "source": [ 13 | "# Hamiltonian simulation via Trotter decomposition\n", 14 | "One of the most sought-after applications of quantum computing is the simulation of physical processes, e.g., simulating molecules for drug development and many-body problems. These simulations generally involve taking a Hamiltonian operator $\\hat H$ and a time $t$ which is used to evolve an arbitrary state from $|\\psi\\rangle$ to $e^{i\\hat H t}|\\psi\\rangle$. Creating a circuit that applies the operator $e^{i \\hat H t}$ is not immediately obvious, but we can start off with a two-qubit example. \n", 15 | "\n", 16 | "**Simulating $\\sigma_i$ exponentials**\n", 17 | "\n", 18 | "Suppose we want to simulate $e^{i \\sigma_z \\otimes \\sigma_z t}$. The circuit to do this is known to be [[1]](https://quantumcomputing.stackexchange.com/a/11373/16092):\n", 19 | "\n", 20 | "\n", 21 | "\n", 22 | "where the argument to the rotation gate $R_z$ is $-2t$. \n", 23 | "\n", 24 | "Showing that this circuit is equivalent to $e^{i \\sigma_z \\otimes \\sigma_z t}$ is not too hard. Remember that we have the Euler-like decomposition of the operator as $e^{i \\sigma_z \\otimes \\sigma_z t} = \\cos(t) I+ i \\sin(t) \\sigma_z \\otimes \\sigma_z$ (which works since we have that $\\sigma_z^2 = I$). Thus, we have to show that the circuit above simplifies to this same expression. Doing this is a bit long but not hard, as shown below:\n", 25 | "\n", 26 | "$$\n", 27 | "\\begin{align}\n", 28 | "\\text{CNOT}(I \\otimes e^{i \\sigma_zt})\\text{CNOT} &= \\text{CNOT}\\big[ \\cos(t) I\\otimes I + i \\sin(t) I \\otimes \\sigma_z \\big]\\big[|0\\rangle \\langle 0 | \\otimes I + |1\\rangle \\langle 1 | \\otimes \\sigma_x \\big] \\\\\n", 29 | "&=\\text{CNOT}\\big[ \\cos(t)|0\\rangle\\langle0|\\otimes I+\\cos(t)|1\\rangle\\langle1| \\otimes \\sigma_x + i\\sin(t)|0\\rangle\\langle0|\\otimes\\sigma_z+ i\\sin(t)|1\\rangle\\langle1|\\otimes\\sigma_z\\sigma_x \\big] \\\\\n", 30 | "&= \\cos(t)|0\\rangle\\langle0|\\otimes I + \\cos(t)|1\\rangle\\langle1|\\otimes I + i\\sin(t)|0\\rangle\\langle0|\\otimes\\sigma_z+i\\sin(t)|1\\rangle\\langle1|\\otimes\\sigma_x\\sigma_z\\sigma_x \\\\\n", 31 | "&= \\cos(t) I+i \\sin(t)\\big[|0\\rangle\\langle0|\\otimes\\sigma_z-|1\\rangle\\langle1|\\otimes\\sigma_z\\big] \\qquad (\\text{since }\\sigma_x\\sigma_z\\sigma_x=-\\sigma_z) \\\\\n", 32 | "&= \\cos(t) I+i \\sin(t)\\big[(|0\\rangle\\langle0| - |1\\rangle\\langle1|) \\otimes\\sigma_z\\big] \\\\\n", 33 | "&= \\cos(t) I + i \\sin(t) \\sigma_z \\otimes \\sigma_z \\qquad (\\text{since } \\sigma_z = |0\\rangle\\langle0| - |1\\rangle\\langle1|)\n", 34 | "\\end{align}\n", 35 | "$$\n", 36 | "\n", 37 | "This can easily be extended to any number of qubits, i.e., $e^{i \\sigma_z \\otimes \\sigma_z \\otimes \\cdots \\otimes \\sigma_z t}$ [[3]](https://www.tandfonline.com/doi/abs/10.1080/00268976.2011.552441). Now, what happens if we have a Pauli matrix that is not $\\sigma_z$ in the exponent? Well, just apply a self-inverse gate $U$ before and after the chain of $CX$s such that $\\sigma_k = U\\sigma_zU$, where $k \\in \\{x, y\\}$. This gate would be the Hadamard gate for $\\sigma_x$ and $\\frac{1}{\\sqrt{2}} \\begin{bmatrix} 1 & -i \\\\ i & -1 \\end{bmatrix}$ for $\\sigma_y$. And if its the identity, you can just leave that qubit unaffected!\n", 38 | "\n", 39 | "**Simulating general exponentials**\n", 40 | "\n", 41 | "But this just tells us how to simulate Pauli strings, and we may not be given the Hamiltonian $\\hat H$ on this form. However, it is a fact that for any matrix $A$ with its dimension being a power of $2$ (which would be the case here since we are working with qubits), there exists some decomposition into a Pauli string of the following form [[2]](https://quantumcomputing.stackexchange.com/a/8726/16092):\n", 42 | "\n", 43 | "$$ A =\\sum_{i,j,k,l}h_{ijkl}\\cdot \\frac{1}{4}\\sigma_i\\otimes\\sigma_j\\otimes\\sigma_k\\otimes\\sigma_l $$\n", 44 | "where\n", 45 | "$$ h_{ijkl} = \\frac{1}{4}\\text{Tr}\\big((\\sigma_i\\otimes\\sigma_j\\otimes\\sigma_k\\otimes\\sigma_l) \\cdot A\\big) $$\n", 46 | "\n", 47 | "Thus, knowing how to simulate Pauli strings, we can basically simulate any Hamiltonian $H$. Using the Pauli string of a Hamiltonian, we can construct the Trotter decomposition for which we can create a circuit based off the simple circuit we saw above. The Trotter decomposition looks as follows:\n", 48 | "\n", 49 | "$$e^{i\\hat Ht} \\approx \\big(\\prod_k e^{i c_k P_k t/N }\\big)^{N},$$\n", 50 | "\n", 51 | "where $P_k$ is a tensor product of Pauli matrices, $c_k$ the coefficient corresponding to each $P_k$, $t$ the time introduced at the beggining, and $N$ a number called the Trotter number. The bigger $N$ is, the more accurate our simulation is. The specifics of Trotter decomposition are out of the scope of this brief notebook, but a good start is chapter 4.1 of [[3]](https://www.tandfonline.com/doi/abs/10.1080/00268976.2011.552441).\n", 52 | "\n", 53 | "**Qiskit implementation**\n", 54 | "\n", 55 | "With this background in place, we can start implementing the simulation in Qiskit. First we are going to define a simple function that creates the circuit scheme introduced at the beggining for operators of the form $e^{i \\sigma_z \\otimes \\sigma_z \\otimes \\cdots \\otimes \\sigma_z t}$." 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 1, 61 | "id": "ee033d63", 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "from qiskit import QuantumCircuit\n", 66 | "import numpy as np\n", 67 | "\n", 68 | "def sim_z(t, qc, qubits):\n", 69 | " \"\"\"\n", 70 | " Add gates to simulate a Pauli Z string exponential\n", 71 | " \n", 72 | " Parameters:\n", 73 | " t: float\n", 74 | " Time parameter to simulate for\n", 75 | " qc: QuantumCircuit\n", 76 | " Circuit to append gates to\n", 77 | " qubits: array\n", 78 | " Array indicating qubits indeces (in order) to \n", 79 | " append the gates to\n", 80 | " \"\"\"\n", 81 | " for i in range(len(qubits) - 1):\n", 82 | " qc.cx(qubits[i], qubits[i + 1])\n", 83 | " qc.rz(-2 * t, qubits[-1])\n", 84 | " for i in range(len(qubits) - 1, 0, -1):\n", 85 | " qc.cx(qubits[i - 1], qubits[i])" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "id": "56b8be4d", 91 | "metadata": {}, 92 | "source": [ 93 | "Using this, we can clearly picture the basic component of the simulation. " 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 2, 99 | "id": "3e09dd1c", 100 | "metadata": {}, 101 | "outputs": [ 102 | { 103 | "data": { 104 | "text/html": [ 105 | "
\n", 106 | "q_0: ──■─────────────────────────■──\n", 107 | " ┌─┴─┐ ┌─┴─┐\n", 108 | "q_1: ┤ X ├──■───────────────■──┤ X ├\n", 109 | " └───┘┌─┴─┐┌─────────┐┌─┴─┐└───┘\n", 110 | "q_2: ─────┤ X ├┤ Rz(-2π) ├┤ X ├─────\n", 111 | " └───┘└─────────┘└───┘" 112 | ], 113 | "text/plain": [ 114 | " \n", 115 | "q_0: ──■─────────────────────────■──\n", 116 | " ┌─┴─┐ ┌─┴─┐\n", 117 | "q_1: ┤ X ├──■───────────────■──┤ X ├\n", 118 | " └───┘┌─┴─┐┌─────────┐┌─┴─┐└───┘\n", 119 | "q_2: ─────┤ X ├┤ Rz(-2π) ├┤ X ├─────\n", 120 | " └───┘└─────────┘└───┘ " 121 | ] 122 | }, 123 | "execution_count": 2, 124 | "metadata": {}, 125 | "output_type": "execute_result" 126 | } 127 | ], 128 | "source": [ 129 | "qc = QuantumCircuit(3)\n", 130 | "sim_z(np.pi, qc, [0, 1, 2])\n", 131 | "qc.draw()" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "id": "9b654bc3", 137 | "metadata": {}, 138 | "source": [ 139 | "Now, we can expand this so we can simulate any Pauli string." 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 3, 145 | "id": "88abacf3", 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [ 149 | "def sim_pauli(arr, t, qc, qubits):\n", 150 | " \"\"\"\n", 151 | " Append gates to simulate any Pauli string\n", 152 | " \n", 153 | " Parameters:\n", 154 | " arr: array\n", 155 | " Array encoding the Pauli string\n", 156 | " t: float\n", 157 | " Time parameter to simulate for\n", 158 | " qc: QuantumCircuit\n", 159 | " Circuit to append gates to\n", 160 | " qubits: array\n", 161 | " Array indicating qubits indeces (in order) to \n", 162 | " append the gates to\n", 163 | " \"\"\"\n", 164 | " new_arr = []\n", 165 | " new_qub = []\n", 166 | " for idx in range(len(arr)):\n", 167 | " if arr[idx] != 'I':\n", 168 | " new_arr.append(arr[idx])\n", 169 | " new_qub.append(qubits[idx])\n", 170 | "\n", 171 | " h_y = 1 / np.sqrt(2) * np.array([[1, -1j], [1j, -1]])\n", 172 | " for i in range(len(new_arr)):\n", 173 | " if new_arr[i] == 'X':\n", 174 | " qc.h(new_qub[i])\n", 175 | " elif new_arr[i] == 'Y':\n", 176 | " qc.unitary(h_y, [new_qub[i]], r'$H_y$')\n", 177 | " \n", 178 | " sim_z(t, qc, new_qub)\n", 179 | " \n", 180 | " for i in range(len(new_arr)):\n", 181 | " if new_arr[i] == 'X':\n", 182 | " qc.h(new_qub[i])\n", 183 | " elif new_arr[i] == 'Y':\n", 184 | " qc.unitary(h_y, [new_qub[i]], r'$H_y$')" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "id": "7de4f752", 190 | "metadata": {}, 191 | "source": [ 192 | "And finally, we write a small function that takes in a Hamiltonian $\\hat H$ as its Trotter decomposition and simulates it in a given quantum circuit. " 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 4, 198 | "id": "b9f204bc", 199 | "metadata": {}, 200 | "outputs": [], 201 | "source": [ 202 | "def sim_ham(hamiltonian, t, qc, qubits, trotter=1):\n", 203 | " \"\"\"\n", 204 | " Simulates Hamiltonian given as Pauli string\n", 205 | " \n", 206 | " Parameters:\n", 207 | " hamiltonian: dict\n", 208 | " Dictionary encoding the hamiltonian with each\n", 209 | " Pauli product as a key with the coefficient as value\n", 210 | " t: float\n", 211 | " Time parameter to simulate for\n", 212 | " qc: QuantumCircuit\n", 213 | " Circuit to append gates to\n", 214 | " qubits: array\n", 215 | " Array indicating qubits indeces (in order) to \n", 216 | " append the gates to\n", 217 | " \n", 218 | " \"\"\"\n", 219 | " temp = QuantumCircuit(len(qubits))\n", 220 | " delta_t = t / trotter\n", 221 | " for pauli in hamiltonian:\n", 222 | " sim_pauli(pauli, hamiltonian[pauli] * delta_t, temp, range(len(qubits)))\n", 223 | " \n", 224 | " for i in range(trotter):\n", 225 | " qc.compose(temp, qubits, inplace=True)" 226 | ] 227 | }, 228 | { 229 | "cell_type": "markdown", 230 | "id": "28844433", 231 | "metadata": {}, 232 | "source": [ 233 | "Analyzing this function, we can see that it basically resembles this formula that we introduced in the background:\n", 234 | "\n", 235 | "$$ e^{i\\hat Ht} \\approx \\big(\\prod_k e^{i c_k P_k t/N }\\big)^{N} $$\n", 236 | "\n", 237 | "First, we see that `delta_t` corresponds to $t / N$. Then, for each Pauli term in the Pauli string representing the Hamiltonian (the first loop corresponds to the product $\\prod_k$, since consecutive gates correspond to matrix multiplication), we call our function `sim_pauli` that adds the corresponding gates, using `time = hamiltonian[pauli] * delta_t`, which corresponds to $c_k t/n$ in the formula. Finally, we simply append the resulting circuit $N$ times in the second loop, which resembles the exponentiation.\n", 238 | "\n", 239 | "**Comparing to exact calculation**\n", 240 | "\n", 241 | "To wrap everything up, we can see how our simulation circuit compares to directly computing $e^{i \\hat H t}|\\psi\\rangle$. Here, we test this with the Hamiltonian $\\hat H = 2 XZY + 5 ZXX + 2 YXZ$, time $\\frac{1}{2 * \\pi}$ and $N = 50$, which gives us high accuracy. First, we will create the quantum circuit that simulates this and extract the resulting statevector." 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 5, 247 | "id": "5903f68b", 248 | "metadata": {}, 249 | "outputs": [ 250 | { 251 | "data": { 252 | "text/html": [ 253 | "
┌───────┐ ┌───┐┌──────────┐┌───┐┌───────┐┌───┐ ┌───┐┌──────────┐»\n", 254 | "q_0: ┤ $H_y$ ├─────┤ X ├┤ Rz(-2/π) ├┤ X ├┤ $H_y$ ├┤ H ├─────┤ X ├┤ Rz(-5/π) ├»\n", 255 | " └───────┘┌───┐└─┬─┘└──────────┘└─┬─┘└─┬───┬─┘├───┤┌───┐└─┬─┘└──────────┘»\n", 256 | "q_1: ─────────┤ X ├──■────────────────■────┤ X ├──┤ H ├┤ X ├──■──────────────»\n", 257 | " ┌───┐ └─┬─┘ └─┬─┘ ├───┤└─┬─┘ »\n", 258 | "q_2: ──┤ H ├────■────────────────────────────■────┤ H ├──■───────────────────»\n", 259 | " └───┘ └───┘ »\n", 260 | "« ┌───┐┌───┐ ┌───┐┌──────────┐┌───┐ \n", 261 | "«q_0: ┤ X ├┤ H ├───────────────────┤ X ├┤ Rz(-2/π) ├┤ X ├──────────────\n", 262 | "« └─┬─┘├───┤ ┌───┐ ┌───┐┌───┐└─┬─┘└──────────┘└─┬─┘┌───┐ ┌───┐ \n", 263 | "«q_1: ──■──┤ X ├──┤ H ├──┤ H ├┤ X ├──■────────────────■──┤ X ├──┤ H ├──\n", 264 | "« └─┬─┘┌─┴───┴─┐└───┘└─┬─┘ └─┬─┘┌─┴───┴─┐\n", 265 | "«q_2: ───────■──┤ $H_y$ ├───────■──────────────────────────■──┤ $H_y$ ├\n", 266 | "« └───────┘ └───────┘" 267 | ], 268 | "text/plain": [ 269 | " ┌───────┐ ┌───┐┌──────────┐┌───┐┌───────┐┌───┐ ┌───┐┌──────────┐»\n", 270 | "q_0: ┤ $H_y$ ├─────┤ X ├┤ Rz(-2/π) ├┤ X ├┤ $H_y$ ├┤ H ├─────┤ X ├┤ Rz(-5/π) ├»\n", 271 | " └───────┘┌───┐└─┬─┘└──────────┘└─┬─┘└─┬───┬─┘├───┤┌───┐└─┬─┘└──────────┘»\n", 272 | "q_1: ─────────┤ X ├──■────────────────■────┤ X ├──┤ H ├┤ X ├──■──────────────»\n", 273 | " ┌───┐ └─┬─┘ └─┬─┘ ├───┤└─┬─┘ »\n", 274 | "q_2: ──┤ H ├────■────────────────────────────■────┤ H ├──■───────────────────»\n", 275 | " └───┘ └───┘ »\n", 276 | "« ┌───┐┌───┐ ┌───┐┌──────────┐┌───┐ \n", 277 | "«q_0: ┤ X ├┤ H ├───────────────────┤ X ├┤ Rz(-2/π) ├┤ X ├──────────────\n", 278 | "« └─┬─┘├───┤ ┌───┐ ┌───┐┌───┐└─┬─┘└──────────┘└─┬─┘┌───┐ ┌───┐ \n", 279 | "«q_1: ──■──┤ X ├──┤ H ├──┤ H ├┤ X ├──■────────────────■──┤ X ├──┤ H ├──\n", 280 | "« └─┬─┘┌─┴───┴─┐└───┘└─┬─┘ └─┬─┘┌─┴───┴─┐\n", 281 | "«q_2: ───────■──┤ $H_y$ ├───────■──────────────────────────■──┤ $H_y$ ├\n", 282 | "« └───────┘ └───────┘" 283 | ] 284 | }, 285 | "execution_count": 5, 286 | "metadata": {}, 287 | "output_type": "execute_result" 288 | } 289 | ], 290 | "source": [ 291 | "qc = QuantumCircuit(3)\n", 292 | "sim_ham({\"XZY\": 2, \"ZXX\": 5, \"YXZ\": 2}, 1 / (2 * np.pi), qc, [0, 1, 2], trotter=1) \n", 293 | "qc = qc.reverse_bits() # reverse because of Qiskit's endianness\n", 294 | "qc.draw()" 295 | ] 296 | }, 297 | { 298 | "cell_type": "markdown", 299 | "id": "7ad3d0ce-c645-41c3-b715-f28ab563d216", 300 | "metadata": {}, 301 | "source": [ 302 | "For illustration purposes, the circuit above has $N=1$, but we will set it to $N=50$ when actually sending the circuit to the simulator." 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 9, 308 | "id": "9fd5b0c4", 309 | "metadata": {}, 310 | "outputs": [ 311 | { 312 | "data": { 313 | "text/latex": [ 314 | "$\\displaystyle \\left[\\begin{matrix}0.62069\\\\0\\\\0\\\\0.0279 + 0.66576 i\\\\0\\\\-0.26743 + 0.23046 i\\\\-0.21432 + 0.01279 i\\\\0\\end{matrix}\\right]$" 315 | ], 316 | "text/plain": [ 317 | "Matrix([\n", 318 | "[ 0.62069],\n", 319 | "[ 0],\n", 320 | "[ 0],\n", 321 | "[ 0.0279 + 0.66576*I],\n", 322 | "[ 0],\n", 323 | "[-0.26743 + 0.23046*I],\n", 324 | "[-0.21432 + 0.01279*I],\n", 325 | "[ 0]])" 326 | ] 327 | }, 328 | "execution_count": 9, 329 | "metadata": {}, 330 | "output_type": "execute_result" 331 | } 332 | ], 333 | "source": [ 334 | "from qiskit import Aer, execute\n", 335 | "from sympy import Matrix\n", 336 | "\n", 337 | "qc = QuantumCircuit(3)\n", 338 | "sim_ham({\"XZY\": 2, \"ZXX\": 5, \"YXZ\": 2}, 1 / (2 * np.pi), qc, [0, 1, 2], trotter=50)\n", 339 | "qc = qc.reverse_bits()\n", 340 | "\n", 341 | "backend = Aer.get_backend('statevector_simulator')\n", 342 | "result = execute(qc, backend).result()\n", 343 | "vec = result.get_statevector()\n", 344 | "vec = vec / vec[0] # global phase\n", 345 | "qvec = vec / np.linalg.norm(vec) # normalize\n", 346 | "Matrix(np.round(qvec, 5))" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "id": "3ea1eca6", 352 | "metadata": {}, 353 | "source": [ 354 | "Note that here we used the `statevector_simulator` to directly extract the statevector. When using a real device, we would need to use state tomography (or a similar procedure) if we want to directly know the statevector. Now that we have our result with a quantum circuit, we can directly compute the expected result and compare. This is relatively simple, but a few comments are left in the following cell to clear any doubts. " 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": 7, 360 | "id": "cb7f7ebd", 361 | "metadata": {}, 362 | "outputs": [ 363 | { 364 | "data": { 365 | "text/latex": [ 366 | "$\\displaystyle \\left[\\begin{matrix}0.62068\\\\0\\\\0\\\\0.02652 + 0.66582 i\\\\0\\\\-0.26746 + 0.23046 i\\\\-0.21449 + 0.00854 i\\\\0\\end{matrix}\\right]$" 367 | ], 368 | "text/plain": [ 369 | "Matrix([\n", 370 | "[ 0.62068],\n", 371 | "[ 0],\n", 372 | "[ 0],\n", 373 | "[ 0.02652 + 0.66582*I],\n", 374 | "[ 0],\n", 375 | "[-0.26746 + 0.23046*I],\n", 376 | "[-0.21449 + 0.00854*I],\n", 377 | "[ 0]])" 378 | ] 379 | }, 380 | "execution_count": 7, 381 | "metadata": {}, 382 | "output_type": "execute_result" 383 | } 384 | ], 385 | "source": [ 386 | "import scipy\n", 387 | "\n", 388 | "# Start with |0> state\n", 389 | "start = np.zeros(2 ** 3)\n", 390 | "start[0] = 1\n", 391 | "\n", 392 | "# Get the matrix corresponding to some Pauli product\n", 393 | "# This function can be optimized, but it is left as it\n", 394 | "# is for clarity purposes\n", 395 | "def get_pauli(string):\n", 396 | " init = string[0]\n", 397 | " string = string[1:]\n", 398 | " if init == 'X':\n", 399 | " out = np.array([[0, 1], [1, 0]])\n", 400 | " elif init == 'Z':\n", 401 | " out = np.array([[1, 0], [0, -1]])\n", 402 | " elif init == 'Y':\n", 403 | " out = np.array([[0, -1j], [1j, 0]])\n", 404 | " else:\n", 405 | " out = np.eye(2)\n", 406 | " \n", 407 | " for p in string:\n", 408 | " if p == 'X':\n", 409 | " out = np.kron(out, np.array([[0, 1], [1, 0]]))\n", 410 | " elif p == 'Z':\n", 411 | " out = np.kron(out, np.array([[1, 0], [0, -1]]))\n", 412 | " elif p == 'Y':\n", 413 | " out = np.kron(out, np.array([[0, -1j], [1j, 0]]))\n", 414 | " else:\n", 415 | " out = np.kron(out, np.eye(2))\n", 416 | "\n", 417 | " return out\n", 418 | "\n", 419 | "# Hamiltonian is calculated from the Pauli decomposition\n", 420 | "decomp = {\"XZY\": 2, \"ZXX\": 5, \"YXZ\": 2}\n", 421 | "H = np.zeros((2 ** 3, 2 ** 3))\n", 422 | "H = H.astype('complex128')\n", 423 | "for pauli in decomp:\n", 424 | " H += decomp[pauli] * get_pauli(pauli)\n", 425 | " \n", 426 | "# Hamiltonian is exponentiated and we multiply the starting\n", 427 | "# vector by it to get our result\n", 428 | "simul = scipy.linalg.expm(1j * H * (1 / (2 * np.pi)))\n", 429 | "vec = simul @ start\n", 430 | "vec = vec / vec[0] # global phase\n", 431 | "cvec = vec / np.linalg.norm(vec) # normalize\n", 432 | "Matrix(np.round(cvec, 5))" 433 | ] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "id": "21b4480e", 438 | "metadata": {}, 439 | "source": [ 440 | "By simply comparing the two vectors, we can say that our simulation was pretty accurate! As a more mathematically rigorous comparison, we can use state fidelity, which also shows us that our simulation is pretty good!" 441 | ] 442 | }, 443 | { 444 | "cell_type": "code", 445 | "execution_count": 8, 446 | "id": "57927828", 447 | "metadata": {}, 448 | "outputs": [ 449 | { 450 | "data": { 451 | "text/plain": [ 452 | "0.9999834345555809" 453 | ] 454 | }, 455 | "execution_count": 8, 456 | "metadata": {}, 457 | "output_type": "execute_result" 458 | } 459 | ], 460 | "source": [ 461 | "from qiskit.quantum_info import state_fidelity\n", 462 | "\n", 463 | "state_fidelity(qvec, cvec)" 464 | ] 465 | }, 466 | { 467 | "cell_type": "markdown", 468 | "id": "bacb0e57", 469 | "metadata": {}, 470 | "source": [ 471 | "**References**:\n", 472 | "- [[1]](https://quantumcomputing.stackexchange.com/a/11373/16092) An approach for Hamiltonian simulation by Davit Khachatryan on Quantum Computing StackExchange.\n", 473 | "- [[2]](https://quantumcomputing.stackexchange.com/a/8726/16092) Can arbitrary matrices be decomposed using the Pauli basis? by Danylo Y on Quantum Computing StackExchange.\n", 474 | "- [[3]](https://www.tandfonline.com/doi/abs/10.1080/00268976.2011.552441) Simulation of electronic structure Hamiltonians using quantum computers by James D. Whitfield ,Jacob Biamonte and Alán Aspuru-Guzik." 475 | ] 476 | } 477 | ], 478 | "metadata": { 479 | "kernelspec": { 480 | "display_name": "Python 3 (ipykernel)", 481 | "language": "python", 482 | "name": "python3" 483 | }, 484 | "language_info": { 485 | "codemirror_mode": { 486 | "name": "ipython", 487 | "version": 3 488 | }, 489 | "file_extension": ".py", 490 | "mimetype": "text/x-python", 491 | "name": "python", 492 | "nbconvert_exporter": "python", 493 | "pygments_lexer": "ipython3", 494 | "version": "3.10.6" 495 | }, 496 | "widgets": { 497 | "application/vnd.jupyter.widget-state+json": { 498 | "state": {}, 499 | "version_major": 2, 500 | "version_minor": 0 501 | } 502 | } 503 | }, 504 | "nbformat": 4, 505 | "nbformat_minor": 5 506 | } 507 | -------------------------------------------------------------------------------- /algorithms/Teleportation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "compact-blogger", 6 | "metadata": {}, 7 | "source": [ 8 | "## Imports" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "pursuant-wagon", 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "import config\n", 19 | "import numpy as np\n", 20 | "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, Aer, execute\n", 21 | "from qiskit.visualization import plot_histogram" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "id": "posted-marine", 27 | "metadata": {}, 28 | "source": [ 29 | "# Teleportation" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "id": "unauthorized-postage", 35 | "metadata": {}, 36 | "source": [ 37 | "The quantum teleportation protocol is a fundamental part of many quantum algorithms. It enables you to transfer the state of one qubit to another qubit instantly. An important distinction to make is that teleportation in this context refers to the transfer of information rather than matter, since the qubits stay in the same place, but the state is transferred.\n", 38 | "\n", 39 | "This protocol is useful to overcome the difficulties imposed by the [no-cloning theorem](https://en.wikipedia.org/wiki/No-cloning_theorem), which tells us that it is not possible to create an exact copy of a quantum state. Which means we cannot copy the state of one qubit into another, but we can teleport it. In fact, most uses of the teleportation protocol are to transfer the state of a qubit into another within a single QPU rather than across large distances like most sci-fi movies portray it. \n", 40 | "\n", 41 | "The circuit is composed the following way:" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 2, 47 | "id": "signed-saudi", 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "def teleportation(hardware = False):\n", 52 | " qreg_sender = QuantumRegister(1, name='q_sender')\n", 53 | " qreg_ep = QuantumRegister(1, name='q_ancillary')\n", 54 | " qreg_receiver = QuantumRegister(1, name='q_receiver')\n", 55 | " creg_receiver = ClassicalRegister(1, name='c_receiver')\n", 56 | " if not hardware:\n", 57 | " creg_ep = ClassicalRegister(1, name='c_ancillary')\n", 58 | " creg_sender = ClassicalRegister(1, name='c_sender')\n", 59 | " qc = QuantumCircuit(qreg_sender, qreg_ep, qreg_receiver, creg_sender, creg_ep, creg_receiver)\n", 60 | " else:\n", 61 | " qc = QuantumCircuit(qreg_sender, qreg_ep, qreg_receiver, creg_receiver)\n", 62 | "\n", 63 | " # Entangle ep register with receiver register\n", 64 | " qc.h(qreg_ep)\n", 65 | " qc.cx(qreg_ep, qreg_receiver)\n", 66 | "\n", 67 | " qc.barrier()\n", 68 | "\n", 69 | " # Prepare qubit to be sent with specific state\n", 70 | " qc.reset(qreg_sender)\n", 71 | " qc.h(qreg_sender)\n", 72 | " qc.rz(np.pi/4, qreg_sender)\n", 73 | " qc.h(qreg_sender)\n", 74 | "\n", 75 | " qc.barrier()\n", 76 | "\n", 77 | " # Send qubit\n", 78 | " qc.cx(qreg_sender, qreg_ep)\n", 79 | " qc.h(qreg_sender)\n", 80 | "\n", 81 | " if not hardware:\n", 82 | " qc.measure(qreg_sender, creg_sender)\n", 83 | " qc.measure(qreg_ep, creg_ep)\n", 84 | "\n", 85 | " qc.barrier()\n", 86 | "\n", 87 | " # Receive qubit and apply gates depending on measures of sender's and entangled's qubits\n", 88 | " qc.x(qreg_receiver).c_if(creg_ep, 1)\n", 89 | " qc.z(qreg_receiver).c_if(creg_sender, 1)\n", 90 | "\n", 91 | " qc.barrier()\n", 92 | " else:\n", 93 | " qc.barrier()\n", 94 | "\n", 95 | " # Use conditional quantum gates instead of classical controlled gates\n", 96 | " qc.cx(qreg_ep, qreg_receiver)\n", 97 | " qc.cz(qreg_sender, qreg_receiver)\n", 98 | "\n", 99 | " qc.barrier()\n", 100 | "\n", 101 | " # Measure\n", 102 | " qc.h(qreg_receiver)\n", 103 | " qc.rz(-np.pi/4, qreg_receiver)\n", 104 | " qc.h(qreg_receiver)\n", 105 | " qc.measure(qreg_receiver, creg_receiver)\n", 106 | "\n", 107 | " # Return circuit\n", 108 | " return qc" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 3, 114 | "id": "indonesian-start", 115 | "metadata": {}, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/html": [ 120 | "
░ ┌───┐┌─────────┐┌───┐ ░ ┌───┐┌─┐ ░ »\n", 121 | " q_sender: ───────────░──|0>─┤ H ├┤ Rz(π/4) ├┤ H ├─░───■──┤ H ├┤M├─░─»\n", 122 | " ┌───┐ ░ └───┘└─────────┘└───┘ ░ ┌─┴─┐└┬─┬┘└╥┘ ░ »\n", 123 | " q_ancillary: ┤ H ├──■───░────────────────────────────░─┤ X ├─┤M├──╫──░─»\n", 124 | " └───┘┌─┴─┐ ░ ░ └───┘ └╥┘ ║ ░ »\n", 125 | " q_receiver: ─────┤ X ├─░────────────────────────────░────────╫───╫──░─»\n", 126 | " └───┘ ░ ░ ║ ║ ░ »\n", 127 | " c_sender: 1/═════════════════════════════════════════════════╬═══╩════»\n", 128 | " ║ 0 »\n", 129 | "c_ancillary: 1/═════════════════════════════════════════════════╩════════»\n", 130 | " 0 »\n", 131 | " c_receiver: 1/══════════════════════════════════════════════════════════»\n", 132 | " »\n", 133 | "« ░ \n", 134 | "« q_sender: ───────────────░──────────────────────────\n", 135 | "« ░ \n", 136 | "« q_ancillary: ───────────────░──────────────────────────\n", 137 | "« ┌───┐ ┌───┐ ░ ┌───┐┌──────────┐┌───┐┌─┐\n", 138 | "« q_receiver: ─┤ X ├──┤ Z ├──░─┤ H ├┤ Rz(-π/4) ├┤ H ├┤M├\n", 139 | "« └─╥─┘ └─╥─┘ ░ └───┘└──────────┘└───┘└╥┘\n", 140 | "« ║ ┌──╨──┐ ║ \n", 141 | "« c_sender: 1/═══╬═══╡ 0x1 ╞══════════════════════════╬═\n", 142 | "« ┌──╨──┐└─────┘ ║ \n", 143 | "«c_ancillary: 1/╡ 0x1 ╞═════════════════════════════════╬═\n", 144 | "« └─────┘ ║ \n", 145 | "« c_receiver: 1/════════════════════════════════════════╩═\n", 146 | "« 0" 147 | ], 148 | "text/plain": [ 149 | " ░ ┌───┐┌─────────┐┌───┐ ░ ┌───┐┌─┐ ░ »\n", 150 | " q_sender: ───────────░──|0>─┤ H ├┤ Rz(π/4) ├┤ H ├─░───■──┤ H ├┤M├─░─»\n", 151 | " ┌───┐ ░ └───┘└─────────┘└───┘ ░ ┌─┴─┐└┬─┬┘└╥┘ ░ »\n", 152 | " q_ancillary: ┤ H ├──■───░────────────────────────────░─┤ X ├─┤M├──╫──░─»\n", 153 | " └───┘┌─┴─┐ ░ ░ └───┘ └╥┘ ║ ░ »\n", 154 | " q_receiver: ─────┤ X ├─░────────────────────────────░────────╫───╫──░─»\n", 155 | " └───┘ ░ ░ ║ ║ ░ »\n", 156 | " c_sender: 1/═════════════════════════════════════════════════╬═══╩════»\n", 157 | " ║ 0 »\n", 158 | "c_ancillary: 1/═════════════════════════════════════════════════╩════════»\n", 159 | " 0 »\n", 160 | " c_receiver: 1/══════════════════════════════════════════════════════════»\n", 161 | " »\n", 162 | "« ░ \n", 163 | "« q_sender: ───────────────░──────────────────────────\n", 164 | "« ░ \n", 165 | "« q_ancillary: ───────────────░──────────────────────────\n", 166 | "« ┌───┐ ┌───┐ ░ ┌───┐┌──────────┐┌───┐┌─┐\n", 167 | "« q_receiver: ─┤ X ├──┤ Z ├──░─┤ H ├┤ Rz(-π/4) ├┤ H ├┤M├\n", 168 | "« └─╥─┘ └─╥─┘ ░ └───┘└──────────┘└───┘└╥┘\n", 169 | "« ║ ┌──╨──┐ ║ \n", 170 | "« c_sender: 1/═══╬═══╡ 0x1 ╞══════════════════════════╬═\n", 171 | "« ┌──╨──┐└─────┘ ║ \n", 172 | "«c_ancillary: 1/╡ 0x1 ╞═════════════════════════════════╬═\n", 173 | "« └─────┘ ║ \n", 174 | "« c_receiver: 1/════════════════════════════════════════╩═\n", 175 | "« 0 " 176 | ] 177 | }, 178 | "execution_count": 3, 179 | "metadata": {}, 180 | "output_type": "execute_result" 181 | } 182 | ], 183 | "source": [ 184 | "circ = teleportation()\n", 185 | "circ.draw()" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "id": "demographic-teddy", 191 | "metadata": {}, 192 | "source": [ 193 | "$\\newcommand\\Hto{\\xrightarrow{H}}\\newcommand\\Xto{\\xrightarrow{X}}\\newcommand\\Zto{\\xrightarrow{Z}}\\newcommand\\Htopsi{\\xrightarrow{H|\\psi\\rangle}}\\newcommand\\Rzto{\\xrightarrow{R_z}}\\newcommand\\Cnot{\\xrightarrow{CNOT|\\psi\\phi\\rangle}}$We define three states $|\\psi\\rangle$, $|\\phi\\rangle$, and $|\\omega\\rangle$. $|\\psi\\rangle$ will be the state we want to send, $|\\phi\\rangle$ will be an ancillary qubit, and $|\\omega\\rangle$ will be the qubit to which we want to send the state originally in $|\\psi\\rangle$.\n", 194 | "\n", 195 | "$$ |\\psi\\rangle\\textrm{: sender qubit, } \\: |\\phi\\rangle\\textrm{: ancillary qubit, } \\: |\\omega\\rangle\\textrm{: receiver qubit.} $$\n", 196 | "\n", 197 | "As you can see, the first thing we do is entangle $|\\phi\\rangle$ with $|\\omega\\rangle$. This gives us the state:\n", 198 | "\n", 199 | "\\begin{equation} \\label{eq:first_entanglement}\n", 200 | " |\\psi\\rangle \\otimes \\frac{1}{\\sqrt{2}}(|00\\rangle + |11\\rangle) \\tag{1}\n", 201 | "\\end{equation}\n", 202 | "\n", 203 | "Note that in this equation and onward, we will describe our state as $|\\psi\\phi\\omega\\rangle$. For example, the state $|010\\rangle$ means that $|\\psi\\rangle = |0\\rangle$, $|\\phi\\rangle = |1\\rangle$, and $|\\omega\\rangle = |0\\rangle$. After entangling $|\\phi\\rangle$ and $|\\omega\\rangle$, we prepare $|\\psi\\rangle$ to the state we want to send. Let's now focus on this state and how it will result after applying the corresponding gates. \n", 204 | "\n", 205 | "\\begin{align}\n", 206 | " |\\psi\\rangle = |0\\rangle &\\Hto \\frac{1}{\\sqrt{2}}(|0\\rangle + |1\\rangle) \\\\\n", 207 | " &\\Rzto{} \\frac{1}{\\sqrt{2}}\\left(e^{-i\\frac{\\pi}{8}}|0\\rangle + e^{i\\frac{\\pi}{8}}|1\\rangle\\right) \\\\ \n", 208 | " &\\Hto{} \\frac{1}{2}\\left(e^{-i\\frac{\\pi}{8}}(|0\\rangle + |1\\rangle) + e^{i\\frac{\\pi}{8}}(|0\\rangle-|1\\rangle)\\right) = \\cos{\\frac{\\pi}{8}}|0\\rangle - \\sin{\\frac{\\pi}{8}}|1\\rangle \\label{eq:prepare_send_state} \\tag{2}\n", 209 | "\\end{align}\n", 210 | "\n", 211 | "The simplified state at \\eqref{eq:prepare_send_state} is the one we will be sending to $|\\omega\\rangle$. Now, we are going to entangle $|\\psi\\rangle$ with $|\\phi\\rangle$ using a CNOT gate and then we are going to send $|\\psi\\rangle$ through a Hadamard gate. Before applying any gates, let's see our state up to here. We can found this state by replacing $|\\psi\\rangle$ in \\eqref{eq:first_entanglement} with the state for $|\\psi\\rangle$ we got in \\eqref{eq:prepare_send_state}. \n", 212 | "\n", 213 | "\\begin{align} \\label{eq:expanded_state}\n", 214 | " \\left(\\cos{\\frac{\\pi}{8}}|0\\rangle - \\sin{\\frac{\\pi}{8}}|1\\rangle\\right) \\otimes \\frac{1}{\\sqrt{2}}\\left(|00\\rangle + |11\\rangle\\right) = \\frac{1}{\\sqrt{2}}\\left(\\cos{\\frac{\\pi}{8}}(|000\\rangle + |011\\rangle) - \\sin{\\frac{\\pi}{8}}(|100\\rangle + |111\\rangle)\\right) \\tag{3}\n", 215 | "\\end{align}\n", 216 | "\n", 217 | "First we are going to send our state through the CNOT gate, where $|\\psi\\rangle$ acts as the control qubit and $|\\phi\\rangle$ as the target qubit, and then we are going to send $|\\psi\\rangle$ through a Hadamard gate. The following equations describe this operations. For simplicity, we will denote the state we are starting with as $|\\psi\\phi\\omega\\rangle$, this state is the one we ended up with in \\eqref{eq:expanded_state}.\n", 218 | "\n", 219 | "\\begin{align}\n", 220 | " |\\psi\\phi\\omega\\rangle &\\Cnot{} \\frac{1}{\\sqrt{2}}\\left(\\cos{\\frac{\\pi}{8}}(|000\\rangle + |011\\rangle) - \\sin{\\frac{\\pi}{8}}(|110\\rangle + |101\\rangle)\\right) \\\\ \n", 221 | " &\\Htopsi{} \\frac{1}{2}\\left(\\cos{\\frac{\\pi}{8}} (|000\\rangle + |100\\rangle + |011\\rangle + |111\\rangle) - \\sin{\\frac{\\pi}{8}}(|010\\rangle - |110\\rangle + |001\\rangle - |101\\rangle) \\right) \\label{before_measuring} \\tag{4}\n", 222 | "\\end{align}\n", 223 | "\n", 224 | "Here it gets a little bit tricky, since we are going to measure $|\\psi\\rangle$ and $|\\phi\\rangle$. As you may know, there are 4 possible states we might end up with, these are $|00\\rangle$, $|01\\rangle$, $|10\\rangle$ and $|11\\rangle$. And for each of this four states, you can have either $|0\\rangle$ or $|1\\rangle$ for our last qubit: $|\\omega\\rangle$. This gives us the 8 possible states we can see in \\eqref{before_measuring}. Since we are only going to measure the first two qubits, $|\\omega\\rangle$ will remain in a superposition of states, we will examine the 4 possibilities in the following equations:\n", 225 | "\n", 226 | "\\begin{align}\n", 227 | " \\textrm{When} \\: |\\psi\\phi\\rangle=|00\\rangle \\textrm{, } |\\omega\\rangle&=\\cos{\\frac{\\pi}{8}}|0\\rangle - \\sin{\\frac{\\pi}{8}}|1\\rangle \\\\\n", 228 | " \\textrm{When} \\: |\\psi\\phi\\rangle=|01\\rangle \\textrm{, } |\\omega\\rangle&=-\\sin{\\frac{\\pi}{8}}|0\\rangle + \\cos{\\frac{\\pi}{8}}|1\\rangle \\\\\n", 229 | " \\textrm{When} \\: |\\psi\\phi\\rangle=|10\\rangle \\textrm{, } |\\omega\\rangle&=\\cos{\\frac{\\pi}{8}}|0\\rangle + \\sin{\\frac{\\pi}{8}}|1\\rangle \\\\\n", 230 | " \\textrm{When} \\: |\\psi\\phi\\rangle=|11\\rangle \\textrm{, } |\\omega\\rangle&=\\sin{\\frac{\\pi}{8}}|0\\rangle + \\cos{\\frac{\\pi}{8}}|1\\rangle\n", 231 | "\\end{align}\n", 232 | "\n", 233 | "Now, as you can see in the circuit, we are going to send $|\\omega\\rangle$ through some gates depending on the measurements we made. We are going to apply a Pauli-X gate if $|\\phi\\rangle = |1\\rangle$, followed by a Pauli-Z gate if $|\\psi\\rangle=|1\\rangle$. After applying this conditional gates, $|\\omega\\rangle$ should be in the state of $|\\psi\\rangle$ showed in \\eqref{eq:prepare_send_state}, meaning that the teleportation was completed successfully. Let's see what happens exactly in each case, we will start with the case in which $|\\psi\\phi\\rangle=|00\\rangle$. Well, in this case no further gate is applied, we just have the following state.\n", 234 | "\n", 235 | "\\begin{equation} \\label{eq:first_case}\n", 236 | " |\\omega\\rangle = \\cos{\\frac{\\pi}{8}}|0\\rangle - \\sin{\\frac{\\pi}{8}}|1\\rangle \\tag{5}\n", 237 | "\\end{equation}\n", 238 | "\n", 239 | "Now, let's look at what happens when $|\\psi\\phi\\rangle=|01\\rangle$. We will only apply a Pauli-X gate. \n", 240 | "\n", 241 | "\\begin{align} \\label{eq:second_case}\n", 242 | " |\\omega\\rangle=-\\sin{\\frac{\\pi}{8}}|0\\rangle + \\cos{\\frac{\\pi}{8}}|1\\rangle \\Xto{} \\cos{\\frac{\\pi}{8}}|0\\rangle - \\sin{\\frac{\\pi}{8}}|1\\rangle \\tag{6}\n", 243 | "\\end{align}\n", 244 | "\n", 245 | "Now, we look at the case where $|\\psi\\phi\\rangle=|10\\rangle$. In this case, we only apply a Pauli-Z gate. \n", 246 | "\n", 247 | "\\begin{align} \\label{eq:third_case}\n", 248 | " |\\omega\\rangle=\\cos{\\frac{\\pi}{8}}|0\\rangle + \\sin{\\frac{\\pi}{8}}|1\\rangle \\Zto{} \\cos{\\frac{\\pi}{8}}|0\\rangle - \\sin{\\frac{\\pi}{8}}|1\\rangle \\tag{7}\n", 249 | "\\end{align}\n", 250 | "\n", 251 | "Finally, we look at what happens when $|\\psi\\phi\\rangle=|11\\rangle$. This time, we apply a Pauli-X gate followed by a Pauli-Z gate.\n", 252 | "\n", 253 | "\\begin{align} \n", 254 | " |\\omega\\rangle=\\sin{\\frac{\\pi}{8}}|0\\rangle + \\cos{\\frac{\\pi}{8}}|1\\rangle &\\Xto{} \\cos{\\frac{\\pi}{8}}|0\\rangle + \\sin{\\frac{\\pi}{8}}|1\\rangle \\\\\n", 255 | " &\\Zto{} \\cos{\\frac{\\pi}{8}}|0\\rangle - \\sin{\\frac{\\pi}{8}}|1\\rangle \\label{eq:fourth_case} \\tag{8}\n", 256 | "\\end{align}\n", 257 | "\n", 258 | "At this point, the quantum teleportation protocol is over. $|\\omega\\rangle$ is in the state we showed on \\eqref{eq:prepare_send_state}, meaning that we successfully sent the state from $|\\psi\\rangle$ into $|\\omega\\rangle$. To achieve this, we needed to send two bits of information through classical channels, which allowed us to perform the controlled operations showed in \\eqref{eq:first_case}, \\eqref{eq:second_case}, \\eqref{eq:third_case}, and \\eqref{eq:fourth_case}. It is common to think that this use of classical channels throws away the whole purpose of teleporting a quantum state, but it really doesn't. This classical communication is really the only way of ensuring that we teleport the state successfully; if we didn't apply this step, we would be stuck with one of the four possibilities shown above without the person that has $|\\omega\\rangle$ having a clue about what $|\\psi\\phi\\rangle$ is, therefore this person would only have the intended state $1/4$ of the time.\n", 259 | "\n", 260 | "In the circuit shown earlier in this notebook, we apply some additional gates to $|\\omega\\rangle$. This is just a way to ensure that the teleportation protocol was successful when running in IBM's quantum computers. As you can see, this gates are the same that were applied to the state $|\\psi\\rangle$ when preparing it, but backwards (which turns out to be the same in this case). As you may know, quantum computation is reversible, so performing this operations will turn $|\\omega\\rangle$ back to the state $|0\\rangle$ (we are applying the operations shown in \\eqref{eq:prepare_send_state} but in reverse). This makes it easier to measure if the protocol was successful since the computer will measure $|\\omega\\rangle$ to be $|0\\rangle$ with certainty (without taking into account noise of actual quantum hardware). " 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": 7, 266 | "id": "boolean-strip", 267 | "metadata": {}, 268 | "outputs": [ 269 | { 270 | "data": { 271 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAc0AAAFLCAYAAAC0rNfYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAAsTAAALEwEAmpwYAAAkSklEQVR4nO3de5hddX3v8fc3BII0oYRgArlgiGhqEpMQBpEaklSu0h70KIKVliIWTFGsFyKnT9GnaLV4pCjVIi1wDgIK3k5r0CKoSC6YgpPYQAgSMBcJlwABSoKSZML3/LH2xMkwQ9ZOZmavmf1+PU8e9v6t3175Ln7Z85l1+63ITCRJ0q4NanQBkiT1F4amJEklGZqSJJVkaEqSVJKhKUlSSYamJEklDW50AY100EEH5fjx4xtdhiSpQpYuXfp0Zr66q2VNHZrjx4+ntbW10WVIkiokItZ1t8zDs5IklWRoSpJUkqEpSVJJhqYkSSUZmpIklWRoSpJUkqEpSVJJhqYkSSUZmpIklWRoSpJUkqEpSVJJhqYkSSUZmpIklWRoSpJUkqEpSVJJhqYkSSUZmpIklWRoSpJUkqEpSVJJhqYkSSUZmpIklWRoSpJUkqEpqdJ++MMfMnHiRA4//HAuvfTSly2//PLLmTRpElOnTuW4445j3bp1O5b9+te/5sQTT+QNb3gDkyZNYu3atQCceeaZTJw4kSlTpnDOOeewbdu2vtoc9XOGpqTK2r59Ox/84Ae59dZbWblyJTfddBMrV67cqc8RRxxBa2sr9957L6eddhqf+MQndiw766yzmDdvHg888AD33HMPI0eOBIrQ/OUvf8l9993Hb3/7W6655po+3S71X4ampMq65557OPzww5kwYQL77LMP73nPe/je9763U58/+qM/Yr/99gPgzW9+M+vXrwdg5cqVtLW1ccIJJwAwdOjQHf1OOeUUIoKI4E1vetOOz6ic3tj7X7NmDUcffTSHH344Z5xxBlu3bu2rzamLoSmpsh599FHGjRu34/3YsWN59NFHu+1/7bXX8ra3vQ2AVatWccABB/DOd76TI444gnnz5rF9+/ad+m/bto0bbriBk08+uXc2YADqrb3/iy66iI9+9KM8/PDDDB8+nGuvvbZPt6ssQ1PSgHDjjTfS2trKvHnzAGhra2PRokVcdtll/PznP2f16tVcd911O33m/PPPZ9asWRx77LENqLh/6o29/8zkjjvu4LTTTgPgL/7iL/j3f//3vtuoOhiakiprzJgxPPLIIzver1+/njFjxrys349//GM++9nPMn/+fIYMGQIUe6XTp09nwoQJDB48mHe84x0sW7Zsx2cuueQSnnrqKS6//PLe35ABpDf2/jdu3MgBBxzA4MGDS62zkQxNSZV11FFH8dBDD7FmzRq2bt3KzTffzKmnnrpTn1/84hd84AMfYP78+TsO9bV/9rnnnuOpp54C4I477mDSpEkAXHPNNdx2223cdNNNDBrkj8Hesjt7/1XnvxZJlTV48GC+8pWvcNJJJ/GGN7yB008/ncmTJ/OpT32K+fPnAzBv3jw2b97Mu9/9bqZPn74jVPfaay8uu+wyjjvuON74xjeSmZx77rkAzJ07lw0bNnDMMccwffp0Pv3pTzdsG/ub3tj7HzFiBM899xxtbW2vuM5KyMym/XPkkUemJKm8bdu25WGHHZarV6/OLVu25NSpU3PFihU79Vm2bFlOmDAhV61atVN7W1tbTp06NZ988snMzDz77LPzK1/5SmZmnnbaaXnTTTdlZuYHPvCB/Od//uc+2JquAa3ZTW64pylJKq239v4///nPc/nll3P44YezceNG3v/+9zdsG19JFKHanFpaWrK1tbXRZUiSKiQilmZmS1fL3NOUJKkkQ1OSpJIMTUmSSjI0JUkqydCUJKkkQ1OSpJIMTalmTx53BPD8888zduxYPvShD+1oO/nkk5k2bRqTJ09m7ty5L3vKhqT+xdCU2PPHHQF88pOfZNasWTu1fetb32L58uWsWLGCp556im9/+9u9vi2Seo+hKbFnjzsCWLp0KRs2bODEE0/c6TP7778/UExUvXXrViKil7dEUm8yNCX27HFHL730Eh//+Me57LLLuux70kknMXLkSIYNG7bjeYGS+qfBjS5A6m/aH3e0YMECAK688kpOOeUUxo4d22X/2267jRdffJEzzzyTO+64Y8cDeJvRuV9qdAU95+qPNLoCNYKhKVH/444WLFiw43FHS5YsYdGiRVx55ZVs3ryZrVu3MnTo0J0uJtp33315+9vfzve+972mDk2pvzM0JXZ+2PGYMWO4+eab+cY3vrFTn/aHHf/whz/c6WHHX//613e8vu6662htbeXSSy9l8+bNbNq0iUMOOYS2tjZ+8IMfcOyxx/bZ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\n", 272 | "text/plain": [ 273 | "
░ ┌───┐┌─────────┐┌───┐ ░ ┌───┐ ░ »\n", 317 | " q_sender: ───────────░──|0>─┤ H ├┤ Rz(π/4) ├┤ H ├─░───■──┤ H ├─░───────■─»\n", 318 | " ┌───┐ ░ └───┘└─────────┘└───┘ ░ ┌─┴─┐└───┘ ░ │ »\n", 319 | " q_ancillary: ┤ H ├──■───░────────────────────────────░─┤ X ├──────░───■───┼─»\n", 320 | " └───┘┌─┴─┐ ░ ░ └───┘ ░ ┌─┴─┐ │ »\n", 321 | " q_receiver: ─────┤ X ├─░────────────────────────────░────────────░─┤ X ├─■─»\n", 322 | " └───┘ ░ ░ ░ └───┘ »\n", 323 | "c_receiver: 1/═══════════════════════════════════════════════════════════════»\n", 324 | " »\n", 325 | "« ░ \n", 326 | "« q_sender: ─░──────────────────────────\n", 327 | "« ░ \n", 328 | "« q_ancillary: ─░──────────────────────────\n", 329 | "« ░ ┌───┐┌──────────┐┌───┐┌─┐\n", 330 | "« q_receiver: ─░─┤ H ├┤ Rz(-π/4) ├┤ H ├┤M├\n", 331 | "« ░ └───┘└──────────┘└───┘└╥┘\n", 332 | "«c_receiver: 1/══════════════════════════╩═\n", 333 | "« 0" 334 | ], 335 | "text/plain": [ 336 | " ░ ┌───┐┌─────────┐┌───┐ ░ ┌───┐ ░ »\n", 337 | " q_sender: ───────────░──|0>─┤ H ├┤ Rz(π/4) ├┤ H ├─░───■──┤ H ├─░───────■─»\n", 338 | " ┌───┐ ░ └───┘└─────────┘└───┘ ░ ┌─┴─┐└───┘ ░ │ »\n", 339 | " q_ancillary: ┤ H ├──■───░────────────────────────────░─┤ X ├──────░───■───┼─»\n", 340 | " └───┘┌─┴─┐ ░ ░ └───┘ ░ ┌─┴─┐ │ »\n", 341 | " q_receiver: ─────┤ X ├─░────────────────────────────░────────────░─┤ X ├─■─»\n", 342 | " └───┘ ░ ░ ░ └───┘ »\n", 343 | "c_receiver: 1/═══════════════════════════════════════════════════════════════»\n", 344 | " »\n", 345 | "« ░ \n", 346 | "« q_sender: ─░──────────────────────────\n", 347 | "« ░ \n", 348 | "« q_ancillary: ─░──────────────────────────\n", 349 | "« ░ ┌───┐┌──────────┐┌───┐┌─┐\n", 350 | "« q_receiver: ─░─┤ H ├┤ Rz(-π/4) ├┤ H ├┤M├\n", 351 | "« ░ └───┘└──────────┘└───┘└╥┘\n", 352 | "«c_receiver: 1/══════════════════════════╩═\n", 353 | "« 0 " 354 | ] 355 | }, 356 | "execution_count": 5, 357 | "metadata": {}, 358 | "output_type": "execute_result" 359 | } 360 | ], 361 | "source": [ 362 | "h_circ = teleportation(hardware = True)\n", 363 | "h_circ.draw()" 364 | ] 365 | }, 366 | { 367 | "cell_type": "markdown", 368 | "id": "dangerous-choir", 369 | "metadata": {}, 370 | "source": [ 371 | "As you can see, the gates that changed are the ones that were conditioned in a classical bit. This types of gates are not available currently in IBM's computers, so we need to change them in order to run the circuit on them. It's quite easy to overcome this difficulty, since we can condition the gates with the corresponding qubits (this time without measuring) and we will get the same result. However, we lose the advantage that we haved where the only connection between the sender and the receiver was at the beggining to split the entangled qubits and afterwards through classical channels. Now, the whole quantum circuit has to be connected. Read more about this [here](https://qiskit.org/textbook/ch-algorithms/teleportation.html#5.-Teleportation-on-a-Real-Quantum-Computer-)." 372 | ] 373 | } 374 | ], 375 | "metadata": { 376 | "kernelspec": { 377 | "display_name": "Python 3 (ipykernel)", 378 | "language": "python", 379 | "name": "python3" 380 | }, 381 | "language_info": { 382 | "codemirror_mode": { 383 | "name": "ipython", 384 | "version": 3 385 | }, 386 | "file_extension": ".py", 387 | "mimetype": "text/x-python", 388 | "name": "python", 389 | "nbconvert_exporter": "python", 390 | "pygments_lexer": "ipython3", 391 | "version": "3.10.6" 392 | } 393 | }, 394 | "nbformat": 4, 395 | "nbformat_minor": 5 396 | } 397 | -------------------------------------------------------------------------------- /challenges/IBM 2021/ex2/solution.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "devoted-techno", 6 | "metadata": {}, 7 | "source": [ 8 | "# Exercise 2 - Shor's algorithm\n", 9 | "This notebook contains my solution to exercise 2 of the IBM Quantum Challenge 2021. My solution is pretty simple and has a total cost of 6. My name is Emilio Peláez and my GitHub profile is [@epelaaez](https://github.com/epelaaez) if you want to check it out!" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "id": "contemporary-shell", 15 | "metadata": {}, 16 | "source": [ 17 | "### Imports\n", 18 | "The next cell imports everything needed for this notebook." 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 13, 24 | "id": "delayed-brother", 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "from qiskit import QuantumRegister, QuantumCircuit, transpile\n", 29 | "import numpy as np" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "id": "grand-tobago", 35 | "metadata": {}, 36 | "source": [ 37 | "### Solution\n", 38 | "The first circuit we had to composed needed to perform the following transformation:\n", 39 | "\n", 40 | "$$\n", 41 | "\\begin{aligned}\n", 42 | "U|00\\rangle &= |01\\rangle \\\\\n", 43 | "U|01\\rangle &= |10\\rangle \\\\\n", 44 | "U|10\\rangle &= |11\\rangle \\\\\n", 45 | "U|11\\rangle &= |00\\rangle \\\\\n", 46 | "\\end{aligned}\n", 47 | "$$\n", 48 | "\n", 49 | "And remember that the $U$ matrix is controlled by another qubit. Thus, the control qubit below dictates if the transformation $U$ is applied to the two target qubits. It can be seen righ away that these can be done with two controlled operations. First, we see that $U$ flips the second target qubit if the first target qubit is in the 1 state. To perform this, we use a Toffoli gate with the control qubit and first target qubit as control and the second target qubit as target. The reason to do this is that we want to activate $U$ if and only if the control qubit is in state 1, thus the extra control. Then, we see that the first target qubit is always flipped, we do this using a CNOT gate. We do this last to not mess up the first control operation." 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 4, 55 | "id": "competent-majority", 56 | "metadata": {}, 57 | "outputs": [ 58 | { 59 | "data": { 60 | "image/png": "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\n", 61 | "text/plain": [ 62 | "