pyGSTi 0.9.12__cp310-cp310-win_amd64.whl → 0.9.13__cp310-cp310-win_amd64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (225) hide show
  1. pyGSTi-0.9.13.dist-info/METADATA +197 -0
  2. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +211 -220
  3. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/WHEEL +1 -1
  4. pygsti/_version.py +2 -2
  5. pygsti/algorithms/contract.py +1 -1
  6. pygsti/algorithms/core.py +62 -35
  7. pygsti/algorithms/fiducialpairreduction.py +95 -110
  8. pygsti/algorithms/fiducialselection.py +17 -8
  9. pygsti/algorithms/gaugeopt.py +2 -2
  10. pygsti/algorithms/germselection.py +87 -77
  11. pygsti/algorithms/mirroring.py +0 -388
  12. pygsti/algorithms/randomcircuit.py +165 -1333
  13. pygsti/algorithms/rbfit.py +0 -234
  14. pygsti/baseobjs/basis.py +94 -396
  15. pygsti/baseobjs/errorgenbasis.py +0 -132
  16. pygsti/baseobjs/errorgenspace.py +0 -10
  17. pygsti/baseobjs/label.py +52 -168
  18. pygsti/baseobjs/opcalc/fastopcalc.cp310-win_amd64.pyd +0 -0
  19. pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
  20. pygsti/baseobjs/polynomial.py +13 -595
  21. pygsti/baseobjs/protectedarray.py +72 -132
  22. pygsti/baseobjs/statespace.py +1 -0
  23. pygsti/circuits/__init__.py +1 -1
  24. pygsti/circuits/circuit.py +753 -504
  25. pygsti/circuits/circuitconstruction.py +0 -4
  26. pygsti/circuits/circuitlist.py +47 -5
  27. pygsti/circuits/circuitparser/__init__.py +8 -8
  28. pygsti/circuits/circuitparser/fastcircuitparser.cp310-win_amd64.pyd +0 -0
  29. pygsti/circuits/circuitstructure.py +3 -3
  30. pygsti/circuits/cloudcircuitconstruction.py +27 -14
  31. pygsti/data/datacomparator.py +4 -9
  32. pygsti/data/dataset.py +51 -46
  33. pygsti/data/hypothesistest.py +0 -7
  34. pygsti/drivers/bootstrap.py +0 -49
  35. pygsti/drivers/longsequence.py +46 -10
  36. pygsti/evotypes/basereps_cython.cp310-win_amd64.pyd +0 -0
  37. pygsti/evotypes/chp/opreps.py +0 -61
  38. pygsti/evotypes/chp/statereps.py +0 -32
  39. pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
  40. pygsti/evotypes/densitymx/effectreps.cp310-win_amd64.pyd +0 -0
  41. pygsti/evotypes/densitymx/effectreps.pyx +1 -1
  42. pygsti/evotypes/densitymx/opreps.cp310-win_amd64.pyd +0 -0
  43. pygsti/evotypes/densitymx/opreps.pyx +2 -2
  44. pygsti/evotypes/densitymx/statereps.cp310-win_amd64.pyd +0 -0
  45. pygsti/evotypes/densitymx/statereps.pyx +1 -1
  46. pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
  47. pygsti/evotypes/densitymx_slow/opreps.py +16 -23
  48. pygsti/evotypes/densitymx_slow/statereps.py +10 -3
  49. pygsti/evotypes/evotype.py +39 -2
  50. pygsti/evotypes/stabilizer/effectreps.cp310-win_amd64.pyd +0 -0
  51. pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
  52. pygsti/evotypes/stabilizer/opreps.cp310-win_amd64.pyd +0 -0
  53. pygsti/evotypes/stabilizer/opreps.pyx +0 -4
  54. pygsti/evotypes/stabilizer/statereps.cp310-win_amd64.pyd +0 -0
  55. pygsti/evotypes/stabilizer/statereps.pyx +1 -5
  56. pygsti/evotypes/stabilizer/termreps.cp310-win_amd64.pyd +0 -0
  57. pygsti/evotypes/stabilizer/termreps.pyx +0 -7
  58. pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
  59. pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
  60. pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
  61. pygsti/evotypes/statevec/effectreps.cp310-win_amd64.pyd +0 -0
  62. pygsti/evotypes/statevec/effectreps.pyx +1 -1
  63. pygsti/evotypes/statevec/opreps.cp310-win_amd64.pyd +0 -0
  64. pygsti/evotypes/statevec/opreps.pyx +2 -2
  65. pygsti/evotypes/statevec/statereps.cp310-win_amd64.pyd +0 -0
  66. pygsti/evotypes/statevec/statereps.pyx +1 -1
  67. pygsti/evotypes/statevec/termreps.cp310-win_amd64.pyd +0 -0
  68. pygsti/evotypes/statevec/termreps.pyx +0 -7
  69. pygsti/evotypes/statevec_slow/effectreps.py +0 -3
  70. pygsti/evotypes/statevec_slow/opreps.py +0 -5
  71. pygsti/extras/__init__.py +0 -1
  72. pygsti/extras/drift/signal.py +1 -1
  73. pygsti/extras/drift/stabilityanalyzer.py +3 -1
  74. pygsti/extras/interpygate/__init__.py +12 -0
  75. pygsti/extras/interpygate/core.py +0 -36
  76. pygsti/extras/interpygate/process_tomography.py +44 -10
  77. pygsti/extras/rpe/rpeconstruction.py +0 -2
  78. pygsti/forwardsims/__init__.py +1 -0
  79. pygsti/forwardsims/forwardsim.py +50 -93
  80. pygsti/forwardsims/mapforwardsim.py +78 -20
  81. pygsti/forwardsims/mapforwardsim_calc_densitymx.cp310-win_amd64.pyd +0 -0
  82. pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
  83. pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
  84. pygsti/forwardsims/matrixforwardsim.py +72 -17
  85. pygsti/forwardsims/termforwardsim.py +9 -111
  86. pygsti/forwardsims/termforwardsim_calc_stabilizer.cp310-win_amd64.pyd +0 -0
  87. pygsti/forwardsims/termforwardsim_calc_statevec.cp310-win_amd64.pyd +0 -0
  88. pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
  89. pygsti/forwardsims/torchfwdsim.py +265 -0
  90. pygsti/forwardsims/weakforwardsim.py +2 -2
  91. pygsti/io/__init__.py +1 -2
  92. pygsti/io/mongodb.py +0 -2
  93. pygsti/io/stdinput.py +6 -22
  94. pygsti/layouts/copalayout.py +10 -12
  95. pygsti/layouts/distlayout.py +0 -40
  96. pygsti/layouts/maplayout.py +103 -25
  97. pygsti/layouts/matrixlayout.py +99 -60
  98. pygsti/layouts/prefixtable.py +1534 -52
  99. pygsti/layouts/termlayout.py +1 -1
  100. pygsti/modelmembers/instruments/instrument.py +3 -3
  101. pygsti/modelmembers/instruments/tpinstrument.py +2 -2
  102. pygsti/modelmembers/modelmember.py +0 -17
  103. pygsti/modelmembers/operations/__init__.py +3 -4
  104. pygsti/modelmembers/operations/affineshiftop.py +206 -0
  105. pygsti/modelmembers/operations/composederrorgen.py +1 -1
  106. pygsti/modelmembers/operations/composedop.py +1 -24
  107. pygsti/modelmembers/operations/denseop.py +5 -5
  108. pygsti/modelmembers/operations/eigpdenseop.py +2 -2
  109. pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
  110. pygsti/modelmembers/operations/embeddedop.py +0 -1
  111. pygsti/modelmembers/operations/experrorgenop.py +5 -2
  112. pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
  113. pygsti/modelmembers/operations/fullcptpop.py +2 -2
  114. pygsti/modelmembers/operations/fulltpop.py +28 -6
  115. pygsti/modelmembers/operations/fullunitaryop.py +5 -4
  116. pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
  117. pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
  118. pygsti/modelmembers/operations/linearop.py +7 -27
  119. pygsti/modelmembers/operations/opfactory.py +1 -1
  120. pygsti/modelmembers/operations/repeatedop.py +1 -24
  121. pygsti/modelmembers/operations/staticstdop.py +1 -1
  122. pygsti/modelmembers/povms/__init__.py +3 -3
  123. pygsti/modelmembers/povms/basepovm.py +7 -36
  124. pygsti/modelmembers/povms/complementeffect.py +4 -9
  125. pygsti/modelmembers/povms/composedeffect.py +0 -320
  126. pygsti/modelmembers/povms/computationaleffect.py +1 -1
  127. pygsti/modelmembers/povms/computationalpovm.py +3 -1
  128. pygsti/modelmembers/povms/effect.py +3 -5
  129. pygsti/modelmembers/povms/marginalizedpovm.py +3 -81
  130. pygsti/modelmembers/povms/tppovm.py +74 -2
  131. pygsti/modelmembers/states/__init__.py +2 -5
  132. pygsti/modelmembers/states/composedstate.py +0 -317
  133. pygsti/modelmembers/states/computationalstate.py +3 -3
  134. pygsti/modelmembers/states/cptpstate.py +4 -4
  135. pygsti/modelmembers/states/densestate.py +10 -8
  136. pygsti/modelmembers/states/fullpurestate.py +0 -24
  137. pygsti/modelmembers/states/purestate.py +1 -1
  138. pygsti/modelmembers/states/state.py +5 -6
  139. pygsti/modelmembers/states/tpstate.py +28 -10
  140. pygsti/modelmembers/term.py +3 -6
  141. pygsti/modelmembers/torchable.py +50 -0
  142. pygsti/modelpacks/_modelpack.py +1 -1
  143. pygsti/modelpacks/smq1Q_ZN.py +3 -1
  144. pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
  145. pygsti/modelpacks/smq2Q_XY.py +3 -3
  146. pygsti/modelpacks/smq2Q_XYI.py +2 -2
  147. pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
  148. pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
  149. pygsti/modelpacks/smq2Q_XYXX.py +1 -1
  150. pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
  151. pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
  152. pygsti/modelpacks/stdtarget.py +0 -121
  153. pygsti/models/cloudnoisemodel.py +1 -2
  154. pygsti/models/explicitcalc.py +3 -3
  155. pygsti/models/explicitmodel.py +3 -13
  156. pygsti/models/fogistore.py +5 -3
  157. pygsti/models/localnoisemodel.py +1 -2
  158. pygsti/models/memberdict.py +0 -12
  159. pygsti/models/model.py +801 -68
  160. pygsti/models/modelconstruction.py +4 -4
  161. pygsti/models/modelnoise.py +2 -2
  162. pygsti/models/modelparaminterposer.py +1 -1
  163. pygsti/models/oplessmodel.py +1 -1
  164. pygsti/models/qutrit.py +15 -14
  165. pygsti/objectivefns/objectivefns.py +75 -140
  166. pygsti/objectivefns/wildcardbudget.py +2 -7
  167. pygsti/optimize/__init__.py +1 -0
  168. pygsti/optimize/arraysinterface.py +28 -0
  169. pygsti/optimize/customcg.py +0 -12
  170. pygsti/optimize/customlm.py +129 -323
  171. pygsti/optimize/customsolve.py +2 -2
  172. pygsti/optimize/optimize.py +0 -84
  173. pygsti/optimize/simplerlm.py +841 -0
  174. pygsti/optimize/wildcardopt.py +19 -598
  175. pygsti/protocols/confidenceregionfactory.py +28 -14
  176. pygsti/protocols/estimate.py +31 -14
  177. pygsti/protocols/gst.py +238 -142
  178. pygsti/protocols/modeltest.py +19 -12
  179. pygsti/protocols/protocol.py +9 -37
  180. pygsti/protocols/rb.py +450 -79
  181. pygsti/protocols/treenode.py +8 -2
  182. pygsti/protocols/vb.py +108 -206
  183. pygsti/protocols/vbdataframe.py +1 -1
  184. pygsti/report/factory.py +0 -15
  185. pygsti/report/fogidiagram.py +1 -17
  186. pygsti/report/modelfunction.py +12 -3
  187. pygsti/report/mpl_colormaps.py +1 -1
  188. pygsti/report/plothelpers.py +11 -3
  189. pygsti/report/report.py +16 -0
  190. pygsti/report/reportables.py +41 -37
  191. pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
  192. pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
  193. pygsti/report/workspace.py +2 -14
  194. pygsti/report/workspaceplots.py +328 -505
  195. pygsti/tools/basistools.py +9 -36
  196. pygsti/tools/edesigntools.py +124 -96
  197. pygsti/tools/fastcalc.cp310-win_amd64.pyd +0 -0
  198. pygsti/tools/fastcalc.pyx +35 -81
  199. pygsti/tools/internalgates.py +151 -15
  200. pygsti/tools/jamiolkowski.py +5 -5
  201. pygsti/tools/lindbladtools.py +19 -11
  202. pygsti/tools/listtools.py +0 -114
  203. pygsti/tools/matrixmod2.py +1 -1
  204. pygsti/tools/matrixtools.py +173 -339
  205. pygsti/tools/nameddict.py +1 -1
  206. pygsti/tools/optools.py +154 -88
  207. pygsti/tools/pdftools.py +0 -25
  208. pygsti/tools/rbtheory.py +3 -320
  209. pygsti/tools/slicetools.py +64 -12
  210. pyGSTi-0.9.12.dist-info/METADATA +0 -157
  211. pygsti/algorithms/directx.py +0 -711
  212. pygsti/evotypes/qibo/__init__.py +0 -33
  213. pygsti/evotypes/qibo/effectreps.py +0 -78
  214. pygsti/evotypes/qibo/opreps.py +0 -376
  215. pygsti/evotypes/qibo/povmreps.py +0 -98
  216. pygsti/evotypes/qibo/statereps.py +0 -174
  217. pygsti/extras/rb/__init__.py +0 -13
  218. pygsti/extras/rb/benchmarker.py +0 -957
  219. pygsti/extras/rb/dataset.py +0 -378
  220. pygsti/extras/rb/io.py +0 -814
  221. pygsti/extras/rb/simulate.py +0 -1020
  222. pygsti/io/legacyio.py +0 -385
  223. pygsti/modelmembers/povms/denseeffect.py +0 -142
  224. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
  225. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
pygsti/tools/fastcalc.pyx CHANGED
@@ -14,6 +14,7 @@
14
14
 
15
15
  import numpy as np
16
16
  from libc.stdlib cimport malloc, free
17
+ from functools import lru_cache
17
18
  cimport numpy as np
18
19
  cimport cython
19
20
 
@@ -50,7 +51,7 @@ def embedded_fast_acton_sparse(embedded_gate_acton_fn,
50
51
  cdef np.ndarray[double, ndim=1, mode="c"] slc1 = np.empty(nActionIndices, dtype='d')
51
52
  cdef np.ndarray[double, ndim=1, mode="c"] slc2 = np.empty(nActionIndices, dtype='d')
52
53
 
53
- # nActionIndices = np.product(numBasisEls_action)
54
+ # nActionIndices = np.prod(numBasisEls_action)
54
55
  #for i in range(nAction):
55
56
  # nActionIndices *= numBasisEls_action[i]
56
57
 
@@ -274,7 +275,7 @@ def embedded_fast_acton_sparse_complex(embedded_gate_acton_fn,
274
275
  cdef np.ndarray[np.complex128_t, ndim=1, mode="c"] slc1 = np.empty(nActionIndices, dtype=np.complex128)
275
276
  cdef np.ndarray[np.complex128_t, ndim=1, mode="c"] slc2 = np.empty(nActionIndices, dtype=np.complex128)
276
277
 
277
- # nActionIndices = np.product(numBasisEls_action)
278
+ # nActionIndices = np.prod(numBasisEls_action)
278
279
  #for i in range(nAction):
279
280
  # nActionIndices *= numBasisEls_action[i]
280
281
 
@@ -570,67 +571,6 @@ def fast_kron(np.ndarray[double, ndim=1, mode="c"] outvec not None,
570
571
  outvec[endoff+i] *= mult
571
572
  sz *= fastArraySizes[k]
572
573
 
573
- #assert(sz == N)
574
-
575
-
576
-
577
- #An attempt at a faster matrix prod specific to 2D matrices -- much SLOWER than numpy!!
578
- #@cython.cdivision(True) # turn off divide-by-zero checking
579
- #@cython.boundscheck(False) # turn off bounds-checking for entire function
580
- #@cython.wraparound(False) # turn off negative index wrapping for entire function
581
- #def fast_dot2(np.ndarray[double, ndim=2] out,
582
- # np.ndarray[double, ndim=2] a, np.ndarray[double, ndim=2] b):
583
- # cdef double* out_ptr = <double*>out.data
584
- # cdef double* a_ptr = <double*>a.data
585
- # cdef double* b_ptr = <double*>b.data
586
- # cdef double* arow
587
- # cdef double* bcol
588
- # cdef double* outrow
589
- # cdef double tot
590
- # cdef INT m = a.shape[0]
591
- # cdef INT n = b.shape[1]
592
- # cdef INT l = a.shape[1]
593
- # cdef INT astride = a.strides[0] // a.itemsize
594
- # cdef INT bstride = b.strides[0] // b.itemsize
595
- # cdef INT outstride = out.strides[0] // out.itemsize
596
- # cdef INT ainc = a.strides[1] // a.itemsize
597
- # cdef INT binc = b.strides[1] // b.itemsize
598
- # cdef INT outinc = out.strides[1] // out.itemsize
599
- # cdef INT i_times_astride
600
- # cdef INT i_times_outstride
601
- # cdef INT j_times_binc
602
- # cdef INT j_times_outinc
603
- # cdef INT k_times_bstride
604
- # cdef INT k_times_ainc
605
- # cdef INT i
606
- # cdef INT j
607
- # cdef INT k
608
- #
609
- # # out_ij = sum_k a_ik * b_kl
610
- #
611
- # i_times_astride = 0
612
- # i_times_outstride = 0
613
- # for i in range(m):
614
- # arow = &a_ptr[i_times_astride]
615
- # outrow = &out_ptr[i_times_outstride]
616
- # j_times_binc = 0
617
- # j_times_outinc = 0
618
- # for j in range(n):
619
- # bcol = &b_ptr[j_times_binc]
620
- # k_times_bstride = 0
621
- # k_times_ainc = 0
622
- # tot = 0.0
623
- # for k in range(l):
624
- # tot = tot + arow[k_times_ainc] * bcol[k_times_bstride]
625
- # k_times_bstride = k_times_bstride + bstride
626
- # k_times_ainc = k_times_ainc + ainc
627
- # outrow[j_times_outinc] = tot
628
- # j_times_binc = j_times_binc + binc
629
- # j_times_outinc = j_times_outinc + outinc
630
- # i_times_astride = i_times_astride + astride
631
- # i_times_outstride = i_times_outstride + outstride
632
-
633
-
634
574
  @cython.boundscheck(False) # turn off bounds-checking for entire function
635
575
  @cython.wraparound(False) # turn off negative index wrapping for entire function
636
576
  def fast_kron_complex(np.ndarray[np.complex128_t, ndim=1, mode="c"] outvec not None,
@@ -680,21 +620,6 @@ def fast_kron_complex(np.ndarray[np.complex128_t, ndim=1, mode="c"] outvec not N
680
620
  #assert(sz == N)
681
621
 
682
622
 
683
- #Manually inline to avoid overhead of argument passing
684
- #@cython.boundscheck(False) # turn off bounds-checking for entire function
685
- #@cython.wraparound(False) # turn off negative index wrapping for entire function
686
- #cdef vec_inf_norm(np.ndarray[double, ndim=1] v):
687
- # cdef INT i
688
- # cdef INT N = v.shape[0]
689
- # cdef double mx = 0.0
690
- # cdef double a
691
- # for i in range(N):
692
- # a = abs(v[i])
693
- # if a > mx: mx = a
694
- # return mx
695
-
696
-
697
-
698
623
  @cython.cdivision(True) # turn off divide-by-zero checking
699
624
  @cython.boundscheck(False) # turn off bounds-checking for entire function
700
625
  @cython.wraparound(False) # turn off negative index wrapping for entire function
@@ -716,9 +641,6 @@ def custom_expm_multiply_simple_core(np.ndarray[double, ndim=1, mode="c"] Adata,
716
641
  &F[0], &scratch[0])
717
642
  return F
718
643
 
719
-
720
-
721
-
722
644
  @cython.cdivision(True) # turn off divide-by-zero checking
723
645
  cdef custom_expm_multiply_simple_core_c(double* Adata, INT* Aindptr,
724
646
  INT* Aindices, double* B,
@@ -1305,6 +1227,38 @@ def fast_compose_cliffords(np.ndarray[np.int64_t, ndim=2] s1, np.ndarray[np.int6
1305
1227
  return s, p
1306
1228
 
1307
1229
 
1230
+ #Faster generation of upper triangular indices specialized to first
1231
+ #superdiagonal and up.
1232
+ @cython.boundscheck(False) # Deactivate bounds checking
1233
+ @cython.wraparound(False) # Deactivate negative indexing.
1234
+ @cython.cdivision(True)
1235
+ @lru_cache(maxsize=16)
1236
+ def fast_triu_indices(int n):
1237
+ if n < 1:
1238
+ raise ValueError('n must be greater than 0')
1239
+
1240
+ cdef int size = (n**2-n)/2
1241
+ cdef int curr_idx = 0
1242
+ cdef int j, i
1243
+
1244
+ cdef np.ndarray[np.int64_t, ndim=1, mode="c"] row_indices_np = np.empty(size, dtype=np.int64)
1245
+ cdef np.ndarray[np.int64_t, ndim=1, mode="c"] col_indices_np = np.empty(size, dtype=np.int64)
1246
+
1247
+ cdef np.int64_t[::1] row_indices = row_indices_np
1248
+ cdef np.int64_t[::1] col_indices = col_indices_np
1249
+
1250
+ for j in range(n-1):
1251
+ for i in range(n-j-1, 0, -1):
1252
+ row_indices[curr_idx] = j
1253
+ curr_idx += 1
1254
+
1255
+ curr_idx = 0
1256
+ for j in range(1, n):
1257
+ for i in range(j, n):
1258
+ col_indices[curr_idx] = i
1259
+ curr_idx += 1
1260
+
1261
+ return row_indices_np, col_indices_np
1308
1262
 
1309
1263
 
1310
1264
 
@@ -16,6 +16,7 @@ import scipy.linalg as _spl
16
16
  from pygsti.tools import optools as _ot
17
17
  from pygsti.tools import symplectic as _symp
18
18
  from pygsti.baseobjs.unitarygatefunction import UnitaryGateFunction as _UnitaryGateFunction
19
+ from pygsti.tools.gatetools import sigmax, sigmay, sigmaz, sigmaxz
19
20
 
20
21
 
21
22
  class Gzr(_UnitaryGateFunction):
@@ -192,14 +193,18 @@ def standard_gatename_unitaries():
192
193
  * 'Gxmpi2','Gympi2','Gzmpi2' : 1Q -pi/2 rotations around X, Y and Z.
193
194
  * 'Gh' : Hadamard.
194
195
  * 'Gp', 'Gpdag' : phase and inverse phase (an alternative notation/name for Gzpi and Gzmpi2).
195
- * 'Gci' where `i = 0, 1, ..., 23` : the 24 1-qubit Cliffor gates (all the gates above are included as one of these).
196
- * 'Gcphase','Gcnot','Gswap' : standard 2Q gates.
197
-
196
+ * 'Gci' where `i = 0, 1, ..., 23` : the 24 1-qubit Clifford gates (all the gates above are included as one of these).
197
+ * 'Gcphase','Gcnot','Gswap', 'Giswap' : standard 2Q gates.
198
+ * 'Gsqrtiswap' : square-root of ISWAP gate, used in some superconducting qubit platforms.
199
+ * 'Gxx', 'Gzz' : MS-style parity gates
200
+ * 'Gcres', 'Gecres' : Cross-resonance and echoed cross-resonance gates. Native gate operations common on transmon systems (including IBM).
201
+
198
202
  * Non-Clifford gates:
199
203
 
200
204
  * 'Gt', 'Gtdag' : the T and inverse T gates (T is a Z rotation by pi/4).
201
205
  * 'Gzr' : a parameterized gate that is a Z rotation by an angle, where when the angle = pi then it equals Z.
202
-
206
+ * 'Gn' : N gate, pi/2 rotation about the (np.sqrt(3)/2, 0, -1/2) axis of the Bloch sphere, native gate in some spin qubit systems.
207
+
203
208
  Mostly, pyGSTi does not assume that a gate with one of these names is indeed
204
209
  the unitary specified here. Instead, these names are intended as short-hand
205
210
  for defining ProcessorSpecs and n-qubit models. Moreover, when these names
@@ -212,10 +217,6 @@ def standard_gatename_unitaries():
212
217
  """
213
218
  std_unitaries = {}
214
219
 
215
- sigmax = _np.array([[0, 1], [1, 0]])
216
- sigmay = _np.array([[0, -1.0j], [1.0j, 0]])
217
- sigmaz = _np.array([[1, 0], [0, -1]])
218
-
219
220
  def u_op(exp):
220
221
  return _np.array(_spl.expm(-1j * exp / 2), complex)
221
222
 
@@ -233,6 +234,11 @@ def standard_gatename_unitaries():
233
234
  std_unitaries['Gympi2'] = u_op(-1 * _np.pi / 2 * sigmay)
234
235
  std_unitaries['Gzmpi2'] = u_op(-1 * _np.pi / 2 * sigmaz)
235
236
 
237
+ std_unitaries['Gxpi4'] = u_op(_np.pi / 4 * sigmax)
238
+ std_unitaries['Gypi4'] = u_op(_np.pi / 4 * sigmay)
239
+ std_unitaries['Gzpi4'] = u_op(_np.pi / 4 * sigmaz)
240
+
241
+
236
242
  H = (1 / _np.sqrt(2)) * _np.array([[1., 1.], [1., -1.]], complex)
237
243
  P = _np.array([[1., 0.], [0., 1j]], complex)
238
244
  Pdag = _np.array([[1., 0.], [0., -1j]], complex)
@@ -245,6 +251,11 @@ def standard_gatename_unitaries():
245
251
  #std_unitaries['Ghph'] = _np.dot(H,_np.dot(P,H))
246
252
  std_unitaries['Gt'] = _np.array([[1., 0.], [0., _np.exp(1j * _np.pi / 4)]], complex)
247
253
  std_unitaries['Gtdag'] = _np.array([[1., 0.], [0., _np.exp(-1j * _np.pi / 4)]], complex)
254
+
255
+ #N gate, pi/2 rotation about the (np.sqrt(3)/2, 0, -1/2) axis of the Bloch sphere
256
+ #native gate in some spin qubit systems.
257
+ std_unitaries['Gn'] = _spl.expm(-1j*(_np.pi/4)*((_np.sqrt(3)/2)*sigmax - (.5)*sigmaz))
258
+
248
259
  # The 1-qubit Clifford group. The labelling is the same as in the the 1-qubit Clifford group generated
249
260
  # in pygsti.extras.rb.group, and also in the internal standard unitary (but with 'Gci' -> 'Ci')
250
261
  std_unitaries['Gc0'] = _np.array([[1, 0], [0, 1]], complex) # This is Gi
@@ -273,6 +284,7 @@ def standard_gatename_unitaries():
273
284
  std_unitaries['Gc21'] = _np.array([[1, -1], [1, 1]], complex) / _np.sqrt(2) # This is Gypi2 (up to phase)
274
285
  std_unitaries['Gc22'] = _np.array([[0.5 + 0.5j, 0.5 - 0.5j], [-0.5 + 0.5j, -0.5 - 0.5j]], complex)
275
286
  std_unitaries['Gc23'] = _np.array([[1, 0], [0, -1j]], complex) # This is Gzmpi2 / Gpdag (up to phase)
287
+
276
288
  # Two-qubit gates
277
289
  std_unitaries['Gcphase'] = _np.array([[1., 0., 0., 0.], [0., 1., 0., 0.], [
278
290
  0., 0., 1., 0.], [0., 0., 0., -1.]], complex)
@@ -285,10 +297,21 @@ def standard_gatename_unitaries():
285
297
  std_unitaries['Gswap'] = _np.array([[1., 0., 0., 0.], [0., 0., 1., 0.],
286
298
  [0., 1., 0., 0.], [0., 0., 0., 1.]], complex)
287
299
 
300
+ std_unitaries['Giswap'] = _np.array([[1., 0., 0., 0.], [0., 0., 1j, 0.],
301
+ [0., 1j, 0., 0.], [0., 0., 0., 1.]], complex)
302
+
303
+ std_unitaries['Gsqrtiswap'] = _np.array([[1., 0., 0., 0.], [0., 1/_np.sqrt(2), 1j/_np.sqrt(2), 0.],
304
+ [0., 1j/_np.sqrt(2), 1/_np.sqrt(2), 0.], [0., 0., 0., 1.]], complex)
305
+
306
+ #cross-resonance gate (exp(-1j*pi/4 sigmaxz))
307
+ std_unitaries['Gcres'] = _spl.expm(-1j*_np.pi/4*sigmaxz)
308
+ std_unitaries['Gecres'] = _np.array([[0, 1, 0., 1j], [1., 0, -1j, 0.],
309
+ [0., 1j, 0, 1], [-1j, 0., 1, 0]], complex)/_np.sqrt(2)
310
+
288
311
  std_unitaries['Gzr'] = Gzr()
289
312
  std_unitaries['Gczr'] = Gczr()
290
313
 
291
- #Add these at the end, since we don't want unitary_to_standard_gatenemt to return these "shorthand" names
314
+ #Add these at the end, since we don't want unitary_to_standard_gatenames to return these "shorthand" names
292
315
  std_unitaries['Gx'] = std_unitaries['Gxpi2']
293
316
  std_unitaries['Gy'] = std_unitaries['Gypi2']
294
317
  std_unitaries['Gz'] = std_unitaries['Gzpi2']
@@ -296,7 +319,7 @@ def standard_gatename_unitaries():
296
319
  return std_unitaries
297
320
 
298
321
 
299
- def unitary_to_standard_gatename(unitary):
322
+ def unitary_to_standard_gatename(unitary, up_to_phase = False, return_phase = False):
300
323
  """
301
324
  Looks up and returns the standard gate name for a unitary gate matrix, if one exists.
302
325
 
@@ -305,6 +328,16 @@ def unitary_to_standard_gatename(unitary):
305
328
  unitary : complex np.array
306
329
  The unitary to convert.
307
330
 
331
+ up_to_phase : bool, optional (default False)
332
+ If true then after checking if the unitary is exactly equivalent to a built-in one,
333
+ this then checks if the input unitary is equal to to a built-in one up to a global
334
+ phase.
335
+
336
+ return_phase : bool, optional (default False)
337
+ If true, and up_to_phase is true, then if a unitary is equivalent up to a global
338
+ phase to a built-in one, we return that phase (i.e. the phase the built-in one
339
+ would need to be multiplied by).
340
+
308
341
  Returns
309
342
  -------
310
343
  str or None
@@ -314,6 +347,28 @@ def unitary_to_standard_gatename(unitary):
314
347
  for std_name, U in standard_gatename_unitaries().items():
315
348
  if not callable(U) and not callable(unitary) and U.shape == unitary.shape and _np.allclose(unitary, U):
316
349
  return std_name
350
+
351
+ #check for equivalence up to a global phase.
352
+ if up_to_phase:
353
+ for std_name, U in standard_gatename_unitaries().items():
354
+ #I think the callable checks are to avoid doing the check on the continuously parameterized Z
355
+ #rotation that is in the built-in dictionary. Follow the original code's lead and do the same here.
356
+ if not callable(U) and not callable(unitary) and U.shape == unitary.shape:
357
+
358
+ inv_prod = U.conj().T@unitary
359
+ inv_prod_diag = _np.diag(inv_prod)
360
+ inv_prod_upper = _np.triu(inv_prod, 1)
361
+ inv_prod_lower = _np.tril(inv_prod, -1)
362
+
363
+ #If all of the diagonals are close to the same value, and all the the off diagonals
364
+ #are close to 0 then we should be proportional to the identity.
365
+ if _np.allclose(inv_prod_diag, inv_prod_diag[0]) and _np.allclose(inv_prod_upper, 0) and _np.allclose(inv_prod_lower, 0):
366
+ if return_phase:
367
+ phase = inv_prod_diag[0]
368
+ return std_name, phase
369
+ else:
370
+ return std_name
371
+
317
372
  return None
318
373
 
319
374
 
@@ -334,12 +389,11 @@ def standard_gatenames_cirq_conversions():
334
389
 
335
390
  Currently there are some standard gate names with no conversion to cirq.
336
391
 
337
- TODO: add Clifford gates with
338
- https://cirq.readthedocs.io/en/latest/generated/cirq.SingleQubitCliffordGate.html
339
-
340
392
  Returns
341
393
  -------
342
- dict mapping strings to string
394
+ std_gatenames_to_cirq
395
+ dict mapping strings corresponding to standard built-in pyGSTi names to
396
+ corresponding cirq operation objects.
343
397
  """
344
398
  try:
345
399
  import cirq
@@ -347,7 +401,10 @@ def standard_gatenames_cirq_conversions():
347
401
  raise ImportError("Cirq is required for this operation, and it does not appear to be installed.")
348
402
 
349
403
  std_gatenames_to_cirq = {}
350
- std_gatenames_to_cirq['Gi'] = None
404
+
405
+ #single-qubit gates
406
+
407
+ std_gatenames_to_cirq['Gi'] = cirq.I
351
408
  std_gatenames_to_cirq['Gxpi2'] = cirq.XPowGate(exponent=1 / 2)
352
409
  std_gatenames_to_cirq['Gxmpi2'] = cirq.XPowGate(exponent=-1 / 2)
353
410
  std_gatenames_to_cirq['Gxpi'] = cirq.X
@@ -362,12 +419,87 @@ def standard_gatenames_cirq_conversions():
362
419
  std_gatenames_to_cirq['Gh'] = cirq.H
363
420
  std_gatenames_to_cirq['Gt'] = cirq.T
364
421
  std_gatenames_to_cirq['Gtdag'] = cirq.T**-1
422
+ std_gatenames_to_cirq['Gn'] = cirq.PhasedXZGate(axis_phase_exponent=0.14758361765043326,
423
+ x_exponent=0.4195693767448338,
424
+ z_exponent=-0.2951672353008665)
425
+
426
+ #two-qubit gates
427
+
365
428
  std_gatenames_to_cirq['Gcphase'] = cirq.CZ
366
429
  std_gatenames_to_cirq['Gcnot'] = cirq.CNOT
367
430
  std_gatenames_to_cirq['Gswap'] = cirq.SWAP
431
+ std_gatenames_to_cirq['Gzz'] = cirq.ZZPowGate(exponent=.5, global_shift=-.5)
432
+ std_gatenames_to_cirq['Gxx'] = cirq.XXPowGate(exponent=.5, global_shift=-.5)
433
+ std_gatenames_to_cirq['Giswap'] = cirq.ISWAP
434
+ std_gatenames_to_cirq['Gsqrtiswap'] = cirq.SQRT_ISWAP
435
+ #I don't presently see a one-to-one conversion for cross-resonance
436
+
437
+ #single-qubit clifford group
438
+
439
+ std_gatenames_to_cirq['Gc0'] = cirq.I # This is Gi
440
+ std_gatenames_to_cirq['Gc1'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=0.5, z_exponent=0.5)
441
+ std_gatenames_to_cirq['Gc2'] = cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=-0.5, z_exponent=-0.5)
442
+ std_gatenames_to_cirq['Gc3'] = cirq.X # This is pauli X
443
+ std_gatenames_to_cirq['Gc4'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=-0.5, z_exponent=0.5)
444
+ std_gatenames_to_cirq['Gc5'] = cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=-0.5, z_exponent=0.5)
445
+ std_gatenames_to_cirq['Gc6'] = cirq.Y # This is pauli Y
446
+ std_gatenames_to_cirq['Gc7'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=0.5, z_exponent=-0.5)
447
+ std_gatenames_to_cirq['Gc8'] = cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=-0.5)
448
+ std_gatenames_to_cirq['Gc9'] = cirq.Z # This is pauli Z
449
+ std_gatenames_to_cirq['Gc10'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=-0.5, z_exponent=-0.5)
450
+ std_gatenames_to_cirq['Gc11'] = cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=0.5)
451
+ std_gatenames_to_cirq['Gc12'] = cirq.H # This is Gh
452
+ std_gatenames_to_cirq['Gc13'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=-0.5, z_exponent=0.0) # This is Gxmpi2 (up to phase)
453
+ std_gatenames_to_cirq['Gc14'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=0.0, z_exponent=0.5) # THis is Gzpi2 / Gp (up to phase)
454
+ std_gatenames_to_cirq['Gc15'] = cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=-0.5, z_exponent=0.0)# This is Gympi2 (up to phase)
455
+ std_gatenames_to_cirq['Gc16'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=0.5, z_exponent=0.0)# This is Gxpi2 (up to phase)
456
+ std_gatenames_to_cirq['Gc17'] = cirq.PhasedXZGate(axis_phase_exponent=0.25, x_exponent=1.0, z_exponent=0.0)# This is Gypi2 (up to phase)
457
+ std_gatenames_to_cirq['Gc18'] = cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=1.0)
458
+ std_gatenames_to_cirq['Gc19'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=-0.5, z_exponent=1.0)
459
+ std_gatenames_to_cirq['Gc20'] = cirq.PhasedXZGate(axis_phase_exponent=-0.25, x_exponent=1.0, z_exponent=0.0)
460
+ std_gatenames_to_cirq['Gc21'] = cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=0.5, z_exponent=0.0) # This is Gypi2 (up to phase)
461
+ std_gatenames_to_cirq['Gc22'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=0.5, z_exponent=1.0)
462
+ std_gatenames_to_cirq['Gc23'] = cirq.PhasedXZGate(axis_phase_exponent=0.0, x_exponent=0.0, z_exponent=-0.5) # This is Gzmpi2 / Gpdag (up to phase)
463
+
464
+ #legacy aliasing:
465
+ std_gatenames_to_cirq['Gx'] = std_gatenames_to_cirq['Gxpi2']
466
+ std_gatenames_to_cirq['Gy'] = std_gatenames_to_cirq['Gypi2']
467
+ std_gatenames_to_cirq['Gz'] = std_gatenames_to_cirq['Gzpi2']
468
+
368
469
 
369
470
  return std_gatenames_to_cirq
370
471
 
472
+ def cirq_gatenames_standard_conversions():
473
+
474
+ """
475
+ A dictionary converting cirq gates to built-in pyGSTi names for these gates.
476
+ Does not currently support conversion of all cirq gate types.
477
+ """
478
+
479
+ try:
480
+ import cirq
481
+ except ImportError:
482
+ raise ImportError("Cirq is required for this operation, and it does not appear to be installed.")
483
+
484
+
485
+ #reverse the mapping in standard_gatenames_cirq_conversions
486
+ cirq_to_standard_mapping = {value: key for key,value in standard_gatenames_cirq_conversions().items()}
487
+
488
+ #A direct reversing doesn't quite do what we want since the originally mapping was not
489
+ #one-to-one (some pyGSTi gate names refer to the same cirq Circuit, primarily because of the cliffords).
490
+ #Manually add back in some preference on the non-one-to-one gates.
491
+ cirq_to_standard_mapping[cirq.I] = 'Gi'
492
+ cirq_to_standard_mapping[cirq.X] = 'Gxpi'
493
+ cirq_to_standard_mapping[cirq.Y] = 'Gypi'
494
+ cirq_to_standard_mapping[cirq.PhasedXZGate(axis_phase_exponent=0.5, x_exponent=-1, z_exponent=0)] = 'Gypi'
495
+ cirq_to_standard_mapping[cirq.Z] = 'Gzpi'
496
+ cirq_to_standard_mapping[cirq.XPowGate(exponent=1 / 2)] = 'Gxpi2'
497
+ cirq_to_standard_mapping[cirq.YPowGate(exponent=1 / 2)] = 'Gypi2'
498
+ cirq_to_standard_mapping[cirq.ZPowGate(exponent=1 / 2)] = 'Gzpi2'
499
+ cirq_to_standard_mapping[cirq.H] = 'Gh'
500
+
501
+ return cirq_to_standard_mapping
502
+
371
503
 
372
504
  def standard_gatenames_quil_conversions():
373
505
  """
@@ -597,6 +729,8 @@ def standard_gatenames_openqasm_conversions(version='u3'):
597
729
  std_gatenames_to_qasm['Gc22'] = ['u3(1.570796326794897, 1.570796326794897, 1.570796326794897)'] # [1,1,1]*pi/2
598
730
  std_gatenames_to_qasm['Gc23'] = ['u3(0, 0, 4.71238898038469)'] # [0, 0, 3] * pi/2 (this is Gzmpi2 / Gpdag)
599
731
 
732
+ std_gatenames_to_qasm['Gecr'] = ['ecr']
733
+
600
734
  std_gatenames_to_argmap = {}
601
735
  std_gatenames_to_argmap['Gzr'] = lambda gatearg: ['u3(0, 0, ' + str(gatearg[0]) + ')']
602
736
  std_gatenames_to_argmap['Gczr'] = lambda gatearg: ['crz(' + str(gatearg[0]) + ')']
@@ -650,6 +784,8 @@ def standard_gatenames_openqasm_conversions(version='u3'):
650
784
  std_gatenames_to_qasm['Gt'] = ['rz(0.7853981633974485)']
651
785
  std_gatenames_to_qasm['Gtdag'] = ['rz(5.497787143782138)']
652
786
 
787
+ std_gatenames_to_qasm['Gecr'] = ['ecr']
788
+
653
789
  std_gatenames_to_argmap = {}
654
790
  std_gatenames_to_argmap['Gzr'] = lambda gatearg: ['rz(' + str(gatearg[0]) + ')']
655
791
  std_gatenames_to_argmap['Gczr'] = lambda gatearg: ['crz(' + str(gatearg[0]) + ')']
@@ -117,9 +117,9 @@ def jamiolkowski_iso(operation_mx, op_mx_basis='pp', choi_mx_basis='pp'):
117
117
  for i in range(M):
118
118
  for j in range(M):
119
119
  BiBj = _np.kron(BVec[i], _np.conjugate(BVec[j]))
120
- BiBj_dag = _np.transpose(_np.conjugate(BiBj))
121
- choiMx[i, j] = _mt.trace(_np.dot(opMxInStdBasis, BiBj_dag)) \
122
- / _mt.trace(_np.dot(BiBj, BiBj_dag))
120
+ num = _np.vdot(BiBj, opMxInStdBasis)
121
+ den = _np.linalg.norm(BiBj) ** 2
122
+ choiMx[i, j] = num / den
123
123
 
124
124
  # This construction results in a Jmx with trace == dim(H) = sqrt(operation_mx.shape[0])
125
125
  # (dimension of density matrix) but we'd like a Jmx with trace == 1, so normalize:
@@ -225,7 +225,7 @@ def fast_jamiolkowski_iso_std(operation_mx, op_mx_basis):
225
225
  N2 = opMxInStdBasis.shape[0]; N = int(_np.sqrt(N2))
226
226
  assert(N * N == N2) # make sure N2 is a perfect square
227
227
  Jmx = opMxInStdBasis.reshape((N, N, N, N))
228
- Jmx = _np.swapaxes(Jmx, 1, 2).flatten()
228
+ Jmx = _np.swapaxes(Jmx, 1, 2).ravel()
229
229
  Jmx = Jmx.reshape((N2, N2))
230
230
 
231
231
  # This construction results in a Jmx with trace == dim(H) = sqrt(gateMxInPauliBasis.shape[0])
@@ -261,7 +261,7 @@ def fast_jamiolkowski_iso_std_inv(choi_mx, op_mx_basis):
261
261
  N2 = choi_mx.shape[0]; N = int(_np.sqrt(N2))
262
262
  assert(N * N == N2) # make sure N2 is a perfect square
263
263
  opMxInStdBasis = choi_mx.reshape((N, N, N, N)) * N
264
- opMxInStdBasis = _np.swapaxes(opMxInStdBasis, 1, 2).flatten()
264
+ opMxInStdBasis = _np.swapaxes(opMxInStdBasis, 1, 2).ravel()
265
265
  opMxInStdBasis = opMxInStdBasis.reshape((N2, N2))
266
266
  op_mx_basis = _bt.create_basis_for_matrix(opMxInStdBasis, op_mx_basis)
267
267
 
@@ -13,7 +13,6 @@ Utility functions relevant to Lindblad forms and projections
13
13
  import numpy as _np
14
14
  import scipy.sparse as _sps
15
15
 
16
- from pygsti.tools import matrixtools as _mt
17
16
  from pygsti.tools.basistools import basis_matrices
18
17
 
19
18
 
@@ -84,18 +83,21 @@ def create_elementary_errorgen_dual(typ, p, q=None, sparse=False, normalization_
84
83
  rho1 = (p @ rho0 @ qdag + q @ rho0 @ pdag) # 1 / (2 * d2) *
85
84
  elif typ == 'A':
86
85
  rho1 = 1j * (p @ rho0 @ qdag - q @ rho0 @ pdag) # 1j / (2 * d2)
87
- elem_errgen[:, i] = rho1.flatten()[:, None] if sparse else rho1.flatten()
86
+ elem_errgen[:, i] = rho1.ravel()
87
+ # ^ That line used to branch depending on the value of "sparse", but it
88
+ # turns out that both codepaths produced the same result.
88
89
 
89
90
  return_normalization = bool(normalization_factor == 'auto_return')
90
91
  if normalization_factor in ('auto', 'auto_return'):
91
92
  primal = create_elementary_errorgen(typ, p, q, sparse)
92
93
  if sparse:
93
- normalization_factor = _np.vdot(elem_errgen.toarray().flatten(), primal.toarray().flatten())
94
+ normalization_factor = _np.vdot(elem_errgen.toarray(), primal.toarray())
94
95
  else:
95
- normalization_factor = _np.vdot(elem_errgen.flatten(), primal.flatten())
96
+ normalization_factor = _np.vdot(elem_errgen, primal)
96
97
  elem_errgen *= _np.real_if_close(1 / normalization_factor).item() # item() -> scalar
97
98
 
98
- if sparse: elem_errgen = elem_errgen.tocsr()
99
+ if sparse:
100
+ elem_errgen = elem_errgen.tocsr()
99
101
  return (elem_errgen, normalization_factor) if return_normalization else elem_errgen
100
102
 
101
103
 
@@ -134,7 +136,8 @@ def create_elementary_errorgen(typ, p, q=None, sparse=False):
134
136
  -------
135
137
  ndarray or Scipy CSR matrix
136
138
  """
137
- d = p.shape[0]; d2 = d**2
139
+ d = p.shape[0]
140
+ d2 = d**2
138
141
  if sparse:
139
142
  elem_errgen = _sps.lil_matrix((d2, d2), dtype=p.dtype)
140
143
  else:
@@ -163,10 +166,12 @@ def create_elementary_errorgen(typ, p, q=None, sparse=False):
163
166
  rho1 = p @ rho0 @ qdag + q @ rho0 @ pdag - 0.5 * (pq_plus_qp @ rho0 + rho0 @ pq_plus_qp)
164
167
  elif typ == 'A':
165
168
  rho1 = 1j * (p @ rho0 @ qdag - q @ rho0 @ pdag + 0.5 * (pq_minus_qp @ rho0 + rho0 @ pq_minus_qp))
169
+ elem_errgen[:, i] = rho1.ravel()
170
+ # ^ That line used to branch depending on the value of sparse, but both
171
+ # branches had the same effect.
166
172
 
167
- elem_errgen[:, i] = rho1.flatten()[:, None] if sparse else rho1.flatten()
168
-
169
- if sparse: elem_errgen = elem_errgen.tocsr()
173
+ if sparse:
174
+ elem_errgen = elem_errgen.tocsr()
170
175
  return elem_errgen
171
176
 
172
177
  def create_lindbladian_term_errorgen(typ, Lm, Ln=None, sparse=False): # noqa N803
@@ -226,7 +231,10 @@ def create_lindbladian_term_errorgen(typ, Lm, Ln=None, sparse=False): # noqa N8
226
231
  elif typ == 'O':
227
232
  rho1 = Ln @ rho0 @ Lm_dag - 0.5 * (Lmdag_Ln @ rho0 + rho0 @ Lmdag_Ln)
228
233
  else: raise ValueError("Invalid lindblad term errogen type!")
229
- lind_errgen[:, i] = rho1.flatten()[:, None] if sparse else rho1.flatten()
234
+ lind_errgen[:, i] = rho1.ravel()
235
+ # ^ That line used to branch based on the value of sparse, but both branches
236
+ # produced the same result.
230
237
 
231
- if sparse: lind_errgen = lind_errgen.tocsr()
238
+ if sparse:
239
+ lind_errgen = lind_errgen.tocsr()
232
240
  return lind_errgen
pygsti/tools/listtools.py CHANGED
@@ -383,117 +383,3 @@ def lists_to_tuples(obj):
383
383
  return {lists_to_tuples(k): lists_to_tuples(v) for k, v in obj.items()}
384
384
  else:
385
385
  return obj
386
-
387
-
388
- # ------------------------------------------------------------------------------
389
- # Machinery initially designed for an in-place take operation, which computes
390
- # how to do in-place permutations of arrays/lists efficiently. Kept here
391
- # commented out in case this is needed some time in the future.
392
- # ------------------------------------------------------------------------------
393
- #
394
- #def build_permute_copy_order(indices):
395
- # #Construct a list of the operations needed to "take" indices
396
- # # out of an array.
397
- #
398
- # nIndices = len(indices)
399
- # flgs = _np.zeros(nIndices,'bool') #flags indicating an index has been processed
400
- # shelved = {}
401
- # copyList = []
402
- #
403
- # while True: #loop until we've processed everything
404
- #
405
- # #The cycle has ended. Now find an unprocessed
406
- # # destination to begin a new cycle
407
- # for i in range(nIndices):
408
- # if flgs[i] == False:
409
- # if indices[i] == i: # index i is already where it need to be!
410
- # flgs[i] = True
411
- # else:
412
- # cycleFirstIndex = iDest = i
413
- # if cycleFirstIndex in indices:
414
- # copyList.append( (-1,i) ) # iDest == -1 means copy to offline storage
415
- # break;
416
- # else:
417
- # break #everything has been processed -- we're done!
418
- #
419
- # while True: # loop over cycle
420
- #
421
- # # at this point, data for index iDest has been stored or copied
422
- # iSrc = indices[iDest] # get source index for current destination
423
- #
424
- # # record appropriate copy command
425
- # if iSrc == cycleFirstIndex:
426
- # copyList.append( (iDest, -1) ) # copy from offline storage
427
- # flgs[iDest] = True
428
- #
429
- # #end of this cycle since we've hit our starting point,
430
- # # but no need to shelve first cycle element in this case.
431
- # break #(end of cycle)
432
- # else:
433
- # if iSrc in shelved: #original iSrc is now at index shelved[iSrc]
434
- # iSrc = shelved[iSrc]
435
- #
436
- # copyList.append( (iDest,iSrc) ) # => copy src -> dest
437
- # flgs[iDest] = True
438
- #
439
- # if iSrc < nIndices:
440
- # #Continue cycle (swapping within "active" (index < nIndices) region)
441
- # iDest = iSrc # make src the new dest
442
- # else:
443
- # #end of this cycle, and first cycle index hasn't been
444
- # # used, so shelve it (store it for later use) if it
445
- # # will be needed in the future.
446
- # if cycleFirstIndex in indices:
447
- # copyList.append( (iSrc,-1) )
448
- # shelved[cycleFirstIndex] = iSrc
449
- #
450
- # break #(end of cycle)
451
- #
452
- # return copyList
453
- #
454
- ## X X X
455
- ## 0 1 2 3 (nIndices == 4)
456
- ## 3, 0, 7, 4
457
- ## store 0
458
- ## 3 -> 0
459
- ## 4 -> 3
460
- ## stored[0] -> 4, shelved[0] = 4
461
- ## store 1
462
- ## shelved[0]==4 -> 1, NO((stored[1] -> 4, shelved[1] = 4)) B/C don't need index 1
463
- ## store 2
464
- ## 7 -> 2
465
- ## NO((Stored[2] -> 7, istore[2] = 7))
466
- #
467
- #
468
- #def inplace_take(a, indices, axis=None, copyList=None):
469
- # check = a.take(indices, axis=axis) #DEBUGGING
470
- # return check #FIX FOR NOW = COPY
471
- #
472
- # if axis is None:
473
- # def mkindex(i):
474
- # return i
475
- # else:
476
- # def mkindex(i):
477
- # sl = [slice(None)] * a.ndim
478
- # sl[axis] = i
479
- # return sl
480
- #
481
- # if copyList is None:
482
- # copyList = build_permute_copy_order(indices)
483
- #
484
- # store = None
485
- # for iDest,iSrc in copyList:
486
- # if iDest == -1: store = a[mkindex(iSrc)].copy() #otherwise just get a view!
487
- # elif iSrc == -1: a[mkindex(iDest)] = store
488
- # else: a[mkindex(iDest)] = a[mkindex(iSrc)]
489
- #
490
- # ret = a[mkindex(slice(0,len(indices)))]
491
- # if _np.linalg.norm(ret-check) > 1e-8 :
492
- # print("ERROR CHECK FAILED")
493
- # print("ret = ",ret)
494
- # print("check = ",check)
495
- # print("diff = ",_np.linalg.norm(ret-check))
496
- # assert(False)
497
- # #check = None #free mem?
498
- # #return ret
499
- # return check
@@ -468,7 +468,7 @@ def fix_top(a):
468
468
  found_B = False
469
469
  for ind in range(t):
470
470
  aa, P = permute_top(a, ind)
471
- B = _np.round_(aa[1:, 1:])
471
+ B = _np.round(aa[1:, 1:])
472
472
 
473
473
  if det_mod2(B) == 0:
474
474
  continue