pyGSTi 0.9.12__cp38-cp38-win32.whl → 0.9.13__cp38-cp38-win32.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (225) hide show
  1. pyGSTi-0.9.13.dist-info/METADATA +185 -0
  2. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +211 -220
  3. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/WHEEL +1 -1
  4. pygsti/_version.py +2 -2
  5. pygsti/algorithms/contract.py +1 -1
  6. pygsti/algorithms/core.py +62 -35
  7. pygsti/algorithms/fiducialpairreduction.py +95 -110
  8. pygsti/algorithms/fiducialselection.py +17 -8
  9. pygsti/algorithms/gaugeopt.py +2 -2
  10. pygsti/algorithms/germselection.py +87 -77
  11. pygsti/algorithms/mirroring.py +0 -388
  12. pygsti/algorithms/randomcircuit.py +165 -1333
  13. pygsti/algorithms/rbfit.py +0 -234
  14. pygsti/baseobjs/basis.py +94 -396
  15. pygsti/baseobjs/errorgenbasis.py +0 -132
  16. pygsti/baseobjs/errorgenspace.py +0 -10
  17. pygsti/baseobjs/label.py +52 -168
  18. pygsti/baseobjs/opcalc/fastopcalc.cp38-win32.pyd +0 -0
  19. pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
  20. pygsti/baseobjs/polynomial.py +13 -595
  21. pygsti/baseobjs/protectedarray.py +72 -132
  22. pygsti/baseobjs/statespace.py +1 -0
  23. pygsti/circuits/__init__.py +1 -1
  24. pygsti/circuits/circuit.py +753 -504
  25. pygsti/circuits/circuitconstruction.py +0 -4
  26. pygsti/circuits/circuitlist.py +47 -5
  27. pygsti/circuits/circuitparser/__init__.py +8 -8
  28. pygsti/circuits/circuitparser/fastcircuitparser.cp38-win32.pyd +0 -0
  29. pygsti/circuits/circuitstructure.py +3 -3
  30. pygsti/circuits/cloudcircuitconstruction.py +27 -14
  31. pygsti/data/datacomparator.py +4 -9
  32. pygsti/data/dataset.py +51 -46
  33. pygsti/data/hypothesistest.py +0 -7
  34. pygsti/drivers/bootstrap.py +0 -49
  35. pygsti/drivers/longsequence.py +46 -10
  36. pygsti/evotypes/basereps_cython.cp38-win32.pyd +0 -0
  37. pygsti/evotypes/chp/opreps.py +0 -61
  38. pygsti/evotypes/chp/statereps.py +0 -32
  39. pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
  40. pygsti/evotypes/densitymx/effectreps.cp38-win32.pyd +0 -0
  41. pygsti/evotypes/densitymx/effectreps.pyx +1 -1
  42. pygsti/evotypes/densitymx/opreps.cp38-win32.pyd +0 -0
  43. pygsti/evotypes/densitymx/opreps.pyx +2 -2
  44. pygsti/evotypes/densitymx/statereps.cp38-win32.pyd +0 -0
  45. pygsti/evotypes/densitymx/statereps.pyx +1 -1
  46. pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
  47. pygsti/evotypes/densitymx_slow/opreps.py +16 -23
  48. pygsti/evotypes/densitymx_slow/statereps.py +10 -3
  49. pygsti/evotypes/evotype.py +39 -2
  50. pygsti/evotypes/stabilizer/effectreps.cp38-win32.pyd +0 -0
  51. pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
  52. pygsti/evotypes/stabilizer/opreps.cp38-win32.pyd +0 -0
  53. pygsti/evotypes/stabilizer/opreps.pyx +0 -4
  54. pygsti/evotypes/stabilizer/statereps.cp38-win32.pyd +0 -0
  55. pygsti/evotypes/stabilizer/statereps.pyx +1 -5
  56. pygsti/evotypes/stabilizer/termreps.cp38-win32.pyd +0 -0
  57. pygsti/evotypes/stabilizer/termreps.pyx +0 -7
  58. pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
  59. pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
  60. pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
  61. pygsti/evotypes/statevec/effectreps.cp38-win32.pyd +0 -0
  62. pygsti/evotypes/statevec/effectreps.pyx +1 -1
  63. pygsti/evotypes/statevec/opreps.cp38-win32.pyd +0 -0
  64. pygsti/evotypes/statevec/opreps.pyx +2 -2
  65. pygsti/evotypes/statevec/statereps.cp38-win32.pyd +0 -0
  66. pygsti/evotypes/statevec/statereps.pyx +1 -1
  67. pygsti/evotypes/statevec/termreps.cp38-win32.pyd +0 -0
  68. pygsti/evotypes/statevec/termreps.pyx +0 -7
  69. pygsti/evotypes/statevec_slow/effectreps.py +0 -3
  70. pygsti/evotypes/statevec_slow/opreps.py +0 -5
  71. pygsti/extras/__init__.py +0 -1
  72. pygsti/extras/drift/signal.py +1 -1
  73. pygsti/extras/drift/stabilityanalyzer.py +3 -1
  74. pygsti/extras/interpygate/__init__.py +12 -0
  75. pygsti/extras/interpygate/core.py +0 -36
  76. pygsti/extras/interpygate/process_tomography.py +44 -10
  77. pygsti/extras/rpe/rpeconstruction.py +0 -2
  78. pygsti/forwardsims/__init__.py +1 -0
  79. pygsti/forwardsims/forwardsim.py +50 -93
  80. pygsti/forwardsims/mapforwardsim.py +78 -20
  81. pygsti/forwardsims/mapforwardsim_calc_densitymx.cp38-win32.pyd +0 -0
  82. pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
  83. pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
  84. pygsti/forwardsims/matrixforwardsim.py +72 -17
  85. pygsti/forwardsims/termforwardsim.py +9 -111
  86. pygsti/forwardsims/termforwardsim_calc_stabilizer.cp38-win32.pyd +0 -0
  87. pygsti/forwardsims/termforwardsim_calc_statevec.cp38-win32.pyd +0 -0
  88. pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
  89. pygsti/forwardsims/torchfwdsim.py +265 -0
  90. pygsti/forwardsims/weakforwardsim.py +2 -2
  91. pygsti/io/__init__.py +1 -2
  92. pygsti/io/mongodb.py +0 -2
  93. pygsti/io/stdinput.py +6 -22
  94. pygsti/layouts/copalayout.py +10 -12
  95. pygsti/layouts/distlayout.py +0 -40
  96. pygsti/layouts/maplayout.py +103 -25
  97. pygsti/layouts/matrixlayout.py +99 -60
  98. pygsti/layouts/prefixtable.py +1534 -52
  99. pygsti/layouts/termlayout.py +1 -1
  100. pygsti/modelmembers/instruments/instrument.py +3 -3
  101. pygsti/modelmembers/instruments/tpinstrument.py +2 -2
  102. pygsti/modelmembers/modelmember.py +0 -17
  103. pygsti/modelmembers/operations/__init__.py +3 -4
  104. pygsti/modelmembers/operations/affineshiftop.py +206 -0
  105. pygsti/modelmembers/operations/composederrorgen.py +1 -1
  106. pygsti/modelmembers/operations/composedop.py +1 -24
  107. pygsti/modelmembers/operations/denseop.py +5 -5
  108. pygsti/modelmembers/operations/eigpdenseop.py +2 -2
  109. pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
  110. pygsti/modelmembers/operations/embeddedop.py +0 -1
  111. pygsti/modelmembers/operations/experrorgenop.py +5 -2
  112. pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
  113. pygsti/modelmembers/operations/fullcptpop.py +2 -2
  114. pygsti/modelmembers/operations/fulltpop.py +28 -6
  115. pygsti/modelmembers/operations/fullunitaryop.py +5 -4
  116. pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
  117. pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
  118. pygsti/modelmembers/operations/linearop.py +7 -27
  119. pygsti/modelmembers/operations/opfactory.py +1 -1
  120. pygsti/modelmembers/operations/repeatedop.py +1 -24
  121. pygsti/modelmembers/operations/staticstdop.py +1 -1
  122. pygsti/modelmembers/povms/__init__.py +3 -3
  123. pygsti/modelmembers/povms/basepovm.py +7 -36
  124. pygsti/modelmembers/povms/complementeffect.py +4 -9
  125. pygsti/modelmembers/povms/composedeffect.py +0 -320
  126. pygsti/modelmembers/povms/computationaleffect.py +1 -1
  127. pygsti/modelmembers/povms/computationalpovm.py +3 -1
  128. pygsti/modelmembers/povms/effect.py +3 -5
  129. pygsti/modelmembers/povms/marginalizedpovm.py +3 -81
  130. pygsti/modelmembers/povms/tppovm.py +74 -2
  131. pygsti/modelmembers/states/__init__.py +2 -5
  132. pygsti/modelmembers/states/composedstate.py +0 -317
  133. pygsti/modelmembers/states/computationalstate.py +3 -3
  134. pygsti/modelmembers/states/cptpstate.py +4 -4
  135. pygsti/modelmembers/states/densestate.py +10 -8
  136. pygsti/modelmembers/states/fullpurestate.py +0 -24
  137. pygsti/modelmembers/states/purestate.py +1 -1
  138. pygsti/modelmembers/states/state.py +5 -6
  139. pygsti/modelmembers/states/tpstate.py +28 -10
  140. pygsti/modelmembers/term.py +3 -6
  141. pygsti/modelmembers/torchable.py +50 -0
  142. pygsti/modelpacks/_modelpack.py +1 -1
  143. pygsti/modelpacks/smq1Q_ZN.py +3 -1
  144. pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
  145. pygsti/modelpacks/smq2Q_XY.py +3 -3
  146. pygsti/modelpacks/smq2Q_XYI.py +2 -2
  147. pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
  148. pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
  149. pygsti/modelpacks/smq2Q_XYXX.py +1 -1
  150. pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
  151. pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
  152. pygsti/modelpacks/stdtarget.py +0 -121
  153. pygsti/models/cloudnoisemodel.py +1 -2
  154. pygsti/models/explicitcalc.py +3 -3
  155. pygsti/models/explicitmodel.py +3 -13
  156. pygsti/models/fogistore.py +5 -3
  157. pygsti/models/localnoisemodel.py +1 -2
  158. pygsti/models/memberdict.py +0 -12
  159. pygsti/models/model.py +801 -68
  160. pygsti/models/modelconstruction.py +4 -4
  161. pygsti/models/modelnoise.py +2 -2
  162. pygsti/models/modelparaminterposer.py +1 -1
  163. pygsti/models/oplessmodel.py +1 -1
  164. pygsti/models/qutrit.py +15 -14
  165. pygsti/objectivefns/objectivefns.py +75 -140
  166. pygsti/objectivefns/wildcardbudget.py +2 -7
  167. pygsti/optimize/__init__.py +1 -0
  168. pygsti/optimize/arraysinterface.py +28 -0
  169. pygsti/optimize/customcg.py +0 -12
  170. pygsti/optimize/customlm.py +129 -323
  171. pygsti/optimize/customsolve.py +2 -2
  172. pygsti/optimize/optimize.py +0 -84
  173. pygsti/optimize/simplerlm.py +841 -0
  174. pygsti/optimize/wildcardopt.py +19 -598
  175. pygsti/protocols/confidenceregionfactory.py +28 -14
  176. pygsti/protocols/estimate.py +31 -14
  177. pygsti/protocols/gst.py +238 -142
  178. pygsti/protocols/modeltest.py +19 -12
  179. pygsti/protocols/protocol.py +9 -37
  180. pygsti/protocols/rb.py +450 -79
  181. pygsti/protocols/treenode.py +8 -2
  182. pygsti/protocols/vb.py +108 -206
  183. pygsti/protocols/vbdataframe.py +1 -1
  184. pygsti/report/factory.py +0 -15
  185. pygsti/report/fogidiagram.py +1 -17
  186. pygsti/report/modelfunction.py +12 -3
  187. pygsti/report/mpl_colormaps.py +1 -1
  188. pygsti/report/plothelpers.py +11 -3
  189. pygsti/report/report.py +16 -0
  190. pygsti/report/reportables.py +41 -37
  191. pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
  192. pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
  193. pygsti/report/workspace.py +2 -14
  194. pygsti/report/workspaceplots.py +328 -505
  195. pygsti/tools/basistools.py +9 -36
  196. pygsti/tools/edesigntools.py +124 -96
  197. pygsti/tools/fastcalc.cp38-win32.pyd +0 -0
  198. pygsti/tools/fastcalc.pyx +35 -81
  199. pygsti/tools/internalgates.py +151 -15
  200. pygsti/tools/jamiolkowski.py +5 -5
  201. pygsti/tools/lindbladtools.py +19 -11
  202. pygsti/tools/listtools.py +0 -114
  203. pygsti/tools/matrixmod2.py +1 -1
  204. pygsti/tools/matrixtools.py +173 -339
  205. pygsti/tools/nameddict.py +1 -1
  206. pygsti/tools/optools.py +154 -88
  207. pygsti/tools/pdftools.py +0 -25
  208. pygsti/tools/rbtheory.py +3 -320
  209. pygsti/tools/slicetools.py +64 -12
  210. pyGSTi-0.9.12.dist-info/METADATA +0 -157
  211. pygsti/algorithms/directx.py +0 -711
  212. pygsti/evotypes/qibo/__init__.py +0 -33
  213. pygsti/evotypes/qibo/effectreps.py +0 -78
  214. pygsti/evotypes/qibo/opreps.py +0 -376
  215. pygsti/evotypes/qibo/povmreps.py +0 -98
  216. pygsti/evotypes/qibo/statereps.py +0 -174
  217. pygsti/extras/rb/__init__.py +0 -13
  218. pygsti/extras/rb/benchmarker.py +0 -957
  219. pygsti/extras/rb/dataset.py +0 -378
  220. pygsti/extras/rb/io.py +0 -814
  221. pygsti/extras/rb/simulate.py +0 -1020
  222. pygsti/io/legacyio.py +0 -385
  223. pygsti/modelmembers/povms/denseeffect.py +0 -142
  224. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
  225. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
@@ -49,61 +49,6 @@ class LindbladErrorgen(_LinearOperator):
49
49
  is CPTP. These terms can be divided into "Hamiltonian"-type terms, which
50
50
  map rho -> i[H,rho] and "non-Hamiltonian"/"other"-type terms, which map rho
51
51
  -> A rho B + 0.5*(ABrho + rhoAB).
52
-
53
- Parameters
54
- ----------
55
- dim : int
56
- The Hilbert-Schmidt (superoperator) dimension, which will be the
57
- dimension of the created operator.
58
-
59
- lindblad_term_dict : dict
60
- A dictionary specifying which Linblad terms are present in the
61
- parameteriztion. Keys are `(termType, basisLabel1, <basisLabel2>)`
62
- tuples, where `termType` can be `"H"` (Hamiltonian), `"S"`
63
- (Stochastic), or `"A"` (Affine). Hamiltonian and Affine terms always
64
- have a single basis label (so key is a 2-tuple) whereas Stochastic
65
- tuples with 1 basis label indicate a *diagonal* term, and are the
66
- only types of terms allowed when `nonham_mode != "all"`. Otherwise,
67
- Stochastic term tuples can include 2 basis labels to specify
68
- "off-diagonal" non-Hamiltonian Lindblad terms. Basis labels can be
69
- strings or integers. Values are complex coefficients.
70
-
71
- basis : Basis, optional
72
- A basis mapping the labels used in the keys of `lindblad_term_dict` to
73
- basis matrices (e.g. numpy arrays or Scipy sparse matrices).
74
-
75
- param_mode : {"unconstrained", "cptp", "depol", "reldepol"}
76
- Describes how the Lindblad coefficients/projections relate to the
77
- error generator's parameter values. Allowed values are:
78
- `"unconstrained"` (coeffs are independent unconstrained parameters),
79
- `"cptp"` (independent parameters but constrained so map is CPTP),
80
- `"reldepol"` (all non-Ham. diagonal coeffs take the *same* value),
81
- `"depol"` (same as `"reldepol"` but coeffs must be *positive*)
82
-
83
- nonham_mode : {"diagonal", "diag_affine", "all"}
84
- Which non-Hamiltonian Lindblad projections are potentially non-zero.
85
- Allowed values are: `"diagonal"` (only the diagonal Lind. coeffs.),
86
- `"diag_affine"` (diagonal coefficients + affine projections), and
87
- `"all"` (the entire matrix of coefficients is allowed).
88
-
89
- truncate : bool, optional
90
- Whether to truncate the projections onto the Lindblad terms in
91
- order to meet constraints (e.g. to preserve CPTP) when necessary.
92
- If False, then an error is thrown when the given dictionary of
93
- Lindblad terms doesn't conform to the constrains.
94
-
95
- mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object
96
- The basis for this error generator's linear mapping. Allowed
97
- values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
98
- and Qutrit (qt) (or a custom basis object).
99
-
100
- evotype : {"densitymx","svterm","cterm"}
101
- The evolution type of the error generator being constructed.
102
- `"densitymx"` means the usual Lioville density-matrix-vector
103
- propagation via matrix-vector products. `"svterm"` denotes
104
- state-vector term-based evolution (action of operation is obtained by
105
- evaluating the rank-1 terms up to some order). `"cterm"` is similar
106
- but uses Clifford operation action on stabilizer states.
107
52
  """
108
53
 
109
54
  _generators_cache = {} # a custom cache for _init_generators method calls
@@ -111,6 +56,41 @@ class LindbladErrorgen(_LinearOperator):
111
56
  @classmethod
112
57
  def from_operation_matrix_and_blocks(cls, op_matrix, lindblad_coefficient_blocks, lindblad_basis='auto',
113
58
  mx_basis='pp', truncate=True, evotype="default", state_space=None):
59
+
60
+ """
61
+ Create a Lindblad-parameterized error generator from an operation matrix and coefficient blocks.
62
+
63
+ Parameters
64
+ ----------
65
+ op_matrix : numpy array or SciPy sparse matrix
66
+ A square 2D array that gives the raw operation matrix, assumed to be in the `mx_basis` basis.
67
+ The shape of this array sets the dimension of the operation.
68
+
69
+ lindblad_coefficient_blocks : list
70
+ A list of Lindblad coefficient blocks to set from the error generator projections.
71
+
72
+ lindblad_basis : {'auto', 'PP', 'std', 'gm', 'qt'}, optional
73
+ The basis used for Lindblad terms. Default is 'auto'.
74
+
75
+ mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object, optional
76
+ The basis for this error generator's linear mapping. Default is 'pp'.
77
+
78
+ truncate : bool, optional
79
+ Whether to truncate the projections onto the Lindblad terms in order to meet constraints.
80
+ Default is True. (e.g. to preserve CPTP) when necessary. If False, then an error is thrown
81
+ when the Lindblad terms don't conform to the constrains.
82
+
83
+ evotype : {"default", "densitymx", "svterm", "cterm"}, optional
84
+ The evolution type of the error generator being constructed. Default is "default".
85
+
86
+ state_space : StateSpace, optional
87
+ The state space for the error generator. Default is None.
88
+
89
+ Returns
90
+ -------
91
+ LindbladErrorgen
92
+ """
93
+
114
94
  sparseOp = _sps.issparse(op_matrix)
115
95
 
116
96
  #Init base from error generator: sets basis members and ultimately
@@ -145,58 +125,31 @@ class LindbladErrorgen(_LinearOperator):
145
125
  Parameters
146
126
  ----------
147
127
  op_matrix : numpy array or SciPy sparse matrix
148
- a square 2D array that gives the raw operation matrix, assumed to
149
- be in the `mx_basis` basis, to parameterize. The shape of this
150
- array sets the dimension of the operation. If None, then it is assumed
151
- equal to `unitary_postfactor` (which cannot also be None). The
152
- quantity `op_matrix inv(unitary_postfactor)` is parameterized via
153
- projection onto the Lindblad terms.
154
-
155
- ham_basis : {'std', 'gm', 'pp', 'qt'}, list of matrices, or Basis object
156
- The basis is used to construct the Hamiltonian-type lindblad error
157
- Allowed values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
158
- and Qutrit (qt), list of numpy arrays, or a custom basis object.
159
-
160
- nonham_basis : {'std', 'gm', 'pp', 'qt'}, list of matrices, or Basis object
161
- The basis is used to construct the non-Hamiltonian (generalized
162
- Stochastic-type) lindblad error Allowed values are Matrix-unit
163
- (std), Gell-Mann (gm), Pauli-product (pp), and Qutrit (qt), list of
164
- numpy arrays, or a custom basis object.
165
-
166
- param_mode : {"unconstrained", "cptp", "depol", "reldepol"}
167
- Describes how the Lindblad coefficients/projections relate to the
168
- operation's parameter values. Allowed values are:
169
- `"unconstrained"` (coeffs are independent unconstrained parameters),
170
- `"cptp"` (independent parameters but constrained so map is CPTP),
171
- `"reldepol"` (all non-Ham. diagonal coeffs take the *same* value),
172
- `"depol"` (same as `"reldepol"` but coeffs must be *positive*)
173
-
174
- nonham_mode : {"diagonal", "diag_affine", "all"}
175
- Which non-Hamiltonian Lindblad projections are potentially non-zero.
176
- Allowed values are: `"diagonal"` (only the diagonal Lind. coeffs.),
177
- `"diag_affine"` (diagonal coefficients + affine projections), and
178
- `"all"` (the entire matrix of coefficients is allowed).
128
+ A square 2D array that gives the raw operation matrix, assumed to be in the `mx_basis` basis.
129
+ The shape of this array sets the dimension of the operation.
179
130
 
180
- truncate : bool, optional
181
- Whether to truncate the projections onto the Lindblad terms in
182
- order to meet constraints (e.g. to preserve CPTP) when necessary.
183
- If False, then an error is thrown when the given `operation` cannot
184
- be realized by the specified set of Lindblad projections.
131
+ parameterization : str, optional (default 'CPTP')
132
+ Describes how the Lindblad coefficients/projections relate to the error generator's parameter values.
133
+ Default is "CPTP". Supported strings are those castable to `LindbladParameterization`. See
134
+ `LindbladParameterization` for supported options.
135
+
136
+ lindblad_basis : {'PP', 'std', 'gm', 'qt'}, optional
137
+ The basis used for Lindblad terms. Default is 'PP'.
185
138
 
186
- mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object
187
- The source and destination basis, respectively. Allowed
139
+ mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object, optional
140
+ The basis for this error generator's linear mapping. Default is 'pp'. Allowed
188
141
  values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
189
142
  and Qutrit (qt) (or a custom basis object).
190
143
 
191
- evotype : Evotype or str, optional
192
- The evolution type. The special value `"default"` is equivalent
193
- to specifying the value of `pygsti.evotypes.Evotype.default_evotype`.
144
+ truncate : bool, optional
145
+ Whether to truncate the projections onto the Lindblad terms in order to meet constraints.
146
+ Default is True.
194
147
 
195
- state_space : TODO docstring
148
+ evotype : {"default", "densitymx", "svterm", "cterm"}, optional
149
+ The evolution type of the error generator being constructed. Default is "default".
196
150
 
197
- Returns
198
- -------
199
- LindbladOp
151
+ state_space : StateSpace, optional
152
+ The state space for the error generator. Default is None.
200
153
  """
201
154
 
202
155
  #Compute an errorgen from the given op_matrix. Works with both
@@ -226,7 +179,40 @@ class LindbladErrorgen(_LinearOperator):
226
179
  def from_error_generator(cls, errgen_or_dim, parameterization="CPTP", lindblad_basis='PP', mx_basis='pp',
227
180
  truncate=True, evotype="default", state_space=None):
228
181
  """
229
- TODO: docstring - take from now-private version below Note: errogen_or_dim can be an integer => zero errgen
182
+ Create a Lindblad-parameterized error generator from an error generator matrix or dimension.
183
+
184
+ Parameters
185
+ ----------
186
+ errgen_or_dim : numpy array, SciPy sparse matrix, or int
187
+ A square 2D array that gives the full error generator or an integer specifying the dimension
188
+ of a zero error generator.
189
+
190
+ parameterization : str, optional (default 'CPTP')
191
+ Describes how the Lindblad coefficients/projections relate to the error generator's parameter values.
192
+ Default is "CPTP". Supported strings are those castable to `LindbladParameterization`. See
193
+ `LindbladParameterization` for supported options.
194
+
195
+ lindblad_basis : {'PP', 'std', 'gm', 'qt'}, optional
196
+ The basis used for Lindblad terms. Default is 'PP'.
197
+
198
+ mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object, optional
199
+ The basis for this error generator's linear mapping. Default is 'pp'. Allowed
200
+ values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
201
+ and Qutrit (qt) (or a custom basis object).
202
+
203
+ truncate : bool, optional
204
+ Whether to truncate the projections onto the Lindblad terms in order to meet constraints.
205
+ Default is True.
206
+
207
+ evotype : {"default", "densitymx", "svterm", "cterm"}, optional
208
+ The evolution type of the error generator being constructed. Default is "default".
209
+
210
+ state_space : StateSpace, optional
211
+ The state space for the error generator. Default is None.
212
+
213
+ Returns
214
+ -------
215
+ LindbladErrorgen
230
216
  """
231
217
  errgen = _np.zeros((errgen_or_dim, errgen_or_dim), 'd') \
232
218
  if isinstance(errgen_or_dim, (int, _np.int64)) else errgen_or_dim
@@ -238,7 +224,36 @@ class LindbladErrorgen(_LinearOperator):
238
224
  lindblad_basis='PP', mx_basis='pp',
239
225
  truncate=True, evotype="default", state_space=None):
240
226
  """
241
- TODO: docstring - take from now-private version below Note: errogen_or_dim can be an integer => zero errgen
227
+ Create a Lindblad-parameterized error generator from an error generator matrix or dimension and coefficient blocks.
228
+
229
+ Parameters
230
+ ----------
231
+ errgen_or_dim : numpy array, SciPy sparse matrix, or int
232
+ A square 2D array that gives the full error generator or an integer specifying the dimension
233
+ of a zero error generator.
234
+
235
+ lindblad_coefficient_blocks : list
236
+ A list of Lindblad coefficient blocks to set from the error generator projections.
237
+
238
+ lindblad_basis : {'PP', 'std', 'gm', 'qt'}, optional
239
+ The basis used for Lindblad terms. Default is 'PP'.
240
+
241
+ mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object, optional
242
+ The basis for this error generator's linear mapping. Default is 'pp'.
243
+
244
+ truncate : bool, optional
245
+ Whether to truncate the projections onto the Lindblad terms in order to meet constraints.
246
+ Default is True.
247
+
248
+ evotype : {"default", "densitymx", "svterm", "cterm"}, optional
249
+ The evolution type of the error generator being constructed. Default is "default".
250
+
251
+ state_space : StateSpace, optional
252
+ The state space for the error generator. Default is None.
253
+
254
+ Returns
255
+ -------
256
+ LindbladErrorgen
242
257
  """
243
258
  errgenMx = _np.zeros((errgen_or_dim, errgen_or_dim), 'd') \
244
259
  if isinstance(errgen_or_dim, (int, _np.int64)) else errgen_or_dim
@@ -251,7 +266,6 @@ class LindbladErrorgen(_LinearOperator):
251
266
  mx_basis="pp", truncate=True, evotype="default", state_space=None):
252
267
  """
253
268
  Create a Lindblad-form error generator from an error generator matrix and a basis.
254
- TODO: fix docstring -- ham/nonham_basis ==> lindblad_basis
255
269
 
256
270
  The basis specifies how to decompose (project) the error generator.
257
271
 
@@ -260,38 +274,19 @@ class LindbladErrorgen(_LinearOperator):
260
274
  errgen : numpy array or SciPy sparse matrix
261
275
  a square 2D array that gives the full error generator. The shape of
262
276
  this array sets the dimension of the operator. The projections of
263
- this quantity onto the `ham_basis` and `nonham_basis` are closely
264
- related to the parameters of the error generator (they may not be
265
- exactly equal if, e.g `cptp=True`).
266
-
267
- ham_basis: {'std', 'gm', 'pp', 'qt'}, list of matrices, or Basis object
268
- The basis is used to construct the Hamiltonian-type lindblad error
269
- Allowed values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
270
- and Qutrit (qt), list of numpy arrays, or a custom basis object.
271
-
272
- nonham_basis: {'std', 'gm', 'pp', 'qt'}, list of matrices, or Basis object
273
- The basis is used to construct the non-Hamiltonian-type lindblad error
274
- Allowed values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
275
- and Qutrit (qt), list of numpy arrays, or a custom basis object.
276
-
277
- param_mode : {"unconstrained", "cptp", "depol", "reldepol"}
278
- Describes how the Lindblad coefficients/projections relate to the
279
- operation's parameter values. Allowed values are:
280
- `"unconstrained"` (coeffs are independent unconstrained parameters),
281
- `"cptp"` (independent parameters but constrained so map is CPTP),
282
- `"reldepol"` (all non-Ham. diagonal coeffs take the *same* value),
283
- `"depol"` (same as `"reldepol"` but coeffs must be *positive*)
284
-
285
- nonham_mode : {"diagonal", "diag_affine", "all"}
286
- Which non-Hamiltonian Lindblad projections are potentially non-zero.
287
- Allowed values are: `"diagonal"` (only the diagonal Lind. coeffs.),
288
- `"diag_affine"` (diagonal coefficients + affine projections), and
289
- `"all"` (the entire matrix of coefficients is allowed).
290
-
291
- mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object
292
- The source and destination basis, respectively. Allowed
293
- values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
294
- and Qutrit (qt) (or a custom basis object).
277
+ this quantity are closely related to the parameters of the error
278
+ generator (they may not be exactly equal if parameterization = 'CPTP').
279
+
280
+ lindblad_basis : {'PP', 'std', 'gm', 'qt'}, optional
281
+ The basis used for Lindblad terms. Default is 'PP'.
282
+
283
+ parameterization : str, optional (default 'CPTP')
284
+ Describes how the Lindblad coefficients/projections relate to the error generator's parameter values.
285
+ Default is "CPTP". Supported strings are those castable to `LindbladParameterization`. See
286
+ `LindbladParameterization` for supported options.
287
+
288
+ mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object, optional
289
+ The basis for this error generator's linear mapping. Default is 'pp'.
295
290
 
296
291
  truncate : bool, optional
297
292
  Whether to truncate the projections onto the Lindblad terms in
@@ -307,7 +302,8 @@ class LindbladErrorgen(_LinearOperator):
307
302
  terms up to some order). `"cterm"` is similar but uses Clifford operation
308
303
  action on stabilizer states.
309
304
 
310
- state_space : TODO docstring
305
+ state_space : StateSpace, optional
306
+ The state space for the error generator. Default is None.
311
307
 
312
308
  Returns
313
309
  -------
@@ -350,8 +346,47 @@ class LindbladErrorgen(_LinearOperator):
350
346
 
351
347
  @classmethod
352
348
  def from_elementary_errorgens(cls, elementary_errorgens, parameterization='auto', elementary_errorgen_basis='PP',
353
- mx_basis="pp", truncate=True, evotype="default", state_space=None):
354
- """TODO: docstring"""
349
+ mx_basis="pp", truncate=True, evotype="default", state_space=None):
350
+ """
351
+ Create a Lindblad-parameterized error generator from elementary error generators.
352
+
353
+ Parameters
354
+ ----------
355
+ elementary_errorgens : dict
356
+ A dictionary of elementary error generators. Keys are labels specifying the type and basis
357
+ elements of the elementary error generators, and values are the corresponding coefficients.
358
+ Keys are `(termType, basisLabel1, <basisLabel2>)` tuples, where `termType` is
359
+ `"H"` (Hamiltonian), `"S"` (Stochastic), `"C"` (Correlation) or `"A"` (Active).
360
+ Hamiltonian and Stochastic terms always have a single basis label (so key is a 2-tuple)
361
+ whereas C and A tuples have 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
362
+ terms. Basis labels are pauli strings. Values are coefficients.
363
+
364
+ parameterization : str, optional (default 'CPTP')
365
+ Describes how the Lindblad coefficients/projections relate to the error generator's parameter values.
366
+ Default is "CPTP". Supported strings are those castable to `LindbladParameterization`. See
367
+ `LindbladParameterization` for supported options.
368
+
369
+ elementary_errorgen_basis : {'PP', 'std', 'gm', 'qt'}, optional
370
+ The basis used for the elementary error generators. Default is 'PP'.
371
+
372
+ mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object, optional
373
+ The basis for this error generator's linear mapping. Default is 'pp'.
374
+
375
+ truncate : bool, optional
376
+ Whether to truncate the projections onto the Lindblad terms in order to meet constraints.
377
+ Default is True.
378
+
379
+ evotype : {"default", "densitymx", "svterm", "cterm"}, optional
380
+ The evolution type of the error generator being constructed. Default is "default".
381
+
382
+ state_space : StateSpace, optional
383
+ The state space for the error generator. Default is None.
384
+
385
+ Returns
386
+ -------
387
+ LindbladErrorgen
388
+ """
389
+
355
390
  state_space = _statespace.StateSpace.cast(state_space)
356
391
  dim = state_space.dim # Store superop dimension
357
392
  basis = _Basis.cast(elementary_errorgen_basis, dim)
@@ -384,6 +419,33 @@ class LindbladErrorgen(_LinearOperator):
384
419
 
385
420
  def __init__(self, lindblad_coefficient_blocks, lindblad_basis='auto', mx_basis='pp',
386
421
  evotype="default", state_space=None):
422
+
423
+ """
424
+ Initialize a LindbladErrorgen object.
425
+
426
+ Parameters
427
+ ----------
428
+ lindblad_coefficient_blocks : list of LindbladCoefficientBlock
429
+ A list of Lindblad coefficient blocks that define the error generator.
430
+
431
+ lindblad_basis : {'auto', 'PP', 'std', 'gm', 'qt'} or Basis object, optional
432
+ The basis used for Lindblad terms. If 'auto', the basis is inferred from the coefficient blocks.
433
+ Default is 'auto'.
434
+
435
+ mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object, optional
436
+ The basis for this error generator's linear mapping. Default is 'pp'.
437
+
438
+ evotype : {"default", "densitymx", "svterm", "cterm"}, optional
439
+ The evolution type of the error generator being constructed. Default is "default".
440
+
441
+ state_space : StateSpace, optional
442
+ The state space for the error generator. Default is None.
443
+
444
+ Raises
445
+ ------
446
+ ValueError
447
+ If the provided evotype does not support any of the required representations for a LindbladErrorgen.
448
+ """
387
449
 
388
450
  if isinstance(lindblad_coefficient_blocks, dict): # backward compat warning
389
451
  _warnings.warn(("You're trying to create a LindbladErrorgen object using a dictionary. This"
@@ -392,10 +454,10 @@ class LindbladErrorgen(_LinearOperator):
392
454
  " a LindbladErrorgen.from_elementary_errorgens(...) instead."))
393
455
 
394
456
  state_space = _statespace.StateSpace.cast(state_space)
395
-
457
+ dim = state_space.dim # Store superop dimension
396
458
  #Decide on our rep-type ahead of time so we know whether to make bases sparse
397
459
  # (a LindbladErrorgen with a sparse rep => sparse bases and similar with dense rep)
398
- evotype = _Evotype.cast(evotype)
460
+ evotype = _Evotype.cast(evotype, state_space=state_space)
399
461
  reptype_preferences = ('lindblad errorgen', 'dense superop', 'sparse superop') \
400
462
  if evotype.prefer_dense_reps else ('lindblad errorgen', 'sparse superop', 'dense superop')
401
463
  for reptype in reptype_preferences:
@@ -403,13 +465,8 @@ class LindbladErrorgen(_LinearOperator):
403
465
  self._rep_type = reptype; break
404
466
  else:
405
467
  raise ValueError("Evotype doesn't support any of the representations a LindbladErrorgen requires.")
406
- sparse_bases = bool(self._rep_type == 'sparse superop') # we use sparse bases iff we have a sparse rep
407
-
408
- state_space = _statespace.StateSpace.cast(state_space)
409
- dim = state_space.dim # Store superop dimension
468
+ sparse_bases = bool(self._rep_type == 'sparse superop') # we use sparse bases iff we have a sparse rep
410
469
 
411
- #UPDATE: no more self.lindblad_basis
412
- #self.lindblad_basis = _Basis.cast(lindblad_basis, dim, sparse=sparse_bases)
413
470
  if lindblad_basis == "auto":
414
471
  assert(all([(blk._basis is not None) for blk in lindblad_coefficient_blocks])), \
415
472
  "When `lindblad_basis == 'auto'`, the supplied coefficient blocks must have valid bases!"
@@ -422,26 +479,6 @@ class LindbladErrorgen(_LinearOperator):
422
479
  elif blk._basis.sparse != sparse_bases: # update block bases to desired sparsity if needed
423
480
  blk._basis = blk._basis.with_sparsity(sparse_bases)
424
481
 
425
- #UPDATE - this essentially constructs the coefficient blocks from a single dict, which are now given as input
426
- ## lindblad_term_dict, basis => bases + parameter values
427
- ## but maybe we want lindblad_term_dict, basisdict => basis + projections/coeffs,
428
- ## then projections/coeffs => paramvals? since the latter is what set_errgen needs
429
- #hamC, otherC, self.ham_basis, self.other_basis = \
430
- # _ot.lindblad_terms_to_projections(lindblad_term_dict, self.lindblad_basis,
431
- # self.parameterization.nonham_mode)
432
-
433
- #UPDATE - self.ham_basis_size and self.other_basis_size have been removed!
434
- #self.ham_basis_size = len(self.ham_basis)
435
- #self.other_basis_size = len(self.other_basis)
436
- #assert(self.parameterization.ham_params_allowed or self.ham_basis_size == 0), \
437
- # "Hamiltonian lindblad terms are not allowed!"
438
- #assert(self.parameterization.nonham_params_allowed or self.other_basis_size == 0), \
439
- # "Non-Hamiltonian lindblad terms are not allowed!"
440
- #
441
- ## Check that bases have the desired sparseness (should be same as lindblad_basis)
442
- #assert (self.ham_basis_size == 0 or self.ham_basis.sparse == sparse_bases)
443
- #assert (self.other_basis_size == 0 or self.other_basis.sparse == sparse_bases)
444
-
445
482
  self.coefficient_blocks = lindblad_coefficient_blocks
446
483
  self.matrix_basis = _Basis.cast(mx_basis, dim, sparse=sparse_bases)
447
484
 
@@ -464,6 +501,9 @@ class LindbladErrorgen(_LinearOperator):
464
501
  blk.create_lindblad_term_superoperators(self.matrix_basis, sparse_bases, include_1norms=True, flat=True)
465
502
  for blk in lindblad_coefficient_blocks]
466
503
 
504
+ #combine all of the linblad term superoperators across the blocks to a single concatenated tensor.
505
+ self.combined_lindblad_term_superops = _np.concatenate([Lterm_superops for (Lterm_superops, _) in self.lindblad_term_superops_and_1norms], axis=0)
506
+
467
507
  #Create a representation of the type chosen above:
468
508
  if self._rep_type == 'lindblad errorgen':
469
509
  rep = evotype.create_lindblad_errorgen_rep(lindblad_coefficient_blocks, state_space)
@@ -497,140 +537,8 @@ class LindbladErrorgen(_LinearOperator):
497
537
  self._paramlbls = _np.array(list(_itertools.chain.from_iterable(
498
538
  [blk.param_labels for blk in self.coefficient_blocks])), dtype=object)
499
539
  assert(self._onenorm_upbound is not None) # _update_rep should set this
500
- #Done with __init__(...)
501
-
502
- #def _init_generators(self, dim):
503
- # #assumes self.dim, self.ham_basis, self.other_basis, and self.matrix_basis are setup...
504
- # sparse_bases = bool(self._rep_type == 'sparse superop')
505
- #
506
- # #HERE TODO - need to update this / MOVE to block class?
507
- # #use caching to increase performance - cache based on all the self.XXX members utilized by this fn
508
- # cache_key = (self._rep_type, self.matrix_basis, self.ham_basis, self.other_basis, self.parameterization)
509
- # #print("cache key = ",self._rep_type, (self.matrix_basis.name, self.matrix_basis.dim),
510
- # # (self.ham_basis.name, self.ham_basis.dim), (self.other_basis.name, self.other_basis.dim),
511
- # # str(self.parameterization))
512
- #
513
- # if cache_key not in self._generators_cache:
514
- #
515
- # d = int(round(_np.sqrt(dim)))
516
- # assert(d * d == dim), "Errorgen dim must be a perfect square"
517
- #
518
- # # Get basis transfer matrix
519
- # mxBasisToStd = self.matrix_basis.create_transform_matrix(
520
- # _BuiltinBasis("std", self.matrix_basis.dim, sparse_bases))
521
- # # use BuiltinBasis("std") instead of just "std" in case matrix_basis is a TensorProdBasis
522
- # leftTrans = _spsl.inv(mxBasisToStd.tocsc()).tocsr() if _sps.issparse(mxBasisToStd) \
523
- # else _np.linalg.inv(mxBasisToStd)
524
- # rightTrans = mxBasisToStd
525
- #
526
- # hamBasisMxs = self.ham_basis.elements
527
- # otherBasisMxs = self.other_basis.elements
528
- #
529
- # hamGens, otherGens = _ot.lindblad_error_generators(
530
- # hamBasisMxs, otherBasisMxs, normalize=False,
531
- # other_mode=self.parameterization.nonham_mode) # in std basis
532
- #
533
- # # Note: lindblad_error_generators will return sparse generators when
534
- # # given a sparse basis (or basis matrices)
535
- #
536
- # if hamGens is not None:
537
- # bsH = len(hamGens) + 1 # projection-basis size (not nec. == dim)
538
- # _ot._assert_shape(hamGens, (bsH - 1, dim, dim), sparse_bases)
539
- #
540
- # # apply basis change now, so we don't need to do so repeatedly later
541
- # if sparse_bases:
542
- # hamGens = [_mt.safe_real(_mt.safe_dot(leftTrans, _mt.safe_dot(mx, rightTrans)),
543
- # inplace=True, check=True) for mx in hamGens]
544
- # for mx in hamGens: mx.sort_indices()
545
- # # for faster addition ops in _construct_errgen_matrix
546
- # else:
547
- # #hamGens = _np.einsum("ik,akl,lj->aij", leftTrans, hamGens, rightTrans)
548
- # hamGens = _np.transpose(_np.tensordot(
549
- # _np.tensordot(leftTrans, hamGens, (1, 1)), rightTrans, (2, 0)), (1, 0, 2))
550
- # else:
551
- # bsH = 0
552
- # assert(bsH == self.ham_basis_size)
553
- #
554
- # if otherGens is not None:
555
- #
556
- # if self.parameterization.nonham_mode == "diagonal":
557
- # bsO = len(otherGens) + 1 # projection-basis size (not nec. == dim)
558
- # _ot._assert_shape(otherGens, (bsO - 1, dim, dim), sparse_bases)
559
- #
560
- # # apply basis change now, so we don't need to do so repeatedly later
561
- # if sparse_bases:
562
- # otherGens = [_mt.safe_real(_mt.safe_dot(leftTrans, _mt.safe_dot(mx, rightTrans)),
563
- # inplace=True, check=True) for mx in otherGens]
564
- # for mx in otherGens: mx.sort_indices()
565
- # # for faster addition ops in _construct_errgen_matrix
566
- # else:
567
- # #otherGens = _np.einsum("ik,akl,lj->aij", leftTrans, otherGens, rightTrans)
568
- # otherGens = _np.transpose(_np.tensordot(
569
- # _np.tensordot(leftTrans, otherGens, (1, 1)), rightTrans, (2, 0)), (1, 0, 2))
570
- #
571
- # elif self.parameterization.nonham_mode == "diag_affine":
572
- # # projection-basis size (not nec. == dim) [~shape[1] but works for lists too]
573
- # bsO = len(otherGens[0]) + 1
574
- # _ot._assert_shape(otherGens, (2, bsO - 1, dim, dim), sparse_bases)
575
- #
576
- # # apply basis change now, so we don't need to do so repeatedly later
577
- # if sparse_bases:
578
- # otherGens = [[_mt.safe_dot(leftTrans, _mt.safe_dot(mx, rightTrans))
579
- # for mx in mxRow] for mxRow in otherGens]
580
- #
581
- # for mxRow in otherGens:
582
- # for mx in mxRow: mx.sort_indices()
583
- # # for faster addition ops in _construct_errgen_matrix
584
- # else:
585
- # #otherGens = _np.einsum("ik,abkl,lj->abij", leftTrans,
586
- # # otherGens, rightTrans)
587
- # otherGens = _np.transpose(_np.tensordot(
588
- # _np.tensordot(leftTrans, otherGens, (1, 2)), rightTrans, (3, 0)), (1, 2, 0, 3))
589
- #
590
- # else:
591
- # bsO = len(otherGens) + 1 # projection-basis size (not nec. == dim)
592
- # _ot._assert_shape(otherGens, (bsO - 1, bsO - 1, dim, dim), sparse_bases)
593
- #
594
- # # apply basis change now, so we don't need to do so repeatedly later
595
- # if sparse_bases:
596
- # otherGens = [[_mt.safe_dot(leftTrans, _mt.safe_dot(mx, rightTrans))
597
- # for mx in mxRow] for mxRow in otherGens]
598
- # #Note: complex OK here, as only linear combos of otherGens (like (i,j) + (j,i)
599
- # # terms) need to be real
600
- #
601
- # for mxRow in otherGens:
602
- # for mx in mxRow: mx.sort_indices()
603
- # # for faster addition ops in _construct_errgen_matrix
604
- # else:
605
- # #otherGens = _np.einsum("ik,abkl,lj->abij", leftTrans,
606
- # # otherGens, rightTrans)
607
- # otherGens = _np.transpose(_np.tensordot(
608
- # _np.tensordot(leftTrans, otherGens, (1, 2)), rightTrans, (3, 0)), (1, 2, 0, 3))
609
- #
610
- # else:
611
- # bsO = 0
612
- # assert(bsO == self.other_basis_size)
613
- #
614
- # if hamGens is not None:
615
- # hamGens_1norms = _np.array([_mt.safe_onenorm(mx) for mx in hamGens], 'd')
616
- # else:
617
- # hamGens_1norms = None
618
- #
619
- # if otherGens is not None:
620
- # if self.parameterization.nonham_mode == "diagonal":
621
- # otherGens_1norms = _np.array([_mt.safe_onenorm(mx) for mx in otherGens], 'd')
622
- # else:
623
- # otherGens_1norms = _np.array([_mt.safe_onenorm(mx)
624
- # for oGenRow in otherGens for mx in oGenRow], 'd')
625
- # else:
626
- # otherGens_1norms = None
627
- #
628
- # self._generators_cache[cache_key] = (hamGens, otherGens, hamGens_1norms, otherGens_1norms)
629
- #
630
- # cached_hamGens, cached_otherGens, cached_h1norms, cached_o1norms = self._generators_cache[cache_key]
631
- # return (_copy.deepcopy(cached_hamGens), _copy.deepcopy(cached_otherGens),
632
- # cached_h1norms.copy() if (cached_h1norms is not None) else None,
633
- # cached_o1norms.copy() if (cached_o1norms is not None) else None)
540
+
541
+ # Done with __init__(...)
634
542
 
635
543
  def _init_terms(self, coefficient_blocks, max_polynomial_vars):
636
544
 
@@ -732,17 +640,16 @@ class LindbladErrorgen(_LinearOperator):
732
640
  # __init__, so we just update the *data* array).
733
641
  self._rep.data[:] = data.real
734
642
 
735
- else: # dense matrices
736
- lnd_error_gen = sum([_np.tensordot(blk.block_data.flat, Lterm_superops, (0, 0)) for blk, (Lterm_superops, _)
737
- in zip(self.coefficient_blocks, self.lindblad_term_superops_and_1norms)])
738
-
739
- assert(_np.isclose(_np.linalg.norm(lnd_error_gen.imag), 0)), \
643
+ else: # dense matrices
644
+ comb_blk_datas = _np.concatenate([blk.block_data.ravel() for blk in self.coefficient_blocks])
645
+ lnd_error_gen = _np.einsum('i,ijk->jk', comb_blk_datas, self.combined_lindblad_term_superops)
646
+
647
+ #This test has been previously commented out in the sparse case, should we do the same for this one?
648
+ assert(_np.linalg.norm(lnd_error_gen.imag)<1e-10), \
740
649
  "Imaginary error gen norm: %g" % _np.linalg.norm(lnd_error_gen.imag)
741
- #print("errgen pre-real = \n"); _mt.print_mx(lnd_error_gen,width=4,prec=1)
742
650
  self._rep.base[:, :] = lnd_error_gen.real
743
651
 
744
652
  self._onenorm_upbound = onenorm
745
- #assert(self._onenorm_upbound >= _np.linalg.norm(self.to_dense(), ord=1) - 1e-6) #DEBUG
746
653
 
747
654
  def to_dense(self, on_space='minimal'):
748
655
  """
@@ -762,10 +669,10 @@ class LindbladErrorgen(_LinearOperator):
762
669
  """
763
670
  if self._rep_type == 'lindblad errorgen':
764
671
  assert(on_space in ('minimal', 'HilbertSchmidt'))
765
- lnd_error_gen = sum([_np.tensordot(blk.block_data.flat, Lterm_superops, (0, 0)) for blk, (Lterm_superops, _)
766
- in zip(self.coefficient_blocks, self.lindblad_term_superops_and_1norms)])
672
+ comb_blk_datas = _np.concatenate([blk.block_data.ravel() for blk in self.coefficient_blocks])
673
+ lnd_error_gen = _np.einsum('i,ijk->jk', comb_blk_datas, self.combined_lindblad_term_superops)
767
674
 
768
- assert(_np.isclose(_np.linalg.norm(lnd_error_gen.imag), 0)), \
675
+ assert(_np.linalg.norm(lnd_error_gen.imag)<1e-10), \
769
676
  "Imaginary error gen norm: %g" % _np.linalg.norm(lnd_error_gen.imag)
770
677
  return lnd_error_gen.real
771
678
 
@@ -791,30 +698,6 @@ class LindbladErrorgen(_LinearOperator):
791
698
  else: # dense rep
792
699
  return _sps.csr_matrix(self.to_dense(on_space))
793
700
 
794
- #def torep(self):
795
- # """
796
- # Return a "representation" object for this error generator.
797
- #
798
- # Such objects are primarily used internally by pyGSTi to compute
799
- # things like probabilities more efficiently.
800
- #
801
- # Returns
802
- # -------
803
- # OpRep
804
- # """
805
- # if self._evotype == "densitymx":
806
- # if self._rep_type == 'sparse superop':
807
- # A = self.err_gen_mx
808
- # return replib.DMOpRepSparse(
809
- # _np.ascontiguousarray(A.data),
810
- # _np.ascontiguousarray(A.indices, _np.int64),
811
- # _np.ascontiguousarray(A.indptr, _np.int64))
812
- # else:
813
- # return replib.DMOpRepDense(_np.ascontiguousarray(self.err_gen_mx, 'd'))
814
- # else:
815
- # raise NotImplementedError("torep(%s) not implemented for %s objects!" %
816
- # (self._evotype, self.__class__.__name__))
817
-
818
701
  def taylor_order_terms(self, order, max_polynomial_vars=100, return_coeff_polys=False):
819
702
  """
820
703
  Get the `order`-th order Taylor-expansion terms of this operation.
@@ -863,11 +746,6 @@ class LindbladErrorgen(_LinearOperator):
863
746
  self._rep.Lterms, self._rep.Lterm_coeffs = self._init_terms(Lblocks, max_polynomial_vars)
864
747
  return self._rep.Lterms # terms with local-index polynomial coefficients
865
748
 
866
- #def get_direct_order_terms(self, order): # , order_base=None - unused currently b/c order is always 0...
867
- # v = self.to_vector()
868
- # poly_terms = self.get_taylor_order_terms(order)
869
- # return [ term.evaluate_coeff(v) for term in poly_terms ]
870
-
871
749
  @property
872
750
  def total_term_magnitude(self):
873
751
  """
@@ -995,7 +873,6 @@ class LindbladErrorgen(_LinearOperator):
995
873
 
996
874
  def coefficients(self, return_basis=False, logscale_nonham=False):
997
875
  """
998
- TODO: docstring
999
876
  Constructs a dictionary of the Lindblad-error-generator coefficients of this error generator.
1000
877
 
1001
878
  Note that these are not necessarily the parameter values, as these
@@ -1022,12 +899,10 @@ class LindbladErrorgen(_LinearOperator):
1022
899
  Ltermdict : dict
1023
900
  Keys are `(termType, basisLabel1, <basisLabel2>)`
1024
901
  tuples, where `termType` is `"H"` (Hamiltonian), `"S"` (Stochastic),
1025
- or `"A"` (Affine). Hamiltonian and Affine terms always have a
1026
- single basis label (so key is a 2-tuple) whereas Stochastic tuples
1027
- have 1 basis label to indicate a *diagonal* term and otherwise have
1028
- 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
1029
- terms. Basis labels are integers starting at 0. Values are complex
1030
- coefficients.
902
+ `"C"` (Correlation) or `"A"` (Active). Hamiltonian and Stochastic terms
903
+ always have a single basis label (so key is a 2-tuple) whereas C and A tuples
904
+ have 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
905
+ terms. Basis labels are pauli strings. Values are coefficients.
1031
906
  basis : Basis
1032
907
  A Basis mapping the basis labels used in the
1033
908
  keys of `Ltermdict` to basis matrices.
@@ -1155,15 +1030,14 @@ class LindbladErrorgen(_LinearOperator):
1155
1030
 
1156
1031
  Returns
1157
1032
  -------
1158
- lindblad_term_dict : dict
1033
+ Ltermdict : dict
1159
1034
  Keys are `(termType, basisLabel1, <basisLabel2>)`
1160
1035
  tuples, where `termType` is `"H"` (Hamiltonian), `"S"` (Stochastic),
1161
- or `"A"` (Affine). Hamiltonian and Affine terms always have a
1162
- single basis label (so key is a 2-tuple) whereas Stochastic tuples
1163
- have 1 basis label to indicate a *diagonal* term and otherwise have
1164
- 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
1165
- terms. Values are real error rates except for the 2-basis-label
1166
- case.
1036
+ `"C"` (Correlation) or `"A"` (Active). Hamiltonian and Stochastic terms
1037
+ always have a single basis label (so key is a 2-tuple) whereas C and A tuples
1038
+ have 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
1039
+ terms. Basis labels are pauli strings. Values are coefficients.
1040
+ Values are real error rates except for the 2-basis-label case.
1167
1041
  """
1168
1042
  return self.coefficients(return_basis=False, logscale_nonham=True)
1169
1043
 
@@ -1171,7 +1045,6 @@ class LindbladErrorgen(_LinearOperator):
1171
1045
  """
1172
1046
  Sets the coefficients of elementary error generator terms in this error generator.
1173
1047
 
1174
- TODO: docstring update
1175
1048
  The dictionary `lindblad_term_dict` has tuple-keys describing the type
1176
1049
  of term and the basis elements used to construct it, e.g. `('H','X')`.
1177
1050
 
@@ -1180,12 +1053,10 @@ class LindbladErrorgen(_LinearOperator):
1180
1053
  lindblad_term_dict : dict
1181
1054
  Keys are `(termType, basisLabel1, <basisLabel2>)`
1182
1055
  tuples, where `termType` is `"H"` (Hamiltonian), `"S"` (Stochastic),
1183
- or `"A"` (Affine). Hamiltonian and Affine terms always have a
1184
- single basis label (so key is a 2-tuple) whereas Stochastic tuples
1185
- have 1 basis label to indicate a *diagonal* term and otherwise have
1186
- 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
1187
- terms. Values are the coefficients of these error generators,
1188
- and should be real except for the 2-basis-label case.
1056
+ `"C"` (Correlation) or `"A"` (Active). Hamiltonian and Stochastic terms
1057
+ always have a single basis label (so key is a 2-tuple) whereas C and A tuples
1058
+ have 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
1059
+ terms. Basis labels are pauli strings.
1189
1060
 
1190
1061
  action : {"update","add","reset"}
1191
1062
  How the values in `lindblad_term_dict` should be combined with existing
@@ -1260,7 +1131,6 @@ class LindbladErrorgen(_LinearOperator):
1260
1131
  """
1261
1132
  Sets the coeffcients of elementary error generator terms in this error generator.
1262
1133
 
1263
- TODO: update docstring
1264
1134
  Coefficients are set so that the contributions of the resulting
1265
1135
  channel's error rate are given by the values in `lindblad_term_dict`.
1266
1136
  See :meth:`error_rates` for more details.
@@ -1270,12 +1140,10 @@ class LindbladErrorgen(_LinearOperator):
1270
1140
  lindblad_term_dict : dict
1271
1141
  Keys are `(termType, basisLabel1, <basisLabel2>)`
1272
1142
  tuples, where `termType` is `"H"` (Hamiltonian), `"S"` (Stochastic),
1273
- or `"A"` (Affine). Hamiltonian and Affine terms always have a
1274
- single basis label (so key is a 2-tuple) whereas Stochastic tuples
1275
- have 1 basis label to indicate a *diagonal* term and otherwise have
1276
- 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
1277
- terms. Values are real error rates except for the 2-basis-label
1278
- case, when they may be complex.
1143
+ `"C"` (Correlation) or `"A"` (Active). Hamiltonian and Stochastic terms
1144
+ always have a single basis label (so key is a 2-tuple) whereas C and A tuples
1145
+ have 2 basis labels to specify off-diagonal non-Hamiltonian Lindblad
1146
+ terms. Basis labels are pauli strings.
1279
1147
 
1280
1148
  action : {"update","add","reset"}
1281
1149
  How the values in `lindblad_term_dict` should be combined with existing
@@ -1289,7 +1157,19 @@ class LindbladErrorgen(_LinearOperator):
1289
1157
 
1290
1158
  def coefficient_weights(self, weights):
1291
1159
  """
1292
- TODO: docstring
1160
+ Get the non-default coefficient weights.
1161
+
1162
+ This method returns a dictionary of coefficient weights that are not equal to the default value of 1.0.
1163
+
1164
+ Parameters
1165
+ ----------
1166
+ weights : dict
1167
+ A dictionary where keys are coefficient labels and values are the corresponding weights.
1168
+
1169
+ Returns
1170
+ -------
1171
+ dict
1172
+ A dictionary where keys are coefficient labels and values are the corresponding weights that are not equal to 1.0.
1293
1173
  """
1294
1174
  coeff_labels = self.coefficient_labels()
1295
1175
  lbl_lookup = {i: lbl for i, lbl in enumerate(coeff_labels)}
@@ -1305,7 +1185,15 @@ class LindbladErrorgen(_LinearOperator):
1305
1185
 
1306
1186
  def set_coefficient_weights(self, weights):
1307
1187
  """
1308
- TODO: docstring
1188
+ Set the coefficient weights.
1189
+
1190
+ This method sets the weights for the coefficients of the error generator. If the coefficient weights
1191
+ array is not initialized, it initializes it to an array of ones.
1192
+
1193
+ Parameters
1194
+ ----------
1195
+ weights : dict
1196
+ A dictionary where keys are coefficient labels and values are the corresponding weights to set.
1309
1197
  """
1310
1198
  coeff_labels = self.coefficient_labels()
1311
1199
  ilbl_lookup = {lbl: i for i, lbl in enumerate(coeff_labels)}
@@ -1341,7 +1229,7 @@ class LindbladErrorgen(_LinearOperator):
1341
1229
 
1342
1230
  #conjugate Lindbladian exponent by U:
1343
1231
  err_gen_mx = self.to_sparse() if self._rep_type == 'sparse superop' else self.to_dense()
1344
- err_gen_mx = _mt.safe_dot(Uinv, _mt.safe_dot(err_gen_mx, U))
1232
+ err_gen_mx = Uinv @ (err_gen_mx @ U)
1345
1233
  trunc = 1e-6 if isinstance(s, _gaugegroup.UnitaryGaugeGroupElement) else False
1346
1234
  self._set_params_from_matrix(err_gen_mx, truncate=trunc)
1347
1235
  self.dirty = True
@@ -1356,56 +1244,6 @@ class LindbladErrorgen(_LinearOperator):
1356
1244
  raise ValueError("Invalid transform for this LindbladErrorgen: type %s"
1357
1245
  % str(type(s)))
1358
1246
 
1359
- #I don't think this is ever needed
1360
- #def spam_transform_inplace(self, s, typ):
1361
- # """
1362
- # Update operation matrix `O` with `inv(s) * O` OR `O * s`, depending on the value of `typ`.
1363
- #
1364
- # This functions as `transform_inplace(...)` but is used when this
1365
- # Lindblad-parameterized operation is used as a part of a SPAM
1366
- # vector. When `typ == "prep"`, the spam vector is assumed
1367
- # to be `rho = dot(self, <spamvec>)`, which transforms as
1368
- # `rho -> inv(s) * rho`, so `self -> inv(s) * self`. When
1369
- # `typ == "effect"`, `e.dag = dot(e.dag, self)` (not that
1370
- # `self` is NOT `self.dag` here), and `e.dag -> e.dag * s`
1371
- # so that `self -> self * s`.
1372
- #
1373
- # Parameters
1374
- # ----------
1375
- # s : GaugeGroupElement
1376
- # A gauge group element which specifies the "s" matrix
1377
- # (and it's inverse) used in the above similarity transform.
1378
- #
1379
- # typ : { 'prep', 'effect' }
1380
- # Which type of SPAM vector is being transformed (see above).
1381
- #
1382
- # Returns
1383
- # -------
1384
- # None
1385
- # """
1386
- # assert(typ in ('prep', 'effect')), "Invalid `typ` argument: %s" % typ
1387
- #
1388
- # if isinstance(s, _gaugegroup.UnitaryGaugeGroupElement) or \
1389
- # isinstance(s, _gaugegroup.TPSpamGaugeGroupElement):
1390
- # U = s.transform_matrix
1391
- # Uinv = s.transform_matrix_inverse
1392
- # err_gen_mx = self.to_sparse() if self._rep_type == 'sparse superop' else self.to_dense()
1393
- #
1394
- # #just act on postfactor and Lindbladian exponent:
1395
- # if typ == "prep":
1396
- # err_gen_mx = _mt.safe_dot(Uinv, err_gen_mx)
1397
- # else:
1398
- # err_gen_mx = _mt.safe_dot(err_gen_mx, U)
1399
- #
1400
- # self._set_params_from_matrix(err_gen_mx, truncate=True)
1401
- # self.dirty = True
1402
- # #Note: truncate=True above because some unitary transforms seem to
1403
- # ## modify eigenvalues to be negative beyond the tolerances
1404
- # ## checked when truncate == False.
1405
- # else:
1406
- # raise ValueError("Invalid transform for this LindbladDenseOp: type %s"
1407
- # % str(type(s)))
1408
-
1409
1247
  def deriv_wrt_params(self, wrt_filter=None):
1410
1248
  """
1411
1249
  The element-wise derivative this operation.
@@ -1427,8 +1265,6 @@ class LindbladErrorgen(_LinearOperator):
1427
1265
  Array of derivatives, shape == (dimension^2, num_params)
1428
1266
  """
1429
1267
  if self._rep_type == 'sparse superop':
1430
- #raise NotImplementedError(("LindbladErrorgen.deriv_wrt_params(...) can only be called "
1431
- # "when using *dense* basis elements!"))
1432
1268
  _warnings.warn("Using finite differencing to compute LindbladErrorGen derivative!")
1433
1269
  return super(LindbladErrorgen, self).deriv_wrt_params(wrt_filter)
1434
1270
 
@@ -1541,28 +1377,25 @@ class LindbladErrorgen(_LinearOperator):
1541
1377
  mm_dict = super().to_memoized_dict(mmg_memo)
1542
1378
 
1543
1379
  mm_dict['rep_type'] = self._rep_type
1544
- #OLD: mm_dict['parameterization'] = self.parameterization.to_nice_serialization()
1545
- #OLD: mm_dict['lindblad_basis'] = self.lindblad_basis.to_nice_serialization()
1546
- #OLD: mm_dict['coefficients'] = [(str(k), self._encodevalue(v)) for k, v in self.coefficients().items()]
1547
1380
  mm_dict['matrix_basis'] = self.matrix_basis.to_nice_serialization()
1548
1381
  mm_dict['coefficient_blocks'] = [blk.to_nice_serialization() for blk in self.coefficient_blocks]
1382
+ #serialize the paramval attribute. Rederiving this from the block data has been leading to sign
1383
+ #ambiguity on deserialization.
1384
+ mm_dict['paramvals'] = self._encodemx(self.paramvals)
1385
+
1549
1386
  return mm_dict
1550
1387
 
1551
1388
  @classmethod
1552
1389
  def _from_memoized_dict(cls, mm_dict, serial_memo):
1553
- #lindblad_term_dict = {_GlobalElementaryErrorgenLabel.cast(k): cls._decodevalue(v)
1554
- # for k, v in mm_dict['coefficients']} # convert keys from str->objects
1555
- #parameterization = LindbladParameterization.from_nice_serialization(mm_dict['parameterization'])
1556
- #lindblad_basis = _Basis.from_nice_serialization(mm_dict['lindblad_basis'])
1557
- #truncate = False # shouldn't need to truncate since we're reloading a valid set of coefficients
1558
1390
  mx_basis = _Basis.from_nice_serialization(mm_dict['matrix_basis'])
1559
1391
  state_space = _statespace.StateSpace.from_nice_serialization(mm_dict['state_space'])
1560
1392
  coeff_blocks = [_LindbladCoefficientBlock.from_nice_serialization(blk)
1561
1393
  for blk in mm_dict['coefficient_blocks']]
1562
-
1563
- return cls(coeff_blocks, 'auto', mx_basis, mm_dict['evotype'], state_space)
1564
- #return cls(lindblad_term_dict, parameterization, lindblad_basis,
1565
- # mx_basis, truncate, mm_dict['evotype'], state_space)
1394
+ ret = cls(coeff_blocks, 'auto', mx_basis, mm_dict['evotype'], state_space)
1395
+ #reinitialize the paramvals attribute from memoized dict. Rederiving this from the block data has
1396
+ #been leading to sign ambiguity on deserialization.
1397
+ ret.paramvals = ret._decodemx(mm_dict['paramvals'])
1398
+ return ret
1566
1399
 
1567
1400
  def _is_similar(self, other, rtol, atol):
1568
1401
  """ Returns True if `other` model member (which it guaranteed to be the same type as self) has
@@ -1629,7 +1462,7 @@ class LindbladParameterization(_NicelySerializable):
1629
1462
  errs : dict
1630
1463
  Error dictionary with keys as `(termType, basisLabel)` tuples, where
1631
1464
  `termType` can be `"H"` (Hamiltonian), `"S"` (Stochastic), or `"A"`
1632
- (Affine), and `basisLabel` is a string of I, X, Y, or Z to describe a
1465
+ (Active), and `basisLabel` is a string of I, X, Y, or Z, or to describe a
1633
1466
  Pauli basis element appropriate for the gate (i.e. having the same
1634
1467
  number of letters as there are qubits in the gate). For example, you
1635
1468
  could specify a 0.01-radian Z-rotation error and 0.05 rate of Pauli-
@@ -1717,12 +1550,6 @@ class LindbladParameterization(_NicelySerializable):
1717
1550
  self.abbrev = abbrev
1718
1551
  self.meta = meta
1719
1552
 
1720
- #REMOVE
1721
- #self.nonham_block_type = nonham_block_type #nonham_mode
1722
- #self.nonham_param_mode = nonham_param_mode #param_mode
1723
- #self.include_ham_block = include_ham_block #ham_params_allowed = ham_params_allowed
1724
- #self.include_nonham_block = include_nonham_block #nonham_params_allowed = nonham_params_allowed
1725
-
1726
1553
  def __hash__(self):
1727
1554
  return hash((self.block_types, self.param_modes))
1728
1555