jezerjojo commited on
Commit
5d45402
·
1 Parent(s): 067e2f3

Added optional flag qubit functionality for hw runs; limited output resolution to be at most twice the input resolution

Browse files
qlbm/qlbm_sample_app.py CHANGED
@@ -251,7 +251,7 @@ def stream(qc,pos_qr,dir_qr,n):
251
  qc.cp( np.pi / (2 ** m), forw_ctrl, pos_qr[i][m])
252
  qc.cp(-np.pi / (2 ** m), backw_ctrl, pos_qr[i][m])
253
 
254
- def get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution=32,measure=True):
255
 
256
  ux_str,uy_str,uz_str=None,None,None
257
  if type(ux)==str:
@@ -278,16 +278,21 @@ def get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution=32,measure
278
  pos_qr=[QuantumRegister(n) for _ in range(dim)]
279
  pos_cr=[ClassicalRegister(n) for _ in range(dim)]
280
  dir_qr=QuantumRegister(2*dim)
281
- dir_cr=[ClassicalRegister(2*dim) for _ in range(T_total)]
 
282
 
283
- qc=QuantumCircuit(*pos_qr,dir_qr,*pos_cr,*dir_cr)
 
 
 
284
 
285
  qc.compose(init_state_prep_circ,[qubit for qr in pos_qr for qubit in list(qr)], inplace=True)
286
 
287
  uniform_bool=False
288
 
289
- if 'x' not in ux_str+uy_str+uz_str and 'y' not in ux_str+uy_str+uz_str and 'z' not in ux_str+uy_str+uz_str:
290
- uniform_bool=True
 
291
 
292
  if uniform_bool:
293
  for i in range(dim):
@@ -296,6 +301,9 @@ def get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution=32,measure
296
  for T in list(range(T_total))[::-1]:
297
 
298
  prep(qc,pos_qr,dir_qr)
 
 
 
299
  if not uniform_bool:
300
  for i in range(dim):
301
  qc.compose(QFT(n, inverse=False, do_swaps=False), pos_qr[i], inplace=True)
@@ -303,9 +311,15 @@ def get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution=32,measure
303
  if not uniform_bool:
304
  for i in range(dim):
305
  qc.compose(QFT(n, inverse=True, do_swaps=False), pos_qr[i], inplace=True)
 
 
 
306
  unprep(qc,pos_qr,dir_qr)
307
 
308
- qc.measure(dir_qr,dir_cr[T])
 
 
 
309
 
310
  if uniform_bool:
311
  for i in range(dim):
@@ -481,6 +495,7 @@ def run_sampling_hw_ibm(
481
  vel_resolution=32,
482
  output_resolution=40,
483
  logger=None,
 
484
  ):
485
  """
486
  Run QLBM simulation on IBM quantum hardware.
@@ -525,7 +540,7 @@ def run_sampling_hw_ibm(
525
  # if type(init_state_prep_circ)==str:
526
  # init_state_prep_circ=get_named_init_state_circuit(n,init_state_prep_circ)
527
 
528
- qc_list=get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution)
529
 
530
  pm_optimization_level = 3
531
 
@@ -545,7 +560,7 @@ def run_sampling_hw_ibm(
545
  # Create Sampler primitive bound to the backend
546
  sampler = Sampler(mode=backend)
547
 
548
- # Submit job: pass a list of PUBs (we send one PUB [qc_compiled])
549
  job = sampler.run(qc_compiled_list, shots=shots)
550
  log("Job submitted; waiting for result...")
551
 
@@ -566,7 +581,7 @@ def run_sampling_hw_ibm(
566
  joined_counts = None
567
 
568
  # Suppress verbose logging by passing None as logger
569
- pts, counts = load_samples(joined_counts, T_total, logger=None)
570
  output+=[estimate_density(pts, counts, bandwidth=0.05, grid_size=output_resolution)]
571
 
572
  log(f"Processing complete: {len(output)} timestep(s)")
@@ -936,7 +951,7 @@ def show_initial_distribution(
936
 
937
  if __name__=="__main__":
938
 
939
- n=4
940
 
941
  # # Step 1: Create the initial state circuit ONCE with all parameters
942
  # init_state_prep_circ = get_named_init_state_circuit(
@@ -951,35 +966,55 @@ if __name__=="__main__":
951
  # # gauss_sigma=0.2,
952
  # )
953
 
954
- # Alternative: Run on local simulator
955
- output, fig = run_sampling_sim(
956
- n=n,
957
- ux="sin(-2*pi*z)",
958
- uy="1",
959
- uz="sin(2*pi*x)",
960
- init_state_prep_circ="multi_dirac_delta",
961
- T_list=[1,3,5,7,9],
962
- vel_resolution=16
963
- )
964
- print(output)
965
- fig.show(renderer="browser")
966
 
967
  # Step 2: (Optional) Preview the initial distribution
968
  # show_initial_distribution(n=n, init_state_name="sin", sine_k_x=1, sine_k_y=1, sine_k_z=1)
969
 
970
  # Step 3: Run simulation - pass the pre-built circuit
971
- # job, get_job_result = run_sampling_hw_ibm(
972
- # n=n,
973
- # ux=lambda x,y,z: 1,
974
- # uy=lambda x,y,z: 1,
975
- # uz=lambda x,y,z: 1,
976
- # init_state_prep_circ=init_state_prep_circ, # Pass the circuit directly
977
- # T_list=[1],
978
- # shots=2**19,
979
- # vel_resolution=2,
 
 
 
 
 
 
 
 
 
980
  # )
 
 
 
 
 
 
 
 
 
 
 
 
981
 
982
- # output = get_job_result(job)
983
  # for xx, yy, zz, dens in output:
984
  # plot_density_isosurface(xx, yy, zz, dens)
985
 
 
251
  qc.cp( np.pi / (2 ** m), forw_ctrl, pos_qr[i][m])
252
  qc.cp(-np.pi / (2 ** m), backw_ctrl, pos_qr[i][m])
253
 
254
+ def get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution=32,measure=True,flag_qubits=False):
255
 
256
  ux_str,uy_str,uz_str=None,None,None
257
  if type(ux)==str:
 
278
  pos_qr=[QuantumRegister(n) for _ in range(dim)]
279
  pos_cr=[ClassicalRegister(n) for _ in range(dim)]
280
  dir_qr=QuantumRegister(2*dim)
281
+ dir_qr_flag=QuantumRegister(2*dim)
282
+ dir_cr=[ClassicalRegister((4 if flag_qubits else 2)*dim) for _ in range(T_total)]
283
 
284
+ if flag_qubits:
285
+ qc=QuantumCircuit(*pos_qr,dir_qr,dir_qr_flag,*pos_cr,*dir_cr)
286
+ else:
287
+ qc=QuantumCircuit(*pos_qr,dir_qr,*pos_cr,*dir_cr)
288
 
289
  qc.compose(init_state_prep_circ,[qubit for qr in pos_qr for qubit in list(qr)], inplace=True)
290
 
291
  uniform_bool=False
292
 
293
+ if ux_str is not None:
294
+ if 'x' not in ux_str+uy_str+uz_str and 'y' not in ux_str+uy_str+uz_str and 'z' not in ux_str+uy_str+uz_str:
295
+ uniform_bool=True
296
 
297
  if uniform_bool:
298
  for i in range(dim):
 
301
  for T in list(range(T_total))[::-1]:
302
 
303
  prep(qc,pos_qr,dir_qr)
304
+ if flag_qubits:
305
+ for q1,q2 in zip(dir_qr,dir_qr_flag):
306
+ qc.cx(q1,q2)
307
  if not uniform_bool:
308
  for i in range(dim):
309
  qc.compose(QFT(n, inverse=False, do_swaps=False), pos_qr[i], inplace=True)
 
311
  if not uniform_bool:
312
  for i in range(dim):
313
  qc.compose(QFT(n, inverse=True, do_swaps=False), pos_qr[i], inplace=True)
314
+ if flag_qubits:
315
+ for q1,q2 in zip(dir_qr,dir_qr_flag):
316
+ qc.cx(q1,q2)
317
  unprep(qc,pos_qr,dir_qr)
318
 
319
+ if flag_qubits:
320
+ qc.measure(list(dir_qr)+list(dir_qr_flag),dir_cr[T])
321
+ else:
322
+ qc.measure(dir_qr,dir_cr[T])
323
 
324
  if uniform_bool:
325
  for i in range(dim):
 
495
  vel_resolution=32,
496
  output_resolution=40,
497
  logger=None,
498
+ flag_qubits=True
499
  ):
500
  """
501
  Run QLBM simulation on IBM quantum hardware.
 
540
  # if type(init_state_prep_circ)==str:
541
  # init_state_prep_circ=get_named_init_state_circuit(n,init_state_prep_circ)
542
 
543
+ qc_list=get_circuit(n,ux,uy,uz,init_state_prep_circ,T_list,vel_resolution,flag_qubits=flag_qubits)
544
 
545
  pm_optimization_level = 3
546
 
 
560
  # Create Sampler primitive bound to the backend
561
  sampler = Sampler(mode=backend)
562
 
563
+ # # Submit job: pass a list of PUBs (we send one PUB [qc_compiled])
564
  job = sampler.run(qc_compiled_list, shots=shots)
565
  log("Job submitted; waiting for result...")
566
 
 
581
  joined_counts = None
582
 
583
  # Suppress verbose logging by passing None as logger
584
+ pts, counts = load_samples(joined_counts, T_total, logger=None, flag_qubits=flag_qubits)
585
  output+=[estimate_density(pts, counts, bandwidth=0.05, grid_size=output_resolution)]
586
 
587
  log(f"Processing complete: {len(output)} timestep(s)")
 
951
 
952
  if __name__=="__main__":
953
 
954
+ n=3
955
 
956
  # # Step 1: Create the initial state circuit ONCE with all parameters
957
  # init_state_prep_circ = get_named_init_state_circuit(
 
966
  # # gauss_sigma=0.2,
967
  # )
968
 
969
+ # # Alternative: Run on local simulator
970
+ # output, fig = run_sampling_sim(
971
+ # n=n,
972
+ # ux="sin(-2*pi*z)",
973
+ # uy="1",
974
+ # uz="sin(2*pi*x)",
975
+ # init_state_prep_circ="multi_dirac_delta",
976
+ # T_list=[1,3,5,7,9],
977
+ # vel_resolution=16
978
+ # )
979
+ # print(output)
980
+ # fig.show(renderer="browser")
981
 
982
  # Step 2: (Optional) Preview the initial distribution
983
  # show_initial_distribution(n=n, init_state_name="sin", sine_k_x=1, sine_k_y=1, sine_k_z=1)
984
 
985
  # Step 3: Run simulation - pass the pre-built circuit
986
+ job, get_job_result = run_sampling_hw_ibm(
987
+ n=n,
988
+ ux="1",
989
+ uy="1",
990
+ uz="1",
991
+ init_state_prep_circ="multi_dirac_delta", # Pass the circuit directly
992
+ T_list=[1,2],
993
+ shots=2**19,
994
+ vel_resolution=2,
995
+ output_resolution=8,
996
+ flag_qubits=True
997
+ )
998
+
999
+ # from qiskit_ibm_runtime import QiskitRuntimeService
1000
+
1001
+ # service = QiskitRuntimeService(
1002
+ # channel='ibm_quantum_platform', token="UMeZUDI5D7fjPJHD5x3MJFwURg4PrGzBnTm142ka9-Hj",
1003
+ # instance='crn:v1:bluemix:public:quantum-computing:us-east:a/15157e4350c04a9dab51b8b8a4a93c86:e29afd91-64bf-4a82-8dbf-731e6c213595::'
1004
  # )
1005
+ # job = service.job('d4spkn3her1c73bdjelg')
1006
+ # job_result = job.result()
1007
+
1008
+ # To get counts for a particular pub result, use
1009
+ #
1010
+ # pub_result = job_result[<idx>].data.<classical register>.get_counts()
1011
+ #
1012
+ # where <idx> is the index of the pub and <classical register> is the name of the classical register.
1013
+ # You can use circuit.cregs to find the name of the classical registers.
1014
+
1015
+ output,fig = get_job_result(job)
1016
+ fig.show(renderer="browser")
1017
 
 
1018
  # for xx, yy, zz, dens in output:
1019
  # plot_density_isosurface(xx, yy, zz, dens)
1020
 
qlbm/visualize_counts.py CHANGED
@@ -22,7 +22,7 @@ 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, logger=None):
26
  """
27
  Load samples from measurement counts dictionary.
28
 
@@ -50,6 +50,10 @@ def load_samples(d, T_total, logger=None):
50
 
51
  pts = []
52
  counts = []
 
 
 
 
53
 
54
  if d is None or len(d) == 0:
55
  log("Warning: Empty counts dictionary")
@@ -60,17 +64,17 @@ def load_samples(d, T_total, logger=None):
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")
@@ -146,6 +150,8 @@ def estimate_density(pts, counts, bandwidth=0.05, grid_size=64):
146
  dens = np.exp(logdens)
147
  dens = dens.reshape(xx.shape)
148
 
 
 
149
  print("Mins:", mins)
150
  print("Maxs:", maxs)
151
  print("dens:", dens)
@@ -220,7 +226,7 @@ def plot_density_isosurface_slider(outputs, T_list=None):
220
  isomin=global_min,
221
  isomax=global_max,
222
  opacity=0.4,
223
- surface_count=5,
224
  caps=dict(x_show=False, y_show=False, z_show=False),
225
  colorscale='Blues',
226
  colorbar=dict(title="Density"),
@@ -257,7 +263,7 @@ def plot_density_isosurface_slider(outputs, T_list=None):
257
  ),
258
  sliders=sliders
259
  )
260
-
261
  # fig.show(renderer="browser")
262
  return fig
263
 
 
22
  maxv = (1 << t)
23
  return ix / maxv, iy / maxv, iz / maxv
24
 
25
+ def load_samples(d, T_total, logger=None, flag_qubits=False):
26
  """
27
  Load samples from measurement counts dictionary.
28
 
 
50
 
51
  pts = []
52
  counts = []
53
+
54
+ pref_length=6*T_total
55
+ if flag_qubits:
56
+ pref_length=12*T_total
57
 
58
  if d is None or len(d) == 0:
59
  log("Warning: Empty counts dictionary")
 
64
  log(f"Sample bitstrings (first 3): {sample_keys}")
65
  if sample_keys:
66
  log(f"Bitstring length: {len(sample_keys[0])}")
67
+ log(f"Expected prefix length: {pref_length}")
68
 
69
  for bs, cnt in d.items():
70
  # Check if the direction qubits (first 6*T_total bits) are all zeros
71
+ prefix = bs[:pref_length]
72
+ expected_prefix = "0" * pref_length
73
 
74
  if prefix == expected_prefix:
75
  if cnt < 0:
76
  continue
77
+ remaining_bits = bs[pref_length:]
78
  # Check if remaining bits are divisible by 3
79
  if len(remaining_bits) % 3 != 0:
80
  log(f"Warning: Remaining bitstring length {len(remaining_bits)} not divisible by 3")
 
150
  dens = np.exp(logdens)
151
  dens = dens.reshape(xx.shape)
152
 
153
+ dens = (grid_size**3)*dens/np.sum(dens.flatten())
154
+
155
  print("Mins:", mins)
156
  print("Maxs:", maxs)
157
  print("dens:", dens)
 
226
  isomin=global_min,
227
  isomax=global_max,
228
  opacity=0.4,
229
+ surface_count=10,
230
  caps=dict(x_show=False, y_show=False, z_show=False),
231
  colorscale='Blues',
232
  colorbar=dict(title="Density"),
 
263
  ),
264
  sliders=sliders
265
  )
266
+
267
  # fig.show(renderer="browser")
268
  return fig
269
 
qlbm_embedded.py CHANGED
@@ -1189,7 +1189,7 @@ def run_simulation():
1189
  # shots=2**14, # Reduced shots for responsiveness/quota
1190
  shots=2**18,
1191
  vel_resolution=min(params['grid_size'], 32),
1192
- output_resolution=40,
1193
  logger=log_to_console
1194
  )
1195
 
 
1189
  # shots=2**14, # Reduced shots for responsiveness/quota
1190
  shots=2**18,
1191
  vel_resolution=min(params['grid_size'], 32),
1192
+ output_resolution=min(2*params['grid_size'], 40),
1193
  logger=log_to_console
1194
  )
1195