Skip to content

Commit

Permalink
Move "cirq_type" responsibility to protocols (#4704)
Browse files Browse the repository at this point in the history
Fixes #4698.

This enforces the `'cirq_type': [<namespace>.]<classname>` convention for JSON serialization by assigning the "cirq_type" field in our protocols instead of in each class. Any external users who define a "cirq_type" will see a warning about this; after a deprecation cycle, we will begin raising errors to prevent explicit definition of "cirq_type" in classes.
  • Loading branch information
95-martin-orion authored Nov 24, 2021
1 parent d42e058 commit 48397d6
Show file tree
Hide file tree
Showing 58 changed files with 155 additions and 104 deletions.
1 change: 0 additions & 1 deletion cirq-core/cirq/circuits/circuit_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,6 @@ def __hash__(self):

def _json_dict_(self):
return {
'cirq_type': 'CircuitOperation',
'circuit': self.circuit,
'repetitions': self.repetitions,
# JSON requires mappings to have keys of basic types.
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/circuits/circuit_operation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,6 @@ def test_json_dict():
)

assert op._json_dict_() == {
'cirq_type': 'CircuitOperation',
'circuit': circuit,
'repetitions': 1,
'qubit_map': sorted([(k, v) for k, v in op.qubit_map.items()]),
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/circuits/circuit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4212,7 +4212,6 @@ def test_json_dict(circuit_cls):
if circuit_cls == cirq.FrozenCircuit:
moments = tuple(moments)
assert c._json_dict_() == {
'cirq_type': circuit_cls.__name__,
'moments': moments,
'device': cirq.UNCONSTRAINED_DEVICE,
}
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/devices/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ def __repr__(self):
def _json_dict_(self):
return {
'qids': sorted(self.qids),
'cirq_type': self.__class__.__name__,
}

@classmethod
Expand Down
2 changes: 0 additions & 2 deletions cirq-core/cirq/devices/grid_qubit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,13 +321,11 @@ def test_neg():

def test_to_json():
assert cirq.GridQubit(5, 6)._json_dict_() == {
'cirq_type': 'GridQubit',
'row': 5,
'col': 6,
}

assert cirq.GridQid(5, 6, dimension=3)._json_dict_() == {
'cirq_type': 'GridQid',
'row': 5,
'col': 6,
'dimension': 3,
Expand Down
2 changes: 0 additions & 2 deletions cirq-core/cirq/devices/line_qubit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,9 @@ def test_neg():

def test_json_dict():
assert cirq.LineQubit(5)._json_dict_() == {
'cirq_type': 'LineQubit',
'x': 5,
}
assert cirq.LineQid(5, 3)._json_dict_() == {
'cirq_type': 'LineQid',
'x': 5,
'dimension': 3,
}
Expand Down
7 changes: 1 addition & 6 deletions cirq-core/cirq/devices/named_topologies.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# limitations under the License.

import abc
import dataclasses
import warnings
from dataclasses import dataclass
from typing import Dict, List, Tuple, Any, Sequence, Union, Iterable, TYPE_CHECKING
Expand All @@ -23,16 +22,12 @@

from cirq import _compat
from cirq.devices import GridQubit, LineQubit
from cirq.protocols.json_serialization import obj_to_dict_helper
from cirq.protocols.json_serialization import dataclass_json_dict

if TYPE_CHECKING:
import cirq


def dataclass_json_dict(obj: Any, namespace: str = None) -> Dict[str, Any]:
return obj_to_dict_helper(obj, [f.name for f in dataclasses.fields(obj)], namespace=namespace)


class NamedTopology(metaclass=abc.ABCMeta):
"""A topology (graph) with a name.
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/experiments/cross_entropy_benchmarking.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ class CrossEntropyResultDict(Mapping[Tuple['cirq.Qid', ...], CrossEntropyResult]

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'results': list(self.results.items()),
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class SingleQubitReadoutCalibrationResult:

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'zero_state_errors': list(self.zero_state_errors.items()),
'one_state_errors': list(self.one_state_errors.items()),
'repetitions': self.repetitions,
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/boolean_hamiltonian.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ def _value_equality_values_(self):

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'qubit_map': self._qubit_map,
'boolean_strs': self._boolean_strs,
'theta': self._theta,
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/clifford_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,6 @@ def _from_json_dict_(cls, n, rs, xs, zs, **kwargs):

def _json_dict_(self) -> Dict[str, Any]:
json_dict = self._clifford_tableau._json_dict_()
json_dict['cirq_type'] = self.__class__.__name__
return json_dict

def _circuit_diagram_info_(
Expand Down
3 changes: 0 additions & 3 deletions cirq-core/cirq/ops/common_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,6 @@ def __repr__(self) -> str:

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'rads': self._rads,
}

Expand Down Expand Up @@ -539,7 +538,6 @@ def __repr__(self) -> str:

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'rads': self._rads,
}

Expand Down Expand Up @@ -825,7 +823,6 @@ def __repr__(self) -> str:

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'rads': self._rads,
}

Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/controlled_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ def __repr__(self) -> str:

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'control_values': self.control_values,
'control_qid_shape': self.control_qid_shape,
'sub_gate': self.sub_gate,
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/controlled_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ def get_symbol(vals):

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'controls': self.controls,
'control_values': self.control_values,
'sub_operation': self.sub_operation,
Expand Down
2 changes: 0 additions & 2 deletions cirq-core/cirq/ops/fourier_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def __init__(self, num_qubits: int, *, without_reverse: bool = False):

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'num_qubits': self._num_qubits,
'without_reverse': self._without_reverse,
}
Expand Down Expand Up @@ -98,7 +97,6 @@ def __init__(self, *, num_qubits: int, exponent: Union[float, sympy.Basic]):

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'num_qubits': self._num_qubits,
'exponent': self.exponent,
}
Expand Down
2 changes: 0 additions & 2 deletions cirq-core/cirq/ops/fsim_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ def test_fsim_repr():

def test_fsim_json_dict():
assert cirq.FSimGate(theta=0.123, phi=0.456)._json_dict_() == {
'cirq_type': 'FSimGate',
'theta': 0.123,
'phi': 0.456,
}
Expand Down Expand Up @@ -799,7 +798,6 @@ def test_phased_fsim_json_dict():
assert cirq.PhasedFSimGate(
theta=0.12, zeta=0.34, chi=0.56, gamma=0.78, phi=0.9
)._json_dict_() == {
'cirq_type': 'PhasedFSimGate',
'theta': 0.12,
'zeta': 0.34,
'chi': 0.56,
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/global_phase_op_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,5 @@ def test_diagram():

def test_global_phase_op_json_dict():
assert cirq.GlobalPhaseOperation(-1j)._json_dict_() == {
'cirq_type': 'GlobalPhaseOperation',
'coefficient': -1j,
}
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ def _json_dict_(self) -> Dict[str, Any]:
if not all(d == 2 for d in self._qid_shape):
other['qid_shape'] = self._qid_shape
return {
'cirq_type': self.__class__.__name__,
'num_qubits': len(self._qid_shape),
**other,
}
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/linear_combinations.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,6 @@ def _json_dict_(self) -> Dict[str, Any]:
key = [[k, v] for k, v in dict(projector_dict).items()]
linear_dict.append([key, scalar])
return {
'cirq_type': self.__class__.__name__,
'linear_dict': linear_dict,
}

Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/matrix_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ def __init__(

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'matrix': self._matrix.tolist(),
'qid_shape': self._qid_shape,
}
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/measurement_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ def _json_dict_(self) -> Dict[str, Any]:
if not all(d == 2 for d in self._qid_shape):
other['qid_shape'] = self._qid_shape
return {
'cirq_type': self.__class__.__name__,
'num_qubits': len(self._qid_shape),
'key': self.key,
'invert_mask': self.invert_mask,
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/ops/moment_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def test_json_dict():
a = cirq.NamedQubit('a')
b = cirq.NamedQubit('b')
mom = cirq.Moment([cirq.CZ(a, b)])
assert mom._json_dict_() == {'cirq_type': 'Moment', 'operations': (cirq.CZ(a, b),)}
assert mom._json_dict_() == {'operations': (cirq.CZ(a, b),)}


def test_inverse():
Expand Down
2 changes: 0 additions & 2 deletions cirq-core/cirq/ops/named_qubit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,10 @@ def test_named_qid_range():

def test_to_json():
assert cirq.NamedQubit('c')._json_dict_() == {
'cirq_type': 'NamedQubit',
'name': 'c',
}

assert cirq.NamedQid('c', dimension=3)._json_dict_() == {
'cirq_type': 'NamedQid',
'name': 'c',
'dimension': 3,
}
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/pauli_measurement_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ def _value_equality_values_(self) -> Any:

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'observable': self._observable,
'key': self.key,
}
Expand Down
2 changes: 0 additions & 2 deletions cirq-core/cirq/ops/pauli_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ def _value_equality_values_(self):

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
# JSON requires mappings to have string keys.
'qubit_pauli_map': list(self._qubit_pauli_map.items()),
'coefficient': self.coefficient,
Expand Down Expand Up @@ -1294,7 +1293,6 @@ def inplace_left_multiply_by(

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
# JSON requires mappings to have string keys.
'pauli_int_dict': list(self.pauli_int_dict.items()),
'coefficient': self.coefficient,
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/permutation_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ def test_permutation_gate_diagram():

def test_permutation_gate_json_dict():
assert cirq.QubitPermutationGate([0, 1, 2])._json_dict_() == {
'cirq_type': 'QubitPermutationGate',
'permutation': (0, 1, 2),
}

Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/phased_iswap_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def _num_qubits_(self) -> int:

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'phase_exponent': self._phase_exponent,
'exponent': self._exponent,
}
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/projector.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ def __repr__(self) -> str:

def _json_dict_(self) -> Dict[str, Any]:
return {
'cirq_type': self.__class__.__name__,
'projector_dict': list(self._projector_dict.items()),
'coefficient': self._coefficient,
}
Expand Down
5 changes: 1 addition & 4 deletions cirq-core/cirq/ops/raw_types_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ def test_wrapped_qid():
assert str(ValidQubit('a').with_dimension(3)) == 'TQ_a (d=3)'

assert ValidQubit('zz').with_dimension(3)._json_dict_() == {
'cirq_type': '_QubitAsQid',
'qubit': ValidQubit('zz'),
'dimension': 3,
}
Expand Down Expand Up @@ -370,9 +369,7 @@ def _qid_shape_(self):

def test_gate_json_dict():
g = cirq.CSWAP # not an eigen gate (which has its own _json_dict_)
assert g._json_dict_() == {
'cirq_type': 'CSwapGate',
}
assert g._json_dict_() == {}


def test_inverse_composite_diagram_info():
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/state_preparation_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ def _has_unitary_(self) -> bool:
def _json_dict_(self) -> Dict[str, Any]:
"""Converts the gate object into a serializable dictionary"""
return {
'cirq_type': self.__class__.__name__,
'target_state': self._state.tolist(),
'name': self._name,
}
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/ops/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ def __repr__(self) -> str:
return 'cirq.VirtualTag()'

def _json_dict_(self) -> Dict[str, str]:
return {'cirq_type': self.__class__.__name__}
return {}
Loading

0 comments on commit 48397d6

Please sign in to comment.