@@ -347,7 +347,6 @@ def convert(povm, to_type, basis, cp_penalty=1e-7, ideal_povm=None, flatten_stru
347
347
object from the object passed as input.
348
348
"""
349
349
350
- ##TEST CONVERSION BETWEEN LINBLAD TYPES
351
350
to_types = to_type if isinstance (to_type , (tuple , list )) else (to_type ,) # HACK to support multiple to_type values
352
351
error_msgs = {}
353
352
@@ -421,14 +420,15 @@ def convert(povm, to_type, basis, cp_penalty=1e-7, ideal_povm=None, flatten_stru
421
420
dense_effects .append (dense_effect .reshape ((1 ,len (dense_effect ))))
422
421
423
422
dense_povm = _np .concatenate (dense_effects , axis = 0 )
424
- degrees_of_freedom = (dense_ideal_povm .shape [0 ] - 1 ) * dense_ideal_povm .shape [1 ]
425
-
423
+
426
424
#It is often the case that there are more error generators than physical degrees of freedom in the POVM
427
425
#We define a function which finds linear comb. of errgens that span these degrees of freedom.
428
426
#This has been called "the trivial gauge", and this function is meant to avoid it
429
427
def calc_physical_subspace (dense_ideal_povm , epsilon = 1e-9 ):
430
-
428
+
429
+ degrees_of_freedom = (dense_ideal_povm .shape [0 ] - 1 ) * dense_ideal_povm .shape [1 ]
431
430
errgen = _LindbladErrorgen .from_error_generator (povm .state_space .dim , parameterization = to_type )
431
+
432
432
if degrees_of_freedom > errgen .num_params :
433
433
warnings .warn ("POVM has more degrees of freedom than the available number of parameters, representation in this parameterization is not guaranteed" )
434
434
exp_errgen = _ExpErrorgenOp (errgen )
@@ -437,16 +437,13 @@ def calc_physical_subspace(dense_ideal_povm, epsilon = 1e-9):
437
437
#TODO: Maybe we can use the num of params instead of number of matrix entries, as some of them are linearly dependent.
438
438
#i.e E0 completely determines E1 if those are the only two povm elements (E0 + E1 = Identity)
439
439
num_entries = dense_ideal_povm .shape [0 ]* dense_ideal_povm .shape [1 ]
440
- #assert num_errgens >= povm.num_params, "POVM has too many elements, error generator parameterization is not possible"
441
-
442
- ideal_vec = _np .zeros (num_errgens )
443
440
444
441
#Compute the jacobian with respect to the error generators. This will allow us to see which
445
442
#error generators change the POVM entries
446
443
J = _np .zeros ((num_entries ,num_errgens ))
447
444
448
- for i in range (len ( ideal_vec ) ):
449
- new_vec = ideal_vec . copy ( )
445
+ for i in range (num_errgens ):
446
+ new_vec = _np . zeros ( num_errgens )
450
447
new_vec [i ] = epsilon
451
448
exp_errgen .from_vector (new_vec )
452
449
vectorized_povm = _np .zeros (num_entries )
@@ -482,7 +479,7 @@ def _objfn(v):
482
479
return _np .linalg .norm (dense_povm - dense_ideal_povm @ proc_matrix ) + cp_penalty * sum_of_negative_choi_eigenvalues_gate (proc_matrix , basis )
483
480
484
481
soln = _spo .minimize (_objfn , _np .zeros (len (phys_directions ), 'd' ), method = "Nelder-Mead" , options = {},
485
- tol = 1e-13 ) # , callback=callback)
482
+ tol = 1e-13 )
486
483
if not soln .success and soln .fun > 1e-6 : # not "or" because success is often not set correctly
487
484
raise ValueError ("Failed to find an errorgen such that <ideal|exp(errorgen) = <effect|" )
488
485
errgen_vec = _np .linalg .pinv (phys_directions ) @ soln .x
0 commit comments