pyGSTi 0.9.12.1__cp38-cp38-win_amd64.whl → 0.9.13__cp38-cp38-win_amd64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. pyGSTi-0.9.13.dist-info/METADATA +185 -0
  2. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +207 -217
  3. {pyGSTi-0.9.12.1.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 +42 -28
  7. pygsti/algorithms/fiducialselection.py +17 -8
  8. pygsti/algorithms/gaugeopt.py +2 -2
  9. pygsti/algorithms/germselection.py +87 -77
  10. pygsti/algorithms/mirroring.py +0 -388
  11. pygsti/algorithms/randomcircuit.py +165 -1333
  12. pygsti/algorithms/rbfit.py +0 -234
  13. pygsti/baseobjs/basis.py +94 -396
  14. pygsti/baseobjs/errorgenbasis.py +0 -132
  15. pygsti/baseobjs/errorgenspace.py +0 -10
  16. pygsti/baseobjs/label.py +52 -168
  17. pygsti/baseobjs/opcalc/fastopcalc.cp38-win_amd64.pyd +0 -0
  18. pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
  19. pygsti/baseobjs/polynomial.py +13 -595
  20. pygsti/baseobjs/statespace.py +1 -0
  21. pygsti/circuits/__init__.py +1 -1
  22. pygsti/circuits/circuit.py +682 -505
  23. pygsti/circuits/circuitconstruction.py +0 -4
  24. pygsti/circuits/circuitlist.py +47 -5
  25. pygsti/circuits/circuitparser/__init__.py +8 -8
  26. pygsti/circuits/circuitparser/fastcircuitparser.cp38-win_amd64.pyd +0 -0
  27. pygsti/circuits/circuitstructure.py +3 -3
  28. pygsti/circuits/cloudcircuitconstruction.py +1 -1
  29. pygsti/data/datacomparator.py +2 -7
  30. pygsti/data/dataset.py +46 -44
  31. pygsti/data/hypothesistest.py +0 -7
  32. pygsti/drivers/bootstrap.py +0 -49
  33. pygsti/drivers/longsequence.py +2 -1
  34. pygsti/evotypes/basereps_cython.cp38-win_amd64.pyd +0 -0
  35. pygsti/evotypes/chp/opreps.py +0 -61
  36. pygsti/evotypes/chp/statereps.py +0 -32
  37. pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
  38. pygsti/evotypes/densitymx/effectreps.cp38-win_amd64.pyd +0 -0
  39. pygsti/evotypes/densitymx/effectreps.pyx +1 -1
  40. pygsti/evotypes/densitymx/opreps.cp38-win_amd64.pyd +0 -0
  41. pygsti/evotypes/densitymx/opreps.pyx +2 -2
  42. pygsti/evotypes/densitymx/statereps.cp38-win_amd64.pyd +0 -0
  43. pygsti/evotypes/densitymx/statereps.pyx +1 -1
  44. pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
  45. pygsti/evotypes/densitymx_slow/opreps.py +16 -23
  46. pygsti/evotypes/densitymx_slow/statereps.py +10 -3
  47. pygsti/evotypes/evotype.py +39 -2
  48. pygsti/evotypes/stabilizer/effectreps.cp38-win_amd64.pyd +0 -0
  49. pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
  50. pygsti/evotypes/stabilizer/opreps.cp38-win_amd64.pyd +0 -0
  51. pygsti/evotypes/stabilizer/opreps.pyx +0 -4
  52. pygsti/evotypes/stabilizer/statereps.cp38-win_amd64.pyd +0 -0
  53. pygsti/evotypes/stabilizer/statereps.pyx +1 -5
  54. pygsti/evotypes/stabilizer/termreps.cp38-win_amd64.pyd +0 -0
  55. pygsti/evotypes/stabilizer/termreps.pyx +0 -7
  56. pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
  57. pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
  58. pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
  59. pygsti/evotypes/statevec/effectreps.cp38-win_amd64.pyd +0 -0
  60. pygsti/evotypes/statevec/effectreps.pyx +1 -1
  61. pygsti/evotypes/statevec/opreps.cp38-win_amd64.pyd +0 -0
  62. pygsti/evotypes/statevec/opreps.pyx +2 -2
  63. pygsti/evotypes/statevec/statereps.cp38-win_amd64.pyd +0 -0
  64. pygsti/evotypes/statevec/statereps.pyx +1 -1
  65. pygsti/evotypes/statevec/termreps.cp38-win_amd64.pyd +0 -0
  66. pygsti/evotypes/statevec/termreps.pyx +0 -7
  67. pygsti/evotypes/statevec_slow/effectreps.py +0 -3
  68. pygsti/evotypes/statevec_slow/opreps.py +0 -5
  69. pygsti/extras/__init__.py +0 -1
  70. pygsti/extras/drift/stabilityanalyzer.py +3 -1
  71. pygsti/extras/interpygate/__init__.py +12 -0
  72. pygsti/extras/interpygate/core.py +0 -36
  73. pygsti/extras/interpygate/process_tomography.py +44 -10
  74. pygsti/extras/rpe/rpeconstruction.py +0 -2
  75. pygsti/forwardsims/__init__.py +1 -0
  76. pygsti/forwardsims/forwardsim.py +14 -55
  77. pygsti/forwardsims/mapforwardsim.py +69 -18
  78. pygsti/forwardsims/mapforwardsim_calc_densitymx.cp38-win_amd64.pyd +0 -0
  79. pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
  80. pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
  81. pygsti/forwardsims/matrixforwardsim.py +63 -15
  82. pygsti/forwardsims/termforwardsim.py +8 -110
  83. pygsti/forwardsims/termforwardsim_calc_stabilizer.cp38-win_amd64.pyd +0 -0
  84. pygsti/forwardsims/termforwardsim_calc_statevec.cp38-win_amd64.pyd +0 -0
  85. pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
  86. pygsti/forwardsims/torchfwdsim.py +265 -0
  87. pygsti/forwardsims/weakforwardsim.py +2 -2
  88. pygsti/io/__init__.py +1 -2
  89. pygsti/io/mongodb.py +0 -2
  90. pygsti/io/stdinput.py +6 -22
  91. pygsti/layouts/copalayout.py +10 -12
  92. pygsti/layouts/distlayout.py +0 -40
  93. pygsti/layouts/maplayout.py +103 -25
  94. pygsti/layouts/matrixlayout.py +99 -60
  95. pygsti/layouts/prefixtable.py +1534 -52
  96. pygsti/layouts/termlayout.py +1 -1
  97. pygsti/modelmembers/instruments/instrument.py +3 -3
  98. pygsti/modelmembers/instruments/tpinstrument.py +2 -2
  99. pygsti/modelmembers/modelmember.py +0 -17
  100. pygsti/modelmembers/operations/__init__.py +2 -4
  101. pygsti/modelmembers/operations/affineshiftop.py +1 -0
  102. pygsti/modelmembers/operations/composederrorgen.py +1 -1
  103. pygsti/modelmembers/operations/composedop.py +1 -24
  104. pygsti/modelmembers/operations/denseop.py +5 -5
  105. pygsti/modelmembers/operations/eigpdenseop.py +2 -2
  106. pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
  107. pygsti/modelmembers/operations/embeddedop.py +0 -1
  108. pygsti/modelmembers/operations/experrorgenop.py +2 -2
  109. pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
  110. pygsti/modelmembers/operations/fullcptpop.py +2 -2
  111. pygsti/modelmembers/operations/fulltpop.py +28 -6
  112. pygsti/modelmembers/operations/fullunitaryop.py +5 -4
  113. pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
  114. pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
  115. pygsti/modelmembers/operations/linearop.py +7 -27
  116. pygsti/modelmembers/operations/opfactory.py +1 -1
  117. pygsti/modelmembers/operations/repeatedop.py +1 -24
  118. pygsti/modelmembers/operations/staticstdop.py +1 -1
  119. pygsti/modelmembers/povms/__init__.py +3 -3
  120. pygsti/modelmembers/povms/basepovm.py +7 -36
  121. pygsti/modelmembers/povms/complementeffect.py +4 -9
  122. pygsti/modelmembers/povms/composedeffect.py +0 -320
  123. pygsti/modelmembers/povms/computationaleffect.py +1 -1
  124. pygsti/modelmembers/povms/computationalpovm.py +3 -1
  125. pygsti/modelmembers/povms/effect.py +3 -5
  126. pygsti/modelmembers/povms/marginalizedpovm.py +0 -79
  127. pygsti/modelmembers/povms/tppovm.py +74 -2
  128. pygsti/modelmembers/states/__init__.py +2 -5
  129. pygsti/modelmembers/states/composedstate.py +0 -317
  130. pygsti/modelmembers/states/computationalstate.py +3 -3
  131. pygsti/modelmembers/states/cptpstate.py +4 -4
  132. pygsti/modelmembers/states/densestate.py +6 -4
  133. pygsti/modelmembers/states/fullpurestate.py +0 -24
  134. pygsti/modelmembers/states/purestate.py +1 -1
  135. pygsti/modelmembers/states/state.py +5 -6
  136. pygsti/modelmembers/states/tpstate.py +28 -10
  137. pygsti/modelmembers/term.py +3 -6
  138. pygsti/modelmembers/torchable.py +50 -0
  139. pygsti/modelpacks/_modelpack.py +1 -1
  140. pygsti/modelpacks/smq1Q_ZN.py +3 -1
  141. pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
  142. pygsti/modelpacks/smq2Q_XY.py +3 -3
  143. pygsti/modelpacks/smq2Q_XYI.py +2 -2
  144. pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
  145. pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
  146. pygsti/modelpacks/smq2Q_XYXX.py +1 -1
  147. pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
  148. pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
  149. pygsti/modelpacks/stdtarget.py +0 -121
  150. pygsti/models/cloudnoisemodel.py +1 -2
  151. pygsti/models/explicitcalc.py +3 -3
  152. pygsti/models/explicitmodel.py +3 -13
  153. pygsti/models/fogistore.py +5 -3
  154. pygsti/models/localnoisemodel.py +1 -2
  155. pygsti/models/memberdict.py +0 -12
  156. pygsti/models/model.py +800 -65
  157. pygsti/models/modelconstruction.py +4 -4
  158. pygsti/models/modelnoise.py +2 -2
  159. pygsti/models/modelparaminterposer.py +1 -1
  160. pygsti/models/oplessmodel.py +1 -1
  161. pygsti/models/qutrit.py +15 -14
  162. pygsti/objectivefns/objectivefns.py +73 -138
  163. pygsti/objectivefns/wildcardbudget.py +2 -7
  164. pygsti/optimize/__init__.py +1 -0
  165. pygsti/optimize/arraysinterface.py +28 -0
  166. pygsti/optimize/customcg.py +0 -12
  167. pygsti/optimize/customlm.py +129 -323
  168. pygsti/optimize/customsolve.py +2 -2
  169. pygsti/optimize/optimize.py +0 -84
  170. pygsti/optimize/simplerlm.py +841 -0
  171. pygsti/optimize/wildcardopt.py +19 -598
  172. pygsti/protocols/confidenceregionfactory.py +28 -14
  173. pygsti/protocols/estimate.py +31 -14
  174. pygsti/protocols/gst.py +142 -68
  175. pygsti/protocols/modeltest.py +6 -10
  176. pygsti/protocols/protocol.py +9 -37
  177. pygsti/protocols/rb.py +450 -79
  178. pygsti/protocols/treenode.py +8 -2
  179. pygsti/protocols/vb.py +108 -206
  180. pygsti/protocols/vbdataframe.py +1 -1
  181. pygsti/report/factory.py +0 -15
  182. pygsti/report/fogidiagram.py +1 -17
  183. pygsti/report/modelfunction.py +12 -3
  184. pygsti/report/mpl_colormaps.py +1 -1
  185. pygsti/report/plothelpers.py +8 -2
  186. pygsti/report/reportables.py +41 -37
  187. pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
  188. pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
  189. pygsti/report/workspace.py +2 -14
  190. pygsti/report/workspaceplots.py +326 -504
  191. pygsti/tools/basistools.py +9 -36
  192. pygsti/tools/edesigntools.py +124 -96
  193. pygsti/tools/fastcalc.cp38-win_amd64.pyd +0 -0
  194. pygsti/tools/fastcalc.pyx +35 -81
  195. pygsti/tools/internalgates.py +151 -15
  196. pygsti/tools/jamiolkowski.py +5 -5
  197. pygsti/tools/lindbladtools.py +19 -11
  198. pygsti/tools/listtools.py +0 -114
  199. pygsti/tools/matrixmod2.py +1 -1
  200. pygsti/tools/matrixtools.py +173 -339
  201. pygsti/tools/nameddict.py +1 -1
  202. pygsti/tools/optools.py +154 -88
  203. pygsti/tools/pdftools.py +0 -25
  204. pygsti/tools/rbtheory.py +3 -320
  205. pygsti/tools/slicetools.py +64 -12
  206. pyGSTi-0.9.12.1.dist-info/METADATA +0 -155
  207. pygsti/algorithms/directx.py +0 -711
  208. pygsti/evotypes/qibo/__init__.py +0 -33
  209. pygsti/evotypes/qibo/effectreps.py +0 -78
  210. pygsti/evotypes/qibo/opreps.py +0 -376
  211. pygsti/evotypes/qibo/povmreps.py +0 -98
  212. pygsti/evotypes/qibo/statereps.py +0 -174
  213. pygsti/extras/rb/__init__.py +0 -13
  214. pygsti/extras/rb/benchmarker.py +0 -957
  215. pygsti/extras/rb/dataset.py +0 -378
  216. pygsti/extras/rb/io.py +0 -814
  217. pygsti/extras/rb/simulate.py +0 -1020
  218. pygsti/io/legacyio.py +0 -385
  219. pygsti/modelmembers/povms/denseeffect.py +0 -142
  220. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
  221. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
pygsti/tools/nameddict.py CHANGED
@@ -88,7 +88,7 @@ class NamedDict(dict, _NicelySerializable):
88
88
  #TODO: serialize via _to_memoized_dict once we have a base class
89
89
  if x is None or isinstance(x, (float, int, str)):
90
90
  return x
91
- elif isinstance(x, _np.int64):
91
+ elif isinstance(x, (_np.int64, _np.int32)):
92
92
  return int(x)
93
93
  elif isinstance(x, _NicelySerializable):
94
94
  return x.to_nice_serialization()
pygsti/tools/optools.py CHANGED
@@ -34,28 +34,17 @@ IMAG_TOL = 1e-7 # tolerance for imaginary part being considered zero
34
34
  def _flat_mut_blks(i, j, block_dims):
35
35
  # like _mut(i,j,dim).flatten() but works with basis *blocks*
36
36
  N = sum(block_dims)
37
- mx = _np.zeros((N, N), 'd'); mx[i, j] = 1.0
37
+ mx = _np.zeros((N, N), 'd')
38
+ mx[i, j] = 1.0
38
39
  ret = _np.zeros(sum([d**2 for d in block_dims]), 'd')
39
40
  i = 0; off = 0
40
41
  for d in block_dims:
41
- ret[i:i + d**2] = mx[off:off + d, off:off + d].flatten()
42
- i += d**2; off += d
42
+ ret[i:i + d**2] = mx[off:off + d, off:off + d].ravel()
43
+ i += d**2
44
+ off += d
43
45
  return ret
44
46
 
45
47
 
46
- def _hack_sqrtm(a):
47
- sqrt, _ = _spl.sqrtm(a, disp=False) # Travis found this scipy function
48
- # to be incorrect in certain cases (we need a workaround)
49
- if _np.any(_np.isnan(sqrt)): # this is sometimes a good fallback when sqrtm doesn't work.
50
- ev, U = _np.linalg.eig(a)
51
- sqrt = _np.dot(U, _np.dot(_np.diag(_np.sqrt(ev)), _np.linalg.inv(U)))
52
- # Scipy 1.10 fix for PR 16294 (which doubles precision of complex to complex)
53
- if _np.iscomplexobj(a):
54
- sqrt = sqrt.astype(a.dtype, copy=False)
55
-
56
- return sqrt
57
-
58
-
59
48
  def fidelity(a, b):
60
49
  """
61
50
  Returns the quantum state fidelity between density matrices.
@@ -81,41 +70,120 @@ def fidelity(a, b):
81
70
  float
82
71
  The resulting fidelity.
83
72
  """
84
- evals, U = _np.linalg.eig(a)
85
- if len([ev for ev in evals if abs(ev) > 1e-8]) == 1:
86
- # special case when a is rank 1, a = vec * vec^T and sqrt(a) = a
87
- ivec = _np.argmax(evals)
88
- vec = U[:, ivec:(ivec + 1)]
89
- F = evals[ivec].real * _np.dot(_np.conjugate(_np.transpose(vec)), _np.dot(b, vec)).real # vec^T * b * vec
90
- return float(F[0, 0])
91
-
92
- evals, U = _np.linalg.eig(b)
93
- if len([ev for ev in evals if abs(ev) > 1e-8]) == 1:
94
- # special case when b is rank 1 (recally fidelity is sym in args)
95
- ivec = _np.argmax(evals)
96
- vec = U[:, ivec:(ivec + 1)]
97
- F = evals[ivec].real * _np.dot(_np.conjugate(_np.transpose(vec)), _np.dot(a, vec)).real # vec^T * a * vec
98
- return float(F[0, 0])
99
-
100
- #if _np.array_equal(a, b): return 1.0 # HACK - some cases when a and b are perfecty equal sqrtm(a) fails...
101
- sqrtA = _hack_sqrtm(a) # _spl.sqrtm(a)
102
- # test the scipy sqrtm function - sometimes fails when rank defficient
103
- #assert(_np.linalg.norm(_np.dot(sqrtA, sqrtA) - a) < 1e-8)
104
- if _np.linalg.norm(_np.dot(sqrtA, sqrtA) - a) > 1e-8:
105
- evals = _np.linalg.eigvals(a)
106
- _warnings.warn(("sqrtm(a) failure when computing fidelity - beware result. "
107
- "Maybe due to rank defficiency - eigenvalues of a are: %s") % evals)
108
- F = (_mt.trace(_hack_sqrtm(_np.dot(sqrtA, _np.dot(b, sqrtA)))).real)**2 # Tr( sqrt{ sqrt(a) * b * sqrt(a) } )^2
109
- return float(F)
73
+ __SCALAR_TOL__ = _np.finfo(a.dtype).eps ** 0.75
74
+ # ^ use for checks that have no dimensional dependence; about 1e-12 for double precision.
75
+ __VECTOR_TOL__ = (a.shape[0] ** 0.5) * __SCALAR_TOL__
76
+ # ^ use for checks that do have dimensional dependence (will naturally increase for larger matrices)
77
+
78
+ def assert_hermitian(mat):
79
+ hermiticity_error = _np.abs(mat - mat.T.conj())
80
+ if _np.any(hermiticity_error > __SCALAR_TOL__):
81
+ message = f"""
82
+ Input matrix 'mat' is not Hermitian, up to tolerance {__SCALAR_TOL__}.
83
+ The absolute values of entries in (mat - mat^H) are \n{hermiticity_error}.
84
+ """
85
+ raise ValueError(message)
86
+
87
+ assert_hermitian(a)
88
+ assert_hermitian(b)
89
+
90
+ def check_rank_one_density(mat):
91
+ """
92
+ mat is Hermitian of order n. This function uses an O(n^2) time randomized algorithm to
93
+ test if mat is a PSD matrix of rank 0 or 1. It returns a tuple (r, vec), where
94
+
95
+ If r == 0, then vec is the zero vector. Either mat's numerical rank is zero
96
+ OR the projection of mat onto the set of PSD matrices is zero.
97
+
98
+ If r == 1, then mat is a PSD matrix of numerical rank one, and vec is mat's
99
+ unique nontrivial eigenvector.
100
+
101
+ If r == 2, then vec is None and our best guess is that mat's (numerical) rank
102
+ is at least two. In exact arithmetic, this "guess" is correct with probability
103
+ one. Additional computations will be needed to determine if mat is PSD.
104
+
105
+ Conceptually, this function just takes a single step of the power iteration method
106
+ for estimating mat's largest eigenvalue (with size measured in absolute value).
107
+ See https://en.wikipedia.org/wiki/Power_iteration for more information.
108
+ """
109
+ n = mat.shape[0]
110
+
111
+ if _np.linalg.norm(mat) < __VECTOR_TOL__:
112
+ # We prefer to return the zero vector instead of None to simplify how we handle
113
+ # this function's output.
114
+ return 0, _np.zeros(n, dtype=complex)
115
+
116
+ _np.random.seed(0)
117
+ test_vec = _np.random.randn(n) + 1j * _np.random.randn(n)
118
+ test_vec /= _np.linalg.norm(test_vec)
119
+
120
+ candidate_v = mat @ test_vec
121
+ candidate_v /= _np.linalg.norm(candidate_v)
122
+ alpha = _np.real(candidate_v.conj() @ mat @ candidate_v)
123
+ reconstruction = alpha * _np.outer(candidate_v, candidate_v.conj())
124
+
125
+ if _np.linalg.norm(mat - reconstruction) > __VECTOR_TOL__:
126
+ # We can't certify that mat is rank-1.
127
+ return 2, None
128
+
129
+ if alpha <= 0.0:
130
+ # Ordinarily we'd project out the negative eigenvalues and proceed with the
131
+ # PSD part of the matrix, but at this point we know that the PSD part is zero.
132
+ return 0, _np.zeros(n)
133
+
134
+ if abs(alpha - 1) > __SCALAR_TOL__:
135
+ message = f"The input matrix is not trace-1 up to tolerance {__SCALAR_TOL__}. Beware result!"
136
+ _warnings.warn(message)
137
+ candidate_v *= _np.sqrt(alpha)
138
+
139
+ return 1, candidate_v
140
+
141
+ r, vec = check_rank_one_density(a)
142
+ if r <= 1:
143
+ # special case when a is rank 1, a = vec * vec^T.
144
+ f = (vec.T.conj() @ b @ vec).real # vec^T * b * vec
145
+ return f
146
+
147
+ r, vec = check_rank_one_density(b)
148
+ if r <= 1:
149
+ # special case when b is rank 1 (recall fidelity is sym in args)
150
+ f = (vec.T.conj() @ a @ vec).real # vec^T * a * vec
151
+ return f
152
+
153
+ # Neither a nor b are rank-1. We need to actually evaluate the matrix square root of
154
+ # one of them. We do this with an eigendecomposition, since this lets us check for
155
+ # negative eigenvalues and raise a warning if needed.
156
+
157
+ def psd_square_root(mat):
158
+ evals, U = _np.linalg.eigh(mat)
159
+ if _np.min(evals) < -__SCALAR_TOL__:
160
+ message = f"""
161
+ Input matrix is not PSD up to tolerance {__SCALAR_TOL__}.
162
+ We'll project out the bad eigenspaces to only work with the PSD part.
163
+ """
164
+ _warnings.warn(message)
165
+ evals[evals < 0] = 0.0
166
+ tr = _np.sum(evals)
167
+ if abs(tr - 1) > __VECTOR_TOL__:
168
+ message = f"""
169
+ The PSD part of the input matrix is not trace-1 up to tolerance {__VECTOR_TOL__}.
170
+ Beware result!
171
+ """
172
+ _warnings.warn(message)
173
+ sqrt_mat = U @ (_np.sqrt(evals).reshape((-1, 1)) * U.T.conj())
174
+ return sqrt_mat
175
+
176
+ sqrt_a = psd_square_root(a)
177
+ tr_arg = psd_square_root(sqrt_a @ b @ sqrt_a)
178
+ f = _np.trace(tr_arg).real ** 2 # Tr( sqrt{ sqrt(a) * b * sqrt(a) } )^2
179
+ return f
110
180
 
111
181
 
112
182
  def frobeniusdist(a, b):
113
183
  """
114
- Returns the frobenius distance between gate or density matrices.
115
-
116
- This is given by :
184
+ Returns the frobenius distance between arrays: ||a - b||_Fro.
117
185
 
118
- `sqrt( sum( (a_ij-b_ij)^2 ) )`
186
+ This could be inlined, but we're keeping it for API consistency with other distance functions.
119
187
 
120
188
  Parameters
121
189
  ----------
@@ -130,16 +198,14 @@ def frobeniusdist(a, b):
130
198
  float
131
199
  The resulting frobenius distance.
132
200
  """
133
- return _mt.frobeniusnorm(a - b)
201
+ return _np.linalg.norm(a - b)
134
202
 
135
203
 
136
204
  def frobeniusdist_squared(a, b):
137
205
  """
138
- Returns the square of the frobenius distance between gate or density matrices.
206
+ Returns the square of the frobenius distance between arrays: (||a - b||_Fro)^2.
139
207
 
140
- This is given by :
141
-
142
- `sum( (A_ij-B_ij)^2 )`
208
+ This could be inlined, but we're keeping it for API consistency with other distance functions.
143
209
 
144
210
  Parameters
145
211
  ----------
@@ -154,27 +220,7 @@ def frobeniusdist_squared(a, b):
154
220
  float
155
221
  The resulting frobenius distance.
156
222
  """
157
- return _mt.frobeniusnorm_squared(a - b)
158
-
159
-
160
- def residuals(a, b):
161
- """
162
- Calculate residuals between the elements of two matrices
163
-
164
- Parameters
165
- ----------
166
- a : numpy array
167
- First matrix.
168
-
169
- b : numpy array
170
- Second matrix.
171
-
172
- Returns
173
- -------
174
- np.array
175
- residuals
176
- """
177
- return (a - b).flatten()
223
+ return frobeniusdist(a, b)**2
178
224
 
179
225
 
180
226
  def tracenorm(a):
@@ -402,11 +448,13 @@ def entanglement_fidelity(a, b, mx_basis='pp', is_tp=None, is_unitary=None):
402
448
 
403
449
  Parameters
404
450
  ----------
405
- a : numpy array
406
- First matrix.
451
+ a : array or gate
452
+ The gate to compute the entanglement fidelity to b of. E.g., an
453
+ imperfect implementation of b.
407
454
 
408
- b : numpy array
409
- Second matrix.
455
+ b : array or gate
456
+ The gate to compute the entanglement fidelity to a of. E.g., the
457
+ target gate corresponding to a.
410
458
 
411
459
  mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object
412
460
  The basis of the matrices. Allowed values are Matrix-unit (std),
@@ -430,6 +478,15 @@ def entanglement_fidelity(a, b, mx_basis='pp', is_tp=None, is_unitary=None):
430
478
  -------
431
479
  float
432
480
  """
481
+ from pygsti.modelmembers.operations.linearop import LinearOperator as _LinearOperator
482
+
483
+ # Attempt to cast to dense array. If this is already an array, the AttributeError
484
+ # will be suppressed.
485
+ if isinstance(a, _LinearOperator):
486
+ a = a.to_dense()
487
+ if isinstance(b, _LinearOperator):
488
+ b = b.to_dense()
489
+
433
490
  d2 = a.shape[0]
434
491
 
435
492
  #if the tp flag isn't set we'll calculate whether it is true here
@@ -504,6 +561,12 @@ def average_gate_fidelity(a, b, mx_basis='pp', is_tp=None, is_unitary=None):
504
561
  AGI : float
505
562
  The AGI of a to b.
506
563
  """
564
+ from pygsti.modelmembers.operations.linearop import LinearOperator as _LinearOperator
565
+
566
+ # Cast to dense to ensure we can extract the shape.
567
+ if isinstance(a, _LinearOperator):
568
+ a = a.to_dense()
569
+
507
570
  d = int(round(_np.sqrt(a.shape[0])))
508
571
  PF = entanglement_fidelity(a, b, mx_basis, is_tp, is_unitary)
509
572
  AGF = (d * PF + 1) / (1 + d)
@@ -710,6 +773,12 @@ def unitarity(a, mx_basis="gm"):
710
773
  -------
711
774
  float
712
775
  """
776
+ from pygsti.modelmembers.operations.linearop import LinearOperator as _LinearOperator
777
+
778
+ # Cast to dense to ensure we can extract the shape.
779
+ if isinstance(a, _LinearOperator):
780
+ a = a.to_dense()
781
+
713
782
  d = int(round(_np.sqrt(a.shape[0])))
714
783
  basisMxs = _bt.basis_matrices(mx_basis, a.shape[0])
715
784
 
@@ -719,10 +788,7 @@ def unitarity(a, mx_basis="gm"):
719
788
  B = _bt.change_basis(a, mx_basis, "gm") # everything should be able to be put in the "gm" basis
720
789
 
721
790
  unital = B[1:d**2, 1:d**2]
722
- #old version
723
- #u = _np.trace(_np.dot(_np.conj(_np.transpose(unital)), unital)) / (d**2 - 1)
724
- #new version
725
- u= _np.einsum('ij,ji->', unital.conjugate().T, unital ) / (d**2 - 1)
791
+ u = _np.linalg.norm(unital)**2 / (d**2 - 1)
726
792
  return u
727
793
 
728
794
 
@@ -755,7 +821,7 @@ def fidelity_upper_bound(operation_mx):
755
821
  # # gives same result:
756
822
  # closestUnitaryJmx = _np.dot(choi_evecs, _np.dot( _np.diag(new_evals), _np.linalg.inv(choi_evecs) ) )
757
823
  closestJmx = _np.kron(closestVec, _np.transpose(_np.conjugate(closestVec))) # closest rank-1 Jmx
758
- closestJmx /= _mt.trace(closestJmx) # normalize so trace of Jmx == 1.0
824
+ closestJmx /= _np.trace(closestJmx) # normalize so trace of Jmx == 1.0
759
825
 
760
826
  maxF = fidelity(choi, closestJmx)
761
827
 
@@ -768,7 +834,7 @@ def fidelity_upper_bound(operation_mx):
768
834
  # print "DEBUG choi_evals = ",choi_evals, " iMax = ",iMax
769
835
  # #print "DEBUG: J = \n", closestUnitaryJmx
770
836
  # print "DEBUG: eigvals(J) = ", _np.linalg.eigvals(closestJmx)
771
- # print "DEBUG: trace(J) = ", _mt.trace(closestJmx)
837
+ # print "DEBUG: trace(J) = ", _np.trace(closestJmx)
772
838
  # print "DEBUG: maxF = %f, maxF_direct = %f" % (maxF, maxF_direct)
773
839
  # raise ValueError("ERROR: maxF - maxF_direct = %f" % (maxF -maxF_direct))
774
840
  assert(abs(maxF - maxF_direct) < 1e-6)
@@ -1097,8 +1163,8 @@ def state_to_dmvec(psi):
1097
1163
  The vectorized density matrix.
1098
1164
  """
1099
1165
  psi = psi.reshape((psi.size, 1)) # convert to (N,1) shape if necessary
1100
- dm = _np.dot(psi, _np.conjugate(psi.T))
1101
- return dm.flatten()
1166
+ dm = psi @ psi.conj().T
1167
+ return dm.ravel()
1102
1168
 
1103
1169
 
1104
1170
  def dmvec_to_state(dmvec, tol=1e-6):
@@ -1577,7 +1643,7 @@ def extract_elementary_errorgen_coefficients(errorgen, elementary_errorgen_label
1577
1643
  errorgen_basis.create_simple_equivalent('std'))
1578
1644
  else:
1579
1645
  errorgen_std = _bt.change_basis(errorgen, errorgen_basis, "std")
1580
- flat_errorgen_std = errorgen_std.toarray().flatten() if _sps.issparse(errorgen_std) else errorgen_std.flatten()
1646
+ flat_errorgen_std = errorgen_std.toarray().ravel() if _sps.issparse(errorgen_std) else errorgen_std.ravel()
1581
1647
 
1582
1648
  d2 = errorgen_std.shape[0]
1583
1649
  d = int(_np.sqrt(d2))
@@ -1593,7 +1659,7 @@ def extract_elementary_errorgen_coefficients(errorgen, elementary_errorgen_label
1593
1659
  bel_lbls = key.basis_element_labels
1594
1660
  bmx0 = elementary_errorgen_basis[bel_lbls[0]]
1595
1661
  bmx1 = elementary_errorgen_basis[bel_lbls[1]] if (len(bel_lbls) > 1) else None
1596
- flat_projector = _lt.create_elementary_errorgen_dual(key.errorgen_type, bmx0, bmx1, sparse=False).flatten()
1662
+ flat_projector = _lt.create_elementary_errorgen_dual(key.errorgen_type, bmx0, bmx1, sparse=False).ravel()
1597
1663
  projections[key] = _np.real_if_close(_np.vdot(flat_projector, flat_errorgen_std), tol=1000)
1598
1664
  if return_projected_errorgen:
1599
1665
  space_projector[:, i] = flat_projector
@@ -1673,7 +1739,7 @@ def project_errorgen(errorgen, elementary_errorgen_type, elementary_errorgen_bas
1673
1739
  errorgen_basis.create_simple_equivalent('std'))
1674
1740
  else:
1675
1741
  errorgen_std = _bt.change_basis(errorgen, errorgen_basis, "std")
1676
- flat_errorgen_std = errorgen_std.toarray().flatten() if _sps.issparse(errorgen_std) else errorgen_std.flatten()
1742
+ flat_errorgen_std = errorgen_std.toarray().ravel() if _sps.issparse(errorgen_std) else errorgen_std.ravel()
1677
1743
 
1678
1744
  d2 = errorgen_std.shape[0]
1679
1745
  d = int(_np.sqrt(d2))
@@ -1687,7 +1753,7 @@ def project_errorgen(errorgen, elementary_errorgen_type, elementary_errorgen_bas
1687
1753
  space_projector = _np.empty((d2 * d2, len(projectors)), complex)
1688
1754
 
1689
1755
  for i, (lbl, projector) in enumerate(projectors.items()):
1690
- flat_projector = projector.flatten()
1756
+ flat_projector = projector.ravel()
1691
1757
  proj = _np.real_if_close(_np.vdot(flat_projector, flat_errorgen_std), tol=1000)
1692
1758
  if return_projected_errorgen:
1693
1759
  space_projector[:, i] = flat_projector
pygsti/tools/pdftools.py CHANGED
@@ -71,28 +71,3 @@ def classical_fidelity(p, q):
71
71
  # sqrt_fidelity += _np.sqrt(x * y)
72
72
 
73
73
  return _np.sum([_np.sqrt(x * q.get(event, 0.)) for (event, x) in p.items()]) ** 2
74
-
75
- #return root_fidelity ** 2
76
-
77
-
78
- # def Hoyer_sparsity_measure(p, n):
79
- # """
80
- # Computes a measure of the sparsity ("spikyness") of a probability distribution (or a
81
- # general real vector).
82
-
83
- # Parameters
84
- # ----------
85
- # p : dict
86
- # The distribution
87
-
88
- # n : the number of possible events (zero probability events do not need to be included in `p`)
89
-
90
- # Returns
91
- # -------
92
- # float
93
- # """
94
- # plist = _np.array(list(p.values()))
95
- # twonorm = _np.sqrt(_np.sum(plist**2))
96
- # onenorm = _np.sum(_np.abs(plist))
97
- # max_onenorm_over_twonorm = _np.sqrt(n)
98
- # return (max_onenorm_over_twonorm - onenorm/twonorm) / (max_onenorm_over_twonorm - 1)