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
@@ -107,10 +107,3 @@ cdef class TermRep(_basereps_cython.TermRep):
107
107
  return TermRep(self.coeff.copy(), self.magnitude, self.logmagnitude,
108
108
  self.pre_state, self.post_state, self.pre_effect, self.post_effect,
109
109
  self.pre_ops, self.post_ops)
110
-
111
- #Not needed - and this implementation is quite right as it will need to change
112
- # the ordering of the pre/post ops also.
113
- #def conjugate(self):
114
- # return TermRep(self.coeff.copy(), self.magnitude, self.logmagnitude,
115
- # self.post_state, self.pre_state, self.post_effect, self.pre_effect,
116
- # self.post_ops, self.pre_ops)
@@ -23,10 +23,6 @@ class EffectRep(_basereps.EffectRep):
23
23
  def nqubits(self):
24
24
  return self.state_space.num_qubits
25
25
 
26
- #@property
27
- #def dim(self):
28
- # return 2**self.nqubits # assume "unitary evolution"-type mode
29
-
30
26
  def probability(self, state):
31
27
  return state.sframe.measurement_probability(self.zvals, check=True) # use check for now?
32
28
 
@@ -37,10 +33,6 @@ class EffectRep(_basereps.EffectRep):
37
33
  return _mt.zvals_to_dense(self.zvals, superket=bool(on_space not in ('minimal', 'Hilbert')))
38
34
 
39
35
 
40
- #class EffectRepConjugatedState(EffectRep):
41
- # pass # TODO - this should be possible
42
-
43
-
44
36
  class EffectRepComputational(EffectRep):
45
37
 
46
38
  def __init__(self, zvals, basis, state_space):
@@ -49,17 +41,6 @@ class EffectRepComputational(EffectRep):
49
41
  assert(self.state_space.num_qubits == len(self.zvals))
50
42
  super(EffectRepComputational, self).__init__(state_space)
51
43
 
52
- #@property
53
- #def outcomes(self):
54
- # """
55
- # The 0/1 outcomes identifying this effect within its StabilizerZPOVM
56
- #
57
- # Returns
58
- # -------
59
- # numpy.ndarray
60
- # """
61
- # return self.zvals
62
-
63
44
  def __str__(self):
64
45
  nQubits = len(self.zvals)
65
46
  s = "Stabilizer effect vector for %d qubits with outcome %s" % (nQubits, str(self.zvals))
@@ -80,9 +61,6 @@ class EffectRepComposed(EffectRep):
80
61
 
81
62
  super(EffectRepComposed, self).__init__(state_space)
82
63
 
83
- #def __reduce__(self):
84
- # return (EffectRepComposed, (self.op_rep, self.effect_rep, self.op_id, self.state_space))
85
-
86
64
  def probability(self, state):
87
65
  state = self.op_rep.acton(state) # *not* acton_adjoint
88
66
  return self.effect_rep.probability(state)
@@ -34,10 +34,6 @@ class OpRep(_basereps.OpRep):
34
34
  def nqubits(self):
35
35
  return self.state_space.num_qubits
36
36
 
37
- #@property
38
- #def dim(self):
39
- # return 2**(self.nqubits) # assume "unitary evolution"-type mode
40
-
41
37
 
42
38
  class OpRepClifford(OpRep):
43
39
  def __init__(self, unitarymx, symplecticrep, basis, state_space):
@@ -42,10 +42,6 @@ class StateRep(_basereps.StateRep):
42
42
  def nqubits(self):
43
43
  return self.sframe.n
44
44
 
45
- #@property
46
- #def dim(self):
47
- # return 2**self.nqubits # assume "unitary evolution"-type mode
48
-
49
45
  def actionable_staterep(self):
50
46
  # return a state rep that can be acted on by op reps or mapped to
51
47
  # a probability/amplitude by POVM effect reps.
@@ -111,7 +111,7 @@ cdef class EffectRepTensorProduct(EffectRep):
111
111
  cdef _np.ndarray[_np.int64_t, ndim=1, mode='c'] factor_dims = \
112
112
  _np.ascontiguousarray(_np.array([fct.state_space.udim for fct in povm_factors], _np.int64))
113
113
 
114
- cdef INT dim = _np.product(factor_dims)
114
+ cdef INT dim = _np.prod(factor_dims)
115
115
  cdef INT nfactors = len(self.povm_factors)
116
116
  self.povm_factors = povm_factors
117
117
  self.effect_labels = effect_labels
@@ -246,7 +246,7 @@ cdef class OpRepEmbedded(OpRep):
246
246
  # final map just acts as identity w.r.t.
247
247
  labelIndices = [tensorProdBlkLabels.index(label) for label in target_labels]
248
248
  cdef _np.ndarray[_np.int64_t, ndim=1, mode='c'] action_inds = _np.array(labelIndices, _np.int64)
249
- assert(_np.product([num_basis_els[i] for i in action_inds]) == embedded_rep.dim), \
249
+ assert(_np.prod([num_basis_els[i] for i in action_inds]) == embedded_rep.dim), \
250
250
  "Embedded operation has dimension (%d) inconsistent with the given target labels (%s)" % (
251
251
  embedded_rep.dim, str(target_labels))
252
252
 
@@ -256,7 +256,7 @@ cdef class OpRepEmbedded(OpRep):
256
256
  cdef INT ncomponents_in_active_block = len(state_space.tensor_product_block_labels(active_block_index))
257
257
  cdef INT embedded_dim = embedded_rep.dim
258
258
  cdef _np.ndarray[_np.int64_t, ndim=1, mode='c'] blocksizes = \
259
- _np.array([_np.product(state_space.tensor_product_block_udimensions(k))
259
+ _np.array([_np.prod(state_space.tensor_product_block_udimensions(k))
260
260
  for k in range(nblocks)], _np.int64)
261
261
  cdef INT i, j
262
262
 
@@ -150,7 +150,7 @@ cdef class StateRepTensorProduct(StateRep):
150
150
 
151
151
  def __init__(self, factor_state_reps, state_space):
152
152
  self.factor_reps = factor_state_reps
153
- dim = _np.product([fct.dim for fct in self.factor_reps])
153
+ dim = _np.prod([fct.dim for fct in self.factor_reps])
154
154
  self._cinit_base(_np.zeros(dim, complex), state_space, None) # TODO: compute a tensorprod basis?
155
155
  self.reps_have_changed()
156
156
 
@@ -112,13 +112,6 @@ cdef class TermRep(_basereps_cython.TermRep):
112
112
  self.pre_state, self.post_state, self.pre_effect, self.post_effect,
113
113
  self.pre_ops, self.post_ops)
114
114
 
115
- #Not needed - and this implementation is quite right as it will need to change
116
- # the ordering of the pre/post ops also.
117
- #def conjugate(self):
118
- # return TermRep(self.coeff.copy(), self.magnitude, self.logmagnitude,
119
- # self.post_state, self.pre_state, self.post_effect, self.pre_effect,
120
- # self.post_ops, self.pre_ops)
121
-
122
115
 
123
116
  #Note: to use direct term reps (numerical coeffs) we'll need to update
124
117
  # what the members are called and add methods as was done for TermRep.
@@ -180,9 +180,6 @@ class EffectRepComposed(EffectRep):
180
180
 
181
181
  super(EffectRepComposed, self).__init__(effect_rep.state_space)
182
182
 
183
- #def __reduce__(self):
184
- # return (EffectRepComposed, (self.op_rep, self.effect_rep, self.op_id, self.state_space))
185
-
186
183
  def probability(self, state):
187
184
  state = self.op_rep.acton(state) # *not* acton_adjoint
188
185
  return self.effect_rep.probability(state)
@@ -107,11 +107,6 @@ class OpRepStandard(OpRepDenseUnitary):
107
107
  super(OpRepStandard, self).__init__(U, basis, state_space)
108
108
 
109
109
 
110
- #class OpRepStochastic(OpRepDense):
111
- # - maybe we could add this, but it wouldn't be a "dense" op here,
112
- # perhaps we need to change API?
113
-
114
-
115
110
  class OpRepComposed(OpRep):
116
111
  # exactly the same as densitymx case
117
112
  def __init__(self, factor_op_reps, state_space):
pygsti/extras/__init__.py CHANGED
@@ -9,5 +9,4 @@
9
9
  """ Container for beyond-GST sub-packages """
10
10
 
11
11
  # from . import drift
12
- # from . import rb # temporarily removed until RB analysis is fixed
13
12
  # from . import rpe
@@ -10,7 +10,7 @@
10
10
 
11
11
  import numpy as _np
12
12
  import numpy.random as _rnd
13
- from scipy import convolve as _convolve
13
+ from numpy import convolve as _convolve
14
14
  from scipy.fftpack import dct as _dct
15
15
  from scipy.fftpack import fft as _fft
16
16
  from scipy.fftpack import idct as _idct
@@ -1235,9 +1235,11 @@ class StabilityAnalyzer(object):
1235
1235
 
1236
1236
  # If we're not testing a single spectrum we need to flatten the >1D array.
1237
1237
  if len(_np.shape(spectra)) > 1:
1238
+ # Use flatten (rather than ravel) to ensure a copy is made.
1238
1239
  powerlist = spectra[indices].flatten()
1239
1240
  # If we're testing a single spectrum, we can just copy the 1D array.
1240
- else: powerlist = spectra[indices].copy()
1241
+ else:
1242
+ powerlist = spectra[indices].copy()
1241
1243
 
1242
1244
  # The indices that will go with the elements in the flattened spectra.
1243
1245
  powerindices = [tup for tup in _itertools.product(*iterBenjHoch)]
@@ -10,3 +10,15 @@
10
10
 
11
11
  from .core import PhysicalProcess, InterpolatedDenseOp, InterpolatedOpFactory
12
12
  from .process_tomography import vec, unvec, run_process_tomography
13
+
14
+ # Note from Riley on September, 2024:
15
+ #
16
+ # vec is deprecated, and shouldn't be called anywhere in the codebase.
17
+ #
18
+ # unvec is deprecated and replaced with unvec_square; the latter function
19
+ # isn't imported here because we don't want people to access it just from
20
+ # the pygsti.extras.interpygate namespace.
21
+ #
22
+ # Ideally we'd remove vec and unvec from the pygsti.extras.interpygate namespace
23
+ # and only have them available in pygsti.extras.interpygate.process_tomography.
24
+ #
@@ -241,15 +241,6 @@ class InterpolatedOpFactory(_OpFactory):
241
241
  return InterpolatedDenseOp(target_op, self.base_interpolator, self.aux_interpolator, self.to_vector(),
242
242
  _np.array(args), self._argument_indices)
243
243
 
244
- #def write(self, dirname):
245
- # dirname = _pathlib.Path(dirname)
246
- # with open(str(dirname / "targetop.pkl"), 'wb') as f:
247
- # _pickle.dump(self.target_op, f)
248
- # _np.save(dirname / "paramvec.np", self._paramvec_with_time)
249
- # self.base_interpolator.write(dirname / "base.interp")
250
- # if self.aux_interpolator is not None:
251
- # self.aux_interptolator.write(dirname / "aux.interp")
252
-
253
244
  @property
254
245
  def num_params(self):
255
246
  return len(self._paramvec)
@@ -267,24 +258,6 @@ class InterpolatedOpFactory(_OpFactory):
267
258
 
268
259
  class InterpolatedDenseOp(_DenseOperator):
269
260
 
270
- #@classmethod
271
- #def from_dir(cls, dirname):
272
- # dirname = _pathlib.Path(dirname)
273
- # with open(str(dirname / "targetop.pkl"), 'rb') as f:
274
- # target_op = _pickle.load(f)
275
- # pt = _np.load(dirname / "paramvec.np")
276
- # base_interp = InterpolatedQuantity.from_file(dirname / "base.interp")
277
- # aux_interp = InterpolatedQuantity.from_file(dirname / "aux.interp") \
278
- # if (dirname / "aux.interp").exists() else None
279
- #
280
- # if base_interp.times is not None:
281
- # tm = pt[-1]
282
- # pt = pt[0:-1]
283
- # else:
284
- # tm = None
285
- #
286
- # return cls(target_op, base_interp, aux_interp, pt, tm)
287
-
288
261
  @classmethod
289
262
  def create_by_interpolating_physical_process(cls, target_op, physical_process, parameter_ranges=None,
290
263
  parameter_points=None, comm=None,
@@ -391,15 +364,6 @@ class InterpolatedDenseOp(_DenseOperator):
391
364
  # initialize object
392
365
  self.from_vector(self._paramvec)
393
366
 
394
- #def write(self, dirname):
395
- # dirname = _pathlib.Path(dirname)
396
- # with open(str(dirname / "targetop.pkl"), 'wb') as f:
397
- # _pickle.dump(self.target_op, f)
398
- # _np.save(dirname / "paramvec.np", self._paramvec_with_time)
399
- # self.base_interpolator.write(dirname / "base.interp")
400
- # if self.aux_interpolator is not None:
401
- # self.aux_interptolator.write(dirname / "aux.interp")
402
-
403
367
  @property
404
368
  def num_params(self):
405
369
  return len(self._paramvec)
@@ -7,6 +7,7 @@ import numpy as _np
7
7
  import numpy.linalg as _lin
8
8
 
9
9
  from pygsti.tools.basistools import change_basis
10
+ from pygsti.tools.legacytools import deprecate
10
11
 
11
12
 
12
13
  #Helper functions
@@ -15,8 +16,11 @@ def multi_kron(*a):
15
16
  return reduce(_np.kron, a)
16
17
 
17
18
 
19
+ @deprecate("Calls to this function should be replaced with in-lined code: matrix.reshape((matrix.size, 1), 'F')")
18
20
  def vec(matrix):
19
- """A function that vectorizes a matrix.
21
+ """
22
+ Returns an explicit column-vector representation of a square matrix, obtained by reading
23
+ from the square matrix in column-major order.
20
24
 
21
25
  Args:
22
26
  matrix (list,numpy.ndarray): NxN matrix
@@ -30,11 +34,12 @@ def vec(matrix):
30
34
  """
31
35
  matrix = _np.array(matrix)
32
36
  if matrix.shape == (len(matrix), len(matrix)):
33
- return _np.array([_np.concatenate(_np.array(matrix).T)]).T
37
+ return matrix.reshape(shape=(matrix.size, 1), order='F')
34
38
  else:
35
39
  raise ValueError('The input matrix must be square.')
36
40
 
37
41
 
42
+ @deprecate("Calls to this function should be replaced by unvec_square(vectorized, 'F')")
38
43
  def unvec(vectorized):
39
44
  """A function that vectorizes a process in the basis of matrix units, sorted first
40
45
  by column, then row.
@@ -49,13 +54,42 @@ def unvec(vectorized):
49
54
  ValueError: If the length of the input is not a perfect square
50
55
 
51
56
  """
52
- vectorized = _np.array(vectorized)
53
- length = int(_np.sqrt(max(vectorized.shape)))
54
- if len(vectorized) == length ** 2:
55
- return _np.reshape(vectorized, [length, length]).T
57
+ return unvec_square(vectorized, order='F')
58
+
59
+
60
+ def unvec_square(vectorized, order):
61
+ """
62
+ Takes a vector whose length is a perfect square, and returns a square matrix
63
+ representation by reading from the vectors entries to define the matrix in
64
+ column-major order (order='F') or row-major order (order='C').
65
+
66
+ Args:
67
+ vectorized: array-like, where np.array(vectorized).size is a perfect square.
68
+ order: 'F' or 'C'
69
+
70
+ Returns:
71
+ numpy.ndarray: NxN dimensional array
72
+
73
+ Raises:
74
+ ValueError: If the length of the input is not a perfect square.
75
+
76
+ """
77
+ assert order == 'F' or order == 'C'
78
+ if not isinstance(vectorized, _np.ndarray):
79
+ vectorized = _np.array(vectorized)
80
+
81
+ if vectorized.ndim == 2:
82
+ assert min(vectorized.shape) == 1
83
+ vectorized = vectorized.ravel()
84
+ elif vectorized.ndim > 2:
85
+ raise ValueError('vectorized.ndim must be <= 2.')
86
+
87
+ n = int(_np.sqrt(max(vectorized.shape)))
88
+ if len(vectorized) == n ** 2:
89
+ return vectorized.reshape((n, n), order=order)
56
90
  else:
57
- raise ValueError(
58
- 'The input vector length must be a perfect square, but this input has length %d.' % len(vectorized))
91
+ msg = 'The input vector length must be a perfect square, but this input has length %d.' % len(vectorized)
92
+ raise ValueError(msg)
59
93
 
60
94
 
61
95
  def split(n, a):
@@ -129,7 +163,7 @@ def run_process_tomography(state_to_density_matrix_fn, n_qubits=1, comm=None,
129
163
  states = _itertools.product(one_qubit_states, repeat=n_qubits)
130
164
  states = [multi_kron(*state) for state in states]
131
165
  in_density_matrices = [_np.outer(state, state.conj()) for state in states]
132
- in_states = _np.column_stack(list([vec(rho) for rho in in_density_matrices]))
166
+ in_states = _np.column_stack(list([rho.ravel(order='F') for rho in in_density_matrices]))
133
167
  my_states = split(size, states)[rank]
134
168
  if verbose:
135
169
  print("Process %d of %d evaluating %d input states." % (rank, size, len(my_states)))
@@ -150,7 +184,7 @@ def run_process_tomography(state_to_density_matrix_fn, n_qubits=1, comm=None,
150
184
  out_density_matrices = _np.array([y for x in gathered_out_density_matrices for y in x])
151
185
  # Sort the list by time
152
186
  out_density_matrices = _np.transpose(out_density_matrices, [1, 0, 2, 3])
153
- out_states = [_np.column_stack(list([vec(rho) for rho in density_matrices_at_time]))
187
+ out_states = [_np.column_stack(list([rho.ravel(order='F') for rho in density_matrices_at_time]))
154
188
  for density_matrices_at_time in out_density_matrices]
155
189
  process_matrices = [_np.dot(out_states_at_time, _lin.inv(in_states)) for out_states_at_time in out_states]
156
190
  process_matrices = [change_basis(process_matrix_at_time, 'col', basis)
@@ -113,8 +113,6 @@ def create_parameterized_rpe_model(alpha_true, epsilon_true, aux_rot, spam_depol
113
113
 
114
114
  return outputModel
115
115
 
116
- #def make_rpe_alpha_str_lists(k_list,angleStr,rpeconfig_inst):
117
-
118
116
 
119
117
  def create_rpe_angle_circuit_lists(k_list, angle_name, rpeconfig_inst):
120
118
  """
@@ -12,6 +12,7 @@ pyGSTi Forward Simulators Python Package
12
12
 
13
13
  from .forwardsim import ForwardSimulator
14
14
  from .mapforwardsim import SimpleMapForwardSimulator, MapForwardSimulator
15
+ from .torchfwdsim import TorchForwardSimulator
15
16
  from .matrixforwardsim import SimpleMatrixForwardSimulator, MatrixForwardSimulator
16
17
  from .termforwardsim import TermForwardSimulator
17
18
  from .weakforwardsim import WeakForwardSimulator
@@ -9,7 +9,7 @@ Defines the ForwardSimulator calculator class
9
9
  # in compliance with the License. You may obtain a copy of the License at
10
10
  # http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
11
11
  #***************************************************************************************************
12
-
12
+ from __future__ import annotations
13
13
  import collections as _collections
14
14
  import warnings as _warnings
15
15
 
@@ -21,6 +21,7 @@ from pygsti.baseobjs import outcomelabeldict as _ld
21
21
  from pygsti.baseobjs.resourceallocation import ResourceAllocation as _ResourceAllocation
22
22
  from pygsti.baseobjs.nicelyserializable import NicelySerializable as _NicelySerializable
23
23
  from pygsti.tools import slicetools as _slct
24
+ from typing import Union, Callable, Literal
24
25
 
25
26
 
26
27
  class ForwardSimulator(_NicelySerializable):
@@ -44,22 +45,38 @@ class ForwardSimulator(_NicelySerializable):
44
45
  The model this forward simulator will use to compute circuit outcome probabilities.
45
46
  """
46
47
 
48
+ Castable = Union[
49
+ 'ForwardSimulator',
50
+ Callable[[], 'ForwardSimulator'],
51
+ Literal['map'],
52
+ Literal['matrix'],
53
+ Literal['auto']
54
+ ]
55
+ # ^ Define a type alias we can reference elsewhere in our code.
56
+
47
57
  @classmethod
48
- def cast(cls, obj, num_qubits=None):
58
+ def cast(cls, obj : ForwardSimulator.Castable, num_qubits=None):
49
59
  """ num_qubits only used if `obj == 'auto'` """
50
60
  from .matrixforwardsim import MatrixForwardSimulator as _MatrixFSim
51
61
  from .mapforwardsim import MapForwardSimulator as _MapFSim
52
62
 
53
63
  if isinstance(obj, ForwardSimulator):
54
64
  return obj
55
- elif obj == "auto":
56
- return _MapFSim() if (num_qubits is None or num_qubits > 2) else _MatrixFSim()
57
- elif obj == "map":
58
- return _MapFSim()
59
- elif obj == "matrix":
60
- return _MatrixFSim()
65
+ elif isinstance(obj, str):
66
+ if obj == "auto" or obj == "map":
67
+ return _MapFSim()
68
+ elif obj == "matrix":
69
+ return _MatrixFSim()
70
+ else:
71
+ raise ValueError(f'Unrecognized string argument, {obj}')
72
+ elif isinstance(obj, Callable):
73
+ out_obj = obj()
74
+ if isinstance(out_obj, ForwardSimulator):
75
+ return out_obj
76
+ else:
77
+ raise ValueError(f'Argument {obj} cannot be cast to a ForwardSimulator.')
61
78
  else:
62
- raise ValueError("Cannot convert %s to a forward simulator!" % str(obj))
79
+ raise ValueError(f'Argument {obj} cannot be cast to a ForwardSimulator.')
63
80
 
64
81
  @classmethod
65
82
  def _array_types_for_method(cls, method_name):
@@ -128,57 +145,6 @@ class ForwardSimulator(_NicelySerializable):
128
145
  `evotype` will be `None` when the current model is None"""
129
146
  pass
130
147
 
131
- #def to_vector(self):
132
- # """
133
- # Returns the parameter vector of the associated Model.
134
- #
135
- # Returns
136
- # -------
137
- # numpy array
138
- # The vectorized model parameters.
139
- # """
140
- # return self.paramvec
141
- #
142
- #def from_vector(self, v, close=False, nodirty=False):
143
- # """
144
- # The inverse of to_vector.
145
- #
146
- # Initializes the Model-like members of this
147
- # calculator based on `v`. Used for computing finite-difference derivatives.
148
- #
149
- # Parameters
150
- # ----------
151
- # v : numpy.ndarray
152
- # The parameter vector.
153
- #
154
- # close : bool, optional
155
- # Set to `True` if `v` is close to the current parameter vector.
156
- # This can make some operations more efficient.
157
- #
158
- # nodirty : bool, optional
159
- # If True, the framework for marking and detecting when operations
160
- # have changed and a Model's parameter-vector needs to be updated
161
- # is disabled. Disabling this will increases the speed of the call.
162
- #
163
- # Returns
164
- # -------
165
- # None
166
- # """
167
- # #Note: this *will* initialize the parent Model's objects too,
168
- # # since only references to preps, effects, and gates are held
169
- # # by the calculator class. ORDER is important, as elements of
170
- # # POVMs and Instruments rely on a fixed from_vector ordering
171
- # # of their simplified effects/gates.
172
- # self.paramvec = v.copy() # now self.paramvec is *not* the same as the Model's paramvec
173
- # self.sos.from_vector(v, close, nodirty) # so don't always want ", nodirty=True)" - we
174
- # # need to set dirty flags so *parent* will re-init it's paramvec...
175
- #
176
- # #Re-init reps for computation
177
- # #self.operationreps = { i:self.operations[lbl].torep() for lbl,i in self.operation_lookup.items() }
178
- # #self.operationreps = { lbl:g.torep() for lbl,g in gates.items() }
179
- # #self.prepreps = { lbl:p.torep('prep') for lbl,p in preps.items() }
180
- # #self.effectreps = { lbl:e.torep('effect') for lbl,e in effects.items() }
181
-
182
148
  def _compute_circuit_outcome_probabilities(self, array_to_fill, circuit, outcomes, resource_alloc, time=None):
183
149
  raise NotImplementedError("Derived classes should implement this!")
184
150
 
@@ -304,7 +270,8 @@ class ForwardSimulator(_NicelySerializable):
304
270
  # ---------------------------------------------------------------------------
305
271
 
306
272
  def create_layout(self, circuits, dataset=None, resource_alloc=None,
307
- array_types=(), derivative_dimensions=None, verbosity=0):
273
+ array_types=(), derivative_dimensions=None, verbosity=0,
274
+ layout_creation_circuit_cache = None):
308
275
  """
309
276
  Constructs an circuit-outcome-probability-array (COPA) layout for `circuits` and `dataset`.
310
277
 
@@ -337,49 +304,39 @@ class ForwardSimulator(_NicelySerializable):
337
304
 
338
305
  derivative_dimensions : tuple, optional
339
306
  A tuple containing, optionally, the parameter-space dimension used when taking first
340
- and second derivatives with respect to the cirucit outcome probabilities. This must be
307
+ and second derivatives with respect to the cirucit outcome probabilities. This should
341
308
  have minimally 1 or 2 elements when `array_types` contains `'ep'` or `'epp'` types,
342
- respectively.
309
+ respectively. If `array_types` contains either of these strings and derivative_dimensions
310
+ is None on input then we automatically set derivative_dimensions based on self.model.
343
311
 
344
312
  verbosity : int or VerbosityPrinter
345
313
  Determines how much output to send to stdout. 0 means no output, higher
346
314
  integers mean more output.
315
+
316
+
347
317
 
348
318
  Returns
349
319
  -------
350
320
  CircuitOutcomeProbabilityArrayLayout
351
321
  """
322
+ if derivative_dimensions is None:
323
+ if 'epp' in array_types:
324
+ derivative_dimensions = (self.model.num_params, self.model.num_params)
325
+ elif 'ep' in array_types:
326
+ derivative_dimensions = (self.model.num_params,)
327
+ else:
328
+ derivative_dimensions = tuple()
352
329
  return _CircuitOutcomeProbabilityArrayLayout.create_from(circuits, self.model, dataset, derivative_dimensions,
353
330
  resource_alloc=resource_alloc)
354
-
355
- #TODO UPDATE
356
- #def bulk_prep_probs(self, eval_tree, comm=None, mem_limit=None):
357
- # """
358
- # Performs initial computation needed for bulk_fill_probs and related calls.
359
- #
360
- # For example, as computing probability polynomials. This is usually coupled with
361
- # the creation of an evaluation tree, but is separated from it because this
362
- # "preparation" may use `comm` to distribute a computationally intensive task.
363
- #
364
- # Parameters
365
- # ----------
366
- # eval_tree : EvalTree
367
- # The evaluation tree used to define a list of circuits and hold (cache)
368
- # any computed quantities.
369
- #
370
- # comm : mpi4py.MPI.Comm, optional
371
- # When not None, an MPI communicator for distributing the computation
372
- # across multiple processors. Distribution is performed over
373
- # subtrees of `eval_tree` (if it is split).
374
- #
375
- # mem_limit : int
376
- # Rough memory limit in bytes.
377
- #
378
- # Returns
379
- # -------
380
- # None
381
- # """
382
- # pass # default is to have no pre-computed quantities (but not an error to call this fn)
331
+
332
+ @staticmethod
333
+ def create_copa_layout_circuit_cache(circuits, model, dataset=None):
334
+ """
335
+ Helper function for pre-computing/pre-processing circuits structures
336
+ used in matrix layout creation.
337
+ """
338
+ msg = "Not currently implemented for this forward simulator class."
339
+ raise NotImplementedError(msg)
383
340
 
384
341
  def bulk_probs(self, circuits, clip_to=None, resource_alloc=None, smartc=None):
385
342
  """
@@ -642,7 +599,7 @@ class ForwardSimulator(_NicelySerializable):
642
599
  iFinal = iParamToFinal[i]
643
600
  vec = orig_vec.copy(); vec[i] += eps
644
601
  self.model.from_vector(vec, close=True)
645
- self._bulk_fill_probs_block(probs2, layout, resource_alloc)
602
+ self._bulk_fill_probs_block(probs2, layout)
646
603
  array_to_fill[:, iFinal] = (probs2 - probs) / eps
647
604
  self.model.from_vector(orig_vec, close=True)
648
605