def parse_result(self, result: CalibrationResult) -> PhasedFSimCalibrationResult: decoded: Dict[int, Dict[str, Any]] = collections.defaultdict(lambda: {}) for keys, values in result.metrics['angles'].items(): for key, value in zip(keys, values): match = re.match(r'(\d+)_(.+)', str(key)) if not match: raise ValueError(f'Unknown metric name {key}') index = int(match[1]) name = match[2] decoded[index][name] = value parsed = {} for data in decoded.values(): a = v2.qubit_from_proto_id(data['qubit_a']) b = v2.qubit_from_proto_id(data['qubit_b']) parsed[(a, b)] = PhasedFSimCharacterization( theta=data.get('theta_est', None), zeta=data.get('zeta_est', None), chi=data.get('chi_est', None), gamma=data.get('gamma_est', None), phi=data.get('phi_est', None), ) return PhasedFSimCalibrationResult(parameters=parsed, gate=self.gate, options=self.options)
def load_sample_device_zphase(processor_id: str) -> util.ZPhaseDataType: """Loads sample Z phase errors for the given device. Args: processor_id: name of the processor to simulate. Returns: Z phases in the form {gate_type: {angle_type: {qubit_pair: error}}}, where gate_type is "syc" or "sqrt_iswap", angle_type is "zeta" or "gamma", and "qubit_pair" is a tuple of qubits. Raises: ValueError: if processor_id is not a supported QCS processor. """ zphase_name = ZPHASE_DATA.get(processor_id, None) if zphase_name is None: raise ValueError( f"Got processor_id={processor_id}, but no Z phase data is defined for that processor." ) path = pathlib.Path(__file__).parent.parent.resolve() with path.joinpath('devices', 'calibrations', zphase_name).open() as f: raw_data = json.load(f) nested_data: util.ZPhaseDataType = { gate_type: { angle: {(v2.qubit_from_proto_id(q0), v2.qubit_from_proto_id(q1)): vals for q0, q1, vals in triples} for angle, triples in angles.items() } for gate_type, angles in raw_data.items() } return nested_data
def from_proto( self, proto: v2.program_pb2.Operation, *, arg_function_language: str = '', constants: List[v2.program_pb2.Constant] = None, ) -> 'cirq.Operation': """Turns a cirq_google.api.v2.Operation proto into a GateOperation.""" qubits = [v2.qubit_from_proto_id(q.id) for q in proto.qubits] args = self._args_from_proto(proto, arg_function_language=arg_function_language) if self.num_qubits_param is not None: args[self.num_qubits_param] = len(qubits) gate = self.gate_constructor(**args) op = self.op_wrapper(gate.on(*qubits), proto) if self.deserialize_tokens: which = proto.WhichOneof('token') if which == 'token_constant_index': if not constants: raise ValueError( 'Proto has references to constants table ' 'but none was passed in, value =' f'{proto}' ) op = op.with_tags( CalibrationTag(constants[proto.token_constant_index].string_value) ) elif which == 'token_value': op = op.with_tags(CalibrationTag(proto.token_value)) return op
def deserialize( self, proto: v2.program_pb2.Program, device: Optional[cirq.Device] = None ) -> cirq.Circuit: """Deserialize a Circuit from a cirq_google.api.v2.Program. Args: proto: A dictionary representing a cirq_google.api.v2.Program proto. device: If the proto is for a schedule, a device is required Otherwise optional. Returns: The deserialized Circuit, with a device if device was not None. Raises: ValueError: If the given proto has no language or the langauge gate set mismatches that specified in as the name of this serialized gate set. Also if deserializing a schedule is attempted. NotImplementedError: If the program proto does not contain a circuit or schedule. """ if not proto.HasField('language') or not proto.language.gate_set: raise ValueError('Missing gate set specification.') if proto.language.gate_set != self.name: raise ValueError( 'Gate set in proto was {} but expected {}'.format( proto.language.gate_set, self.name ) ) which = proto.WhichOneof('program') arg_func_language = ( proto.language.arg_function_language or arg_func_langs.MOST_PERMISSIVE_LANGUAGE ) if which == 'circuit': deserialized_constants: List[Any] = [] for constant in proto.constants: which_const = constant.WhichOneof('const_value') if which_const == 'string_value': deserialized_constants.append(constant.string_value) elif which_const == 'circuit_value': circuit = self._deserialize_circuit( constant.circuit_value, arg_function_language=arg_func_language, constants=proto.constants, deserialized_constants=deserialized_constants, ) deserialized_constants.append(circuit.freeze()) elif which_const == 'qubit': deserialized_constants.append(v2.qubit_from_proto_id(constant.qubit.id)) circuit = self._deserialize_circuit( proto.circuit, arg_function_language=arg_func_language, constants=proto.constants, deserialized_constants=deserialized_constants, ) return circuit if device is None else circuit.with_device(device) if which == 'schedule': raise ValueError('Deserializing a schedule is no longer supported.') raise NotImplementedError('Program proto does not contain a circuit.')
def parse_result( self, result: CalibrationResult, job: Optional[EngineJob] = None) -> PhasedFSimCalibrationResult: if result.code != v2.calibration_pb2.SUCCESS: raise PhasedFSimCalibrationError(result.error_message) decoded: Dict[int, Dict[str, Any]] = collections.defaultdict(lambda: {}) for keys, values in result.metrics['angles'].items(): for key, value in zip(keys, values): match = re.match(r'(\d+)_(.+)', str(key)) if not match: raise ValueError(f'Unknown metric name {key}') index = int(match[1]) name = match[2] decoded[index][name] = value parsed = {} for data in decoded.values(): a = v2.qubit_from_proto_id(data['qubit_a']) b = v2.qubit_from_proto_id(data['qubit_b']) parsed[(a, b)] = PhasedFSimCharacterization( theta=data.get('theta_est', None), zeta=data.get('zeta_est', None), chi=data.get('chi_est', None), gamma=data.get('gamma_est', None), phi=data.get('phi_est', None), ) return PhasedFSimCalibrationResult( parameters=parsed, gate=self.gate, options=self.options, project_id=None if job is None else job.project_id, program_id=None if job is None else job.program_id, job_id=None if job is None else job.job_id, )
def test_generic_qubit_from_proto_id(): assert v2.qubit_from_proto_id('1_2') == cirq.GridQubit(1, 2) assert v2.qubit_from_proto_id('1') == cirq.LineQubit(1) assert v2.qubit_from_proto_id('a') == cirq.NamedQubit('a') # Despite the fact that int(1_2_3) = 123, only pure numbers are parsed into # LineQubits. assert v2.qubit_from_proto_id('1_2_3') == cirq.NamedQubit('1_2_3') # All non-int-parseable names are converted to NamedQubits. assert v2.qubit_from_proto_id('a') == cirq.NamedQubit('a') assert v2.qubit_from_proto_id('1_b') == cirq.NamedQubit('1_b')
def from_proto( self, proto: v2.program_pb2.Operation, *, arg_function_language: str = '', constants: List[v2.program_pb2.Constant] = None, deserialized_constants: List[Any] = None, # unused ) -> cirq.Operation: """Turns a cirq_google.api.v2.Operation proto into a GateOperation. Args: proto: The proto object to be deserialized. 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: Unused in this method. Returns: The deserialized GateOperation represented by `proto`. Raises: ValueError: If the proto references a missing constants table, or a required arg is missing. """ qubits = [v2.qubit_from_proto_id(q.id) for q in proto.qubits] args = self._args_from_proto( proto, arg_function_language=arg_function_language) if self._num_qubits_param is not None: args[self._num_qubits_param] = len(qubits) gate = self._gate_constructor(**args) op = self._op_wrapper(gate.on(*qubits), proto) if self._deserialize_tokens: which = proto.WhichOneof('token') if which == 'token_constant_index': if not constants: raise ValueError('Proto has references to constants table ' 'but none was passed in, value =' f'{proto}') op = op.with_tags( CalibrationTag( constants[proto.token_constant_index].string_value)) elif which == 'token_value': op = op.with_tags(CalibrationTag(proto.token_value)) return op
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. """ if deserialized_constants is not None: qubits = [ deserialized_constants[q] for q in operation_proto.qubit_constant_index ] else: qubits = [] for q in operation_proto.qubits: # Preserve previous functionality in case # constants table was not used qubits.append(v2.qubit_from_proto_id(q.id)) which_gate_type = operation_proto.WhichOneof('gate_value') if which_gate_type == 'xpowgate': op = cirq.XPowGate(exponent=arg_func_langs.float_arg_from_proto( operation_proto.xpowgate.exponent, arg_function_language=arg_function_language, required_arg_name=None, ))(*qubits) elif which_gate_type == 'ypowgate': op = cirq.YPowGate(exponent=arg_func_langs.float_arg_from_proto( operation_proto.ypowgate.exponent, arg_function_language=arg_function_language, required_arg_name=None, ))(*qubits) elif which_gate_type == 'zpowgate': op = cirq.ZPowGate(exponent=arg_func_langs.float_arg_from_proto( operation_proto.zpowgate.exponent, arg_function_language=arg_function_language, required_arg_name=None, ))(*qubits) if operation_proto.zpowgate.is_physical_z: op = op.with_tags(PhysicalZTag()) elif which_gate_type == 'phasedxpowgate': exponent = arg_func_langs.float_arg_from_proto( operation_proto.phasedxpowgate.exponent, arg_function_language=arg_function_language, required_arg_name=None, ) phase_exponent = arg_func_langs.float_arg_from_proto( operation_proto.phasedxpowgate.phase_exponent, arg_function_language=arg_function_language, required_arg_name=None, ) op = cirq.PhasedXPowGate(exponent=exponent, phase_exponent=phase_exponent)(*qubits) elif which_gate_type == 'phasedxzgate': x_exponent = arg_func_langs.float_arg_from_proto( operation_proto.phasedxzgate.x_exponent, arg_function_language=arg_function_language, required_arg_name=None, ) z_exponent = arg_func_langs.float_arg_from_proto( operation_proto.phasedxzgate.z_exponent, arg_function_language=arg_function_language, required_arg_name=None, ) axis_phase_exponent = arg_func_langs.float_arg_from_proto( operation_proto.phasedxzgate.axis_phase_exponent, arg_function_language=arg_function_language, required_arg_name=None, ) op = cirq.PhasedXZGate( x_exponent=x_exponent, z_exponent=z_exponent, axis_phase_exponent=axis_phase_exponent, )(*qubits) elif which_gate_type == 'czpowgate': op = cirq.CZPowGate(exponent=arg_func_langs.float_arg_from_proto( operation_proto.czpowgate.exponent, arg_function_language=arg_function_language, required_arg_name=None, ))(*qubits) elif which_gate_type == 'iswappowgate': op = cirq.ISwapPowGate( exponent=arg_func_langs.float_arg_from_proto( operation_proto.iswappowgate.exponent, arg_function_language=arg_function_language, required_arg_name=None, ))(*qubits) elif which_gate_type == 'fsimgate': theta = arg_func_langs.float_arg_from_proto( operation_proto.fsimgate.theta, arg_function_language=arg_function_language, required_arg_name=None, ) phi = arg_func_langs.float_arg_from_proto( operation_proto.fsimgate.phi, arg_function_language=arg_function_language, required_arg_name=None, ) if isinstance(theta, (float, sympy.Basic)) and isinstance( phi, (float, sympy.Basic)): op = cirq.FSimGate(theta=theta, phi=phi)(*qubits) else: raise ValueError( 'theta and phi must be specified for FSimGate') elif which_gate_type == 'measurementgate': key = arg_func_langs.arg_from_proto( operation_proto.measurementgate.key, arg_function_language=arg_function_language, required_arg_name=None, ) invert_mask = arg_func_langs.arg_from_proto( operation_proto.measurementgate.invert_mask, arg_function_language=arg_function_language, required_arg_name=None, ) if isinstance(invert_mask, list) and isinstance(key, str): op = cirq.MeasurementGate( num_qubits=len(qubits), key=key, invert_mask=tuple(invert_mask))(*qubits) else: raise ValueError( f'Incorrect types for measurement gate {invert_mask} {key}' ) elif which_gate_type == 'waitgate': total_nanos = arg_func_langs.float_arg_from_proto( operation_proto.waitgate.duration_nanos, arg_function_language=arg_function_language, required_arg_name=None, ) op = cirq.WaitGate(duration=cirq.Duration(nanos=total_nanos))( *qubits) else: raise ValueError( f'Unsupported serialized gate with type "{which_gate_type}".' f'\n\noperation_proto:\n{operation_proto}') which = operation_proto.WhichOneof('token') if which == 'token_constant_index': if not constants: raise ValueError('Proto has references to constants table ' 'but none was passed in, value =' f'{operation_proto}') op = op.with_tags( CalibrationTag(constants[ operation_proto.token_constant_index].string_value)) elif which == 'token_value': op = op.with_tags(CalibrationTag(operation_proto.token_value)) return op
def from_proto( self, proto: v2.program_pb2.CircuitOperation, *, arg_function_language: str = '', constants: List[v2.program_pb2.Constant] = None, deserialized_constants: List[Any] = None, ) -> cirq.CircuitOperation: """Turns a cirq.google.api.v2.CircuitOperation proto into a CircuitOperation. Args: proto: The proto object to be deserialized. arg_function_language: The `arg_function_language` field from `Program.Language`. constants: The list of Constant protos referenced by constant table indices in `proto`. This list should already have been parsed to produce 'deserialized_constants'. deserialized_constants: The deserialized contents of `constants`. Returns: The deserialized CircuitOperation represented by `proto`. """ if constants is None or deserialized_constants is None: raise ValueError( 'CircuitOp deserialization requires a constants list and a corresponding list of ' 'post-deserialization values (deserialized_constants).' ) if len(deserialized_constants) <= proto.circuit_constant_index: raise ValueError( f'Constant index {proto.circuit_constant_index} in CircuitOperation ' 'does not appear in the deserialized_constants list ' f'(length {len(deserialized_constants)}).' ) circuit = deserialized_constants[proto.circuit_constant_index] if not isinstance(circuit, cirq.FrozenCircuit): raise ValueError( f'Constant at index {proto.circuit_constant_index} was expected to be a circuit, ' f'but it has type {type(circuit)} in the deserialized_constants list.' ) which_rep_spec = proto.repetition_specification.WhichOneof('repetition_value') if which_rep_spec == 'repetition_count': rep_ids = None repetitions = proto.repetition_specification.repetition_count elif which_rep_spec == 'repetition_ids': rep_ids = proto.repetition_specification.repetition_ids.ids repetitions = len(rep_ids) else: rep_ids = None repetitions = 1 qubit_map = { v2.qubit_from_proto_id(entry.key.id): v2.qubit_from_proto_id(entry.value.id) for entry in proto.qubit_map.entries } measurement_key_map = { entry.key.string_key: entry.value.string_key for entry in proto.measurement_key_map.entries } arg_map = { arg_func_langs.arg_from_proto( entry.key, arg_function_language=arg_function_language ): arg_func_langs.arg_from_proto( entry.value, arg_function_language=arg_function_language ) for entry in proto.arg_map.entries } for arg in arg_map.keys(): if not isinstance(arg, (str, sympy.Symbol)): raise ValueError( 'Invalid key parameter type in deserialized CircuitOperation. ' f'Expected str or sympy.Symbol, found {type(arg)}.' f'\nFull arg: {arg}' ) for arg in arg_map.values(): if not isinstance(arg, (str, sympy.Symbol, float, int)): raise ValueError( 'Invalid value parameter type in deserialized CircuitOperation. ' f'Expected str, sympy.Symbol, or number; found {type(arg)}.' f'\nFull arg: {arg}' ) return cirq.CircuitOperation( circuit, repetitions, qubit_map, measurement_key_map, arg_map, # type: ignore rep_ids, )