cirq-core 1.3.0.dev20231201164435__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cirq/__init__.py +4 -0
- cirq/_compat.py +9 -11
- cirq/_compat_test.py +45 -56
- cirq/_version.py +31 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/circuit.py +13 -8
- cirq/circuits/circuit_operation.py +2 -1
- cirq/circuits/circuit_test.py +2 -2
- cirq/circuits/frozen_circuit.py +3 -2
- cirq/circuits/moment.py +12 -10
- cirq/circuits/qasm_output.py +5 -1
- cirq/circuits/qasm_output_test.py +25 -10
- cirq/contrib/qcircuit/qcircuit_diagram_info.py +9 -7
- cirq/contrib/quimb/mps_simulator_test.py +1 -1
- cirq/contrib/quimb/state_vector.py +9 -2
- cirq/contrib/svg/svg.py +2 -1
- cirq/contrib/svg/svg_test.py +1 -0
- cirq/devices/grid_qubit.py +85 -32
- cirq/devices/grid_qubit_test.py +22 -4
- cirq/devices/line_qubit.py +74 -26
- cirq/devices/line_qubit_test.py +19 -0
- cirq/devices/noise_utils.py +33 -31
- cirq/devices/noise_utils_test.py +1 -84
- cirq/devices/superconducting_qubits_noise_properties.py +7 -6
- cirq/experiments/__init__.py +8 -0
- cirq/experiments/qubit_characterizations.py +288 -44
- cirq/experiments/qubit_characterizations_test.py +61 -7
- cirq/experiments/random_quantum_circuit_generation.py +1 -1
- cirq/experiments/single_qubit_readout_calibration.py +132 -6
- cirq/experiments/single_qubit_readout_calibration_test.py +3 -1
- cirq/experiments/t1_decay_experiment.py +14 -7
- cirq/experiments/t1_decay_experiment_test.py +14 -26
- cirq/experiments/two_qubit_xeb.py +483 -0
- cirq/experiments/two_qubit_xeb_test.py +304 -0
- cirq/json_resolver_cache.py +2 -0
- cirq/linalg/decompositions.py +11 -13
- cirq/linalg/decompositions_test.py +1 -3
- cirq/linalg/diagonalize.py +5 -4
- cirq/linalg/predicates.py +8 -6
- cirq/linalg/transformations.py +2 -1
- cirq/linalg/transformations_test.py +1 -1
- cirq/ops/__init__.py +2 -0
- cirq/ops/clifford_gate.py +59 -16
- cirq/ops/common_gates_test.py +1 -2
- cirq/ops/control_values.py +4 -3
- cirq/ops/controlled_gate_test.py +1 -3
- cirq/ops/gate_operation.py +10 -1
- cirq/ops/named_qubit.py +74 -28
- cirq/ops/named_qubit_test.py +19 -0
- cirq/ops/parity_gates.py +5 -0
- cirq/ops/parity_gates_test.py +2 -10
- cirq/ops/pauli_gates.py +5 -2
- cirq/ops/pauli_string.py +2 -2
- cirq/ops/permutation_gate.py +16 -18
- cirq/ops/phased_iswap_gate_test.py +1 -3
- cirq/ops/phased_x_gate.py +1 -1
- cirq/ops/phased_x_z_gate.py +17 -1
- cirq/ops/phased_x_z_gate_test.py +24 -0
- cirq/ops/qid_util.py +4 -8
- cirq/ops/qubit_manager.py +7 -4
- cirq/ops/qubit_manager_test.py +20 -0
- cirq/ops/raw_types.py +5 -2
- cirq/ops/raw_types_test.py +14 -15
- cirq/ops/uniform_superposition_gate.py +123 -0
- cirq/ops/uniform_superposition_gate_test.py +94 -0
- cirq/protocols/approximate_equality_protocol_test.py +2 -2
- cirq/protocols/circuit_diagram_info_protocol.py +6 -4
- cirq/protocols/commutes_protocol.py +2 -4
- cirq/protocols/decompose_protocol.py +7 -12
- cirq/protocols/decompose_protocol_test.py +7 -3
- cirq/protocols/has_stabilizer_effect_protocol.py +1 -5
- cirq/protocols/has_stabilizer_effect_protocol_test.py +13 -4
- cirq/protocols/json_serialization.py +51 -181
- cirq/protocols/json_serialization_test.py +13 -47
- cirq/protocols/json_test_data/CircuitOperation.json +131 -148
- cirq/protocols/json_test_data/CircuitOperation.json_inward +55 -0
- cirq/protocols/json_test_data/CircuitOperation.repr_inward +6 -0
- cirq/protocols/json_test_data/FrozenCircuit.json +196 -210
- cirq/protocols/json_test_data/FrozenCircuit.json_inward +35 -0
- cirq/protocols/json_test_data/FrozenCircuit.repr_inward +4 -0
- cirq/protocols/json_test_data/UniformSuperpositionGate.json +5 -0
- cirq/protocols/json_test_data/UniformSuperpositionGate.repr +1 -0
- cirq/protocols/json_test_data/cirq.MSGate.json +4 -0
- cirq/protocols/json_test_data/cirq.MSGate.repr +1 -0
- cirq/protocols/json_test_data/spec.py +2 -0
- cirq/protocols/pow_protocol_test.py +1 -3
- cirq/protocols/resolve_parameters.py +4 -2
- cirq/qis/__init__.py +10 -0
- cirq/qis/clifford_tableau.py +8 -2
- cirq/qis/noise_utils.py +123 -0
- cirq/qis/noise_utils_test.py +97 -0
- cirq/sim/classical_simulator.py +227 -87
- cirq/sim/classical_simulator_test.py +135 -0
- cirq/sim/clifford/clifford_simulator_test.py +4 -2
- cirq/sim/mux.py +5 -3
- cirq/sim/simulation_product_state.py +15 -10
- cirq/sim/simulation_state.py +1 -1
- cirq/sim/simulation_state_test.py +2 -2
- cirq/sim/simulator_base.py +3 -3
- cirq/sim/state_vector_simulation_state.py +4 -4
- cirq/sim/state_vector_simulator.py +17 -2
- cirq/study/__init__.py +1 -0
- cirq/study/result.py +14 -0
- cirq/study/result_test.py +6 -0
- cirq/study/sweeps.py +4 -2
- cirq/study/sweeps_test.py +8 -0
- cirq/testing/__init__.py +6 -1
- cirq/testing/_compat_test_data/__init__.py +3 -3
- cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
- cirq/testing/circuit_compare.py +1 -1
- cirq/testing/consistent_qasm.py +6 -0
- cirq/testing/gate_features.py +10 -0
- cirq/testing/lin_alg_utils.py +5 -3
- cirq/transformers/__init__.py +15 -0
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +3 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +24 -0
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +17 -0
- cirq/transformers/dynamical_decoupling.py +122 -0
- cirq/transformers/dynamical_decoupling_test.py +123 -0
- cirq/transformers/gauge_compiling/__init__.py +26 -0
- cirq/transformers/gauge_compiling/cz_gauge.py +46 -0
- cirq/transformers/gauge_compiling/cz_gauge_test.py +23 -0
- cirq/transformers/gauge_compiling/gauge_compiling.py +214 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +41 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +83 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +52 -0
- cirq/transformers/gauge_compiling/iswap_gauge.py +105 -0
- cirq/transformers/gauge_compiling/iswap_gauge_test.py +23 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge.py +33 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge_test.py +37 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +64 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge_test.py +27 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +94 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge_test.py +22 -0
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +1 -0
- cirq/transformers/merge_k_qubit_gates_test.py +23 -23
- cirq/transformers/merge_single_qubit_gates_test.py +14 -14
- cirq/transformers/optimize_for_target_gateset.py +39 -17
- cirq/transformers/optimize_for_target_gateset_test.py +189 -39
- cirq/transformers/qubit_management_transformers.py +1 -1
- cirq/transformers/routing/visualize_routed_circuit_test.py +17 -17
- cirq/transformers/stratify_test.py +13 -13
- cirq/transformers/target_gatesets/compilation_target_gateset.py +26 -2
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +16 -16
- cirq/transformers/target_gatesets/cz_gateset.py +4 -0
- cirq/transformers/transformer_api.py +1 -2
- cirq/transformers/transformer_primitives.py +15 -14
- cirq/transformers/transformer_primitives_test.py +99 -72
- cirq/value/classical_data.py +6 -6
- cirq/value/value_equality_attr.py +4 -0
- cirq/work/sampler.py +3 -4
- cirq/work/sampler_test.py +25 -0
- {cirq_core-1.3.0.dev20231201164435.dist-info → cirq_core-1.4.0.dist-info}/METADATA +10 -19
- {cirq_core-1.3.0.dev20231201164435.dist-info → cirq_core-1.4.0.dist-info}/RECORD +157 -130
- {cirq_core-1.3.0.dev20231201164435.dist-info → cirq_core-1.4.0.dist-info}/WHEEL +1 -1
- {cirq_core-1.3.0.dev20231201164435.dist-info → cirq_core-1.4.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.3.0.dev20231201164435.dist-info → cirq_core-1.4.0.dist-info}/top_level.txt +0 -0
|
@@ -28,7 +28,6 @@ from typing import (
|
|
|
28
28
|
Optional,
|
|
29
29
|
overload,
|
|
30
30
|
Sequence,
|
|
31
|
-
Set,
|
|
32
31
|
Tuple,
|
|
33
32
|
Type,
|
|
34
33
|
Union,
|
|
@@ -48,8 +47,7 @@ ObjectFactory = Union[Type, Callable[..., Any]]
|
|
|
48
47
|
class JsonResolver(Protocol):
|
|
49
48
|
"""Protocol for json resolver functions passed to read_json."""
|
|
50
49
|
|
|
51
|
-
def __call__(self, cirq_type: str) -> Optional[ObjectFactory]:
|
|
52
|
-
...
|
|
50
|
+
def __call__(self, cirq_type: str) -> Optional[ObjectFactory]: ...
|
|
53
51
|
|
|
54
52
|
|
|
55
53
|
def _lazy_resolver(dict_factory: Callable[[], Dict[str, ObjectFactory]]) -> JsonResolver:
|
|
@@ -221,10 +219,22 @@ class CirqEncoder(json.JSONEncoder):
|
|
|
221
219
|
See https://github.com/quantumlib/Cirq/issues/2014
|
|
222
220
|
"""
|
|
223
221
|
|
|
222
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
223
|
+
super().__init__(*args, **kwargs)
|
|
224
|
+
self._memo: dict[Any, dict] = {}
|
|
225
|
+
|
|
224
226
|
def default(self, o):
|
|
225
227
|
# Object with custom method?
|
|
226
228
|
if hasattr(o, '_json_dict_'):
|
|
227
|
-
|
|
229
|
+
json_dict = _json_dict_with_cirq_type(o)
|
|
230
|
+
if isinstance(o, SerializableByKey):
|
|
231
|
+
if ref := self._memo.get(o):
|
|
232
|
+
return ref
|
|
233
|
+
key = len(self._memo)
|
|
234
|
+
ref = {"cirq_type": "REF", "key": key}
|
|
235
|
+
self._memo[o] = ref
|
|
236
|
+
return {"cirq_type": "VAL", "key": key, "val": json_dict}
|
|
237
|
+
return json_dict
|
|
228
238
|
|
|
229
239
|
# Sympy object? (Must come before general number checks.)
|
|
230
240
|
# TODO: More support for sympy
|
|
@@ -306,27 +316,46 @@ class CirqEncoder(json.JSONEncoder):
|
|
|
306
316
|
return super().default(o) # pragma: no cover
|
|
307
317
|
|
|
308
318
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
319
|
+
class ObjectHook:
|
|
320
|
+
"""Callable to be used as object_hook during deserialization."""
|
|
321
|
+
|
|
322
|
+
LEGACY_CONTEXT_TYPES = {'_ContextualSerialization', '_SerializedKey', '_SerializedContext'}
|
|
323
|
+
|
|
324
|
+
def __init__(self, resolvers: Sequence[JsonResolver]) -> None:
|
|
325
|
+
self.resolvers = resolvers
|
|
326
|
+
self.memo: Dict[int, SerializableByKey] = {}
|
|
327
|
+
self.context_map: Dict[int, SerializableByKey] = {}
|
|
312
328
|
|
|
313
|
-
|
|
314
|
-
|
|
329
|
+
def __call__(self, d):
|
|
330
|
+
cirq_type = d.get('cirq_type')
|
|
331
|
+
if cirq_type is None:
|
|
332
|
+
return d
|
|
315
333
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
334
|
+
if cirq_type == 'VAL':
|
|
335
|
+
obj = d['val']
|
|
336
|
+
self.memo[d['key']] = obj
|
|
337
|
+
return obj
|
|
319
338
|
|
|
320
|
-
|
|
321
|
-
|
|
339
|
+
if cirq_type == 'REF':
|
|
340
|
+
return self.memo[d['key']]
|
|
322
341
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
342
|
+
# Deserialize from legacy "contextual serialization" format
|
|
343
|
+
if cirq_type in self.LEGACY_CONTEXT_TYPES:
|
|
344
|
+
if cirq_type == '_SerializedKey':
|
|
345
|
+
return self.context_map[d['key']]
|
|
346
|
+
if cirq_type == '_SerializedContext':
|
|
347
|
+
self.context_map[d['key']] = d['obj']
|
|
348
|
+
return None
|
|
349
|
+
if cirq_type == '_ContextualSerialization':
|
|
350
|
+
return d['object_dag'][-1]
|
|
327
351
|
|
|
328
|
-
|
|
329
|
-
|
|
352
|
+
cls = factory_from_json(cirq_type, resolvers=self.resolvers)
|
|
353
|
+
from_json_dict = getattr(cls, '_from_json_dict_', None)
|
|
354
|
+
if from_json_dict is not None:
|
|
355
|
+
return from_json_dict(**d)
|
|
356
|
+
|
|
357
|
+
del d['cirq_type']
|
|
358
|
+
return cls(**d)
|
|
330
359
|
|
|
331
360
|
|
|
332
361
|
class SerializableByKey(SupportsJSON):
|
|
@@ -338,137 +367,6 @@ class SerializableByKey(SupportsJSON):
|
|
|
338
367
|
"""
|
|
339
368
|
|
|
340
369
|
|
|
341
|
-
class _SerializedKey(SupportsJSON):
|
|
342
|
-
"""Internal object for holding a SerializableByKey key.
|
|
343
|
-
|
|
344
|
-
This is a private type used in contextual serialization. Its deserialization
|
|
345
|
-
is context-dependent, and is not expected to match the original; in other
|
|
346
|
-
words, `cls._from_json_dict_(obj._json_dict_())` does not return
|
|
347
|
-
the original `obj` for this type.
|
|
348
|
-
"""
|
|
349
|
-
|
|
350
|
-
def __init__(self, key: str):
|
|
351
|
-
self.key = key
|
|
352
|
-
|
|
353
|
-
def _json_dict_(self):
|
|
354
|
-
return obj_to_dict_helper(self, ['key'])
|
|
355
|
-
|
|
356
|
-
@classmethod
|
|
357
|
-
def _from_json_dict_(cls, **kwargs):
|
|
358
|
-
raise TypeError(f'Internal error: {cls} should never deserialize with _from_json_dict_.')
|
|
359
|
-
|
|
360
|
-
@classmethod
|
|
361
|
-
def read_from_context(cls, context_map, key, **kwargs):
|
|
362
|
-
return context_map[key]
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
class _SerializedContext(SupportsJSON):
|
|
366
|
-
"""Internal object for a single SerializableByKey key-to-object mapping.
|
|
367
|
-
|
|
368
|
-
This is a private type used in contextual serialization. Its deserialization
|
|
369
|
-
is context-dependent, and is not expected to match the original; in other
|
|
370
|
-
words, `cls._from_json_dict_(obj._json_dict_())` does not return
|
|
371
|
-
the original `obj` for this type.
|
|
372
|
-
"""
|
|
373
|
-
|
|
374
|
-
def __init__(self, obj: SerializableByKey, uid: int):
|
|
375
|
-
self.key = uid
|
|
376
|
-
self.obj = obj
|
|
377
|
-
|
|
378
|
-
def _json_dict_(self):
|
|
379
|
-
return obj_to_dict_helper(self, ['key', 'obj'])
|
|
380
|
-
|
|
381
|
-
@classmethod
|
|
382
|
-
def _from_json_dict_(cls, **kwargs):
|
|
383
|
-
raise TypeError(f'Internal error: {cls} should never deserialize with _from_json_dict_.')
|
|
384
|
-
|
|
385
|
-
@classmethod
|
|
386
|
-
def update_context(cls, context_map, key, obj, **kwargs):
|
|
387
|
-
context_map.update({key: obj})
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
class _ContextualSerialization(SupportsJSON):
|
|
391
|
-
"""Internal object for serializing an object with its context.
|
|
392
|
-
|
|
393
|
-
This is a private type used in contextual serialization. Its deserialization
|
|
394
|
-
is context-dependent, and is not expected to match the original; in other
|
|
395
|
-
words, `cls._from_json_dict_(obj._json_dict_())` does not return
|
|
396
|
-
the original `obj` for this type.
|
|
397
|
-
"""
|
|
398
|
-
|
|
399
|
-
def __init__(self, obj: Any):
|
|
400
|
-
# Context information and the wrapped object are stored together in
|
|
401
|
-
# `object_dag` to ensure consistent serialization ordering.
|
|
402
|
-
self.object_dag = []
|
|
403
|
-
context = []
|
|
404
|
-
for sbk in get_serializable_by_keys(obj):
|
|
405
|
-
if sbk not in context:
|
|
406
|
-
context.append(sbk)
|
|
407
|
-
new_sc = _SerializedContext(sbk, len(context))
|
|
408
|
-
self.object_dag.append(new_sc)
|
|
409
|
-
self.object_dag += [obj]
|
|
410
|
-
|
|
411
|
-
def _json_dict_(self):
|
|
412
|
-
return obj_to_dict_helper(self, ['object_dag'])
|
|
413
|
-
|
|
414
|
-
@classmethod
|
|
415
|
-
def _from_json_dict_(cls, **kwargs):
|
|
416
|
-
raise TypeError(f'Internal error: {cls} should never deserialize with _from_json_dict_.')
|
|
417
|
-
|
|
418
|
-
@classmethod
|
|
419
|
-
def deserialize_with_context(cls, object_dag, **kwargs):
|
|
420
|
-
# The last element of object_dag is the object to be deserialized.
|
|
421
|
-
return object_dag[-1]
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
def has_serializable_by_keys(obj: Any) -> bool:
|
|
425
|
-
"""Returns true if obj contains one or more SerializableByKey objects."""
|
|
426
|
-
if isinstance(obj, SerializableByKey):
|
|
427
|
-
return True
|
|
428
|
-
json_dict = getattr(obj, '_json_dict_', lambda: None)()
|
|
429
|
-
if isinstance(json_dict, Dict):
|
|
430
|
-
return any(has_serializable_by_keys(v) for v in json_dict.values())
|
|
431
|
-
|
|
432
|
-
# Handle primitive container types.
|
|
433
|
-
if isinstance(obj, Dict):
|
|
434
|
-
return any(has_serializable_by_keys(elem) for pair in obj.items() for elem in pair)
|
|
435
|
-
|
|
436
|
-
if hasattr(obj, '__iter__') and not isinstance(obj, str):
|
|
437
|
-
# Return False on TypeError because some numpy values
|
|
438
|
-
# (like np.array(1)) have iterable methods
|
|
439
|
-
# yet return a TypeError when there is an attempt to iterate over them
|
|
440
|
-
try:
|
|
441
|
-
return any(has_serializable_by_keys(elem) for elem in obj)
|
|
442
|
-
except TypeError:
|
|
443
|
-
return False
|
|
444
|
-
return False
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
def get_serializable_by_keys(obj: Any) -> List[SerializableByKey]:
|
|
448
|
-
"""Returns all SerializableByKeys contained by obj.
|
|
449
|
-
|
|
450
|
-
Objects are ordered such that nested objects appear before the object they
|
|
451
|
-
are nested inside. This is required to ensure SerializableByKeys are only
|
|
452
|
-
fully defined once in serialization.
|
|
453
|
-
"""
|
|
454
|
-
result = []
|
|
455
|
-
if isinstance(obj, SerializableByKey):
|
|
456
|
-
result.append(obj)
|
|
457
|
-
json_dict = getattr(obj, '_json_dict_', lambda: None)()
|
|
458
|
-
if isinstance(json_dict, Dict):
|
|
459
|
-
for v in json_dict.values():
|
|
460
|
-
result = get_serializable_by_keys(v) + result
|
|
461
|
-
if result:
|
|
462
|
-
return result
|
|
463
|
-
|
|
464
|
-
# Handle primitive container types.
|
|
465
|
-
if isinstance(obj, Dict):
|
|
466
|
-
return [sbk for pair in obj.items() for sbk in get_serializable_by_keys(pair)]
|
|
467
|
-
if hasattr(obj, '__iter__') and not isinstance(obj, str):
|
|
468
|
-
return [sbk for v in obj for sbk in get_serializable_by_keys(v)]
|
|
469
|
-
return []
|
|
470
|
-
|
|
471
|
-
|
|
472
370
|
def json_namespace(type_obj: Type) -> str:
|
|
473
371
|
"""Returns a namespace for JSON serialization of `type_obj`.
|
|
474
372
|
|
|
@@ -610,37 +508,12 @@ def to_json(
|
|
|
610
508
|
party classes, prefer adding the `_json_dict_` magic method
|
|
611
509
|
to your classes rather than overriding this default.
|
|
612
510
|
"""
|
|
613
|
-
if has_serializable_by_keys(obj):
|
|
614
|
-
obj = _ContextualSerialization(obj)
|
|
615
|
-
|
|
616
|
-
class ContextualEncoder(cls): # type: ignore
|
|
617
|
-
"""An encoder with a context map for concise serialization."""
|
|
618
|
-
|
|
619
|
-
# These lists populate gradually during serialization. An object
|
|
620
|
-
# with components defined in 'context' will represent those
|
|
621
|
-
# components using their keys instead of inline definition.
|
|
622
|
-
seen: Set[str] = set()
|
|
623
|
-
|
|
624
|
-
def default(self, o):
|
|
625
|
-
if not isinstance(o, SerializableByKey):
|
|
626
|
-
return super().default(o)
|
|
627
|
-
for candidate in obj.object_dag[:-1]:
|
|
628
|
-
if candidate.obj == o:
|
|
629
|
-
if not candidate.key in ContextualEncoder.seen:
|
|
630
|
-
ContextualEncoder.seen.add(candidate.key)
|
|
631
|
-
return _json_dict_with_cirq_type(candidate.obj)
|
|
632
|
-
else:
|
|
633
|
-
return _json_dict_with_cirq_type(_SerializedKey(candidate.key))
|
|
634
|
-
raise ValueError("Object mutated during serialization.") # pragma: no cover
|
|
635
|
-
|
|
636
|
-
cls = ContextualEncoder
|
|
637
|
-
|
|
638
511
|
if file_or_fn is None:
|
|
639
512
|
return json.dumps(obj, indent=indent, separators=separators, cls=cls)
|
|
640
513
|
|
|
641
514
|
if isinstance(file_or_fn, (str, pathlib.Path)):
|
|
642
515
|
with open(file_or_fn, 'w') as actually_a_file:
|
|
643
|
-
json.dump(obj, actually_a_file, indent=indent, cls=cls)
|
|
516
|
+
json.dump(obj, actually_a_file, indent=indent, separators=separators, cls=cls)
|
|
644
517
|
return None
|
|
645
518
|
|
|
646
519
|
json.dump(obj, file_or_fn, indent=indent, separators=separators, cls=cls)
|
|
@@ -682,10 +555,7 @@ def read_json(
|
|
|
682
555
|
if resolvers is None:
|
|
683
556
|
resolvers = DEFAULT_RESOLVERS
|
|
684
557
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
def obj_hook(x):
|
|
688
|
-
return _cirq_object_hook(x, resolvers, context_map)
|
|
558
|
+
obj_hook = ObjectHook(resolvers)
|
|
689
559
|
|
|
690
560
|
if json_text is not None:
|
|
691
561
|
return json.loads(json_text, object_hook=obj_hook)
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
14
15
|
import contextlib
|
|
15
16
|
import dataclasses
|
|
16
17
|
import datetime
|
|
@@ -19,7 +20,6 @@ import io
|
|
|
19
20
|
import json
|
|
20
21
|
import os
|
|
21
22
|
import pathlib
|
|
22
|
-
import sys
|
|
23
23
|
import warnings
|
|
24
24
|
from typing import Dict, List, Optional, Tuple, Type
|
|
25
25
|
from unittest import mock
|
|
@@ -56,12 +56,6 @@ TESTED_MODULES: Dict[str, Optional[_ModuleDeprecation]] = {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
# pyQuil 3.0, necessary for cirq_rigetti module requires
|
|
60
|
-
# python >= 3.9
|
|
61
|
-
if sys.version_info < (3, 9): # pragma: no cover
|
|
62
|
-
del TESTED_MODULES['cirq_rigetti']
|
|
63
|
-
|
|
64
|
-
|
|
65
59
|
def _get_testspecs_for_modules() -> List[ModuleJsonTestSpec]:
|
|
66
60
|
modules = []
|
|
67
61
|
for m in TESTED_MODULES.keys():
|
|
@@ -237,7 +231,7 @@ def test_not_yet_serializable_no_superfluous(mod_spec: ModuleJsonTestSpec):
|
|
|
237
231
|
|
|
238
232
|
|
|
239
233
|
@pytest.mark.parametrize('mod_spec', MODULE_TEST_SPECS, ids=repr)
|
|
240
|
-
def
|
|
234
|
+
def test_mutually_exclusive_not_serialize_lists(mod_spec: ModuleJsonTestSpec):
|
|
241
235
|
common = set(mod_spec.should_not_be_serialized) & set(mod_spec.not_yet_serializable)
|
|
242
236
|
assert len(common) == 0, (
|
|
243
237
|
f"Defined in both {mod_spec.name} 'Not yet serializable' "
|
|
@@ -373,6 +367,11 @@ class SBKImpl(cirq.SerializableByKey):
|
|
|
373
367
|
and self.data_dict == other.data_dict
|
|
374
368
|
)
|
|
375
369
|
|
|
370
|
+
def __hash__(self):
|
|
371
|
+
return hash(
|
|
372
|
+
(self.name, tuple(self.data_list), self.data_tuple, frozenset(self.data_dict.items()))
|
|
373
|
+
)
|
|
374
|
+
|
|
376
375
|
def _json_dict_(self):
|
|
377
376
|
return {
|
|
378
377
|
"name": self.name,
|
|
@@ -386,12 +385,12 @@ class SBKImpl(cirq.SerializableByKey):
|
|
|
386
385
|
return cls(name, data_list, tuple(data_tuple), data_dict)
|
|
387
386
|
|
|
388
387
|
|
|
389
|
-
def
|
|
388
|
+
def test_serializable_by_key():
|
|
390
389
|
def custom_resolver(name):
|
|
391
390
|
if name == 'SBKImpl':
|
|
392
391
|
return SBKImpl
|
|
393
392
|
|
|
394
|
-
test_resolvers = [custom_resolver
|
|
393
|
+
test_resolvers = [custom_resolver, *cirq.DEFAULT_RESOLVERS]
|
|
395
394
|
|
|
396
395
|
sbki_empty = SBKImpl('sbki_empty')
|
|
397
396
|
assert_json_roundtrip_works(sbki_empty, resolvers=test_resolvers)
|
|
@@ -406,21 +405,10 @@ def test_context_serialization():
|
|
|
406
405
|
assert_json_roundtrip_works(sbki_dict, resolvers=test_resolvers)
|
|
407
406
|
|
|
408
407
|
sbki_json = str(cirq.to_json(sbki_dict))
|
|
409
|
-
# There
|
|
410
|
-
assert sbki_json.count('"cirq_type": "
|
|
411
|
-
# There
|
|
412
|
-
|
|
413
|
-
assert sbki_json.count('"cirq_type": "_SerializedKey"') == 7
|
|
414
|
-
# The final object should be a _SerializedKey for sbki_dict.
|
|
415
|
-
final_obj_idx = sbki_json.rfind('{')
|
|
416
|
-
final_obj = sbki_json[final_obj_idx : sbki_json.find('}', final_obj_idx) + 1]
|
|
417
|
-
assert (
|
|
418
|
-
final_obj
|
|
419
|
-
== """{
|
|
420
|
-
"cirq_type": "_SerializedKey",
|
|
421
|
-
"key": 4
|
|
422
|
-
}"""
|
|
423
|
-
)
|
|
408
|
+
# There are 4 SBKImpl instances, one each for empty, list, tuple, dict.
|
|
409
|
+
assert sbki_json.count('"cirq_type": "VAL"') == 4
|
|
410
|
+
# There are 3 SBKImpl refs, one each for empty, list, and tuple.
|
|
411
|
+
assert sbki_json.count('"cirq_type": "REF"') == 3
|
|
424
412
|
|
|
425
413
|
list_sbki = [sbki_dict]
|
|
426
414
|
assert_json_roundtrip_works(list_sbki, resolvers=test_resolvers)
|
|
@@ -428,33 +416,11 @@ def test_context_serialization():
|
|
|
428
416
|
dict_sbki = {'a': sbki_dict}
|
|
429
417
|
assert_json_roundtrip_works(dict_sbki, resolvers=test_resolvers)
|
|
430
418
|
|
|
431
|
-
assert sbki_list != json_serialization._SerializedKey(sbki_list)
|
|
432
|
-
|
|
433
419
|
# Serialization keys have unique suffixes.
|
|
434
420
|
sbki_other_list = SBKImpl('sbki_list', data_list=[sbki_list])
|
|
435
421
|
assert_json_roundtrip_works(sbki_other_list, resolvers=test_resolvers)
|
|
436
422
|
|
|
437
423
|
|
|
438
|
-
def test_internal_serializer_types():
|
|
439
|
-
sbki = SBKImpl('test_key')
|
|
440
|
-
key = 1
|
|
441
|
-
test_key = json_serialization._SerializedKey(key)
|
|
442
|
-
test_context = json_serialization._SerializedContext(sbki, 1)
|
|
443
|
-
test_serialization = json_serialization._ContextualSerialization(sbki)
|
|
444
|
-
|
|
445
|
-
key_json = test_key._json_dict_()
|
|
446
|
-
with pytest.raises(TypeError, match='_from_json_dict_'):
|
|
447
|
-
_ = json_serialization._SerializedKey._from_json_dict_(**key_json)
|
|
448
|
-
|
|
449
|
-
context_json = test_context._json_dict_()
|
|
450
|
-
with pytest.raises(TypeError, match='_from_json_dict_'):
|
|
451
|
-
_ = json_serialization._SerializedContext._from_json_dict_(**context_json)
|
|
452
|
-
|
|
453
|
-
serialization_json = test_serialization._json_dict_()
|
|
454
|
-
with pytest.raises(TypeError, match='_from_json_dict_'):
|
|
455
|
-
_ = json_serialization._ContextualSerialization._from_json_dict_(**serialization_json)
|
|
456
|
-
|
|
457
|
-
|
|
458
424
|
# during test setup deprecated submodules are inspected and trigger the
|
|
459
425
|
# deprecation error in testing. It is cleaner to just turn it off than to assert
|
|
460
426
|
# deprecation for each submodule.
|