Skip to content

Commit 482e86e

Browse files
implemented Stefan's PR requests and cleaned up init.py s a little
1 parent 18b9294 commit 482e86e

File tree

3 files changed

+15
-19
lines changed

3 files changed

+15
-19
lines changed

pygsti/modelmembers/povms/__init__.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,6 @@ def convert(povm, to_type, basis, cp_penalty=1e-7, ideal_povm=None, flatten_stru
347347
object from the object passed as input.
348348
"""
349349

350-
##TEST CONVERSION BETWEEN LINBLAD TYPES
351350
to_types = to_type if isinstance(to_type, (tuple, list)) else (to_type,) # HACK to support multiple to_type values
352351
error_msgs = {}
353352

@@ -421,14 +420,15 @@ def convert(povm, to_type, basis, cp_penalty=1e-7, ideal_povm=None, flatten_stru
421420
dense_effects.append(dense_effect.reshape((1,len(dense_effect))))
422421

423422
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+
426424
#It is often the case that there are more error generators than physical degrees of freedom in the POVM
427425
#We define a function which finds linear comb. of errgens that span these degrees of freedom.
428426
#This has been called "the trivial gauge", and this function is meant to avoid it
429427
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]
431430
errgen = _LindbladErrorgen.from_error_generator(povm.state_space.dim, parameterization=to_type)
431+
432432
if degrees_of_freedom > errgen.num_params:
433433
warnings.warn("POVM has more degrees of freedom than the available number of parameters, representation in this parameterization is not guaranteed")
434434
exp_errgen = _ExpErrorgenOp(errgen)
@@ -437,16 +437,13 @@ def calc_physical_subspace(dense_ideal_povm, epsilon = 1e-9):
437437
#TODO: Maybe we can use the num of params instead of number of matrix entries, as some of them are linearly dependent.
438438
#i.e E0 completely determines E1 if those are the only two povm elements (E0 + E1 = Identity)
439439
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)
443440

444441
#Compute the jacobian with respect to the error generators. This will allow us to see which
445442
#error generators change the POVM entries
446443
J = _np.zeros((num_entries,num_errgens))
447444

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)
450447
new_vec[i] = epsilon
451448
exp_errgen.from_vector(new_vec)
452449
vectorized_povm = _np.zeros(num_entries)
@@ -482,7 +479,7 @@ def _objfn(v):
482479
return _np.linalg.norm(dense_povm - dense_ideal_povm @ proc_matrix) + cp_penalty * sum_of_negative_choi_eigenvalues_gate(proc_matrix, basis)
483480

484481
soln = _spo.minimize(_objfn, _np.zeros(len(phys_directions), 'd'), method="Nelder-Mead", options={},
485-
tol=1e-13) # , callback=callback)
482+
tol=1e-13)
486483
if not soln.success and soln.fun > 1e-6: # not "or" because success is often not set correctly
487484
raise ValueError("Failed to find an errorgen such that <ideal|exp(errorgen) = <effect|")
488485
errgen_vec = _np.linalg.pinv(phys_directions) @ soln.x

pygsti/modelmembers/states/__init__.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -266,22 +266,22 @@ def convert(state, to_type, basis, cp_penalty=1e-7, ideal_state=None, flatten_st
266266
dense_state = state.to_dense()
267267
num_qubits = st.state_space.num_qubits
268268

269-
errgen = _LindbladErrorgen.from_error_generator(2**(2*num_qubits), parameterization=to_type)
270-
num_errgens = errgen.num_params
269+
271270

272271
#GLND for states suffers from "trivial gauge" freedom. This function identifies
273272
#the physical directions to avoid this gauge.
274273
def calc_physical_subspace(ideal_prep, epsilon = 1e-9):
274+
errgen = _LindbladErrorgen.from_error_generator(2**(2*num_qubits), parameterization=to_type)
275+
num_errgens = errgen.num_params
275276

276277
exp_errgen = _ExpErrorgenOp(errgen)
277-
ideal_vec = _np.zeros(num_errgens)
278278

279279
#Compute the jacobian with respect to the error generators. This will allow us to see which
280280
#error generators change the POVM entries
281281
J = _np.zeros((state.num_params, num_errgens))
282282

283-
for i in range(len(ideal_vec)):
284-
new_vec = ideal_vec.copy()
283+
for i in range(num_errgens):
284+
new_vec = _np.zeros(num_errgens)
285285
new_vec[i] = epsilon
286286
exp_errgen.from_vector(new_vec)
287287
J[:,i] = (exp_errgen.to_dense() @ ideal_prep - ideal_prep)[1:]/epsilon
@@ -302,8 +302,8 @@ def _objfn(v):
302302
return _np.linalg.norm(proc_matrix @ dense_st - dense_state) + cp_penalty * sum_of_negative_choi_eigenvalues_gate(proc_matrix, basis)
303303

304304
soln = _spo.minimize(_objfn, _np.zeros(len(phys_directions), 'd'), method="Nelder-Mead", options={},
305-
tol=1e-13) # , callback=callback)
306-
#print("DEBUG: opt done: ",soln.success, soln.fun, soln.x) # REMOVE
305+
tol=1e-13)
306+
307307
if not soln.success and soln.fun > 1e-6: # not "or" because success is often not set correctly
308308
raise ValueError("Failed to find an errorgen such that exp(errorgen)|ideal> = |state>")
309309

@@ -322,7 +322,6 @@ def _objfn(v):
322322
return create_from_dmvec(vec, to_type, basis, state.evotype, state.state_space)
323323

324324
except ValueError as e:
325-
#_warnings.warn('Failed to convert state to type %s with error: %s' % (to_type, e))
326325
error_msgs[to_type] = str(e) # try next to_type
327326

328327
raise ValueError("Could not convert state to to type(s): %s\n%s" % (str(to_types), str(error_msgs)))

test/unit/objects/test_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ def test_bulk_fill_hprobs_with_high_smallness_threshold(self):
741741
def test_iter_hprobs_by_rectangle(self):
742742
self.skipTest("TODO should probably warn user?")
743743

744-
class LinbladModelTester(GLNDModelBase, StandardMethodBase, BaseCase):
744+
class LindbladModelTester(GLNDModelBase, StandardMethodBase, BaseCase):
745745
pass
746746
class FullMapSimMethodTester(FullModelBase, SimMethodBase, BaseCase):
747747
def setUp(self):

0 commit comments

Comments
 (0)