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_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 _create_device_spec_with_horizontal_couplings(): # Qubit layout: # x -- x # x -- x # x -- x # x -- x # x -- x grid_qubits = [ cirq.GridQubit(i, j) for i in range(GRID_HEIGHT) for j in range(2) ] spec = v2.device_pb2.DeviceSpecification() spec.valid_qubits.extend([v2.qubit_to_proto_id(q) for q in grid_qubits]) grid_targets = spec.valid_targets.add() grid_targets.name = '2_qubit_targets' grid_targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC for row in range(int(GRID_HEIGHT / 2)): new_target = grid_targets.targets.add() new_target.ids.extend( [v2.qubit_to_proto_id(cirq.GridQubit(row, j)) for j in range(2)]) for row in range(int(GRID_HEIGHT / 2), GRID_HEIGHT): # Flip the qubit pair order for the second half of qubits # to verify GridDevice properly handles pair symmetry. new_target = grid_targets.targets.add() new_target.ids.extend([ v2.qubit_to_proto_id(cirq.GridQubit(row, 1 - j)) for j in range(2) ]) gate = spec.valid_gates.add() gate.syc.SetInParent() gate.gate_duration_picos = 12000 gate.valid_targets.extend(['2_qubit_targets']) return grid_qubits, spec
def to_proto( self, op: cirq.CircuitOperation, msg: Optional[v2.program_pb2.CircuitOperation] = None, *, arg_function_language: Optional[str] = '', constants: List[v2.program_pb2.Constant] = None, raw_constants: Dict[Any, int] = None, ) -> v2.program_pb2.CircuitOperation: """Returns the cirq.google.api.v2.CircuitOperation message as a proto dict. Note that this function requires constants and raw_constants to be pre-populated with the circuit in op. """ if constants is None or raw_constants is None: raise ValueError( 'CircuitOp serialization requires a constants list and a corresponding list of ' 'pre-serialization values (raw_constants).') if not isinstance(op, cirq.CircuitOperation): raise ValueError( f'Serializer expected CircuitOperation but got {type(op)}.') msg = msg or v2.program_pb2.CircuitOperation() try: msg.circuit_constant_index = raw_constants[op.circuit] except KeyError as err: # Circuits must be serialized prior to any CircuitOperations that use them. raise ValueError( 'Encountered a circuit not in the constants table. ' f'Full error message:\n{err}') if (op.repetition_ids is not None and op.repetition_ids != circuit_operation.default_repetition_ids(op.repetitions)): for rep_id in op.repetition_ids: msg.repetition_specification.repetition_ids.ids.append(rep_id) else: msg.repetition_specification.repetition_count = op.repetitions for q1, q2 in op.qubit_map.items(): entry = msg.qubit_map.entries.add() entry.key.id = v2.qubit_to_proto_id(q1) entry.value.id = v2.qubit_to_proto_id(q2) for mk1, mk2 in op.measurement_key_map.items(): entry = msg.measurement_key_map.entries.add() entry.key.string_key = mk1 entry.value.string_key = mk2 for p1, p2 in op.param_resolver.param_dict.items(): entry = msg.arg_map.entries.add() arg_to_proto(p1, out=entry.key, arg_function_language=arg_function_language) arg_to_proto(p2, out=entry.value, arg_function_language=arg_function_language) return msg
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_results_from_proto_default_ordering(): proto = v2.result_pb2.Result() sr = proto.sweep_results.add() sr.repetitions = 8 pr = sr.parameterized_results.add() pr.params.assignments.update({'i': 1}) mr = pr.measurement_results.add() mr.key = 'foo' for qubit, results in [(q(0, 1), 0b1100_1100), (q(1, 1), 0b1010_1010), (q(0, 0), 0b1111_0000)]: qmr = mr.qubit_measurement_results.add() qmr.qubit.id = v2.qubit_to_proto_id(qubit) qmr.results = bytes([results]) trial_results = v2.results_from_proto(proto) trial = trial_results[0][0] assert trial.params == cirq.ParamResolver({'i': 1}) assert trial.repetitions == 8 np.testing.assert_array_equal( trial.measurements['foo'], np.array( [ [0, 0, 0], [0, 1, 0], [1, 0, 0], [1, 1, 0], [0, 0, 1], [0, 1, 1], [1, 0, 1], [1, 1, 1], ], dtype=bool, ), )
def results_to_proto( trial_sweeps: Iterable[Iterable[study.Result]], measurements: List[MeasureInfo], *, out: Optional[result_pb2.Result] = None, ) -> result_pb2.Result: """Converts trial results from multiple sweeps to v2 protobuf message. Args: trial_sweeps: Iterable over sweeps and then over trial results within each sweep. measurements: List of info about measurements in the program. out: Optional message to populate. If not given, create a new message. """ if out is None: out = result_pb2.Result() for trial_sweep in trial_sweeps: sweep_result = out.sweep_results.add() for i, trial_result in enumerate(trial_sweep): if i == 0: sweep_result.repetitions = trial_result.repetitions elif trial_result.repetitions != sweep_result.repetitions: raise ValueError( 'different numbers of repetitions in one sweep') pr = sweep_result.parameterized_results.add() pr.params.assignments.update(trial_result.params.param_dict) for m in measurements: mr = pr.measurement_results.add() mr.key = m.key m_data = trial_result.measurements[m.key] for i, qubit in enumerate(m.qubits): qmr = mr.qubit_measurement_results.add() qmr.qubit.id = v2.qubit_to_proto_id(qubit) qmr.results = pack_bits(m_data[:, i]) return out
def to_proto(self) -> v2.metrics_pb2.MetricsSnapshot: """Reconstruct the protobuf message represented by this class.""" proto = v2.metrics_pb2.MetricsSnapshot() for key in self._metric_dict: for targets, value_list in self._metric_dict[key].items(): current_metric = proto.metrics.add() current_metric.name = key current_metric.targets.extend( [ target if isinstance(target, str) else v2.qubit_to_proto_id(target) for target in targets ] ) for value in value_list: current_value = current_metric.values.add() if isinstance(value, float): current_value.double_val = value elif isinstance(value, int): current_value.int64_val = value elif isinstance(value, str): current_value.str_val = value else: raise ValueError( f'Unsupported metric value {value}. ' 'Must be int, float, or str to ' 'convert to proto.' ) return proto
def _create_device_spec_duplicate_qubit() -> v2.device_pb2.DeviceSpecification: """Creates a DeviceSpecification with a qubit name that does not conform to '<int>_<int>'.""" q_proto_id = v2.qubit_to_proto_id(cirq.GridQubit(0, 0)) spec = v2.device_pb2.DeviceSpecification() spec.valid_qubits.extend([q_proto_id, q_proto_id]) return spec
def to_proto( self, op: cirq.Operation, msg: Optional[v2.program_pb2.Operation] = None, *, arg_function_language: Optional[str] = '', constants: List[v2.program_pb2.Constant] = None, raw_constants: Dict[Any, int] = None, ) -> Optional[v2.program_pb2.Operation]: """Returns the cirq_google.api.v2.Operation message as a proto dict. Note that this function may modify the constant list if it adds tokens to the circuit's constant table. """ gate = op.gate if not isinstance(gate, self.internal_type): raise ValueError( f'Gate of type {type(gate)} but serializer expected type {self.internal_type}' ) if not self._can_serialize_predicate(op): return None if msg is None: msg = v2.program_pb2.Operation() msg.gate.id = self._serialized_gate_id for qubit in op.qubits: msg.qubits.add().id = v2.qubit_to_proto_id(qubit) for arg in self._args: value = self._value_from_gate(op, arg) if value is not None and (not arg.default or value != arg.default): arg_to_proto( value, out=msg.args[arg.serialized_name], arg_function_language=arg_function_language, ) if self._serialize_tokens: for tag in op.tags: if isinstance(tag, CalibrationTag): if constants is not None: constant = v2.program_pb2.Constant() constant.string_value = tag.token try: msg.token_constant_index = constants.index( constant) except ValueError: # Token not found, add it to the list msg.token_constant_index = len(constants) constants.append(constant) if raw_constants is not None: raw_constants[ tag.token] = msg.token_constant_index else: msg.token_value = tag.token return msg
def test_qubit_to_proto_id(): assert v2.qubit_to_proto_id(cirq.GridQubit(1, 2)) == '1_2' assert v2.qubit_to_proto_id(cirq.GridQubit(10, 2)) == '10_2' assert v2.qubit_to_proto_id(cirq.GridQubit(-1, 2)) == '-1_2' assert v2.qubit_to_proto_id(cirq.LineQubit(1)) == '1' assert v2.qubit_to_proto_id(cirq.LineQubit(10)) == '10' assert v2.qubit_to_proto_id(cirq.LineQubit(-1)) == '-1' assert v2.qubit_to_proto_id(cirq.NamedQubit('named')) == 'named'
def populate_qubits_in_device_proto( qubits: Collection[cirq.Qid], out: device_pb2.DeviceSpecification) -> None: """Populates `DeviceSpecification.valid_qubits` with the device's qubits. Args: qubits: The collection of the device's qubits. out: The `DeviceSpecification` to be populated. """ out.valid_qubits.extend(v2.qubit_to_proto_id(q) for q in qubits)
def _create_device_spec_with_horizontal_couplings(): # Qubit layout: # x -- x # x -- x # x -- x # x -- x # x -- x grid_qubits = [cirq.GridQubit(i, j) for i in range(GRID_HEIGHT) for j in range(2)] spec = v2.device_pb2.DeviceSpecification() spec.valid_qubits.extend([v2.qubit_to_proto_id(q) for q in grid_qubits]) grid_targets = spec.valid_targets.add() grid_targets.name = '2_qubit_targets' grid_targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC for row in range(int(GRID_HEIGHT / 2)): new_target = grid_targets.targets.add() new_target.ids.extend([v2.qubit_to_proto_id(cirq.GridQubit(row, j)) for j in range(2)]) for row in range(int(GRID_HEIGHT / 2), GRID_HEIGHT): # Flip the qubit pair order for the second half of qubits # to verify GridDevice properly handles pair symmetry. new_target = grid_targets.targets.add() new_target.ids.extend([v2.qubit_to_proto_id(cirq.GridQubit(row, 1 - j)) for j in range(2)]) gate_names = [ 'syc', 'sqrt_iswap', 'sqrt_iswap_inv', 'cz', 'phased_xz', 'virtual_zpow', 'physical_zpow', 'coupler_pulse', 'meas', 'wait', ] for i, g in enumerate(gate_names): gate = spec.valid_gates.add() getattr(gate, g).SetInParent() gate.gate_duration_picos = i * 1000 return grid_qubits, spec
def _create_device_spec_with_all_couplings(): # Qubit layout: # x -- x # | | # x -- x # | | # x -- x # | | # x -- x # | | # x -- x grid_qubits, spec = _create_device_spec_with_horizontal_couplings() for row in range(GRID_HEIGHT - 1): for col in range(2): new_target = spec.valid_targets[0].targets.add() new_target.ids.extend([ v2.qubit_to_proto_id(cirq.GridQubit(row, col)), v2.qubit_to_proto_id(cirq.GridQubit(row + 1, col)), ]) return grid_qubits, spec
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 _create_device_spec_qubit_pair_self_loops() -> v2.device_pb2.DeviceSpecification: """Creates an invalid DeviceSpecification with a qubit pair ('0_0', '0_0').""" q_proto_id = v2.qubit_to_proto_id(cirq.GridQubit(0, 0)) spec = v2.device_pb2.DeviceSpecification() spec.valid_qubits.extend([q_proto_id]) targets = spec.valid_targets.add() targets.name = 'test_targets' targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC new_target = targets.targets.add() new_target.ids.extend([q_proto_id, q_proto_id]) return spec
def _create_device_spec_invalid_qubit_in_qubit_pair() -> v2.device_pb2.DeviceSpecification: """Creates a DeviceSpecification where qubit '0_1' is in a pair but not in valid_qubits.""" q_proto_ids = [v2.qubit_to_proto_id(cirq.GridQubit(0, i)) for i in range(2)] spec = v2.device_pb2.DeviceSpecification() spec.valid_qubits.extend([q_proto_ids[0]]) targets = spec.valid_targets.add() targets.name = 'test_targets' targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC new_target = targets.targets.add() new_target.ids.extend([q_proto_ids[0], q_proto_ids[1]]) return spec
def test_to_proto_id_unsupport_qid(): class ValidQubit(cirq.Qid): def __init__(self, name): self._name = name @property def dimension(self): pass def _comparison_key(self): pass with pytest.raises(ValueError, match='ValidQubit'): _ = v2.qubit_to_proto_id(ValidQubit('d'))
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 populate_qubit_pairs_in_device_proto( pairs: Collection[Tuple[cirq.Qid, cirq.Qid]], out: device_pb2.DeviceSpecification) -> None: """Populates `DeviceSpecification.valid_targets` with the device's qubit pairs. Args: pairs: The collection of the device's bi-directional qubit pairs. out: The `DeviceSpecification` to be populated. """ 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)
def _create_device_spec_invalid_subset_permutation_target( ) -> v2.device_pb2.DeviceSpecification: """Creates a DeviceSpecification where a SUBSET_PERMUTATION target contains 2 qubits.""" q_proto_ids = [ v2.qubit_to_proto_id(cirq.GridQubit(0, i)) for i in range(2) ] spec = v2.device_pb2.DeviceSpecification() spec.valid_qubits.extend(q_proto_ids) targets = spec.valid_targets.add() targets.name = 'test_targets' targets.target_ordering = v2.device_pb2.TargetSet.SUBSET_PERMUTATION new_target = targets.targets.add() new_target.ids.extend(q_proto_ids) # should only have 1 qubit instead return spec
def test_results_from_proto_duplicate_qubit(): measurements = [ v2.MeasureInfo('foo', [q(0, 0), q(0, 1), q(1, 1)], slot=0, invert_mask=[False, False, False], tags=[]) ] proto = v2.result_pb2.Result() sr = proto.sweep_results.add() sr.repetitions = 8 pr = sr.parameterized_results.add() pr.params.assignments.update({'i': 0}) mr = pr.measurement_results.add() mr.key = 'foo' for qubit, results in [(q(0, 0), 0b1100_1100), (q(0, 1), 0b1010_1010), (q(0, 1), 0b1111_0000)]: qmr = mr.qubit_measurement_results.add() qmr.qubit.id = v2.qubit_to_proto_id(qubit) qmr.results = bytes([results]) with pytest.raises(ValueError, match='Qubit already exists'): v2.results_from_proto(proto, measurements)
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 _serialize_gate_op( self, op: cirq.Operation, msg: v2.program_pb2.Operation, *, constants: List[v2.program_pb2.Constant], raw_constants: Dict[Any, int], arg_function_language: Optional[str] = '', ) -> 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. """ gate = op.gate if isinstance(gate, cirq.XPowGate): arg_func_langs.float_arg_to_proto( gate.exponent, out=msg.xpowgate.exponent, arg_function_language=arg_function_language, ) elif isinstance(gate, cirq.YPowGate): arg_func_langs.float_arg_to_proto( gate.exponent, out=msg.ypowgate.exponent, arg_function_language=arg_function_language, ) elif isinstance(gate, cirq.ZPowGate): arg_func_langs.float_arg_to_proto( gate.exponent, out=msg.zpowgate.exponent, arg_function_language=arg_function_language, ) if any(isinstance(tag, PhysicalZTag) for tag in op.tags): msg.zpowgate.is_physical_z = True elif isinstance(gate, cirq.PhasedXPowGate): arg_func_langs.float_arg_to_proto( gate.phase_exponent, out=msg.phasedxpowgate.phase_exponent, arg_function_language=arg_function_language, ) arg_func_langs.float_arg_to_proto( gate.exponent, out=msg.phasedxpowgate.exponent, arg_function_language=arg_function_language, ) elif isinstance(gate, cirq.PhasedXZGate): arg_func_langs.float_arg_to_proto( gate.x_exponent, out=msg.phasedxzgate.x_exponent, arg_function_language=arg_function_language, ) arg_func_langs.float_arg_to_proto( gate.z_exponent, out=msg.phasedxzgate.z_exponent, arg_function_language=arg_function_language, ) arg_func_langs.float_arg_to_proto( gate.axis_phase_exponent, out=msg.phasedxzgate.axis_phase_exponent, arg_function_language=arg_function_language, ) elif isinstance(gate, cirq.CZPowGate): arg_func_langs.float_arg_to_proto( gate.exponent, out=msg.czpowgate.exponent, arg_function_language=arg_function_language, ) elif isinstance(gate, cirq.ISwapPowGate): arg_func_langs.float_arg_to_proto( gate.exponent, out=msg.iswappowgate.exponent, arg_function_language=arg_function_language, ) elif isinstance(gate, cirq.FSimGate): arg_func_langs.float_arg_to_proto( gate.theta, out=msg.fsimgate.theta, arg_function_language=arg_function_language, ) arg_func_langs.float_arg_to_proto( gate.phi, out=msg.fsimgate.phi, arg_function_language=arg_function_language, ) elif isinstance(gate, cirq.MeasurementGate): arg_func_langs.arg_to_proto( gate.key, out=msg.measurementgate.key, arg_function_language=arg_function_language, ) arg_func_langs.arg_to_proto( gate.invert_mask, out=msg.measurementgate.invert_mask, arg_function_language=arg_function_language, ) elif isinstance(gate, cirq.WaitGate): arg_func_langs.float_arg_to_proto( gate.duration.total_nanos(), out=msg.waitgate.duration_nanos, arg_function_language=arg_function_language, ) else: raise ValueError( f'Cannot serialize op {op!r} of type {type(gate)}') for qubit in op.qubits: if qubit not in raw_constants: constants.append( v2.program_pb2.Constant(qubit=v2.program_pb2.Qubit( id=v2.qubit_to_proto_id(qubit)))) raw_constants[qubit] = len(constants) - 1 msg.qubit_constant_index.append(raw_constants[qubit]) for tag in op.tags: if isinstance(tag, CalibrationTag): constant = v2.program_pb2.Constant() constant.string_value = tag.token if tag.token in raw_constants: msg.token_constant_index = raw_constants[tag.token] else: # Token not found, add it to the list msg.token_constant_index = len(constants) constants.append(constant) if raw_constants is not None: raw_constants[tag.token] = msg.token_constant_index return msg
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
def _create_device_spec_with_horizontal_couplings(): # Qubit layout: # x -- x # x -- x # x -- x # x -- x # x -- x grid_qubits = [ cirq.GridQubit(i, j) for i in range(GRID_HEIGHT) for j in range(2) ] spec = v2.device_pb2.DeviceSpecification() spec.valid_qubits.extend([v2.qubit_to_proto_id(q) for q in grid_qubits]) qubit_pairs = [] grid_targets = spec.valid_targets.add() grid_targets.name = '2_qubit_targets' grid_targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC for row in range(int(GRID_HEIGHT / 2)): qubit_pairs.append((cirq.GridQubit(row, 0), cirq.GridQubit(row, 1))) for row in range(int(GRID_HEIGHT / 2), GRID_HEIGHT): # Flip the qubit pair order for the second half of qubits # to verify GridDevice properly handles pair symmetry. qubit_pairs.append((cirq.GridQubit(row, 1), cirq.GridQubit(row, 0))) for pair in qubit_pairs: new_target = grid_targets.targets.add() new_target.ids.extend([v2.qubit_to_proto_id(q) for q in pair]) gate_names = [ 'syc', 'sqrt_iswap', 'sqrt_iswap_inv', 'cz', 'phased_xz', 'virtual_zpow', 'physical_zpow', 'coupler_pulse', 'meas', 'wait', ] gate_durations = [(n, i * 1000) for i, n in enumerate(gate_names)] for gate_name, duration in sorted(gate_durations): gate = spec.valid_gates.add() getattr(gate, gate_name).SetInParent() gate.gate_duration_picos = duration expected_gateset = cirq.Gateset( cirq_google.FSimGateFamily(gates_to_accept=[cirq_google.SYC]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP_INV]), cirq_google.FSimGateFamily(gates_to_accept=[cirq.CZ]), cirq.ops.phased_x_z_gate.PhasedXZGate, cirq.ops.common_gates.XPowGate, cirq.ops.common_gates.YPowGate, cirq.ops.phased_x_gate.PhasedXPowGate, cirq.GateFamily(cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()]), cirq.GateFamily(cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()]), cirq_google.experimental.ops.coupler_pulse.CouplerPulse, cirq.ops.measurement_gate.MeasurementGate, cirq.ops.wait_gate.WaitGate, ) base_duration = cirq.Duration(picos=1_000) expected_gate_durations = { cirq_google.FSimGateFamily(gates_to_accept=[cirq_google.SYC]): base_duration * 0, cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP]): base_duration * 1, cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP_INV]): base_duration * 2, cirq_google.FSimGateFamily(gates_to_accept=[cirq.CZ]): base_duration * 3, cirq.GateFamily(cirq.ops.phased_x_z_gate.PhasedXZGate): base_duration * 4, cirq.GateFamily(cirq.ops.common_gates.XPowGate): base_duration * 4, cirq.GateFamily(cirq.ops.common_gates.YPowGate): base_duration * 4, cirq.GateFamily(cirq.ops.phased_x_gate.PhasedXPowGate): 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, } expected_target_gatesets = ( cirq.CZTargetGateset(), cirq_google.SycamoreTargetGateset(), cirq.SqrtIswapTargetGateset(use_sqrt_iswap_inv=True), ) return ( _DeviceInfo( grid_qubits, qubit_pairs, expected_gateset, expected_gate_durations, expected_target_gatesets, ), spec, )