{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Problem Sheet 3\n", "\n", "_Quantum Processes and Computation 2024_\n", "\n", "\n", "In this problem sheet, we will get the hang of working with the basic generators of circuits and ZX-diagrams concretely, using matrix calculations. For this, we will use the `sympy` library.\n", "\n", "If you haven't done so already, read Section 3.1 in [Picturing Quantum Software](https://github.com/zxcalc/book) to see the basic definitions of spiders and ZX-diagrams." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from sympy import *\n", "from sympy.physics.quantum import TensorProduct\n", "from fractions import Fraction\n", "\n", "def T(*args):\n", " if len(args) == 1: return args[0]\n", " elif len(args) == 0: return Matrix([[1]])\n", " else: return TensorProduct(args[0], T(*args[1:]))\n", "\n", "alpha = var(\"alpha\")\n", "beta = var(\"beta\")\n", "gamma = var(\"gamma\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With this library, we can construct matrices with `Matrix`. Then `*` is matrix multiplication, and `T` is tensor product.\n", "\n", "Note `T` takes any number of arguments, e.g. $A \\otimes B \\otimes C$ is `T(A,B,C)`, and if you want to be fancy: $A^{\\otimes n}$ is `T(*n*[A])`. (Python trivia: Why does that work??)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M = Matrix([[1, 2],\n", " [3, 4]])\n", "\n", "display(M)\n", "display(M * M * M)\n", "display(T(M,M))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also define some variables with `var` which can be used in mathmatical expressions, and substituted via `.subs(...)`. Variable names can be any string, but `sympy` knows how to pretty-print some variable names, e.g. Greek letters.\n", "\n", "NOTE: $\\sqrt{2}$ is `sqrt(2)`, $i$ is `I`, $\\pi$ is `pi`, and $e^x$ is `exp(x)`, so phases $e^{i \\alpha}$ are written `exp(i * alpha)`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "alpha = var(\"alpha\")\n", "phase = exp(I * alpha)\n", "epi4 = exp(I * pi / 4)\n", "\n", "display(alpha)\n", "display(phase)\n", "display(phase.subs(alpha, -pi / 2))\n", "display(phase.subs(alpha, pi / 4) == epi4)\n", "display(re(epi4) + I * im(epi4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That should be enough to get going. If in doubt, [read the docs](https://docs.sympy.org/latest/index.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Question 0\n", "\n", "First some basics. Define matrices for:\n", " * `z0` := $|0\\rangle$, `z1` := $|1\\rangle$, `x0` := $|{+}\\rangle$, `x1` := $|{-}\\rangle$\n", " * `bz0` := $\\langle 0|$, `bz1` := $\\langle 1|$, `bx0` := $\\langle {+}|$, `bx1` := $\\langle {-}|$\n", " * `w` for the 2D identity matrix (\"wire\")\n", " * `swap` for the swap\n", "\n", "Compute various products and tensor products and show the results are sensible." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Question 1\n", "\n", "Define a function that produces the matrix of a Z-spider. It should take 3 arguments: `m` for input legs, `n` for output legs, and `phase` for phase. The phase should have a default value of 0.\n", "\n", "Build this function in (at least) 2 different ways:\n", " 1. by building the $2^n \\times 2^m$ matrix of the spider explicitly (call this function `zs`)\n", " 2. by using sums, compositions, and tensor products of the generators from the previous question\n", "\n", "Test your implementation by comparing the matrices for various choices of inputs, outputs, and phases. (Don't forget to check no-legged spiders!)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Question 2\n", "\n", "Similarly, define a function for X-spiders:\n", "\n", "1. by first defining the Hadamard gate `had` and using `zs` (call this function `xs`)\n", "2. using the generators from Question 0\n", "\n", "Again, check these two definitions agree for various numbers of legs and angles." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Question 3\n", "\n", "* Make an XOR using an X spider and a scalar multiplication, and show it acts like XOR on $\\{|0\\rangle, |1\\rangle\\}$.\n", "* Make a CNOT and TONC (a CNOT with a control on the second qubit and target on the first) using Z spiders, X spiders, swaps, and scalar multiplication. Check that CNOT acts as expected on basis states and `swap * CNOT * swap` is the same as `TONC`\n", "* Check XOR is associative and `CNOT * TONC * CNOT = swap`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Question 4\n", "\n", "Build a 2-qubit parity-phase gate, i.e. a gate that acts as: $|x, y\\rangle \\mapsto e^{i (x \\oplus y) \\alpha} |x, y\\rangle$ in (at least) two ways:\n", "\n", "1. using CNOT gates and a Z phase gate\n", "2. using some Z-spiders and XOR\n", "\n", "Check the two definitions coincide and act correctly on Z basis states." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Question 5\n", "\n", "Define a function that constructs an N-qubit parity phase gate $|x_1 ... x_n\\rangle \\mapsto e^{i (x_1 \\oplus ... \\oplus x_n) \\alpha} |x_1 ... x_n\\rangle$ either concretely or from gates and spiders. Do this however you like, and preferably in multiple ways. Check your answers, and try to come up with cool answers. :)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.12.0" } }, "nbformat": 4, "nbformat_minor": 2 }