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
@@ -57,7 +57,7 @@ class _TermCOPALayoutAtom(_DistributableAtom):
57
57
  expanded_circuit_outcomes = _collections.OrderedDict()
58
58
  for i in group:
59
59
  observed_outcomes = None if (dataset is None) else dataset[ds_circuits[i]].outcomes
60
- d = unique_complete_circuits[i].expand_instruments_and_separate_povm(model, observed_outcomes)
60
+ d = model.expand_instruments_and_separate_povm(unique_complete_circuits[i], observed_outcomes)
61
61
  expanded_circuit_outcomes_by_unique[i] = d
62
62
  expanded_circuit_outcomes.update(d)
63
63
 
@@ -71,7 +71,7 @@ class Instrument(_mm.ModelMember, _collections.OrderedDict):
71
71
  if state_space is None:
72
72
  state_space = _statespace.default_space_for_dim(member_list[0][1].shape[0])
73
73
  if evotype is None:
74
- evotype = _Evotype.cast('default')
74
+ evotype = _Evotype.cast('default', state_space=state_space)
75
75
  member_list = [(k, v if isinstance(v, _op.LinearOperator) else
76
76
  _op.FullArbitraryOp(v, None, evotype, state_space)) for k, v in member_list]
77
77
 
@@ -79,10 +79,10 @@ class Instrument(_mm.ModelMember, _collections.OrderedDict):
79
79
  "Must specify `state_space` when there are no instrument members!"
80
80
  assert(len(member_list) > 0 or evotype is not None), \
81
81
  "Must specify `evotype` when there are no instrument members!"
82
- evotype = _Evotype.cast(evotype) if (evotype is not None) else member_list[0][1].evotype
83
82
  state_space = member_list[0][1].state_space if (state_space is None) \
84
83
  else _statespace.StateSpace.cast(state_space)
85
-
84
+ evotype = _Evotype.cast(evotype, state_space=state_space) if (evotype is not None)\
85
+ else member_list[0][1].evotype
86
86
  items = []
87
87
  for k, member in member_list:
88
88
  assert(evotype == member.evotype), \
@@ -77,8 +77,6 @@ class TPInstrument(_mm.ModelMember, _collections.OrderedDict):
77
77
  self._readonly = False # until init is done
78
78
  if len(items) > 0:
79
79
  assert(op_matrices is None), "`items` was given when op_matrices != None"
80
-
81
- evotype = _Evotype.cast(evotype)
82
80
  self.param_ops = [] # first element is TP sum (MT), following
83
81
  #elements are fully-param'd (Mi-Mt) for i=0...n-2
84
82
 
@@ -98,6 +96,7 @@ class TPInstrument(_mm.ModelMember, _collections.OrderedDict):
98
96
  "Must specify `state_space` when there are no instrument members!"
99
97
  state_space = _statespace.default_space_for_dim(matrix_list[0][1].shape[0]) if (state_space is None) \
100
98
  else _statespace.StateSpace.cast(state_space)
99
+ evotype = _Evotype.cast(evotype, state_space=state_space)
101
100
 
102
101
  # Create gate objects that are used to parameterize this instrument
103
102
  MT_mx = sum([v for k, v in matrix_list]) # sum-of-instrument-members matrix
@@ -125,6 +124,7 @@ class TPInstrument(_mm.ModelMember, _collections.OrderedDict):
125
124
  # print(k,":\n",v)
126
125
  else:
127
126
  assert(state_space is not None), "`state_space` cannot be `None` when there are no members!"
127
+ evotype = _Evotype.cast(evotype, state_space=state_space)
128
128
 
129
129
  _collections.OrderedDict.__init__(self, items)
130
130
  _mm.ModelMember.__init__(self, state_space, evotype)
@@ -340,23 +340,6 @@ class ModelMember(ModelChild, _NicelySerializable):
340
340
  if (self.parent is not None) and (force or self.parent._obj_refcount(self) == 0):
341
341
  self._parent = None
342
342
 
343
- # UNUSED - as this doesn't mark parameter for reallocation like it used to
344
- #def clear_gpindices(self):
345
- # """
346
- # Sets gpindices to None, along with any submembers' gpindices.
347
- #
348
- # This essentially marks these members for parameter re-allocation
349
- # (e.g. if the number - not just the value - of parameters they have
350
- # changes).
351
- #
352
- # Returns
353
- # -------
354
- # None
355
- # """
356
- # for subm in self.submembers():
357
- # subm.clear_gpindices()
358
- # self._gpindices = None
359
-
360
343
  def set_gpindices(self, gpindices, parent, memo=None):
361
344
  """
362
345
  Set the parent and indices into the parent's parameter vector that are used by this ModelMember object.
@@ -38,6 +38,7 @@ from .staticstdop import StaticStandardOp
38
38
  from .staticunitaryop import StaticUnitaryOp
39
39
  from .stochasticop import StochasticNoiseOp
40
40
  from .lindbladcoefficients import LindbladCoefficientBlock as _LindbladCoefficientBlock
41
+ from .affineshiftop import AffineShiftOp
41
42
  from pygsti.baseobjs import statespace as _statespace
42
43
  from pygsti.tools import basistools as _bt
43
44
  from pygsti.tools import optools as _ot
@@ -474,18 +475,16 @@ def optimize_operation(op_to_optimize, target_op):
474
475
  return
475
476
 
476
477
  from pygsti import optimize as _opt
477
- from pygsti.tools import matrixtools as _mt
478
478
  assert(target_op.dim == op_to_optimize.dim) # operations must have the same overall dimension
479
479
  targetMatrix = target_op.to_dense() if isinstance(target_op, LinearOperator) else target_op
480
480
 
481
481
  def _objective_func(param_vec):
482
482
  op_to_optimize.from_vector(param_vec)
483
- return _mt.frobeniusnorm(op_to_optimize.to_dense() - targetMatrix)
483
+ return _np.linalg.norm(op_to_optimize.to_dense() - targetMatrix)
484
484
 
485
485
  x0 = op_to_optimize.to_vector()
486
486
  minSol = _opt.minimize(_objective_func, x0, method='BFGS', maxiter=10000, maxfev=10000,
487
487
  tol=1e-6, callback=None)
488
488
 
489
489
  op_to_optimize.from_vector(minSol.x)
490
- #print("DEBUG: optimized operation to min frobenius distance %g" %
491
- # _mt.frobeniusnorm(op_to_optimize-targetMatrix))
490
+ return
@@ -0,0 +1,206 @@
1
+ """
2
+ The AffineShiftOp class and supporting functionality.
3
+ """
4
+ #***************************************************************************************************
5
+ # Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
6
+ # Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights
7
+ # in this software.
8
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
9
+ # in compliance with the License. You may obtain a copy of the License at
10
+ # http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
11
+ #***************************************************************************************************
12
+
13
+ import numpy as _np
14
+
15
+ from pygsti.modelmembers.operations.denseop import DenseOperator as _DenseOperator
16
+ from pygsti.modelmembers.operations.linearop import LinearOperator as _LinearOperator
17
+ from pygsti.baseobjs.protectedarray import ProtectedArray as _ProtectedArray
18
+
19
+
20
+ class AffineShiftOp(_DenseOperator):
21
+ """
22
+ An operation matrix that induces an affine shift.
23
+
24
+ An operation matrix with ones on the diagonal and nonzero values in
25
+ the first columns.
26
+
27
+ Meant to work in the Pauli basis for now.
28
+
29
+ Parameters
30
+ ----------
31
+ m : array_like or LinearOperator
32
+ a square 2D array-like or LinearOperator object representing the operation action.
33
+ The shape of m sets the dimension of the operation.
34
+
35
+ basis : Basis or {'pp','gm','std'} or None
36
+ The basis used to construct the Hilbert-Schmidt space representation
37
+ of this state as a super-operator. If None, certain functionality,
38
+ such as access to Kraus operators, will be unavailable.
39
+
40
+ evotype : Evotype or str, optional
41
+ The evolution type. The special value `"default"` is equivalent
42
+ to specifying the value of `pygsti.evotypes.Evotype.default_evotype`.
43
+
44
+ state_space : StateSpace, optional
45
+ The state space for this operation. If `None` a default state space
46
+ with the appropriate number of qubits is used.
47
+
48
+ Attributes
49
+ ----------
50
+ base : numpy.ndarray
51
+ Direct access to the underlying process matrix data.
52
+ """
53
+
54
+ def __init__(self, m, basis=None, evotype="default", state_space=None):
55
+ #LinearOperator.__init__(self, LinearOperator.convert_to_matrix(m))
56
+ mx = _LinearOperator.convert_to_matrix(m)
57
+ assert(_np.isrealobj(mx)), "FullTPOp must have *real* values!"
58
+
59
+ #this line checks whether the input matrix has the correct
60
+ #arrowhead structure.
61
+ if not (_np.allclose(_np.diag(mx), 1) and _np.allclose((mx-_np.eye(mx.shape[0]))[:, 1:], 0.0)):
62
+ raise ValueError("Cannot create AffineShiftOp: "
63
+ "Matrix does not have the correct arrowhead structure")
64
+ _DenseOperator.__init__(self, mx, basis, evotype, state_space)
65
+ assert(self._rep.base.flags['C_CONTIGUOUS'] and self._rep.base.flags['OWNDATA'])
66
+ assert(isinstance(self._ptr, _ProtectedArray))
67
+
68
+ self._paramlbls = _np.array(["MxElement %d,0" % (i) for i in range(1, self.dim)],
69
+ dtype=object)
70
+
71
+ @property
72
+ def _ptr(self):
73
+ """
74
+ The underlying dense process matrix.
75
+ """
76
+ return _ProtectedArray(self._rep.base, indices_to_protect=[(0,slice(None,None,None)),
77
+ (slice(1,None, None), slice(1, None, None))])
78
+
79
+ def set_dense(self, m):
80
+ """
81
+ Set the dense-matrix value of this operation.
82
+
83
+ Attempts to modify operation parameters so that the specified raw
84
+ operation matrix becomes m. Will raise ValueError if this operation
85
+ is not possible.
86
+
87
+ Parameters
88
+ ----------
89
+ m : array_like or LinearOperator
90
+ An array of shape (dim, dim) or LinearOperator representing the operation action.
91
+
92
+ Returns
93
+ -------
94
+ None
95
+ """
96
+ mx = _LinearOperator.convert_to_matrix(m)
97
+ if(mx.shape != (self.dim, self.dim)):
98
+ raise ValueError("Argument must be a (%d,%d) matrix!"
99
+ % (self.dim, self.dim))
100
+ if not (_np.allclose(_np.diag(mx), 1) and _np.allclose((mx-_np.eye(mx.shape[0]))[:, 1:], 0.0)):
101
+ raise ValueError("Cannot create AffineShiftOp: "
102
+ "Matrix does not have the correct arrowhead structure")
103
+ #For further debugging: + "\n".join([str(e) for e in mx[0,:]])
104
+ self._ptr[1:, 0] = mx[1:, 0]
105
+ self._ptr_has_changed()
106
+ self.dirty = True
107
+
108
+ @property
109
+ def num_params(self):
110
+ """
111
+ Get the number of independent parameters which specify this operation.
112
+
113
+ Returns
114
+ -------
115
+ int
116
+ the number of independent parameters.
117
+ """
118
+ return self.dim-1
119
+
120
+ def to_vector(self):
121
+ """
122
+ Get the operation parameters as an array of values.
123
+
124
+ Returns
125
+ -------
126
+ numpy array
127
+ The operation parameters as a 1D array with length num_params().
128
+ """
129
+ # Use flatten (rather than ravel) to ensure a copy is made.
130
+ return self._ptr[1:,0].flatten() # .real in case of complex matrices?
131
+
132
+ def from_vector(self, v, close=False, dirty_value=True):
133
+ """
134
+ Initialize the operation using a vector of parameters.
135
+
136
+ Parameters
137
+ ----------
138
+ v : numpy array
139
+ The 1D vector of operation parameters. Length
140
+ must == num_params()
141
+
142
+ close : bool, optional
143
+ Whether `v` is close to this operation's current
144
+ set of parameters. Under some circumstances, when this
145
+ is true this call can be completed more quickly.
146
+
147
+ dirty_value : bool, optional
148
+ The value to set this object's "dirty flag" to before exiting this
149
+ call. This is passed as an argument so it can be updated *recursively*.
150
+ Leave this set to `True` unless you know what you're doing.
151
+
152
+ Returns
153
+ -------
154
+ None
155
+ """
156
+ #TODO: Circle back to comments about it being faster to directly
157
+ #operate on the rep.
158
+ #assert(self._ptr.shape == (self.dim, self.dim))
159
+ assert (len(v) == self.dim-1)
160
+ self._ptr[1:, 0] = v
161
+ #self._rep.base[1:, :] = v.reshape((self.dim - 1, self.dim)) # faster than line above
162
+ #self._rep.base.flat[self.dim:] = v # faster still
163
+ self._ptr_has_changed() # because _rep.base == _ptr (same memory)
164
+ self.dirty = dirty_value
165
+
166
+ def deriv_wrt_params(self, wrt_filter=None):
167
+ """
168
+ The element-wise derivative this operation.
169
+
170
+ Construct a matrix whose columns are the vectorized
171
+ derivatives of the flattened operation matrix with respect to a
172
+ single operation parameter. Thus, each column is of length
173
+ op_dim^2 and there is one column per operation parameter.
174
+
175
+ Parameters
176
+ ----------
177
+ wrt_filter : list or numpy.ndarray
178
+ List of parameter indices to take derivative with respect to.
179
+ (None means to use all the this operation's parameters.)
180
+
181
+ Returns
182
+ -------
183
+ numpy array
184
+ Array of derivatives with shape (dimension^2, num_params)
185
+ """
186
+ derivMx = _np.identity(self.dim**2, 'd') # TP operations are assumed to be real
187
+
188
+ derivMx = derivMx[:, self.dim::self.dim] # Extract only columns of derivMx matrix
189
+ #corresponding to the first column of the PTR less the first row.
190
+
191
+ if wrt_filter is None:
192
+ return derivMx
193
+ else:
194
+ return _np.take(derivMx, wrt_filter, axis=1)
195
+
196
+ def has_nonzero_hessian(self):
197
+ """
198
+ Whether this operation has a non-zero Hessian with respect to its parameters.
199
+
200
+ (i.e. whether it only depends linearly on its parameters or not)
201
+
202
+ Returns
203
+ -------
204
+ bool
205
+ """
206
+ return False
@@ -63,7 +63,7 @@ class ComposedErrorgen(_LinearOperator):
63
63
 
64
64
  if evotype == "auto":
65
65
  evotype = errgens_to_compose[0]._evotype
66
- evotype = _Evotype.cast(evotype)
66
+ evotype = _Evotype.cast(evotype, state_space=state_space)
67
67
  assert(all([evotype == eg._evotype for eg in errgens_to_compose])), \
68
68
  "All error generators must have the same evolution type (%s expected)!" % evotype
69
69
 
@@ -69,7 +69,7 @@ class ComposedOp(_LinearOperator):
69
69
  evotype = ops_to_compose[0]._evotype
70
70
  assert(all([evotype == operation._evotype for operation in ops_to_compose])), \
71
71
  "All operations must have the same evolution type (%s expected)!" % evotype
72
- evotype = _Evotype.cast(evotype)
72
+ evotype = _Evotype.cast(evotype, state_space=state_space)
73
73
 
74
74
  rep = self._create_rep_object(evotype, state_space)
75
75
 
@@ -491,10 +491,6 @@ class ComposedOp(_LinearOperator):
491
491
 
492
492
  self.terms[order] = terms
493
493
 
494
- #def _decompose_indices(x):
495
- # return tuple(_modelmember._decompose_gpindices(
496
- # self.gpindices, _np.array(x, _np.int64)))
497
-
498
494
  mapvec = _np.ascontiguousarray(_np.zeros(max_polynomial_vars, _np.int64))
499
495
  for ii, i in enumerate(gpindices_array):
500
496
  mapvec[i] = ii
@@ -555,25 +551,6 @@ class ComposedOp(_LinearOperator):
555
551
  if mag >= min_term_mag:
556
552
  terms.append(_term.compose_terms_with_mag(factors, mag))
557
553
  return terms
558
- #def _decompose_indices(x):
559
- # return tuple(_modelmember._decompose_gpindices(
560
- # self.gpindices, _np.array(x, _np.int64)))
561
- #
562
- #mapvec = _np.ascontiguousarray(_np.zeros(max_polynomial_vars,_np.int64))
563
- #for ii,i in enumerate(self.gpindices_as_array()):
564
- # mapvec[i] = ii
565
- #
566
- ##poly_coeffs = [t.coeff.map_indices(_decompose_indices) for t in terms] # with *local* indices
567
- #poly_coeffs = [t.coeff.mapvec_indices(mapvec) for t in terms] # with *local* indices
568
- #tapes = [poly.compact(complex_coeff_tape=True) for poly in poly_coeffs]
569
- #if len(tapes) > 0:
570
- # vtape = _np.concatenate([t[0] for t in tapes])
571
- # ctape = _np.concatenate([t[1] for t in tapes])
572
- #else:
573
- # vtape = _np.empty(0, _np.int64)
574
- # ctape = _np.empty(0, complex)
575
- #coeffs_as_compact_polys = (vtape, ctape)
576
- #self.local_term_poly_coeffs[order] = coeffs_as_compact_polys
577
554
 
578
555
  @property
579
556
  def total_term_magnitude(self):
@@ -313,7 +313,7 @@ class DenseOperator(DenseOperatorInterface, _KrausOperatorInterface, _LinearOper
313
313
  mx = _LinearOperator.convert_to_matrix(mx)
314
314
  state_space = _statespace.default_space_for_dim(mx.shape[0]) if (state_space is None) \
315
315
  else _statespace.StateSpace.cast(state_space)
316
- evotype = _Evotype.cast(evotype)
316
+ evotype = _Evotype.cast(evotype, state_space=state_space)
317
317
  self._basis = _Basis.cast(basis, state_space.dim) if (basis is not None) else None # for Hilbert-Schmidt space
318
318
  rep = evotype.create_dense_superop_rep(mx, self._basis, state_space)
319
319
  _LinearOperator.__init__(self, rep, evotype)
@@ -416,11 +416,11 @@ class DenseOperator(DenseOperatorInterface, _KrausOperatorInterface, _LinearOper
416
416
  #CHECK 1 (to unit test?) REMOVE
417
417
  #tmp_std = _bt.change_basis(superop_mx, self._basis, 'std')
418
418
  #B = _bt.basis_matrices('std', superop_mx.shape[0])
419
- #check_superop = sum([ choi_mx[i,j] * _np.kron(B[i], B[j].T) for i in range(d*d) for j in range(d*d)])
419
+ #check_superop = sum([ choi_mx[i,j] * _np.kron(B[i], B[j].conjugate()) for i in range(d*d) for j in range(d*d)])
420
420
  #assert(_np.allclose(check_superop, tmp_std))
421
421
 
422
- evals, evecs = _np.linalg.eig(choi_mx)
423
- #assert(_np.allclose(evecs @ _np.diag(evals) @ (evecs.conjugate().T), choi_mx))
422
+ evals, evecs = _np.linalg.eigh(choi_mx)
423
+ assert(_np.allclose(evecs @ _np.diag(evals) @ (evecs.conjugate().T), choi_mx))
424
424
  TOL = 1e-7 # consider lowering this tolerance as it leads to errors of this order in the Kraus decomp
425
425
  if any([ev <= -TOL for ev in evals]):
426
426
  raise ValueError("Cannot compute Kraus decomposition of non-positive-definite superoperator!")
@@ -533,7 +533,7 @@ class DenseUnitaryOperator(DenseOperatorInterface, _KrausOperatorInterface, _Lin
533
533
  state_space = _statespace.default_space_for_udim(mx.shape[0]) if (state_space is None) \
534
534
  else _statespace.StateSpace.cast(state_space)
535
535
  basis = _Basis.cast(basis, state_space.dim) # basis for Hilbert-Schmidt (superop) space
536
- evotype = _Evotype.cast(evotype)
536
+ evotype = _Evotype.cast(evotype, state_space=state_space)
537
537
 
538
538
  #Try to create a dense unitary rep. If this fails, see if a dense superop rep
539
539
  # can be created, as this type of rep can also hold arbitrary unitary ops.
@@ -432,13 +432,13 @@ class EigenvalueParamDenseOp(_DenseOperator):
432
432
  dMx = _np.zeros((self.dim, self.dim), 'complex')
433
433
  for prefactor, (i, j) in pdesc:
434
434
  dMx[i, j] = prefactor
435
- tmp = _np.dot(self.B, _np.dot(dMx, self.Bi))
435
+ tmp = self.B @ (dMx @ self.Bi)
436
436
  if _np.linalg.norm(tmp.imag) >= IMAG_TOL: # just a warning until we figure this out.
437
437
  print("EigenvalueParamDenseOp deriv_wrt_params WARNING:"
438
438
  " Imag part = ", _np.linalg.norm(tmp.imag), " pdesc = ", pdesc) # pragma: no cover
439
439
  #assert(_np.linalg.norm(tmp.imag) < IMAG_TOL), \
440
440
  # "Imaginary mag = %g!" % _np.linalg.norm(tmp.imag)
441
- derivMx[:, k] = tmp.real.flatten()
441
+ derivMx[:, k] = tmp.real.ravel()
442
442
 
443
443
  if wrt_filter is None:
444
444
  return derivMx
@@ -11,10 +11,10 @@ The EmbeddedErrorgen class and supporting functionality.
11
11
  #***************************************************************************************************
12
12
 
13
13
  import collections as _collections
14
+ from pygsti.baseobjs.basis import Basis as _Basis
14
15
  import warnings as _warnings
15
16
 
16
17
  from pygsti.modelmembers.operations.embeddedop import EmbeddedOp as _EmbeddedOp
17
- from pygsti.baseobjs.basis import Basis as _Basis, EmbeddedBasis as _EmbeddedBasis
18
18
 
19
19
 
20
20
  # Idea:
@@ -18,7 +18,6 @@ import scipy.sparse as _sps
18
18
 
19
19
  from pygsti.modelmembers.operations.linearop import LinearOperator as _LinearOperator
20
20
  from pygsti.modelmembers import modelmember as _modelmember
21
- from pygsti.baseobjs.basis import EmbeddedBasis as _EmbeddedBasis
22
21
  from pygsti.baseobjs.statespace import StateSpace as _StateSpace
23
22
 
24
23
 
@@ -699,10 +699,13 @@ class ExpErrorgenOp(_LinearOperator, _ErrorGeneratorContainer):
699
699
 
700
700
  #just act on postfactor and Lindbladian exponent:
701
701
  if typ == "prep":
702
- mx = _mt.safe_dot(Uinv, mx)
702
+ mx = Uinv @ mx
703
703
  else:
704
- mx = _mt.safe_dot(mx, U)
704
+ mx = mx @ U
705
705
  self.set_dense(mx) # calls _update_rep() and sets dirty flag
706
+ else:
707
+ raise ValueError("Invalid transform for this LindbladErrorgen: type %s"
708
+ % str(type(s)))
706
709
 
707
710
  def __str__(self):
708
711
  s = "Exponentiated operation map with dim = %d, num params = %d\n" % \
@@ -93,6 +93,7 @@ class FullArbitraryOp(_DenseOperator):
93
93
  numpy array
94
94
  The operation parameters as a 1D array with length num_params().
95
95
  """
96
+ # Use flatten (rather than ravel) to ensure a copy is made.
96
97
  return self._ptr.flatten()
97
98
 
98
99
  def from_vector(self, v, close=False, dirty_value=True):
@@ -42,7 +42,7 @@ class FullCPTPOp(_KrausOperatorInterface, _LinearOperator):
42
42
  choi_mx = _LinearOperator.convert_to_matrix(choi_mx)
43
43
  state_space = _statespace.default_space_for_dim(choi_mx.shape[0]) if (state_space is None) \
44
44
  else _statespace.StateSpace.cast(state_space)
45
- evotype = _Evotype.cast(evotype)
45
+ evotype = _Evotype.cast(evotype, state_space=state_space)
46
46
  self._basis = _Basis.cast(basis, state_space.dim) if (basis is not None) else None # for Hilbert-Schmidt space
47
47
 
48
48
  #scratch space
@@ -93,7 +93,7 @@ class FullCPTPOp(_KrausOperatorInterface, _LinearOperator):
93
93
  Lmx = _np.linalg.cholesky(choi_mx)
94
94
 
95
95
  #check TP condition: that diagonal els of Lmx squared add to 1.0
96
- Lmx_norm = _np.trace(_np.dot(Lmx.T.conjugate(), Lmx)) # sum of magnitude^2 of all els
96
+ Lmx_norm = _np.linalg.norm(Lmx) # = sqrt(tr(Lmx' Lmx))
97
97
  assert(_np.isclose(Lmx_norm, 1.0)), "Cholesky decomp didn't preserve trace=1!"
98
98
 
99
99
  self.params = _np.empty(dim**2, 'd')
@@ -10,14 +10,25 @@ The FullTPOp class and supporting functionality.
10
10
  # http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
11
11
  #***************************************************************************************************
12
12
 
13
- import numpy as _np
13
+ from __future__ import annotations
14
+ from typing import Tuple, TYPE_CHECKING
15
+ if TYPE_CHECKING:
16
+ import torch as _torch
17
+ try:
18
+ import torch as _torch
19
+ except ImportError:
20
+ pass
14
21
 
22
+ import numpy as _np
15
23
  from pygsti.modelmembers.operations.denseop import DenseOperator as _DenseOperator
16
24
  from pygsti.modelmembers.operations.linearop import LinearOperator as _LinearOperator
17
25
  from pygsti.baseobjs.protectedarray import ProtectedArray as _ProtectedArray
26
+ from pygsti.modelmembers.torchable import Torchable as _Torchable
27
+
28
+
18
29
 
19
30
 
20
- class FullTPOp(_DenseOperator):
31
+ class FullTPOp(_DenseOperator, _Torchable):
21
32
  """
22
33
  A trace-preserving operation matrix.
23
34
 
@@ -52,11 +63,9 @@ class FullTPOp(_DenseOperator):
52
63
  """
53
64
 
54
65
  def __init__(self, m, basis=None, evotype="default", state_space=None):
55
- #LinearOperator.__init__(self, LinearOperator.convert_to_matrix(m))
56
66
  mx = _LinearOperator.convert_to_matrix(m)
57
67
  assert(_np.isrealobj(mx)), "FullTPOp must have *real* values!"
58
- if not (_np.isclose(mx[0, 0], 1.0)
59
- and _np.allclose(mx[0, 1:], 0.0)):
68
+ if not (_np.isclose(mx[0, 0], 1.0) and _np.allclose(mx[0, 1:], 0.0)):
60
69
  raise ValueError("Cannot create FullTPOp: "
61
70
  "invalid form for 1st row!")
62
71
  _DenseOperator.__init__(self, mx, basis, evotype, state_space)
@@ -122,7 +131,7 @@ class FullTPOp(_DenseOperator):
122
131
  numpy array
123
132
  The operation parameters as a 1D array with length num_params().
124
133
  """
125
- return self._ptr.flatten()[self.dim:] # .real in case of complex matrices?
134
+ return self._ptr.ravel()[self.dim:].copy() # .real in case of complex matrices?
126
135
 
127
136
  def from_vector(self, v, close=False, dirty_value=True):
128
137
  """
@@ -155,6 +164,19 @@ class FullTPOp(_DenseOperator):
155
164
  self._ptr_has_changed() # because _rep.base == _ptr (same memory)
156
165
  self.dirty = dirty_value
157
166
 
167
+ def stateless_data(self) -> Tuple[int]:
168
+ return (self.dim,)
169
+
170
+ @staticmethod
171
+ def torch_base(sd: Tuple[int], t_param: _torch.Tensor) -> _torch.Tensor:
172
+ dim = sd[0]
173
+ t_const = _torch.zeros(size=(1, dim), dtype=_torch.double)
174
+ t_const[0,0] = 1.0
175
+ t_param_mat = t_param.reshape((dim - 1, dim))
176
+ t = _torch.row_stack((t_const, t_param_mat))
177
+ return t
178
+
179
+
158
180
  def deriv_wrt_params(self, wrt_filter=None):
159
181
  """
160
182
  The element-wise derivative this operation.
@@ -98,7 +98,8 @@ class FullUnitaryOp(_DenseUnitaryOperator):
98
98
  numpy array
99
99
  The operation parameters as a 1D array with length num_params().
100
100
  """
101
- return _np.concatenate((self._ptr.real.flatten(), self._ptr.imag.flatten()), axis=0)
101
+ # _np.concatenate will make a copy for us, so use ravel instead of flatten.
102
+ return _np.concatenate((self._ptr.real.ravel(), self._ptr.imag.ravel()), axis=0)
102
103
 
103
104
  def from_vector(self, v, close=False, dirty_value=True):
104
105
  """
@@ -200,7 +201,7 @@ class FullUnitaryOp(_DenseUnitaryOperator):
200
201
  Uinv = s.transform_matrix_inverse
201
202
 
202
203
  my_superop_mx = _ot.unitary_to_superop(self._ptr, self._basis)
203
- my_superop_mx = _mt.safe_dot(Uinv, _mt.safe_dot(my_superop_mx, U))
204
+ my_superop_mx = Uinv @ (my_superop_mx @ U)
204
205
 
205
206
  self._ptr[:, :] = _ot.superop_to_unitary(my_superop_mx, self._basis)
206
207
  self._ptr_has_changed()
@@ -250,9 +251,9 @@ class FullUnitaryOp(_DenseUnitaryOperator):
250
251
 
251
252
  #Note: this code may need to be tweaked to work with sparse matrices
252
253
  if typ == "prep":
253
- my_superop_mx = _mt.safe_dot(Uinv, my_superop_mx)
254
+ my_superop_mx = Uinv @ my_superop_mx
254
255
  else:
255
- my_superop_mx = _mt.safe_dot(my_superop_mx, U)
256
+ my_superop_mx = my_superop_mx @ U
256
257
 
257
258
  self._ptr[:, :] = _ot.superop_to_unitary(my_superop_mx, self._basis)
258
259
  self._ptr_has_changed()