def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared lower than three - absolute amp is within [0.9, 1.1] - base is less than 0.1 - amp error is less than 0.1 - tau error is less than its value - base error is less than 0.1 """ amp = fit_data.fitval("amp") tau = fit_data.fitval("tau") base = fit_data.fitval("base") criteria = [ fit_data.reduced_chisq < 3, abs(amp.value - 1.0) < 0.1, abs(base.value) < 0.1, amp.stderr is None or amp.stderr < 0.1, tau.stderr is None or tau.stderr < tau.value, base.stderr is None or base.stderr < 0.1, ] if all(criteria): return "good" return "bad"
def _extra_database_entry(self, fit_data: curve.FitData) -> List[AnalysisResultData]: """Calculate EPC.""" nrb = 2**self._num_qubits scale = (nrb - 1) / nrb alpha = fit_data.fitval("alpha") alpha_c = fit_data.fitval("alpha_c") # Calculate epc_est (=r_c^est) - Eq. (4): epc = scale * (1 - alpha_c) # Calculate the systematic error bounds - Eq. (5): systematic_err_1 = scale * (abs(alpha.n - alpha_c.n) + (1 - alpha.n)) systematic_err_2 = ( 2 * (nrb * nrb - 1) * (1 - alpha.n) / (alpha.n * nrb * nrb) + 4 * (np.sqrt(1 - alpha.n)) * (np.sqrt(nrb * nrb - 1)) / alpha.n ) systematic_err = min(systematic_err_1, systematic_err_2) systematic_err_l = epc.n - systematic_err systematic_err_r = epc.n + systematic_err extra_data = AnalysisResultData( name="EPC", value=epc, chisq=fit_data.reduced_chisq, quality=self._evaluate_quality(fit_data), extra={ "EPC_systematic_err": systematic_err, "EPC_systematic_bounds": [max(systematic_err_l, 0), systematic_err_r], }, ) return [extra_data]
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared lower than three - absolute amp is within [0.4, 0.6] - base is less is within [0.4, 0.6] - amp error is less than 0.1 - tau error is less than its value - base error is less than 0.1 """ amp = fit_data.fitval("amp") tau = fit_data.fitval("tau") base = fit_data.fitval("base") criteria = [ fit_data.reduced_chisq < 3, abs(amp.nominal_value - 0.5) < 0.1, abs(base.nominal_value - 0.5) < 0.1, curve.is_error_not_significant(amp, absolute=0.1), curve.is_error_not_significant(tau), curve.is_error_not_significant(base, absolute=0.1), ] if all(criteria): return "good" return "bad"
def _extra_database_entry(self, fit_data: curve.FitData) -> List[AnalysisResultData]: """Calculate Hamiltonian coefficients from fit values.""" extra_entries = [] for control in ("z", "i"): for target in ("x", "y", "z"): p0_val = fit_data.fitval(f"p{target}0") p1_val = fit_data.fitval(f"p{target}1") if control == "z": coef_val = 0.5 * (p0_val - p1_val) / (2 * np.pi) else: coef_val = 0.5 * (p0_val + p1_val) / (2 * np.pi) extra_entries.append( AnalysisResultData( name=f"omega_{control}{target}", value=coef_val, chisq=fit_data.reduced_chisq, device_components=[Qubit(q) for q in self._physical_qubits], extra={"unit": "Hz"}, ) ) return extra_entries
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared lower than three, - an error on the frequency smaller than the frequency. """ fit_freq = fit_data.fitval("freq").value fit_freq_err = fit_data.fitval("freq").stderr criteria = [ fit_data.reduced_chisq < 3, fit_freq_err < abs(fit_freq), ] if all(criteria): return "good" return "bad"
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared less than 3, - a peak within the scanned frequency range, - a standard deviation that is not larger than the scanned frequency range, - a standard deviation that is wider than the smallest frequency increment, - a signal-to-noise ratio, defined as the amplitude of the peak divided by the square root of the median y-value less the fit offset, greater than a threshold of two, and - a standard error on the sigma of the Gaussian that is smaller than the sigma. """ curve_data = self._data() max_freq = np.max(curve_data.x) min_freq = np.min(curve_data.x) freq_increment = np.mean(np.diff(curve_data.x)) fit_a = fit_data.fitval("a").value fit_b = fit_data.fitval("b").value fit_freq = fit_data.fitval("freq").value fit_sigma = fit_data.fitval("sigma").value fit_sigma_err = fit_data.fitval("sigma").stderr snr = abs(fit_a) / np.sqrt(abs(np.median(curve_data.y) - fit_b)) fit_width_ratio = fit_sigma / (max_freq - min_freq) criteria = [ min_freq <= fit_freq <= max_freq, 1.5 * freq_increment < fit_sigma, fit_width_ratio < 0.25, fit_data.reduced_chisq < 3, (fit_sigma_err is None or fit_sigma_err < fit_sigma), snr > 2, ] if all(criteria): return "good" return "bad"
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared lower than three - relative error of tau is less than its value - relative error of freq is less than its value """ tau = fit_data.fitval("tau") freq = fit_data.fitval("freq") criteria = [ fit_data.reduced_chisq < 3, tau.stderr is None or tau.stderr < tau.value, freq.stderr is None or freq.stderr < freq.value, ] if all(criteria): return "good" return "bad"
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared lower than three, - a DRAG parameter value within the first period of the lowest number of repetitions, - an error on the drag beta smaller than the beta. """ fit_beta = fit_data.fitval("beta") fit_freq0 = fit_data.fitval("freq0") criteria = [ fit_data.reduced_chisq < 3, fit_beta.nominal_value < 1 / fit_freq0.nominal_value, curve.is_error_not_significant(fit_beta), ] if all(criteria): return "good" return "bad"
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared lower than three - relative error of tau is less than its value - relative error of freq is less than its value """ tau = fit_data.fitval("tau") freq = fit_data.fitval("freq") criteria = [ fit_data.reduced_chisq < 3, curve.is_error_not_significant(tau), curve.is_error_not_significant(freq), ] if all(criteria): return "good" return "bad"
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared lower than three, - more than a quarter of a full period, - less than 10 full periods, and - an error on the fit frequency lower than the fit frequency. """ fit_freq = fit_data.fitval("freq").value fit_freq_err = fit_data.fitval("freq").stderr criteria = [ fit_data.reduced_chisq < 3, 1.0 / 4.0 < fit_freq < 10.0, (fit_freq_err is None or (fit_freq_err < fit_freq)), ] if all(criteria): return "good" return "bad"
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared less than 3, - a peak within the scanned frequency range, - a standard deviation that is not larger than the scanned frequency range, - a standard deviation that is wider than the smallest frequency increment, - a signal-to-noise ratio, defined as the amplitude of the peak divided by the square root of the median y-value less the fit offset, greater than a threshold of two, and - a standard error on the kappa of the Lorentzian that is smaller than the kappa. """ freq_increment = np.mean(np.diff(fit_data.x_data)) fit_a = fit_data.fitval("a") fit_b = fit_data.fitval("b") fit_freq = fit_data.fitval("freq") fit_kappa = fit_data.fitval("kappa") snr = abs(fit_a.n) / np.sqrt(abs(np.median(fit_data.y_data) - fit_b.n)) fit_width_ratio = fit_kappa.n / np.ptp(fit_data.x_data) criteria = [ fit_data.x_range[0] <= fit_freq.n <= fit_data.x_range[1], 1.5 * freq_increment < fit_kappa.n, fit_width_ratio < 0.25, fit_data.reduced_chisq < 3, curve.is_error_not_significant(fit_kappa), snr > 2, ] if all(criteria): return "good" return "bad"
def _evaluate_quality(self, fit_data: curve.FitData) -> Union[str, None]: """Algorithmic criteria for whether the fit is good or bad. A good fit has: - a reduced chi-squared lower than three, - a measured angle error that is smaller than the allowed maximum good angle error. This quantity is set in the analysis options. """ fit_d_theta = fit_data.fitval("d_theta").value criteria = [ fit_data.reduced_chisq < 3, abs(fit_d_theta) < abs(self.options.max_good_angle_error), ] if all(criteria): return "good" return "bad"
def _create_analysis_results( self, fit_data: curve.FitData, quality: str, **metadata, ) -> List[AnalysisResultData]: """Create analysis results for important fit parameters. Args: fit_data: Fit outcome. quality: Quality of fit outcome. Returns: List of analysis result data. """ outcomes = super()._create_analysis_results(fit_data, quality, **metadata) for control in ("z", "i"): for target in ("x", "y", "z"): p0_val = fit_data.fitval(f"p{target}0") p1_val = fit_data.fitval(f"p{target}1") if control == "z": coef_val = 0.5 * (p0_val - p1_val) / (2 * np.pi) else: coef_val = 0.5 * (p0_val + p1_val) / (2 * np.pi) outcomes.append( AnalysisResultData( name=f"omega_{control}{target}", value=coef_val, chisq=fit_data.reduced_chisq, quality=quality, extra={ "unit": "Hz", **metadata, }, )) return outcomes
def _extra_database_entry( self, fit_data: curve.FitData) -> List[AnalysisResultData]: """Calculate EPC.""" extra_entries = [] # Calculate EPC alpha = fit_data.fitval("alpha") scale = (2**self._num_qubits - 1) / (2**self._num_qubits) epc = scale * (1 - alpha) extra_entries.append( AnalysisResultData( name="EPC", value=epc, chisq=fit_data.reduced_chisq, quality=self._evaluate_quality(fit_data), )) # Calculate EPG if not self.options.gate_error_ratio: # we attempt to get the ratio from the backend properties if not self.options.error_dict: gate_error_ratio = RBUtils.get_error_dict_from_backend( backend=self._backend, qubits=self._physical_qubits) else: gate_error_ratio = self.options.error_dict else: gate_error_ratio = self.options.gate_error_ratio count_ops = [] for meta in self._data(label="raw_data").metadata: count_ops += meta.get("count_ops", []) if len(count_ops) > 0 and gate_error_ratio is not None: gates_per_clifford = RBUtils.gates_per_clifford(count_ops) num_qubits = len(self._physical_qubits) if num_qubits == 1: epg_dict = RBUtils.calculate_1q_epg( epc, self._physical_qubits, gate_error_ratio, gates_per_clifford, ) elif num_qubits == 2: epg_1_qubit = self.options.epg_1_qubit epg_dict = RBUtils.calculate_2q_epg( epc, self._physical_qubits, gate_error_ratio, gates_per_clifford, epg_1_qubit=epg_1_qubit, ) else: # EPG calculation is not supported for more than 3 qubits RB epg_dict = None if epg_dict: for qubits, gate_dict in epg_dict.items(): for gate, value in gate_dict.items(): extra_entries.append( AnalysisResultData( f"EPG_{gate}", value, chisq=fit_data.reduced_chisq, quality=self._evaluate_quality(fit_data), device_components=[Qubit(i) for i in qubits], )) return extra_entries
def _create_analysis_results( self, fit_data: curve.FitData, quality: str, **metadata, ) -> List[AnalysisResultData]: """Create analysis results for important fit parameters. Args: fit_data: Fit outcome. quality: Quality of fit outcome. Returns: List of analysis result data. """ outcomes = super()._create_analysis_results(fit_data, quality, **metadata) num_qubits = len(self._physical_qubits) # Calculate EPC alpha = fit_data.fitval("alpha") scale = (2**num_qubits - 1) / (2**num_qubits) epc = scale * (1 - alpha) outcomes.append( AnalysisResultData( name="EPC", value=epc, chisq=fit_data.reduced_chisq, quality=quality, extra=metadata, )) # Correction for 1Q depolarizing channel if EPGs are provided if self.options.epg_1_qubit and num_qubits == 2: epc = _exclude_1q_error( epc=epc, qubits=self._physical_qubits, gate_counts_per_clifford=self._gate_counts_per_clifford, extra_analyses=self.options.epg_1_qubit, ) outcomes.append( AnalysisResultData( name="EPC_corrected", value=epc, chisq=fit_data.reduced_chisq, quality=quality, extra=metadata, )) # Calculate EPG if self._gate_counts_per_clifford is not None and self.options.gate_error_ratio: epg_dict = _calculate_epg( epc=epc, qubits=self._physical_qubits, gate_error_ratio=self.options.gate_error_ratio, gate_counts_per_clifford=self._gate_counts_per_clifford, ) if epg_dict: for gate, epg_val in epg_dict.items(): outcomes.append( AnalysisResultData( name=f"EPG_{gate}", value=epg_val, chisq=fit_data.reduced_chisq, quality=quality, extra=metadata, )) return outcomes