def get_parameterized_gate(self): theta = THETA_SYMBOL if self.characterize_theta else self.theta_default zeta = ZETA_SYMBOL if self.characterize_zeta else self.zeta_default chi = CHI_SYMBOL if self.characterize_chi else self.chi_default gamma = GAMMA_SYMBOL if self.characterize_gamma else self.gamma_default phi = PHI_SYMBOL if self.characterize_phi else self.phi_default return ops.PhasedFSimGate(theta=theta, zeta=zeta, chi=chi, gamma=gamma, phi=phi)
def parameterize_phased_fsim_circuit( circuit: 'cirq.Circuit', phased_fsim_options: XEBPhasedFSimCharacterizationOptions, ) -> 'cirq.Circuit': """Parameterize PhasedFSim-like gates in a given circuit according to `phased_fsim_options`. """ options = phased_fsim_options theta = THETA_SYMBOL if options.characterize_theta else options.theta_default zeta = ZETA_SYMBOL if options.characterize_zeta else options.zeta_default chi = CHI_SYMBOL if options.characterize_chi else options.chi_default gamma = GAMMA_SYMBOL if options.characterize_gamma else options.gamma_default phi = PHI_SYMBOL if options.characterize_phi else options.phi_default fsim_gate = ops.PhasedFSimGate(theta=theta, zeta=zeta, chi=chi, gamma=gamma, phi=phi) return Circuit( ops.Moment( fsim_gate.on(*op.qubits) if options.should_parameterize(op) else op for op in moment.operations) for moment in circuit.moments)
def noise_properties_from_calibration( calibration: engine.Calibration, zphase_data: Optional[util.ZPhaseDataType] = None, gate_times_ns: Optional[Dict[Type['cirq.Gate'], float]] = None, ) -> google_noise_properties.GoogleNoiseProperties: """Translates between `cirq_google.Calibration` and NoiseProperties. The NoiseProperties object can then be used as input to the `cirq_google.NoiseModelFromGoogleNoiseProperties` class to create a `cirq.NoiseModel` that can be used with a simulator. To manually override noise properties, call `with_params` on the output: >>> noise_props = noise_properties_from_calibration(cal).with_params(gate_times_ns=37) # noise_props with all gate durations set to 37ns. See `cirq_google.GoogleNoiseProperties` for details. Args: calibration: a Calibration object with hardware metrics. zphase_data: Optional data for Z phases not captured by Calibration - specifically, zeta and gamma. These values require Floquet calibration and can be provided here if available. gate_times_ns: Map of gate durations in nanoseconds. If not provided, defaults to the Sycamore gate times listed in `known_devices.py`. Returns: A `cirq_google.GoogleNoiseProperties` which represents the error present in the given Calibration object. """ if gate_times_ns is None: gate_times_ns = DEFAULT_GATE_NS # Unpack all values from Calibration object # 1. Extract T1 for all qubits T1_micros = _unpack_1q_from_calibration('single_qubit_idle_t1_micros', calibration) t1_ns = {q: T1_micro * 1000 for q, T1_micro in T1_micros.items()} # 2. Extract Tphi for all qubits rb_incoherent_errors = _unpack_1q_from_calibration( 'single_qubit_rb_incoherent_error_per_gate', calibration) tphi_ns = {} if rb_incoherent_errors: microwave_time_ns = gate_times_ns[ops.PhasedXZGate] for qubit, q_t1_ns in t1_ns.items(): tphi_err = rb_incoherent_errors[qubit] - microwave_time_ns / ( 3 * q_t1_ns) q_tphi_ns = 1e10 if tphi_err <= 0 else microwave_time_ns / ( 3 * tphi_err) tphi_ns[qubit] = q_tphi_ns # 3a. Extract Pauli error for single-qubit gates. rb_pauli_errors = _unpack_1q_from_calibration( 'single_qubit_rb_pauli_error_per_gate', calibration) gate_pauli_errors = { noise_utils.OpIdentifier(gate, q): pauli_err for q, pauli_err in rb_pauli_errors.items() for gate in google_noise_properties.GoogleNoiseProperties.single_qubit_gates() } # 3b. Extract Pauli error for two-qubit gates. for gate, prefix in GATE_PREFIX_PAIRS.items(): pauli_error = _unpack_2q_from_calibration( prefix + '_xeb_pauli_error_per_cycle', calibration) gate_pauli_errors.update({ k: v for qs, pauli_err in pauli_error.items() for k, v in { noise_utils.OpIdentifier(gate, *qs): pauli_err, noise_utils.OpIdentifier(gate, *qs[::-1]): pauli_err, }.items() }) # 4. Extract readout fidelity for all qubits. p00 = _unpack_1q_from_calibration('single_qubit_p00_error', calibration) p11 = _unpack_1q_from_calibration('single_qubit_p11_error', calibration) readout_errors = { q: [p00.get(q, 0), p11.get(q, 0)] for q in set(p00.keys()) | set(p11.keys()) } # 5. Extract entangling angle errors. fsim_errors = {} for gate, prefix in GATE_PREFIX_PAIRS.items(): theta_errors = _unpack_2q_from_calibration( prefix + '_xeb_entangler_theta_error_per_cycle', calibration) phi_errors = _unpack_2q_from_calibration( prefix + '_xeb_entangler_phi_error_per_cycle', calibration) gate_str = GATE_ZPHASE_CODE_PAIRS[gate] if zphase_data and gate_str in zphase_data: zeta_errors = zphase_data[gate_str]["zeta"] gamma_errors = zphase_data[gate_str]["gamma"] else: zeta_errors = {} gamma_errors = {} angle_keys = { *theta_errors.keys(), *phi_errors.keys(), *zeta_errors.keys(), *gamma_errors.keys(), } for qubits in angle_keys: theta = theta_errors.get(qubits, 0) phi = phi_errors.get(qubits, 0) zeta = zeta_errors.get(qubits, 0) gamma = gamma_errors.get(qubits, 0) op_id = noise_utils.OpIdentifier(gate, *qubits) error_gate = ops.PhasedFSimGate(theta=theta, phi=phi, zeta=zeta, gamma=gamma) fsim_errors[op_id] = error_gate op_id_reverse = noise_utils.OpIdentifier(gate, *qubits[::-1]) fsim_errors[op_id_reverse] = error_gate # Known false positive: https://github.com/PyCQA/pylint/issues/5857 return google_noise_properties.GoogleNoiseProperties( # pylint: disable=unexpected-keyword-arg gate_times_ns=gate_times_ns, t1_ns=t1_ns, tphi_ns=tphi_ns, readout_errors=readout_errors, gate_pauli_errors=gate_pauli_errors, fsim_errors=fsim_errors, )
def noise_properties_from_calibration( calibration: engine.Calibration, ) -> google_noise_properties.GoogleNoiseProperties: """Translates between `cirq_google.Calibration` and NoiseProperties. The NoiseProperties object can then be used as input to the `cirq_google.NoiseModelFromGoogleNoiseProperties` class to create a `cirq.NoiseModel` that can be used with a simulator. To manually override noise properties, call `with_params` on the output: >>> noise_props = noise_properties_from_calibration(cal).with_params(gate_times_ns=37) # noise_props with all gate durations set to 37ns. See `cirq_google.GoogleNoiseProperties` for details. Args: calibration: a Calibration object with hardware metrics. Returns: A `cirq_google.GoogleNoiseProperties` which represents the error present in the given Calibration object. """ # TODO: acquire this based on the target device. # Default map of gates to their durations. default_gate_ns: Dict[Type['cirq.Gate'], float] = { ops.ZPowGate: 25.0, ops.MeasurementGate: 4000.0, ops.ResetChannel: 250.0, ops.PhasedXZGate: 25.0, ops.FSimGate: 32.0, ops.ISwapPowGate: 32.0, ops.CZPowGate: 32.0, cg_ops.SycamoreGate: 12.0, # ops.WaitGate is a special case. } # Unpack all values from Calibration object # 1. Extract T1 for all qubits T1_micros = _unpack_1q_from_calibration('single_qubit_idle_t1_micros', calibration) t1_ns = {q: T1_micro * 1000 for q, T1_micro in T1_micros.items()} # 2. Extract Tphi for all qubits rb_incoherent_errors = _unpack_1q_from_calibration( 'single_qubit_rb_incoherent_error_per_gate', calibration) tphi_ns = {} if rb_incoherent_errors: microwave_time_ns = default_gate_ns[ops.PhasedXZGate] for qubit, q_t1_ns in t1_ns.items(): tphi_err = rb_incoherent_errors[qubit] - microwave_time_ns / ( 3 * q_t1_ns) q_tphi_ns = 1e10 if tphi_err <= 0 else microwave_time_ns / ( 3 * tphi_err) tphi_ns[qubit] = q_tphi_ns # 3a. Extract Pauli error for single-qubit gates. rb_pauli_errors = _unpack_1q_from_calibration( 'single_qubit_rb_pauli_error_per_gate', calibration) gate_pauli_errors = { noise_utils.OpIdentifier(gate, q): pauli_err for q, pauli_err in rb_pauli_errors.items() for gate in google_noise_properties.GoogleNoiseProperties.single_qubit_gates() } # 3b. Extract Pauli error for two-qubit gates. gate_prefix_pairs: Dict[Type['cirq.Gate'], str] = { cg_ops.SycamoreGate: 'two_qubit_parallel_sycamore_gate', ops.ISwapPowGate: 'two_qubit_parallel_sqrt_iswap_gate', } for gate, prefix in gate_prefix_pairs.items(): pauli_error = _unpack_2q_from_calibration( prefix + '_xeb_pauli_error_per_cycle', calibration) gate_pauli_errors.update({ k: v for qs, pauli_err in pauli_error.items() for k, v in { noise_utils.OpIdentifier(gate, *qs): pauli_err, noise_utils.OpIdentifier(gate, *qs[::-1]): pauli_err, }.items() }) # 4. Extract readout fidelity for all qubits. p00 = _unpack_1q_from_calibration('single_qubit_p00_error', calibration) p11 = _unpack_1q_from_calibration('single_qubit_p11_error', calibration) readout_errors = { q: np.array([p00.get(q, 0), p11.get(q, 0)]) for q in set(p00.keys()) | set(p11.keys()) } # 5. Extract entangling angle errors. fsim_errors = {} for gate, prefix in gate_prefix_pairs.items(): theta_errors = _unpack_2q_from_calibration( prefix + '_xeb_entangler_theta_error_per_cycle', calibration) phi_errors = _unpack_2q_from_calibration( prefix + '_xeb_entangler_phi_error_per_cycle', calibration) angle_keys = set(theta_errors.keys()) | set(phi_errors.keys()) for qubits in angle_keys: theta = theta_errors.get(qubits, 0) phi = phi_errors.get(qubits, 0) op_id = noise_utils.OpIdentifier(gate, *qubits) fsim_errors[op_id] = ops.PhasedFSimGate(theta=theta, phi=phi) op_id_reverse = noise_utils.OpIdentifier(gate, *qubits[::-1]) fsim_errors[op_id_reverse] = ops.PhasedFSimGate(theta=theta, phi=phi) # Known false positive: https://github.com/PyCQA/pylint/issues/5857 return google_noise_properties.GoogleNoiseProperties( # pylint: disable=unexpected-keyword-arg gate_times_ns=default_gate_ns, t1_ns=t1_ns, tphi_ns=tphi_ns, readout_errors=readout_errors, gate_pauli_errors=gate_pauli_errors, fsim_errors=fsim_errors, )