harishaseebat92 commited on
Commit
fd3d804
·
1 Parent(s): c37820f

QLBM : IBM QPU version integrated

Browse files
Files changed (2) hide show
  1. qlbm/qlbm_sample_app.py +15 -4
  2. qlbm/visualize_counts.py +85 -9
qlbm/qlbm_sample_app.py CHANGED
@@ -390,13 +390,16 @@ def get_named_init_state_circuit(
390
  # Configurable Gaussian distribution
391
  # f(x,y,z) = exp(-((x-cx)^2 + (y-cy)^2 + (z-cz)^2) / (2*sigma^2))
392
 
393
- # Default centers to 0.5 (middle of domain)
394
  cx = float(gauss_cx) if gauss_cx is not None else 0.5
395
  cy = float(gauss_cy) if gauss_cy is not None else 0.5
396
  cz = float(gauss_cz) if gauss_cz is not None else 0.5
397
 
398
- # Default sigma to 0.2 (similar to original sig=1 with mu=0.5 behavior)
399
- sigma = float(gauss_sigma) if gauss_sigma is not None else 0.2
 
 
 
400
 
401
  coords = np.arange(N) / N # Normalized [0, 1)
402
 
@@ -486,6 +489,10 @@ def run_sampling_hw_ibm(
486
  if type(ux)==str:
487
  ux,uy,uz=str_to_lambda(ux,uy,uz)
488
 
 
 
 
 
489
  qc_list=get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution)
490
 
491
  pm_optimization_level = 3
@@ -541,7 +548,7 @@ def run_sampling_hw_ibm(
541
  joined_counts = None
542
 
543
 
544
- pts, counts = load_samples(joined_counts,T_total)
545
  output+=[estimate_density(pts, counts, bandwidth=0.05, grid_size=output_resolution)]
546
 
547
  fig = plot_density_isosurface_slider(output, T_list)
@@ -589,6 +596,10 @@ def run_sampling_sim(
589
  if type(ux)==str:
590
  ux,uy,uz=str_to_lambda(ux,uy,uz)
591
 
 
 
 
 
592
  qc_list=get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution,measure=False)
593
  backend = AerSimulator(method = 'statevector')
594
  output=[]
 
390
  # Configurable Gaussian distribution
391
  # f(x,y,z) = exp(-((x-cx)^2 + (y-cy)^2 + (z-cz)^2) / (2*sigma^2))
392
 
393
+ # Default centers to 0.5 (middle of domain) - matches original mu=0.5
394
  cx = float(gauss_cx) if gauss_cx is not None else 0.5
395
  cy = float(gauss_cy) if gauss_cy is not None else 0.5
396
  cz = float(gauss_cz) if gauss_cz is not None else 0.5
397
 
398
+ # Default sigma to 1.0 to match original sig=1 behavior
399
+ # Original formula: exp(-((x - mu) / sig)^2 / 2) with sig=1
400
+ # Our formula: exp(-((x - cx)^2) / (2 * sigma^2))
401
+ # For equivalence: sigma = 1.0 (they are the same formula)
402
+ sigma = float(gauss_sigma) if gauss_sigma is not None else 1.0
403
 
404
  coords = np.arange(N) / N # Normalized [0, 1)
405
 
 
489
  if type(ux)==str:
490
  ux,uy,uz=str_to_lambda(ux,uy,uz)
491
 
492
+ # Convert string init_state_prep_circ to circuit if needed (matches original logic)
493
+ if type(init_state_prep_circ)==str:
494
+ init_state_prep_circ=get_named_init_state_circuit(n,init_state_prep_circ)
495
+
496
  qc_list=get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution)
497
 
498
  pm_optimization_level = 3
 
548
  joined_counts = None
549
 
550
 
551
+ pts, counts = load_samples(joined_counts, T_total, logger=log)
552
  output+=[estimate_density(pts, counts, bandwidth=0.05, grid_size=output_resolution)]
553
 
554
  fig = plot_density_isosurface_slider(output, T_list)
 
596
  if type(ux)==str:
597
  ux,uy,uz=str_to_lambda(ux,uy,uz)
598
 
599
+ # Convert string init_state_prep_circ to circuit if needed (matches original logic)
600
+ if type(init_state_prep_circ)==str:
601
+ init_state_prep_circ=get_named_init_state_circuit(n,init_state_prep_circ)
602
+
603
  qc_list=get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution,measure=False)
604
  backend = AerSimulator(method = 'statevector')
605
  output=[]
qlbm/visualize_counts.py CHANGED
@@ -22,22 +22,73 @@ def bitstring_to_xyz(bs):
22
  maxv = (1 << t)
23
  return ix / maxv, iy / maxv, iz / maxv
24
 
25
- def load_samples(d,T_total):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  pts = []
27
  counts = []
 
 
 
 
 
 
 
 
 
 
 
 
28
  for bs, cnt in d.items():
29
- if bs[:6*T_total] == "0" * 6*T_total:
30
- if cnt<0:
 
 
 
 
31
  continue
32
- x, y, z = bitstring_to_xyz(bs[6*T_total:])
 
 
 
 
 
33
  pts.append([x, y, z])
34
  counts.append(cnt)
 
35
  pts = np.array(pts)
36
  counts = np.array(counts)
37
- print("Number of valid counts:", np.sum(counts))
38
- print("Number of valid bitstrings:", len(counts))
39
- # counts=counts*len(counts)*10/np.sum(counts)
40
- # print(counts)
 
 
 
 
41
  return pts, counts
42
 
43
  def estimate_density(pts, counts, bandwidth=0.05, grid_size=64):
@@ -46,12 +97,37 @@ def estimate_density(pts, counts, bandwidth=0.05, grid_size=64):
46
  Returns (grid_x, grid_y, grid_z, grid_density) where
47
  grid_x, etc. are 3D mesh arrays, and grid_density has same shape.
48
  """
 
 
 
 
 
 
 
 
 
 
 
 
49
  # Expand points by weights: we can replicate points (if counts small),
50
  # or directly use weights in log-likelihood calculation.
51
- # sklearns KernelDensity doesnt support sample weights in .fit,
52
  # but you can approximate by replication or by customizing the KDE.
53
  # Here, for simplicity, replicate (careful of explosion):
54
  pts_rep = np.repeat(pts, counts.astype(int), axis=0)
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  kde = KernelDensity(bandwidth=bandwidth, kernel='gaussian')
56
  kde.fit(pts_rep)
57
 
 
22
  maxv = (1 << t)
23
  return ix / maxv, iy / maxv, iz / maxv
24
 
25
+ def load_samples(d, T_total, logger=None):
26
+ """
27
+ Load samples from measurement counts dictionary.
28
+
29
+ Parameters
30
+ ----------
31
+ d : dict
32
+ Dictionary mapping bitstrings to counts
33
+ T_total : int
34
+ Total number of timesteps (used to determine how many direction bits to check)
35
+ logger : callable, optional
36
+ Function to log messages
37
+
38
+ Returns
39
+ -------
40
+ pts : ndarray
41
+ Array of (x, y, z) points
42
+ counts : ndarray
43
+ Array of counts for each point
44
+ """
45
+ def log(msg):
46
+ if logger:
47
+ logger(str(msg))
48
+ else:
49
+ print(msg)
50
+
51
  pts = []
52
  counts = []
53
+
54
+ if d is None or len(d) == 0:
55
+ log("Warning: Empty counts dictionary")
56
+ return np.array(pts), np.array(counts)
57
+
58
+ # Debug: show sample bitstrings
59
+ sample_keys = list(d.keys())[:3]
60
+ log(f"Sample bitstrings (first 3): {sample_keys}")
61
+ if sample_keys:
62
+ log(f"Bitstring length: {len(sample_keys[0])}")
63
+ log(f"Expected prefix length (6*T_total): {6*T_total}")
64
+
65
  for bs, cnt in d.items():
66
+ # Check if the direction qubits (first 6*T_total bits) are all zeros
67
+ prefix = bs[:6*T_total]
68
+ expected_prefix = "0" * 6*T_total
69
+
70
+ if prefix == expected_prefix:
71
+ if cnt < 0:
72
  continue
73
+ remaining_bits = bs[6*T_total:]
74
+ # Check if remaining bits are divisible by 3
75
+ if len(remaining_bits) % 3 != 0:
76
+ log(f"Warning: Remaining bitstring length {len(remaining_bits)} not divisible by 3")
77
+ continue
78
+ x, y, z = bitstring_to_xyz(remaining_bits)
79
  pts.append([x, y, z])
80
  counts.append(cnt)
81
+
82
  pts = np.array(pts)
83
  counts = np.array(counts)
84
+ log(f"Number of valid counts: {np.sum(counts)}")
85
+ log(f"Number of valid bitstrings: {len(counts)}")
86
+
87
+ if len(counts) == 0:
88
+ log("Warning: No bitstrings matched the zero-prefix filter. This may indicate:")
89
+ log(" - All measurement outcomes had non-zero direction qubits")
90
+ log(" - Bitstring format mismatch")
91
+
92
  return pts, counts
93
 
94
  def estimate_density(pts, counts, bandwidth=0.05, grid_size=64):
 
97
  Returns (grid_x, grid_y, grid_z, grid_density) where
98
  grid_x, etc. are 3D mesh arrays, and grid_density has same shape.
99
  """
100
+ # Handle empty input
101
+ if len(pts) == 0 or len(counts) == 0 or np.sum(counts) == 0:
102
+ print("Warning: No valid samples to estimate density. Returning uniform distribution.")
103
+ mins = [0, 0, 0]
104
+ maxs = [1, 1, 1]
105
+ xs = np.linspace(mins[0], maxs[0], grid_size)
106
+ ys = np.linspace(mins[1], maxs[1], grid_size)
107
+ zs = np.linspace(mins[2], maxs[2], grid_size)
108
+ xx, yy, zz = np.meshgrid(xs, ys, zs, indexing='ij')
109
+ dens = np.ones(xx.shape) * 0.001 # Small uniform density
110
+ return xx, yy, zz, dens
111
+
112
  # Expand points by weights: we can replicate points (if counts small),
113
  # or directly use weights in log-likelihood calculation.
114
+ # sklearn's KernelDensity doesn't support sample weights in .fit,
115
  # but you can approximate by replication or by customizing the KDE.
116
  # Here, for simplicity, replicate (careful of explosion):
117
  pts_rep = np.repeat(pts, counts.astype(int), axis=0)
118
+
119
+ # Handle case where all counts are zero after conversion
120
+ if len(pts_rep) == 0:
121
+ print("Warning: No points after replication. Returning uniform distribution.")
122
+ mins = [0, 0, 0]
123
+ maxs = [1, 1, 1]
124
+ xs = np.linspace(mins[0], maxs[0], grid_size)
125
+ ys = np.linspace(mins[1], maxs[1], grid_size)
126
+ zs = np.linspace(mins[2], maxs[2], grid_size)
127
+ xx, yy, zz = np.meshgrid(xs, ys, zs, indexing='ij')
128
+ dens = np.ones(xx.shape) * 0.001 # Small uniform density
129
+ return xx, yy, zz, dens
130
+
131
  kde = KernelDensity(bandwidth=bandwidth, kernel='gaussian')
132
  kde.fit(pts_rep)
133