From d68830a95311c31150c4c01c43b993494713d44f Mon Sep 17 00:00:00 2001 From: Wong Zi Cheng <70616433+chmwzc@users.noreply.github.com> Date: Fri, 29 Nov 2024 06:38:49 +0000 Subject: [PATCH] Upload some rough QM and linear algebra notes Written for a JC student to (hopefully) get a basic idea of quantum mechanics and computing --- tutorials/qibo-demonstration.ipynb | 463 +++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 tutorials/qibo-demonstration.ipynb diff --git a/tutorials/qibo-demonstration.ipynb b/tutorials/qibo-demonstration.ipynb new file mode 100644 index 0000000..cad9dd5 --- /dev/null +++ b/tutorials/qibo-demonstration.ipynb @@ -0,0 +1,463 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "d882888a-e00d-4489-9eb8-fdadb2d2a792", + "metadata": {}, + "outputs": [], + "source": [ + "import qibo\n", + "from qibo import gates, Circuit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28a1977b-68b0-4e28-bd43-eac0174a9547", + "metadata": {}, + "outputs": [], + "source": [ + "qibo.set_backend(\"numpy\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ec45559-cfbd-4e38-8254-f0d8c8808258", + "metadata": {}, + "outputs": [], + "source": [ + "circuit = Circuit(4)\n", + "circuit.add(gates.X(0))\n", + "circuit.add(gates.CNOT(0, 1))\n", + "\n", + "circuit.draw()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "910e3cca-444b-46f4-9372-997a7bc80eeb", + "metadata": {}, + "outputs": [], + "source": [ + "from qibo.hamiltonians import SymbolicHamiltonian\n", + "from qibo.symbols import I, X, Y, Z" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f9e18bb-26a6-4e4e-b462-e401747b322e", + "metadata": {}, + "outputs": [], + "source": [ + "some_term = Y(0)*Z(1)*Y(2)*Z(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65e8c38f-5702-4696-8188-641ab655b99e", + "metadata": {}, + "outputs": [], + "source": [ + "some_hamiltonian = SymbolicHamiltonian(some_term)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad5c8715-5cb8-492a-ad34-c8743f813f6a", + "metadata": {}, + "outputs": [], + "source": [ + "from qibochem.measurement import expectation, expectation_from_samples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26dcd980-25c5-4f48-89f3-b4a92c9db24c", + "metadata": {}, + "outputs": [], + "source": [ + "result = expectation(circuit, some_hamiltonian)\n", + "result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b6ab5d5-a64e-463f-98e4-f6857faede5c", + "metadata": {}, + "outputs": [], + "source": [ + "z0_ham = SymbolicHamiltonian(Z(0)*I(3))\n", + "\n", + "z0_exp = expectation(circuit, z0_ham)\n", + "z0_exp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce7b5437-6960-4fdb-9a53-39f098423ac0", + "metadata": {}, + "outputs": [], + "source": [ + "x0_ham = SymbolicHamiltonian(X(0)*I(3))\n", + "\n", + "x0_exp = expectation(circuit, x0_ham)\n", + "x0_exp" + ] + }, + { + "cell_type": "markdown", + "id": "373d0cd6-1079-48c9-93ba-39a4ec54a434", + "metadata": {}, + "source": [ + "## State vector of a qubit\n", + "\n", + "The actual state vector of a single qubit (formally, the wave function for the system) can be given by a column vector, e.g. \n", + "\n", + "$$\n", + "\\begin{pmatrix}\n", + "1 \\\\ 0\n", + "\\end{pmatrix}\n", + "$$\n", + "\n", + "The state vector for multiple qubits can be found by taking the tensor product ($\\otimes$) of the individual vectors:\n", + "\n", + "$$\n", + "\\begin{pmatrix}\n", + "1 \\\\ 0\n", + "\\end{pmatrix}\n", + "\\otimes\n", + "\\begin{pmatrix}\n", + "1 \\\\ 0\n", + "\\end{pmatrix}\n", + "=\n", + "\\begin{pmatrix}\n", + "1 * \\begin{pmatrix}\n", + "1 \\\\ 0\n", + "\\end{pmatrix} \\\\\n", + "0 * \\begin{pmatrix}\n", + "1 \\\\ 0\n", + "\\end{pmatrix}\n", + "\\end{pmatrix}\n", + "= \n", + "\\begin{pmatrix}\n", + "1 \\\\ 0 \\\\ 0 \\\\0\n", + "\\end{pmatrix}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "8a2e0f6c-ce7d-4355-a0db-e932edb84b71", + "metadata": {}, + "source": [ + "## Bra-ket or Dirac notation\n", + "\n", + "Bra-ket notation is a simpler form to denote the state vector of the system; \"bra\" refers to a row vector, and \"ket\" is a column vector.\n", + "\n", + "An example for a 1-qubit system:\n", + "$$\n", + "\\text{bra: }\n", + "\\langle 0 \\rvert =\n", + "\\begin{pmatrix}\n", + "1 & 0\n", + "\\end{pmatrix}\n", + "\\text{, and ket: }\n", + "\\lvert 0 \\rangle =\n", + "\\begin{pmatrix}\n", + "1 \\\\ 0\n", + "\\end{pmatrix}\n", + "$$\n", + "\n", + "and\n", + "\n", + "$$\n", + "\\text{bra: }\n", + "\\langle 1 \\rvert =\n", + "\\begin{pmatrix}\n", + "0 & 1\n", + "\\end{pmatrix}\n", + "\\text{, and ket: }\n", + "\\lvert 1 \\rangle =\n", + "\\begin{pmatrix}\n", + "0 \\\\ 1\n", + "\\end{pmatrix}\n", + "$$\n", + "\n", + "Same thing for multiple qubits:\n", + "\n", + "$$\n", + "\\lvert 01 \\rangle =\n", + "\\lvert 0 \\rangle \\otimes \\lvert 1 \\rangle =\n", + "\\begin{pmatrix}\n", + "0 \\\\ 1 \\\\ 0 \\\\ 0\n", + "\\end{pmatrix}\n", + "$$\n", + "\n", + "Another way of seeing it is, the binary string (\"01\") in the ket refers to which row is 1 in the column matrix.\n", + "\n", + "E.g. converting \"11\" from binary to decimal gives $1*2^{1} + 1*2^{0} = 3$, so the row 3 is 1 in $\\lvert 11 \\rangle$.\n", + "(Python indexing starts from 0, so row 3 is the last row in our 4 by 1 column vector.)" + ] + }, + { + "cell_type": "markdown", + "id": "af7ad6c7-af7a-407c-8870-090533f87dc0", + "metadata": {}, + "source": [ + "# Some linear algebra\n", + "\n", + "In general, the state vector can be written as a linear combination of $\\lvert 0 \\rangle$ and $\\lvert 1 \\rangle$ (basis functions):\n", + "\n", + "$$\n", + "\\text{General state vector, }\n", + "\\lvert \\Psi \\rangle\n", + "=\n", + "\\begin{pmatrix}\n", + "a \\\\ b\n", + "\\end{pmatrix}\n", + "=\n", + "a\\begin{pmatrix}\n", + "1 \\\\ 0\n", + "\\end{pmatrix}\n", + "+\n", + "b\\begin{pmatrix}\n", + "0 \\\\ 1\n", + "\\end{pmatrix}\n", + "=\n", + "a \\lvert 0 \\rangle + b\\lvert 1 \\rangle\n", + "$$\n", + "\n", + "where $a$ and $b$ are some real numbers\n", + "\n", + "## Applying it to quantum measurements\n", + "\n", + "A basic [rule](https://en.wikipedia.org/wiki/Born_rule) of quantum mechanics is $a^{2} + b^{2} = 1$.\n", + "The squared coefficients of each basis function is the probability of obtaining that particular measurement.\n", + "\n", + "E.g. for the $Z$ term, if our qubit is in the state $\\lvert 0 \\rangle$, we will get $+1$ when we measure $Z$, and $-1$ if it is in the state $\\lvert 1 \\rangle$.\n", + "\n", + "For the general case $\\Psi = a \\lvert 0 \\rangle + b\\lvert 1 \\rangle$, the mean (formally, the expectation) value of $Z$ will be $(1*a^{2} + (-1)*b^{2}) = a^{2} - b^{2}$\n", + "\n", + "If we don't know the exact coefficients $a$ and $b$. we have to take a number of measurements for $Z$ separately, giving us something like: `sample_result = [+1, -1, +1, +1, ..., +1]`.\n", + "Ideally, the mean value of `sample_result` will be close to the exact value of $a^{2} - b^{2}$ as we obtain more and more measurements." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af9e7d42-05f8-47fe-85d1-f71a53712c8a", + "metadata": {}, + "outputs": [], + "source": [ + "circuit = Circuit(1)\n", + "circuit.add(gates.RX(0, 0.3))\n", + "\n", + "circuit.draw()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14d00b65-2773-4587-9b07-0630142e43b4", + "metadata": {}, + "outputs": [], + "source": [ + "z0_ham2 = SymbolicHamiltonian(Z(0))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f65673d-6ec2-46df-85b0-af9d923e3bd5", + "metadata": {}, + "outputs": [], + "source": [ + "expectation_from_samples(circuit, z0_ham2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7d4ed41-ed2b-46cd-aa69-52c827ddc82b", + "metadata": {}, + "outputs": [], + "source": [ + "expectation(circuit, z0_ham2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b34a6bcd-c642-4df7-a0b4-c85e3f7fe89c", + "metadata": {}, + "outputs": [], + "source": [ + "expectation_from_samples(circuit, z0_ham2, n_shots=1000000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e95d2ecf-1208-4811-9610-fcfae62592a0", + "metadata": {}, + "outputs": [], + "source": [ + "hamiltonian = SymbolicHamiltonian(0.5*X(0)*X(1) + 5*Y(0)*Y(1) + 25*Z(0)*Z(1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c6ac04b-9c8b-4936-9f53-c4d1c3d6aad0", + "metadata": {}, + "outputs": [], + "source": [ + "circuit = Circuit(2)\n", + "circuit.add(gates.RX(_i, 0.3) for _i in range(2))\n", + "\n", + "circuit.draw()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f1319c1a-beb1-4304-ab98-c67094afed37", + "metadata": {}, + "outputs": [], + "source": [ + "expectation(circuit, hamiltonian)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91b42e80-b468-4bbc-b026-8e0eb59d578c", + "metadata": {}, + "outputs": [], + "source": [ + "expectation_from_samples(circuit, hamiltonian)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bff67196-0557-4d56-abf8-2400da77cfb8", + "metadata": {}, + "outputs": [], + "source": [ + "expectation_from_samples(circuit, hamiltonian, n_shots_per_pauli_term=False, shot_allocation=[10, 100, 100000])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a8b876a-aa2e-4df4-bb21-a53be3c8439d", + "metadata": {}, + "outputs": [], + "source": [ + "x_ham = SymbolicHamiltonian(0.5*X(0)*X(1))\n", + "\n", + "k = 1000\n", + "samples = [expectation_from_samples(circuit, x_ham, n_shots=1) for _ in range(k)]\n", + "samples[:5]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1068694d-ee53-462b-a92a-306d13e734ac", + "metadata": {}, + "outputs": [], + "source": [ + "bell_circuit = circuit.copy()\n", + "bell_circuit.add(gates.CNOT(1, 0))\n", + "bell_circuit.add(gates.H(1))\n", + "\n", + "bell_circuit.draw()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dadd4f59-810e-43fe-a12e-4bbc0e259961", + "metadata": {}, + "outputs": [], + "source": [ + "circuit_result = bell_circuit()\n", + "probabilities = circuit_result.probabilities()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "98c5a415-04e7-4e02-a40d-58b4456ac430", + "metadata": {}, + "outputs": [], + "source": [ + "probabilities" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "240c47a0-e85f-4114-8087-a0deda439d18", + "metadata": {}, + "outputs": [], + "source": [ + "phi_p, phi_m, psi_p, psi_m = probabilities" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0143a8e8-60ba-4dd9-a06a-9217791c38f0", + "metadata": {}, + "outputs": [], + "source": [ + "sigma_xx = 0.5*(phi_p - phi_m + psi_p - psi_m)\n", + "sigma_yy = 5*(-phi_p + phi_m + psi_p - psi_m)\n", + "sigma_zz = 25*(phi_p + phi_m - psi_p - psi_m)\n", + "\n", + "print(sigma_xx + sigma_yy + sigma_zz)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9783fb2e-cd6c-4405-a5c1-0edbc0cf41b2", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}