hchevva commited on
Commit
133c57c
·
verified ·
1 Parent(s): 82467f9

Upload noise_model.py

Browse files
Files changed (1) hide show
  1. quread/noise_model.py +68 -0
quread/noise_model.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from typing import Dict, Optional
4
+
5
+ import numpy as np
6
+
7
+ from .metrics import parse_calibration_json
8
+
9
+
10
+ def sample_noisy_counts(
11
+ state: np.ndarray,
12
+ n_qubits: int,
13
+ shots: int,
14
+ *,
15
+ calibration_json: str = "",
16
+ readout_scale: float = 1.0,
17
+ depolarizing_prob: float = 0.0,
18
+ seed: Optional[int] = None,
19
+ ) -> Dict[str, int]:
20
+ """
21
+ Sample measurement outcomes from a statevector, then apply a simple hardware-noise proxy:
22
+ - Depolarizing stage: with probability depolarizing_prob, replace shot with random basis state.
23
+ - Readout stage: independent bit-flip per qubit using scaled readout_error from calibration JSON.
24
+ """
25
+ n = int(n_qubits)
26
+ s = int(shots)
27
+ if n < 1:
28
+ raise ValueError("n_qubits must be >= 1")
29
+ if s < 1:
30
+ raise ValueError("shots must be >= 1")
31
+
32
+ vec = np.asarray(state, dtype=complex).reshape(-1)
33
+ dim = 2 ** n
34
+ if vec.size != dim:
35
+ raise ValueError(f"State size mismatch: expected {dim}, got {vec.size}")
36
+
37
+ probs = np.abs(vec) ** 2
38
+ total = float(np.sum(probs))
39
+ if total <= 0:
40
+ raise ValueError("State probabilities are all zero.")
41
+ probs = probs / total
42
+
43
+ cal, _note = parse_calibration_json(calibration_json, n)
44
+ readout_error = np.clip(cal["readout_error"] * float(readout_scale), 0.0, 1.0)
45
+ depol = float(np.clip(float(depolarizing_prob), 0.0, 1.0))
46
+
47
+ rng = np.random.default_rng(seed)
48
+ ideal = rng.choice(np.arange(dim), size=s, p=probs)
49
+
50
+ counts: Dict[str, int] = {}
51
+ for idx in ideal:
52
+ idx_i = int(idx)
53
+
54
+ # Depolarizing replacement
55
+ if rng.random() < depol:
56
+ idx_i = int(rng.integers(0, dim))
57
+
58
+ bits = list(format(idx_i, f"0{n}b"))
59
+
60
+ # Readout bit flips
61
+ for q in range(n):
62
+ if rng.random() < float(readout_error[q]):
63
+ bits[q] = "1" if bits[q] == "0" else "0"
64
+
65
+ b = "".join(bits)
66
+ counts[b] = counts.get(b, 0) + 1
67
+
68
+ return dict(sorted(counts.items()))