Skip to content

Commit 99f88c8

Browse files
authored
Add json serialization to diagonal gates (quantumlib#5356)
1 parent b0d96db commit 99f88c8

14 files changed

+89
-8
lines changed

cirq/json_resolver_cache.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ def _symmetricalqidpair(qids):
9797
'CXPowGate': cirq.CXPowGate,
9898
'CZPowGate': cirq.CZPowGate,
9999
'CZTargetGateset': cirq.CZTargetGateset,
100+
'DiagonalGate': cirq.DiagonalGate,
100101
'DensePauliString': cirq.DensePauliString,
101102
'DepolarizingChannel': cirq.DepolarizingChannel,
102103
'DeviceMetadata': cirq.DeviceMetadata,
@@ -165,7 +166,6 @@ def _symmetricalqidpair(qids):
165166
'QuantumFourierTransformGate': cirq.QuantumFourierTransformGate,
166167
'QubitPermutationGate': cirq.QubitPermutationGate,
167168
'RandomGateChannel': cirq.RandomGateChannel,
168-
'TensoredConfusionMatrices': cirq.TensoredConfusionMatrices,
169169
'RepetitionsStoppingCriteria': cirq.work.RepetitionsStoppingCriteria,
170170
'ResetChannel': cirq.ResetChannel,
171171
'Result': cirq.ResultDict, # Keep support for Cirq < 0.14.
@@ -182,8 +182,11 @@ def _symmetricalqidpair(qids):
182182
'SwapPowGate': cirq.SwapPowGate,
183183
'SympyCondition': cirq.SympyCondition,
184184
'TaggedOperation': cirq.TaggedOperation,
185+
'TensoredConfusionMatrices': cirq.TensoredConfusionMatrices,
185186
'TiltedSquareLattice': cirq.TiltedSquareLattice,
187+
'ThreeQubitDiagonalGate': cirq.ThreeQubitDiagonalGate,
186188
'TrialResult': cirq.ResultDict, # keep support for Cirq < 0.11.
189+
'TwoQubitDiagonalGate': cirq.TwoQubitDiagonalGate,
187190
'TwoQubitGateTabulation': cirq.TwoQubitGateTabulation,
188191
'_UnconstrainedDevice': cirq.devices.unconstrained_device._UnconstrainedDevice,
189192
'VarianceStoppingCriteria': cirq.work.VarianceStoppingCriteria,

cirq/ops/diagonal_gate.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,18 @@
1818
passed as a list.
1919
"""
2020

21-
from typing import AbstractSet, Any, Iterator, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
21+
from typing import (
22+
AbstractSet,
23+
Any,
24+
Dict,
25+
Iterator,
26+
List,
27+
Optional,
28+
Sequence,
29+
Tuple,
30+
TYPE_CHECKING,
31+
Union,
32+
)
2233

2334
import numpy as np
2435
import sympy
@@ -83,6 +94,10 @@ def __init__(self, diag_angles_radians: Sequence['cirq.TParamVal']) -> None:
8394
"""
8495
self._diag_angles_radians: Tuple['cirq.TParamVal', ...] = tuple(diag_angles_radians)
8596

97+
@property
98+
def diag_angles_radians(self) -> Tuple['cirq.TParamVal', ...]:
99+
return self._diag_angles_radians
100+
86101
def _num_qubits_(self):
87102
return int(np.log2(len(self._diag_angles_radians)))
88103

@@ -194,6 +209,9 @@ def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
194209
decomposed_circ.extend(self._decompose_for_basis(i, bit_flip, -hat_angles[i], qubits))
195210
return decomposed_circ
196211

212+
def _json_dict_(self) -> Dict[str, Any]:
213+
return protocols.obj_to_dict_helper(self, attribute_names=["diag_angles_radians"])
214+
197215
def __repr__(self) -> str:
198216
return 'cirq.DiagonalGate([{}])'.format(
199217
','.join(proper_repr(angle) for angle in self._diag_angles_radians)

cirq/ops/diagonal_gate_test.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ def test_consistent_protocols(gate):
3939
cirq.testing.assert_implements_consistent_protocols(gate)
4040

4141

42+
def test_property():
43+
assert cirq.DiagonalGate([2, 3, 5, 7]).diag_angles_radians == (2, 3, 5, 7)
44+
45+
4246
@pytest.mark.parametrize('n', [1, 2, 3, 4, 5, 6, 7, 8, 9])
4347
def test_decomposition_unitary(n):
4448
diagonal_angles = np.random.randn(2**n)

cirq/ops/three_qubit_gates.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
AbstractSet,
1919
Any,
2020
Collection,
21+
Dict,
2122
List,
2223
Optional,
2324
Sequence,
@@ -221,7 +222,7 @@ class ThreeQubitDiagonalGate(raw_types.Gate):
221222
elements are all phases.
222223
"""
223224

224-
def __init__(self, diag_angles_radians: List[value.TParamVal]) -> None:
225+
def __init__(self, diag_angles_radians: Sequence[value.TParamVal]) -> None:
225226
r"""A three qubit gate with only diagonal elements.
226227
227228
This gate's off-diagonal elements are zero and its on diagonal
@@ -232,7 +233,11 @@ def __init__(self, diag_angles_radians: List[value.TParamVal]) -> None:
232233
If these values are $(x_0, x_1, \ldots , x_7)$ then the unitary
233234
has diagonal values $(e^{i x_0}, e^{i x_1}, \ldots, e^{i x_7})$.
234235
"""
235-
self._diag_angles_radians: List[value.TParamVal] = diag_angles_radians
236+
self._diag_angles_radians: Tuple[value.TParamVal, ...] = tuple(diag_angles_radians)
237+
238+
@property
239+
def diag_angles_radians(self) -> Tuple[value.TParamVal, ...]:
240+
return self._diag_angles_radians
236241

237242
def _is_parameterized_(self) -> bool:
238243
return any(protocols.is_parameterized(angle) for angle in self._diag_angles_radians)
@@ -367,6 +372,9 @@ def _pauli_expansion_(self) -> value.LinearDict[str]:
367372
}
368373
)
369374

375+
def _json_dict_(self) -> Dict[str, Any]:
376+
return protocols.obj_to_dict_helper(self, attribute_names=["diag_angles_radians"])
377+
370378
def __repr__(self) -> str:
371379
return 'cirq.ThreeQubitDiagonalGate([{}])'.format(
372380
','.join(proper_repr(angle) for angle in self._diag_angles_radians)

cirq/ops/three_qubit_gates_test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ def test_decomposition_cost(op: cirq.Operation, max_two_cost: int):
206206
assert two_cost == max_two_cost
207207

208208

209+
def test_diagonal_gate_property():
210+
assert cirq.ThreeQubitDiagonalGate([2, 3, 5, 7, 0, 0, 0, 1]).diag_angles_radians == (
211+
(2, 3, 5, 7, 0, 0, 0, 1)
212+
)
213+
214+
209215
@pytest.mark.parametrize(
210216
'gate',
211217
[cirq.CCX, cirq.CSWAP, cirq.CCZ, cirq.ThreeQubitDiagonalGate([2, 3, 5, 7, 11, 13, 17, 19])],

cirq/ops/two_qubit_diagonal_gate.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
passed as a list.
1818
"""
1919

20-
from typing import AbstractSet, Any, Tuple, Optional, Sequence, TYPE_CHECKING
20+
from typing import AbstractSet, Any, Dict, Tuple, Optional, Sequence, TYPE_CHECKING
2121
import numpy as np
2222
import sympy
2323

@@ -62,6 +62,10 @@ def __init__(self, diag_angles_radians: Sequence[value.TParamVal]) -> None:
6262
"""
6363
self._diag_angles_radians: Tuple[value.TParamVal, ...] = tuple(diag_angles_radians)
6464

65+
@property
66+
def diag_angles_radians(self) -> Tuple[value.TParamVal, ...]:
67+
return self._diag_angles_radians
68+
6569
def _num_qubits_(self) -> int:
6670
return 2
6771

@@ -134,6 +138,9 @@ def __repr__(self) -> str:
134138
','.join(proper_repr(angle) for angle in self._diag_angles_radians)
135139
)
136140

141+
def _json_dict_(self) -> Dict[str, Any]:
142+
return protocols.obj_to_dict_helper(self, attribute_names=["diag_angles_radians"])
143+
137144
def _quil_(
138145
self, qubits: Tuple['cirq.Qid', ...], formatter: 'cirq.QuilFormatter'
139146
) -> Optional[str]:

cirq/ops/two_qubit_diagonal_gate_test.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ def test_consistent_protocols(gate):
3434
cirq.testing.assert_implements_consistent_protocols(gate)
3535

3636

37+
def test_property():
38+
assert cirq.TwoQubitDiagonalGate([2, 3, 5, 7]).diag_angles_radians == (2, 3, 5, 7)
39+
40+
3741
def test_parameterized_decompose():
3842
angles = sympy.symbols('x0, x1, x2, x3')
3943
parameterized_op = cirq.TwoQubitDiagonalGate(angles).on(*cirq.LineQubit.range(2))
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"cirq_type": "DiagonalGate",
3+
"diag_angles_radians": [
4+
0.0,
5+
1.0,
6+
-1.0,
7+
0.0
8+
]
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cirq.DiagonalGate(diag_angles_radians=[0.0, 1.0, -1.0, 0.0])
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"cirq_type": "ThreeQubitDiagonalGate",
3+
"diag_angles_radians": [
4+
0.0,
5+
1.0,
6+
-1.0,
7+
0.0,
8+
0.5,
9+
0.5,
10+
0.5,
11+
0.5
12+
]
13+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cirq.ThreeQubitDiagonalGate(diag_angles_radians=[0.0, 1.0, -1.0, 0.0, 0.5, 0.5, 0.5, 0.5])
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"cirq_type": "TwoQubitDiagonalGate",
3+
"diag_angles_radians": [
4+
0.0,
5+
1.0,
6+
-1.0,
7+
0.0
8+
]
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cirq.TwoQubitDiagonalGate(diag_angles_radians=[0.0, 1.0, -1.0, 0.0])

cirq/protocols/json_test_data/spec.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
'LinearCombinationOfOperations',
4545
'Linspace',
4646
'ListSweep',
47-
'DiagonalGate',
4847
'NeutralAtomDevice',
4948
'PauliInteractionGate',
5049
'PauliSumCollector',
@@ -65,9 +64,7 @@
6564
'SparseSimulatorStep',
6665
'StateVectorMixin',
6766
'TextDiagramDrawer',
68-
'ThreeQubitDiagonalGate',
6967
'Timestamp',
70-
'TwoQubitDiagonalGate',
7168
'TwoQubitGateTabulationResult',
7269
'UnitSweep',
7370
'StateVectorSimulatorState',

0 commit comments

Comments
 (0)