Skip to content

Commit 5fcd5d0

Browse files
authored
Complete gate zoo and fix gate docs (quantumlib#5344)
1 parent 6b225ad commit 5fcd5d0

16 files changed

+445
-225
lines changed

cirq/ops/boolean_hamiltonian.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
1717
References:
1818
[1] On the representation of Boolean and real functions as Hamiltonians for quantum computing
19-
by Stuart Hadfield, https://arxiv.org/pdf/1804.09130.pdf
19+
by Stuart Hadfield, https://arxiv.org/abs/1804.09130
2020
[2] https://www.youtube.com/watch?v=AOKM9BkweVU is a useful intro
2121
[3] https://github.com/rsln-s/IEEE_QW_2020/blob/master/Slides.pdf
2222
[4] Efficient Quantum Circuits for Diagonal Unitaries Without Ancillas by Jonathan Welch, Daniel
@@ -36,7 +36,20 @@
3636

3737
@value.value_equality
3838
class BooleanHamiltonianGate(raw_types.Gate):
39-
"""A gate that represents a Hamiltonian from a set of Boolean functions."""
39+
r"""A gate that represents evolution due to a Hamiltonian from a set of Boolean functions.
40+
41+
This gate constructs a diagonal gate in the computational basis that encodes in its
42+
phases classical functions.
43+
44+
The gate is specified by a list of parameters, $[x_0, x_1, \dots, x_{n-1}]$, a
45+
list of boolean expressions that are functions of these parameters,
46+
$[f_0(x_0,\dots,x_{n-1}), f_1(x_0,\dots,x_{n-1}), \dots f_{p-1}(x_0,\dots,x_{n-1})]$
47+
and an angle $t$. For these parameters the gate is
48+
49+
$$
50+
\sum_{x=0}^{2^n-1} e^{i \frac{t}{2} \sum_{k=0}^{p-1}f_k(x_0,\dots,x_{n-1})} |x\rangle\langle x|
51+
$$
52+
"""
4053

4154
def __init__(self, parameter_names: Sequence[str], boolean_strs: Sequence[str], theta: float):
4255
"""Builds a BooleanHamiltonianGate.

cirq/ops/common_gates.py

+51-35
Original file line numberDiff line numberDiff line change
@@ -906,18 +906,18 @@ def __repr__(self) -> str:
906906

907907

908908
class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
909-
"""A gate that applies a phase to the |11⟩ state of two qubits.
909+
r"""A gate that applies a phase to the |11⟩ state of two qubits.
910910
911911
The unitary matrix of `CZPowGate(exponent=t)` is:
912912
913-
[[1, 0, 0, 0],
914-
[0, 1, 0, 0],
915-
[0, 0, 1, 0],
916-
[0, 0, 0, g]]
917-
918-
where:
919-
920-
g = exp(i·π·t).
913+
$$
914+
\begin{bmatrix}
915+
1 & 0 & 0 & 0 \\
916+
0 & 1 & 0 & 0 \\
917+
0 & 0 & 1 & 0 \\
918+
0 & 0 & 0 & e^{i \pi t} \\
919+
\end{bmatrix}
920+
$$
921921
922922
`cirq.CZ`, the controlled Z gate, is an instance of this gate at
923923
`exponent=1`.
@@ -1065,7 +1065,7 @@ def __repr__(self) -> str:
10651065

10661066

10671067
class CXPowGate(eigen_gate.EigenGate):
1068-
"""A gate that applies a controlled power of an X gate.
1068+
r"""A gate that applies a controlled power of an X gate.
10691069
10701070
When applying CNOT (controlled-not) to qubits, you can either use
10711071
positional arguments CNOT(q1, q2), where q2 is toggled when q1 is on,
@@ -1074,16 +1074,26 @@ class CXPowGate(eigen_gate.EigenGate):
10741074
10751075
The unitary matrix of `cirq.CXPowGate(exponent=t)` is:
10761076
1077-
[[1, 0, 0, 0],
1078-
[0, 1, 0, 0],
1079-
[0, 0, g·c, -i·g·s],
1080-
[0, 0, -i·g·s, g·c]]
1077+
$$
1078+
\begin{bmatrix}
1079+
1 & 0 & 0 & 0 \\
1080+
0 & 1 & 0 & 0 \\
1081+
0 & 0 & g c & -i g s \\
1082+
0 & 0 & -i g s & g c
1083+
\end{bmatrix}
1084+
$$
10811085
10821086
where:
10831087
1084-
c = cos(π·t/2)
1085-
s = sin(π·t/2)
1086-
g = exp(i·π·t/2).
1088+
$$
1089+
c = \cos\left(\frac{\pi t}{2}\right)
1090+
$$
1091+
$$
1092+
s = \sin\left(\frac{\pi t}{2}\right)
1093+
$$
1094+
$$
1095+
g = e^{\frac{i \pi t}{2}}
1096+
$$
10871097
10881098
`cirq.CNOT`, the controlled NOT gate, is an instance of this gate at
10891099
`exponent=1`.
@@ -1322,34 +1332,40 @@ def cphase(rads: value.TParamVal) -> CZPowGate:
13221332
CZ = CZPowGate()
13231333
document(
13241334
CZ,
1325-
"""The controlled Z gate.
1335+
r"""The controlled Z gate.
13261336
1327-
The `exponent=1` instance of `cirq.CZPowGate`.
1337+
This is the `exponent=1` instance of `cirq.CZPowGate`.
13281338
1329-
Matrix:
1330-
```
1331-
[[1 . . .],
1332-
[. 1 . .],
1333-
[. . 1 .],
1334-
[. . . -1]]
1335-
```
1339+
The unitary matrix of this gate is (empty elements are $0$):
1340+
$$
1341+
\begin{bmatrix}
1342+
1 & & & \\
1343+
& 1 & & \\
1344+
& & 1 & \\
1345+
& & & -1
1346+
\end{bmatrix}
1347+
$$
13361348
""",
13371349
)
13381350

13391351
CNotPowGate = CXPowGate
13401352
CNOT = CX = CNotPowGate()
13411353
document(
13421354
CNOT,
1343-
"""The controlled NOT gate.
1355+
r"""The controlled NOT gate.
1356+
1357+
This is the `exponent=1` instance of `cirq.CXPowGate`.
13441358
1345-
The `exponent=1` instance of `cirq.CXPowGate`.
1359+
Alternative name: `cirq.CNOT`.
13461360
1347-
Matrix:
1348-
```
1349-
[[1 . . .],
1350-
[. 1 . .],
1351-
[. . . 1],
1352-
[. . 1 .]]
1353-
```
1361+
The unitary matrix of this gate is (empty elements are $0$):
1362+
$$
1363+
\begin{bmatrix}
1364+
1 & 0 & 0 & 0 \\
1365+
0 & 1 & 0 & 0 \\
1366+
0 & 0 & 0 & 1 \\
1367+
0 & 0 & 1 & 0
1368+
\end{bmatrix}
1369+
$$
13541370
""",
13551371
)

cirq/ops/dense_pauli_string.py

+30
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,21 @@ def copy(
390390

391391

392392
class DensePauliString(BaseDensePauliString):
393+
"""An immutable string of Paulis, like `XIXY`, with a coefficient.
394+
395+
This represents a Pauli operator acting on qubits.
396+
397+
For example, `cirq.MutableDensePauliString("XXY")` represents a
398+
three qubit operation that acts with `X` on the first two qubits, and
399+
`Y` on the last.
400+
401+
This can optionally take a coefficient, for example,
402+
`cirq.MutableDensePauliString("XX", 3)`, which represents 3 times
403+
the operator acting on X on two qubits.
404+
405+
If the coefficient has magnitude of 1, then this is also a `cirq.Gate`.
406+
"""
407+
393408
def frozen(self) -> 'DensePauliString':
394409
return self
395410

@@ -408,6 +423,21 @@ def copy(
408423

409424
@value.value_equality(unhashable=True, approximate=True)
410425
class MutableDensePauliString(BaseDensePauliString):
426+
"""A mutable string of Paulis, like `XIXY`, with a coefficient.
427+
428+
This represents a Pauli operator acting on qubits.
429+
430+
For example, `cirq.MutableDensePauliString("XXY")` represents a
431+
three qubit operation that acts with `X` on the first two qubits, and
432+
`Y` on the last.
433+
434+
This can optionally take a coefficient, for example,
435+
`cirq.MutableDensePauliString("XX", 3)`, which represents 3 times
436+
the operator acting on X on two qubits.
437+
438+
If the coefficient has magnitude of 1, then this is also a `cirq.Gate`.
439+
"""
440+
411441
def __setitem__(self, key, value):
412442
if isinstance(key, int):
413443
self.pauli_mask[key] = _pauli_index(value)

cirq/ops/diagonal_gate.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,16 @@ def _gen_gray_code(n: int) -> Iterator[Tuple[int, int]]:
6464

6565
@value.value_equality()
6666
class DiagonalGate(raw_types.Gate):
67-
"""A gate given by a diagonal (2^n)\\times(2^n) matrix."""
67+
r"""An n qubit gate which acts as phases on computational basis states.
68+
69+
This gate's off-diagonal elements are zero and its on-diagonal elements are
70+
all phases.
71+
"""
6872

6973
def __init__(self, diag_angles_radians: Sequence['cirq.TParamVal']) -> None:
7074
r"""A n-qubit gate with only diagonal elements.
7175
72-
This gate's off-diagonal elements are zero and it's on diagonal
76+
This gate's off-diagonal elements are zero and its on-diagonal
7377
elements are all phases.
7478
7579
Args:

cirq/ops/fourier_transform.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,19 @@
2424

2525
@value.value_equality
2626
class QuantumFourierTransformGate(raw_types.Gate):
27-
"""Switches from the computational basis to the frequency basis."""
27+
r"""Switches from the computational basis to the frequency basis.
28+
29+
This gate has the unitary
30+
31+
$$
32+
\frac{1}{2^{n/2}}\sum_{x,y=0}^{2^n-1} \omega^{xy} |x\rangle\langle y|
33+
$$
34+
35+
where
36+
$$
37+
\omega = e^{\frac{2\pi i}{2^n}}
38+
$$
39+
"""
2840

2941
def __init__(self, num_qubits: int, *, without_reverse: bool = False):
3042
"""Inits QuantumFourierTransformGate.
@@ -86,7 +98,19 @@ def _circuit_diagram_info_(
8698

8799
@value.value_equality
88100
class PhaseGradientGate(raw_types.Gate):
89-
"""Phases each state |k⟩ out of n by e^(2*pi*i*k/n*exponent)."""
101+
r"""Phases all computational basis states proportional to the integer value of the state.
102+
103+
The gate `cirq.PhaseGradientGate(n, t)` has the unitary
104+
$$
105+
\sum_{x=0}^{2^n-1} \omega^x |x\rangle \langle x|
106+
$$
107+
where
108+
$$
109+
\omega=e^{2 \pi i/2^n}
110+
$$
111+
112+
This gate makes up a portion of the quantum fourier transform.
113+
"""
90114

91115
def __init__(self, *, num_qubits: int, exponent: Union[float, sympy.Basic]):
92116
self._num_qubits = num_qubits

cirq/ops/fsim_gate.py

+33-17
Original file line numberDiff line numberDiff line change
@@ -54,28 +54,40 @@ def _half_pi_mod_pi(param: 'cirq.TParamVal') -> bool:
5454

5555
@value.value_equality(approximate=True)
5656
class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
57-
"""Fermionic simulation gate family.
57+
r"""Fermionic simulation gate family.
5858
5959
Contains all two qubit interactions that preserve excitations, up to
6060
single-qubit rotations and global phase.
6161
6262
The unitary matrix of this gate is:
6363
64-
[[1, 0, 0, 0],
65-
[0, a, b, 0],
66-
[0, b, a, 0],
67-
[0, 0, 0, c]]
64+
$$
65+
\begin{bmatrix}
66+
1 & 0 & 0 & 0 \\
67+
0 & a & b & 0 \\
68+
0 & b & a & 0 \\
69+
0 & 0 & 0 & c
70+
\end{bmatrix}
71+
$$
6872
6973
where:
7074
71-
a = cos(theta)
72-
b = -i·sin(theta)
73-
c = exp(-i·phi)
75+
$$
76+
a = \cos(\theta)
77+
$$
78+
79+
$$
80+
b = -i \sin(\theta)
81+
$$
82+
83+
$$
84+
c = e^{i \phi}
85+
$$
7486
7587
Note the difference in sign conventions between FSimGate and the
7688
ISWAP and CZPowGate:
7789
78-
FSimGate(θ, φ) = ISWAP**(-2θ/π) CZPowGate(exponent=-φ/π)
90+
FSimGate(θ, φ) = ISWAP**(-2θ/π) CZPowGate(exponent=-φ/π)
7991
"""
8092

8193
def __init__(self, theta: 'cirq.TParamVal', phi: 'cirq.TParamVal') -> None:
@@ -202,20 +214,24 @@ def _json_dict_(self) -> Dict[str, Any]:
202214

203215
@value.value_equality(approximate=True)
204216
class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
205-
"""General excitation-preserving two-qubit gate.
217+
r"""General excitation-preserving two-qubit gate.
206218
207219
The unitary matrix of PhasedFSimGate(θ, ζ, χ, γ, φ) is:
208220
209-
[[1, 0, 0, 0],
210-
[0, exp(-iγ - iζ) cos(θ), -i exp(-iγ + iχ) sin(θ), 0],
211-
[0, -i exp(-iγ - iχ) sin(θ), exp(-iγ + iζ) cos(θ), 0],
212-
[0, 0, 0, exp(-2iγ-iφ)]].
221+
$$
222+
\begin{bmatrix}
223+
1 & 0 & 0 & 0 \\
224+
0 & e^{-i \gamma - i \zeta} & -i e^{-i \gamma + i\chi} & 0 \\
225+
0 & -i e^{-i \gamma - i \chi} & e^{-i \gamma + i \zeta} & 0 \\
226+
0 & 0 & 0 & e^{-2i \gamma - i \phi}
227+
\end{bmatrix}
228+
$$
213229
214230
This parametrization follows eq (18) in https://arxiv.org/abs/2010.07965.
215231
See also eq (43) in https://arxiv.org/abs/1910.11333 for an older variant
216-
which uses the same θ and φ parameters, but its three phase angles have
217-
different names and opposite sign. Specifically, ∆+ angle corresponds to
218-
-γ, ∆- corresponds to -ζ and ∆-,off corresponds to -χ.
232+
which uses the same θ and φ parameters, but has three phase angles that
233+
have different names and opposite sign. Specifically, ∆+ angle corresponds
234+
to -γ, ∆- corresponds to -ζ and ∆-,off corresponds to -χ.
219235
220236
Another useful parametrization of PhasedFSimGate is based on the fact that
221237
the gate is equivalent up to global phase to the following circuit:

cirq/ops/matrix_gates.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,17 @@
3737

3838

3939
class MatrixGate(raw_types.Gate):
40-
"""A unitary qubit or qudit gate defined entirely by its matrix."""
40+
r"""A unitary qubit or qudit gate defined entirely by its numpy matrix.
41+
42+
For example `cirq.MatrixGate(np.array([[0, 1j], [1, 0]]))` has the unitary matrix:
43+
44+
$$
45+
\begin{bmatrix}
46+
0 & i \\
47+
1 & 0
48+
\end{bmatrix}
49+
$$
50+
"""
4151

4252
def __init__(
4353
self,

cirq/ops/measurement_gate.py

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ class MeasurementGate(raw_types.Gate):
2929
3030
The measurement gate contains a key that is used to identify results
3131
of measurements.
32+
33+
Instead of constructing this directly, consider using the `cirq.measure`
34+
helper method.
3235
"""
3336

3437
def __init__(

0 commit comments

Comments
 (0)