diff --git a/cirq-core/cirq/ion/ion_gates.py b/cirq-core/cirq/ion/ion_gates.py index e9a461ab290..161cab3719d 100644 --- a/cirq-core/cirq/ion/ion_gates.py +++ b/cirq-core/cirq/ion/ion_gates.py @@ -14,7 +14,7 @@ """Operations native to iontrap systems.""" -from typing import Union, TYPE_CHECKING +from typing import Any, Dict, Union, TYPE_CHECKING import numpy as np from cirq import ops, value @@ -39,6 +39,7 @@ class MSGate(ops.XXPowGate): def __init__(self, *, rads: float): # Forces keyword args. ops.XXPowGate.__init__(self, exponent=rads * 2 / np.pi, global_shift=-0.5) + self.rads = rads def _with_exponent(self: 'MSGate', exponent: value.TParamVal) -> 'MSGate': return type(self)(rads=exponent * np.pi / 2) @@ -60,6 +61,13 @@ def __repr__(self) -> str: return 'cirq.ms(np.pi/2)' return f'cirq.ms({self._exponent!r}*np.pi/2)' + def _json_dict_(self) -> Dict[str, Any]: + return protocols.obj_to_dict_helper(self, ["rads"]) + + @classmethod + def _from_json_dict_(cls, rads: float, **kwargs: Any) -> 'MSGate': + return cls(rads=rads) + # TODO(#3388) Add summary line to docstring. # pylint: disable=docstring-first-line-empty diff --git a/cirq-core/cirq/ion/ion_gates_test.py b/cirq-core/cirq/ion/ion_gates_test.py index 9df490b4397..18a69c31850 100644 --- a/cirq-core/cirq/ion/ion_gates_test.py +++ b/cirq-core/cirq/ion/ion_gates_test.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - +from typing import Callable, Union import numpy as np import cirq @@ -66,3 +66,15 @@ def test_ms_diagrams(): b: ───×───────────MS(π)─── """, ) + + +def test_json_serialization(): + def custom_resolver(cirq_type: str) -> Union[Callable[..., cirq.Gate], None]: + if cirq_type == "MSGate": + return cirq.ion.ion_gates.MSGate + return None + + assert cirq.read_json( + json_text=cirq.to_json(cirq.ms(np.pi / 2)), resolvers=[custom_resolver] + ) == cirq.ms(np.pi / 2) + assert custom_resolver('X') == None