diff --git a/doc/index.rst b/doc/index.rst index 2161c483..67a10827 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -21,6 +21,7 @@ PyZX :caption: Notebooks: notebooks/gettingstarted + notebooks/qasm Indices and tables ================== diff --git a/doc/notebooks/gettingstarted.ipynb b/doc/notebooks/gettingstarted.ipynb index 71d639be..e9aed34e 100644 --- a/doc/notebooks/gettingstarted.ipynb +++ b/doc/notebooks/gettingstarted.ipynb @@ -15,7 +15,7 @@ "metadata": {}, "outputs": [], "source": [ - "import sys; sys.path.insert(0, '..') # So that we import the local copy of pyzx if you have installed from Github\n", + "import sys; sys.path.insert(0, '../..') # So that we import the local copy of pyzx if you have installed from Github\n", "import random\n", "import pyzx as zx" ] diff --git a/doc/notebooks/qasm.ipynb b/doc/notebooks/qasm.ipynb new file mode 100644 index 00000000..b4bac0a0 --- /dev/null +++ b/doc/notebooks/qasm.ipynb @@ -0,0 +1,311 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "9ab292bf", + "metadata": { + "nbsphinx": "hidden" + }, + "outputs": [], + "source": [ + "import sys; sys.path.insert(0, '../..') # So that we import the local copy of pyzx if you have installed from Github" + ] + }, + { + "cell_type": "markdown", + "id": "2b28a205", + "metadata": {}, + "source": [ + "# Supported OpenQASM Gates\n", + "\n", + "The pyzx library supports a subset of the OpenQASM format.\n", + "\n", + "Here are some examples illustrating the usage:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7cd93df8", + "metadata": {}, + "outputs": [], + "source": [ + "import pyzx as zx\n", + "from pyzx.circuit import Circuit\n", + "\n", + "s = \"\"\"\n", + "OPENQASM 2.0;\n", + "include \"qelib1.inc\";\n", + "qreg q[1];\n", + "z q[0];\n", + "\"\"\"\n", + "\n", + "c1 = zx.qasm(s)\n", + "c2 = Circuit.from_qasm(s) # or: Circuit.from_qasm_file(\"filename.qasm\")\n", + "\n", + "print(c2.to_qasm())" + ] + }, + { + "cell_type": "markdown", + "id": "4fb99b07", + "metadata": {}, + "source": [ + "The set of supported OpenQASM gates are listed below for reference, using the following function to draw their graphs. (Set `simplify` to `True` to reduce the graphs, and set `show_matrix` to `True` to output their matrices.)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "084548de", + "metadata": {}, + "outputs": [], + "source": [ + "from pyzx.circuit.qasmparser import QASMParser\n", + "\n", + "def draw_qasm_circuit(num_qubits, qasm, simplify=False, show_matrix=False):\n", + " print(qasm)\n", + " g = QASMParser().parse(f\"qreg q[{num_qubits}];\\n\" + qasm, strict=False).to_graph()\n", + " if simplify:\n", + " g.auto_detect_io()\n", + " zx.simplify.full_reduce(g)\n", + " zx.draw(g)\n", + " if show_matrix:\n", + " print(g.to_matrix())" + ] + }, + { + "cell_type": "markdown", + "id": "b9a641a1", + "metadata": {}, + "source": [ + "## One-qubit gates\n", + "\n", + "### Pauli gates and Hadamard" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91d88893", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(1, 'x q;')\n", + "draw_qasm_circuit(1, 'y q;')\n", + "draw_qasm_circuit(1, 'z q;')\n", + "draw_qasm_circuit(1, 'h q;')" + ] + }, + { + "cell_type": "markdown", + "id": "4d8dba52", + "metadata": {}, + "source": [ + "### Parametrized one-qubit gates\n", + "\n", + "These are shown with a phase of π/8 for illustrative purposes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ea662a9", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(1, 'rx(0.125*pi) q;')\n", + "draw_qasm_circuit(1, 'ry(0.125*pi) q;')\n", + "draw_qasm_circuit(1, 'rz(0.125*pi) q;') # can also use 'p' or 'u1'\n", + "\n", + "draw_qasm_circuit(1, 'u2(0.125*pi,0.125*pi) q[0];')\n", + "draw_qasm_circuit(1, 'u3(0.125*pi,0.125*pi,0.125*pi) q[0];')" + ] + }, + { + "cell_type": "markdown", + "id": "38f1e292", + "metadata": {}, + "source": [ + "### Fixed Z- and X- rotations defined for convenience" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "175fd12c", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(1, 's q;')\n", + "draw_qasm_circuit(1, 'sdg q;')\n", + "draw_qasm_circuit(1, 't q;')\n", + "draw_qasm_circuit(1, 'tdg q;')\n", + "draw_qasm_circuit(1, 'sx q;')\n", + "draw_qasm_circuit(1, 'sxdg q;')" + ] + }, + { + "cell_type": "markdown", + "id": "a206e2f0", + "metadata": {}, + "source": [ + "## Two-qubit gates" + ] + }, + { + "cell_type": "markdown", + "id": "b4788808", + "metadata": {}, + "source": [ + "### Swap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ca9ce1dd", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(2, 'swap q[0], q[1];')" + ] + }, + { + "cell_type": "markdown", + "id": "5ec55ec8", + "metadata": {}, + "source": [ + "### Two-qubit rotations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aa10bd37", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(2, 'rxx(0.125*pi) q[0], q[1];')\n", + "draw_qasm_circuit(2, 'rzz(0.125*pi) q[0], q[1];')" + ] + }, + { + "cell_type": "markdown", + "id": "41366a55", + "metadata": {}, + "source": [ + "### Controlled versions of (non-parametrized) one-qubit gates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3136424", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(2, 'cx q[0], q[1];')\n", + "draw_qasm_circuit(2, 'cy q[0], q[1];')\n", + "draw_qasm_circuit(2, 'cz q[0], q[1];')\n", + "draw_qasm_circuit(2, 'ch q[0], q[1];')\n", + "draw_qasm_circuit(2, 'csx q[0], q[1];')" + ] + }, + { + "cell_type": "markdown", + "id": "74fa6d83", + "metadata": {}, + "source": [ + "### Controlled versions of parametrized one-qubit gates\n", + "\n", + "These are shown with a phase of π/8 for illustrative purposes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e4eb34ab", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(2, 'crx(0.125*pi) q[0], q[1];')\n", + "draw_qasm_circuit(2, 'cry(0.125*pi) q[0], q[1];')\n", + "draw_qasm_circuit(2, 'crz(0.125*pi) q[0], q[1];')\n", + "\n", + "# Note that this differs from 'crz' by a relative phase.\n", + "draw_qasm_circuit(2, 'cp(0.125*pi) q[0], q[1];') # can also use 'cphase' or 'cu1'\n", + "\n", + "draw_qasm_circuit(2, 'cu3(0.125*pi,0.125*pi,0.125*pi) q[0], q[1];')\n", + "draw_qasm_circuit(2, 'cu(0.125*pi,0.125*pi,0.125*pi,0.125*pi) q[0], q[1];')" + ] + }, + { + "cell_type": "markdown", + "id": "b1a96dca", + "metadata": {}, + "source": [ + "## Three-qubit gates" + ] + }, + { + "cell_type": "markdown", + "id": "514830c5", + "metadata": {}, + "source": [ + "### Controlled versions of two-qubit gates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63d0996c", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(3, 'cswap q[0], q[1], q[2];') # Fredkin" + ] + }, + { + "cell_type": "markdown", + "id": "8521a36e", + "metadata": {}, + "source": [ + "### Doubly-controlled one-qubit gates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90a9ec61", + "metadata": {}, + "outputs": [], + "source": [ + "draw_qasm_circuit(3, 'ccx q[0], q[1], q[2];') # Toffoli\n", + "draw_qasm_circuit(3, 'ccz q[0], q[1], q[2];')" + ] + } + ], + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/representations.rst b/doc/representations.rst index c6ca53fb..9f12ba70 100644 --- a/doc/representations.rst +++ b/doc/representations.rst @@ -21,7 +21,7 @@ The currently supported formats are To convert a PyZX circuit to these formats, use :meth:`~pyzx.circuit.Circuit.to_qasm`, :meth:`~pyzx.circuit.Circuit.to_quipper`, :meth:`~pyzx.circuit.Circuit.to_qc`. -PyZX also offers a convenience function to construct a circuit out of a string containing QASM code using either :meth:`~pyzx.circuit.Circuit.from_qasm` or :func:`~pyzx.circuit.qasmparser.qasm`. +PyZX also offers a convenience function to construct a circuit out of a string containing QASM code using either :meth:`~pyzx.circuit.Circuit.from_qasm` or :func:`~pyzx.circuit.qasmparser.qasm`. See the `Supported OpenQASM Gates notebook `_ for more details. To convert a Circuit into a PyZX Graph (i.e. a ZX-diagram), call the method :meth:`~pyzx.circuit.Circuit.to_graph`. @@ -38,4 +38,4 @@ Additionally, PyZX diagrams can be directly exported into the applications `Tikz Finally, to display a ZX-diagram in Jupyter call :func:`~pyzx.drawing.draw` and to create a matplotlib picture of the ZX-diagram use :func:`~pyzx.drawing.draw_matplotlib`. -Some ZX-diagrams can be converted into an equivalent circuit. For complicated ZX-diagrams, the function :func:`~pyzx.extract.extract_circuit` is supplied. For ZX-diagrams that come directly from Circuits, e.g. those produced by calling ``c.to_graph`` for a Circuit ``c``, one can also use the static method :meth:`~pyzx.circuit.Circuit.from_graph`, which is more lightweight. \ No newline at end of file +Some ZX-diagrams can be converted into an equivalent circuit. For complicated ZX-diagrams, the function :func:`~pyzx.extract.extract_circuit` is supplied. For ZX-diagrams that come directly from Circuits, e.g. those produced by calling ``c.to_graph`` for a Circuit ``c``, one can also use the static method :meth:`~pyzx.circuit.Circuit.from_graph`, which is more lightweight.