Skip to content

Commit a3ab2a6

Browse files
authored
Merge pull request #605: Add type annotation for on_space parameter
Add type annotation for on_space parameter. Also add an optional enum, but keep use of string literals throughout current code.
2 parents b599d9e + 6e21d4d commit a3ab2a6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+295
-262
lines changed

pygsti/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
# http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
88
#***************************************************************************************************
99
""" A Python implementation of LinearOperator Set Tomography """
10+
from .pgtypes import (
11+
SpaceT
12+
)
1013

1114
from . import baseobjs
1215
from . import algorithms as alg
@@ -19,6 +22,7 @@
1922
from . import protocols
2023
from . import report as rpt
2124
from . import serialization
25+
from . import enums
2226

2327
# Import the most important/useful routines of each module/sub-package
2428
# into the package namespace
@@ -30,6 +34,7 @@
3034
from pygsti.tools.gatetools import * # *_qubit_gate fns
3135
from .drivers import *
3236
from .tools import *
37+
3338
# NUMPY BUG FIX (imported from tools)
3439
from pygsti.baseobjs._compatibility import _numpy14einsumfix
3540

pygsti/algorithms/gaugeopt.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,8 @@ def _jacobian_fn(gauge_group_el):
517517
# d(op_term) = S_inv * (-dS * S_inv * G * S + G * dS) = S_inv * (-dS * G' + G * dS)
518518
# Note: (S_inv * G * S) is G' (transformed G)
519519
wt = item_weights.get(lbl, opWeight)
520-
left = -1 * _np.dot(dS, mdl_post.operations[lbl].to_dense(on_space='minimal')) # shape (n,d1,d2)
521-
right = _np.swapaxes(_np.dot(G.to_dense(on_space='minimal'), dS), 0, 1) # shape (d1,n,d2) -> (n,d1,d2)
520+
left = -1 * _np.dot(dS, mdl_post.operations[lbl].to_dense('minimal')) # shape (n,d1,d2)
521+
right = _np.swapaxes(_np.dot(G.to_dense('minimal'), dS), 0, 1) # shape (d1,n,d2) -> (n,d1,d2)
522522
result = _np.swapaxes(_np.dot(S_inv, left + right), 1, 2) # shape (d1, d2, n)
523523
result = result.reshape((d**2, n)) # must copy b/c non-contiguous
524524
my_jacMx[start:start + d**2] = wt * result
@@ -530,8 +530,8 @@ def _jacobian_fn(gauge_group_el):
530530
wt = item_weights.get(ilbl, opWeight)
531531
for lbl, G in Inst.items():
532532
# same calculation as for operation terms
533-
left = -1 * _np.dot(dS, mdl_post.instruments[ilbl][lbl].to_dense(on_space='minimal')) # (n,d1,d2)
534-
right = _np.swapaxes(_np.dot(G.to_dense(on_space='minimal'), dS), 0, 1) # (d1,n,d2) -> (n,d1,d2)
533+
left = -1 * _np.dot(dS, mdl_post.instruments[ilbl][lbl].to_dense('minimal')) # (n,d1,d2)
534+
right = _np.swapaxes(_np.dot(G.to_dense('minimal'), dS), 0, 1) # (d1,n,d2) -> (n,d1,d2)
535535
result = _np.swapaxes(_np.dot(S_inv, left + right), 1, 2) # shape (d1, d2, n)
536536
result = result.reshape((d**2, n)) # must copy b/c non-contiguous
537537
my_jacMx[start:start + d**2] = wt * result
@@ -544,7 +544,7 @@ def _jacobian_fn(gauge_group_el):
544544
# Note: (S_inv * rho) is transformed rho
545545
wt = item_weights.get(lbl, spamWeight)
546546
Sinv_dS = _np.dot(S_inv, dS) # shape (d1,n,d2)
547-
result = -1 * _np.dot(Sinv_dS, rho.to_dense(on_space='minimal')) # shape (d,n)
547+
result = -1 * _np.dot(Sinv_dS, rho.to_dense('minimal')) # shape (d,n)
548548
my_jacMx[start:start + d] = wt * result
549549
start += d
550550

@@ -554,7 +554,7 @@ def _jacobian_fn(gauge_group_el):
554554
for lbl, E in povm.items():
555555
# d(ET_term) = E.T * dS
556556
wt = item_weights.get(povmlbl + "_" + lbl, spamWeight)
557-
result = _np.dot(E.to_dense(on_space='minimal')[None, :], dS).T # shape (1,n,d2).T => (d2,n,1)
557+
result = _np.dot(E.to_dense('minimal')[None, :], dS).T # shape (1,n,d2).T => (d2,n,1)
558558
my_jacMx[start:start + d] = wt * result.squeeze(2) # (d2,n)
559559
start += d
560560

@@ -851,7 +851,7 @@ def _spam_penalty_jac_fill(spam_penalty_vec_grad_to_fill, mdl_pre, mdl_post,
851851

852852
#get sgn(denMx) == d(|denMx|_Tr)/d(denMx) in std basis
853853
# dmDim = denMx.shape[0]
854-
denMx = _tools.vec_to_stdmx(prepvec.to_dense(on_space='minimal')[:, None], op_basis)
854+
denMx = _tools.vec_to_stdmx(prepvec.to_dense('minimal')[:, None], op_basis)
855855
assert(_np.linalg.norm(denMx - denMx.T.conjugate()) < 1e-4), \
856856
"denMx should be Hermitian!"
857857

@@ -865,7 +865,7 @@ def _spam_penalty_jac_fill(spam_penalty_vec_grad_to_fill, mdl_pre, mdl_post,
865865
# get d(prepvec')/dp = d(S_inv * prepvec)/dp in op_basis [shape == (n,dim)]
866866
# = (-S_inv*dS*S_inv) * prepvec = -S_inv*dS * prepvec'
867867
Sinv_dS = _np.dot(S_inv, dS) # shape (d1,n,d2)
868-
dVdp = -1 * _np.dot(Sinv_dS, prepvec.to_dense(on_space='minimal')[:, None]).squeeze(2) # shape (d,n,1) => (d,n)
868+
dVdp = -1 * _np.dot(Sinv_dS, prepvec.to_dense('minimal')[:, None]).squeeze(2) # shape (d,n,1) => (d,n)
869869
assert(dVdp.shape == (d, n))
870870

871871
# denMx = sum( spamvec[i] * Bmx[i] )
@@ -890,7 +890,7 @@ def _spam_penalty_jac_fill(spam_penalty_vec_grad_to_fill, mdl_pre, mdl_post,
890890
for lbl, effectvec in povm.items():
891891

892892
#get sgn(EMx) == d(|EMx|_Tr)/d(EMx) in std basis
893-
EMx = _tools.vec_to_stdmx(effectvec.to_dense(on_space='minimal')[:, None], op_basis)
893+
EMx = _tools.vec_to_stdmx(effectvec.to_dense('minimal')[:, None], op_basis)
894894
# dmDim = EMx.shape[0]
895895
assert(_np.linalg.norm(EMx - EMx.T.conjugate()) < 1e-4), \
896896
"denMx should be Hermitian!"
@@ -905,7 +905,7 @@ def _spam_penalty_jac_fill(spam_penalty_vec_grad_to_fill, mdl_pre, mdl_post,
905905
# get d(effectvec')/dp = [d(effectvec.T * S)/dp].T in op_basis [shape == (n,dim)]
906906
# = [effectvec.T * dS].T
907907
# OR = dS.T * effectvec
908-
pre_effectvec = mdl_pre.povms[povmlbl][lbl].to_dense(on_space='minimal')[:, None]
908+
pre_effectvec = mdl_pre.povms[povmlbl][lbl].to_dense('minimal')[:, None]
909909
dVdp = _np.dot(pre_effectvec.T, dS).squeeze(0).T
910910
# shape = (1,d) * (n, d1,d2) = (1,n,d2) => (n,d2) => (d2,n)
911911
assert(dVdp.shape == (d, n))

pygsti/circuits/cloudcircuitconstruction.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@
2727
from pygsti.circuits.circuitstructure import GermFiducialPairPlaquette as _GermFiducialPairPlaquette, \
2828
PlaquetteGridCircuitStructure as _PlaquetteGridCircuitStructure
2929

30-
from pygsti.tools import basistools as _bt
31-
from pygsti.tools import internalgates as _itgs
3230
from pygsti.tools import listtools as _lt
3331
from pygsti.tools import mpitools as _mpit
34-
from pygsti.tools import optools as _ot
3532
from pygsti.tools import slicetools as _slct
3633
from pygsti.tools.legacytools import deprecate as _deprecated_fn
3734

pygsti/enums/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""
2+
These enums are intended to make it simplier to call functions with fixed strings expected as input.
3+
"""
4+
5+
6+
from .convertspaceenum import SpaceConversionType

pygsti/enums/convertspaceenum.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from enum import Enum
2+
3+
4+
class SpaceConversionType(Enum):
5+
Minimal = 'minimal'
6+
Hilbert = 'Hilbert'
7+
HilbertSchmidt = 'HilbertSchmidt'

pygsti/evotypes/chp/opreps.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from .. import basereps as _basereps
1818
from pygsti.baseobjs.statespace import StateSpace as _StateSpace
1919
from ...tools import internalgates as _itgs
20+
from pygsti import SpaceT
2021

2122

2223
class OpRep(_basereps.OpRep):
@@ -49,7 +50,7 @@ def adjoint_acton_random(self, state, rand_state):
4950
def _chp_ops(self, seed_or_state=None):
5051
return self.base_chp_ops
5152

52-
def to_dense(self, on_space):
53+
def to_dense(self, on_space: SpaceT):
5354
try:
5455
str_ops = str(self._chp_ops())
5556
except Exception:

pygsti/evotypes/densitymx_slow/effectreps.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# import functools as _functools
1616
from pygsti.baseobjs.statespace import StateSpace as _StateSpace
1717
from ...tools import matrixtools as _mt
18-
18+
from pygsti import SpaceT
1919

2020
class EffectRep:
2121
"""Any representation of an "effect" in the sense of a POVM."""
@@ -44,7 +44,7 @@ def probability(self, state):
4444
# can assume state is a StateRep and self.state_rep is
4545
return _np.dot(self.state_rep.data, state.data) # not vdot b/c *real* data
4646

47-
def to_dense(self, on_space):
47+
def to_dense(self, on_space: SpaceT):
4848
return self.state_rep.to_dense(on_space)
4949

5050

@@ -79,7 +79,7 @@ def probability(self, state):
7979
Edense = self.to_dense('HilbertSchmidt', scratch)
8080
return _np.dot(Edense, state.data) # not vdot b/c data is *real*
8181

82-
def to_dense(self, on_space, outvec=None):
82+
def to_dense(self, on_space: SpaceT, outvec=None):
8383
if on_space not in ('minimal', 'HilbertSchmidt'):
8484
raise ValueError("'densitymx' evotype cannot produce Hilbert-space ops!")
8585
return _mt.zvals_int64_to_dense(self.zvals_int, self.nfactors, outvec, False, self.abs_elval)
@@ -105,7 +105,7 @@ def __init__(self, povm_factors, effect_labels, state_space):
105105
super(EffectRepTensorProduct, self).__init__(state_space)
106106
self.factor_effects_have_changed()
107107

108-
def to_dense(self, on_space, outvec=None):
108+
def to_dense(self, on_space: SpaceT, outvec=None):
109109

110110
if on_space not in ('minimal', 'HilbertSchmidt'):
111111
raise ValueError("'densitymx' evotype cannot produce Hilbert-space ops!")

pygsti/evotypes/densitymx_slow/opreps.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from ...tools import lindbladtools as _lbt
2424
from ...tools import matrixtools as _mt
2525
from ...tools import optools as _ot
26-
26+
from pygsti import SpaceT
2727

2828
class OpRep:
2929
"""
@@ -51,12 +51,12 @@ def aslinearoperator(self):
5151
def mv(v):
5252
if v.ndim == 2 and v.shape[1] == 1: v = v[:, 0]
5353
in_state = _StateRepDense(_np.ascontiguousarray(v, 'd'), self.state_space, None)
54-
return self.acton(in_state).to_dense(on_space='HilbertSchmidt')
54+
return self.acton(in_state).to_dense(on_space="HilbertSchmidt")
5555

5656
def rmv(v):
5757
if v.ndim == 2 and v.shape[1] == 1: v = v[:, 0]
5858
in_state = _StateRepDense(_np.ascontiguousarray(v, 'd'), self.state_space, None)
59-
return self.adjoint_acton(in_state).to_dense(on_space='HilbertSchmidt')
59+
return self.adjoint_acton(in_state).to_dense(on_space="HilbertSchmidt")
6060
return LinearOperator((self.dim, self.dim), matvec=mv, rmatvec=rmv) # transpose, adjoint, dot, matmat?
6161

6262

@@ -80,7 +80,7 @@ def __init__(self, mx, basis, state_space):
8080
def base_has_changed(self):
8181
pass
8282

83-
def to_dense(self, on_space):
83+
def to_dense(self, on_space: SpaceT):
8484
if on_space not in ('minimal', 'HilbertSchmidt'):
8585
raise ValueError("'densitymx_slow' evotype cannot produce Hilbert-space ops!")
8686
return self.base
@@ -115,7 +115,7 @@ def __init__(self, mx, basis, state_space):
115115
def base_has_changed(self):
116116
self.superop_base[:, :] = _ot.unitary_to_superop(self.base, self.basis)
117117

118-
def to_dense(self, on_space):
118+
def to_dense(self, on_space: SpaceT):
119119
if on_space in ('minimal', 'HilbertSchmidt'):
120120
return self.to_dense_superop()
121121
else: # 'Hilbert'
@@ -167,7 +167,7 @@ def adjoint_acton(self, state):
167167
Aadj = self.A.conjugate(copy=True).transpose()
168168
return _StateRepDense(Aadj.dot(state.data), state.state_space, None)
169169

170-
def to_dense(self, on_space):
170+
def to_dense(self, on_space: SpaceT):
171171
if on_space not in ('minimal', 'HilbertSchmidt'):
172172
raise ValueError("'densitymx_slow' evotype cannot produce Hilbert-space ops!")
173173
return self.A.toarray()
@@ -212,7 +212,7 @@ def __str__(self):
212212
def copy(self):
213213
return OpRepKraus(self.basis, list(self.kraus_reps), self.state_space)
214214

215-
def to_dense(self, on_space):
215+
def to_dense(self, on_space: SpaceT):
216216
assert(on_space in ('minimal', 'HilbertSchmidt')), \
217217
'Can only compute OpRepKraus.to_dense on HilbertSchmidt space!'
218218
return sum([rep.to_dense(on_space) for rep in self.kraus_reps])
@@ -245,7 +245,7 @@ def copy(self):
245245
def update_unitary_rates(self, rates):
246246
self.unitary_rates[:] = rates
247247

248-
def to_dense(self, on_space):
248+
def to_dense(self, on_space: SpaceT):
249249
assert(on_space in ('minimal', 'HilbertSchmidt')) # below code only works in this case
250250
return sum([rate * rep.to_dense(on_space) for rate, rep in zip(self.unitary_rates, self.unitary_reps)])
251251

pygsti/evotypes/densitymx_slow/statereps.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from pygsti.baseobjs.statespace import StateSpace as _StateSpace
1818
from ...tools import basistools as _bt
1919
from ...tools import optools as _ot
20-
20+
from pygsti import SpaceT
2121
try:
2222
from ...tools import fastcalc as _fastcalc
2323
except ImportError:
@@ -51,7 +51,7 @@ def actionable_staterep(self):
5151
# a probability/amplitude by POVM effect reps.
5252
return self # for most classes, the rep itself is actionable
5353

54-
def to_dense(self, on_space):
54+
def to_dense(self, on_space: SpaceT):
5555
if on_space not in ('minimal', 'HilbertSchmidt'):
5656
raise ValueError("'densitymx' evotype cannot produce Hilbert-space ops!")
5757
return self.data
@@ -136,7 +136,7 @@ class StateRepComposed(StateRep):
136136
def __init__(self, state_rep, op_rep, state_space):
137137
self.state_rep = state_rep
138138
self.op_rep = op_rep
139-
super(StateRepComposed, self).__init__(state_rep.to_dense('HilbertSchmidt'), state_space)
139+
super(StateRepComposed, self).__init__(state_rep.to_dense("HilbertSchmidt"), state_space)
140140
self.reps_have_changed()
141141

142142
def reps_have_changed(self):
@@ -158,9 +158,9 @@ def reps_have_changed(self):
158158
if len(self.factor_reps) == 0:
159159
vec = _np.empty(0, 'd')
160160
else:
161-
vec = self.factor_reps[0].to_dense('HilbertSchmidt')
161+
vec = self.factor_reps[0].to_dense("HilbertSchmidt")
162162
for i in range(1, len(self.factor_reps)):
163-
vec = _np.kron(vec, self.factor_reps[i].to_dense('HilbertSchmidt'))
163+
vec = _np.kron(vec, self.factor_reps[i].to_dense("HilbertSchmidt"))
164164
self.data[:] = vec
165165

166166
def __reduce__(self):

pygsti/evotypes/stabilizer_slow/effectreps.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from .. import basereps as _basereps
1414
from pygsti.baseobjs.statespace import StateSpace as _StateSpace
1515
from ...tools import matrixtools as _mt
16-
16+
from pygsti import SpaceT
1717

1818
class EffectRep(_basereps.EffectRep):
1919
def __init__(self, state_space):
@@ -29,7 +29,7 @@ def probability(self, state):
2929
def amplitude(self, state):
3030
return state.sframe.extract_amplitude(self.zvals)
3131

32-
def to_dense(self, on_space):
32+
def to_dense(self, on_space: SpaceT):
3333
return _mt.zvals_to_dense(self.zvals, superket=bool(on_space not in ('minimal', 'Hilbert')))
3434

3535

@@ -46,7 +46,7 @@ def __str__(self):
4646
s = "Stabilizer effect vector for %d qubits with outcome %s" % (nQubits, str(self.zvals))
4747
return s
4848

49-
def to_dense(self, on_space, outvec=None):
49+
def to_dense(self, on_space: SpaceT, outvec=None):
5050
return _mt.zvals_to_dense(self.zvals, superket=bool(on_space not in ('minimal', 'Hilbert')))
5151

5252

0 commit comments

Comments
 (0)