def test_asymmetric_gate(): spec = device_pb2.DeviceSpecification() for row in range(5): for col in range(2): spec.valid_qubits.extend( [v2.qubit_to_proto_id(cirq.GridQubit(row, col))]) grid_targets = spec.valid_targets.add() grid_targets.name = 'left_to_right' grid_targets.target_ordering = device_pb2.TargetSet.ASYMMETRIC for row in range(5): new_target = grid_targets.targets.add() new_target.ids.extend([ v2.qubit_to_proto_id(cirq.GridQubit(row, 0)), v2.qubit_to_proto_id(cirq.GridQubit(row, 1)), ]) gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'cz_left_to_right_only' gate = gs_proto.valid_gates.add() gate.id = 'cz' gate.valid_targets.extend(['left_to_right']) dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ]) for row in range(5): dev.validate_operation( cirq.CZ(cirq.GridQubit(row, 0), cirq.GridQubit(row, 1))) with pytest.raises(ValueError): dev.validate_operation( cirq.CZ(cirq.GridQubit(row, 1), cirq.GridQubit(row, 0)))
def test_constrained_permutations(): spec = device_pb2.DeviceSpecification() for row in range(5): for col in range(2): spec.valid_qubits.extend( [v2.qubit_to_proto_id(cirq.GridQubit(row, col))]) grid_targets = spec.valid_targets.add() grid_targets.name = 'meas_on_first_line' grid_targets.target_ordering = device_pb2.TargetSet.SUBSET_PERMUTATION new_target = grid_targets.targets.add() new_target.ids.extend( [v2.qubit_to_proto_id(cirq.GridQubit(i, 0)) for i in range(5)]) gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'meas_set' gate = gs_proto.valid_gates.add() gate.id = 'meas' gate.valid_targets.extend(['meas_on_first_line']) dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_MEAS]) dev.validate_operation(cirq.measure(cirq.GridQubit(0, 0))) dev.validate_operation(cirq.measure(cirq.GridQubit(1, 0))) dev.validate_operation(cirq.measure(cirq.GridQubit(2, 0))) dev.validate_operation( cirq.measure(*[cirq.GridQubit(i, 0) for i in range(5)])) with pytest.raises(ValueError): dev.validate_operation(cirq.measure(cirq.GridQubit(1, 1))) with pytest.raises(ValueError): dev.validate_operation( cirq.measure(cirq.GridQubit(0, 0), cirq.GridQubit(1, 1)))
def test_mixing_types(): """Mixing SUBSET_PERMUTATION with SYMMETRIC targets is confusing, and not yet supported""" spec = device_pb2.DeviceSpecification() grid_targets = spec.valid_targets.add() grid_targets.name = 'subset' grid_targets.target_ordering = device_pb2.TargetSet.SUBSET_PERMUTATION grid_targets = spec.valid_targets.add() grid_targets.name = 'sym' grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'set_with_mismatched_targets' gate = gs_proto.valid_gates.add() 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=[meas_gateset])
def test_number_of_qubits_cz(): spec = device_pb2.DeviceSpecification() spec.valid_qubits.extend([ v2.qubit_to_proto_id(cirq.GridQubit(0, 0)), v2.qubit_to_proto_id(cirq.GridQubit(0, 1)) ]) grid_targets = spec.valid_targets.add() grid_targets.name = '2_qubit_anywhere' grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'cz_requires_three_qubits' gate = gs_proto.valid_gates.add() gate.id = '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=[cz_gateset]) with pytest.raises(ValueError): dev.validate_operation( cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)))
def test_unconstrained_gate(): spec = device_pb2.DeviceSpecification() for row in range(5): for col in range(5): spec.valid_qubits.extend( [v2.qubit_to_proto_id(cirq.GridQubit(row, col))]) grid_targets = spec.valid_targets.add() grid_targets.name = '2_qubit_anywhere' grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'cz_free_for_all' gate = gs_proto.valid_gates.add() 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=[cz_gateset]) valid_qubit1 = cirq.GridQubit(4, 4) for row in range(4): for col in range(4): valid_qubit2 = cirq.GridQubit(row, col) dev.validate_operation(cirq.CZ(valid_qubit1, valid_qubit2))
def test_number_of_qubits_cz(): spec = device_pb2.DeviceSpecification() spec.valid_qubits.extend( [v2.qubit_to_proto_id(cirq.GridQubit(0, 0)), v2.qubit_to_proto_id(cirq.GridQubit(0, 1))] ) grid_targets = spec.valid_targets.add() grid_targets.name = '2_qubit_anywhere' grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'cz_requires_three_qubits' gate = gs_proto.valid_gates.add() gate.id = 'cz' gate.valid_targets.extend(['2_qubit_anywhere']) gate.number_of_qubits = 3 dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ]) with pytest.raises(ValueError): dev.validate_operation(cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)))
def test_mixing_types(): """Mixing SUBSET_PERMUTATION with SYMMETRIC targets is confusing, and not yet supported""" spec = device_pb2.DeviceSpecification() grid_targets = spec.valid_targets.add() grid_targets.name = 'subset' grid_targets.target_ordering = device_pb2.TargetSet.SUBSET_PERMUTATION grid_targets = spec.valid_targets.add() grid_targets.name = 'sym' grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'set_with_mismatched_targets' gate = gs_proto.valid_gates.add() gate.id = 'meas' gate.valid_targets.extend(['subset', 'sym']) with pytest.raises(NotImplementedError): _ = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_MEAS])
def test_unconstrained_gate(): spec = device_pb2.DeviceSpecification() for row in range(5): for col in range(5): spec.valid_qubits.extend([v2.qubit_to_proto_id(cirq.GridQubit(row, col))]) grid_targets = spec.valid_targets.add() grid_targets.name = '2_qubit_anywhere' grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'cz_free_for_all' gate = gs_proto.valid_gates.add() gate.id = 'cz' gate.valid_targets.extend(['2_qubit_anywhere']) dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ]) valid_qubit1 = cirq.GridQubit(4, 4) for row in range(4): for col in range(4): valid_qubit2 = cirq.GridQubit(row, col) dev.validate_operation(cirq.CZ(valid_qubit1, valid_qubit2))
def test_asymmetric_gate(): spec = device_pb2.DeviceSpecification() for row in range(5): for col in range(2): spec.valid_qubits.extend( [v2.qubit_to_proto_id(cirq.GridQubit(row, col))]) grid_targets = spec.valid_targets.add() grid_targets.name = 'left_to_right' grid_targets.target_ordering = device_pb2.TargetSet.ASYMMETRIC for row in range(5): new_target = grid_targets.targets.add() new_target.ids.extend([ v2.qubit_to_proto_id(cirq.GridQubit(row, 0)), v2.qubit_to_proto_id(cirq.GridQubit(row, 1)), ]) gs_proto = spec.valid_gate_sets.add() gs_proto.name = 'cz_left_to_right_only' gate = gs_proto.valid_gates.add() 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=[cz_gateset]) for row in range(5): dev.validate_operation( cirq.CZ(cirq.GridQubit(row, 0), cirq.GridQubit(row, 1))) with pytest.raises(ValueError): dev.validate_operation( cirq.CZ(cirq.GridQubit(row, 1), cirq.GridQubit(row, 0)))
def create_device_proto_for_qubits( qubits: Collection[cirq.Qid], pairs: Collection[Tuple[cirq.Qid, cirq.Qid]], gate_sets: Optional[Iterable[ serializable_gate_set.SerializableGateSet]] = None, durations_picos: Optional[Dict[str, int]] = None, out: Optional[device_pb2.DeviceSpecification] = None, ) -> device_pb2.DeviceSpecification: """Create device spec for the given qubits and coupled pairs. Args: qubits: Qubits that can perform single-qubit gates. pairs: Pairs of coupled qubits that can perform two-qubit gates. gate_sets: Gate sets that define the translation between gate ids and cirq Gate objects. durations_picos: A map from gate ids to gate durations in picoseconds. out: If given, populate this proto, otherwise create a new proto. """ if out is None: out = device_pb2.DeviceSpecification() # Create valid qubit list out.valid_qubits.extend(v2.qubit_to_proto_id(q) for q in qubits) # Set up a target set for measurement (any qubit permutation) meas_targets = out.valid_targets.add() meas_targets.name = _MEAS_TARGET_SET meas_targets.target_ordering = device_pb2.TargetSet.SUBSET_PERMUTATION # Set up a target set for 2 qubit gates (specified qubit pairs) grid_targets = out.valid_targets.add() grid_targets.name = _2_QUBIT_TARGET_SET grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC for pair in pairs: new_target = grid_targets.targets.add() new_target.ids.extend(v2.qubit_to_proto_id(q) for q in pair) # Create gate sets arg_def = device_pb2.ArgDefinition for gate_set in gate_sets or []: gs_proto = out.valid_gate_sets.add() gs_proto.name = gate_set.name gate_ids: Set[str] = set() for internal_type in gate_set.serializers: for serializer in gate_set.serializers[internal_type]: gate_id = serializer.serialized_id if gate_id in gate_ids: # Only add each type once continue gate_ids.add(gate_id) gate = gs_proto.valid_gates.add() gate.id = gate_id if not isinstance(serializer, op_serializer.GateOpSerializer): # This implies that 'serializer' handles non-gate ops, # such as CircuitOperations. No other properties apply. continue # Choose target set and number of qubits based on gate type. gate_type = internal_type # Note: if it is not a measurement gate and doesn't inherit # from SingleQubitGate, it's assumed to be a two qubit gate. if gate_type == cirq.MeasurementGate: gate.valid_targets.append(_MEAS_TARGET_SET) elif gate_type == cirq.WaitGate: # TODO: Refactor gate-sets / device to eliminate the need # to keep checking type here. # Github issue: # https://github.com/quantumlib/Cirq/issues/2537 gate.number_of_qubits = 1 elif issubclass(gate_type, cirq.SingleQubitGate): gate.number_of_qubits = 1 else: # This must be a two-qubit gate gate.valid_targets.append(_2_QUBIT_TARGET_SET) gate.number_of_qubits = 2 # Add gate duration if durations_picos is not None and gate.id in durations_picos: gate.gate_duration_picos = durations_picos[gate.id] # Add argument names and types for each gate. for arg in serializer.args: new_arg = gate.valid_args.add() if arg.serialized_type == str: new_arg.type = arg_def.STRING if arg.serialized_type == float: new_arg.type = arg_def.FLOAT if arg.serialized_type == List[bool]: new_arg.type = arg_def.REPEATED_BOOLEAN new_arg.name = arg.serialized_name # Note: this does not yet support adding allowed_ranges return out