@@ -324,25 +324,17 @@ def _mean_infidelity(angles):
324
324
)
325
325
326
326
327
+ @dataclass (frozen = True )
327
328
class _CharacterizePhasedFsimParametersWithXebClosure :
328
329
"""A closure object to wrap `characterize_phased_fsim_parameters_with_xeb` for use in
329
330
multiprocessing."""
330
331
331
- def __init__ (
332
- self ,
333
- parameterized_circuits : List ['cirq.Circuit' ],
334
- cycle_depths : Sequence [int ],
335
- phased_fsim_options : XEBPhasedFSimCharacterizationOptions ,
336
- initial_simplex_step_size : float = 0.1 ,
337
- xatol : float = 1e-3 ,
338
- fatol : float = 1e-3 ,
339
- ):
340
- self .parameterized_circuits = parameterized_circuits
341
- self .cycle_depths = cycle_depths
342
- self .phased_fsim_options = phased_fsim_options
343
- self .initial_simplex_step_size = initial_simplex_step_size
344
- self .xatol = xatol
345
- self .fatol = fatol
332
+ parameterized_circuits : List ['cirq.Circuit' ]
333
+ cycle_depths : Sequence [int ]
334
+ phased_fsim_options : XEBPhasedFSimCharacterizationOptions
335
+ initial_simplex_step_size : float = 0.1
336
+ xatol : float = 1e-3
337
+ fatol : float = 1e-3
346
338
347
339
def __call__ (self , sampled_df ) -> XEBCharacterizationResult :
348
340
return characterize_phased_fsim_parameters_with_xeb (
@@ -419,13 +411,36 @@ def characterize_phased_fsim_parameters_with_xeb_by_pair(
419
411
)
420
412
421
413
422
- def exponential_decay (cycle_depths : np .ndarray , A : float , layer_fid : float ) -> np .ndarray :
423
- """An exponential decay for fitting."""
424
- return A * layer_fid ** cycle_depths
414
+ def exponential_decay (cycle_depths : np .ndarray , a : float , layer_fid : float ) -> np .ndarray :
415
+ """An exponential decay for fitting.
416
+
417
+ This computes `a * layer_fid**cycle_depths`
418
+
419
+ Args:
420
+ cycle_depths: The various depths at which fidelity was estimated. This is the independent
421
+ variable in the exponential function.
422
+ a: A scale parameter in the exponential function.
423
+ layer_fid: The base of the exponent in the exponential function.
424
+ """
425
+ return a * layer_fid ** cycle_depths
425
426
426
427
427
428
def _fit_exponential_decay (cycle_depths : np .ndarray , fidelities : np .ndarray ) -> Tuple [float , float ]:
428
- """Fit an exponential model fidelities = A * layer_fid**x using nonlinear least squares."""
429
+ """Fit an exponential model fidelity = a * layer_fid**x using nonlinear least squares.
430
+
431
+ This uses `exponential_decay` as the function to fit with parameters `a` and `layer_fid`.
432
+
433
+ Args:
434
+ cycle_depths: The various depths at which fidelity was estimated. Each element is `x`
435
+ in the fit expression.
436
+ fidelities: The estimated fidelities for each cycle depth. Each element is `fidelity`
437
+ in the fit expression.
438
+
439
+ Returns:
440
+ a: The first fit parameter that scales the exponential function, perhaps accounting for
441
+ state prep and measurement (SPAM) error.
442
+ layer_fid: The second fit parameters which serves as the base of the exponential.
443
+ """
429
444
cycle_depths = np .asarray (cycle_depths )
430
445
fidelities = np .asarray (fidelities )
431
446
@@ -435,12 +450,12 @@ def _fit_exponential_decay(cycle_depths: np.ndarray, fidelities: np.ndarray) ->
435
450
log_fidelities = np .log (fidelities [positives ])
436
451
slope , intercept , _ , _ , _ = scipy .stats .linregress (cycle_depths_pos , log_fidelities )
437
452
layer_fid_0 = np .clip (np .exp (slope ), 0 , 1 )
438
- A_0 = np .clip (np .exp (intercept ), 0 , 1 )
453
+ a_0 = np .clip (np .exp (intercept ), 0 , 1 )
439
454
440
- (A , layer_fid ), _ = scipy .optimize .curve_fit (
441
- exponential_decay , cycle_depths , fidelities , p0 = (A_0 , layer_fid_0 ), bounds = ((0 , 0 ), (1 , 1 ))
455
+ (a , layer_fid ), _ = scipy .optimize .curve_fit (
456
+ exponential_decay , cycle_depths , fidelities , p0 = (a_0 , layer_fid_0 ), bounds = ((0 , 0 ), (1 , 1 ))
442
457
)
443
- return A , layer_fid
458
+ return a , layer_fid
444
459
445
460
446
461
def _one_unique (df , name , default ):
@@ -463,16 +478,16 @@ def fit_exponential_decays(fidelities_df: pd.DataFrame) -> pd.DataFrame:
463
478
464
479
Returns:
465
480
A new, aggregated dataframe with index given by (pair, layer_i, pair_i); columns
466
- for the fit parameters "A " and "layer_fid"; and nested "cycles_depths" and "fidelities"
481
+ for the fit parameters "a " and "layer_fid"; and nested "cycles_depths" and "fidelities"
467
482
lists (now grouped by pair).
468
483
"""
469
484
records = []
470
485
for pair in fidelities_df ['pair' ].unique ():
471
486
f1 = fidelities_df [fidelities_df ['pair' ] == pair ]
472
- A , layer_fid = _fit_exponential_decay (f1 ['cycle_depth' ], f1 ['fidelity' ])
487
+ a , layer_fid = _fit_exponential_decay (f1 ['cycle_depth' ], f1 ['fidelity' ])
473
488
record = {
474
489
'pair' : pair ,
475
- 'A ' : A ,
490
+ 'a ' : a ,
476
491
'layer_fid' : layer_fid ,
477
492
'cycle_depths' : f1 ['cycle_depth' ].values ,
478
493
'fidelities' : f1 ['fidelity' ].values ,
@@ -506,8 +521,9 @@ def before_and_after_characterization(
506
521
joined_df ['characterized_angles' ] = [
507
522
characterization_result .final_params [pair ] for pair , _ , _ in joined_df .index
508
523
]
509
- angle_names = list (list (characterization_result .final_params .values ())[0 ].keys ())
510
- for angle_name in angle_names :
524
+ # Take any `final_params` (for any pair). We just need the angle names.
525
+ fp , * _ = characterization_result .final_params .values ()
526
+ for angle_name in fp .keys ():
511
527
joined_df [angle_name ] = [
512
528
characterization_result .final_params [pair ][angle_name ] for pair , _ , _ in joined_df .index
513
529
]
0 commit comments