diff --git a/cirq-core/cirq/ops/common_gates.py b/cirq-core/cirq/ops/common_gates.py index d2f6d830f02..2c2dd8eb25b 100644 --- a/cirq-core/cirq/ops/common_gates.py +++ b/cirq-core/cirq/ops/common_gates.py @@ -68,26 +68,23 @@ def _pi(rads): @value.value_equality class XPowGate(eigen_gate.EigenGate): - """A gate that rotates around the X axis of the Bloch sphere. + r"""A gate that rotates around the X axis of the Bloch sphere. - The unitary matrix of ``XPowGate(exponent=t)`` is: - - [[g·c, -i·g·s], - [-i·g·s, g·c]] - - where: - - c = cos(π·t/2) - s = sin(π·t/2) - g = exp(i·π·t/2). + The unitary matrix of `cirq.XPowGate(exponent=t)` is: + $$ + \begin{bmatrix} + e^{i \pi t /2} \cos(\pi t) & -i e^{i \pi t /2} \sin(\pi t) \\ + -i e^{i \pi t /2} \sin(\pi t) & e^{i \pi t /2} \cos(\pi t) + \end{bmatrix} + $$ Note in particular that this gate has a global phase factor of - e^{i·π·t/2} vs the traditionally defined rotation matrices - about the Pauli X axis. See `cirq.rx` for rotations without the global + $e^{i \pi t / 2}$ vs the traditionally defined rotation matrices + about the Pauli X axis. See `cirq.Rx` for rotations without the global phase. The global phase factor can be adjusted by using the `global_shift` parameter when initializing. - `cirq.X`, the Pauli X gate, is an instance of this gate at exponent=1. + `cirq.X`, the Pauli X gate, is an instance of this gate at `exponent=1`. """ def _num_qubits_(self) -> int: @@ -245,14 +242,18 @@ def __repr__(self) -> str: class Rx(XPowGate): - """A gate, with matrix e^{-i X rads/2}, that rotates around the X axis of the Bloch sphere. - - The unitary matrix of ``Rx(rads=t)`` is: - - exp(-i X t/2) = [ cos(t/2) -isin(t/2)] - [-isin(t/2) cos(t/2) ] - - The gate corresponds to the traditionally defined rotation matrices about the Pauli X axis. + r"""A gate with matrix $e^{-i X t/2}$ that rotates around the X axis of the Bloch sphere by $t$. + + The unitary matrix of `cirq.Rx(rads=t)` is: + $$ + e^{-i X t /2} = + \begin{bmatrix} + \cos(t/2) & -i \sin(t/2) \\ + -i \sin(t/2) & \cos(t/2) + \end{bmatrix} + $$ + + This gate corresponds to the traditionally defined rotation matrices about the Pauli X axis. """ def __init__(self, *, rads: value.TParamVal): @@ -286,26 +287,23 @@ def _from_json_dict_(cls, rads, **kwargs) -> 'Rx': @value.value_equality class YPowGate(eigen_gate.EigenGate): - """A gate that rotates around the Y axis of the Bloch sphere. - - The unitary matrix of ``YPowGate(exponent=t)`` is: + r"""A gate that rotates around the Y axis of the Bloch sphere. - [[g·c, -g·s], - [g·s, g·c]] - - where: - - c = cos(π·t/2) - s = sin(π·t/2) - g = exp(i·π·t/2). + The unitary matrix of `cirq.YPowGate(exponent=t)` is: + $$ + \begin{bmatrix} + e^{i \pi t /2} \cos(\pi t /2) & - e^{i \pi t /2} \sin(\pi t /2) \\ + e^{i \pi t /2} \sin(\pi t /2) & e^{i \pi t /2} \cos(\pi t /2) + \end{bmatrix} + $$ Note in particular that this gate has a global phase factor of - e^{i·π·t/2} vs the traditionally defined rotation matrices + $e^{i \pi t / 2}$ vs the traditionally defined rotation matrices about the Pauli Y axis. See `cirq.Ry` for rotations without the global phase. The global phase factor can be adjusted by using the `global_shift` parameter when initializing. - `cirq.Y`, the Pauli Y gate, is an instance of this gate at exponent=1. + `cirq.Y`, the Pauli Y gate, is an instance of this gate at `exponent=1`. """ def _num_qubits_(self) -> int: @@ -416,14 +414,18 @@ def __repr__(self) -> str: class Ry(YPowGate): - """A gate, with matrix e^{-i Y rads/2}, that rotates around the Y axis of the Bloch sphere. - - The unitary matrix of ``Ry(rads=t)`` is: - - exp(-i Y t/2) = [cos(t/2) -sin(t/2)] - [sin(t/2) cos(t/2) ] - - The gate corresponds to the traditionally defined rotation matrices about the Pauli Y axis. + r"""A gate with matrix $e^{-i Y t/2}$ that rotates around the Y axis of the Bloch sphere by $t$. + + The unitary matrix of `cirq.Ry(rads=t)` is: + $$ + e^{-i Y t / 2} = + \begin{bmatrix} + \cos(t/2) & -\sin(t/2) \\ + \sin(t/2) & \cos(t/2) + \end{bmatrix} + $$ + + This gate corresponds to the traditionally defined rotation matrices about the Pauli Y axis. """ def __init__(self, *, rads: value.TParamVal): @@ -457,24 +459,23 @@ def _from_json_dict_(cls, rads, **kwargs) -> 'Ry': @value.value_equality class ZPowGate(eigen_gate.EigenGate): - """A gate that rotates around the Z axis of the Bloch sphere. - - The unitary matrix of ``ZPowGate(exponent=t)`` is: + r"""A gate that rotates around the Z axis of the Bloch sphere. - [[1, 0], - [0, g]] - - where: - - g = exp(i·π·t). + The unitary matrix of `cirq.ZPowGate(exponent=t)` is: + $$ + \begin{bmatrix} + 1 & 0 \\ + 0 & e^{i \pi t} + \end{bmatrix} + $$ Note in particular that this gate has a global phase factor of - e^{i·π·t/2} vs the traditionally defined rotation matrices + $e^{i\pi t/2}$ vs the traditionally defined rotation matrices about the Pauli Z axis. See `cirq.Rz` for rotations without the global phase. The global phase factor can be adjusted by using the `global_shift` parameter when initializing. - `cirq.Z`, the Pauli Z gate, is an instance of this gate at exponent=1. + `cirq.Z`, the Pauli Z gate, is an instance of this gate at `exponent=1`. """ def _num_qubits_(self) -> int: @@ -658,14 +659,18 @@ def _commutes_on_qids_( class Rz(ZPowGate): - """A gate, with matrix e^{-i Z rads/2}, that rotates around the Z axis of the Bloch sphere. - - The unitary matrix of ``Rz(rads=t)`` is: - - exp(-i Z t/2) = [ e^(-it/2) 0 ] - [ 0 e^(it/2)] - - The gate corresponds to the traditionally defined rotation matrices about the Pauli Z axis. + r"""A gate with matrix $e^{-i Z t/2}$ that rotates around the Z axis of the Bloch sphere by $t$. + + The unitary matrix of `cirq.Rz(rads=t)` is: + $$ + e^{-i Z t /2} = + \begin{bmatrix} + e^{-it/2} & 0 \\ + 0 & e^{it/2} + \end{bmatrix} + $$ + + This gate corresponds to the traditionally defined rotation matrices about the Pauli Z axis. """ def __init__(self, *, rads: value.TParamVal): @@ -698,20 +703,24 @@ def _from_json_dict_(cls, rads, **kwargs) -> 'Rz': class HPowGate(eigen_gate.EigenGate): - """A Gate that performs a rotation around the X+Z axis of the Bloch sphere. - - The unitary matrix of ``HPowGate(exponent=t)`` is: - - [[g·(c-i·s/sqrt(2)), -i·g·s/sqrt(2)], - [-i·g·s/sqrt(2)], g·(c+i·s/sqrt(2))]] - - where - - c = cos(π·t/2) - s = sin(π·t/2) - g = exp(i·π·t/2). - - Note in particular that for `t=1`, this gives the Hadamard matrix. + r"""A Gate that performs a rotation around the X+Z axis of the Bloch sphere. + + The unitary matrix of `cirq.HPowGate(exponent=t)` is: + $$ + \begin{bmatrix} + e^{i\pi t/2} \left(\cos(\pi t/2) - i \frac{\sin (\pi t /2)}{\sqrt{2}}\right) + && -i e^{i\pi t/2} \frac{\sin(\pi t /2)}{\sqrt{2}} \\ + -i e^{i\pi t/2} \frac{\sin(\pi t /2)}{\sqrt{2}} + && e^{i\pi t/2} \left(\cos(\pi t/2) + i \frac{\sin (\pi t /2)}{\sqrt{2}}\right) + \end{bmatrix} + $$ + Note in particular that for $t=1$, this gives the Hadamard matrix + $$ + \begin{bmatrix} + \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ + \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} + \end{bmatrix} + $$ `cirq.H`, the Hadamard gate, is an instance of this gate at `exponent=1`. """ @@ -1001,7 +1010,7 @@ class CXPowGate(eigen_gate.EigenGate): or named arguments CNOT(control=q1, target=q2). (Mixing the two is not permitted.) - The unitary matrix of `CXPowGate(exponent=t)` is: + The unitary matrix of `cirq.CXPowGate(exponent=t)` is: [[1, 0, 0, 0], [0, 1, 0, 0], @@ -1197,46 +1206,51 @@ def cphase(rads: value.TParamVal) -> CZPowGate: H = HPowGate() document( H, - """The Hadamard gate. + r"""The Hadamard gate. The `exponent=1` instance of `cirq.HPowGate`. - Matrix: - ``` - [[s, s], - [s, -s]] - ``` - where s = sqrt(0.5). + The unitary matrix of `cirq.H` is: + $$ + \begin{bmatrix} + \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ + \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} + \end{bmatrix} + $$ """, ) S = ZPowGate(exponent=0.5) document( S, - """The Clifford S gate. + r"""The Clifford S gate. The `exponent=0.5` instance of `cirq.ZPowGate`. - Matrix: - ``` - [[1, 0], - [0, i]] - ``` + The unitary matrix of `cirq.S` is: + $$ + \begin{bmatrix} + 1 & 0 \\ + 0 & i + \end{bmatrix} + $$ """, ) T = ZPowGate(exponent=0.25) document( T, - """The non-Clifford T gate. + r"""The non-Clifford T gate. The `exponent=0.25` instance of `cirq.ZPowGate`. - Matrix: - ``` - [[1, 0] - [0, exp(i pi / 4)]] - ``` + The unitary matrix of `cirq.T` is + $$ + \begin{bmatrix} + 1 & 0 \\ + 0 & e^{i \pi /4} + \end{bmatrix} + $$ """, ) diff --git a/cirq-core/cirq/ops/pauli_gates.py b/cirq-core/cirq/ops/pauli_gates.py index 12c82e7c8c5..7d4ed3ee293 100644 --- a/cirq-core/cirq/ops/pauli_gates.py +++ b/cirq-core/cirq/ops/pauli_gates.py @@ -182,36 +182,51 @@ def basis(self: '_PauliZ') -> Dict[int, '_ZEigenState']: X = _PauliX() document( X, - """The Pauli X gate. + r"""The Pauli X gate. - Matrix: + This is the `exponent=1` instance of the `cirq.XPowGate`. - [[0, 1], - [1, 0]] + The untary matrix of `cirq.X` is: + $$ + \begin{bmatrix} + 0 & 1 \\ + 1 & 0 + \end{bmatrix} + $$ """, ) Y = _PauliY() document( Y, - """The Pauli Y gate. + r"""The Pauli Y gate. - Matrix: + This is the `exponent=1` instance of the `cirq.YPowGate`. - [[0, -i], - [i, 0]] + The unitary matrix of `cirq.Y` is: + $$ + \begin{bmatrix} + 0 & -i \\ + i & 0 + \end{bmatrix} + $$ """, ) Z = _PauliZ() document( Z, - """The Pauli Z gate. + r"""The Pauli Z gate. - Matrix: + This is the `exponent=1` instance of the `cirq.ZPowGate`. - [[1, 0], - [0, -1]] + The unitary matrix of `cirq.Z` is: + $$ + \begin{bmatrix} + 1 & 0 \\ + 0 & -1 + \end{bmatrix} + $$ """, ) diff --git a/cirq-core/cirq/ops/phased_x_gate.py b/cirq-core/cirq/ops/phased_x_gate.py index fa6723793a0..e5fb03f6352 100644 --- a/cirq-core/cirq/ops/phased_x_gate.py +++ b/cirq-core/cirq/ops/phased_x_gate.py @@ -27,7 +27,21 @@ @value.value_equality(manual_cls=True, approximate=True) class PhasedXPowGate(raw_types.Gate): - """A gate equivalent to the circuit ───Z^-p───X^t───Z^p───.""" + r"""A gate equivalent to $Z^{p} X^t Z^{-p}$. + + The unitary matrix of `cirq.PhasedXPowGate(exponent=t, phase_exponent=p)` is: + $$ + \begin{bmatrix} + e^{i \pi t /2} \cos(\pi t/2) & -i e^{i \pi (t /2 - p)} \sin(\pi t /2) \\ + -i e^{i \pi (t /2 + p)} \sin(\pi t /2) & e^{i \pi t /2} \cos(\pi t/2) + \end{bmatrix} + $$ + + This gate is like an `cirq.XPowGate`, but which has been "phased", + by applying a `cirq.ZPowGate` before and after this gate. In the language + of the Bloch sphere, $p$ determines the axis in the XY plane about which + a rotation of amount determined by $t$ occurs. + """ def __init__( self, diff --git a/cirq-core/cirq/ops/phased_x_z_gate.py b/cirq-core/cirq/ops/phased_x_z_gate.py index 300d6229d19..cb12b72dcb2 100644 --- a/cirq-core/cirq/ops/phased_x_z_gate.py +++ b/cirq-core/cirq/ops/phased_x_z_gate.py @@ -15,16 +15,23 @@ @value.value_equality(approximate=True) class PhasedXZGate(raw_types.Gate): - """A single qubit operation expressed as $Z^z Z^a X^x Z^{-a}$. + r"""A single qubit gate equivalent to the circuit $Z^z Z^{a} X^x Z^{-a}$. - The above expression is a matrix multiplication with time going to the left. - In quantum circuit notation, this operation decomposes into this circuit: + The unitary matrix of `cirq.PhasedXZGate(x_exponent=x, z_exponent=z, axis_phase_exponent=a)` is: + $$ + \begin{bmatrix} + e^{i \pi x / 2} \cos(\pi x /2) & -i e^{i \pi (x/2 - a)} \sin(\pi x / 2) \\ + -i e^{i \pi (x/2 + z + a)} \sin(\pi x / 2) & e^{i \pi (x / 2 + z)} \cos(\pi x /2) + \end{bmatrix} + $$ - ───Z^(-a)──X^x──Z^a────Z^z─── + This gate can be thought of as a `cirq.PhasedXPowGate` followed by a `cirq.ZPowGate`. - The axis phase exponent (a) decides which axis in the XY plane to rotate + The axis phase exponent ($a$) decides which axis in the XY plane to rotate around. The amount of rotation around that axis is decided by the x - exponent (x). Then the z exponent (z) decides how much to phase the qubit. + exponent ($x$). Then the z exponent ($z$) decides how much to finally phase the qubit. + + Every single qubit gate can be written as a single `cirq.PhasedXZGate`. """ def __init__( diff --git a/docs/gatezoo.ipynb b/docs/gatezoo.ipynb new file mode 100644 index 00000000000..05c7ee3345e --- /dev/null +++ b/docs/gatezoo.ipynb @@ -0,0 +1,215 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "2e694355-6c8f-43c5-b1ae-4e86af9fc9eb", + "metadata": { + "cellView": "form", + "id": "KQa9t_gadIuR" + }, + "outputs": [], + "source": [ + "#@title Copyright 2022 The Cirq Developers\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# https://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License." + ] + }, + { + "cell_type": "markdown", + "id": "42a837dc-73a7-4a4e-a79b-563786f1bfc6", + "metadata": { + "id": "xwec7FrkdFmi" + }, + "source": [ + "# Gate Zoo" + ] + }, + { + "cell_type": "markdown", + "id": "1ffc5e6a-50af-495e-b713-ad7c626a6181", + "metadata": { + "id": "5KZia7jmdJ3V" + }, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " View on QuantumAI\n", + " \n", + " Run in Google Colab\n", + " \n", + " View source on GitHub\n", + " \n", + " Download notebook\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "bb448db9-c75a-44e1-900c-532101085565", + "metadata": { + "id": "541571c2edcd" + }, + "source": [ + "## Setup\n", + "Note: this notebook relies on unreleased Cirq features. If you want to try these features, make sure you install cirq via `pip install cirq --pre`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b650764-128c-46fe-8b19-ee54762a77ef", + "metadata": { + "id": "bd9529db1c0b" + }, + "outputs": [], + "source": [ + "try:\n", + " import cirq\n", + "except ImportError:\n", + " print(\"installing cirq...\")\n", + " !pip install --quiet --pre cirq\n", + " print(\"installed cirq.\")\n", + " \n", + "import IPython.display as ipd\n", + "import cirq\n", + "import inspect\n", + "\n", + "def display_gates(*gates):\n", + " for gate_name in gates:\n", + " ipd.display(ipd.Markdown(\"---\"))\n", + " gate = getattr(cirq, gate_name)\n", + " ipd.display(ipd.Markdown(f\"#### cirq.{gate_name}\"))\n", + " ipd.display(ipd.Markdown(inspect.cleandoc(gate.__doc__)))\n", + " else:\n", + " ipd.display(ipd.Markdown(\"---\")) " + ] + }, + { + "cell_type": "markdown", + "id": "5731f798-b633-4039-a138-8c70b4d8fac4", + "metadata": { + "id": "1cd004cc2f3a" + }, + "source": [ + "Cirq comes with many gates that are standard across quantum computing. This notebook serves as a reference sheet for these gates.\n", + "\n", + "## Single Qubit Gates\n", + "\n", + "\n", + "### Gate constants \n", + "\n", + "Cirq defines constants which are gate instances for particular important single qubit gates." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cb68f8a-4285-42ba-9a0f-b73bf13cd4f1", + "metadata": { + "id": "0c3a029e2155" + }, + "outputs": [], + "source": [ + "display_gates(\"X\", \"Y\", \"Z\", \"H\", \"S\", \"T\")" + ] + }, + { + "cell_type": "markdown", + "id": "d65a3acf-4446-4d7b-9077-39cd0b1095b6", + "metadata": { + "id": "10c855370f45" + }, + "source": [ + "### Traditional Pauli Rotation Gates\n", + "\n", + "Traditional single qubit rotations expressed in radians of rotation about Pauli axis are defined." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e5d38c50-1774-4acf-b22c-47cd103c8a8d", + "metadata": { + "id": "e96e1c459258" + }, + "outputs": [], + "source": [ + "display_gates(\"Rx\", \"Ry\", \"Rz\")" + ] + }, + { + "cell_type": "markdown", + "id": "9a7fec58-bbe6-4ec7-8158-5afe735ea7e2", + "metadata": { + "id": "4bfc17ef80bb" + }, + "source": [ + "### Pauli PowGates\n", + "\n", + "If you think of the `cirq.Z` gate as phasing the state $|1\\rangle$ by $-1$, then you might think that the square root of this gate phases the state $|1\\rangle$ by $i=\\sqrt{-1}$. The `XPowGate`, `YPowGate` and `ZPowGate`s all act in this manner, phasing the state corresponding to their $-1$ eigenvalue by a prescribed amount. This ends up being the same as the `Rx`, `Ry`, and `Rz` up to a global phase." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e478b06c-3a62-4b6c-a614-12dc25182304", + "metadata": { + "id": "0e2ea8a0a0ae" + }, + "outputs": [], + "source": [ + "display_gates(\"XPowGate\", \"YPowGate\", \"ZPowGate\")" + ] + }, + { + "cell_type": "markdown", + "id": "110838d7-5a53-4b53-aeea-4496549e8e1f", + "metadata": { + "id": "6631a361ac42" + }, + "source": [ + "### More Single Qubit Gate\n", + "\n", + "Many quantum computing implementations use qubits whose energy eigenstates for a qubit that is not interacting are the computational basis states. In these cases it is often useful to move `cirq.ZPowGate`'s through other single qubit gates, \"phasing\" the " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a560cfb-6d7b-4837-85d1-6aa96accc264", + "metadata": { + "id": "b5ffeefa3c76" + }, + "outputs": [], + "source": [ + "display_gates(\"PhasedXPowGate\", \"PhasedXZGate\", \"HPowGate\")" + ] + } + ], + "metadata": { + "colab": { + "name": "gatezoo.ipynb", + "toc_visible": true + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}