Skip to content

Commit 203035a

Browse files
maffootonybruguier
authored andcommitted
Deprecate json_serializable_dataclass (quantumlib#5208)
Fixes quantumlib#4460
1 parent 69a55dd commit 203035a

File tree

5 files changed

+63
-32
lines changed

5 files changed

+63
-32
lines changed

Diff for: cirq-core/cirq/experiments/cross_entropy_benchmarking.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def purity(self) -> float:
9898
return self.cycle_depolarization**2
9999

100100

101-
@protocols.json_serializable_dataclass(frozen=True)
101+
@dataclasses.dataclass(frozen=True)
102102
class CrossEntropyResult:
103103
"""Results from a cross-entropy benchmarking (XEB) experiment.
104104
@@ -208,6 +208,9 @@ def _from_json_dict_(cls, data, repetitions, **kwargs):
208208
purity_data=purity_data,
209209
)
210210

211+
def _json_dict_(self):
212+
return protocols.dataclass_json_dict(self)
213+
211214
def __repr__(self) -> str:
212215
args = f'data={[tuple(p) for p in self.data]!r}, repetitions={self.repetitions!r}'
213216
if self.purity_data is not None:

Diff for: cirq-core/cirq/experiments/grid_parallel_two_qubit_xeb.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
by executing circuits that act on many pairs simultaneously.
2121
"""
2222

23-
from typing import Any, Iterable, List, Optional, Sequence, TYPE_CHECKING, Tuple, cast
23+
from typing import Any, Dict, Iterable, List, Optional, Sequence, TYPE_CHECKING, Tuple, cast
2424
import collections
2525
from concurrent.futures import ThreadPoolExecutor
2626
import dataclasses
@@ -46,7 +46,6 @@
4646
)
4747

4848
if TYPE_CHECKING:
49-
from typing import Dict
5049
import cirq
5150

5251
DEFAULT_BASE_DIR = os.path.expanduser(
@@ -101,22 +100,25 @@ def load(params: Any, base_dir: str) -> Any:
101100
return protocols.read_json(filename)
102101

103102

104-
@protocols.json_serializable_dataclass
103+
@dataclasses.dataclass
105104
class GridParallelXEBMetadata:
106105
"""Metadata for a grid parallel XEB experiment.
107106
108107
Attributes:
109108
data_collection_id: The data collection ID of the experiment.
110109
"""
111110

112-
qubits: List['cirq.Qid']
111+
qubits: Sequence['cirq.Qid']
113112
two_qubit_gate: 'cirq.Gate'
114113
num_circuits: int
115114
repetitions: int
116-
cycles: List[int]
117-
layers: List[GridInteractionLayer]
115+
cycles: Sequence[int]
116+
layers: Sequence[GridInteractionLayer]
118117
seed: Optional[int]
119118

119+
def _json_dict_(self):
120+
return protocols.dataclass_json_dict(self)
121+
120122
def __repr__(self) -> str:
121123
return (
122124
'cirq.experiments.grid_parallel_two_qubit_xeb.'

Diff for: cirq-core/cirq/protocols/json_serialization.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
import sympy
4040
from typing_extensions import Protocol
4141

42-
from cirq._compat import deprecated_parameter
42+
from cirq._compat import deprecated, deprecated_parameter
4343
from cirq._doc import doc_private
4444
from cirq.type_workarounds import NotImplementedType
4545

@@ -190,6 +190,7 @@ class name via a dot (.)
190190

191191
# Copying the Python API, whose usage of `repr` annoys pylint.
192192
# pylint: disable=redefined-builtin
193+
@deprecated(deadline='v0.15', fix='Implement _json_dict_ using cirq.dataclass_json_dict()')
193194
def json_serializable_dataclass(
194195
_cls: Optional[Type] = None,
195196
*,

Diff for: cirq-core/cirq/protocols/json_serialization_test.py

+25-13
Original file line numberDiff line numberDiff line change
@@ -855,10 +855,14 @@ def test_pathlib_paths(tmpdir):
855855

856856

857857
def test_json_serializable_dataclass():
858-
@cirq.json_serializable_dataclass
859-
class MyDC:
860-
q: cirq.LineQubit
861-
desc: str
858+
with cirq.testing.assert_deprecated(
859+
"Implement _json_dict_ using cirq.dataclass_json_dict()", deadline="v0.15"
860+
):
861+
862+
@cirq.json_serializable_dataclass
863+
class MyDC:
864+
q: cirq.LineQubit
865+
desc: str
862866

863867
my_dc = MyDC(cirq.LineQubit(4), 'hi mom')
864868

@@ -885,10 +889,14 @@ def custom_resolver(name):
885889

886890

887891
def test_json_serializable_dataclass_parenthesis():
888-
@cirq.json_serializable_dataclass()
889-
class MyDC:
890-
q: cirq.LineQubit
891-
desc: str
892+
with cirq.testing.assert_deprecated(
893+
"Implement _json_dict_ using cirq.dataclass_json_dict()", deadline="v0.15"
894+
):
895+
896+
@cirq.json_serializable_dataclass()
897+
class MyDC:
898+
q: cirq.LineQubit
899+
desc: str
892900

893901
def custom_resolver(name):
894902
if name == 'MyDC':
@@ -918,11 +926,15 @@ def custom_resolver(name):
918926

919927

920928
def test_json_serializable_dataclass_namespace():
921-
@cirq.json_serializable_dataclass(namespace='cirq.experiments')
922-
class QuantumVolumeParams:
923-
width: int
924-
depth: int
925-
circuit_i: int
929+
with cirq.testing.assert_deprecated(
930+
"Implement _json_dict_ using cirq.dataclass_json_dict()", deadline="v0.15"
931+
):
932+
933+
@cirq.json_serializable_dataclass(namespace='cirq.experiments')
934+
class QuantumVolumeParams:
935+
width: int
936+
depth: int
937+
circuit_i: int
926938

927939
qvp = QuantumVolumeParams(width=5, depth=5, circuit_i=0)
928940

Diff for: cirq-google/cirq_google/calibration/phased_fsim.py

+24-11
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,6 @@
4747
if TYPE_CHECKING:
4848
import cirq_google
4949

50-
# Workaround for mypy custom dataclasses (python/mypy#5406)
51-
from dataclasses import dataclass as json_serializable_dataclass
52-
else:
53-
from cirq.protocols import json_serializable_dataclass
54-
5550

5651
_FLOQUET_PHASED_FSIM_HANDLER_NAME = 'floquet_phased_fsim_characterization'
5752
_XEB_PHASED_FSIM_HANDLER_NAME = 'xeb_phased_fsim_characterization'
@@ -94,7 +89,7 @@ def _create_pairs_from_moment(
9489
return tuple(pairs), gate
9590

9691

97-
@json_serializable_dataclass(frozen=True)
92+
@dataclasses.dataclass(frozen=True)
9893
class PhasedFSimCharacterization:
9994
"""Holder for the unitary angles of the cirq.PhasedFSimGate.
10095
@@ -202,6 +197,9 @@ def override_by(self, other: 'PhasedFSimCharacterization') -> 'PhasedFSimCharact
202197
"""
203198
return other.merge_with(self)
204199

200+
def _json_dict_(self):
201+
return cirq.dataclass_json_dict(self)
202+
205203

206204
SQRT_ISWAP_INV_PARAMETERS = PhasedFSimCharacterization(
207205
theta=np.pi / 4, zeta=0.0, chi=0.0, gamma=0.0, phi=0.0
@@ -429,7 +427,7 @@ def parse_result(
429427
"""Decodes the characterization result issued for this request."""
430428

431429

432-
@json_serializable_dataclass(frozen=True)
430+
@dataclasses.dataclass(frozen=True)
433431
class XEBPhasedFSimCalibrationOptions(PhasedFSimCalibrationOptions):
434432
"""Options for configuring a PhasedFSim calibration using XEB.
435433
@@ -496,8 +494,11 @@ def _from_json_dict_(cls, **kwargs):
496494
kwargs['cycle_depths'] = tuple(kwargs['cycle_depths'])
497495
return cls(**kwargs)
498496

497+
def _json_dict_(self):
498+
return cirq.dataclass_json_dict(self)
499499

500-
@json_serializable_dataclass(frozen=True)
500+
501+
@dataclasses.dataclass(frozen=True)
501502
class LocalXEBPhasedFSimCalibrationOptions(XEBPhasedFSimCalibrationOptions):
502503
"""Options for configuring a PhasedFSim calibration using a local version of XEB.
503504
@@ -542,8 +543,11 @@ def create_phased_fsim_request(
542543
):
543544
return LocalXEBPhasedFSimCalibrationRequest(pairs=pairs, gate=gate, options=self)
544545

546+
def _json_dict_(self):
547+
return cirq.dataclass_json_dict(self)
548+
545549

546-
@json_serializable_dataclass(frozen=True)
550+
@dataclasses.dataclass(frozen=True)
547551
class FloquetPhasedFSimCalibrationOptions(PhasedFSimCalibrationOptions):
548552
"""Options specific to Floquet PhasedFSimCalibration.
549553
@@ -590,6 +594,9 @@ def create_phased_fsim_request(
590594
) -> 'FloquetPhasedFSimCalibrationRequest':
591595
return FloquetPhasedFSimCalibrationRequest(pairs=pairs, gate=gate, options=self)
592596

597+
def _json_dict_(self):
598+
return cirq.dataclass_json_dict(self)
599+
593600

594601
"""Floquet PhasedFSimCalibrationOptions options with all angles characterization requests set to
595602
True."""
@@ -821,7 +828,7 @@ def _parse_characterized_angles(
821828
return dict(records)
822829

823830

824-
@json_serializable_dataclass(frozen=True)
831+
@dataclasses.dataclass(frozen=True)
825832
class LocalXEBPhasedFSimCalibrationRequest(PhasedFSimCalibrationRequest):
826833
"""PhasedFSim characterization request for local cross entropy benchmarking (XEB) calibration.
827834
@@ -856,8 +863,11 @@ def _from_json_dict_(
856863
instantiation_pairs = tuple((q_a, q_b) for q_a, q_b in pairs)
857864
return cls(instantiation_pairs, gate, options)
858865

866+
def _json_dict_(self):
867+
return cirq.dataclass_json_dict(self)
859868

860-
@json_serializable_dataclass(frozen=True)
869+
870+
@dataclasses.dataclass(frozen=True)
861871
class XEBPhasedFSimCalibrationRequest(PhasedFSimCalibrationRequest):
862872
"""PhasedFSim characterization request for cross entropy benchmarking (XEB) calibration.
863873
@@ -915,6 +925,9 @@ def _from_json_dict_(
915925
instantiation_pairs = tuple((q_a, q_b) for q_a, q_b in pairs)
916926
return cls(instantiation_pairs, gate, options)
917927

928+
def _json_dict_(self):
929+
return cirq.dataclass_json_dict(self)
930+
918931

919932
class IncompatibleMomentError(Exception):
920933
"""Error that occurs when a moment is not supported by a calibration routine."""

0 commit comments

Comments
 (0)