pyGSTi 0.9.12.1__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.
- pyGSTi-0.9.13.dist-info/METADATA +197 -0
- {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +207 -217
- {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/WHEEL +1 -1
- pygsti/_version.py +2 -2
- pygsti/algorithms/contract.py +1 -1
- pygsti/algorithms/core.py +42 -28
- pygsti/algorithms/fiducialselection.py +17 -8
- pygsti/algorithms/gaugeopt.py +2 -2
- pygsti/algorithms/germselection.py +87 -77
- pygsti/algorithms/mirroring.py +0 -388
- pygsti/algorithms/randomcircuit.py +165 -1333
- pygsti/algorithms/rbfit.py +0 -234
- pygsti/baseobjs/basis.py +94 -396
- pygsti/baseobjs/errorgenbasis.py +0 -132
- pygsti/baseobjs/errorgenspace.py +0 -10
- pygsti/baseobjs/label.py +52 -168
- pygsti/baseobjs/opcalc/fastopcalc.cp310-win_amd64.pyd +0 -0
- pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
- pygsti/baseobjs/polynomial.py +13 -595
- pygsti/baseobjs/statespace.py +1 -0
- pygsti/circuits/__init__.py +1 -1
- pygsti/circuits/circuit.py +682 -505
- pygsti/circuits/circuitconstruction.py +0 -4
- pygsti/circuits/circuitlist.py +47 -5
- pygsti/circuits/circuitparser/__init__.py +8 -8
- pygsti/circuits/circuitparser/fastcircuitparser.cp310-win_amd64.pyd +0 -0
- pygsti/circuits/circuitstructure.py +3 -3
- pygsti/circuits/cloudcircuitconstruction.py +1 -1
- pygsti/data/datacomparator.py +2 -7
- pygsti/data/dataset.py +46 -44
- pygsti/data/hypothesistest.py +0 -7
- pygsti/drivers/bootstrap.py +0 -49
- pygsti/drivers/longsequence.py +2 -1
- pygsti/evotypes/basereps_cython.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/chp/opreps.py +0 -61
- pygsti/evotypes/chp/statereps.py +0 -32
- pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
- pygsti/evotypes/densitymx/effectreps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/effectreps.pyx +1 -1
- pygsti/evotypes/densitymx/opreps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/opreps.pyx +2 -2
- pygsti/evotypes/densitymx/statereps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/statereps.pyx +1 -1
- pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
- pygsti/evotypes/densitymx_slow/opreps.py +16 -23
- pygsti/evotypes/densitymx_slow/statereps.py +10 -3
- pygsti/evotypes/evotype.py +39 -2
- pygsti/evotypes/stabilizer/effectreps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
- pygsti/evotypes/stabilizer/opreps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/opreps.pyx +0 -4
- pygsti/evotypes/stabilizer/statereps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/statereps.pyx +1 -5
- pygsti/evotypes/stabilizer/termreps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/termreps.pyx +0 -7
- pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
- pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
- pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
- pygsti/evotypes/statevec/effectreps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/effectreps.pyx +1 -1
- pygsti/evotypes/statevec/opreps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/opreps.pyx +2 -2
- pygsti/evotypes/statevec/statereps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/statereps.pyx +1 -1
- pygsti/evotypes/statevec/termreps.cp310-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/termreps.pyx +0 -7
- pygsti/evotypes/statevec_slow/effectreps.py +0 -3
- pygsti/evotypes/statevec_slow/opreps.py +0 -5
- pygsti/extras/__init__.py +0 -1
- pygsti/extras/drift/stabilityanalyzer.py +3 -1
- pygsti/extras/interpygate/__init__.py +12 -0
- pygsti/extras/interpygate/core.py +0 -36
- pygsti/extras/interpygate/process_tomography.py +44 -10
- pygsti/extras/rpe/rpeconstruction.py +0 -2
- pygsti/forwardsims/__init__.py +1 -0
- pygsti/forwardsims/forwardsim.py +14 -55
- pygsti/forwardsims/mapforwardsim.py +69 -18
- pygsti/forwardsims/mapforwardsim_calc_densitymx.cp310-win_amd64.pyd +0 -0
- pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
- pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
- pygsti/forwardsims/matrixforwardsim.py +63 -15
- pygsti/forwardsims/termforwardsim.py +8 -110
- pygsti/forwardsims/termforwardsim_calc_stabilizer.cp310-win_amd64.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.cp310-win_amd64.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
- pygsti/forwardsims/torchfwdsim.py +265 -0
- pygsti/forwardsims/weakforwardsim.py +2 -2
- pygsti/io/__init__.py +1 -2
- pygsti/io/mongodb.py +0 -2
- pygsti/io/stdinput.py +6 -22
- pygsti/layouts/copalayout.py +10 -12
- pygsti/layouts/distlayout.py +0 -40
- pygsti/layouts/maplayout.py +103 -25
- pygsti/layouts/matrixlayout.py +99 -60
- pygsti/layouts/prefixtable.py +1534 -52
- pygsti/layouts/termlayout.py +1 -1
- pygsti/modelmembers/instruments/instrument.py +3 -3
- pygsti/modelmembers/instruments/tpinstrument.py +2 -2
- pygsti/modelmembers/modelmember.py +0 -17
- pygsti/modelmembers/operations/__init__.py +2 -4
- pygsti/modelmembers/operations/affineshiftop.py +1 -0
- pygsti/modelmembers/operations/composederrorgen.py +1 -1
- pygsti/modelmembers/operations/composedop.py +1 -24
- pygsti/modelmembers/operations/denseop.py +5 -5
- pygsti/modelmembers/operations/eigpdenseop.py +2 -2
- pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
- pygsti/modelmembers/operations/embeddedop.py +0 -1
- pygsti/modelmembers/operations/experrorgenop.py +2 -2
- pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
- pygsti/modelmembers/operations/fullcptpop.py +2 -2
- pygsti/modelmembers/operations/fulltpop.py +28 -6
- pygsti/modelmembers/operations/fullunitaryop.py +5 -4
- pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
- pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
- pygsti/modelmembers/operations/linearop.py +7 -27
- pygsti/modelmembers/operations/opfactory.py +1 -1
- pygsti/modelmembers/operations/repeatedop.py +1 -24
- pygsti/modelmembers/operations/staticstdop.py +1 -1
- pygsti/modelmembers/povms/__init__.py +3 -3
- pygsti/modelmembers/povms/basepovm.py +7 -36
- pygsti/modelmembers/povms/complementeffect.py +4 -9
- pygsti/modelmembers/povms/composedeffect.py +0 -320
- pygsti/modelmembers/povms/computationaleffect.py +1 -1
- pygsti/modelmembers/povms/computationalpovm.py +3 -1
- pygsti/modelmembers/povms/effect.py +3 -5
- pygsti/modelmembers/povms/marginalizedpovm.py +0 -79
- pygsti/modelmembers/povms/tppovm.py +74 -2
- pygsti/modelmembers/states/__init__.py +2 -5
- pygsti/modelmembers/states/composedstate.py +0 -317
- pygsti/modelmembers/states/computationalstate.py +3 -3
- pygsti/modelmembers/states/cptpstate.py +4 -4
- pygsti/modelmembers/states/densestate.py +6 -4
- pygsti/modelmembers/states/fullpurestate.py +0 -24
- pygsti/modelmembers/states/purestate.py +1 -1
- pygsti/modelmembers/states/state.py +5 -6
- pygsti/modelmembers/states/tpstate.py +28 -10
- pygsti/modelmembers/term.py +3 -6
- pygsti/modelmembers/torchable.py +50 -0
- pygsti/modelpacks/_modelpack.py +1 -1
- pygsti/modelpacks/smq1Q_ZN.py +3 -1
- pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
- pygsti/modelpacks/smq2Q_XY.py +3 -3
- pygsti/modelpacks/smq2Q_XYI.py +2 -2
- pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
- pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
- pygsti/modelpacks/smq2Q_XYXX.py +1 -1
- pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
- pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
- pygsti/modelpacks/stdtarget.py +0 -121
- pygsti/models/cloudnoisemodel.py +1 -2
- pygsti/models/explicitcalc.py +3 -3
- pygsti/models/explicitmodel.py +3 -13
- pygsti/models/fogistore.py +5 -3
- pygsti/models/localnoisemodel.py +1 -2
- pygsti/models/memberdict.py +0 -12
- pygsti/models/model.py +800 -65
- pygsti/models/modelconstruction.py +4 -4
- pygsti/models/modelnoise.py +2 -2
- pygsti/models/modelparaminterposer.py +1 -1
- pygsti/models/oplessmodel.py +1 -1
- pygsti/models/qutrit.py +15 -14
- pygsti/objectivefns/objectivefns.py +73 -138
- pygsti/objectivefns/wildcardbudget.py +2 -7
- pygsti/optimize/__init__.py +1 -0
- pygsti/optimize/arraysinterface.py +28 -0
- pygsti/optimize/customcg.py +0 -12
- pygsti/optimize/customlm.py +129 -323
- pygsti/optimize/customsolve.py +2 -2
- pygsti/optimize/optimize.py +0 -84
- pygsti/optimize/simplerlm.py +841 -0
- pygsti/optimize/wildcardopt.py +19 -598
- pygsti/protocols/confidenceregionfactory.py +28 -14
- pygsti/protocols/estimate.py +31 -14
- pygsti/protocols/gst.py +142 -68
- pygsti/protocols/modeltest.py +6 -10
- pygsti/protocols/protocol.py +9 -37
- pygsti/protocols/rb.py +450 -79
- pygsti/protocols/treenode.py +8 -2
- pygsti/protocols/vb.py +108 -206
- pygsti/protocols/vbdataframe.py +1 -1
- pygsti/report/factory.py +0 -15
- pygsti/report/fogidiagram.py +1 -17
- pygsti/report/modelfunction.py +12 -3
- pygsti/report/mpl_colormaps.py +1 -1
- pygsti/report/plothelpers.py +8 -2
- pygsti/report/reportables.py +41 -37
- pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
- pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
- pygsti/report/workspace.py +2 -14
- pygsti/report/workspaceplots.py +326 -504
- pygsti/tools/basistools.py +9 -36
- pygsti/tools/edesigntools.py +124 -96
- pygsti/tools/fastcalc.cp310-win_amd64.pyd +0 -0
- pygsti/tools/fastcalc.pyx +35 -81
- pygsti/tools/internalgates.py +151 -15
- pygsti/tools/jamiolkowski.py +5 -5
- pygsti/tools/lindbladtools.py +19 -11
- pygsti/tools/listtools.py +0 -114
- pygsti/tools/matrixmod2.py +1 -1
- pygsti/tools/matrixtools.py +173 -339
- pygsti/tools/nameddict.py +1 -1
- pygsti/tools/optools.py +154 -88
- pygsti/tools/pdftools.py +0 -25
- pygsti/tools/rbtheory.py +3 -320
- pygsti/tools/slicetools.py +64 -12
- pyGSTi-0.9.12.1.dist-info/METADATA +0 -155
- pygsti/algorithms/directx.py +0 -711
- pygsti/evotypes/qibo/__init__.py +0 -33
- pygsti/evotypes/qibo/effectreps.py +0 -78
- pygsti/evotypes/qibo/opreps.py +0 -376
- pygsti/evotypes/qibo/povmreps.py +0 -98
- pygsti/evotypes/qibo/statereps.py +0 -174
- pygsti/extras/rb/__init__.py +0 -13
- pygsti/extras/rb/benchmarker.py +0 -957
- pygsti/extras/rb/dataset.py +0 -378
- pygsti/extras/rb/io.py +0 -814
- pygsti/extras/rb/simulate.py +0 -1020
- pygsti/io/legacyio.py +0 -385
- pygsti/modelmembers/povms/denseeffect.py +0 -142
- {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
- {pyGSTi-0.9.12.1.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.
|
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.
|
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
|
|
pygsti/tools/internalgates.py
CHANGED
@@ -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
|
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
|
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
|
-
|
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
|
-
|
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]) + ')']
|
pygsti/tools/jamiolkowski.py
CHANGED
@@ -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
|
-
|
121
|
-
|
122
|
-
|
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).
|
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).
|
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
|
|
pygsti/tools/lindbladtools.py
CHANGED
@@ -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.
|
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()
|
94
|
+
normalization_factor = _np.vdot(elem_errgen.toarray(), primal.toarray())
|
94
95
|
else:
|
95
|
-
normalization_factor = _np.vdot(elem_errgen
|
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:
|
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]
|
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
|
-
|
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.
|
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:
|
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
|