Skip to content

Commit

Permalink
Merge pull request #191 from dlyongemallo/document_all_gates
Browse files Browse the repository at this point in the history
Document all support gates in the notebook.
  • Loading branch information
jvdwetering authored Dec 11, 2023
2 parents d3c1af9 + 9bebdab commit c657667
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 48 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
Right now this project is in Beta and does not yet follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
Right now this project is in Beta and does not yet follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
Hence, occasionally changes will be backwards incompatible (although they will all be documented here).

## [0.x.x] - xxxx-xx-xx
Expand All @@ -13,7 +13,8 @@ Hence, occasionally changes will be backwards incompatible (although they will a
- Support for W nodes and Z boxes (courtesy of @RazinShaikh).
- Support for poly phases (courtesy of @RazinShaikh)
- Support for Jupyter notebooks in documentation using nbsphinx (courtesy of @dlyongemallo).
- Support for OpenQASM 3.0; added Jupyter notebook documenting supported qasm gates (courtesy of @dlyongemallo).
- Jupyter notebook documenting all supported gates (courtesy of @dlyongemallo).
- Support for OpenQASM 3.0 (courtesy of @dlyongemallo).
- A function `is_well_formed` to check that a graph is a well-formed ZX-diagram (courtesy of @RazinShaikh).
- A function `is_pauli` to check whether a phase is Pauli (courtesy of @y-richie-y)
- A function `GraphDiff` that calculates what actions are needed to bring one graph to another (used in ZXLive).
Expand Down Expand Up @@ -76,7 +77,7 @@ This release adds several new features: support for evaluating ZX-diagrams as te
There is one small breaking change, which is that `Graph.inputs` and `Graph.outputs` are now methods that return a list, instead of being lists themselves.

### Added
- Added support for evaluating ZX-diagrams as tensor networks in [quimb](https://quimb.readthedocs.io/en/latest/index.html) (courtesy of
- Added support for evaluating ZX-diagrams as tensor networks in [quimb](https://quimb.readthedocs.io/en/latest/index.html) (courtesy of
Paul Tirlisan).
- Added [quizx](https://github.com/Quantomatic/quizx) backend for the `Graph` class.
- `Graph` vertices can now carry a `ground` generator. This makes it possible to represent measurements and classical control in the diagrams. See the accompanying [paper](https://arxiv.org/abs/2109.06071) (courtesy of ABorgna).
Expand Down
2 changes: 1 addition & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ PyZX
:caption: Notebooks:

notebooks/gettingstarted
notebooks/qasm
notebooks/gates

Indices and tables
==================
Expand Down
128 changes: 86 additions & 42 deletions doc/notebooks/qasm.ipynb → doc/notebooks/gates.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
"id": "2b28a205",
"metadata": {},
"source": [
"# Supported OpenQASM Gates\n",
"# Supported Gates\n",
"\n",
"The pyzx library supports a subset of the OpenQASM format.\n",
"The pyzx library supports a variety of gates, including all the commonly-used gates in the OpenQASM standard library. It also supports a subset of the OpenQASM file format.\n",
"\n",
"Here are some examples illustrating the usage:"
]
Expand All @@ -32,8 +32,14 @@
"outputs": [],
"source": [
"import pyzx as zx\n",
"from pyzx.circuit import Circuit\n",
"from pyzx.circuit import Circuit, CNOT\n",
"\n",
"# Add pyzx gates.\n",
"c = Circuit(2)\n",
"c.add_gate(\"CNOT\", 0, 1)\n",
"c.add_gate(CNOT(1, 0))\n",
"\n",
"# Adding qasm gates.\n",
"s = \"\"\"\n",
"OPENQASM 2.0;\n",
"include \"qelib1.inc\";\n",
Expand All @@ -52,7 +58,7 @@
"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.)"
"The set of supported 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.)"
]
},
{
Expand All @@ -64,15 +70,30 @@
"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",
"def _print_gate_name(gate):\n",
" print(gate.name + (\" (adjoint)\" if hasattr(gate, \"adjoint\") and gate.adjoint else \"\"))\n",
"\n",
"def draw_zx_diagram(num_qubits, gate_or_qasm, simplify=False, show_matrix=False):\n",
" if isinstance(gate_or_qasm, str):\n",
" qasm = gate_or_qasm\n",
" c = QASMParser().parse(f\"qreg q[{num_qubits}];\\n\" + qasm, strict=False)\n",
" for gate in c.gates:\n",
" _print_gate_name(gate)\n",
" print(qasm)\n",
" else:\n",
" gate = gate_or_qasm\n",
" c = Circuit(num_qubits)\n",
" c.add_gate(gate)\n",
" _print_gate_name(gate)\n",
" print(\"(no simple qasm command)\")\n",
"\n",
" g = c.to_graph()\n",
" if simplify:\n",
" g.auto_detect_io()\n",
" zx.simplify.full_reduce(g)\n",
" g.auto_detect_io()\n",
" zx.simplify.full_reduce(g)\n",
" zx.draw(g)\n",
" if show_matrix:\n",
" print(g.to_matrix())"
" print(g.to_matrix())"
]
},
{
Expand All @@ -92,10 +113,10 @@
"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;')"
"draw_zx_diagram(1, 'x q;')\n",
"draw_zx_diagram(1, 'y q;')\n",
"draw_zx_diagram(1, 'z q;')\n",
"draw_zx_diagram(1, 'h q;')"
]
},
{
Expand All @@ -115,12 +136,12 @@
"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",
"draw_zx_diagram(1, 'rx(0.125*pi) q;')\n",
"draw_zx_diagram(1, 'ry(0.125*pi) q;')\n",
"draw_zx_diagram(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];')"
"draw_zx_diagram(1, 'u2(0.125*pi,0.125*pi) q[0];')\n",
"draw_zx_diagram(1, 'u3(0.125*pi,0.125*pi,0.125*pi) q[0];')"
]
},
{
Expand All @@ -138,12 +159,12 @@
"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;')"
"draw_zx_diagram(1, 's q;')\n",
"draw_zx_diagram(1, 'sdg q;')\n",
"draw_zx_diagram(1, 't q;')\n",
"draw_zx_diagram(1, 'tdg q;')\n",
"draw_zx_diagram(1, 'sx q;')\n",
"draw_zx_diagram(1, 'sxdg q;')"
]
},
{
Expand All @@ -169,7 +190,7 @@
"metadata": {},
"outputs": [],
"source": [
"draw_qasm_circuit(2, 'swap q[0], q[1];')"
"draw_zx_diagram(2, 'swap q[0], q[1];')"
]
},
{
Expand All @@ -187,8 +208,8 @@
"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];')"
"draw_zx_diagram(2, 'rxx(0.125*pi) q[0], q[1];')\n",
"draw_zx_diagram(2, 'rzz(0.125*pi) q[0], q[1];')"
]
},
{
Expand All @@ -206,11 +227,13 @@
"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];')"
"from pyzx.circuit import XCX\n",
"draw_zx_diagram(2, 'cx q[0], q[1];')\n",
"draw_zx_diagram(2, 'cy q[0], q[1];')\n",
"draw_zx_diagram(2, 'cz q[0], q[1];')\n",
"draw_zx_diagram(2, 'ch q[0], q[1];')\n",
"draw_zx_diagram(2, 'csx q[0], q[1];')\n",
"draw_zx_diagram(2, XCX(0, 1))"
]
},
{
Expand All @@ -230,15 +253,15 @@
"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",
"draw_zx_diagram(2, 'crx(0.125*pi) q[0], q[1];')\n",
"draw_zx_diagram(2, 'cry(0.125*pi) q[0], q[1];')\n",
"draw_zx_diagram(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",
"draw_zx_diagram(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];')"
"draw_zx_diagram(2, 'cu3(0.125*pi,0.125*pi,0.125*pi) q[0], q[1];')\n",
"draw_zx_diagram(2, 'cu(0.125*pi,0.125*pi,0.125*pi,0.125*pi) q[0], q[1];')"
]
},
{
Expand All @@ -264,7 +287,7 @@
"metadata": {},
"outputs": [],
"source": [
"draw_qasm_circuit(3, 'cswap q[0], q[1], q[2];') # Fredkin"
"draw_zx_diagram(3, 'cswap q[0], q[1], q[2];') # Fredkin"
]
},
{
Expand All @@ -282,8 +305,29 @@
"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];')"
"draw_zx_diagram(3, 'ccx q[0], q[1], q[2];') # Toffoli\n",
"draw_zx_diagram(3, 'ccz q[0], q[1], q[2];')"
]
},
{
"cell_type": "markdown",
"id": "a79198ef-d527-4c81-bb9f-d5aa9851c266",
"metadata": {},
"source": [
"## Other gates"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bca3b4c3",
"metadata": {},
"outputs": [],
"source": [
"from pyzx.circuit import ParityPhase, FSim\n",
"\n",
"draw_zx_diagram(4, ParityPhase(0.5, 0, 1, 2, 3))\n",
"draw_zx_diagram(2, FSim(0, 1, 1/2, 1))"
]
}
],
Expand Down
2 changes: 1 addition & 1 deletion doc/representations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`. See the `Supported OpenQASM Gates notebook <notebooks/qasm.ipynb>`_ for more details.
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 Gates notebook <notebooks/gates.ipynb>`_ 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`.

Expand Down
4 changes: 3 additions & 1 deletion pyzx/circuit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

import numpy as np

from .gates import Gate, gate_types, ZPhase, XPhase, CZ, XCX, CNOT, HAD, SWAP, CCZ, Tofolli, Measurement
from .gates import (Gate, gate_types, NOT, Y, Z, HAD, XPhase, YPhase, ZPhase, U2, U3, S, T, SX, SWAP, RXX, RZZ, CNOT,
CY, CZ, CHAD, CSX, XCX, CRX, CRY, CRZ, CPhase, CU3, CU, CSWAP, Tofolli, CCZ, ParityPhase, FSim,
Measurement)

from ..graph.base import BaseGraph
from ..utils import EdgeType
Expand Down
2 changes: 2 additions & 0 deletions pyzx/circuit/gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,8 @@ class FSim(Gate):
qsim_name = 'fs'
print_phase = True
def __init__(self, control:int, target:int, theta:FractionLike, phi:FractionLike):
# TODO: this version assumes theta is always (pi/2)
assert theta == Fraction(1, 2)
self.control = control
self.target = target
self.theta = theta
Expand Down

0 comments on commit c657667

Please sign in to comment.