From 0c2f824180124af7b72b579eaf919d9c90df4ccf Mon Sep 17 00:00:00 2001 From: Manideep3969 Date: Thu, 20 Aug 2026 12:25:16 +0530 Subject: [PATCH] fix(#50): centralize duplicated default constants in utils.py Default error rates (0.0005, 0.01, 0.015), T2 time (150e-6), and gate durations (50e-9, 300e-9) were hardcoded in cost_model.py, cutting.py, scheduling.py, and utils.py. Updating one would miss the others. Fix: Define DEFAULT_SINGLE_QUBIT_ERROR, DEFAULT_TWO_QUBIT_ERROR, DEFAULT_READOUT_ERROR, DEFAULT_T2_TIME, DEFAULT_SINGLE_QUBIT_GATE_TIME, DEFAULT_TWO_QUBIT_GATE_TIME as module-level constants in utils.py. Import and use them in cost_model.py, cutting.py, and scheduling.py. --- src/qc_compiler/__init__.py | 12 ++++++++++++ src/qc_compiler/cost_model.py | 19 ++++++++++--------- src/qc_compiler/cutting.py | 18 ++++++++++++------ src/qc_compiler/scheduling.py | 3 ++- src/qc_compiler/utils.py | 15 +++++++++++---- 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/qc_compiler/__init__.py b/src/qc_compiler/__init__.py index e8f0c5e..84a83bb 100644 --- a/src/qc_compiler/__init__.py +++ b/src/qc_compiler/__init__.py @@ -21,6 +21,12 @@ from qc_compiler.scheduling import CoherenceAwareScheduler, ScheduleResult from qc_compiler.transpiler import OptimizerConfig, QCompiler, QCompilerResult from qc_compiler.utils import ( + DEFAULT_READOUT_ERROR, + DEFAULT_SINGLE_QUBIT_ERROR, + DEFAULT_SINGLE_QUBIT_GATE_TIME, + DEFAULT_T2_TIME, + DEFAULT_TWO_QUBIT_ERROR, + DEFAULT_TWO_QUBIT_GATE_TIME, TWO_QUBIT_GATES, compute_circuit_depth, compute_cnot_count, @@ -30,6 +36,12 @@ ) __all__ = [ + "DEFAULT_READOUT_ERROR", + "DEFAULT_SINGLE_QUBIT_ERROR", + "DEFAULT_SINGLE_QUBIT_GATE_TIME", + "DEFAULT_T2_TIME", + "DEFAULT_TWO_QUBIT_ERROR", + "DEFAULT_TWO_QUBIT_GATE_TIME", "TWO_QUBIT_GATES", "AdaptiveErrorMitigation", "AutoTuner", diff --git a/src/qc_compiler/cost_model.py b/src/qc_compiler/cost_model.py index 3352a49..2cc5251 100644 --- a/src/qc_compiler/cost_model.py +++ b/src/qc_compiler/cost_model.py @@ -18,6 +18,11 @@ from qiskit import QuantumCircuit from qc_compiler.utils import ( + DEFAULT_READOUT_ERROR, + DEFAULT_SINGLE_QUBIT_ERROR, + DEFAULT_SINGLE_QUBIT_GATE_TIME, + DEFAULT_T2_TIME, + DEFAULT_TWO_QUBIT_ERROR, TWO_QUBIT_GATES, compute_circuit_depth, get_backend_properties, @@ -342,7 +347,7 @@ def _get_gate_fidelity_for_pair( def _avg_single_qubit_error(self) -> float: """Compute average single-qubit gate error across all qubits.""" if not self.device.single_qubit_gate_errors: - return 0.0005 + return DEFAULT_SINGLE_QUBIT_ERROR errors = list(self.device.single_qubit_gate_errors.values()) return sum(errors) / len(errors) @@ -350,7 +355,7 @@ def _avg_single_qubit_error(self) -> float: def _avg_two_qubit_error(self) -> float: """Compute average two-qubit gate error across all qubit pairs.""" if not self.device.two_qubit_gate_errors: - return 0.01 + return DEFAULT_TWO_QUBIT_ERROR errors = list(self.device.two_qubit_gate_errors.values()) return sum(errors) / len(errors) @@ -401,12 +406,9 @@ def _estimate_decoherence_error_default( Uses typical superconducting qubit T2 time of 150 μs. """ - DEFAULT_T2 = 150e-6 - DEFAULT_GATE_TIME = 50e-9 - depth = compute_circuit_depth(circuit) - total_time = depth * DEFAULT_GATE_TIME - fidelity = float(2.0 ** (-total_time / DEFAULT_T2)) + total_time = depth * DEFAULT_SINGLE_QUBIT_GATE_TIME + fidelity = float(2.0 ** (-total_time / DEFAULT_T2_TIME)) product = fidelity**circuit.num_qubits return 1.0 - product @@ -414,7 +416,7 @@ def _estimate_decoherence_error_default( def _avg_gate_time(self) -> float: """Compute average gate duration across all gate types.""" if not self.device.gate_lengths: - return 50e-9 + return DEFAULT_SINGLE_QUBIT_GATE_TIME times = list(self.device.gate_lengths.values()) return sum(times) / len(times) @@ -435,7 +437,6 @@ def estimate_measurement_error( measured_qubits = self._get_measured_qubits(circuit) if not self.device.readout_errors: - DEFAULT_READOUT_ERROR = 0.015 return 1.0 - (1.0 - DEFAULT_READOUT_ERROR) ** len(measured_qubits) product = 1.0 diff --git a/src/qc_compiler/cutting.py b/src/qc_compiler/cutting.py index 9bbacbc..269e557 100644 --- a/src/qc_compiler/cutting.py +++ b/src/qc_compiler/cutting.py @@ -43,7 +43,13 @@ from qiskit import QuantumCircuit from qc_compiler.cost_model import CostModel -from qc_compiler.utils import TWO_QUBIT_GATES +from qc_compiler.utils import ( + DEFAULT_SINGLE_QUBIT_ERROR, + DEFAULT_SINGLE_QUBIT_GATE_TIME, + DEFAULT_T2_TIME, + DEFAULT_TWO_QUBIT_ERROR, + TWO_QUBIT_GATES, +) @dataclass @@ -535,8 +541,8 @@ def _estimate_cut_error( depth = max(1, circuit.depth() // num_groups) avg_t2 = self._avg_t2() decoherence_error = 1 - float( - 2.0 ** (-depth * 50e-9 / avg_t2) - ) if avg_t2 > 0 else 0.01 + 2.0 ** (-depth * DEFAULT_SINGLE_QUBIT_GATE_TIME / avg_t2) + ) if avg_t2 > 0 else DEFAULT_TWO_QUBIT_ERROR group_error = 1 - (1 - gate_error) * (1 - decoherence_error) group_errors.append(group_error) @@ -654,7 +660,7 @@ def _avg_single_qubit_error(self) -> float: self.cost_model.device.single_qubit_gate_errors.values() ) return sum(errors) / len(errors) - return 0.0005 + return DEFAULT_SINGLE_QUBIT_ERROR def _avg_two_qubit_error(self) -> float: """Get average two-qubit gate error from device or default.""" @@ -663,11 +669,11 @@ def _avg_two_qubit_error(self) -> float: self.cost_model.device.two_qubit_gate_errors.values() ) return sum(errors) / len(errors) - return 0.01 + return DEFAULT_TWO_QUBIT_ERROR def _avg_t2(self) -> float: """Get average T2 time from device or default.""" if self.cost_model.device.t2_times: times = list(self.cost_model.device.t2_times.values()) return sum(times) / len(times) - return 150e-6 \ No newline at end of file + return DEFAULT_T2_TIME \ No newline at end of file diff --git a/src/qc_compiler/scheduling.py b/src/qc_compiler/scheduling.py index 0277c35..902f477 100644 --- a/src/qc_compiler/scheduling.py +++ b/src/qc_compiler/scheduling.py @@ -33,6 +33,7 @@ from qiskit import QuantumCircuit from qc_compiler.cost_model import CostModel +from qc_compiler.utils import DEFAULT_SINGLE_QUBIT_GATE_TIME @dataclass @@ -504,7 +505,7 @@ def _avg_gate_time(self) -> float: if self.cost_model.device.gate_lengths: times = list(self.cost_model.device.gate_lengths.values()) return sum(times) / len(times) - return 50e-9 + return DEFAULT_SINGLE_QUBIT_GATE_TIME def _compute_t2_priority(self, num_qubits: int) -> dict[int, float]: """Compute per-qubit T2-based scheduling priority. diff --git a/src/qc_compiler/utils.py b/src/qc_compiler/utils.py index 98f525c..f7dd805 100644 --- a/src/qc_compiler/utils.py +++ b/src/qc_compiler/utils.py @@ -13,6 +13,13 @@ TWO_QUBIT_GATES = {"cx", "cz", "ecr", "swap", "rxx", "rzz", "ryy", "crx", "cry", "crz"} +DEFAULT_SINGLE_QUBIT_ERROR = 0.0005 +DEFAULT_TWO_QUBIT_ERROR = 0.01 +DEFAULT_READOUT_ERROR = 0.015 +DEFAULT_T2_TIME = 150e-6 +DEFAULT_SINGLE_QUBIT_GATE_TIME = 50e-9 +DEFAULT_TWO_QUBIT_GATE_TIME = 300e-9 + def get_backend_properties(backend: BackendV2) -> dict: """Extract calibration properties from a quantum backend. @@ -164,8 +171,8 @@ def get_avg_gate_time(device_props: dict, gate_type: str = "all") -> float: if not gate_lengths: if gate_type == "two": - return 300e-9 - return 50e-9 + return DEFAULT_TWO_QUBIT_GATE_TIME + return DEFAULT_SINGLE_QUBIT_GATE_TIME times = [] for (gate_name, qubits), duration in gate_lengths.items(): @@ -174,7 +181,7 @@ def get_avg_gate_time(device_props: dict, gate_type: str = "all") -> float: if not times: if gate_type == "two": - return 300e-9 - return 50e-9 + return DEFAULT_TWO_QUBIT_GATE_TIME + return DEFAULT_SINGLE_QUBIT_GATE_TIME return sum(times) / len(times) \ No newline at end of file