diff --git a/cirq-google/cirq_google/__init__.py b/cirq-google/cirq_google/__init__.py index d177c7d6f37..13b4633fa29 100644 --- a/cirq-google/cirq_google/__init__.py +++ b/cirq-google/cirq_google/__init__.py @@ -163,7 +163,50 @@ _compat.deprecate_attributes( __name__, { - 'Bristlecone': ('v0.15', 'Bristlecone will no longer be supported.'), - 'Foxtail': ('v0.15', 'Foxtail will no longer be supported.'), + 'XMON': ( + 'v0.16', + 'SerializableGateSet will no longer be supported.' + ' In cirq_google.GridDevice, the new representation of Google devices, the gateset of ' + ' a device is represented as a cirq.Gateset and is available as' + ' GridDevice.metadata.gateset.' + ' Engine methods no longer require gate sets to be passed in.' + ' In addition, circuit serialization is replaced by cirq_google.CircuitSerializer.', + ), + 'FSIM_GATESET': ( + 'v0.16', + 'SerializableGateSet will no longer be supported.' + ' In cirq_google.GridDevice, the new representation of Google devices, the gateset of ' + ' a device is represented as a cirq.Gateset and is available as' + ' GridDevice.metadata.gateset.' + ' Engine methods no longer require gate sets to be passed in.' + ' In addition, circuit serialization is replaced by cirq_google.CircuitSerializer.', + ), + 'SQRT_ISWAP_GATESET': ( + 'v0.16', + 'SerializableGateSet will no longer be supported.' + ' In cirq_google.GridDevice, the new representation of Google devices, the gateset of ' + ' a device is represented as a cirq.Gateset and is available as' + ' GridDevice.metadata.gateset.' + ' Engine methods no longer require gate sets to be passed in.' + ' In addition, circuit serialization is replaced by cirq_google.CircuitSerializer.', + ), + 'SYC_GATESET': ( + 'v0.16', + 'SerializableGateSet will no longer be supported.' + ' In cirq_google.GridDevice, the new representation of Google devices, the gateset of ' + ' a device is represented as a cirq.Gateset and is available as' + ' GridDevice.metadata.gateset.' + ' Engine methods no longer require gate sets to be passed in.' + ' In addition, circuit serialization is replaced by cirq_google.CircuitSerializer.', + ), + 'NAMED_GATESETS': ( + 'v0.16', + 'SerializableGateSet will no longer be supported.' + ' In cirq_google.GridDevice, the new representation of Google devices, the gateset of ' + ' a device is represented as a cirq.Gateset and is available as' + ' GridDevice.metadata.gateset.' + ' Engine methods no longer require gate sets to be passed in.' + ' In addition, circuit serialization is replaced by cirq_google.CircuitSerializer.', + ), }, ) diff --git a/cirq-google/cirq_google/calibration/phased_fsim_test.py b/cirq-google/cirq_google/calibration/phased_fsim_test.py index 1a208d72ffe..157d0de58fc 100644 --- a/cirq-google/cirq_google/calibration/phased_fsim_test.py +++ b/cirq-google/cirq_google/calibration/phased_fsim_test.py @@ -221,54 +221,55 @@ def test_floquet_to_calibration_layer_with_measure_qubits(): def test_xeb_to_calibration_layer(): - q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)] - gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0) - request = XEBPhasedFSimCalibrationRequest( - gate=gate, - pairs=((q_00, q_01), (q_02, q_03)), - options=XEBPhasedFSimCalibrationOptions( - n_library_circuits=22, - fsim_options=XEBPhasedFSimCharacterizationOptions( - characterize_theta=True, - characterize_zeta=True, - characterize_chi=False, - characterize_gamma=False, - characterize_phi=True, + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)] + gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0) + request = XEBPhasedFSimCalibrationRequest( + gate=gate, + pairs=((q_00, q_01), (q_02, q_03)), + options=XEBPhasedFSimCalibrationOptions( + n_library_circuits=22, + fsim_options=XEBPhasedFSimCharacterizationOptions( + characterize_theta=True, + characterize_zeta=True, + characterize_chi=False, + characterize_gamma=False, + characterize_phi=True, + ), ), - ), - ) - layer = request.to_calibration_layer() - assert layer == cirq_google.CalibrationLayer( - calibration_type='xeb_phased_fsim_characterization', - program=cirq.Circuit([gate.on(q_00, q_01), gate.on(q_02, q_03)]), - args={ - 'n_library_circuits': 22, - 'n_combinations': 10, - 'cycle_depths': '5_25_50_100_200_300', - 'fatol': 5e-3, - 'xatol': 5e-3, - 'characterize_theta': True, - 'characterize_zeta': True, - 'characterize_chi': False, - 'characterize_gamma': False, - 'characterize_phi': True, - }, - ) + ) + layer = request.to_calibration_layer() + assert layer == cirq_google.CalibrationLayer( + calibration_type='xeb_phased_fsim_characterization', + program=cirq.Circuit([gate.on(q_00, q_01), gate.on(q_02, q_03)]), + args={ + 'n_library_circuits': 22, + 'n_combinations': 10, + 'cycle_depths': '5_25_50_100_200_300', + 'fatol': 5e-3, + 'xatol': 5e-3, + 'characterize_theta': True, + 'characterize_zeta': True, + 'characterize_chi': False, + 'characterize_gamma': False, + 'characterize_phi': True, + }, + ) - # Serialize to proto - calibration = v2.calibration_pb2.FocusedCalibration() - new_layer = calibration.layers.add() - new_layer.calibration_type = layer.calibration_type - for arg in layer.args: - arg_to_proto(layer.args[arg], out=new_layer.args[arg]) - cirq_google.SQRT_ISWAP_GATESET.serialize(layer.program, msg=new_layer.layer) - with open(os.path.dirname(__file__) + '/test_data/xeb_calibration_layer.textproto') as f: - desired_textproto = f.read() - - layer_str = str(new_layer) - # Fix precision issues - layer_str = re.sub(r'0.004999\d+', '0.005', layer_str) - assert layer_str == desired_textproto + # Serialize to proto + calibration = v2.calibration_pb2.FocusedCalibration() + new_layer = calibration.layers.add() + new_layer.calibration_type = layer.calibration_type + for arg in layer.args: + arg_to_proto(layer.args[arg], out=new_layer.args[arg]) + cirq_google.SQRT_ISWAP_GATESET.serialize(layer.program, msg=new_layer.layer) + with open(os.path.dirname(__file__) + '/test_data/xeb_calibration_layer.textproto') as f: + desired_textproto = f.read() + + layer_str = str(new_layer) + # Fix precision issues + layer_str = re.sub(r'0.004999\d+', '0.005', layer_str) + assert layer_str == desired_textproto def test_from_moment(): diff --git a/cirq-google/cirq_google/devices/grid_device_test.py b/cirq-google/cirq_google/devices/grid_device_test.py index 7f9822a3b3d..547e9d03ce5 100644 --- a/cirq-google/cirq_google/devices/grid_device_test.py +++ b/cirq-google/cirq_google/devices/grid_device_test.py @@ -418,78 +418,82 @@ def test_to_proto_invalid_input(error_match, qubits, qubit_pairs, gateset, gate_ def test_to_proto_backward_compatibility(): - device_info, _ = _create_device_spec_with_horizontal_couplings() - - # The set of gates in gate_durations are consistent with what's generated in - # _create_device_spec_with_horizontal_couplings() - base_duration = cirq.Duration(picos=1_000) - gate_durations = { - cirq.GateFamily(cirq_google.SYC): base_duration * 0, - cirq.GateFamily(cirq.SQRT_ISWAP): base_duration * 1, - cirq.GateFamily(cirq.SQRT_ISWAP_INV): base_duration * 2, - cirq.GateFamily(cirq.CZ): base_duration * 3, - cirq.GateFamily(cirq.ops.phased_x_z_gate.PhasedXZGate): base_duration * 4, - cirq.GateFamily( - cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()] - ): base_duration - * 5, - cirq.GateFamily( - cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()] - ): base_duration - * 6, - cirq.GateFamily(cirq_google.experimental.ops.coupler_pulse.CouplerPulse): base_duration * 7, - cirq.GateFamily(cirq.ops.measurement_gate.MeasurementGate): base_duration * 8, - cirq.GateFamily(cirq.ops.wait_gate.WaitGate): base_duration * 9, - } - - # Serialize the old way - spec = known_devices.create_device_proto_for_qubits( - device_info.grid_qubits, - device_info.qubit_pairs, - [cirq_google.FSIM_GATESET], - known_devices._SYCAMORE_DURATIONS_PICOS, - ) - - # Serialize the new way - grid_device.create_device_specification_proto( - qubits=device_info.grid_qubits, - pairs=device_info.qubit_pairs, - gateset=cirq.Gateset(*gate_durations.keys()), - gate_durations=gate_durations, - out=spec, - ) - - with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=None): - # Deserialize both ways - serializable_dev = cirq_google.SerializableDevice.from_proto( - spec, [cirq_google.FSIM_GATESET] - ) - grid_dev = cirq_google.GridDevice.from_proto(spec) - - assert serializable_dev.metadata.qubit_set == grid_dev.metadata.qubit_set - assert serializable_dev.metadata.qubit_pairs == grid_dev.metadata.qubit_pairs - - assert serializable_dev.metadata.gateset == cirq.Gateset( - cirq.FSimGate, - cirq.ISwapPowGate, - cirq.CZPowGate, - cirq.PhasedXPowGate, - cirq.XPowGate, - cirq.YPowGate, - cirq.ZPowGate, - cirq.PhasedXZGate, - cirq.MeasurementGate, - cirq.WaitGate, - cirq.GlobalPhaseGate, + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + device_info, _ = _create_device_spec_with_horizontal_couplings() + + # The set of gates in gate_durations are consistent with what's generated in + # _create_device_spec_with_horizontal_couplings() + base_duration = cirq.Duration(picos=1_000) + gate_durations = { + cirq.GateFamily(cirq_google.SYC): base_duration * 0, + cirq.GateFamily(cirq.SQRT_ISWAP): base_duration * 1, + cirq.GateFamily(cirq.SQRT_ISWAP_INV): base_duration * 2, + cirq.GateFamily(cirq.CZ): base_duration * 3, + cirq.GateFamily(cirq.ops.phased_x_z_gate.PhasedXZGate): base_duration * 4, + cirq.GateFamily( + cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()] + ): base_duration + * 5, + cirq.GateFamily( + cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()] + ): base_duration + * 6, + cirq.GateFamily(cirq_google.experimental.ops.coupler_pulse.CouplerPulse): base_duration + * 7, + cirq.GateFamily(cirq.ops.measurement_gate.MeasurementGate): base_duration * 8, + cirq.GateFamily(cirq.ops.wait_gate.WaitGate): base_duration * 9, + } + + # Serialize the old way + spec = known_devices.create_device_proto_for_qubits( + device_info.grid_qubits, + device_info.qubit_pairs, + [cirq_google.FSIM_GATESET], + known_devices._SYCAMORE_DURATIONS_PICOS, ) - assert grid_dev.metadata.gateset == device_info.expected_gateset - assert ( - tuple(grid_dev.metadata.compilation_target_gatesets) - == device_info.expected_target_gatesets + # Serialize the new way + grid_device.create_device_specification_proto( + qubits=device_info.grid_qubits, + pairs=device_info.qubit_pairs, + gateset=cirq.Gateset(*gate_durations.keys()), + gate_durations=gate_durations, + out=spec, ) - assert grid_dev.metadata.gate_durations == device_info.expected_gate_durations + with cirq.testing.assert_deprecated( + 'Use cirq_google.GridDevice', deadline='v0.16', count=None + ): + # Deserialize both ways + serializable_dev = cirq_google.SerializableDevice.from_proto( + spec, [cirq_google.FSIM_GATESET] + ) + grid_dev = cirq_google.GridDevice.from_proto(spec) + + assert serializable_dev.metadata.qubit_set == grid_dev.metadata.qubit_set + assert serializable_dev.metadata.qubit_pairs == grid_dev.metadata.qubit_pairs + + assert serializable_dev.metadata.gateset == cirq.Gateset( + cirq.FSimGate, + cirq.ISwapPowGate, + cirq.CZPowGate, + cirq.PhasedXPowGate, + cirq.XPowGate, + cirq.YPowGate, + cirq.ZPowGate, + cirq.PhasedXZGate, + cirq.MeasurementGate, + cirq.WaitGate, + cirq.GlobalPhaseGate, + ) + + assert grid_dev.metadata.gateset == device_info.expected_gateset + assert ( + tuple(grid_dev.metadata.compilation_target_gatesets) + == device_info.expected_target_gatesets + ) + + assert grid_dev.metadata.gate_durations == device_info.expected_gate_durations def test_to_proto_empty(): diff --git a/cirq-google/cirq_google/devices/known_devices_test.py b/cirq-google/cirq_google/devices/known_devices_test.py index 7f13f6caa97..35cd357e22a 100644 --- a/cirq-google/cirq_google/devices/known_devices_test.py +++ b/cirq-google/cirq_google/devices/known_devices_test.py @@ -61,7 +61,12 @@ def test_create_device_proto_for_irregular_grid(): def test_multiple_gate_sets(): - with cirq.testing.assert_deprecated('no longer be available', deadline='v0.16', count=1): + # Deprecations: cirq_google.SerializableGateSets class, + # well-known cirq_google SerializableGateSets (e.g. cirq_google.SYC_GATESET), and + # cirq_google.devices.known_devices.create_device_proto_from_diagram + with cirq.testing.assert_deprecated( + 'SerializableGateSet', 'no longer be available', deadline='v0.16', count=3 + ): halfPiGateSet = cirq_google.SerializableGateSet( gate_set_name='half_pi_gateset', serializers=[*cgc.SINGLE_QUBIT_HALF_PI_SERIALIZERS, cgc.MEASUREMENT_SERIALIZER], @@ -221,10 +226,15 @@ def test_multiple_gate_sets(): def test_sycamore_circuitop_device(): - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableGateSets class, + # well-known cirq_google SerializableGateSets (e.g. cirq_google.SYC_GATESET), and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=6, ): circuitop_gateset = cirq_google.SerializableGateSet( gate_set_name='circuitop_gateset', @@ -268,7 +278,11 @@ def test_sycamore_grid_layout(): def test_proto_with_circuitop(): - with cirq.testing.assert_deprecated('no longer be available', deadline='v0.16', count=1): + # Deprecations: cirq_google.SerializableGateSets class and + # cirq_google.devices.known_devices.create_device_proto_from_diagram + with cirq.testing.assert_deprecated( + 'SerializableGateSet', 'no longer be available', deadline='v0.16', count=2 + ): circuitop_gateset = cirq_google.SerializableGateSet( gate_set_name='circuitop_gateset', serializers=[cgc.CIRCUIT_OP_SERIALIZER], @@ -320,10 +334,14 @@ def test_proto_with_circuitop(): def test_proto_with_waitgate(): - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, cirq_google.SerializableGateSet, and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=4, ): wait_gateset = cirq_google.SerializableGateSet( gate_set_name='wait_gateset', @@ -387,10 +405,14 @@ def test_proto_with_waitgate(): def test_adding_gates_multiple_times(): - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, cirq_google.SerializableGateSet, and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=4, ): waiting_for_godot = cirq_google.SerializableGateSet( gate_set_name='wait_gateset', diff --git a/cirq-google/cirq_google/devices/serializable_device_test.py b/cirq-google/cirq_google/devices/serializable_device_test.py index 1b2349a6851..493a9821ad6 100644 --- a/cirq-google/cirq_google/devices/serializable_device_test.py +++ b/cirq-google/cirq_google/devices/serializable_device_test.py @@ -25,40 +25,56 @@ import cirq_google.devices.known_devices as cgdk import cirq_google.serialization.common_serializers as cgc -_JUST_CZ = cg.SerializableGateSet( - gate_set_name='cz_gate_set', - serializers=[cg.GateOpSerializer(gate_type=cirq.CZPowGate, serialized_gate_id='cz', args=[])], - deserializers=[ - cg.GateOpDeserializer(serialized_gate_id='cz', gate_constructor=cirq.CZPowGate, args=[]) - ], -) - -_JUST_MEAS = cg.SerializableGateSet( - gate_set_name='meas_gate_set', - serializers=[ - cg.GateOpSerializer(gate_type=cirq.MeasurementGate, serialized_gate_id='meas', args=[]) - ], - deserializers=[ - cg.GateOpDeserializer( - serialized_gate_id='meas', gate_constructor=cirq.MeasurementGate, args=[] + +def _just_cz(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + return cg.SerializableGateSet( + gate_set_name='cz_gate_set', + serializers=[ + cg.GateOpSerializer(gate_type=cirq.CZPowGate, serialized_gate_id='cz', args=[]) + ], + deserializers=[ + cg.GateOpDeserializer( + serialized_gate_id='cz', gate_constructor=cirq.CZPowGate, args=[] + ) + ], + ) + + +def _just_meas(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + return cg.SerializableGateSet( + gate_set_name='meas_gate_set', + serializers=[ + cg.GateOpSerializer( + gate_type=cirq.MeasurementGate, serialized_gate_id='meas', args=[] + ) + ], + deserializers=[ + cg.GateOpDeserializer( + serialized_gate_id='meas', gate_constructor=cirq.MeasurementGate, args=[] + ) + ], ) - ], -) def test_str_with_grid_qubits(): - qubits = cirq.GridQubit.rect(2, 3, left=1, top=1) - device_proto = cgdk.create_device_proto_for_qubits( - qubits=qubits, - pairs=[ - (qubits[0], qubits[1]), - (qubits[0], qubits[3]), - (qubits[1], qubits[4]), - (qubits[4], qubits[5]), - ], - gate_sets=[cg.FSIM_GATESET], - ) - with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=2): + # Deprecations: cirq_google.SerializableDevice and well-known cirq_google SerializableGateSets + # (e.g. cirq_google.SYC_GATESET) + with cirq.testing.assert_deprecated( + 'Use cirq_google.GridDevice', 'SerializableGateSet', deadline='v0.16', count=4 + ): + qubits = cirq.GridQubit.rect(2, 3, left=1, top=1) + device_proto = cgdk.create_device_proto_for_qubits( + qubits=qubits, + pairs=[ + (qubits[0], qubits[1]), + (qubits[0], qubits[3]), + (qubits[1], qubits[4]), + (qubits[4], qubits[5]), + ], + gate_sets=[cg.FSIM_GATESET], + ) device = cg.SerializableDevice.from_proto(device_proto, gate_sets=[cg.FSIM_GATESET]) assert str(device) == textwrap.dedent( """\ @@ -78,17 +94,20 @@ def test_repr_pretty(cycle, func): def test_metadata_correct(): - qubits = cirq.GridQubit.rect(2, 3, left=1, top=1) - pairs = [ - (qubits[0], qubits[1]), - (qubits[0], qubits[3]), - (qubits[1], qubits[4]), - (qubits[4], qubits[5]), - ] - device_proto = cgdk.create_device_proto_for_qubits( - qubits=qubits, pairs=pairs, gate_sets=[cg.FSIM_GATESET] - ) - with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=2): + # Deprecations: cirq_google.SerializableDevice and well-known cirq_google SerializableGateSets + # (e.g. cirq_google.SYC_GATESET) + with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=4): + qubits = cirq.GridQubit.rect(2, 3, left=1, top=1) + pairs = [ + (qubits[0], qubits[1]), + (qubits[0], qubits[3]), + (qubits[1], qubits[4]), + (qubits[4], qubits[5]), + ] + device_proto = cgdk.create_device_proto_for_qubits( + qubits=qubits, pairs=pairs, gate_sets=[cg.FSIM_GATESET] + ) + device = cg.SerializableDevice.from_proto(device_proto, gate_sets=[cg.FSIM_GATESET]) assert device.metadata.qubit_pairs == frozenset({frozenset(p) for p in pairs}) assert device.metadata.gateset == cirq.Gateset( @@ -134,10 +153,15 @@ def test_gate_definition_equality(): def test_mismatched_proto_serializer(): - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, well-known cirq_google SerializableGateSets + # (e.g. cirq_google.SYC_GATESET), and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=2 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=5, ): augmented_proto = cgdk.create_device_proto_from_diagram( cgdk._SYCAMORE_GRID, @@ -154,10 +178,15 @@ def test_mismatched_proto_serializer(): def test_named_qubit(): - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, well-known cirq_google SerializableGateSets + # (e.g. cirq_google.SYC_GATESET), and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=6, ): augmented_proto = cgdk.create_device_proto_from_diagram( cgdk._SYCAMORE_GRID, @@ -174,10 +203,15 @@ def test_named_qubit(): def test_duration_of(): - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, well-known cirq_google SerializableGateSets + # (e.g. cirq_google.SYC_GATESET), and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=5, ): valid_qubit1 = cirq.GridQubit(0, 0) @@ -219,8 +253,9 @@ def test_asymmetric_gate(): gate.id = 'cz' gate.valid_targets.extend(['left_to_right']) + cz_gateset = _just_cz() with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=2): - dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ]) + dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[cz_gateset]) for row in range(5): dev.validate_operation(cirq.CZ(cirq.GridQubit(row, 0), cirq.GridQubit(row, 1))) @@ -243,8 +278,9 @@ def test_unconstrained_gate(): gate.id = 'cz' gate.valid_targets.extend(['2_qubit_anywhere']) + cz_gateset = _just_cz() with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=2): - dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ]) + dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[cz_gateset]) valid_qubit1 = cirq.GridQubit(4, 4) for row in range(4): @@ -270,8 +306,9 @@ def test_number_of_qubits_cz(): gate.valid_targets.extend(['2_qubit_anywhere']) gate.number_of_qubits = 3 + cz_gateset = _just_cz() with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=2): - dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ]) + dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[cz_gateset]) with pytest.raises(ValueError): dev.validate_operation(cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1))) @@ -296,8 +333,9 @@ def test_constrained_permutations(): gate.id = 'meas' gate.valid_targets.extend(['meas_on_first_line']) + meas_gateset = _just_meas() with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=2): - dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_MEAS]) + dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[meas_gateset]) dev.validate_operation(cirq.measure(cirq.GridQubit(0, 0))) dev.validate_operation(cirq.measure(cirq.GridQubit(1, 0))) @@ -330,16 +368,21 @@ def test_mixing_types(): gate.id = 'meas' gate.valid_targets.extend(['subset', 'sym']) + meas_gateset = _just_meas() with cirq.testing.assert_deprecated('Use cirq_google.GridDevice', deadline='v0.16', count=1): with pytest.raises(NotImplementedError): - _ = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_MEAS]) + _ = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[meas_gateset]) def test_multiple_gatesets(): - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, cirq_google.SerializableGateSet, and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=5, ): halfPiGateSet = cirq_google.SerializableGateSet( gate_set_name='half_pi_gateset', @@ -374,10 +417,14 @@ def test_half_pi_takes_half_duration(): gate perform correctly. In this case, we set the XPowGate to be half the duration of the full exponent and make sure it still works. """ - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, cirq_google.SerializableGateSet, and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=4, ): half_pi_gs = cirq_google.SerializableGateSet( gate_set_name='half_pi', @@ -403,10 +450,14 @@ def test_multiple_fsim_gatesets(): gate perform correctly. In this case, we set the XPowGate to be half the duration of the full exponent and make sure it still works. """ - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, cirq_google.SerializableGateSet, and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=4, ): half_pi_gs = cirq_google.SerializableGateSet( gate_set_name='half_pi', @@ -428,10 +479,15 @@ def test_multiple_fsim_gatesets(): def test_serializable_device_str_grid_qubits(): - # Deprecations: cirq_google.SerializableDevice and + # Deprecations: cirq_google.SerializableDevice, well-known cirq_google SerializableGateSets + # (e.g. cirq_google.SYC_GATESET), and # cirq_google.devices.known_devices.create_device_proto_from_diagram with cirq.testing.assert_deprecated( - 'Use cirq_google.GridDevice', 'no longer be available', deadline='v0.16', count=3 + 'Use cirq_google.GridDevice', + 'SerializableGateSet', + 'no longer be available', + deadline='v0.16', + count=5, ): spec = cirq_google.devices.known_devices.create_device_proto_from_diagram( "aa\naa", [cg.SYC_GATESET] diff --git a/cirq-google/cirq_google/engine/engine_processor_test.py b/cirq-google/cirq_google/engine/engine_processor_test.py index 59bffe67a3e..88ec5fe0ff4 100644 --- a/cirq-google/cirq_google/engine/engine_processor_test.py +++ b/cirq-google/cirq_google/engine/engine_processor_test.py @@ -100,15 +100,6 @@ def _to_timestamp(json_string): ) -_GATE_SET = cg.SerializableGateSet( - gate_set_name='x_gate_set', - serializers=[cg.GateOpSerializer(gate_type=cirq.XPowGate, serialized_gate_id='x', args=[])], - deserializers=[ - cg.GateOpDeserializer(serialized_gate_id='x', gate_constructor=cirq.XPowGate, args=[]) - ], -) - - _CIRCUIT = cirq.Circuit( cirq.X(cirq.GridQubit(5, 2)) ** 0.5, cirq.measure(cirq.GridQubit(5, 2), key='result') ) diff --git a/cirq-google/cirq_google/engine/engine_program.py b/cirq-google/cirq_google/engine/engine_program.py index 289f69d8df4..37302e9ba71 100644 --- a/cirq-google/cirq_google/engine/engine_program.py +++ b/cirq-google/cirq_google/engine/engine_program.py @@ -30,6 +30,14 @@ import cirq_google.engine.engine as engine_base +_GOOGLE_GATESETS = [ + gate_sets.SYC_GATESET, + gate_sets.SQRT_ISWAP_GATESET, + gate_sets.FSIM_GATESET, + gate_sets.XMON, +] + + class EngineProgram(abstract_program.AbstractProgram): """A program created via the Quantum Engine API. @@ -555,7 +563,8 @@ def _deserialize_program(code: any_pb2.Any, program_num: Optional[int] = None) - program = batch.programs[program_num] if program is not None: - gate_set_map = {g.name: g for g in gate_sets.GOOGLE_GATESETS} + # TODO(#5050) Move to CircuitSerializer + gate_set_map = {g.name: g for g in _GOOGLE_GATESETS} if program.language.gate_set not in gate_set_map: raise ValueError( f'Unknown gateset {program.language.gate_set}. ' diff --git a/cirq-google/cirq_google/engine/engine_validator_test.py b/cirq-google/cirq_google/engine/engine_validator_test.py index ed94b6e85e1..0687c680966 100644 --- a/cirq-google/cirq_google/engine/engine_validator_test.py +++ b/cirq-google/cirq_google/engine/engine_validator_test.py @@ -38,32 +38,34 @@ def _big_circuit(num_cycles: int) -> cirq.Circuit: def test_validate_gate_set(): - circuit = _big_circuit(4) - - engine_validator.validate_gate_set( - [circuit] * 5, [{}] * 5, 1000, cg.FSIM_GATESET, max_size=100000 - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + circuit = _big_circuit(4) - with pytest.raises(RuntimeError, match='Program too long'): engine_validator.validate_gate_set( - [circuit] * 10, [{}] * 10, 1000, cg.FSIM_GATESET, max_size=100000 + [circuit] * 5, [{}] * 5, 1000, cg.FSIM_GATESET, max_size=100000 ) - with pytest.raises(RuntimeError, match='Program too long'): - engine_validator.validate_gate_set( - [circuit] * 5, [{}] * 5, 1000, cg.FSIM_GATESET, max_size=10000 - ) + with pytest.raises(RuntimeError, match='Program too long'): + engine_validator.validate_gate_set( + [circuit] * 10, [{}] * 10, 1000, cg.FSIM_GATESET, max_size=100000 + ) + with pytest.raises(RuntimeError, match='Program too long'): + engine_validator.validate_gate_set( + [circuit] * 5, [{}] * 5, 1000, cg.FSIM_GATESET, max_size=10000 + ) -def test_create_gate_set_validator(): - circuit = _big_circuit(4) - smaller_size_validator = engine_validator.create_gate_set_validator(max_size=30000) - smaller_size_validator([circuit] * 2, [{}] * 2, 1000, cg.FSIM_GATESET) - with pytest.raises(RuntimeError, match='Program too long'): - smaller_size_validator([circuit] * 5, [{}] * 5, 1000, cg.FSIM_GATESET) - larger_size_validator = engine_validator.create_gate_set_validator(max_size=500000) - larger_size_validator([circuit] * 10, [{}] * 10, 1000, cg.FSIM_GATESET) +def test_create_gate_set_validator(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + circuit = _big_circuit(4) + + smaller_size_validator = engine_validator.create_gate_set_validator(max_size=30000) + smaller_size_validator([circuit] * 2, [{}] * 2, 1000, cg.FSIM_GATESET) + with pytest.raises(RuntimeError, match='Program too long'): + smaller_size_validator([circuit] * 5, [{}] * 5, 1000, cg.FSIM_GATESET) + larger_size_validator = engine_validator.create_gate_set_validator(max_size=500000) + larger_size_validator([circuit] * 10, [{}] * 10, 1000, cg.FSIM_GATESET) def test_validate_for_engine(): diff --git a/cirq-google/cirq_google/optimizers/convert_to_sqrt_iswap_test.py b/cirq-google/cirq_google/optimizers/convert_to_sqrt_iswap_test.py index 50769f8926c..3865141a29a 100644 --- a/cirq-google/cirq_google/optimizers/convert_to_sqrt_iswap_test.py +++ b/cirq-google/cirq_google/optimizers/convert_to_sqrt_iswap_test.py @@ -51,9 +51,10 @@ def test_two_qubit_gates(gate: cirq.Gate, expected_length: int): ) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'): cgoc.ConvertToSqrtIswapGates().optimize_circuit(converted_circuit) - cig.SQRT_ISWAP_GATESET.serialize(converted_circuit) - cig.SQRT_ISWAP_GATESET.serialize(converted_circuit_iswap) - cig.SQRT_ISWAP_GATESET.serialize(converted_circuit_iswap_inv) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + cig.SQRT_ISWAP_GATESET.serialize(converted_circuit) + cig.SQRT_ISWAP_GATESET.serialize(converted_circuit_iswap) + cig.SQRT_ISWAP_GATESET.serialize(converted_circuit_iswap_inv) assert len(converted_circuit) <= expected_length assert ( len(converted_circuit_iswap) <= expected_length diff --git a/cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py b/cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py index 0190d64b00e..fa9d8299a61 100644 --- a/cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py +++ b/cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py @@ -24,15 +24,17 @@ def __init__(self): pass -_OPTIMIZERS_AND_GATESETS = [ - ('sqrt_iswap', cg.SQRT_ISWAP_GATESET), - ('sycamore', cg.SYC_GATESET), - ('xmon', cg.XMON), - ('xmon_partial_cz', cg.XMON), -] +def _optimizers_and_gatesets(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + return [ + ('sqrt_iswap', cg.SQRT_ISWAP_GATESET), + ('sycamore', cg.SYC_GATESET), + ('xmon', cg.XMON), + ('xmon_partial_cz', cg.XMON), + ] -@pytest.mark.parametrize('optimizer_type, gateset', _OPTIMIZERS_AND_GATESETS) +@pytest.mark.parametrize('optimizer_type, gateset', _optimizers_and_gatesets()) def test_optimizer_output_gates_are_supported(optimizer_type, gateset): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( @@ -48,7 +50,7 @@ def test_optimizer_output_gates_are_supported(optimizer_type, gateset): assert gateset.is_supported_operation(op) -@pytest.mark.parametrize('optimizer_type, gateset', _OPTIMIZERS_AND_GATESETS) +@pytest.mark.parametrize('optimizer_type, gateset', _optimizers_and_gatesets()) def test_optimize_large_measurement_gates(optimizer_type, gateset): qubits = cirq.LineQubit.range(53) circuit = cirq.Circuit( @@ -128,8 +130,11 @@ def test_one_q_matrix_gate(): circuit0 = cirq.Circuit(cirq.MatrixGate(u).on(q)) assert len(circuit0) == 1 + # Deprecations: well-known cirq_google SerializableGateSets + # (e.g. cirq_google.SYC_GATESET), and + # cirq_google.optimized_for_sycamore with cirq.testing.assert_deprecated( - 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + 'SerializableGateSet', 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=6 ): circuit_iswap = cg.optimized_for_sycamore(circuit0, optimizer_type='sqrt_iswap') assert len(circuit_iswap) == 1 diff --git a/cirq-google/cirq_google/serialization/arg_func_langs_test.py b/cirq-google/cirq_google/serialization/arg_func_langs_test.py index 15eb318a3fb..d61d7da7dca 100644 --- a/cirq-google/cirq_google/serialization/arg_func_langs_test.py +++ b/cirq-google/cirq_google/serialization/arg_func_langs_test.py @@ -154,21 +154,22 @@ def test_serialize_conversion(value: ARG_LIKE, proto: v2.program_pb2.Arg): def test_infer_language(): - q = cirq.GridQubit(0, 0) - a = sympy.Symbol('a') - b = sympy.Symbol('b') - - c_linear = cirq.Circuit(cirq.X(q) ** (b - a)) - packed = cirq_google.XMON.serialize(c_linear) - assert packed.language.arg_function_language == 'linear' - - c_empty = cirq.Circuit(cirq.X(q) ** b) - packed = cirq_google.XMON.serialize(c_empty) - assert packed.language.arg_function_language == '' - - c_exp = cirq.Circuit(cirq.X(q) ** (b**a)) - packed = cirq_google.XMON.serialize(c_exp) - assert packed.language.arg_function_language == 'exp' + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + q = cirq.GridQubit(0, 0) + a = sympy.Symbol('a') + b = sympy.Symbol('b') + + c_linear = cirq.Circuit(cirq.X(q) ** (b - a)) + packed = cirq_google.XMON.serialize(c_linear) + assert packed.language.arg_function_language == 'linear' + + c_empty = cirq.Circuit(cirq.X(q) ** b) + packed = cirq_google.XMON.serialize(c_empty) + assert packed.language.arg_function_language == '' + + c_exp = cirq.Circuit(cirq.X(q) ** (b**a)) + packed = cirq_google.XMON.serialize(c_exp) + assert packed.language.arg_function_language == 'exp' @pytest.mark.parametrize( diff --git a/cirq-google/cirq_google/serialization/common_serializers_test.py b/cirq-google/cirq_google/serialization/common_serializers_test.py index 49377cf7f0b..a4d2cd60f57 100644 --- a/cirq-google/cirq_google/serialization/common_serializers_test.py +++ b/cirq-google/cirq_google/serialization/common_serializers_test.py @@ -26,17 +26,23 @@ import cirq_google.serialization.common_serializers as cgc from cirq_google.api import v2 -SINGLE_QUBIT_GATE_SET = cg.SerializableGateSet( - gate_set_name='test_half_pi', - serializers=([cgc.MEASUREMENT_SERIALIZER] + cgc.SINGLE_QUBIT_SERIALIZERS), - deserializers=([cgc.MEASUREMENT_DESERIALIZER] + cgc.SINGLE_QUBIT_DESERIALIZERS), -) -HALF_PI_GATE_SET = cg.SerializableGateSet( - gate_set_name='test_half_pi', - serializers=([cgc.MEASUREMENT_SERIALIZER] + cgc.SINGLE_QUBIT_HALF_PI_SERIALIZERS), - deserializers=([cgc.MEASUREMENT_DESERIALIZER] + cgc.SINGLE_QUBIT_HALF_PI_DESERIALIZERS), -) +def _single_qubit_gate_set(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + return cg.SerializableGateSet( + gate_set_name='test_half_pi', + serializers=([cgc.MEASUREMENT_SERIALIZER] + cgc.SINGLE_QUBIT_SERIALIZERS), + deserializers=([cgc.MEASUREMENT_DESERIALIZER] + cgc.SINGLE_QUBIT_DESERIALIZERS), + ) + + +def _half_pi_gate_set(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + return cg.SerializableGateSet( + gate_set_name='test_half_pi', + serializers=([cgc.MEASUREMENT_SERIALIZER] + cgc.SINGLE_QUBIT_HALF_PI_SERIALIZERS), + deserializers=([cgc.MEASUREMENT_DESERIALIZER] + cgc.SINGLE_QUBIT_HALF_PI_DESERIALIZERS), + ) def op_proto(json_dict: Dict) -> v2.program_pb2.Operation: @@ -56,8 +62,8 @@ def test_serialize_deserialize_phased_x_pi_gate(phase_exponent): ) q = cirq.GridQubit(1, 2) op = cirq.PhasedXPowGate(phase_exponent=phase_exponent)(q) - assert HALF_PI_GATE_SET.serialize_op(op) == proto - assert HALF_PI_GATE_SET.deserialize_op(proto) == op + assert _half_pi_gate_set().serialize_op(op) == proto + assert _half_pi_gate_set().deserialize_op(proto) == op @pytest.mark.parametrize('phase_exponent', (0, 0.25, 0.75)) @@ -71,8 +77,8 @@ def test_serialize_deserialize_phased_x_half_pi_gate(phase_exponent): ) q = cirq.GridQubit(1, 2) op = cirq.PhasedXPowGate(exponent=0.5, phase_exponent=phase_exponent)(q) - assert HALF_PI_GATE_SET.serialize_op(op) == proto - assert HALF_PI_GATE_SET.deserialize_op(proto) == op + assert _half_pi_gate_set().serialize_op(op) == proto + assert _half_pi_gate_set().deserialize_op(proto) == op def test_serialize_x_pow_gate(): @@ -85,9 +91,9 @@ def test_serialize_x_pow_gate(): ) q = cirq.GridQubit(1, 2) op = cirq.XPowGate(exponent=1)(q) - assert HALF_PI_GATE_SET.serialize_op(op) == proto + assert _half_pi_gate_set().serialize_op(op) == proto cirq.testing.assert_allclose_up_to_global_phase( - cirq.unitary(HALF_PI_GATE_SET.deserialize_op(proto)), cirq.unitary(op), atol=1e-6 + cirq.unitary(_half_pi_gate_set().deserialize_op(proto)), cirq.unitary(op), atol=1e-6 ) @@ -101,9 +107,9 @@ def test_serialize_y_pow_gate(): ) q = cirq.GridQubit(1, 2) op = cirq.YPowGate(exponent=1)(q) - assert HALF_PI_GATE_SET.serialize_op(op) == proto + assert _half_pi_gate_set().serialize_op(op) == proto cirq.testing.assert_allclose_up_to_global_phase( - cirq.unitary(HALF_PI_GATE_SET.deserialize_op(proto)), cirq.unitary(op), atol=1e-6 + cirq.unitary(_half_pi_gate_set().deserialize_op(proto)), cirq.unitary(op), atol=1e-6 ) @@ -117,9 +123,9 @@ def test_serialize_sqrt_x_pow_gate(): ) q = cirq.GridQubit(1, 2) op = cirq.XPowGate(exponent=0.5)(q) - assert HALF_PI_GATE_SET.serialize_op(op) == proto + assert _half_pi_gate_set().serialize_op(op) == proto cirq.testing.assert_allclose_up_to_global_phase( - cirq.unitary(HALF_PI_GATE_SET.deserialize_op(proto)), cirq.unitary(op), atol=1e-6 + cirq.unitary(_half_pi_gate_set().deserialize_op(proto)), cirq.unitary(op), atol=1e-6 ) @@ -133,9 +139,9 @@ def test_serialize_sqrt_y_pow_gate(): ) q = cirq.GridQubit(1, 2) op = cirq.YPowGate(exponent=0.5)(q) - assert HALF_PI_GATE_SET.serialize_op(op) == proto + assert _half_pi_gate_set().serialize_op(op) == proto cirq.testing.assert_allclose_up_to_global_phase( - cirq.unitary(HALF_PI_GATE_SET.deserialize_op(proto)), cirq.unitary(op), atol=1e-6 + cirq.unitary(_half_pi_gate_set().deserialize_op(proto)), cirq.unitary(op), atol=1e-6 ) @@ -163,8 +169,8 @@ def test_serialize_deserialize_arbitrary_xy(gate, axis_half_turns, half_turns): 'qubits': [{'id': '1_2'}], } ) - assert SINGLE_QUBIT_GATE_SET.serialize_op(op) == expected - deserialized_op = SINGLE_QUBIT_GATE_SET.deserialize_op(expected) + assert _single_qubit_gate_set().serialize_op(op) == expected + deserialized_op = _single_qubit_gate_set().deserialize_op(expected) cirq.testing.assert_allclose_up_to_global_phase( cirq.unitary(deserialized_op), cirq.unitary(op), atol=1e-7 ) @@ -174,11 +180,11 @@ def test_half_pi_does_not_serialize_arbitrary_xy(): q = cirq.GridQubit(1, 2) gate = cirq.PhasedXPowGate(exponent=0.125, phase_exponent=0.25) with pytest.raises(ValueError): - HALF_PI_GATE_SET.serialize_op(gate(q)) + _half_pi_gate_set().serialize_op(gate(q)) gate = cirq.PhasedXPowGate(exponent=sympy.Symbol('a'), phase_exponent=sympy.Symbol('b')) with pytest.raises(ValueError): - HALF_PI_GATE_SET.serialize_op(gate(q)) + _half_pi_gate_set().serialize_op(gate(q)) @pytest.mark.parametrize( @@ -201,8 +207,8 @@ def test_serialize_deserialize_arbitrary_xyz(x_exponent, z_exponent, axis_phase_ 'qubits': [{'id': '1_2'}], } ) - assert SINGLE_QUBIT_GATE_SET.serialize_op(op) == expected - deserialized_op = SINGLE_QUBIT_GATE_SET.deserialize_op(expected) + assert _single_qubit_gate_set().serialize_op(op) == expected + deserialized_op = _single_qubit_gate_set().deserialize_op(expected) cirq.testing.assert_allclose_up_to_global_phase( cirq.unitary(deserialized_op), cirq.unitary(op), atol=1e-7 ) @@ -228,10 +234,10 @@ def test_serialize_deserialize_meas(qubits, qubit_ids, key, invert_mask): }, } ) - assert SINGLE_QUBIT_GATE_SET.serialize_op(op) == proto - assert SINGLE_QUBIT_GATE_SET.deserialize_op(proto) == op - assert HALF_PI_GATE_SET.serialize_op(op) == proto - assert HALF_PI_GATE_SET.deserialize_op(proto) == op + assert _single_qubit_gate_set().serialize_op(op) == proto + assert _single_qubit_gate_set().deserialize_op(proto) == op + assert _half_pi_gate_set().serialize_op(op) == proto + assert _half_pi_gate_set().deserialize_op(proto) == op @pytest.mark.parametrize( @@ -259,7 +265,7 @@ def test_serialize_xy(gate, axis_half_turns, half_turns): } ) - assert SINGLE_QUBIT_GATE_SET.serialize_op(gate.on(q)) == expected + assert _single_qubit_gate_set().serialize_op(gate.on(q)) == expected @pytest.mark.parametrize( @@ -283,7 +289,7 @@ def test_serialize_xy_parameterized_half_turns(gate, axis_half_turns, half_turns } ) - assert SINGLE_QUBIT_GATE_SET.serialize_op(gate.on(q)) == expected + assert _single_qubit_gate_set().serialize_op(gate.on(q)) == expected def test_serialize_xy_parameterized_axis_half_turns(): @@ -300,7 +306,7 @@ def test_serialize_xy_parameterized_axis_half_turns(): } ) - assert SINGLE_QUBIT_GATE_SET.serialize_op(gate.on(q)) == expected + assert _single_qubit_gate_set().serialize_op(gate.on(q)) == expected @pytest.mark.parametrize( @@ -309,7 +315,7 @@ def test_serialize_xy_parameterized_axis_half_turns(): ) def test_serialize_z(gate, half_turns): q = cirq.GridQubit(1, 2) - assert SINGLE_QUBIT_GATE_SET.serialize_op(gate.on(q)) == op_proto( + assert _single_qubit_gate_set().serialize_op(gate.on(q)) == op_proto( { 'gate': {'id': 'z'}, 'args': { @@ -320,7 +326,7 @@ def test_serialize_z(gate, half_turns): } ) physical_op = gate.on(q).with_tags(cg.PhysicalZTag()) - assert SINGLE_QUBIT_GATE_SET.serialize_op(physical_op) == op_proto( + assert _single_qubit_gate_set().serialize_op(physical_op) == op_proto( { 'gate': {'id': 'z'}, 'args': { @@ -346,7 +352,7 @@ def test_deserialize_xy(axis_half_turns, half_turns): ) q = cirq.GridQubit(1, 2) expected = cirq.PhasedXPowGate(exponent=half_turns, phase_exponent=axis_half_turns)(q) - actual = SINGLE_QUBIT_GATE_SET.deserialize_op(serialized_op) + actual = _single_qubit_gate_set().deserialize_op(serialized_op) assert actual == expected @@ -360,7 +366,7 @@ def test_deserialize_xy_parameterized(): ) q = cirq.GridQubit(1, 2) expected = cirq.PhasedXPowGate(exponent=sympy.Symbol('b'), phase_exponent=sympy.Symbol('a'))(q) - assert SINGLE_QUBIT_GATE_SET.deserialize_op(serialized_op) == expected + assert _single_qubit_gate_set().deserialize_op(serialized_op) == expected @pytest.mark.parametrize('half_turns', [0, 0.25, 1.0]) @@ -377,11 +383,11 @@ def test_deserialize_z(half_turns): ) q = cirq.GridQubit(1, 2) expected = cirq.ZPowGate(exponent=half_turns)(q) - assert SINGLE_QUBIT_GATE_SET.deserialize_op(serialized_op) == expected + assert _single_qubit_gate_set().deserialize_op(serialized_op) == expected serialized_op.args['type'].arg_value.string_value = cgc.PHYSICAL_Z expected = cirq.ZPowGate(exponent=half_turns)(q).with_tags(cg.PhysicalZTag()) - assert SINGLE_QUBIT_GATE_SET.deserialize_op(serialized_op) == expected + assert _single_qubit_gate_set().deserialize_op(serialized_op) == expected def test_deserialize_z_parameterized(): @@ -397,7 +403,7 @@ def test_deserialize_z_parameterized(): ) q = cirq.GridQubit(1, 2) expected = cirq.ZPowGate(exponent=sympy.Symbol('a'))(q) - assert SINGLE_QUBIT_GATE_SET.deserialize_op(serialized_op) == expected + assert _single_qubit_gate_set().deserialize_op(serialized_op) == expected def _phys_z_args(phys_z): @@ -416,98 +422,103 @@ def assert_phys_z_tag(phys_z, op): ) @pytest.mark.parametrize('phys_z', [False, True]) def test_serialize_deserialize_cz_gate(gate, exponent, phys_z): - gate_set = cg.SerializableGateSet('test', [cgc.CZ_SERIALIZER], [cgc.CZ_POW_DESERIALIZER]) - proto = op_proto( - { - 'gate': {'id': 'cz'}, - 'args': { - 'half_turns': {'arg_value': {'float_value': exponent}}, - **_phys_z_args(phys_z), - }, - 'qubits': [{'id': '5_4'}, {'id': '5_5'}], - } - ) - q1 = cirq.GridQubit(5, 4) - q2 = cirq.GridQubit(5, 5) - op = gate(q1, q2) - if phys_z: - op = op.with_tags(cg.PhysicalZTag()) - assert gate_set.serialize_op(op) == proto - deserialized_op = gate_set.deserialize_op(proto) - expected_gate = cirq.CZPowGate(exponent=exponent) - cirq.testing.assert_allclose_up_to_global_phase( - cirq.unitary(deserialized_op), cirq.unitary(expected_gate), atol=1e-7 - ) - assert_phys_z_tag(phys_z, deserialized_op) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + gate_set = cg.SerializableGateSet('test', [cgc.CZ_SERIALIZER], [cgc.CZ_POW_DESERIALIZER]) + proto = op_proto( + { + 'gate': {'id': 'cz'}, + 'args': { + 'half_turns': {'arg_value': {'float_value': exponent}}, + **_phys_z_args(phys_z), + }, + 'qubits': [{'id': '5_4'}, {'id': '5_5'}], + } + ) + q1 = cirq.GridQubit(5, 4) + q2 = cirq.GridQubit(5, 5) + op = gate(q1, q2) + if phys_z: + op = op.with_tags(cg.PhysicalZTag()) + assert gate_set.serialize_op(op) == proto + deserialized_op = gate_set.deserialize_op(proto) + expected_gate = cirq.CZPowGate(exponent=exponent) + cirq.testing.assert_allclose_up_to_global_phase( + cirq.unitary(deserialized_op), cirq.unitary(expected_gate), atol=1e-7 + ) + assert_phys_z_tag(phys_z, deserialized_op) def test_cz_pow_non_integer_does_not_serialize(): - gate_set = cg.SerializableGateSet('test', [cgc.CZ_SERIALIZER], [cgc.CZ_POW_DESERIALIZER]) - q1 = cirq.GridQubit(5, 4) - q2 = cirq.GridQubit(5, 5) - with pytest.raises(ValueError): - gate_set.serialize_op(cirq.CZ(q1, q2) ** 0.5) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + gate_set = cg.SerializableGateSet('test', [cgc.CZ_SERIALIZER], [cgc.CZ_POW_DESERIALIZER]) + q1 = cirq.GridQubit(5, 4) + q2 = cirq.GridQubit(5, 5) + with pytest.raises(ValueError): + gate_set.serialize_op(cirq.CZ(q1, q2) ** 0.5) def test_coupler_pulse(): - gate_set = cg.SerializableGateSet( - 'test', [cgc.COUPLER_PULSE_SERIALIZER], [cgc.COUPLER_PULSE_DESERIALIZER] - ) - proto = op_proto( - { - 'gate': {'id': 'coupler_pulse'}, - 'args': { - 'hold_time_ns': {'arg_value': {'float_value': 16.0}}, - 'padding_time_ns': {'arg_value': {'float_value': 12.0}}, - 'rise_time_ns': {'arg_value': {'float_value': 32.0}}, - 'coupling_mhz': {'arg_value': {'float_value': 20.0}}, - }, - 'qubits': [{'id': '1_2'}, {'id': '2_2'}], - } - ) - q = cirq.GridQubit(1, 2) - q2 = cirq.GridQubit(2, 2) - op = cg.experimental.ops.CouplerPulse( - hold_time=cirq.Duration(nanos=16), - padding_time=cirq.Duration(nanos=12), - rise_time=cirq.Duration(nanos=32), - coupling_mhz=20, - )(q, q2) - assert gate_set.serialize_op(op) == proto - assert gate_set.deserialize_op(proto) == op + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + gate_set = cg.SerializableGateSet( + 'test', [cgc.COUPLER_PULSE_SERIALIZER], [cgc.COUPLER_PULSE_DESERIALIZER] + ) + proto = op_proto( + { + 'gate': {'id': 'coupler_pulse'}, + 'args': { + 'hold_time_ns': {'arg_value': {'float_value': 16.0}}, + 'padding_time_ns': {'arg_value': {'float_value': 12.0}}, + 'rise_time_ns': {'arg_value': {'float_value': 32.0}}, + 'coupling_mhz': {'arg_value': {'float_value': 20.0}}, + }, + 'qubits': [{'id': '1_2'}, {'id': '2_2'}], + } + ) + q = cirq.GridQubit(1, 2) + q2 = cirq.GridQubit(2, 2) + op = cg.experimental.ops.CouplerPulse( + hold_time=cirq.Duration(nanos=16), + padding_time=cirq.Duration(nanos=12), + rise_time=cirq.Duration(nanos=32), + coupling_mhz=20, + )(q, q2) + assert gate_set.serialize_op(op) == proto + assert gate_set.deserialize_op(proto) == op def test_wait_gate(): - gate_set = cg.SerializableGateSet( - 'test', [cgc.WAIT_GATE_SERIALIZER], [cgc.WAIT_GATE_DESERIALIZER] - ) - proto = op_proto( - { - 'gate': {'id': 'wait'}, - 'args': {'nanos': {'arg_value': {'float_value': 20.0}}}, - 'qubits': [{'id': '1_2'}], - } - ) - q = cirq.GridQubit(1, 2) - op = cirq.wait(q, nanos=20) - assert gate_set.serialize_op(op) == proto - assert gate_set.deserialize_op(proto) == op + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + gate_set = cg.SerializableGateSet( + 'test', [cgc.WAIT_GATE_SERIALIZER], [cgc.WAIT_GATE_DESERIALIZER] + ) + proto = op_proto( + { + 'gate': {'id': 'wait'}, + 'args': {'nanos': {'arg_value': {'float_value': 20.0}}}, + 'qubits': [{'id': '1_2'}], + } + ) + q = cirq.GridQubit(1, 2) + op = cirq.wait(q, nanos=20) + assert gate_set.serialize_op(op) == proto + assert gate_set.deserialize_op(proto) == op def test_wait_gate_multi_qubit(): - gate_set = cg.SerializableGateSet( - 'test', [cgc.WAIT_GATE_SERIALIZER], [cgc.WAIT_GATE_DESERIALIZER] - ) - proto = op_proto( - { - 'gate': {'id': 'wait'}, - 'args': {'nanos': {'arg_value': {'float_value': 20.0}}}, - 'qubits': [{'id': '1_2'}, {'id': '3_4'}], - } - ) - op = cirq.wait(cirq.GridQubit(1, 2), cirq.GridQubit(3, 4), nanos=20) - assert gate_set.serialize_op(op) == proto - assert gate_set.deserialize_op(proto) == op + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + gate_set = cg.SerializableGateSet( + 'test', [cgc.WAIT_GATE_SERIALIZER], [cgc.WAIT_GATE_DESERIALIZER] + ) + proto = op_proto( + { + 'gate': {'id': 'wait'}, + 'args': {'nanos': {'arg_value': {'float_value': 20.0}}}, + 'qubits': [{'id': '1_2'}, {'id': '3_4'}], + } + ) + op = cirq.wait(cirq.GridQubit(1, 2), cirq.GridQubit(3, 4), nanos=20) + assert gate_set.serialize_op(op) == proto + assert gate_set.deserialize_op(proto) == op @pytest.mark.parametrize( @@ -540,32 +551,33 @@ def test_wait_gate_multi_qubit(): ) @pytest.mark.parametrize('phys_z', [False, True]) def test_serialize_deserialize_fsim_gate(gate, theta, phi, phys_z): - gate_set = cg.SerializableGateSet( - 'test', cgc.LIMITED_FSIM_SERIALIZERS, [cgc.LIMITED_FSIM_DESERIALIZER] - ) - proto = op_proto( - { - 'gate': {'id': 'fsim'}, - 'args': { - 'theta': {'arg_value': {'float_value': theta}}, - 'phi': {'arg_value': {'float_value': phi}}, - **_phys_z_args(phys_z), - }, - 'qubits': [{'id': '5_4'}, {'id': '5_5'}], - } - ) - q1 = cirq.GridQubit(5, 4) - q2 = cirq.GridQubit(5, 5) - op = gate(q1, q2) - if phys_z: - op = op.with_tags(cg.PhysicalZTag()) - expected_gate = cirq.FSimGate(theta=theta, phi=phi) - assert gate_set.serialize_op(op) == proto - deserialized_op = gate_set.deserialize_op(proto) - cirq.testing.assert_allclose_up_to_global_phase( - cirq.unitary(deserialized_op), cirq.unitary(expected_gate), atol=1e-7 - ) - assert_phys_z_tag(phys_z, deserialized_op) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + gate_set = cg.SerializableGateSet( + 'test', cgc.LIMITED_FSIM_SERIALIZERS, [cgc.LIMITED_FSIM_DESERIALIZER] + ) + proto = op_proto( + { + 'gate': {'id': 'fsim'}, + 'args': { + 'theta': {'arg_value': {'float_value': theta}}, + 'phi': {'arg_value': {'float_value': phi}}, + **_phys_z_args(phys_z), + }, + 'qubits': [{'id': '5_4'}, {'id': '5_5'}], + } + ) + q1 = cirq.GridQubit(5, 4) + q2 = cirq.GridQubit(5, 5) + op = gate(q1, q2) + if phys_z: + op = op.with_tags(cg.PhysicalZTag()) + expected_gate = cirq.FSimGate(theta=theta, phi=phi) + assert gate_set.serialize_op(op) == proto + deserialized_op = gate_set.deserialize_op(proto) + cirq.testing.assert_allclose_up_to_global_phase( + cirq.unitary(deserialized_op), cirq.unitary(expected_gate), atol=1e-7 + ) + assert_phys_z_tag(phys_z, deserialized_op) @pytest.mark.parametrize( @@ -585,44 +597,46 @@ def test_serialize_deserialize_fsim_gate(gate, theta, phi, phys_z): ) @pytest.mark.parametrize('phys_z', [False, True]) def test_serialize_deserialize_fsim_gate_symbols(gate, theta, phi, phys_z): - gate_set = cg.SerializableGateSet( - 'test', cgc.LIMITED_FSIM_SERIALIZERS, [cgc.LIMITED_FSIM_DESERIALIZER] - ) - q1 = cirq.GridQubit(5, 4) - q2 = cirq.GridQubit(5, 5) - op = gate(q1, q2) - if phys_z: - op = op.with_tags(cg.PhysicalZTag()) - expected = op_proto( - { - 'gate': {'id': 'fsim'}, - 'args': {'theta': theta, 'phi': phi, **_phys_z_args(phys_z)}, - 'qubits': [{'id': '5_4'}, {'id': '5_5'}], - } - ) - proto = gate_set.serialize_op(op, arg_function_language='linear') - actual = gate_set.deserialize_op(proto, arg_function_language='linear') - assert proto == expected - assert actual == op - assert_phys_z_tag(phys_z, actual) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + gate_set = cg.SerializableGateSet( + 'test', cgc.LIMITED_FSIM_SERIALIZERS, [cgc.LIMITED_FSIM_DESERIALIZER] + ) + q1 = cirq.GridQubit(5, 4) + q2 = cirq.GridQubit(5, 5) + op = gate(q1, q2) + if phys_z: + op = op.with_tags(cg.PhysicalZTag()) + expected = op_proto( + { + 'gate': {'id': 'fsim'}, + 'args': {'theta': theta, 'phi': phi, **_phys_z_args(phys_z)}, + 'qubits': [{'id': '5_4'}, {'id': '5_5'}], + } + ) + proto = gate_set.serialize_op(op, arg_function_language='linear') + actual = gate_set.deserialize_op(proto, arg_function_language='linear') + assert proto == expected + assert actual == op + assert_phys_z_tag(phys_z, actual) @pytest.mark.parametrize('phys_z', [False, True]) def test_serialize_deserialize_iswap_symbols(phys_z): - gate_set = cg.SerializableGateSet( - 'test', cgc.LIMITED_FSIM_SERIALIZERS, [cgc.LIMITED_FSIM_DESERIALIZER] - ) - q1 = cirq.GridQubit(5, 4) - q2 = cirq.GridQubit(5, 5) - op = cirq.ISWAP(q1, q2) ** sympy.Symbol('t') - if phys_z: - op = op.with_tags(cg.PhysicalZTag()) - proto = gate_set.serialize_op(op, arg_function_language='linear') - actual = gate_set.deserialize_op(proto, arg_function_language='linear') - assert isinstance(actual.untagged.gate, cirq.FSimGate) - assert math.isclose(actual.untagged.gate.phi, 0) - assert math.isclose(actual.untagged.gate.theta.subs('t', 2), -np.pi, abs_tol=1e-5) - assert_phys_z_tag(phys_z, actual) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + gate_set = cg.SerializableGateSet( + 'test', cgc.LIMITED_FSIM_SERIALIZERS, [cgc.LIMITED_FSIM_DESERIALIZER] + ) + q1 = cirq.GridQubit(5, 4) + q2 = cirq.GridQubit(5, 5) + op = cirq.ISWAP(q1, q2) ** sympy.Symbol('t') + if phys_z: + op = op.with_tags(cg.PhysicalZTag()) + proto = gate_set.serialize_op(op, arg_function_language='linear') + actual = gate_set.deserialize_op(proto, arg_function_language='linear') + assert isinstance(actual.untagged.gate, cirq.FSimGate) + assert math.isclose(actual.untagged.gate.phi, 0) + assert math.isclose(actual.untagged.gate.theta.subs('t', 2), -np.pi, abs_tol=1e-5) + assert_phys_z_tag(phys_z, actual) @pytest.mark.parametrize( @@ -636,10 +650,11 @@ def test_serialize_deserialize_iswap_symbols(phys_z): ], ) def test_fsim_gate_not_allowed(gate): - q1 = cirq.GridQubit(5, 4) - q2 = cirq.GridQubit(5, 5) - gate_set = cg.SerializableGateSet( - 'test', cgc.LIMITED_FSIM_SERIALIZERS, [cgc.LIMITED_FSIM_DESERIALIZER] - ) - with pytest.raises(ValueError): - gate_set.serialize_op(gate(q1, q2)) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=None): + q1 = cirq.GridQubit(5, 4) + q2 = cirq.GridQubit(5, 5) + gate_set = cg.SerializableGateSet( + 'test', cgc.LIMITED_FSIM_SERIALIZERS, [cgc.LIMITED_FSIM_DESERIALIZER] + ) + with pytest.raises(ValueError): + gate_set.serialize_op(gate(q1, q2)) diff --git a/cirq-google/cirq_google/serialization/gate_sets.py b/cirq-google/cirq_google/serialization/gate_sets.py index ca15f0ff710..f1c55c0a1c3 100644 --- a/cirq-google/cirq_google/serialization/gate_sets.py +++ b/cirq-google/cirq_google/serialization/gate_sets.py @@ -12,7 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. """Gate sets supported by Google's apis.""" +from typing import cast + from cirq._doc import document +from cirq import _compat from cirq_google.serialization import serializable_gate_set from cirq_google.serialization.common_serializers import ( SINGLE_QUBIT_SERIALIZERS, @@ -37,85 +40,97 @@ CIRCUIT_OP_DESERIALIZER, ) -SYC_GATESET = serializable_gate_set.SerializableGateSet( - gate_set_name='sycamore', - serializers=[ - SYC_SERIALIZER, - *SINGLE_QUBIT_SERIALIZERS, - *SINGLE_QUBIT_HALF_PI_SERIALIZERS, - MEASUREMENT_SERIALIZER, - WAIT_GATE_SERIALIZER, - CIRCUIT_OP_SERIALIZER, - ], - deserializers=[ - SYC_DESERIALIZER, - *SINGLE_QUBIT_DESERIALIZERS, - *SINGLE_QUBIT_HALF_PI_DESERIALIZERS, - MEASUREMENT_DESERIALIZER, - WAIT_GATE_DESERIALIZER, - CIRCUIT_OP_DESERIALIZER, - ], +SYC_GATESET = cast( + serializable_gate_set.SerializableGateSet, + serializable_gate_set._SerializableGateSet( + gate_set_name='sycamore', + serializers=[ + SYC_SERIALIZER, + *SINGLE_QUBIT_SERIALIZERS, + *SINGLE_QUBIT_HALF_PI_SERIALIZERS, + MEASUREMENT_SERIALIZER, + WAIT_GATE_SERIALIZER, + CIRCUIT_OP_SERIALIZER, + ], + deserializers=[ + SYC_DESERIALIZER, + *SINGLE_QUBIT_DESERIALIZERS, + *SINGLE_QUBIT_HALF_PI_DESERIALIZERS, + MEASUREMENT_DESERIALIZER, + WAIT_GATE_DESERIALIZER, + CIRCUIT_OP_DESERIALIZER, + ], + ), ) document(SYC_GATESET, """Gate set with fsim(pi/2, pi/6) as the core 2 qubit interaction.""") -SQRT_ISWAP_GATESET = serializable_gate_set.SerializableGateSet( - gate_set_name='sqrt_iswap', - serializers=[ - *SQRT_ISWAP_SERIALIZERS, - *SINGLE_QUBIT_SERIALIZERS, - MEASUREMENT_SERIALIZER, - WAIT_GATE_SERIALIZER, - CIRCUIT_OP_SERIALIZER, - ], - deserializers=[ - *SQRT_ISWAP_DESERIALIZERS, - *SINGLE_QUBIT_DESERIALIZERS, - MEASUREMENT_DESERIALIZER, - WAIT_GATE_DESERIALIZER, - CIRCUIT_OP_DESERIALIZER, - ], +SQRT_ISWAP_GATESET = cast( + serializable_gate_set.SerializableGateSet, + serializable_gate_set._SerializableGateSet( + gate_set_name='sqrt_iswap', + serializers=[ + *SQRT_ISWAP_SERIALIZERS, + *SINGLE_QUBIT_SERIALIZERS, + MEASUREMENT_SERIALIZER, + WAIT_GATE_SERIALIZER, + CIRCUIT_OP_SERIALIZER, + ], + deserializers=[ + *SQRT_ISWAP_DESERIALIZERS, + *SINGLE_QUBIT_DESERIALIZERS, + MEASUREMENT_DESERIALIZER, + WAIT_GATE_DESERIALIZER, + CIRCUIT_OP_DESERIALIZER, + ], + ), ) document(SQRT_ISWAP_GATESET, """Gate set with sqrt(iswap) as the core 2 qubit interaction.""") -FSIM_GATESET = serializable_gate_set.SerializableGateSet( - gate_set_name='fsim', - serializers=[ - *LIMITED_FSIM_SERIALIZERS, - *SINGLE_QUBIT_SERIALIZERS, - MEASUREMENT_SERIALIZER, - WAIT_GATE_SERIALIZER, - CIRCUIT_OP_SERIALIZER, - ], - deserializers=[ - LIMITED_FSIM_DESERIALIZER, - *SINGLE_QUBIT_DESERIALIZERS, - MEASUREMENT_DESERIALIZER, - WAIT_GATE_DESERIALIZER, - CIRCUIT_OP_DESERIALIZER, - ], +FSIM_GATESET = cast( + serializable_gate_set.SerializableGateSet, + serializable_gate_set._SerializableGateSet( + gate_set_name='fsim', + serializers=[ + *LIMITED_FSIM_SERIALIZERS, + *SINGLE_QUBIT_SERIALIZERS, + MEASUREMENT_SERIALIZER, + WAIT_GATE_SERIALIZER, + CIRCUIT_OP_SERIALIZER, + ], + deserializers=[ + LIMITED_FSIM_DESERIALIZER, + *SINGLE_QUBIT_DESERIALIZERS, + MEASUREMENT_DESERIALIZER, + WAIT_GATE_DESERIALIZER, + CIRCUIT_OP_DESERIALIZER, + ], + ), ) document(FSIM_GATESET, """Gate set that combines sqrt(iswap) and syc as one fsim id.""") -EXPERIMENTAL_PULSE_GATESET = serializable_gate_set.SerializableGateSet( - gate_set_name='pulse', - serializers=[ - COUPLER_PULSE_SERIALIZER, - *LIMITED_FSIM_SERIALIZERS, - *SINGLE_QUBIT_SERIALIZERS, - MEASUREMENT_SERIALIZER, - WAIT_GATE_SERIALIZER, - CIRCUIT_OP_SERIALIZER, - ], - deserializers=[ - COUPLER_PULSE_DESERIALIZER, - LIMITED_FSIM_DESERIALIZER, - *SINGLE_QUBIT_DESERIALIZERS, - MEASUREMENT_DESERIALIZER, - WAIT_GATE_DESERIALIZER, - CIRCUIT_OP_DESERIALIZER, - ], +EXPERIMENTAL_PULSE_GATESET = cast( + serializable_gate_set.SerializableGateSet, + serializable_gate_set._SerializableGateSet( + gate_set_name='pulse', + serializers=[ + COUPLER_PULSE_SERIALIZER, + *LIMITED_FSIM_SERIALIZERS, + *SINGLE_QUBIT_SERIALIZERS, + MEASUREMENT_SERIALIZER, + WAIT_GATE_SERIALIZER, + CIRCUIT_OP_SERIALIZER, + ], + deserializers=[ + COUPLER_PULSE_DESERIALIZER, + LIMITED_FSIM_DESERIALIZER, + *SINGLE_QUBIT_DESERIALIZERS, + MEASUREMENT_DESERIALIZER, + WAIT_GATE_DESERIALIZER, + CIRCUIT_OP_DESERIALIZER, + ], + ), ) document( EXPERIMENTAL_PULSE_GATESET, @@ -124,20 +139,23 @@ # The xmon gate set. -XMON = serializable_gate_set.SerializableGateSet( - gate_set_name='xmon', - serializers=[ - *SINGLE_QUBIT_SERIALIZERS, - CZ_POW_SERIALIZER, - MEASUREMENT_SERIALIZER, - CIRCUIT_OP_SERIALIZER, - ], - deserializers=[ - *SINGLE_QUBIT_DESERIALIZERS, - CZ_POW_DESERIALIZER, - MEASUREMENT_DESERIALIZER, - CIRCUIT_OP_DESERIALIZER, - ], +XMON = cast( + serializable_gate_set.SerializableGateSet, + serializable_gate_set._SerializableGateSet( + gate_set_name='xmon', + serializers=[ + *SINGLE_QUBIT_SERIALIZERS, + CZ_POW_SERIALIZER, + MEASUREMENT_SERIALIZER, + CIRCUIT_OP_SERIALIZER, + ], + deserializers=[ + *SINGLE_QUBIT_DESERIALIZERS, + CZ_POW_DESERIALIZER, + MEASUREMENT_DESERIALIZER, + CIRCUIT_OP_DESERIALIZER, + ], + ), ) document(XMON, """Gate set for XMON devices.""") @@ -148,3 +166,28 @@ GOOGLE_GATESETS = [SYC_GATESET, SQRT_ISWAP_GATESET, FSIM_GATESET, XMON] document(GOOGLE_GATESETS, """All Google gatesets""") + + +_compat.deprecate_attributes( + __name__, + { + 'EXPERIMENTAL_PULSE_GATESET': ( + 'v0.16', + 'SerializableGateSet will no longer be supported.' + ' In cirq_google.GridDevice, the new representation of Google devices, the gateset of ' + ' a device is represented as a cirq.Gateset and is available as' + ' GridDevice.metadata.gateset.' + ' Engine methods no longer require gate sets to be passed in.' + ' In addition, circuit serialization is replaced by cirq_google.CircuitSerializer.', + ), + 'GOOGLE_GATESETS': ( + 'v0.16', + 'SerializableGateSet will no longer be supported.' + ' In cirq_google.GridDevice, the new representation of Google devices, the gateset of ' + ' a device is represented as a cirq.Gateset and is available as' + ' GridDevice.metadata.gateset.' + ' Engine methods no longer require gate sets to be passed in.' + ' In addition, circuit serialization is replaced by cirq_google.CircuitSerializer.', + ), + }, +) diff --git a/cirq-google/cirq_google/serialization/gate_sets_test.py b/cirq-google/cirq_google/serialization/gate_sets_test.py index 354b2150a85..8a37ec7b1c0 100644 --- a/cirq-google/cirq_google/serialization/gate_sets_test.py +++ b/cirq-google/cirq_google/serialization/gate_sets_test.py @@ -42,19 +42,20 @@ def op_proto(json_dict: Dict) -> v2.program_pb2.Operation: ], ) def test_serialize_exp_w(gate, axis_half_turns, half_turns): - q = cirq.GridQubit(1, 2) - expected = op_proto( - { - 'gate': {'id': 'xy'}, - 'args': { - 'axis_half_turns': {'arg_value': {'float_value': axis_half_turns}}, - 'half_turns': {'arg_value': {'float_value': half_turns}}, - }, - 'qubits': [{'id': '1_2'}], - } - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + q = cirq.GridQubit(1, 2) + expected = op_proto( + { + 'gate': {'id': 'xy'}, + 'args': { + 'axis_half_turns': {'arg_value': {'float_value': axis_half_turns}}, + 'half_turns': {'arg_value': {'float_value': half_turns}}, + }, + 'qubits': [{'id': '1_2'}], + } + ) - assert cg.XMON.serialize_op(gate.on(q)) == expected + assert cg.XMON.serialize_op(gate.on(q)) == expected @pytest.mark.parametrize( @@ -66,36 +67,38 @@ def test_serialize_exp_w(gate, axis_half_turns, half_turns): ], ) def test_serialize_exp_w_parameterized_half_turns(gate, axis_half_turns, half_turns): - q = cirq.GridQubit(1, 2) - expected = op_proto( - { - 'gate': {'id': 'xy'}, - 'args': { - 'axis_half_turns': {'arg_value': {'float_value': axis_half_turns}}, - 'half_turns': {'symbol': half_turns}, - }, - 'qubits': [{'id': '1_2'}], - } - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + q = cirq.GridQubit(1, 2) + expected = op_proto( + { + 'gate': {'id': 'xy'}, + 'args': { + 'axis_half_turns': {'arg_value': {'float_value': axis_half_turns}}, + 'half_turns': {'symbol': half_turns}, + }, + 'qubits': [{'id': '1_2'}], + } + ) - assert cg.XMON.serialize_op(gate.on(q)) == expected + assert cg.XMON.serialize_op(gate.on(q)) == expected def test_serialize_exp_w_parameterized_axis_half_turns(): - gate = cirq.PhasedXPowGate(exponent=0.25, phase_exponent=sympy.Symbol('x')) - q = cirq.GridQubit(1, 2) - expected = op_proto( - { - 'gate': {'id': 'xy'}, - 'args': { - 'axis_half_turns': {'symbol': 'x'}, - 'half_turns': {'arg_value': {'float_value': 0.25}}, - }, - 'qubits': [{'id': '1_2'}], - } - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + gate = cirq.PhasedXPowGate(exponent=0.25, phase_exponent=sympy.Symbol('x')) + q = cirq.GridQubit(1, 2) + expected = op_proto( + { + 'gate': {'id': 'xy'}, + 'args': { + 'axis_half_turns': {'symbol': 'x'}, + 'half_turns': {'arg_value': {'float_value': 0.25}}, + }, + 'qubits': [{'id': '1_2'}], + } + ) - assert cg.XMON.serialize_op(gate.on(q)) == expected + assert cg.XMON.serialize_op(gate.on(q)) == expected @pytest.mark.parametrize( @@ -103,58 +106,62 @@ def test_serialize_exp_w_parameterized_axis_half_turns(): [(cirq.Z, 1.0), (cirq.Z**0.125, 0.125), (cirq.rz(0.125 * np.pi), 0.125)], ) def test_serialize_exp_z(gate, half_turns): - q = cirq.GridQubit(1, 2) - assert cg.XMON.serialize_op(gate.on(q)) == op_proto( - { - 'gate': {'id': 'z'}, - 'args': { - 'half_turns': {'arg_value': {'float_value': half_turns}}, - 'type': {'arg_value': {'string_value': 'virtual_propagates_forward'}}, - }, - 'qubits': [{'id': '1_2'}], - } - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + q = cirq.GridQubit(1, 2) + assert cg.XMON.serialize_op(gate.on(q)) == op_proto( + { + 'gate': {'id': 'z'}, + 'args': { + 'half_turns': {'arg_value': {'float_value': half_turns}}, + 'type': {'arg_value': {'string_value': 'virtual_propagates_forward'}}, + }, + 'qubits': [{'id': '1_2'}], + } + ) def test_serialize_exp_z_parameterized(): - q = cirq.GridQubit(1, 2) - gate = cirq.Z ** sympy.Symbol('x') - assert cg.XMON.serialize_op(gate.on(q)) == op_proto( - { - 'gate': {'id': 'z'}, - 'args': { - 'half_turns': {'symbol': 'x'}, - 'type': {'arg_value': {'string_value': 'virtual_propagates_forward'}}, - }, - 'qubits': [{'id': '1_2'}], - } - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + q = cirq.GridQubit(1, 2) + gate = cirq.Z ** sympy.Symbol('x') + assert cg.XMON.serialize_op(gate.on(q)) == op_proto( + { + 'gate': {'id': 'z'}, + 'args': { + 'half_turns': {'symbol': 'x'}, + 'type': {'arg_value': {'string_value': 'virtual_propagates_forward'}}, + }, + 'qubits': [{'id': '1_2'}], + } + ) @pytest.mark.parametrize(('gate', 'half_turns'), [(cirq.CZ, 1.0), (cirq.CZ**0.125, 0.125)]) def test_serialize_exp_11(gate, half_turns): - c = cirq.GridQubit(1, 2) - t = cirq.GridQubit(1, 3) - assert cg.XMON.serialize_op(gate.on(c, t)) == op_proto( - { - 'gate': {'id': 'cz'}, - 'args': {'half_turns': {'arg_value': {'float_value': half_turns}}}, - 'qubits': [{'id': '1_2'}, {'id': '1_3'}], - } - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + c = cirq.GridQubit(1, 2) + t = cirq.GridQubit(1, 3) + assert cg.XMON.serialize_op(gate.on(c, t)) == op_proto( + { + 'gate': {'id': 'cz'}, + 'args': {'half_turns': {'arg_value': {'float_value': half_turns}}}, + 'qubits': [{'id': '1_2'}, {'id': '1_3'}], + } + ) def test_serialize_exp_11_parameterized(): - c = cirq.GridQubit(1, 2) - t = cirq.GridQubit(1, 3) - gate = cirq.CZ ** sympy.Symbol('x') - assert cg.XMON.serialize_op(gate.on(c, t)) == op_proto( - { - 'gate': {'id': 'cz'}, - 'args': {'half_turns': {'symbol': 'x'}}, - 'qubits': [{'id': '1_2'}, {'id': '1_3'}], - } - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + c = cirq.GridQubit(1, 2) + t = cirq.GridQubit(1, 3) + gate = cirq.CZ ** sympy.Symbol('x') + assert cg.XMON.serialize_op(gate.on(c, t)) == op_proto( + { + 'gate': {'id': 'cz'}, + 'args': {'half_turns': {'symbol': 'x'}}, + 'qubits': [{'id': '1_2'}, {'id': '1_3'}], + } + ) @pytest.mark.parametrize( @@ -166,130 +173,145 @@ def test_serialize_exp_11_parameterized(): ], ) def test_serialize_meas(qubits, qubit_ids, key, invert_mask): - op = cirq.measure(*qubits, key=key, invert_mask=invert_mask) - expected = op_proto( - { - 'gate': {'id': 'meas'}, - 'qubits': [{'id': id} for id in qubit_ids], - 'args': { - 'key': {'arg_value': {'string_value': key}}, - 'invert_mask': {'arg_value': {'bool_values': {'values': list(invert_mask)}}}, - }, - } - ) - assert cg.XMON.serialize_op(op) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + op = cirq.measure(*qubits, key=key, invert_mask=invert_mask) + expected = op_proto( + { + 'gate': {'id': 'meas'}, + 'qubits': [{'id': id} for id in qubit_ids], + 'args': { + 'key': {'arg_value': {'string_value': key}}, + 'invert_mask': {'arg_value': {'bool_values': {'values': list(invert_mask)}}}, + }, + } + ) + assert cg.XMON.serialize_op(op) == expected def test_serialize_circuit(): - q0 = cirq.GridQubit(1, 1) - q1 = cirq.GridQubit(1, 2) - circuit = cirq.Circuit(cirq.CZ(q0, q1), cirq.X(q0), cirq.Z(q1), cirq.measure(q1, key='m')) - expected = v2.program_pb2.Program( - language=v2.program_pb2.Language(arg_function_language='', gate_set='xmon'), - circuit=v2.program_pb2.Circuit( - scheduling_strategy=v2.program_pb2.Circuit.MOMENT_BY_MOMENT, - moments=[ - v2.program_pb2.Moment(operations=[cg.XMON.serialize_op(cirq.CZ(q0, q1))]), - v2.program_pb2.Moment( - operations=[cg.XMON.serialize_op(cirq.X(q0)), cg.XMON.serialize_op(cirq.Z(q1))] - ), - v2.program_pb2.Moment(operations=[cg.XMON.serialize_op(cirq.measure(q1, key='m'))]), - ], - ), - ) - assert cg.XMON.serialize(circuit) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=5): + q0 = cirq.GridQubit(1, 1) + q1 = cirq.GridQubit(1, 2) + circuit = cirq.Circuit(cirq.CZ(q0, q1), cirq.X(q0), cirq.Z(q1), cirq.measure(q1, key='m')) + expected = v2.program_pb2.Program( + language=v2.program_pb2.Language(arg_function_language='', gate_set='xmon'), + circuit=v2.program_pb2.Circuit( + scheduling_strategy=v2.program_pb2.Circuit.MOMENT_BY_MOMENT, + moments=[ + v2.program_pb2.Moment(operations=[cg.XMON.serialize_op(cirq.CZ(q0, q1))]), + v2.program_pb2.Moment( + operations=[ + cg.XMON.serialize_op(cirq.X(q0)), + cg.XMON.serialize_op(cirq.Z(q1)), + ] + ), + v2.program_pb2.Moment( + operations=[cg.XMON.serialize_op(cirq.measure(q1, key='m'))] + ), + ], + ), + ) + assert cg.XMON.serialize(circuit) == expected @pytest.mark.parametrize(('axis_half_turns', 'half_turns'), [(0.25, 0.25), (0, 0.25), (0.5, 0.25)]) def test_deserialize_exp_w(axis_half_turns, half_turns): - serialized_op = op_proto( - { - 'gate': {'id': 'xy'}, - 'args': { - 'axis_half_turns': {'arg_value': {'float_value': axis_half_turns}}, - 'half_turns': {'arg_value': {'float_value': half_turns}}, - }, - 'qubits': [{'id': '1_2'}], - } - ) - q = cirq.GridQubit(1, 2) - expected = cirq.PhasedXPowGate(exponent=half_turns, phase_exponent=axis_half_turns)(q) - assert cg.XMON.deserialize_op(serialized_op) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + serialized_op = op_proto( + { + 'gate': {'id': 'xy'}, + 'args': { + 'axis_half_turns': {'arg_value': {'float_value': axis_half_turns}}, + 'half_turns': {'arg_value': {'float_value': half_turns}}, + }, + 'qubits': [{'id': '1_2'}], + } + ) + q = cirq.GridQubit(1, 2) + expected = cirq.PhasedXPowGate(exponent=half_turns, phase_exponent=axis_half_turns)(q) + assert cg.XMON.deserialize_op(serialized_op) == expected def test_deserialize_exp_w_parameterized(): - serialized_op = op_proto( - { - 'gate': {'id': 'xy'}, - 'args': {'axis_half_turns': {'symbol': 'x'}, 'half_turns': {'symbol': 'y'}}, - 'qubits': [{'id': '1_2'}], - } - ) - q = cirq.GridQubit(1, 2) - expected = cirq.PhasedXPowGate(exponent=sympy.Symbol('y'), phase_exponent=sympy.Symbol('x'))(q) - assert cg.XMON.deserialize_op(serialized_op) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + serialized_op = op_proto( + { + 'gate': {'id': 'xy'}, + 'args': {'axis_half_turns': {'symbol': 'x'}, 'half_turns': {'symbol': 'y'}}, + 'qubits': [{'id': '1_2'}], + } + ) + q = cirq.GridQubit(1, 2) + expected = cirq.PhasedXPowGate( + exponent=sympy.Symbol('y'), phase_exponent=sympy.Symbol('x') + )(q) + assert cg.XMON.deserialize_op(serialized_op) == expected @pytest.mark.parametrize('half_turns', [0, 0.25, 1.0]) def test_deserialize_exp_z(half_turns): - serialized_op = op_proto( - { - 'gate': {'id': 'z'}, - 'args': { - 'half_turns': {'arg_value': {'float_value': half_turns}}, - 'type': {'arg_value': {'string_value': 'virtual_propagates_forward'}}, - }, - 'qubits': [{'id': '1_2'}], - } - ) - q = cirq.GridQubit(1, 2) - expected = cirq.ZPowGate(exponent=half_turns)(q) - assert cg.XMON.deserialize_op(serialized_op) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + serialized_op = op_proto( + { + 'gate': {'id': 'z'}, + 'args': { + 'half_turns': {'arg_value': {'float_value': half_turns}}, + 'type': {'arg_value': {'string_value': 'virtual_propagates_forward'}}, + }, + 'qubits': [{'id': '1_2'}], + } + ) + q = cirq.GridQubit(1, 2) + expected = cirq.ZPowGate(exponent=half_turns)(q) + assert cg.XMON.deserialize_op(serialized_op) == expected def test_deserialize_exp_z_parameterized(): - serialized_op = op_proto( - { - 'gate': {'id': 'z'}, - 'args': { - 'half_turns': {'symbol': 'x'}, - 'type': {'arg_value': {'string_value': 'virtual_propagates_forward'}}, - }, - 'qubits': [{'id': '1_2'}], - } - ) - q = cirq.GridQubit(1, 2) - expected = cirq.ZPowGate(exponent=sympy.Symbol('x'))(q) - assert cg.XMON.deserialize_op(serialized_op) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + serialized_op = op_proto( + { + 'gate': {'id': 'z'}, + 'args': { + 'half_turns': {'symbol': 'x'}, + 'type': {'arg_value': {'string_value': 'virtual_propagates_forward'}}, + }, + 'qubits': [{'id': '1_2'}], + } + ) + q = cirq.GridQubit(1, 2) + expected = cirq.ZPowGate(exponent=sympy.Symbol('x'))(q) + assert cg.XMON.deserialize_op(serialized_op) == expected @pytest.mark.parametrize('half_turns', [0, 0.25, 1.0]) def test_deserialize_exp_11(half_turns): - serialized_op = op_proto( - { - 'gate': {'id': 'cz'}, - 'args': {'half_turns': {'arg_value': {'float_value': half_turns}}}, - 'qubits': [{'id': '1_2'}, {'id': '2_2'}], - } - ) - c = cirq.GridQubit(1, 2) - t = cirq.GridQubit(2, 2) - expected = cirq.CZPowGate(exponent=half_turns)(c, t) - assert cg.XMON.deserialize_op(serialized_op) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + serialized_op = op_proto( + { + 'gate': {'id': 'cz'}, + 'args': {'half_turns': {'arg_value': {'float_value': half_turns}}}, + 'qubits': [{'id': '1_2'}, {'id': '2_2'}], + } + ) + c = cirq.GridQubit(1, 2) + t = cirq.GridQubit(2, 2) + expected = cirq.CZPowGate(exponent=half_turns)(c, t) + assert cg.XMON.deserialize_op(serialized_op) == expected def test_deserialize_exp_11_parameterized(): - serialized_op = op_proto( - { - 'gate': {'id': 'cz'}, - 'args': {'half_turns': {'symbol': 'x'}}, - 'qubits': [{'id': '1_2'}, {'id': '2_2'}], - } - ) - c = cirq.GridQubit(1, 2) - t = cirq.GridQubit(2, 2) - expected = cirq.CZPowGate(exponent=sympy.Symbol('x'))(c, t) - assert cg.XMON.deserialize_op(serialized_op) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + serialized_op = op_proto( + { + 'gate': {'id': 'cz'}, + 'args': {'half_turns': {'symbol': 'x'}}, + 'qubits': [{'id': '1_2'}, {'id': '2_2'}], + } + ) + c = cirq.GridQubit(1, 2) + t = cirq.GridQubit(2, 2) + expected = cirq.CZPowGate(exponent=sympy.Symbol('x'))(c, t) + assert cg.XMON.deserialize_op(serialized_op) == expected @pytest.mark.parametrize( @@ -301,127 +323,142 @@ def test_deserialize_exp_11_parameterized(): ], ) def test_deserialize_meas(qubits, qubit_ids, key, invert_mask): - serialized_op = op_proto( - { - 'gate': {'id': 'meas'}, - 'args': { - 'invert_mask': {'arg_value': {'bool_values': {'values': list(invert_mask)}}}, - 'key': {'arg_value': {'string_value': key}}, - }, - 'qubits': [{'id': id} for id in qubit_ids], - } - ) - expected = cirq.measure(*qubits, key=key, invert_mask=invert_mask) - assert cg.XMON.deserialize_op(serialized_op) == expected + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + serialized_op = op_proto( + { + 'gate': {'id': 'meas'}, + 'args': { + 'invert_mask': {'arg_value': {'bool_values': {'values': list(invert_mask)}}}, + 'key': {'arg_value': {'string_value': key}}, + }, + 'qubits': [{'id': id} for id in qubit_ids], + } + ) + expected = cirq.measure(*qubits, key=key, invert_mask=invert_mask) + assert cg.XMON.deserialize_op(serialized_op) == expected def test_deserialize_circuit(): - q0 = cirq.GridQubit(1, 1) - q1 = cirq.GridQubit(1, 2) - circuit = cirq.Circuit(cirq.CZ(q0, q1), cirq.X(q0), cirq.Z(q1), cirq.measure(q1, key='m')) - serialized = v2.program_pb2.Program( - language=v2.program_pb2.Language(gate_set='xmon'), - circuit=v2.program_pb2.Circuit( - scheduling_strategy=v2.program_pb2.Circuit.MOMENT_BY_MOMENT, - moments=[ - v2.program_pb2.Moment(operations=[cg.XMON.serialize_op(cirq.CZ(q0, q1))]), - v2.program_pb2.Moment( - operations=[cg.XMON.serialize_op(cirq.X(q0)), cg.XMON.serialize_op(cirq.Z(q1))] - ), - v2.program_pb2.Moment(operations=[cg.XMON.serialize_op(cirq.measure(q1, key='m'))]), - ], - ), - ) - assert cg.XMON.deserialize(serialized) == circuit + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=5): + q0 = cirq.GridQubit(1, 1) + q1 = cirq.GridQubit(1, 2) + circuit = cirq.Circuit(cirq.CZ(q0, q1), cirq.X(q0), cirq.Z(q1), cirq.measure(q1, key='m')) + serialized = v2.program_pb2.Program( + language=v2.program_pb2.Language(gate_set='xmon'), + circuit=v2.program_pb2.Circuit( + scheduling_strategy=v2.program_pb2.Circuit.MOMENT_BY_MOMENT, + moments=[ + v2.program_pb2.Moment(operations=[cg.XMON.serialize_op(cirq.CZ(q0, q1))]), + v2.program_pb2.Moment( + operations=[ + cg.XMON.serialize_op(cirq.X(q0)), + cg.XMON.serialize_op(cirq.Z(q1)), + ] + ), + v2.program_pb2.Moment( + operations=[cg.XMON.serialize_op(cirq.measure(q1, key='m'))] + ), + ], + ), + ) + assert cg.XMON.deserialize(serialized) == circuit def test_deserialize_schedule(): - q0 = cirq.GridQubit(4, 4) - q1 = cirq.GridQubit(4, 5) - circuit = cirq.Circuit(cirq.CZ(q0, q1), cirq.X(q0), cirq.Z(q1), cirq.measure(q0, key='a')) - serialized = v2.program_pb2.Program( - language=v2.program_pb2.Language(gate_set='xmon'), - schedule=v2.program_pb2.Schedule( - scheduled_operations=[ - v2.program_pb2.ScheduledOperation( - operation=cg.XMON.serialize_op(cirq.CZ(q0, q1)), start_time_picos=0 - ), - v2.program_pb2.ScheduledOperation( - operation=cg.XMON.serialize_op(cirq.X(q0)), start_time_picos=200000 - ), - v2.program_pb2.ScheduledOperation( - operation=cg.XMON.serialize_op(cirq.Z(q1)), start_time_picos=200000 - ), - v2.program_pb2.ScheduledOperation( - operation=cg.XMON.serialize_op(cirq.measure(q0, key='a')), - start_time_picos=400000, - ), - ] - ), - ) - assert cg.XMON.deserialize(serialized) == circuit + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=5): + q0 = cirq.GridQubit(4, 4) + q1 = cirq.GridQubit(4, 5) + circuit = cirq.Circuit(cirq.CZ(q0, q1), cirq.X(q0), cirq.Z(q1), cirq.measure(q0, key='a')) + serialized = v2.program_pb2.Program( + language=v2.program_pb2.Language(gate_set='xmon'), + schedule=v2.program_pb2.Schedule( + scheduled_operations=[ + v2.program_pb2.ScheduledOperation( + operation=cg.XMON.serialize_op(cirq.CZ(q0, q1)), start_time_picos=0 + ), + v2.program_pb2.ScheduledOperation( + operation=cg.XMON.serialize_op(cirq.X(q0)), start_time_picos=200000 + ), + v2.program_pb2.ScheduledOperation( + operation=cg.XMON.serialize_op(cirq.Z(q1)), start_time_picos=200000 + ), + v2.program_pb2.ScheduledOperation( + operation=cg.XMON.serialize_op(cirq.measure(q0, key='a')), + start_time_picos=400000, + ), + ] + ), + ) + assert cg.XMON.deserialize(serialized) == circuit def test_serialize_deserialize_syc(): - proto = op_proto({'gate': {'id': 'syc'}, 'args': {}, 'qubits': [{'id': '1_2'}, {'id': '1_3'}]}) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=2): + proto = op_proto( + {'gate': {'id': 'syc'}, 'args': {}, 'qubits': [{'id': '1_2'}, {'id': '1_3'}]} + ) - q0 = cirq.GridQubit(1, 2) - q1 = cirq.GridQubit(1, 3) - op = cg.SYC(q0, q1) - assert cg.SYC_GATESET.serialize_op(op) == proto - assert cg.SYC_GATESET.deserialize_op(proto) == op + q0 = cirq.GridQubit(1, 2) + q1 = cirq.GridQubit(1, 3) + op = cg.SYC(q0, q1) + assert cg.SYC_GATESET.serialize_op(op) == proto + assert cg.SYC_GATESET.deserialize_op(proto) == op def test_serialize_fails_on_other_fsim_gates(): - a = cirq.GridQubit(1, 2) - b = cirq.GridQubit(2, 2) - op = cirq.FSimGate(phi=0.5, theta=-0.2)(a, b) - with pytest.raises(ValueError, match='Cannot serialize'): - _ = cg.SYC_GATESET.serialize_op(op) - with pytest.raises(ValueError, match='Cannot serialize'): - _ = cg.SQRT_ISWAP_GATESET.serialize_op(op) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=2): + a = cirq.GridQubit(1, 2) + b = cirq.GridQubit(2, 2) + op = cirq.FSimGate(phi=0.5, theta=-0.2)(a, b) + with pytest.raises(ValueError, match='Cannot serialize'): + _ = cg.SYC_GATESET.serialize_op(op) + with pytest.raises(ValueError, match='Cannot serialize'): + _ = cg.SQRT_ISWAP_GATESET.serialize_op(op) def test_serialize_fails_on_symbols(): - a = cirq.GridQubit(1, 2) - b = cirq.GridQubit(2, 2) - op = cirq.FSimGate(phi=np.pi / 2, theta=sympy.Symbol('t'))(a, b) - with pytest.raises(ValueError, match='Cannot serialize'): - _ = cg.SYC_GATESET.serialize_op(op) - with pytest.raises(ValueError, match='Cannot serialize'): - _ = cg.SQRT_ISWAP_GATESET.serialize_op(op) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=2): + a = cirq.GridQubit(1, 2) + b = cirq.GridQubit(2, 2) + op = cirq.FSimGate(phi=np.pi / 2, theta=sympy.Symbol('t'))(a, b) + with pytest.raises(ValueError, match='Cannot serialize'): + _ = cg.SYC_GATESET.serialize_op(op) + with pytest.raises(ValueError, match='Cannot serialize'): + _ = cg.SQRT_ISWAP_GATESET.serialize_op(op) def test_serialize_deserialize_sqrt_iswap(): - proto = op_proto( - {'gate': {'id': 'fsim_pi_4'}, 'args': {}, 'qubits': [{'id': '1_2'}, {'id': '1_3'}]} - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=4): + proto = op_proto( + {'gate': {'id': 'fsim_pi_4'}, 'args': {}, 'qubits': [{'id': '1_2'}, {'id': '1_3'}]} + ) - q0 = cirq.GridQubit(1, 2) - q1 = cirq.GridQubit(1, 3) - op = cirq.FSimGate(theta=np.pi / 4, phi=0)(q0, q1) - op2 = cirq.ISWAP(q0, q1) ** -0.5 - assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == proto - assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op - assert cg.SQRT_ISWAP_GATESET.serialize_op(op2) == proto - # Note that ISWAP deserializes back to a FSimGate - assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op + q0 = cirq.GridQubit(1, 2) + q1 = cirq.GridQubit(1, 3) + op = cirq.FSimGate(theta=np.pi / 4, phi=0)(q0, q1) + op2 = cirq.ISWAP(q0, q1) ** -0.5 + assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == proto + assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op + assert cg.SQRT_ISWAP_GATESET.serialize_op(op2) == proto + # Note that ISWAP deserializes back to a FSimGate + assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op def test_serialize_deserialize_inv_sqrt_iswap(): - proto = op_proto( - {'gate': {'id': 'inv_fsim_pi_4'}, 'args': {}, 'qubits': [{'id': '1_2'}, {'id': '1_3'}]} - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=4): + proto = op_proto( + {'gate': {'id': 'inv_fsim_pi_4'}, 'args': {}, 'qubits': [{'id': '1_2'}, {'id': '1_3'}]} + ) - q0 = cirq.GridQubit(1, 2) - q1 = cirq.GridQubit(1, 3) - op = cirq.FSimGate(theta=-np.pi / 4, phi=0)(q0, q1) - op2 = cirq.ISWAP(q0, q1) ** +0.5 - assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == proto - assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op - assert cg.SQRT_ISWAP_GATESET.serialize_op(op2) == proto - # Note that ISWAP deserializes back to a FSimGate - assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op + q0 = cirq.GridQubit(1, 2) + q1 = cirq.GridQubit(1, 3) + op = cirq.FSimGate(theta=-np.pi / 4, phi=0)(q0, q1) + op2 = cirq.ISWAP(q0, q1) ** +0.5 + assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == proto + assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op + assert cg.SQRT_ISWAP_GATESET.serialize_op(op2) == proto + # Note that ISWAP deserializes back to a FSimGate + assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op @pytest.mark.parametrize( @@ -437,27 +474,28 @@ def test_serialize_deserialize_inv_sqrt_iswap(): ], ) def test_serialize_deserialize_arbitrary_xy(gate, axis_half_turns, half_turns): - op = gate.on(cirq.GridQubit(1, 2)) - expected = op_proto( - { - 'gate': {'id': 'xy'}, - 'args': { - 'axis_half_turns': {'arg_value': {'float_value': axis_half_turns}}, - 'half_turns': {'arg_value': {'float_value': half_turns}}, - }, - 'qubits': [{'id': '1_2'}], - } - ) - assert cg.SYC_GATESET.serialize_op(op) == expected - deserialized_op = cg.SYC_GATESET.deserialize_op(expected) - cirq.testing.assert_allclose_up_to_global_phase( - cirq.unitary(deserialized_op), cirq.unitary(op), atol=1e-7 - ) - assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == expected - deserialized_op = cg.SQRT_ISWAP_GATESET.deserialize_op(expected) - cirq.testing.assert_allclose_up_to_global_phase( - cirq.unitary(deserialized_op), cirq.unitary(op), atol=1e-7 - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=4): + op = gate.on(cirq.GridQubit(1, 2)) + expected = op_proto( + { + 'gate': {'id': 'xy'}, + 'args': { + 'axis_half_turns': {'arg_value': {'float_value': axis_half_turns}}, + 'half_turns': {'arg_value': {'float_value': half_turns}}, + }, + 'qubits': [{'id': '1_2'}], + } + ) + assert cg.SYC_GATESET.serialize_op(op) == expected + deserialized_op = cg.SYC_GATESET.deserialize_op(expected) + cirq.testing.assert_allclose_up_to_global_phase( + cirq.unitary(deserialized_op), cirq.unitary(op), atol=1e-7 + ) + assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == expected + deserialized_op = cg.SQRT_ISWAP_GATESET.deserialize_op(expected) + cirq.testing.assert_allclose_up_to_global_phase( + cirq.unitary(deserialized_op), cirq.unitary(op), atol=1e-7 + ) @pytest.mark.parametrize( @@ -469,36 +507,38 @@ def test_serialize_deserialize_arbitrary_xy(gate, axis_half_turns, half_turns): ], ) def test_serialize_deserialize_meas(qubits, qubit_ids, key, invert_mask): - op = cirq.measure(*qubits, key=key, invert_mask=invert_mask) - proto = op_proto( - { - 'gate': {'id': 'meas'}, - 'qubits': [{'id': id} for id in qubit_ids], - 'args': { - 'key': {'arg_value': {'string_value': key}}, - 'invert_mask': {'arg_value': {'bool_values': {'values': list(invert_mask)}}}, - }, - } - ) - assert cg.SYC_GATESET.serialize_op(op) == proto - assert cg.SYC_GATESET.deserialize_op(proto) == op - assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == proto - assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=4): + op = cirq.measure(*qubits, key=key, invert_mask=invert_mask) + proto = op_proto( + { + 'gate': {'id': 'meas'}, + 'qubits': [{'id': id} for id in qubit_ids], + 'args': { + 'key': {'arg_value': {'string_value': key}}, + 'invert_mask': {'arg_value': {'bool_values': {'values': list(invert_mask)}}}, + }, + } + ) + assert cg.SYC_GATESET.serialize_op(op) == proto + assert cg.SYC_GATESET.deserialize_op(proto) == op + assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == proto + assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op def test_serialize_deserialize_wait_gate(): - op = cirq.wait(cirq.GridQubit(1, 2), nanos=50.0) - proto = op_proto( - { - 'gate': {'id': 'wait'}, - 'qubits': [{'id': '1_2'}], - 'args': {'nanos': {'arg_value': {'float_value': 50.0}}}, - } - ) - assert cg.SYC_GATESET.serialize_op(op) == proto - assert cg.SYC_GATESET.deserialize_op(proto) == op - assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == proto - assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=4): + op = cirq.wait(cirq.GridQubit(1, 2), nanos=50.0) + proto = op_proto( + { + 'gate': {'id': 'wait'}, + 'qubits': [{'id': '1_2'}], + 'args': {'nanos': {'arg_value': {'float_value': 50.0}}}, + } + ) + assert cg.SYC_GATESET.serialize_op(op) == proto + assert cg.SYC_GATESET.deserialize_op(proto) == op + assert cg.SQRT_ISWAP_GATESET.serialize_op(op) == proto + assert cg.SQRT_ISWAP_GATESET.deserialize_op(proto) == op def default_circuit_proto(): @@ -520,25 +560,46 @@ def default_circuit(): ) -@pytest.mark.parametrize('gateset', [cg.XMON, cg.SYC_GATESET, cg.SQRT_ISWAP_GATESET]) -def test_serialize_deserialize_circuit_op(gateset): - circuit_op = cirq.CircuitOperation(default_circuit()) - proto = v2.program_pb2.CircuitOperation() - proto.circuit_constant_index = 0 - proto.repetition_specification.repetition_count = 1 - - constants = [default_circuit_proto()] - raw_constants = {default_circuit(): 0} - assert ( - gateset.serialize_op(circuit_op, constants=constants, raw_constants=raw_constants) == proto - ) +@pytest.mark.parametrize('gateset_name', ['xmon', 'syc', 'sqrt_iswap']) +def test_serialize_deserialize_circuit_op(gateset_name): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + gateset = _get_gateset(gateset_name) + circuit_op = cirq.CircuitOperation(default_circuit()) + proto = v2.program_pb2.CircuitOperation() + proto.circuit_constant_index = 0 + proto.repetition_specification.repetition_count = 1 + + constants = [default_circuit_proto()] + raw_constants = {default_circuit(): 0} + assert ( + gateset.serialize_op(circuit_op, constants=constants, raw_constants=raw_constants) + == proto + ) - constants = [default_circuit_proto()] - deserialized_constants = [default_circuit()] + deserialized_constants = [default_circuit()] - assert ( - gateset.deserialize_op( - proto, constants=constants, deserialized_constants=deserialized_constants + assert ( + gateset.deserialize_op( + proto, constants=constants, deserialized_constants=deserialized_constants + ) + == circuit_op ) - == circuit_op - ) + + +def _get_gateset(gateset_name): + if gateset_name == 'xmon': + return cg.XMON + elif gateset_name == 'syc': + return cg.SYC_GATESET + elif gateset_name == 'sqrt_iswap': + return cg.SQRT_ISWAP_GATESET + + +def test_deprecated_experimental_pulse_gateset(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + _ = cg.serialization.gate_sets.EXPERIMENTAL_PULSE_GATESET + + +def test_deprecated_google_gatesets(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + _ = cg.serialization.gate_sets.GOOGLE_GATESETS diff --git a/cirq-google/cirq_google/serialization/serializable_gate_set.py b/cirq-google/cirq_google/serialization/serializable_gate_set.py index 3a76b729ea2..b8d904d45b7 100644 --- a/cirq-google/cirq_google/serialization/serializable_gate_set.py +++ b/cirq-google/cirq_google/serialization/serializable_gate_set.py @@ -24,10 +24,11 @@ _GateOrFrozenCircuitTypes = Union[Type[cirq.Gate], Type[cirq.FrozenCircuit]] -class SerializableGateSet(serializer.Serializer): - """A class for serializing and deserializing programs and operations. +class _SerializableGateSet(serializer.Serializer): + """HACK: non-deprecated version of SerializableGateSet. - This class is for cirq_google.api.v2 protos. + This is used by global gatesets to bypass the behavior that deprecation warnings thrown + during module loading fail unit tests. """ def __init__( @@ -36,19 +37,6 @@ def __init__( serializers: Iterable[op_serializer.OpSerializer], deserializers: Iterable[op_deserializer.OpDeserializer], ): - """Construct the gate set. - - Args: - gate_set_name: The name used to identify the gate set. - serializers: The OpSerializers to use for serialization. - Multiple serializers for a given gate type are allowed and - will be checked for a given type in the order specified here. - This allows for a given gate type to be serialized into - different serialized form depending on the parameters of the - gate. - deserializers: The OpDeserializers to convert serialized - forms of gates or circuits into Operations. - """ super().__init__(gate_set_name) self.serializers: Dict[_GateOrFrozenCircuitTypes, List[op_serializer.OpSerializer]] = {} for s in serializers: @@ -62,14 +50,6 @@ def with_added_types( serializers: Iterable[op_serializer.OpSerializer] = (), deserializers: Iterable[op_deserializer.OpDeserializer] = (), ) -> 'SerializableGateSet': - """Creates a new gateset with additional (de)serializers. - - Args: - gate_set_name: Optional new name of the gateset. If not given, use - the same name as this gateset. - serializers: Serializers to add to those in this gateset. - deserializers: Deserializers to add to those in this gateset. - """ # Iterate over all serializers in this gateset. curr_serializers = ( serializer for serializers in self.serializers.values() for serializer in serializers @@ -491,3 +471,261 @@ def _deserialize_schedule( ) ret = cirq.Circuit(result) return ret + + +@cirq._compat.deprecated_class( + deadline='v0.16', + fix='SerializableGateSet will no longer be supported.' + ' In cirq_google.GridDevice, the new representation of Google devices, the gateset of a device' + ' is represented as a cirq.Gateset and is available as GridDevice.metadata.gateset.' + ' Engine methods no longer require gate sets to be passed in.' + ' In addition, circuit serialization is replaced by cirq_google.CircuitSerializer.', +) +class SerializableGateSet(_SerializableGateSet): + """A class for serializing and deserializing programs and operations. + + This class is for cirq_google.api.v2 protos. + """ + + def __init__( + self, + gate_set_name: str, + serializers: Iterable[op_serializer.OpSerializer], + deserializers: Iterable[op_deserializer.OpDeserializer], + ): + """Construct the gate set. + + Args: + gate_set_name: The name used to identify the gate set. + serializers: The OpSerializers to use for serialization. + Multiple serializers for a given gate type are allowed and + will be checked for a given type in the order specified here. + This allows for a given gate type to be serialized into + different serialized form depending on the parameters of the + gate. + deserializers: The OpDeserializers to convert serialized + forms of gates or circuits into Operations. + """ + super().__init__(gate_set_name, serializers, deserializers) + + def with_added_types( + self, + *, + gate_set_name: Optional[str] = None, + serializers: Iterable[op_serializer.OpSerializer] = (), + deserializers: Iterable[op_deserializer.OpDeserializer] = (), + ) -> 'SerializableGateSet': + """Creates a new gateset with additional (de)serializers. + + Args: + gate_set_name: Optional new name of the gateset. If not given, use + the same name as this gateset. + serializers: Serializers to add to those in this gateset. + deserializers: Deserializers to add to those in this gateset. + """ + return super().with_added_types( + gate_set_name=gate_set_name, serializers=serializers, deserializers=deserializers + ) + + def is_supported(self, op_tree: cirq.OP_TREE) -> bool: + """Whether the given object contains only supported operations.""" + return super().is_supported(op_tree) + + def is_supported_operation(self, op: cirq.Operation) -> bool: + """Whether or not the given gate can be serialized by this gate set.""" + return super().is_supported_operation(op) + + def serialize( + self, + program: cirq.AbstractCircuit, + msg: Optional[v2.program_pb2.Program] = None, + *, + arg_function_language: Optional[str] = None, + use_constants: Optional[bool] = True, + ) -> v2.program_pb2.Program: + """Serialize a Circuit to cirq_google.api.v2.Program proto. + + Args: + program: The Circuit to serialize. + msg: An optional proto object to populate with the serialization + results. + arg_function_language: The `arg_function_language` field from + `Program.Language`. + use_constants: Whether to use constants in serialization. This is + required to be True for serializing CircuitOperations. + + Raises: + NotImplementedError: If the program type is not supported. + """ + return super().serialize( + program, msg, arg_function_language=arg_function_language, use_constants=use_constants + ) + + def serialize_op( + self, + op: cirq.Operation, + msg: Union[None, v2.program_pb2.Operation, v2.program_pb2.CircuitOperation] = None, + **kwargs, + ) -> Union[v2.program_pb2.Operation, v2.program_pb2.CircuitOperation]: + """Disambiguation for operation serialization.""" + return super().serialize_op(op, msg, **kwargs) + + def serialize_gate_op( + self, + op: cirq.Operation, + msg: Optional[v2.program_pb2.Operation] = None, + *, + arg_function_language: Optional[str] = '', + constants: Optional[List[v2.program_pb2.Constant]] = None, + raw_constants: Optional[Dict[Any, int]] = None, + ) -> v2.program_pb2.Operation: + """Serialize an Operation to cirq_google.api.v2.Operation proto. + + Args: + op: The operation to serialize. + msg: An optional proto object to populate with the serialization + results. + arg_function_language: The `arg_function_language` field from + `Program.Language`. + constants: The list of previously-serialized Constant protos. + raw_constants: A map raw objects to their respective indices in + `constants`. + + Returns: + The cirq.google.api.v2.Operation proto. + + Raises: + ValueError: If the op cannot be serialized. + """ + return super().serialize_gate_op( + op, + msg, + arg_function_language=arg_function_language, + constants=constants, + raw_constants=raw_constants, + ) + + def serialize_circuit_op( + self, + op: cirq.Operation, + msg: Optional[v2.program_pb2.CircuitOperation] = None, + *, + arg_function_language: Optional[str] = '', + constants: Optional[List[v2.program_pb2.Constant]] = None, + raw_constants: Optional[Dict[Any, int]] = None, + ) -> Union[v2.program_pb2.Operation, v2.program_pb2.CircuitOperation]: + """Serialize a CircuitOperation to cirq.google.api.v2.CircuitOperation proto. + + Args: + op: The circuit operation to serialize. + msg: An optional proto object to populate with the serialization + results. + arg_function_language: The `arg_function_language` field from + `Program.Language`. + constants: The list of previously-serialized Constant protos. + raw_constants: A map raw objects to their respective indices in + `constants`. + + Returns: + The cirq.google.api.v2.CircuitOperation proto. + + Raises: + ValueError: If one of `constants` or `raw_constants` is None, or the circuit operation + cannot be serialized. + """ + return super().serialize_circuit_op( + op, + msg, + arg_function_language=arg_function_language, + constants=constants, + raw_constants=raw_constants, + ) + + def deserialize(self, proto: v2.program_pb2.Program) -> cirq.Circuit: + """Deserialize a Circuit from a cirq_google.api.v2.Program. + + Args: + proto: A dictionary representing a cirq_google.api.v2.Program proto. + + Returns: + The deserialized Circuit. + + Raises: + ValueError: If the given proto has no language specified or it mismatched the + name specified for this serializable gate set. + NotImplementedError: If the program does not contain a circuit or schedule. + """ + return super().deserialize(proto) + + def deserialize_op( + self, + operation_proto: Union[v2.program_pb2.Operation, v2.program_pb2.CircuitOperation,], + **kwargs, + ) -> cirq.Operation: + """Disambiguation for operation deserialization.""" + return super().deserialize_op(operation_proto, **kwargs) + + def deserialize_gate_op( + self, + operation_proto: v2.program_pb2.Operation, + *, + arg_function_language: str = '', + constants: Optional[List[v2.program_pb2.Constant]] = None, + deserialized_constants: Optional[List[Any]] = None, + ) -> cirq.Operation: + """Deserialize an Operation from a cirq_google.api.v2.Operation. + + Args: + operation_proto: A dictionary representing a + cirq.google.api.v2.Operation proto. + arg_function_language: The `arg_function_language` field from + `Program.Language`. + constants: The list of Constant protos referenced by constant + table indices in `proto`. + deserialized_constants: The deserialized contents of `constants`. + cirq_google.api.v2.Operation proto. + + Returns: + The deserialized Operation. + + Raises: + ValueError: If the gate cannot be deserialized. + """ + return super().deserialize_gate_op( + operation_proto, + arg_function_language=arg_function_language, + constants=constants, + deserialized_constants=deserialized_constants, + ) + + def deserialize_circuit_op( + self, + operation_proto: v2.program_pb2.CircuitOperation, + *, + arg_function_language: str = '', + constants: Optional[List[v2.program_pb2.Constant]] = None, + deserialized_constants: Optional[List[Any]] = None, + ) -> cirq.CircuitOperation: + """Deserialize a CircuitOperation from a cirq.google.api.v2.CircuitOperation. + + Args: + operation_proto: A dictionary representing a + cirq.google.api.v2.CircuitOperation proto. + arg_function_language: The `arg_function_language` field from + `Program.Language`. + constants: The list of Constant protos referenced by constant + table indices in `proto`. + deserialized_constants: The deserialized contents of `constants`. + + Returns: + The deserialized CircuitOperation. + + Raises: + ValueError: If the deserializer does not support deserializing `CircuitOperation`. + """ + return super().deserialize_circuit_op( + operation_proto, + arg_function_language=arg_function_language, + constants=constants, + deserialized_constants=deserialized_constants, + ) diff --git a/cirq-google/cirq_google/serialization/serializable_gate_set_test.py b/cirq-google/cirq_google/serialization/serializable_gate_set_test.py index abd3038539f..03e0fab6fd5 100644 --- a/cirq-google/cirq_google/serialization/serializable_gate_set_test.py +++ b/cirq-google/cirq_google/serialization/serializable_gate_set_test.py @@ -52,11 +52,14 @@ CIRCUIT_OP_SERIALIZER = cg.CircuitOpSerializer() CIRCUIT_OP_DESERIALIZER = cg.CircuitOpDeserializer() -MY_GATE_SET = cg.SerializableGateSet( - gate_set_name='my_gate_set', - serializers=[X_SERIALIZER, CIRCUIT_OP_SERIALIZER], - deserializers=[X_DESERIALIZER, CIRCUIT_OP_DESERIALIZER], -) + +def _my_gate_set(): + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + return cg.SerializableGateSet( + gate_set_name='my_gate_set', + serializers=[X_SERIALIZER, CIRCUIT_OP_SERIALIZER], + deserializers=[X_DESERIALIZER, CIRCUIT_OP_DESERIALIZER], + ) def op_proto(json: Dict) -> v2.program_pb2.Operation: @@ -66,70 +69,73 @@ def op_proto(json: Dict) -> v2.program_pb2.Operation: def test_naming(): - assert MY_GATE_SET.name == 'my_gate_set' + assert _my_gate_set().name == 'my_gate_set' def test_supported_internal_types(): - assert MY_GATE_SET.supported_internal_types() == (cirq.XPowGate, cirq.FrozenCircuit) + assert _my_gate_set().supported_internal_types() == (cirq.XPowGate, cirq.FrozenCircuit) def test_is_supported(): q0, q1 = cirq.GridQubit.rect(1, 2) - assert MY_GATE_SET.is_supported(cirq.Circuit(cirq.X(q0), cirq.X(q1))) - assert not MY_GATE_SET.is_supported(cirq.Circuit(cirq.X(q0), cirq.Z(q1))) + assert _my_gate_set().is_supported(cirq.Circuit(cirq.X(q0), cirq.X(q1))) + assert not _my_gate_set().is_supported(cirq.Circuit(cirq.X(q0), cirq.Z(q1))) def test_is_supported_subcircuits(): q0, q1 = cirq.GridQubit.rect(1, 2) - assert MY_GATE_SET.is_supported( + assert _my_gate_set().is_supported( cirq.Circuit(cirq.X(q0), cirq.CircuitOperation(cirq.FrozenCircuit(cirq.X(q1)))) ) - assert not MY_GATE_SET.is_supported( + assert not _my_gate_set().is_supported( cirq.Circuit(cirq.X(q0), cirq.CircuitOperation(cirq.FrozenCircuit(cirq.Z(q1)))) ) def test_is_supported_operation(): q = cirq.GridQubit(1, 1) - assert MY_GATE_SET.is_supported_operation(cirq.XPowGate()(q)) - assert MY_GATE_SET.is_supported_operation(cirq.X(q)) - assert not MY_GATE_SET.is_supported_operation(cirq.ZPowGate()(q)) + assert _my_gate_set().is_supported_operation(cirq.XPowGate()(q)) + assert _my_gate_set().is_supported_operation(cirq.X(q)) + assert not _my_gate_set().is_supported_operation(cirq.ZPowGate()(q)) def test_is_supported_circuit_operation(): q = cirq.GridQubit(1, 1) - assert MY_GATE_SET.is_supported_operation(cirq.CircuitOperation(cirq.FrozenCircuit(cirq.X(q)))) - assert MY_GATE_SET.is_supported_operation( + assert _my_gate_set().is_supported_operation( + cirq.CircuitOperation(cirq.FrozenCircuit(cirq.X(q))) + ) + assert _my_gate_set().is_supported_operation( cirq.CircuitOperation(cirq.FrozenCircuit(cirq.X(q))).with_tags('test_tag') ) - assert MY_GATE_SET.is_supported_operation( + assert _my_gate_set().is_supported_operation( cirq.CircuitOperation( cirq.FrozenCircuit(cirq.CircuitOperation(cirq.FrozenCircuit(cirq.X(q)))) ) ) - assert not MY_GATE_SET.is_supported_operation( + assert not _my_gate_set().is_supported_operation( cirq.CircuitOperation(cirq.FrozenCircuit(cirq.Z(q))) ) def test_is_supported_operation_can_serialize_predicate(): - q = cirq.GridQubit(1, 2) - serializer = cg.GateOpSerializer( - gate_type=cirq.XPowGate, - serialized_gate_id='x_pow', - args=[ - cg.SerializingArg( - serialized_name='half_turns', serialized_type=float, op_getter='exponent' - ) - ], - can_serialize_predicate=lambda x: x.gate.exponent == 1.0, - ) - gate_set = cg.SerializableGateSet( - gate_set_name='my_gate_set', serializers=[serializer], deserializers=[X_DESERIALIZER] - ) - assert gate_set.is_supported_operation(cirq.XPowGate()(q)) - assert not gate_set.is_supported_operation(cirq.XPowGate()(q) ** 0.5) - assert gate_set.is_supported_operation(cirq.X(q)) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + q = cirq.GridQubit(1, 2) + serializer = cg.GateOpSerializer( + gate_type=cirq.XPowGate, + serialized_gate_id='x_pow', + args=[ + cg.SerializingArg( + serialized_name='half_turns', serialized_type=float, op_getter='exponent' + ) + ], + can_serialize_predicate=lambda x: x.gate.exponent == 1.0, + ) + gate_set = cg.SerializableGateSet( + gate_set_name='my_gate_set', serializers=[serializer], deserializers=[X_DESERIALIZER] + ) + assert gate_set.is_supported_operation(cirq.XPowGate()(q)) + assert not gate_set.is_supported_operation(cirq.XPowGate()(q) ** 0.5) + assert gate_set.is_supported_operation(cirq.X(q)) def test_serialize_deserialize_circuit(): @@ -152,8 +158,8 @@ def test_serialize_deserialize_circuit(): ), ) for circuit in [circuit_base, circuit_base.freeze()]: - assert proto == MY_GATE_SET.serialize(circuit) - assert MY_GATE_SET.deserialize(proto) == circuit + assert proto == _my_gate_set().serialize(circuit) + assert _my_gate_set().deserialize(proto) == circuit def test_serialize_deserialize_circuit_with_tokens(): @@ -189,8 +195,8 @@ def test_serialize_deserialize_circuit_with_tokens(): v2.program_pb2.Constant(string_value='def456'), ], ) - assert proto == MY_GATE_SET.serialize(circuit) - assert MY_GATE_SET.deserialize(proto) == circuit + assert proto == _my_gate_set().serialize(circuit) + assert _my_gate_set().deserialize(proto) == circuit def test_serialize_deserialize_circuit_with_subcircuit(): @@ -245,8 +251,8 @@ def test_serialize_deserialize_circuit_with_subcircuit(): ), ], ) - assert proto == MY_GATE_SET.serialize(circuit) - assert MY_GATE_SET.deserialize(proto) == circuit + assert proto == _my_gate_set().serialize(circuit) + assert _my_gate_set().deserialize(proto) == circuit def test_deserialize_infinite_recursion_fails(): @@ -255,7 +261,7 @@ def test_deserialize_infinite_recursion_fails(): setattr(inf_op.circuit, '_moments', tuple(cirq.Circuit(inf_op).moments)) circuit = cirq.Circuit(inf_op) with pytest.raises(RecursionError): - _ = MY_GATE_SET.serialize(circuit) + _ = _my_gate_set().serialize(circuit) c_op1 = v2.program_pb2.CircuitOperation() c_op1.circuit_constant_index = 0 @@ -280,7 +286,7 @@ def test_deserialize_infinite_recursion_fails(): ], ) with pytest.raises(ValueError, match="Failed to deserialize circuit"): - _ = MY_GATE_SET.deserialize(proto) + _ = _my_gate_set().deserialize(proto) def test_deserialize_bad_operation_id(): @@ -309,7 +315,7 @@ def test_deserialize_bad_operation_id(): with pytest.raises( ValueError, match='problem in moment 1 handling an operation with the following' ): - MY_GATE_SET.deserialize(proto) + _my_gate_set().deserialize(proto) def test_serialize_deserialize_empty_circuit(): @@ -321,8 +327,8 @@ def test_serialize_deserialize_empty_circuit(): scheduling_strategy=v2.program_pb2.Circuit.MOMENT_BY_MOMENT, moments=[] ), ) - assert proto == MY_GATE_SET.serialize(circuit) - assert MY_GATE_SET.deserialize(proto) == circuit + assert proto == _my_gate_set().serialize(circuit) + assert _my_gate_set().deserialize(proto) == circuit def test_deserialize_empty_moment(): @@ -335,12 +341,12 @@ def test_deserialize_empty_moment(): moments=[v2.program_pb2.Moment()], ), ) - assert MY_GATE_SET.deserialize(proto) == circuit + assert _my_gate_set().deserialize(proto) == circuit def test_serialize_unrecognized(): with pytest.raises(NotImplementedError, match='program type'): - MY_GATE_SET.serialize("not quite right") + _my_gate_set().serialize("not quite right") def test_serialize_deserialize_op(): @@ -352,8 +358,8 @@ def test_serialize_deserialize_op(): 'qubits': [{'id': '1_1'}], } ) - assert proto == MY_GATE_SET.serialize_op(cirq.XPowGate(exponent=0.125)(q0)) - assert MY_GATE_SET.deserialize_op(proto) == cirq.XPowGate(exponent=0.125)(q0) + assert proto == _my_gate_set().serialize_op(cirq.XPowGate(exponent=0.125)(q0)) + assert _my_gate_set().deserialize_op(proto) == cirq.XPowGate(exponent=0.125)(q0) def test_serialize_deserialize_op_with_token(): @@ -367,8 +373,8 @@ def test_serialize_deserialize_op_with_token(): } ) op = cirq.XPowGate(exponent=0.125)(q0).with_tags(cg.CalibrationTag('abc123')) - assert proto == MY_GATE_SET.serialize_op(op) - assert MY_GATE_SET.deserialize_op(proto) == op + assert proto == _my_gate_set().serialize_op(op) + assert _my_gate_set().deserialize_op(proto) == op def test_serialize_deserialize_op_with_constants(): @@ -382,10 +388,10 @@ def test_serialize_deserialize_op_with_constants(): } ) op = cirq.XPowGate(exponent=0.125)(q0).with_tags(cg.CalibrationTag('abc123')) - assert proto == MY_GATE_SET.serialize_op(op, constants=[]) + assert proto == _my_gate_set().serialize_op(op, constants=[]) constant = v2.program_pb2.Constant() constant.string_value = 'abc123' - assert MY_GATE_SET.deserialize_op(proto, constants=[constant]) == op + assert _my_gate_set().deserialize_op(proto, constants=[constant]) == op def test_serialize_deserialize_op_subclass(): @@ -398,8 +404,8 @@ def test_serialize_deserialize_op_subclass(): } ) # cirq.X is a subclass of XPowGate. - assert proto == MY_GATE_SET.serialize_op(cirq.X(q0)) - assert MY_GATE_SET.deserialize_op(proto) == cirq.X(q0) + assert proto == _my_gate_set().serialize_op(cirq.X(q0)) + assert _my_gate_set().deserialize_op(proto) == cirq.X(q0) def default_circuit_proto(): @@ -427,53 +433,57 @@ def test_serialize_circuit_op_errors(): op = cirq.CircuitOperation(default_circuit()) with pytest.raises(ValueError, match='CircuitOp serialization requires a constants list'): - MY_GATE_SET.serialize_op(op) + _my_gate_set().serialize_op(op) with pytest.raises(ValueError, match='CircuitOp serialization requires a constants list'): - MY_GATE_SET.serialize_op(op, constants=constants) + _my_gate_set().serialize_op(op, constants=constants) with pytest.raises(ValueError, match='CircuitOp serialization requires a constants list'): - MY_GATE_SET.serialize_op(op, raw_constants=raw_constants) + _my_gate_set().serialize_op(op, raw_constants=raw_constants) - NO_CIRCUIT_OP_GATE_SET = cg.SerializableGateSet( - gate_set_name='no_circuit_op_gateset', - serializers=[X_SERIALIZER], - deserializers=[X_DESERIALIZER], - ) - with pytest.raises(ValueError, match='Cannot serialize CircuitOperation'): - NO_CIRCUIT_OP_GATE_SET.serialize_op(op, constants=constants, raw_constants=raw_constants) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + NO_CIRCUIT_OP_GATE_SET = cg.SerializableGateSet( + gate_set_name='no_circuit_op_gateset', + serializers=[X_SERIALIZER], + deserializers=[X_DESERIALIZER], + ) + with pytest.raises(ValueError, match='Cannot serialize CircuitOperation'): + NO_CIRCUIT_OP_GATE_SET.serialize_op( + op, constants=constants, raw_constants=raw_constants + ) def test_deserialize_circuit_op_errors(): - constants = [default_circuit_proto()] - deserialized_constants = [default_circuit()] - - proto = v2.program_pb2.CircuitOperation() - proto.circuit_constant_index = 0 - proto.repetition_specification.repetition_count = 1 - - NO_CIRCUIT_OP_GATE_SET = cg.SerializableGateSet( - gate_set_name='no_circuit_op_gateset', - serializers=[X_SERIALIZER], - deserializers=[X_DESERIALIZER], - ) - with pytest.raises(ValueError, match='Unsupported deserialized of a CircuitOperation'): - NO_CIRCUIT_OP_GATE_SET.deserialize_op( - proto, constants=constants, deserialized_constants=deserialized_constants + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=2): + constants = [default_circuit_proto()] + deserialized_constants = [default_circuit()] + + proto = v2.program_pb2.CircuitOperation() + proto.circuit_constant_index = 0 + proto.repetition_specification.repetition_count = 1 + + NO_CIRCUIT_OP_GATE_SET = cg.SerializableGateSet( + gate_set_name='no_circuit_op_gateset', + serializers=[X_SERIALIZER], + deserializers=[X_DESERIALIZER], ) + with pytest.raises(ValueError, match='Unsupported deserialized of a CircuitOperation'): + NO_CIRCUIT_OP_GATE_SET.deserialize_op( + proto, constants=constants, deserialized_constants=deserialized_constants + ) - BAD_CIRCUIT_DESERIALIZER = cg.GateOpDeserializer( - serialized_gate_id='circuit', gate_constructor=cirq.ZPowGate, args=[] - ) - BAD_CIRCUIT_DESERIALIZER_GATE_SET = cg.SerializableGateSet( - gate_set_name='bad_circuit_gateset', - serializers=[CIRCUIT_OP_SERIALIZER], - deserializers=[BAD_CIRCUIT_DESERIALIZER], - ) - with pytest.raises(ValueError, match='Expected CircuitOpDeserializer for id "circuit"'): - BAD_CIRCUIT_DESERIALIZER_GATE_SET.deserialize_op( - proto, constants=constants, deserialized_constants=deserialized_constants + BAD_CIRCUIT_DESERIALIZER = cg.GateOpDeserializer( + serialized_gate_id='circuit', gate_constructor=cirq.ZPowGate, args=[] + ) + BAD_CIRCUIT_DESERIALIZER_GATE_SET = cg.SerializableGateSet( + gate_set_name='bad_circuit_gateset', + serializers=[CIRCUIT_OP_SERIALIZER], + deserializers=[BAD_CIRCUIT_DESERIALIZER], ) + with pytest.raises(ValueError, match='Expected CircuitOpDeserializer for id "circuit"'): + BAD_CIRCUIT_DESERIALIZER_GATE_SET.deserialize_op( + proto, constants=constants, deserialized_constants=deserialized_constants + ) def test_serialize_deserialize_circuit_op(): @@ -486,9 +496,11 @@ def test_serialize_deserialize_circuit_op(): proto.repetition_specification.repetition_count = 1 op = cirq.CircuitOperation(default_circuit()) - assert proto == MY_GATE_SET.serialize_op(op, constants=constants, raw_constants=raw_constants) + assert proto == _my_gate_set().serialize_op( + op, constants=constants, raw_constants=raw_constants + ) assert ( - MY_GATE_SET.deserialize_op( + _my_gate_set().deserialize_op( proto, constants=constants, deserialized_constants=deserialized_constants ) == op @@ -496,89 +508,92 @@ def test_serialize_deserialize_circuit_op(): def test_multiple_serializers(): - serializer1 = cg.GateOpSerializer( - gate_type=cirq.XPowGate, - serialized_gate_id='x_pow', - args=[ - cg.SerializingArg( - serialized_name='half_turns', serialized_type=float, op_getter='exponent' - ) - ], - can_serialize_predicate=lambda x: x.gate.exponent != 1, - ) - serializer2 = cg.GateOpSerializer( - gate_type=cirq.XPowGate, - serialized_gate_id='x', - args=[ - cg.SerializingArg( - serialized_name='half_turns', serialized_type=float, op_getter='exponent' - ) - ], - can_serialize_predicate=lambda x: x.gate.exponent == 1, - ) - gate_set = cg.SerializableGateSet( - gate_set_name='my_gate_set', serializers=[serializer1, serializer2], deserializers=[] - ) - q0 = cirq.GridQubit(1, 1) - assert gate_set.serialize_op(cirq.X(q0)).gate.id == 'x' - assert gate_set.serialize_op(cirq.X(q0) ** 0.5).gate.id == 'x_pow' + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=1): + serializer1 = cg.GateOpSerializer( + gate_type=cirq.XPowGate, + serialized_gate_id='x_pow', + args=[ + cg.SerializingArg( + serialized_name='half_turns', serialized_type=float, op_getter='exponent' + ) + ], + can_serialize_predicate=lambda x: x.gate.exponent != 1, + ) + serializer2 = cg.GateOpSerializer( + gate_type=cirq.XPowGate, + serialized_gate_id='x', + args=[ + cg.SerializingArg( + serialized_name='half_turns', serialized_type=float, op_getter='exponent' + ) + ], + can_serialize_predicate=lambda x: x.gate.exponent == 1, + ) + gate_set = cg.SerializableGateSet( + gate_set_name='my_gate_set', serializers=[serializer1, serializer2], deserializers=[] + ) + q0 = cirq.GridQubit(1, 1) + assert gate_set.serialize_op(cirq.X(q0)).gate.id == 'x' + assert gate_set.serialize_op(cirq.X(q0) ** 0.5).gate.id == 'x_pow' def test_gateset_with_added_types(): - q = cirq.GridQubit(1, 1) - x_gateset = cg.SerializableGateSet( - gate_set_name='x', serializers=[X_SERIALIZER], deserializers=[X_DESERIALIZER] - ) - xy_gateset = x_gateset.with_added_types( - gate_set_name='xy', serializers=[Y_SERIALIZER], deserializers=[Y_DESERIALIZER] - ) - assert x_gateset.name == 'x' - assert x_gateset.is_supported_operation(cirq.X(q)) - assert not x_gateset.is_supported_operation(cirq.Y(q)) - assert xy_gateset.name == 'xy' - assert xy_gateset.is_supported_operation(cirq.X(q)) - assert xy_gateset.is_supported_operation(cirq.Y(q)) - - # test serialization and deserialization - proto = op_proto( - { - 'gate': {'id': 'y_pow'}, - 'args': {'half_turns': {'arg_value': {'float_value': 0.125}}}, - 'qubits': [{'id': '1_1'}], - } - ) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=2): + q = cirq.GridQubit(1, 1) + x_gateset = cg.SerializableGateSet( + gate_set_name='x', serializers=[X_SERIALIZER], deserializers=[X_DESERIALIZER] + ) + xy_gateset = x_gateset.with_added_types( + gate_set_name='xy', serializers=[Y_SERIALIZER], deserializers=[Y_DESERIALIZER] + ) + assert x_gateset.name == 'x' + assert x_gateset.is_supported_operation(cirq.X(q)) + assert not x_gateset.is_supported_operation(cirq.Y(q)) + assert xy_gateset.name == 'xy' + assert xy_gateset.is_supported_operation(cirq.X(q)) + assert xy_gateset.is_supported_operation(cirq.Y(q)) + + # test serialization and deserialization + proto = op_proto( + { + 'gate': {'id': 'y_pow'}, + 'args': {'half_turns': {'arg_value': {'float_value': 0.125}}}, + 'qubits': [{'id': '1_1'}], + } + ) - expected_gate = cirq.YPowGate(exponent=0.125)(cirq.GridQubit(1, 1)) - assert xy_gateset.serialize_op(expected_gate) == proto - assert xy_gateset.deserialize_op(proto) == expected_gate + expected_gate = cirq.YPowGate(exponent=0.125)(cirq.GridQubit(1, 1)) + assert xy_gateset.serialize_op(expected_gate) == proto + assert xy_gateset.deserialize_op(proto) == expected_gate def test_gateset_with_added_types_again(): """Verify that adding a serializer twice doesn't mess anything up.""" - q = cirq.GridQubit(2, 2) - x_gateset = cg.SerializableGateSet( - gate_set_name='x', serializers=[X_SERIALIZER], deserializers=[X_DESERIALIZER] - ) - xx_gateset = x_gateset.with_added_types( - gate_set_name='xx', serializers=[X_SERIALIZER], deserializers=[X_DESERIALIZER] - ) - - assert xx_gateset.name == 'xx' - assert xx_gateset.is_supported_operation(cirq.X(q)) - assert not xx_gateset.is_supported_operation(cirq.Y(q)) + with cirq.testing.assert_deprecated('SerializableGateSet', deadline='v0.16', count=2): + q = cirq.GridQubit(2, 2) + x_gateset = cg.SerializableGateSet( + gate_set_name='x', serializers=[X_SERIALIZER], deserializers=[X_DESERIALIZER] + ) + xx_gateset = x_gateset.with_added_types( + gate_set_name='xx', serializers=[X_SERIALIZER], deserializers=[X_DESERIALIZER] + ) - # test serialization and deserialization - proto = op_proto( - { - 'gate': {'id': 'x_pow'}, - 'args': {'half_turns': {'arg_value': {'float_value': 0.125}}}, - 'qubits': [{'id': '1_1'}], - } - ) + assert xx_gateset.name == 'xx' + assert xx_gateset.is_supported_operation(cirq.X(q)) + assert not xx_gateset.is_supported_operation(cirq.Y(q)) + + # test serialization and deserialization + proto = op_proto( + { + 'gate': {'id': 'x_pow'}, + 'args': {'half_turns': {'arg_value': {'float_value': 0.125}}}, + 'qubits': [{'id': '1_1'}], + } + ) - expected_gate = cirq.XPowGate(exponent=0.125)(cirq.GridQubit(1, 1)) - assert xx_gateset.serialize_op(expected_gate) == proto - assert xx_gateset.deserialize_op(proto) == expected_gate + expected_gate = cirq.XPowGate(exponent=0.125)(cirq.GridQubit(1, 1)) + assert xx_gateset.serialize_op(expected_gate) == proto + assert xx_gateset.deserialize_op(proto) == expected_gate def test_deserialize_op_invalid_gate(): @@ -590,19 +605,19 @@ def test_deserialize_op_invalid_gate(): } ) with pytest.raises(ValueError, match='does not have a gate'): - MY_GATE_SET.deserialize_op(proto) + _my_gate_set().deserialize_op(proto) proto = op_proto( {'args': {'half_turns': {'arg_value': {'float_value': 0.125}}}, 'qubits': [{'id': '1_1'}]} ) with pytest.raises(ValueError, match='does not have a gate'): - MY_GATE_SET.deserialize_op(proto) + _my_gate_set().deserialize_op(proto) def test_deserialize_op_bad_operation_proto(): proto = v2.program_pb2.Circuit() with pytest.raises(ValueError, match='Operation proto has unknown type'): - MY_GATE_SET.deserialize_op(proto) + _my_gate_set().deserialize_op(proto) def test_deserialize_unsupported_gate_type(): @@ -614,13 +629,13 @@ def test_deserialize_unsupported_gate_type(): } ) with pytest.raises(ValueError, match='no_pow'): - MY_GATE_SET.deserialize_op(proto) + _my_gate_set().deserialize_op(proto) def test_serialize_op_unsupported_type(): q0 = cirq.GridQubit(1, 1) with pytest.raises(ValueError, match='YPowGate'): - MY_GATE_SET.serialize_op(cirq.YPowGate()(q0)) + _my_gate_set().serialize_op(cirq.YPowGate()(q0)) def test_serialize_op_bad_operation(): @@ -634,14 +649,14 @@ def with_qubits(self, *qubits): null_op = NullOperation() with pytest.raises(ValueError, match='Operation is of an unrecognized type'): - MY_GATE_SET.serialize_op(null_op) + _my_gate_set().serialize_op(null_op) def test_serialize_op_bad_operation_proto(): q0 = cirq.GridQubit(1, 1) msg = v2.program_pb2.Circuit() with pytest.raises(ValueError, match='Operation proto is of an unrecognized type'): - MY_GATE_SET.serialize_op(cirq.X(q0), msg) + _my_gate_set().serialize_op(cirq.X(q0), msg) def test_deserialize_invalid_gate_set(): @@ -652,11 +667,11 @@ def test_deserialize_invalid_gate_set(): ), ) with pytest.raises(ValueError, match='not_my_gate_set'): - MY_GATE_SET.deserialize(proto) + _my_gate_set().deserialize(proto) proto.language.gate_set = '' with pytest.raises(ValueError, match='Missing gate set'): - MY_GATE_SET.deserialize(proto) + _my_gate_set().deserialize(proto) proto = v2.program_pb2.Program( circuit=v2.program_pb2.Circuit( @@ -664,7 +679,7 @@ def test_deserialize_invalid_gate_set(): ) ) with pytest.raises(ValueError, match='Missing gate set'): - MY_GATE_SET.deserialize(proto) + _my_gate_set().deserialize(proto) def test_deserialize_no_operation(): @@ -675,4 +690,4 @@ def test_deserialize_no_operation(): ), ) with pytest.raises(ValueError, match='operation'): - MY_GATE_SET.deserialize(proto) + _my_gate_set().deserialize(proto)