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, ) -> Optional[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_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, ), ), ) 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, 'theta_default': 0.0, 'zeta_default': 0.0, 'chi_default': 0.0, 'gamma_default': 0.0, 'phi_default': 0.0, }, ) # 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 create_calibration_program( self, layers: List['cirq_google.CalibrationLayer'], program_id: Optional[str] = None, gate_set: Optional[sgs.SerializableGateSet] = None, description: Optional[str] = None, labels: Optional[Dict[str, str]] = None, ) -> engine_program.EngineProgram: """Wraps a list of calibration layers into an Any for Quantum Engine. Args: layers: The calibration routines to execute. All layers will be executed within the same API call in the order specified, though some layers may be interleaved together using hardware-specific batching. program_id: A user-provided identifier for the program. This must be unique within the Google Cloud project being used. If this parameter is not provided, a random id of the format 'calibration-################YYMMDD' will be generated, where # is alphanumeric and YYMMDD is the current year, month, and day. gate_set: The gate set used to serialize the circuits in each layer. The gate set must be supported by the processor. description: An optional description to set on the program. labels: Optional set of labels to set on the program. Returns: A EngineProgram for the newly created program. """ if not gate_set: raise ValueError('Gate set must be specified.') if not program_id: program_id = _make_random_id('calibration-') calibration = v2.calibration_pb2.FocusedCalibration() for layer in layers: 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]) gate_set.serialize(layer.program, msg=new_layer.layer) new_program_id, new_program = self.context.client.create_program( self.project_id, program_id, code=self._pack_any(calibration), description=description, labels=labels, ) return engine_program.EngineProgram( self.project_id, new_program_id, self.context, new_program, result_type=ResultType.Calibration, )
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_unsupported_function_language(): with pytest.raises(ValueError, match='Unrecognized arg_function_language'): _ = arg_to_proto(sympy.Symbol('a') + sympy.Symbol('b'), arg_function_language='NEVER GONNAH APPEN') with pytest.raises(ValueError, match='Unrecognized arg_function_language'): _ = arg_to_proto(3 * sympy.Symbol('b'), arg_function_language='NEVER GONNAH APPEN') with pytest.raises(ValueError, match='Unrecognized arg_function_language'): _ = arg_from_proto( v2.program_pb2.Arg(func=v2.program_pb2.ArgFunction( type='add', args=[ v2.program_pb2.Arg(symbol='a'), v2.program_pb2.Arg(symbol='b') ], )), arg_function_language='NEVER GONNAH APPEN', )
def test_serialize_conversion(value: ARG_LIKE, proto: v2.program_pb2.Arg): msg = v2.program_pb2.Arg() json_format.ParseDict(proto, msg) packed = json_format.MessageToDict( arg_to_proto(value, arg_function_language=''), including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=True, ) assert packed == proto
def test_serialize_sympy_constants(): proto = arg_to_proto(sympy.pi, arg_function_language='') packed = json_format.MessageToDict( proto, including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=True, ) assert len(packed) == 1 assert len(packed['arg_value']) == 1 # protobuf 3.12+ truncates floats to 4 bytes assert np.isclose(packed['arg_value']['float_value'], np.float32(sympy.pi), atol=1e-7)
def test_correspondence(min_lang: str, value: ARG_LIKE, proto: v2.program_pb2.Arg): msg = v2.program_pb2.Arg() json_format.ParseDict(proto, msg) min_i = LANGUAGE_ORDER.index(min_lang) for i, lang in enumerate(LANGUAGE_ORDER): if i < min_i: with pytest.raises(ValueError, match='not supported by arg_function_language'): _ = arg_to_proto(value, arg_function_language=lang) with pytest.raises(ValueError, match='Unrecognized function type'): _ = arg_from_proto(msg, arg_function_language=lang) else: parsed = arg_from_proto(msg, arg_function_language=lang) packed = json_format.MessageToDict( arg_to_proto(value, arg_function_language=lang), including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=True, ) assert parsed == value assert packed == proto
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 test_unsupported_function_language(): with pytest.raises(ValueError, match='Unrecognized arg_function_language'): _ = arg_to_proto(1, arg_function_language='NEVER GONNAH APPEN') with pytest.raises(ValueError, match='Unrecognized arg_function_language'): _ = arg_from_proto(None, arg_function_language='NEVER GONNAH APPEN')