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
@@ -51,7 +51,6 @@ def mapfill_probs_atom(fwdsim, mx_to_fill, dest_indices, layout_atom, resource_a
|
|
51
51
|
|
52
52
|
#TODO: if layout_atom is split, distribute somehow among processors(?) instead of punting for all but rank-0 above
|
53
53
|
for iDest, iStart, remainder, iCache in layout_atom.table.contents:
|
54
|
-
remainder = remainder.circuit_without_povm.layertup
|
55
54
|
|
56
55
|
if iStart is None: # then first element of remainder is a state prep label
|
57
56
|
rholabel = remainder[0]
|
@@ -73,7 +72,63 @@ def mapfill_probs_atom(fwdsim, mx_to_fill, dest_indices, layout_atom, resource_a
|
|
73
72
|
mx_to_fill[final_indices] = povmreps[povm_lbl].probabilities(final_state, None, effect_labels)
|
74
73
|
else:
|
75
74
|
ereps = [effectreps[j] for j in layout_atom.elbl_indices_by_expcircuit[iDest]]
|
75
|
+
#print(ereps)
|
76
|
+
if shared_mem_leader:
|
77
|
+
for j, erep in zip(final_indices, ereps):
|
78
|
+
mx_to_fill[j] = erep.probability(final_state) # outcome probability
|
79
|
+
#raise Exception
|
80
|
+
#Version of the probability calculation that updates circuit probabilities conditionally based on
|
81
|
+
#Whether the circuit is sensitive to the parameter. If not we leave that circuit alone.
|
82
|
+
def cond_update_probs_atom(fwdsim, mx_to_fill, dest_indices, layout_atom, param_index, resource_alloc):
|
83
|
+
|
84
|
+
# The required ending condition is that array_to_fill on each processor has been filled. But if
|
85
|
+
# memory is being shared and resource_alloc contains multiple processors on a single host, we only
|
86
|
+
# want *one* (the rank=0) processor to perform the computation, since array_to_fill will be
|
87
|
+
# shared memory that we don't want to have muliple procs using simultaneously to compute the
|
88
|
+
# same thing. Thus, we carefully guard any shared mem updates/usage
|
89
|
+
# using "if shared_mem_leader" (and barriers, if needed) below.
|
90
|
+
shared_mem_leader = resource_alloc.is_host_leader if (resource_alloc is not None) else True
|
91
|
+
|
92
|
+
dest_indices = _slct.to_array(dest_indices) # make sure this is an array and not a slice
|
93
|
+
cacheSize = layout_atom.jac_table.cache_size_by_parameter[param_index]
|
94
|
+
|
95
|
+
#Create rhoCache
|
96
|
+
rho_cache = [None] * cacheSize # so we can store (s,p) tuples in cache
|
97
|
+
|
98
|
+
#Get operationreps and ereps now so we don't make unnecessary ._rep references
|
99
|
+
rhoreps = {rholbl: fwdsim.model._circuit_layer_operator(rholbl, 'prep')._rep for rholbl in layout_atom.rho_labels}
|
100
|
+
operationreps = {gl: fwdsim.model._circuit_layer_operator(gl, 'op')._rep for gl in layout_atom.op_labels}
|
101
|
+
povmreps = {plbl: fwdsim.model._circuit_layer_operator(plbl, 'povm')._rep for plbl in layout_atom.povm_labels}
|
102
|
+
if any([(povmrep is None) for povmrep in povmreps.values()]):
|
103
|
+
effectreps = {i: fwdsim.model._circuit_layer_operator(Elbl, 'povm')._rep
|
104
|
+
for i, Elbl in enumerate(layout_atom.full_effect_labels)} # cache these in future
|
105
|
+
else:
|
106
|
+
effectreps = None # not needed, as we use povm reps directly
|
107
|
+
|
108
|
+
|
109
|
+
#TODO: if layout_atom is split, distribute somehow among processors(?) instead of punting for all but rank-0 above
|
110
|
+
|
111
|
+
for iDest, iStart, remainder, iCache in layout_atom.jac_table.contents_by_parameter[param_index]:
|
112
|
+
|
113
|
+
if iStart is None: # then first element of remainder is a state prep label
|
114
|
+
rholabel = remainder[0]
|
115
|
+
init_state = rhoreps[rholabel]
|
116
|
+
remainder = remainder[1:]
|
117
|
+
else:
|
118
|
+
init_state = rho_cache[iStart] # [:,None]
|
119
|
+
|
120
|
+
final_state = propagate_staterep(init_state, [operationreps[gl] for gl in remainder])
|
121
|
+
if iCache is not None: rho_cache[iCache] = final_state # [:,0] #store this state in the cache
|
122
|
+
|
123
|
+
final_indices = [dest_indices[j] for j in layout_atom.elindices_by_expcircuit[iDest]]
|
124
|
+
|
125
|
+
if effectreps is None:
|
126
|
+
povm_lbl, *effect_labels = layout_atom.povm_and_elbls_by_expcircuit[iDest]
|
76
127
|
|
128
|
+
if shared_mem_leader:
|
129
|
+
mx_to_fill[final_indices] = povmreps[povm_lbl].probabilities(final_state, None, effect_labels)
|
130
|
+
else:
|
131
|
+
ereps = [effectreps[j] for j in layout_atom.elbl_indices_by_expcircuit[iDest]]
|
77
132
|
if shared_mem_leader:
|
78
133
|
for j, erep in zip(final_indices, ereps):
|
79
134
|
mx_to_fill[j] = erep.probability(final_state) # outcome probability
|
@@ -82,11 +137,10 @@ def mapfill_probs_atom(fwdsim, mx_to_fill, dest_indices, layout_atom, resource_a
|
|
82
137
|
def mapfill_dprobs_atom(fwdsim, mx_to_fill, dest_indices, dest_param_indices, layout_atom, param_indices,
|
83
138
|
resource_alloc, eps):
|
84
139
|
|
85
|
-
|
86
|
-
#shared_mem_leader = resource_alloc.is_host_leader if (resource_alloc is not None) else True
|
140
|
+
num_params = fwdsim.model.num_params
|
87
141
|
|
88
142
|
if param_indices is None:
|
89
|
-
param_indices = list(range(
|
143
|
+
param_indices = list(range(num_params))
|
90
144
|
if dest_param_indices is None:
|
91
145
|
dest_param_indices = list(range(_slct.length(param_indices)))
|
92
146
|
|
@@ -105,19 +159,43 @@ def mapfill_dprobs_atom(fwdsim, mx_to_fill, dest_indices, dest_param_indices, la
|
|
105
159
|
nEls = layout_atom.num_elements
|
106
160
|
probs, shm = _smt.create_shared_ndarray(resource_alloc, (nEls,), 'd', memory_tracker=None)
|
107
161
|
probs2, shm2 = _smt.create_shared_ndarray(resource_alloc, (nEls,), 'd', memory_tracker=None)
|
162
|
+
#probs2_test, shm2_test = _smt.create_shared_ndarray(resource_alloc, (nEls,), 'd', memory_tracker=None)
|
163
|
+
|
164
|
+
#mx_to_fill_test = mx_to_fill.copy()
|
165
|
+
|
108
166
|
mapfill_probs_atom(fwdsim, probs, slice(0, nEls), layout_atom, resource_alloc) # probs != shared
|
109
167
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
168
|
+
#Split off the first finite difference step, as the pattern I want in the loop with each step
|
169
|
+
#is to simultaneously undo the previous update and apply the new one.
|
170
|
+
if len(param_indices)>0:
|
171
|
+
probs2[:] = probs[:]
|
172
|
+
first_param_idx = param_indices[0]
|
173
|
+
iFinal = iParamToFinal[first_param_idx]
|
174
|
+
fwdsim.model.set_parameter_value(first_param_idx, orig_vec[first_param_idx]+eps)
|
175
|
+
#mapfill_probs_atom(fwdsim, probs2, slice(0, nEls), layout_atom, resource_alloc)
|
176
|
+
cond_update_probs_atom(fwdsim, probs2, slice(0, nEls), layout_atom, first_param_idx, resource_alloc)
|
177
|
+
#assert _np.linalg.norm(probs2_test-probs2) < 1e-10
|
178
|
+
#print(f'{_np.linalg.norm(probs2_test-probs2)=}')
|
179
|
+
_fas(mx_to_fill, [dest_indices, iFinal], (probs2 - probs) / eps)
|
180
|
+
|
181
|
+
|
182
|
+
for i in range(1, len(param_indices)):
|
183
|
+
probs2[:] = probs[:]
|
184
|
+
iFinal = iParamToFinal[param_indices[i]]
|
185
|
+
fwdsim.model.set_parameter_values([param_indices[i-1], param_indices[i]],
|
186
|
+
[orig_vec[param_indices[i-1]], orig_vec[param_indices[i]]+eps])
|
187
|
+
#mapfill_probs_atom(fwdsim, probs2, slice(0, nEls), layout_atom, resource_alloc)
|
188
|
+
cond_update_probs_atom(fwdsim, probs2, slice(0, nEls), layout_atom, param_indices[i], resource_alloc)
|
189
|
+
#assert _np.linalg.norm(probs2_test-probs2) < 1e-10
|
190
|
+
#print(f'{_np.linalg.norm(probs2_test-probs2)=}')
|
191
|
+
_fas(mx_to_fill, [dest_indices, iFinal], (probs2 - probs) / eps)
|
192
|
+
|
193
|
+
#reset the final model parameter we changed to it's original value.
|
194
|
+
fwdsim.model.set_parameter_value(param_indices[-1], orig_vec[param_indices[-1]])
|
195
|
+
|
119
196
|
_smt.cleanup_shared_ndarray(shm)
|
120
197
|
_smt.cleanup_shared_ndarray(shm2)
|
198
|
+
#_smt.cleanup_shared_ndarray(shm2_test)
|
121
199
|
|
122
200
|
|
123
201
|
def mapfill_TDchi2_terms(fwdsim, array_to_fill, dest_indices, num_outcomes, layout_atom, dataset_rows,
|
@@ -29,6 +29,8 @@ from pygsti.tools import mpitools as _mpit
|
|
29
29
|
from pygsti.tools import sharedmemtools as _smt
|
30
30
|
from pygsti.tools import slicetools as _slct
|
31
31
|
from pygsti.tools.matrixtools import _fas
|
32
|
+
from pygsti.tools import listtools as _lt
|
33
|
+
from pygsti.circuits import CircuitList as _CircuitList
|
32
34
|
|
33
35
|
_dummy_profiler = _DummyProfiler()
|
34
36
|
|
@@ -132,12 +134,18 @@ class SimpleMatrixForwardSimulator(_ForwardSimulator):
|
|
132
134
|
obj_wrtFilter = [] # values = object-local param indices
|
133
135
|
relevant_gpindices = [] # indices into original wrt_filter'd indices
|
134
136
|
|
135
|
-
|
137
|
+
if isinstance(obj.gpindices, slice):
|
138
|
+
gpindices_list = _slct.indices(obj.gpindices)
|
139
|
+
elif obj.gpindices is None:
|
140
|
+
gpindices_list = []
|
141
|
+
else:
|
142
|
+
gpindices_list = list(obj.gpindices)
|
143
|
+
gpindices_set = set(gpindices_list)
|
136
144
|
|
137
145
|
for ii, i in enumerate(wrt_filter):
|
138
|
-
if i in
|
146
|
+
if i in gpindices_set:
|
139
147
|
relevant_gpindices.append(ii)
|
140
|
-
obj_wrtFilter.append(
|
148
|
+
obj_wrtFilter.append(gpindices_list.index(i))
|
141
149
|
relevant_gpindices = _np.array(relevant_gpindices, _np.int64)
|
142
150
|
if len(relevant_gpindices) == 1:
|
143
151
|
#Don't return a length-1 list, as this doesn't index numpy arrays
|
@@ -590,7 +598,7 @@ class SimpleMatrixForwardSimulator(_ForwardSimulator):
|
|
590
598
|
use_scaling = False # Hardcoded for now
|
591
599
|
assert(time is None), "MatrixForwardSimulator cannot be used to simulate time-dependent circuits"
|
592
600
|
|
593
|
-
expanded_circuit_outcomes =
|
601
|
+
expanded_circuit_outcomes = self.model.expand_instruments_and_separate_povm(circuit, outcomes)
|
594
602
|
outcome_to_index = {outc: i for i, outc in enumerate(outcomes)}
|
595
603
|
for spc, spc_outcomes in expanded_circuit_outcomes.items(): # spc is a SeparatePOVMCircuit
|
596
604
|
indices = [outcome_to_index[o] for o in spc_outcomes]
|
@@ -1025,7 +1033,7 @@ class MatrixForwardSimulator(_DistributableForwardSimulator, SimpleMatrixForward
|
|
1025
1033
|
return hProdCache
|
1026
1034
|
|
1027
1035
|
def create_layout(self, circuits, dataset=None, resource_alloc=None, array_types=('E',),
|
1028
|
-
derivative_dimensions=None, verbosity=0):
|
1036
|
+
derivative_dimensions=None, verbosity=0, layout_creation_circuit_cache= None):
|
1029
1037
|
"""
|
1030
1038
|
Constructs an circuit-outcome-probability-array (COPA) layout for a list of circuits.
|
1031
1039
|
|
@@ -1056,6 +1064,12 @@ class MatrixForwardSimulator(_DistributableForwardSimulator, SimpleMatrixForward
|
|
1056
1064
|
Determines how much output to send to stdout. 0 means no output, higher
|
1057
1065
|
integers mean more output.
|
1058
1066
|
|
1067
|
+
layout_creation_circuit_cache : dict, optional (default None)
|
1068
|
+
A precomputed dictionary serving as a cache for completed
|
1069
|
+
circuits. I.e. circuits with prep labels and POVM labels appended.
|
1070
|
+
Along with other useful pre-computed circuit structures used in layout
|
1071
|
+
creation.
|
1072
|
+
|
1059
1073
|
Returns
|
1060
1074
|
-------
|
1061
1075
|
MatrixCOPALayout
|
@@ -1105,7 +1119,8 @@ class MatrixForwardSimulator(_DistributableForwardSimulator, SimpleMatrixForward
|
|
1105
1119
|
assert(_np.prod((na,) + npp) <= nprocs), "Processor grid size exceeds available processors!"
|
1106
1120
|
|
1107
1121
|
layout = _MatrixCOPALayout(circuits, self.model, dataset, natoms,
|
1108
|
-
na, npp, param_dimensions, param_blk_sizes, resource_alloc, verbosity
|
1122
|
+
na, npp, param_dimensions, param_blk_sizes, resource_alloc, verbosity,
|
1123
|
+
layout_creation_circuit_cache=layout_creation_circuit_cache)
|
1109
1124
|
|
1110
1125
|
if mem_limit is not None:
|
1111
1126
|
loc_nparams1 = num_params / npp[0] if len(npp) > 0 else 0
|
@@ -1132,13 +1147,6 @@ class MatrixForwardSimulator(_DistributableForwardSimulator, SimpleMatrixForward
|
|
1132
1147
|
(blk1, blk2), max_atom_cachesize,
|
1133
1148
|
self.model.evotype.minimal_dim(self.model.state_space))
|
1134
1149
|
|
1135
|
-
#def approx_mem_estimate(natoms, np1, np2):
|
1136
|
-
# approx_cachesize = (num_circuits / natoms) * 1.3 # inflate expected # circuits per atom => cache_size
|
1137
|
-
# return _bytes_for_array_types(array_types, num_elements, num_elements / natoms,
|
1138
|
-
# num_circuits, num_circuits / natoms,
|
1139
|
-
# (num_params, num_params), (num_params / np1, num_params / np2),
|
1140
|
-
# approx_cachesize, self.model.state_space.dim)
|
1141
|
-
|
1142
1150
|
GB = 1.0 / 1024.0**3
|
1143
1151
|
if mem_estimate > mem_limit:
|
1144
1152
|
raise MemoryError("Not enough memory for desired layout! (limit=%.1fGB, required=%.1fGB)" % (
|
@@ -1147,6 +1155,46 @@ class MatrixForwardSimulator(_DistributableForwardSimulator, SimpleMatrixForward
|
|
1147
1155
|
printer.log(" Esimated memory required = %.1fGB" % (mem_estimate * GB))
|
1148
1156
|
|
1149
1157
|
return layout
|
1158
|
+
|
1159
|
+
@staticmethod
|
1160
|
+
def create_copa_layout_circuit_cache(circuits, model, dataset=None):
|
1161
|
+
"""
|
1162
|
+
Helper function for pre-computing/pre-processing circuits structures
|
1163
|
+
used in matrix layout creation.
|
1164
|
+
"""
|
1165
|
+
cache = dict()
|
1166
|
+
completed_circuits, split_circuits = model.complete_circuits(circuits, return_split=True)
|
1167
|
+
|
1168
|
+
cache['completed_circuits'] = {ckt: comp_ckt for ckt, comp_ckt in zip(circuits, completed_circuits)}
|
1169
|
+
cache['split_circuits'] = {ckt: split_ckt for ckt, split_ckt in zip(circuits, split_circuits)}
|
1170
|
+
|
1171
|
+
if dataset is not None:
|
1172
|
+
aliases = circuits.op_label_aliases if isinstance(circuits, _CircuitList) else None
|
1173
|
+
ds_circuits = _lt.apply_aliases_to_circuits(circuits, aliases)
|
1174
|
+
unique_outcomes_list = []
|
1175
|
+
for ckt in ds_circuits:
|
1176
|
+
ds_row = dataset[ckt]
|
1177
|
+
unique_outcomes_list.append(ds_row.unique_outcomes if ds_row is not None else None)
|
1178
|
+
else:
|
1179
|
+
unique_outcomes_list = [None]*len(circuits)
|
1180
|
+
|
1181
|
+
expanded_circuit_outcome_list = model.bulk_expand_instruments_and_separate_povm(circuits,
|
1182
|
+
observed_outcomes_list = unique_outcomes_list,
|
1183
|
+
split_circuits = split_circuits)
|
1184
|
+
|
1185
|
+
expanded_circuit_cache = {ckt: expanded_ckt for ckt,expanded_ckt in zip(circuits, expanded_circuit_outcome_list)}
|
1186
|
+
|
1187
|
+
cache['expanded_and_separated_circuits'] = expanded_circuit_cache
|
1188
|
+
|
1189
|
+
expanded_subcircuits_no_spam_cache = dict()
|
1190
|
+
for expc_outcomes in cache['expanded_and_separated_circuits'].values():
|
1191
|
+
for sep_povm_c, _ in expc_outcomes.items(): # for each expanded cir from unique_i-th circuit
|
1192
|
+
exp_nospam_c = sep_povm_c.circuit_without_povm[1:]
|
1193
|
+
expanded_subcircuits_no_spam_cache[exp_nospam_c] = exp_nospam_c.expand_subcircuits()
|
1194
|
+
|
1195
|
+
cache['expanded_subcircuits_no_spam'] = expanded_subcircuits_no_spam_cache
|
1196
|
+
|
1197
|
+
return cache
|
1150
1198
|
|
1151
1199
|
def _scale_exp(self, scale_exps):
|
1152
1200
|
old_err = _np.seterr(over='ignore')
|
@@ -1194,7 +1242,8 @@ class MatrixForwardSimulator(_DistributableForwardSimulator, SimpleMatrixForward
|
|
1194
1242
|
# dp_dOps[i,j] = dot( e, dot( d_gs, rho ) )[0,i,j,0]
|
1195
1243
|
# dp_dOps = squeeze( dot( e, dot( d_gs, rho ) ), axis=(0,3))
|
1196
1244
|
old_err2 = _np.seterr(invalid='ignore', over='ignore')
|
1197
|
-
|
1245
|
+
path = _np.einsum_path('hk,ijkl,lm->ij', e, d_gs, rho, optimize='optimal')
|
1246
|
+
dp_dOps = _np.einsum('hk,ijkl,lm->ij', e, d_gs, rho, optimize=path[0]) * scale_vals[:, None]
|
1198
1247
|
_np.seterr(**old_err2)
|
1199
1248
|
# may overflow, but OK ; shape == (len(circuit_list), nDerivCols)
|
1200
1249
|
# may also give invalid value due to scale_vals being inf and dot-prod being 0. In
|
@@ -1234,7 +1283,6 @@ class MatrixForwardSimulator(_DistributableForwardSimulator, SimpleMatrixForward
|
|
1234
1283
|
# dp_drhos[i,J0+J] = sum_kl e[0,k] gs[i,k,l] drhoP[l,J]
|
1235
1284
|
# dp_drhos[i,J0+J] = dot(e, gs, drhoP)[0,i,J]
|
1236
1285
|
# dp_drhos[:,J0+J] = squeeze(dot(e, gs, drhoP),axis=(0,))[:,J]
|
1237
|
-
|
1238
1286
|
dp_drhos = _np.zeros((nCircuits, nOpDerivCols))
|
1239
1287
|
_fas(dp_drhos, [None, rho_gpindices],
|
1240
1288
|
_np.squeeze(_np.dot(_np.dot(e, gs),
|
@@ -243,16 +243,6 @@ class TermForwardSimulator(_DistributableForwardSimulator):
|
|
243
243
|
# and this is done by the parent model which will cause _set_evotype to be called.
|
244
244
|
return state
|
245
245
|
|
246
|
-
#OLD - now we have a _set_evotype method.
|
247
|
-
#@_ForwardSimulator.model.setter
|
248
|
-
#def model(self, val):
|
249
|
-
# _ForwardSimulator.model.fset(self, val) # set the base class property (self.model)
|
250
|
-
#
|
251
|
-
# #Do some additional initialization
|
252
|
-
# if self.model.evotype not in ("svterm", "cterm"):
|
253
|
-
# #raise ValueError(f"Evolution type {self.model.evotype} is incompatible with term-based calculations")
|
254
|
-
# _warnings.warn("Evolution type %s is incompatible with term-based calculations" % self.model.evotype)
|
255
|
-
|
256
246
|
def copy(self):
|
257
247
|
"""
|
258
248
|
Return a shallow copy of this TermForwardSimulator.
|
@@ -267,7 +257,7 @@ class TermForwardSimulator(_DistributableForwardSimulator):
|
|
267
257
|
self.oob_check_interval, self.cache)
|
268
258
|
|
269
259
|
def create_layout(self, circuits, dataset=None, resource_alloc=None, array_types=('E',),
|
270
|
-
derivative_dimension=None, verbosity=0):
|
260
|
+
derivative_dimension=None, verbosity=0, layout_creation_circuit_cache=None):
|
271
261
|
"""
|
272
262
|
Constructs an circuit-outcome-probability-array (COPA) layout for a list of circuits.
|
273
263
|
|
@@ -296,6 +286,12 @@ class TermForwardSimulator(_DistributableForwardSimulator):
|
|
296
286
|
verbosity : int or VerbosityPrinter
|
297
287
|
Determines how much output to send to stdout. 0 means no output, higher
|
298
288
|
integers mean more output.
|
289
|
+
|
290
|
+
layout_creation_circuit_cache:
|
291
|
+
A precomputed dictionary serving as a cache for completed
|
292
|
+
circuits. I.e. circuits with prep labels and POVM labels appended.
|
293
|
+
Along with other useful pre-computed circuit structures used in layout
|
294
|
+
creation.
|
299
295
|
|
300
296
|
Returns
|
301
297
|
-------
|
@@ -330,6 +326,7 @@ class TermForwardSimulator(_DistributableForwardSimulator):
|
|
330
326
|
printer.log(" %d atoms, parameter block size limits %s" % (natoms, str(param_blk_sizes)))
|
331
327
|
assert(_np.prod((na,) + npp) <= nprocs), "Processor grid size exceeds available processors!"
|
332
328
|
|
329
|
+
# TODO: Layout circuit creation cache unused for TermCOPALayout
|
333
330
|
layout = _TermCOPALayout(circuits, self.model, dataset, natoms, na, npp, param_dimensions,
|
334
331
|
param_blk_sizes, resource_alloc, printer)
|
335
332
|
#MEM debug_prof.print_memory("CreateLayout2 - nAtoms = %d" % len(layout.atoms), True)
|
@@ -409,105 +406,6 @@ class TermForwardSimulator(_DistributableForwardSimulator):
|
|
409
406
|
hpolys[0], hpolys[1], self.model.to_vector(), (nEls, len(wrtInds1), len(wrtInds2)))
|
410
407
|
_fas(array_to_fill, [slice(0, array_to_fill.shape[0]), dest_param_slice1, dest_param_slice2], hprobs)
|
411
408
|
|
412
|
-
#DIRECT FNS - keep these around, but they need to be updated (as do routines in fastreplib.pyx)
|
413
|
-
#def _prs_directly(self, layout_atom, resource_alloc): #comm=None, mem_limit=None, reset_wts=True, repcache=None):
|
414
|
-
# """
|
415
|
-
# Compute probabilities of `layout`'s circuits using "direct" mode.
|
416
|
-
#
|
417
|
-
# Parameters
|
418
|
-
# ----------
|
419
|
-
# layout : CircuitOutcomeProbabilityArrayLayout
|
420
|
-
# The layout.
|
421
|
-
#
|
422
|
-
# comm : mpi4py.MPI.Comm, optional
|
423
|
-
# When not None, an MPI communicator for distributing the computation
|
424
|
-
# across multiple processors. Distribution is performed over
|
425
|
-
# subtrees of eval_tree (if it is split).
|
426
|
-
#
|
427
|
-
# mem_limit : int, optional
|
428
|
-
# A rough memory limit in bytes.
|
429
|
-
#
|
430
|
-
# reset_wts : bool, optional
|
431
|
-
# Whether term magnitudes should be updated based on current term coefficients
|
432
|
-
# (which are based on the current point in model-parameter space) or not.
|
433
|
-
#
|
434
|
-
# repcache : dict, optional
|
435
|
-
# A cache of term representations for increased performance.
|
436
|
-
# """
|
437
|
-
# prs = _np.empty(layout_atom.num_elements, 'd')
|
438
|
-
# #print("Computing prs directly for %d circuits" % len(circuit_list))
|
439
|
-
# if repcache is None: repcache = {} # new repcache...
|
440
|
-
# k = 0 # *linear* evaluation order so we know final indices are just running
|
441
|
-
# for i in eval_tree.evaluation_order():
|
442
|
-
# circuit = eval_tree[i]
|
443
|
-
# #print("Computing prs directly: circuit %d of %d" % (i,len(circuit_list)))
|
444
|
-
# assert(self.evotype == "svterm") # for now, just do SV case
|
445
|
-
# fastmode = False # start with slow mode
|
446
|
-
# wtTol = 0.1
|
447
|
-
# rholabel = circuit[0]
|
448
|
-
# opStr = circuit[1:]
|
449
|
-
# elabels = eval_tree.simplified_circuit_elabels[i]
|
450
|
-
# prs[k:k + len(elabels)] = replib.SV_prs_directly(self, rholabel, elabels, opStr,
|
451
|
-
# repcache, comm, mem_limit, fastmode, wtTol, reset_wts,
|
452
|
-
# self.times_debug)
|
453
|
-
# k += len(elabels)
|
454
|
-
# #print("PRS = ",prs)
|
455
|
-
# return prs
|
456
|
-
#
|
457
|
-
#def _dprs_directly(self, eval_tree, wrt_slice, comm=None, mem_limit=None, reset_wts=True, repcache=None):
|
458
|
-
# """
|
459
|
-
# Compute probability derivatives of `eval_tree`'s circuits using "direct" mode.
|
460
|
-
#
|
461
|
-
# Parameters
|
462
|
-
# ----------
|
463
|
-
# eval_tree : TermEvalTree
|
464
|
-
# The evaluation tree.
|
465
|
-
#
|
466
|
-
# wrt_slice : slice
|
467
|
-
# A slice specifying which model parameters to differentiate with respect to.
|
468
|
-
#
|
469
|
-
# comm : mpi4py.MPI.Comm, optional
|
470
|
-
# When not None, an MPI communicator for distributing the computation
|
471
|
-
# across multiple processors. Distribution is performed over
|
472
|
-
# subtrees of eval_tree (if it is split).
|
473
|
-
#
|
474
|
-
# mem_limit : int, optional
|
475
|
-
# A rough memory limit in bytes.
|
476
|
-
#
|
477
|
-
# reset_wts : bool, optional
|
478
|
-
# Whether term magnitudes should be updated based on current term coefficients
|
479
|
-
# (which are based on the current point in model-parameter space) or not.
|
480
|
-
#
|
481
|
-
# repcache : dict, optional
|
482
|
-
# A cache of term representations for increased performance.
|
483
|
-
# """
|
484
|
-
# #Note: Finite difference derivatives are SLOW!
|
485
|
-
# if wrt_slice is None:
|
486
|
-
# wrt_indices = list(range(self.Np))
|
487
|
-
# elif isinstance(wrt_slice, slice):
|
488
|
-
# wrt_indices = _slct.indices(wrt_slice)
|
489
|
-
# else:
|
490
|
-
# wrt_indices = wrt_slice
|
491
|
-
#
|
492
|
-
# eps = 1e-6 # HARDCODED
|
493
|
-
# probs = self._prs_directly(eval_tree, comm, mem_limit, reset_wts, repcache)
|
494
|
-
# dprobs = _np.empty((eval_tree.num_final_elements(), len(wrt_indices)), 'd')
|
495
|
-
# orig_vec = self.to_vector().copy()
|
496
|
-
# iParamToFinal = {i: ii for ii, i in enumerate(wrt_indices)}
|
497
|
-
# for i in range(self.Np):
|
498
|
-
# #print("direct dprobs cache %d of %d" % (i,self.Np))
|
499
|
-
# if i in iParamToFinal: # LATER: add MPI support?
|
500
|
-
# iFinal = iParamToFinal[i]
|
501
|
-
# vec = orig_vec.copy(); vec[i] += eps
|
502
|
-
# self.from_vector(vec, close=True)
|
503
|
-
# dprobs[:, iFinal] = (self._prs_directly(eval_tree,
|
504
|
-
# comm=None,
|
505
|
-
# mem_limit=None,
|
506
|
-
# reset_wts=False,
|
507
|
-
# repcache=repcache) - probs) / eps
|
508
|
-
# self.from_vector(orig_vec, close=True)
|
509
|
-
# return dprobs
|
510
|
-
|
511
409
|
## ----- Find a "minimal" path set (i.e. find thresholds for each circuit -----
|
512
410
|
def _compute_pruned_pathmag_threshold(self, rholabel, elabels, circuit, polynomial_vindices_per_int,
|
513
411
|
repcache, circuitsetup_cache,
|
Binary file
|
Binary file
|