pyGSTi 0.9.12__cp39-cp39-win_amd64.whl → 0.9.13__cp39-cp39-win_amd64.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 +197 -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.cp39-win_amd64.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.cp39-win_amd64.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.cp39-win_amd64.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.cp39-win_amd64.pyd +0 -0
  41. pygsti/evotypes/densitymx/effectreps.pyx +1 -1
  42. pygsti/evotypes/densitymx/opreps.cp39-win_amd64.pyd +0 -0
  43. pygsti/evotypes/densitymx/opreps.pyx +2 -2
  44. pygsti/evotypes/densitymx/statereps.cp39-win_amd64.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.cp39-win_amd64.pyd +0 -0
  51. pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
  52. pygsti/evotypes/stabilizer/opreps.cp39-win_amd64.pyd +0 -0
  53. pygsti/evotypes/stabilizer/opreps.pyx +0 -4
  54. pygsti/evotypes/stabilizer/statereps.cp39-win_amd64.pyd +0 -0
  55. pygsti/evotypes/stabilizer/statereps.pyx +1 -5
  56. pygsti/evotypes/stabilizer/termreps.cp39-win_amd64.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.cp39-win_amd64.pyd +0 -0
  62. pygsti/evotypes/statevec/effectreps.pyx +1 -1
  63. pygsti/evotypes/statevec/opreps.cp39-win_amd64.pyd +0 -0
  64. pygsti/evotypes/statevec/opreps.pyx +2 -2
  65. pygsti/evotypes/statevec/statereps.cp39-win_amd64.pyd +0 -0
  66. pygsti/evotypes/statevec/statereps.pyx +1 -1
  67. pygsti/evotypes/statevec/termreps.cp39-win_amd64.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.cp39-win_amd64.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.cp39-win_amd64.pyd +0 -0
  87. pygsti/forwardsims/termforwardsim_calc_statevec.cp39-win_amd64.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.cp39-win_amd64.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
@@ -44,30 +44,6 @@ class FullPureState(_DensePureState):
44
44
  self._paramlbls = _np.array(["VecElement Re(%d)" % i for i in range(self.state_space.udim)]
45
45
  + ["VecElement Im(%d)" % i for i in range(self.state_space.udim)], dtype=object)
46
46
 
47
- #REMOVE (Cannot set to arbitrary vector) - but maybe could set to pure vector?
48
- #def set_dense(self, vec):
49
- # """
50
- # Set the dense-vector value of this SPAM vector.
51
- #
52
- # Attempts to modify this SPAM vector's parameters so that the raw
53
- # SPAM vector becomes `vec`. Will raise ValueError if this operation
54
- # is not possible.
55
- #
56
- # Parameters
57
- # ----------
58
- # vec : array_like or State
59
- # A numpy array representing a SPAM vector, or a State object.
60
- #
61
- # Returns
62
- # -------
63
- # None
64
- # """
65
- # vec = State._to_vector(vec)
66
- # if(vec.size != self.dim):
67
- # raise ValueError("Argument must be length %d" % self.dim)
68
- # self._ptr[:] = vec
69
- # self.dirty = True
70
-
71
47
  @property
72
48
  def num_params(self):
73
49
  """
@@ -64,7 +64,7 @@ class EmbeddedPureState(_State):
64
64
  self.pure_state = pure_state
65
65
  self.basis = dm_basis # only used for dense conversion
66
66
 
67
- evotype = _Evotype.cast(evotype)
67
+ evotype = _Evotype.cast(evotype, state_space=self.pure_state.state_space)
68
68
  #rep = evotype.create_state_rep()
69
69
  #rep.init_from_dense_purevec(pure_state)
70
70
  raise NotImplementedError("Maybe this class isn't even needed, or need to create a static pure state class?")
@@ -350,11 +350,10 @@ class State(_modelmember.ModelMember):
350
350
  float
351
351
  """
352
352
  vec = self.to_dense(on_space='minimal')
353
- if inv_transform is None:
354
- return _ot.residuals(vec, other_spam_vec.to_dense(on_space='minimal'))
355
- else:
356
- return _ot.residuals(_np.dot(inv_transform, vec),
357
- other_spam_vec.to_dense(on_space='minimal'))
353
+ if inv_transform is not None:
354
+ vec = inv_transform @ vec
355
+ return (vec - other_spam_vec.to_dense(on_space='minimal')).ravel()
356
+
358
357
 
359
358
  def transform_inplace(self, s):
360
359
  """
@@ -573,4 +572,4 @@ class State(_modelmember.ModelMember):
573
572
  vector = _np.array(v, typ)[:, None] # make into a 2-D column vec
574
573
 
575
574
  assert(len(vector.shape) == 2 and vector.shape[1] == 1)
576
- return vector.flatten() # HACK for convention change -> (N,) instead of (N,1)
575
+ return vector.ravel() # HACK for convention change -> (N,) instead of (N,1)
@@ -11,16 +11,25 @@ The TPState class and supporting functionality.
11
11
  #***************************************************************************************************
12
12
 
13
13
 
14
- import numpy as _np
14
+ from __future__ import annotations
15
+ from typing import Tuple, TYPE_CHECKING
16
+ if TYPE_CHECKING:
17
+ import torch as _torch
18
+ try:
19
+ import torch as _torch
20
+ except ImportError:
21
+ pass
15
22
 
23
+ import numpy as _np
16
24
  from pygsti.baseobjs import Basis as _Basis
17
25
  from pygsti.baseobjs import statespace as _statespace
26
+ from pygsti.modelmembers.torchable import Torchable as _Torchable
18
27
  from pygsti.modelmembers.states.densestate import DenseState as _DenseState
19
28
  from pygsti.modelmembers.states.state import State as _State
20
29
  from pygsti.baseobjs.protectedarray import ProtectedArray as _ProtectedArray
21
30
 
22
31
 
23
- class TPState(_DenseState):
32
+ class TPState(_DenseState, _Torchable):
24
33
  """
25
34
  A fixed-unit-trace state vector.
26
35
 
@@ -57,15 +66,14 @@ class TPState(_DenseState):
57
66
  # alpha = 1/sqrt(d) = 1/(len(vec)**0.25).
58
67
  def __init__(self, vec, basis=None, evotype="default", state_space=None):
59
68
  vector = _State._to_vector(vec)
60
- if basis is not None:
61
- if not isinstance(basis, _Basis):
62
- basis = _Basis.cast(basis, len(vector)) # don't perform this cast if we're given a basis
63
- firstEl = basis.elsize**-0.25 # not dim, as the dimension of the vector space may be less
64
- if not _np.isclose(vector[0], firstEl):
65
- raise ValueError("Cannot create TPState: first element must equal %g!" % firstEl)
66
- # if basis is None, don't check first element (hackfor de-serialization, so we don't need to store basis)
67
-
69
+ if basis is None:
70
+ dim = vector.size
71
+ basis = 'pp' if int(2**_np.log2(dim)) == dim else 'gm'
68
72
  _DenseState.__init__(self, vector, basis, evotype, state_space)
73
+ basis = self._basis # <-- __init__ ensures that self._basis is a Basis object.
74
+ firstEl = basis.elsize ** -0.25 # <-- not dim, as the dimension of the vector space may be less
75
+ if not _np.isclose(vector[0], firstEl):
76
+ raise ValueError("Cannot create TPState: first element must equal %g!" % firstEl)
69
77
  assert(isinstance(self.columnvec, _ProtectedArray))
70
78
  self._paramlbls = _np.array(["VecElement %d" % i for i in range(1, self.dim)], dtype=object)
71
79
 
@@ -158,6 +166,16 @@ class TPState(_DenseState):
158
166
  self._ptr_has_changed()
159
167
  self.dirty = dirty_value
160
168
 
169
+ def stateless_data(self) -> Tuple[int]:
170
+ return (self.dim,)
171
+
172
+ @staticmethod
173
+ def torch_base(sd: Tuple[int], t_param: _torch.Tensor) -> _torch.Tensor:
174
+ dim = sd[0]
175
+ t_const = (dim ** -0.25) * _torch.ones(1, dtype=_torch.double)
176
+ t = _torch.concat((t_const, t_param))
177
+ return t
178
+
161
179
  def deriv_wrt_params(self, wrt_filter=None):
162
180
  """
163
181
  The element-wise derivative this state vector.
@@ -384,7 +384,7 @@ class RankOnePrepTerm(RankOneTerm, _NoMagnitude):
384
384
  -------
385
385
  RankOnePrepTerm
386
386
  """
387
- evotype = _Evotype.cast(evotype)
387
+ evotype = _Evotype.cast(evotype, state_space=state_space)
388
388
  default_basis = 'pp'
389
389
 
390
390
  if isinstance(pre_state, _mm.ModelMember):
@@ -459,7 +459,7 @@ class RankOneEffectTerm(RankOneTerm, _NoMagnitude):
459
459
  -------
460
460
  RankOneEffectTerm
461
461
  """
462
- evotype = _Evotype.cast(evotype)
462
+ evotype = _Evotype.cast(evotype, state_space=state_space)
463
463
  default_basis = 'pp'
464
464
 
465
465
  if isinstance(pre_effect, _mm.ModelMember):
@@ -534,7 +534,7 @@ class RankOneOpTerm(RankOneTerm, _NoMagnitude):
534
534
  -------
535
535
  RankOneOpTerm
536
536
  """
537
- evotype = _Evotype.cast(evotype)
537
+ evotype = _Evotype.cast(evotype, state_space=state_space)
538
538
  pre_reps = []
539
539
  post_reps = []
540
540
 
@@ -718,9 +718,6 @@ class _HasPolynomialCoefficient(object):
718
718
  """
719
719
  return _Polynomial.from_rep(self._rep.coeff)
720
720
 
721
- #def _coeff_copy(self):
722
- # return self.coeff.copy()
723
-
724
721
  def map_indices_inplace(self, mapfn):
725
722
  """
726
723
  Performs a bulk find & replace on the coefficient polynomial's variable indices.
@@ -0,0 +1,50 @@
1
+ """
2
+ Defines the interface that ModelMembers must satisfy to be compatible with
3
+ the PyTorch-backed forward simulator in pyGSTi/forwardsims/torchfwdsim.py.
4
+ """
5
+ #***************************************************************************************************
6
+ # Copyright 2024, National Technology & Engineering Solutions of Sandia, LLC (NTESS).
7
+ # Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights
8
+ # in this software.
9
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
10
+ # in compliance with the License. You may obtain a copy of the License at
11
+ # http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
12
+ #***************************************************************************************************
13
+
14
+
15
+ from __future__ import annotations
16
+ from typing import Tuple, TYPE_CHECKING
17
+ if TYPE_CHECKING:
18
+ import torch as _torch
19
+
20
+ from pygsti.modelmembers.modelmember import ModelMember
21
+
22
+
23
+ class Torchable(ModelMember):
24
+
25
+ def stateless_data(self) -> Tuple:
26
+ """
27
+ Return this ModelMember's data that is considered constant for purposes of model fitting.
28
+
29
+ Note: the word "stateless" here is used in the sense of object-oriented programming.
30
+ """
31
+ raise NotImplementedError()
32
+
33
+ @staticmethod
34
+ def torch_base(sd : Tuple, t_param : _torch.Tensor) -> _torch.Tensor:
35
+ """
36
+ Suppose "obj" is an instance of some Torchable subclass. If we compute
37
+
38
+ vec = obj.to_vector()
39
+ t_param = torch.from_numpy(vec)
40
+ sd = obj.stateless_data()
41
+ t = type(obj).torch_base(sd, t_param)
42
+
43
+ then t will be a PyTorch Tensor that represents "obj" in a canonical numerical way.
44
+
45
+ The meaning of "canonical" is implementation dependent. If type(obj) implements
46
+ the ``.base`` attribute, then a reasonable implementation will probably satisfy
47
+
48
+ np.allclose(obj.base, t.numpy()).
49
+ """
50
+ raise NotImplementedError()
@@ -129,7 +129,7 @@ class ModelPack(_ABC):
129
129
  QubitProcessorSpec
130
130
  """
131
131
  static_target_model = self.target_model('static', qubit_labels=qubit_labels) # assumed to be an ExplicitOpModel
132
- return static_target_model.create_processor_spec(self._sslbls)
132
+ return static_target_model.create_processor_spec(qubit_labels if qubit_labels is not None else self._sslbls)
133
133
 
134
134
  def _get_cachefile_names(self, param_type, simulator):
135
135
  """ Get the standard cache file names for a modelpack """
@@ -1,7 +1,9 @@
1
1
  """
2
2
  A standard multi-qubit gate set module.
3
3
 
4
- Variables for working with the a model containing Idle, Z(pi/2) and rot(X=pi/2, Y=sqrt(3)/2) gates.
4
+ Variables for working with the a model containing Idle, Z(pi/2) and N gate, where the N gate is a
5
+ pi/2 rotation about the (np.sqrt(3)/2, 0, -1/2) axis of the Bloch sphere.
6
+ gates.
5
7
  """
6
8
  #***************************************************************************************************
7
9
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -2,7 +2,8 @@
2
2
  A standard multi-qubit gate set module.
3
3
 
4
4
  Variables for working with the 2-qubit model containing the gates
5
- I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CPHASE.
5
+ I*I, I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, X(pi/2)*X(pi/2),
6
+ Y(pi/2)*Y(pi/2), X(pi/2)*Y(pi/2), and Y(pi/2)*X(pi/2) gates.
6
7
  """
7
8
  #***************************************************************************************************
8
9
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -2,7 +2,7 @@
2
2
  A standard multi-qubit gate set module.
3
3
 
4
4
  Variables for working with the 2-qubit model containing the gates
5
- I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CPHASE.
5
+ I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I.
6
6
  """
7
7
  #***************************************************************************************************
8
8
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -17,9 +17,9 @@ from pygsti.modelpacks._modelpack import GSTModelPack
17
17
 
18
18
 
19
19
  class _Module(GSTModelPack):
20
- description = "I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CPHASE gates"
20
+ description = "I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I"
21
21
 
22
- gates = [('Gxpi2', 1), ('Gypi2', 1), ('Gxpi2', 0), ('Gypi2', 0), ('Gcphase', 0, 1)]
22
+ gates = [('Gxpi2', 1), ('Gypi2', 1), ('Gxpi2', 0), ('Gypi2', 0)]
23
23
 
24
24
  _sslbls = (0, 1)
25
25
 
@@ -2,7 +2,7 @@
2
2
  A standard multi-qubit gate set module.
3
3
 
4
4
  Variables for working with the 2-qubit model containing the gates
5
- I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CPHASE.
5
+ I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and Idle.
6
6
  """
7
7
  #***************************************************************************************************
8
8
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -19,7 +19,7 @@ from pygsti.modelpacks._modelpack import GSTModelPack
19
19
 
20
20
 
21
21
  class _Module(GSTModelPack):
22
- description = "I*I, I*X(pi/2), I*Y(pi/2), X(pi/2)*I, and Y(pi/2)*I gates"
22
+ description = "I*I, I*X(pi/2), I*Y(pi/2), X(pi/2)*I, and Y(pi/2)*I gates and Idle"
23
23
 
24
24
  gates = [(), ('Gxpi2', 1), ('Gypi2', 1), ('Gxpi2', 0), ('Gypi2', 0)]
25
25
 
@@ -2,7 +2,7 @@
2
2
  A standard multi-qubit gate set module.
3
3
 
4
4
  Variables for working with the 2-qubit model containing the gates
5
- I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CNOT.
5
+ I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, CNOT and idle.
6
6
  """
7
7
  #***************************************************************************************************
8
8
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -17,9 +17,9 @@ from pygsti.modelpacks._modelpack import GSTModelPack
17
17
 
18
18
 
19
19
  class _Module(GSTModelPack):
20
- description = "I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CNOT gates"
20
+ description = "I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, CNOT and idle gates"
21
21
 
22
- gates = [('Gxpi2', 1), ('Gypi2', 1), ('Gxpi2', 0), ('Gypi2', 0), ('Gcnot', 0, 1)]
22
+ gates = [(), ('Gxpi2', 1), ('Gypi2', 1), ('Gxpi2', 0), ('Gypi2', 0), ('Gcnot', 0, 1)]
23
23
 
24
24
  _sslbls = (0, 1)
25
25
 
@@ -2,7 +2,7 @@
2
2
  A standard multi-qubit gate set module.
3
3
 
4
4
  Variables for working with the 2-qubit model containing the gates
5
- I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CPHASE.
5
+ I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, CPHASE, and idle.
6
6
  """
7
7
  #***************************************************************************************************
8
8
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -17,9 +17,9 @@ from pygsti.modelpacks._modelpack import GSTModelPack
17
17
 
18
18
 
19
19
  class _Module(GSTModelPack):
20
- description = "I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CPHASE gates"
20
+ description = "I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, CPHASE and idle gates"
21
21
 
22
- gates = [('Gxpi2', 1), ('Gypi2', 1), ('Gxpi2', 0), ('Gypi2', 0), ('Gcphase', 0, 1)]
22
+ gates = [(), ('Gxpi2', 1), ('Gypi2', 1), ('Gxpi2', 0), ('Gypi2', 0), ('Gcphase', 0, 1)]
23
23
 
24
24
  _sslbls = (0, 1)
25
25
 
@@ -2,7 +2,7 @@
2
2
  A standard multi-qubit gate set module.
3
3
 
4
4
  Variables for working with the 2-qubit model containing the gates
5
- I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CNOT.
5
+ I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and XX gates
6
6
  """
7
7
  #***************************************************************************************************
8
8
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -2,7 +2,7 @@
2
2
  A standard multi-qubit gate set module.
3
3
 
4
4
  Variables for working with the 2-qubit model containing the gates
5
- I*X(pi/2), I*Y(pi/2), I*Z(pi/2), X(pi/2)*I, Y(pi/2)*I, Z(pi/2)*I and CNOT.
5
+ I*X(pi/2), I*Y(pi/2), I*Z(pi/2), X(pi/2)*I, Y(pi/2)*I, Z(pi/2)*I, CNOT and idle.
6
6
  """
7
7
  #***************************************************************************************************
8
8
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -17,9 +17,9 @@ from pygsti.modelpacks._modelpack import GSTModelPack
17
17
 
18
18
 
19
19
  class _Module(GSTModelPack):
20
- description = "I*X(pi/2), I*Y(pi/2), I*Z(pi/2), X(pi/2)*I, Y(pi/2)*I, Z(pi/2)*I and CNOT gates"
20
+ description = "I*X(pi/2), I*Y(pi/2), I*Z(pi/2), X(pi/2)*I, Y(pi/2)*I, Z(pi/2)*I, CNOT and idle gates"
21
21
 
22
- gates = [('Gxpi2', 1), ('Gypi2', 1), ('Gzpi2', 1), ('Gxpi2', 0), ('Gypi2', 0), ('Gzpi2', 0), ('Gcnot', 0, 1)]
22
+ gates = [(), ('Gxpi2', 1), ('Gypi2', 1), ('Gzpi2', 1), ('Gxpi2', 0), ('Gypi2', 0), ('Gzpi2', 0), ('Gcnot', 0, 1)]
23
23
 
24
24
  _sslbls = (0, 1)
25
25
 
@@ -2,7 +2,7 @@
2
2
  A standard multi-qubit gate set module.
3
3
 
4
4
  Variables for working with the 2-qubit model containing the gates
5
- I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and CNOT.
5
+ I*X(pi/2), I*Y(pi/2), X(pi/2)*I, Y(pi/2)*I, and ZZ gates.
6
6
  """
7
7
  #***************************************************************************************************
8
8
  # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
@@ -42,127 +42,6 @@ def _get_cachefile_names(std_module, param_type, simulator, py_version):
42
42
  raise ValueError("No cache files used for param-type=%s" % param_type)
43
43
 
44
44
 
45
- # XXX is this used?
46
- # def _make_hs_cache_for_std_model(std_module, term_order, max_length, json_too=False, comm=None):
47
- # """
48
- # A utility routine to for creating the term-based cache files for a standard module
49
- # """
50
- # target_model = std_module.target_model()
51
- # prep_fiducials = std_module.prepStrs
52
- # effect_fiducials = std_module.effectStrs
53
- # germs = std_module.germs
54
- #
55
- # x = 1
56
- # maxLengths = []
57
- # while(x <= max_length):
58
- # maxLengths.append(x)
59
- # x *= 2
60
- #
61
- # listOfExperiments = _stdlists.create_lsgst_circuits(
62
- # target_model, prep_fiducials, effect_fiducials, germs, maxLengths)
63
- #
64
- # mdl_terms = target_model.copy()
65
- # mdl_terms.set_all_parameterizations("H+S terms") # CPTP terms?
66
- # my_calc_cache = {}
67
- # mdl_terms.sim = _TermFSim(mode="taylor", max_order=term_order, cache=my_calc_cache)
68
- #
69
- # comm_method = "scheduler"
70
- # if comm is not None and comm.Get_size() > 1 and comm_method == "scheduler":
71
- # from mpi4py import MPI # just needed for MPI.SOURCE below
72
- #
73
- # #Alternate: use rank0 as "scheduler"
74
- # rank = 0 if (comm is None) else comm.Get_rank()
75
- # nprocs = 1 if (comm is None) else comm.Get_size()
76
- # N = len(listOfExperiments); cur_index = 0; active_workers = nprocs - 1
77
- # buf = _np.zeros(1, _np.int64) # use buffer b/c mpi4py .send/.recv seem buggy
78
- # if rank == 0:
79
- # # ** I am the scheduler **
80
- # # Give each "worker" rank an initial index to compute
81
- # for i in range(1, nprocs):
82
- # if cur_index == N: # there are more procs than items - just send -1 index to mean "you're done!"
83
- # buf[0] = -1
84
- # comm.Send(buf, dest=i, tag=1) # tag == 1 => scheduler to worker
85
- # active_workers -= 1
86
- # else:
87
- # buf[0] = cur_index
88
- # comm.Send(buf, dest=i, tag=1); cur_index += 1
89
- #
90
- # # while there are active workers keep dishing out indices
91
- # while active_workers > 0:
92
- # comm.Recv(buf, source=MPI.ANY_SOURCE, tag=2) # worker requesting assignment
93
- # worker_rank = buf[0]
94
- # if cur_index == N: # nothing more to do: just send -1 index to mean "you're done!"
95
- # buf[0] = -1
96
- # comm.Send(buf, dest=worker_rank, tag=1) # tag == 1 => scheduler to worker
97
- # active_workers -= 1
98
- # else:
99
- # buf[0] = cur_index
100
- # comm.Send(buf, dest=worker_rank, tag=1)
101
- # cur_index += 1
102
- #
103
- # else:
104
- # # ** I am a worker **
105
- # comm.Recv(buf, source=0, tag=1)
106
- # index_to_compute = buf[0]
107
- #
108
- # while index_to_compute >= 0:
109
- # print("Worker %d computing prob %d of %d" % (rank, index_to_compute, N))
110
- # t0 = _time.time()
111
- # mdl_terms.probabilities(listOfExperiments[index_to_compute])
112
- # print("Worker %d finished computing prob %d in %.2fs" % (rank, index_to_compute, _time.time() - t0))
113
- #
114
- # buf[0] = rank
115
- # comm.Send(buf, dest=0, tag=2) # tag == 2 => worker requests next assignment
116
- # comm.Recv(buf, source=0, tag=1)
117
- # index_to_compute = buf[0]
118
- #
119
- # print("Rank %d at barrier" % rank)
120
- # comm.barrier() # wait here until all workers and scheduler are done
121
- #
122
- # else:
123
- #
124
- # #divide up strings among ranks
125
- # my_expList, _, _ = _mpit.distribute_indices(listOfExperiments, comm, False)
126
- # rankStr = "" if (comm is None) else "Rank%d: " % comm.Get_rank()
127
- #
128
- # if comm is not None and comm.Get_rank() == 0:
129
- # print("%d circuits divided among %d processors" % (len(listOfExperiments), comm.Get_size()))
130
- #
131
- # t0 = _time.time()
132
- # for i, opstr in enumerate(my_expList):
133
- # print("%s%.2fs: Computing prob %d of %d" % (rankStr, _time.time() - t0, i, len(my_expList)))
134
- # mdl_terms.probabilities(opstr)
135
- # #mdl_terms.bulk_probs(my_expList) # also fills cache, but allocs more mem at once
136
- #
137
- # py_version = 3 if (_sys.version_info > (3, 0)) else 2
138
- # key_fn, val_fn = _get_cachefile_names(std_module, "H+S terms",
139
- # "termorder:%d" % term_order, py_version)
140
- # _write_calccache(my_calc_cache, key_fn, val_fn, json_too, comm)
141
- #
142
- # if comm is None or comm.Get_rank() == 0:
143
- # print("Completed in %.2fs" % (_time.time() - t0))
144
- # print("Num of Experiments = ", len(listOfExperiments))
145
- #
146
- # #if comm is None:
147
- # # calcc_list = [ my_calc_cache ]
148
- # #else:
149
- # # calcc_list = comm.gather(my_calc_cache, root=0)
150
- # #
151
- # #if comm is None or comm.Get_rank() == 0:
152
- # # calc_cache = {}
153
- # # for c in calcc_list:
154
- # # calc_cache.update(c)
155
- # #
156
- # # print("Completed in %.2fs" % (_time.time()-t0))
157
- # # print("Cachesize = ",len(calc_cache))
158
- # # print("Num of Experiments = ", len(listOfExperiments))
159
- # #
160
- # # py_version = 3 if (_sys.version_info > (3, 0)) else 2
161
- # # key_fn, val_fn = _get_cachefile_names(std_module, "H+S terms",
162
- # # "termorder:%d" % term_order,py_version)
163
- # # _write_calccache(calc_cache, key_fn, val_fn, json_too, comm)
164
-
165
-
166
45
  # XXX apparently only used from _make_hs_cache_for_std_model which itself looks unused
167
46
  def _write_calccache(calc_cache, key_fn, val_fn, json_too=False, comm=None):
168
47
  """
@@ -156,8 +156,7 @@ class CloudNoiseModel(_ImplicitOpModel):
156
156
 
157
157
  simulator = _FSim.cast(simulator,
158
158
  state_space.num_qubits if isinstance(state_space, _statespace.QubitSpace) else None)
159
- prefer_dense_reps = isinstance(simulator, _MatrixFSim)
160
- evotype = _Evotype.cast(evotype, default_prefer_dense_reps=prefer_dense_reps)
159
+ evotype = _Evotype.cast(evotype, state_space=state_space)
161
160
 
162
161
  # Build gate dictionaries. A value of `gatedict` can be an array, a LinearOperator, or an OpFactory.
163
162
  # For later processing, we'll create mm_gatedict to contain each item as a ModelMember. For cloud-
@@ -283,7 +283,7 @@ class ExplicitOpModelCalc(object):
283
283
  wt * Evec.residuals(other_calc.effects[lbl]))
284
284
  nSummands += wt**2 * Evec.dim
285
285
 
286
- resids = [r.flatten() for r in resids]
286
+ resids = [r.ravel() for r in resids]
287
287
  resids = _np.concatenate(resids)
288
288
  return resids, nSummands
289
289
 
@@ -545,7 +545,7 @@ class ExplicitOpModelCalc(object):
545
545
  # parameterization object, which gives a vector of length
546
546
  # equal to the number of model *elements*.
547
547
  to_vector = _np.concatenate(
548
- [obj.flatten() for obj in _itertools.chain(
548
+ [obj.ravel() for obj in _itertools.chain(
549
549
  mdlDeriv_preps.values(), mdlDeriv_effects.values(),
550
550
  mdlDeriv_ops.values())], axis=0)
551
551
  dPG[:, nParams + i * dim + j] = to_vector
@@ -688,7 +688,7 @@ class ExplicitOpModelCalc(object):
688
688
  - unitMx_i @ gate @ unitMx_j - unitMx_j @ gate @ unitMx_i
689
689
 
690
690
  to_vector = _np.concatenate(
691
- [obj.flatten() for obj in _itertools.chain(
691
+ [obj.ravel() for obj in _itertools.chain(
692
692
  mdlHess_preps.values(), mdlHess_effects.values(),
693
693
  mdlHess_ops.values())], axis=0)
694
694
  Heps[:, i1 * dim + i2, j1 * dim + j2] = to_vector
@@ -186,16 +186,6 @@ class ExplicitOpModel(_mdl.OpModel):
186
186
  return _explicitcalc.ExplicitOpModelCalc(self.state_space.dim, simplified_preps, simplified_ops,
187
187
  simplified_effects, self.num_params, self._param_interposer)
188
188
 
189
- #Unneeded - just use string processing & rely on effect labels *not* having underscores in them
190
- #def simplify_spamtuple_to_outcome_label(self, simplified_spamTuple):
191
- # #TODO: make this more efficient (prep lbl isn't even used!)
192
- # for prep_lbl in self.preps:
193
- # for povm_lbl in self.povms:
194
- # for elbl in self.povms[povm_lbl]:
195
- # if simplified_spamTuple == (prep_lbl, povm_lbl + "_" + elbl):
196
- # return (elbl,) # outcome "label" (a tuple)
197
- # raise ValueError("No outcome label found for simplified spam_tuple: ", simplified_spamTuple)
198
-
199
189
  def _embed_operation(self, op_target_labels, op_val, force=False):
200
190
  """
201
191
  Called by OrderedMemberDict._auto_embed to create an embedded-gate
@@ -909,7 +899,7 @@ class ExplicitOpModel(_mdl.OpModel):
909
899
  for lbl, inst in self.instruments.items():
910
900
  s += "%s = " % str(lbl) + str(inst) + "\n"
911
901
  for lbl, factory in self.factories.items():
912
- s += "%s = (factory)" % lbl + '\n'
902
+ s += "%s = (factory)" % str(lbl) + '\n'
913
903
  s += "\n"
914
904
 
915
905
  return s
@@ -1521,11 +1511,11 @@ class ExplicitOpModel(_mdl.OpModel):
1521
1511
  return U_extracted
1522
1512
 
1523
1513
  def add_availability(opkey, op):
1524
- if opkey == _Label(()) or opkey.is_simple():
1514
+ if opkey == _Label(()) or opkey.is_simple:
1525
1515
  if opkey == _Label(()): # special case: turn empty tuple labels into "{idle}" gate in processor spec
1526
1516
  gn = "{idle}"
1527
1517
  sslbls = None
1528
- elif opkey.is_simple():
1518
+ elif opkey.is_simple:
1529
1519
  gn = opkey.name
1530
1520
  sslbls = opkey.sslbls
1531
1521
  #if sslbls is not None:
@@ -265,8 +265,9 @@ class FirstOrderGaugeInvariantStore(object):
265
265
  errorgen_vec = _np.zeros(self.errorgen_space_dim, 'd')
266
266
  for i, (op_label, elem_lbl) in enumerate(self.errorgen_space_op_elem_labels):
267
267
  errorgen_vec[i] += op_coeffs[op_label].get(elem_lbl, 0.0)
268
- return self.errorgen_vec_to_fogi_components_array(errorgen_vec), \
269
- self.errorgen_vec_to_fogv_components_array(errorgen_vec)
268
+ out1 = self.errorgen_vec_to_fogi_components_array(errorgen_vec)
269
+ out2 = self.errorgen_vec_to_fogv_components_array(errorgen_vec)
270
+ return out1, out2
270
271
 
271
272
  def fogi_components_array_to_errorgen_vec(self, fogi_components):
272
273
  assert(self._dependent_fogi_action == 'drop'), \
@@ -547,7 +548,8 @@ class FirstOrderGaugeInvariantStore(object):
547
548
  else:
548
549
  raise ValueError("Invalid intrinsic_or_relational value: `%s`" % str(intrinsic_or_relational))
549
550
 
550
- space = _mt.remove_dependent_cols(space)
551
+ col_indices = _mt.independent_columns(space)
552
+ space = space[:, col_indices]
551
553
  return space
552
554
 
553
555
  @classmethod
@@ -152,8 +152,7 @@ class LocalNoiseModel(_ImplicitOpModel):
152
152
 
153
153
  simulator = _FSim.cast(simulator,
154
154
  state_space.num_qubits if isinstance(state_space, _statespace.QubitSpace) else None)
155
- prefer_dense_reps = isinstance(simulator, _MatrixFSim)
156
- evotype = _Evotype.cast(evotype, default_prefer_dense_reps=prefer_dense_reps)
155
+ evotype = _Evotype.cast(evotype, state_space=state_space)
157
156
 
158
157
  # Build gate dictionaries. A value of `gatedict` can be an array, a LinearOperator, or an OpFactory.
159
158
  # For later processing, we'll create mm_gatedict to contain each item as a ModelMember. In local noise
@@ -45,18 +45,6 @@ class _PrefixOrderedDict(_collections.OrderedDict):
45
45
  "beginning with the prefix '%s'" % self._prefix)
46
46
  super(_PrefixOrderedDict, self).__setitem__(key, val)
47
47
 
48
- #Handled by derived classes
49
- #def __reduce__(self):
50
- # items = [(k,v) for k,v in self.iteritems()]
51
- # return (_PrefixOrderedDict, (self._prefix, items), None)
52
-
53
- """
54
- An ordered dictionary whose keys must begin with a given prefix,
55
- and which holds LinearOperator objects. This class ensures that every value is a
56
- :class:`LinearOperator`-derived object by converting any non-`LinearOperator` values into
57
- `LinearOperator`s upon assignment and raising an error if this is not possible.
58
- """
59
-
60
48
 
61
49
  class OrderedMemberDict(_PrefixOrderedDict, _mm.ModelChild):
62
50
  """