Skip to content

Commit 17ecf95

Browse files
authored
Update numpy_backend.py
1 parent 801175d commit 17ecf95

1 file changed

Lines changed: 18 additions & 11 deletions

File tree

backends/numpy_backend.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
# quantum_sim/backends/numpy_backend.py
22

33
import numpy as np
4-
from typing import Dict, List
4+
from typing import Dict, List, Optional, Any
55

66
from quantum_sim.backends.backend import QuantumBackend
7+
# Note: Ensure GateOperation is defined/exported in quantum_sim.core.circuit
78
from quantum_sim.core.circuit import QuantumCircuit, GateOperation
89
from quantum_sim.core.noise import NoiseChannel, ThermalRelaxationChannel
910

1011

1112
class NumpyBackend(QuantumBackend):
1213
"""
1314
A quantum simulation backend that uses NumPy for density matrix manipulation
14-
and accurately models time-dependent noise (T1/T2) and per-gate noise using Numba JIT acceleration.
15-
Acts as a time-aware scheduling engine.
15+
and accurately models time-dependent noise (T1/T2) and per-gate noise.
1616
"""
1717

1818
def __init__(self,
1919
num_qubits: int,
20-
t1_times: Dict[int, float] = None,
21-
t2_times: Dict[int, float] = None,
20+
t1_times: Optional[Dict[int, float]] = None,
21+
t2_times: Optional[Dict[int, float]] = None,
2222
p_ex: float = 0.0,
23-
per_qubit_noise_channels: Dict[int, List[NoiseChannel]] = None):
23+
per_qubit_noise_channels: Optional[Dict[int, List[NoiseChannel]]] = None):
2424
"""
2525
Initializes the backend with hardware-specific noise parameters.
2626
"""
@@ -57,12 +57,16 @@ def run_circuit(self, circuit: QuantumCircuit) -> np.ndarray:
5757
current_rho_tensor = self._create_initial_density_matrix(circuit.num_qubits)
5858
qubit_map = {q_id: q_id for q_id in range(circuit.num_qubits)}
5959

60-
for component in circuit._components:
60+
# Ensure circuit._components is handled by type checking or
61+
# defined in the QuantumCircuit class.
62+
for component in getattr(circuit, "_components", []):
6163
gate_duration = 0.0
6264
if isinstance(component, GateOperation):
6365
gate_duration = component.gate.duration
6466
elif isinstance(component, QuantumCircuit):
65-
durations = [op.gate.duration for op in component._components if isinstance(op, GateOperation)]
67+
# Safely access internal components of sub-circuits
68+
sub_comps = getattr(component, "_components", [])
69+
durations = [op.gate.duration for op in sub_comps if isinstance(op, GateOperation)]
6670
gate_duration = max(durations) if durations else 0.0
6771

6872
# --- Apply IDLE Noise BEFORE operation ---
@@ -99,7 +103,8 @@ def run_circuit(self, circuit: QuantumCircuit) -> np.ndarray:
99103
current_rho_tensor, q_id, circuit.num_qubits, dt=dt_final
100104
)
101105

102-
return current_rho_tensor.reshape((2**circuit.num_qubits, 2**circuit.num_qubits))
106+
final_dim = 2**circuit.num_qubits
107+
return current_rho_tensor.reshape((final_dim, final_dim))
103108

104109
def get_probabilities(self, rho_matrix: np.ndarray) -> np.ndarray:
105110
return np.diag(rho_matrix).real
@@ -108,8 +113,10 @@ def get_measurements(self, rho_matrix: np.ndarray, num_shots: int) -> Dict[str,
108113
probabilities = self.get_probabilities(rho_matrix)
109114
num_qubits = int(np.log2(rho_matrix.shape[0]))
110115
outcomes = np.random.choice(len(rho_matrix), size=num_shots, p=probabilities)
111-
counts = {}
116+
117+
# Fixed: Explicit type annotation for the dictionary to satisfy mypy
118+
counts: Dict[str, int] = {}
112119
for outcome in outcomes:
113-
bitstring = bin(outcome)[2:].zfill(num_qubits)
120+
bitstring = bin(int(outcome))[2:].zfill(num_qubits)
114121
counts[bitstring] = counts.get(bitstring, 0) + 1
115122
return counts

0 commit comments

Comments
 (0)