pyGSTi 0.9.12__cp39-cp39-win_amd64.whl → 0.9.13__cp39-cp39-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.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +211 -220
- {pyGSTi-0.9.12.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 +62 -35
- pygsti/algorithms/fiducialpairreduction.py +95 -110
- 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.cp39-win_amd64.pyd +0 -0
- pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
- pygsti/baseobjs/polynomial.py +13 -595
- pygsti/baseobjs/protectedarray.py +72 -132
- pygsti/baseobjs/statespace.py +1 -0
- pygsti/circuits/__init__.py +1 -1
- pygsti/circuits/circuit.py +753 -504
- pygsti/circuits/circuitconstruction.py +0 -4
- pygsti/circuits/circuitlist.py +47 -5
- pygsti/circuits/circuitparser/__init__.py +8 -8
- pygsti/circuits/circuitparser/fastcircuitparser.cp39-win_amd64.pyd +0 -0
- pygsti/circuits/circuitstructure.py +3 -3
- pygsti/circuits/cloudcircuitconstruction.py +27 -14
- pygsti/data/datacomparator.py +4 -9
- pygsti/data/dataset.py +51 -46
- pygsti/data/hypothesistest.py +0 -7
- pygsti/drivers/bootstrap.py +0 -49
- pygsti/drivers/longsequence.py +46 -10
- pygsti/evotypes/basereps_cython.cp39-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.cp39-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/effectreps.pyx +1 -1
- pygsti/evotypes/densitymx/opreps.cp39-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/opreps.pyx +2 -2
- pygsti/evotypes/densitymx/statereps.cp39-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.cp39-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
- pygsti/evotypes/stabilizer/opreps.cp39-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/opreps.pyx +0 -4
- pygsti/evotypes/stabilizer/statereps.cp39-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/statereps.pyx +1 -5
- pygsti/evotypes/stabilizer/termreps.cp39-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.cp39-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/effectreps.pyx +1 -1
- pygsti/evotypes/statevec/opreps.cp39-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/opreps.pyx +2 -2
- pygsti/evotypes/statevec/statereps.cp39-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/statereps.pyx +1 -1
- pygsti/evotypes/statevec/termreps.cp39-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/signal.py +1 -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 +50 -93
- pygsti/forwardsims/mapforwardsim.py +78 -20
- pygsti/forwardsims/mapforwardsim_calc_densitymx.cp39-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 +72 -17
- pygsti/forwardsims/termforwardsim.py +9 -111
- pygsti/forwardsims/termforwardsim_calc_stabilizer.cp39-win_amd64.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.cp39-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 +3 -4
- pygsti/modelmembers/operations/affineshiftop.py +206 -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 +5 -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 +3 -81
- 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 +10 -8
- 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 +801 -68
- 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 +75 -140
- 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 +238 -142
- pygsti/protocols/modeltest.py +19 -12
- 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 +11 -3
- pygsti/report/report.py +16 -0
- 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 +328 -505
- pygsti/tools/basistools.py +9 -36
- pygsti/tools/edesigntools.py +124 -96
- pygsti/tools/fastcalc.cp39-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.dist-info/METADATA +0 -157
- 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.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
- {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
@@ -26,6 +26,8 @@ from pygsti.baseobjs.verbosityprinter import VerbosityPrinter as _VerbosityPrint
|
|
26
26
|
from pygsti.tools import sharedmemtools as _smt
|
27
27
|
from pygsti.tools import slicetools as _slct
|
28
28
|
from pygsti.tools.matrixtools import _fas
|
29
|
+
from pygsti.tools import listtools as _lt
|
30
|
+
from pygsti.circuits import CircuitList as _CircuitList
|
29
31
|
|
30
32
|
_dummy_profiler = _DummyProfiler()
|
31
33
|
|
@@ -49,7 +51,7 @@ class SimpleMapForwardSimulator(_ForwardSimulator):
|
|
49
51
|
# If this is done, then MapForwardSimulator wouldn't need to separately subclass DistributableForwardSimulator
|
50
52
|
|
51
53
|
def _compute_circuit_outcome_probabilities(self, array_to_fill, circuit, outcomes, resource_alloc, time=None):
|
52
|
-
expanded_circuit_outcomes =
|
54
|
+
expanded_circuit_outcomes = self.model.expand_instruments_and_separate_povm(circuit, outcomes)
|
53
55
|
outcome_to_index = {outc: i for i, outc in enumerate(outcomes)}
|
54
56
|
for spc, spc_outcomes in expanded_circuit_outcomes.items(): # spc is a SeparatePOVMCircuit
|
55
57
|
# Note: `spc.circuit_without_povm` *always* begins with a prep label.
|
@@ -157,7 +159,7 @@ class MapForwardSimulator(_DistributableForwardSimulator, SimpleMapForwardSimula
|
|
157
159
|
if method_name == 'bulk_fill_timedep_dchi2': return ('p',) # just an additional parameter vector
|
158
160
|
return super()._array_types_for_method(method_name)
|
159
161
|
|
160
|
-
def __init__(self, model=None, max_cache_size=
|
162
|
+
def __init__(self, model=None, max_cache_size=None, num_atoms=None, processor_grid=None, param_blk_sizes=None,
|
161
163
|
derivative_eps=1e-7, hessian_eps=1e-5):
|
162
164
|
#super().__init__(model, num_atoms, processor_grid, param_blk_sizes)
|
163
165
|
_DistributableForwardSimulator.__init__(self, model, num_atoms, processor_grid, param_blk_sizes)
|
@@ -193,7 +195,9 @@ class MapForwardSimulator(_DistributableForwardSimulator, SimpleMapForwardSimula
|
|
193
195
|
self._processor_grid, self._pblk_sizes)
|
194
196
|
|
195
197
|
def create_layout(self, circuits, dataset=None, resource_alloc=None, array_types=('E',),
|
196
|
-
|
198
|
+
derivative_dimensions=None, verbosity=0, layout_creation_circuit_cache=None,
|
199
|
+
circuit_partition_cost_functions=('size', 'propagations'),
|
200
|
+
load_balancing_parameters=(1.15,.1)):
|
197
201
|
"""
|
198
202
|
Constructs an circuit-outcome-probability-array (COPA) layout for a list of circuits.
|
199
203
|
|
@@ -214,14 +218,32 @@ class MapForwardSimulator(_DistributableForwardSimulator, SimpleMapForwardSimula
|
|
214
218
|
array_types : tuple, optional
|
215
219
|
A tuple of string-valued array types. See :meth:`ForwardSimulator.create_layout`.
|
216
220
|
|
217
|
-
|
221
|
+
derivative_dimensions : int or tuple[int], optional
|
218
222
|
Optionally, the parameter-space dimension used when taking first
|
219
223
|
and second derivatives with respect to the cirucit outcome probabilities. This must be
|
220
224
|
non-None when `array_types` contains `'ep'` or `'epp'` types.
|
225
|
+
If a tuple, then must be length 1.
|
221
226
|
|
222
227
|
verbosity : int or VerbosityPrinter
|
223
228
|
Determines how much output to send to stdout. 0 means no output, higher
|
224
229
|
integers mean more output.
|
230
|
+
|
231
|
+
layout_creation_circuit_cache : dict, optional (default None)
|
232
|
+
A precomputed dictionary serving as a cache for completed circuits. I.e. circuits
|
233
|
+
with prep labels and POVM labels appended. Along with other useful pre-computed
|
234
|
+
circuit structures used in layout creation.
|
235
|
+
|
236
|
+
circuit_partition_cost_functions : tuple of str, optional (default ('size', 'propagations'))
|
237
|
+
A tuple of strings denoting cost function to use in each of the two stages of the algorithm
|
238
|
+
for determining the partitions of the complete circuit set amongst atoms.
|
239
|
+
Allowed options are 'size', which corresponds to balancing the number of circuits,
|
240
|
+
and 'propagations', which corresponds to balancing the number of state propagations.
|
241
|
+
|
242
|
+
load_balancing_parameters : tuple of floats, optional (default (1.15, .1))
|
243
|
+
A tuple of floats used as load balancing parameters when splitting a layout across atoms,
|
244
|
+
as in the multi-processor setting when using MPI. These parameters correspond to the `imbalance_threshold`
|
245
|
+
and `minimum_improvement_threshold` parameters described in the method `find_splitting_new`
|
246
|
+
of the `PrefixTable` class.
|
225
247
|
|
226
248
|
Returns
|
227
249
|
-------
|
@@ -233,7 +255,13 @@ class MapForwardSimulator(_DistributableForwardSimulator, SimpleMapForwardSimula
|
|
233
255
|
if (resource_alloc.mem_limit is not None) else None # *per-processor* memory limit
|
234
256
|
nprocs = resource_alloc.comm_size
|
235
257
|
comm = resource_alloc.comm
|
236
|
-
|
258
|
+
if isinstance(derivative_dimensions, int):
|
259
|
+
num_params = derivative_dimensions
|
260
|
+
elif isinstance(derivative_dimensions, tuple):
|
261
|
+
assert len(derivative_dimensions) == 1
|
262
|
+
num_params = derivative_dimensions[0]
|
263
|
+
else:
|
264
|
+
num_params = self.model.num_params
|
237
265
|
C = 1.0 / (1024.0**3)
|
238
266
|
|
239
267
|
if mem_limit is not None:
|
@@ -241,15 +269,15 @@ class MapForwardSimulator(_DistributableForwardSimulator, SimpleMapForwardSimula
|
|
241
269
|
raise MemoryError("Attempted layout creation w/memory limit = %g <= 0!" % mem_limit)
|
242
270
|
printer.log("Layout creation w/mem limit = %.2fGB" % (mem_limit * C))
|
243
271
|
|
244
|
-
#Start with how we'd like to split processors up (without regard to memory limit):
|
245
|
-
|
246
|
-
#
|
247
|
-
|
248
|
-
#
|
249
|
-
#work_per_proc = self.model.dim**2
|
272
|
+
#Start with how we'd like to split processors up (without regard to memory limit):
|
273
|
+
#The current implementation of map (should) benefit more from having a matching between the number of atoms
|
274
|
+
#and the number of processors, at least for up to around two-qubits.
|
275
|
+
default_natoms = nprocs # heuristic
|
276
|
+
#TODO: factor in the mem_limit value to more intelligently set the default number of atoms.
|
250
277
|
|
251
278
|
natoms, na, npp, param_dimensions, param_blk_sizes = self._compute_processor_distribution(
|
252
|
-
array_types, nprocs, num_params, len(circuits), default_natoms=
|
279
|
+
array_types, nprocs, num_params, len(circuits), default_natoms=default_natoms)
|
280
|
+
|
253
281
|
printer.log(f'Num Param Processors {npp}')
|
254
282
|
|
255
283
|
printer.log("MapLayout: %d processors divided into %s (= %d) grid along circuit and parameter directions." %
|
@@ -258,7 +286,9 @@ class MapForwardSimulator(_DistributableForwardSimulator, SimpleMapForwardSimula
|
|
258
286
|
assert(_np.prod((na,) + npp) <= nprocs), "Processor grid size exceeds available processors!"
|
259
287
|
|
260
288
|
layout = _MapCOPALayout(circuits, self.model, dataset, self._max_cache_size, natoms, na, npp,
|
261
|
-
param_dimensions, param_blk_sizes, resource_alloc,
|
289
|
+
param_dimensions, param_blk_sizes, resource_alloc,circuit_partition_cost_functions,
|
290
|
+
verbosity, layout_creation_circuit_cache= layout_creation_circuit_cache,
|
291
|
+
load_balancing_parameters=load_balancing_parameters)
|
262
292
|
|
263
293
|
if mem_limit is not None:
|
264
294
|
loc_nparams1 = num_params / npp[0] if len(npp) > 0 else 0
|
@@ -284,13 +314,6 @@ class MapForwardSimulator(_DistributableForwardSimulator, SimpleMapForwardSimula
|
|
284
314
|
layout._param_dimensions, (loc_nparams1, loc_nparams2),
|
285
315
|
(blk1, blk2), max_atom_cachesize, self.model.dim)
|
286
316
|
|
287
|
-
#def approx_mem_estimate(nc, np1, np2):
|
288
|
-
# approx_cachesize = (num_circuits / nc) * 1.3 # inflate expected # of circuits per atom => cache_size
|
289
|
-
# return _bytes_for_array_types(array_types, num_elements, num_elements / nc,
|
290
|
-
# num_circuits, num_circuits / nc,
|
291
|
-
# (num_params, num_params), (num_params / np1, num_params / np2),
|
292
|
-
# approx_cachesize, self.model.dim)
|
293
|
-
|
294
317
|
GB = 1.0 / 1024.0**3
|
295
318
|
if mem_estimate > mem_limit:
|
296
319
|
raise MemoryError("Not enough memory for desired layout! (limit=%.1fGB, required=%.1fGB)" % (
|
@@ -299,6 +322,41 @@ class MapForwardSimulator(_DistributableForwardSimulator, SimpleMapForwardSimula
|
|
299
322
|
printer.log(" Esimated memory required = %.1fGB" % (mem_estimate * GB))
|
300
323
|
|
301
324
|
return layout
|
325
|
+
|
326
|
+
@staticmethod
|
327
|
+
def create_copa_layout_circuit_cache(circuits, model, dataset=None):
|
328
|
+
"""
|
329
|
+
Helper function for pre-computing/pre-processing circuits structures
|
330
|
+
used in matrix layout creation.
|
331
|
+
"""
|
332
|
+
cache = dict()
|
333
|
+
completed_circuits = model.complete_circuits(circuits)
|
334
|
+
|
335
|
+
cache['completed_circuits'] = {ckt: comp_ckt for ckt, comp_ckt in zip(circuits, completed_circuits)}
|
336
|
+
|
337
|
+
split_circuits = model.split_circuits(completed_circuits, split_prep=False)
|
338
|
+
cache['split_circuits'] = {ckt: split_ckt for ckt, split_ckt in zip(circuits, split_circuits)}
|
339
|
+
|
340
|
+
|
341
|
+
if dataset is not None:
|
342
|
+
aliases = circuits.op_label_aliases if isinstance(circuits, _CircuitList) else None
|
343
|
+
ds_circuits = _lt.apply_aliases_to_circuits(circuits, aliases)
|
344
|
+
unique_outcomes_list = []
|
345
|
+
for ckt in ds_circuits:
|
346
|
+
ds_row = dataset[ckt]
|
347
|
+
unique_outcomes_list.append(ds_row.unique_outcomes if ds_row is not None else None)
|
348
|
+
else:
|
349
|
+
unique_outcomes_list = [None]*len(circuits)
|
350
|
+
|
351
|
+
expanded_circuit_outcome_list = model.bulk_expand_instruments_and_separate_povm(circuits,
|
352
|
+
observed_outcomes_list = unique_outcomes_list,
|
353
|
+
completed_circuits= completed_circuits)
|
354
|
+
|
355
|
+
expanded_circuit_cache = {ckt: expanded_ckt for ckt,expanded_ckt in zip(completed_circuits, expanded_circuit_outcome_list)}
|
356
|
+
cache['expanded_and_separated_circuits'] = expanded_circuit_cache
|
357
|
+
|
358
|
+
return cache
|
359
|
+
|
302
360
|
|
303
361
|
def _bulk_fill_probs_atom(self, array_to_fill, layout_atom, resource_alloc):
|
304
362
|
# Note: *don't* set dest_indices arg = layout.element_slice, as this is already done by caller
|
Binary file
|
@@ -1,6 +1,4 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
# cython: profile=False
|
3
|
-
# cython: linetrace=False
|
4
2
|
|
5
3
|
#***************************************************************************************************
|
6
4
|
# Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
@@ -28,12 +26,6 @@ from ..tools import slicetools as _slct
|
|
28
26
|
#from ..tools import optools as _ot
|
29
27
|
from ..tools.matrixtools import _fas
|
30
28
|
|
31
|
-
#DEBUG REMOVE MEMORY PROFILING
|
32
|
-
#import os, psutil
|
33
|
-
#process = psutil.Process(os.getpid())
|
34
|
-
#def print_mem_usage(prefix):
|
35
|
-
# print("%s: mem usage = %.3f GB" % (prefix, process.memory_info().rss / (1024.0**3)))
|
36
|
-
|
37
29
|
#Use 64-bit integers
|
38
30
|
ctypedef long long INT
|
39
31
|
ctypedef unsigned long long UINT
|
@@ -59,15 +51,16 @@ def propagate_staterep(staterep, operationreps):
|
|
59
51
|
# Python -> C Conversion functions
|
60
52
|
# -----------------------------------------
|
61
53
|
|
62
|
-
|
54
|
+
@cython.wraparound(False)
|
55
|
+
cdef vector[vector[INT]] convert_maplayout(prefix_table_contents, operation_lookup, rho_lookup):
|
63
56
|
# c_layout :
|
64
57
|
# an array of INT-arrays; each INT-array is [iDest,iStart,iCache,<remainder gate indices>]
|
65
58
|
cdef vector[INT] intarray
|
66
|
-
cdef vector[vector[INT]] c_layout_atom = vector[vector[INT]](len(
|
67
|
-
for kk, (iDest, iStart, remainder, iCache) in enumerate(
|
59
|
+
cdef vector[vector[INT]] c_layout_atom = vector[vector[INT]](len(prefix_table_contents))
|
60
|
+
for kk, (iDest, iStart, remainder, iCache) in enumerate(prefix_table_contents):
|
68
61
|
if iStart is None: iStart = -1 # so always an int
|
69
62
|
if iCache is None: iCache = -1 # so always an int
|
70
|
-
remainder = remainder
|
63
|
+
remainder = remainder
|
71
64
|
intarray = vector[INT](3 + len(remainder))
|
72
65
|
intarray[0] = iDest
|
73
66
|
intarray[1] = iStart
|
@@ -107,6 +100,8 @@ cdef vector[vector[INT]] convert_and_wrap_dict_of_intlists(d, wrapper):
|
|
107
100
|
ret[i][j] = wrapper[intlist[j]]
|
108
101
|
return ret
|
109
102
|
|
103
|
+
@cython.boundscheck(False)
|
104
|
+
@cython.wraparound(False)
|
110
105
|
cdef vector[StateCRep*] create_rhocache(INT cacheSize, INT state_dim):
|
111
106
|
cdef INT i
|
112
107
|
cdef vector[StateCRep*] rho_cache = vector[StateCRep_ptr](cacheSize)
|
@@ -114,11 +109,14 @@ cdef vector[StateCRep*] create_rhocache(INT cacheSize, INT state_dim):
|
|
114
109
|
rho_cache[i] = new StateCRep(state_dim)
|
115
110
|
return rho_cache
|
116
111
|
|
112
|
+
@cython.boundscheck(False)
|
113
|
+
@cython.wraparound(False)
|
117
114
|
cdef void free_rhocache(vector[StateCRep*] rho_cache):
|
118
115
|
cdef UINT i
|
119
116
|
for i in range(rho_cache.size()): # fill cache with empty but alloc'd states
|
120
117
|
del rho_cache[i]
|
121
118
|
|
119
|
+
@cython.wraparound(False)
|
122
120
|
cdef vector[OpCRep*] convert_opreps(operationreps):
|
123
121
|
# c_opreps : an array of OpCReps
|
124
122
|
cdef vector[OpCRep*] c_opreps = vector[OpCRep_ptr](len(operationreps))
|
@@ -130,19 +128,20 @@ cdef StateCRep* convert_rhorep(rhorep):
|
|
130
128
|
# extract c-reps from rhorep and ereps => c_rho and c_ereps
|
131
129
|
return (<StateRep?>rhorep).c_state
|
132
130
|
|
131
|
+
@cython.wraparound(False)
|
133
132
|
cdef vector[StateCRep*] convert_rhoreps(rhoreps):
|
134
133
|
cdef vector[StateCRep*] c_rhoreps = vector[StateCRep_ptr](len(rhoreps))
|
135
134
|
for ii,rrep in rhoreps.items(): # (ii = python variable)
|
136
135
|
c_rhoreps[ii] = (<StateRep?>rrep).c_state
|
137
136
|
return c_rhoreps
|
138
137
|
|
138
|
+
@cython.wraparound(False)
|
139
139
|
cdef vector[EffectCRep*] convert_ereps(ereps):
|
140
140
|
cdef vector[EffectCRep*] c_ereps = vector[EffectCRep_ptr](len(ereps))
|
141
141
|
for i in range(len(ereps)):
|
142
142
|
c_ereps[i] = (<EffectRep>ereps[i]).c_effect
|
143
143
|
return c_ereps
|
144
144
|
|
145
|
-
|
146
145
|
# -----------------------------------------
|
147
146
|
# Mapfill functions
|
148
147
|
# -----------------------------------------
|
@@ -159,7 +158,6 @@ def mapfill_probs_atom(fwdsim, np.ndarray[double, mode="c", ndim=1] array_to_fil
|
|
159
158
|
shared_mem_leader = resource_alloc.is_host_leader if (resource_alloc is not None) else True
|
160
159
|
|
161
160
|
dest_indices = _slct.to_array(dest_indices) # make sure this is an array and not a slice
|
162
|
-
#dest_indices = np.ascontiguousarray(dest_indices) #unneeded
|
163
161
|
|
164
162
|
#Get (extension-type) representation objects
|
165
163
|
rho_lookup = { lbl:i for i,lbl in enumerate(layout_atom.rho_labels) } # rho labels -> ints for faster lookup
|
@@ -169,7 +167,7 @@ def mapfill_probs_atom(fwdsim, np.ndarray[double, mode="c", ndim=1] array_to_fil
|
|
169
167
|
ereps = [fwdsim.model._circuit_layer_operator(elbl, 'povm')._rep for elbl in layout_atom.full_effect_labels] # cache these in future
|
170
168
|
|
171
169
|
# convert to C-mode: evaltree, operation_lookup, operationreps
|
172
|
-
cdef vector[vector[INT]] c_layout_atom = convert_maplayout(layout_atom, operation_lookup, rho_lookup)
|
170
|
+
cdef vector[vector[INT]] c_layout_atom = convert_maplayout(layout_atom.table.contents, operation_lookup, rho_lookup)
|
173
171
|
cdef vector[StateCRep*] c_rhos = convert_rhoreps(rhoreps)
|
174
172
|
cdef vector[EffectCRep*] c_ereps = convert_ereps(ereps)
|
175
173
|
cdef vector[OpCRep*] c_opreps = convert_opreps(operationreps)
|
@@ -182,17 +180,6 @@ def mapfill_probs_atom(fwdsim, np.ndarray[double, mode="c", ndim=1] array_to_fil
|
|
182
180
|
cdef vector[vector[INT]] final_indices_per_circuit = convert_and_wrap_dict_of_intlists(
|
183
181
|
layout_atom.elindices_by_expcircuit, dest_indices)
|
184
182
|
|
185
|
-
#DEBUG REMOVE
|
186
|
-
#print_mem_usage("MAPFILL PROBS begin")
|
187
|
-
#for i in [1808, 419509, 691738, 497424]:
|
188
|
-
# from ..evotypes.densitymx.opreps import OpRepComposed
|
189
|
-
# op = operationreps[i]
|
190
|
-
# if isinstance(op.embedded_rep, OpRepComposed):
|
191
|
-
# extra = " factors = " + ', '.join([str(type(opp)) for opp in op.embedded_rep.factor_reps])
|
192
|
-
# else:
|
193
|
-
# extra = ""
|
194
|
-
# print("ID ",i,str(type(op)),str(type(op.embedded_rep)), extra)
|
195
|
-
|
196
183
|
if shared_mem_leader:
|
197
184
|
#Note: dm_mapfill_probs could have taken a resource_alloc to employ multiple cpus to do computation.
|
198
185
|
# Since array_fo_fill is assumed to be shared mem it would need to only update `array_to_fill` *if*
|
@@ -203,6 +190,7 @@ def mapfill_probs_atom(fwdsim, np.ndarray[double, mode="c", ndim=1] array_to_fil
|
|
203
190
|
free_rhocache(rho_cache) #delete cache entries
|
204
191
|
|
205
192
|
|
193
|
+
@cython.wraparound(False)
|
206
194
|
cdef dm_mapfill_probs(double[:] array_to_fill,
|
207
195
|
vector[vector[INT]] c_layout_atom,
|
208
196
|
vector[OpCRep*] c_opreps,
|
@@ -234,7 +222,7 @@ cdef dm_mapfill_probs(double[:] array_to_fill,
|
|
234
222
|
# - all rho_cache entries have been allocated via "new"
|
235
223
|
#REMOVE print("MAPFILL PROBS begin cfn")
|
236
224
|
for k in range(<INT>c_layout_atom.size()):
|
237
|
-
t0 = pytime.time() # DEBUG
|
225
|
+
#t0 = pytime.time() # DEBUG
|
238
226
|
intarray = c_layout_atom[k]
|
239
227
|
i = intarray[0]
|
240
228
|
istart = intarray[1]
|
@@ -298,22 +286,27 @@ cdef dm_mapfill_probs(double[:] array_to_fill,
|
|
298
286
|
del prop2
|
299
287
|
del shelved
|
300
288
|
|
301
|
-
|
289
|
+
@cython.wraparound(False)
|
302
290
|
def mapfill_dprobs_atom(fwdsim,
|
303
291
|
np.ndarray[double, ndim=2] array_to_fill,
|
304
292
|
dest_indices,
|
305
293
|
dest_param_indices,
|
306
294
|
layout_atom, param_indices, resource_alloc, double eps):
|
307
295
|
|
308
|
-
|
296
|
+
cdef int num_params = fwdsim.model.num_params
|
297
|
+
cdef int model_dim = fwdsim.model.dim
|
309
298
|
|
310
299
|
if param_indices is None:
|
311
|
-
param_indices = list(range(
|
300
|
+
param_indices = list(range(num_params))
|
312
301
|
if dest_param_indices is None:
|
313
302
|
dest_param_indices = list(range(_slct.length(param_indices)))
|
314
303
|
|
315
|
-
|
316
|
-
|
304
|
+
cdef np.ndarray[np.int64_t, ndim=1, mode='c'] param_indices_array = _slct.to_array(param_indices)
|
305
|
+
cdef np.ndarray[np.int64_t, ndim=1, mode='c'] dest_param_indices_array = _slct.to_array(dest_param_indices)
|
306
|
+
|
307
|
+
cdef np.int64_t[::1] param_indices_view = param_indices_array
|
308
|
+
cdef np.int64_t[::1] dest_param_indices_view = dest_param_indices_array
|
309
|
+
|
317
310
|
|
318
311
|
#Get (extension-type) representation objects
|
319
312
|
# NOTE: the circuit_layer_operator(lbl) functions cache the returned operation
|
@@ -327,7 +320,7 @@ def mapfill_dprobs_atom(fwdsim,
|
|
327
320
|
ereps = [fwdsim.model._circuit_layer_operator(elbl, 'povm')._rep for elbl in layout_atom.full_effect_labels] # cache these in future
|
328
321
|
|
329
322
|
# convert to C-mode: evaltree, operation_lookup, operationreps
|
330
|
-
cdef vector[vector[INT]] c_layout_atom = convert_maplayout(layout_atom, operation_lookup, rho_lookup)
|
323
|
+
cdef vector[vector[INT]] c_layout_atom = convert_maplayout(layout_atom.table.contents, operation_lookup, rho_lookup)
|
331
324
|
cdef vector[StateCRep*] c_rhos = convert_rhoreps(rhoreps)
|
332
325
|
cdef vector[EffectCRep*] c_ereps = convert_ereps(ereps)
|
333
326
|
cdef vector[OpCRep*] c_opreps = convert_opreps(operationreps)
|
@@ -335,53 +328,60 @@ def mapfill_dprobs_atom(fwdsim,
|
|
335
328
|
# create rho_cache = vector of StateCReps
|
336
329
|
#print "DB: creating rho_cache of size %d * %g GB => %g GB" % \
|
337
330
|
# (layout_atom.cache_size, 8.0 * fwdsim.model.dim / 1024.0**3, layout_atom.cache_size * 8.0 * fwdsim.model.dim / 1024.0**3)
|
338
|
-
cdef vector[StateCRep*] rho_cache = create_rhocache(layout_atom.cache_size,
|
331
|
+
cdef vector[StateCRep*] rho_cache = create_rhocache(layout_atom.cache_size, model_dim)
|
339
332
|
|
340
333
|
cdef vector[vector[INT]] elabel_indices_per_circuit = convert_dict_of_intlists(layout_atom.elbl_indices_by_expcircuit)
|
341
334
|
cdef vector[vector[INT]] final_indices_per_circuit = convert_dict_of_intlists(layout_atom.elindices_by_expcircuit)
|
342
335
|
|
343
|
-
orig_vec = fwdsim.model.to_vector().copy()
|
336
|
+
cdef np.ndarray[np.float64_t, ndim=1, mode='c'] orig_vec = fwdsim.model.to_vector().copy()
|
337
|
+
cdef double[::1] orig_vec_view = orig_vec
|
344
338
|
fwdsim.model.from_vector(orig_vec, close=False) # ensure we call with close=False first
|
345
339
|
|
346
340
|
nEls = layout_atom.num_elements
|
347
|
-
probs = np.empty(nEls,
|
348
|
-
probs2 = np.empty(nEls,
|
341
|
+
cdef np.ndarray[np.float64_t, ndim=1, mode='c'] probs = np.empty(nEls, dtype=np.float64) #must be contiguous!
|
342
|
+
cdef np.ndarray[np.float64_t, ndim=1, mode='c'] probs2 = np.empty(nEls, dtype=np.float64) #must be contiguous!
|
343
|
+
|
344
|
+
cdef double[::1] probs_view = probs
|
345
|
+
cdef double[::1] probs2_view = probs2
|
349
346
|
|
350
347
|
#if resource_alloc.comm_rank == 0:
|
351
348
|
# print("MAPFILL DPROBS ATOM 1"); t=pytime.time(); t0=pytime.time()
|
352
|
-
dm_mapfill_probs(
|
353
|
-
elabel_indices_per_circuit, final_indices_per_circuit, fwdsim.model.dim)
|
349
|
+
dm_mapfill_probs(probs_view, c_layout_atom, c_opreps, c_rhos, c_ereps, &rho_cache, elabel_indices_per_circuit, final_indices_per_circuit, model_dim)
|
354
350
|
#if resource_alloc.comm_rank == 0:
|
355
351
|
# print("MAPFILL DPROBS ATOM 2 %.3fs" % (pytime.time() - t)); t=pytime.time()
|
356
352
|
|
357
|
-
shared_mem_leader = resource_alloc.is_host_leader
|
358
|
-
|
359
|
-
#
|
360
|
-
|
361
|
-
|
353
|
+
cdef bint shared_mem_leader = resource_alloc.is_host_leader
|
354
|
+
|
355
|
+
#add typing to indices we'll be using below:
|
356
|
+
cdef int i
|
357
|
+
cdef int first_param_idx
|
358
|
+
cdef int iFinal
|
359
|
+
|
360
|
+
#Split off the first finite difference step, as the pattern I want in the loop with each step
|
361
|
+
#is to simultaneously undo the previous update and apply the new one.
|
362
|
+
if len(param_indices_view)>0:
|
363
|
+
#probs2_view[:] = probs_view[:]
|
364
|
+
first_param_idx = param_indices_view[0]
|
365
|
+
iFinal = dest_param_indices_view[0]
|
366
|
+
fwdsim.model.set_parameter_value(first_param_idx, orig_vec_view[first_param_idx]+eps)
|
367
|
+
if shared_mem_leader: # don't fill assumed-shared array-to_fill on non-mem-leaders
|
368
|
+
dm_mapfill_probs(probs2_view, c_layout_atom, c_opreps, c_rhos, c_ereps, &rho_cache, elabel_indices_per_circuit, final_indices_per_circuit, model_dim)
|
369
|
+
array_to_fill[dest_indices, iFinal] = (probs2 - probs) / eps
|
370
|
+
|
371
|
+
for i in range(1, len(param_indices_view)):
|
372
|
+
#probs2_view[:] = probs_view[:]
|
373
|
+
iFinal = dest_param_indices_view[i]
|
374
|
+
fwdsim.model.set_parameter_values([param_indices_view[i-1], param_indices_view[i]], [orig_vec_view[param_indices_view[i-1]], orig_vec_view[param_indices_view[i]]+eps])
|
375
|
+
|
376
|
+
if shared_mem_leader: # don't fill assumed-shared array-to_fill on non-mem-leaders
|
377
|
+
dm_mapfill_probs(probs2_view, c_layout_atom, c_opreps, c_rhos, c_ereps, &rho_cache, elabel_indices_per_circuit, final_indices_per_circuit, model_dim)
|
378
|
+
array_to_fill[dest_indices, iFinal] = (probs2 - probs) / eps
|
379
|
+
|
380
|
+
#reset the final model parameter we changed to it's original value.
|
381
|
+
fwdsim.model.set_parameter_value(param_indices_view[len(param_indices_view)-1], orig_vec_view[param_indices_view[len(param_indices_view)-1]])
|
362
382
|
|
363
|
-
for i in range(fwdsim.model.num_params):
|
364
|
-
#print("dprobs cache %d of %d" % (i,self.Np))
|
365
|
-
if i in iParamToFinal:
|
366
|
-
#if resource_alloc.comm_rank == 0:
|
367
|
-
# print("MAPFILL DPROBS ATOM 3 (i=%d) %.3fs elapssed=%.1fs" % (i, pytime.time() - t, pytime.time() - t0)); t=pytime.time()
|
368
|
-
iFinal = iParamToFinal[i]
|
369
|
-
vec = orig_vec.copy(); vec[i] += eps
|
370
|
-
fwdsim.model.from_vector(vec, close=True)
|
371
|
-
#Note: dm_mapfill_probs could have taken a resource_alloc to employ multiple cpus to do computation.
|
372
|
-
# If probs2 were shared mem (seems not benefit to this?) it would need to only update `probs2` *if*
|
373
|
-
# it were the host leader.
|
374
|
-
if shared_mem_leader: # don't fill assumed-shared array-to_fill on non-mem-leaders
|
375
|
-
dm_mapfill_probs(probs2, c_layout_atom, c_opreps, c_rhos, c_ereps, &rho_cache,
|
376
|
-
elabel_indices_per_circuit, final_indices_per_circuit, fwdsim.model.dim)
|
377
|
-
#_fas(array_to_fill, [dest_indices, iFinal], (probs2 - probs) / eps) # I don't think this is needed
|
378
|
-
array_to_fill[dest_indices, iFinal] = (probs2 - probs) / eps
|
379
|
-
|
380
|
-
#if resource_alloc.comm_rank == 0:
|
381
|
-
# print("MAPFILL DPROBS ATOM 4 elapsed=%.1fs" % (pytime.time() - t0))
|
382
|
-
fwdsim.model.from_vector(orig_vec, close=True)
|
383
383
|
free_rhocache(rho_cache) #delete cache entries
|
384
|
-
|
384
|
+
|
385
385
|
|
386
386
|
cdef double TDchi2_obj_fn(double p, double f, double n_i, double n, double omitted_p, double min_prob_clip_for_weighting, double extra):
|
387
387
|
cdef double cp, v, omitted_cp
|
@@ -475,7 +475,6 @@ def mapfill_TDterms(fwdsim, objective, array_to_fill, dest_indices, num_outcomes
|
|
475
475
|
#comm is currently ignored
|
476
476
|
#TODO: if layout_atom is split, distribute among processors
|
477
477
|
for iDest, iStart, remainder, iCache in layout_atom.table.contents:
|
478
|
-
remainder = remainder.circuit_without_povm.layertup
|
479
478
|
rholabel = remainder[0]; remainder = remainder[1:]
|
480
479
|
rhoVec = fwdsim.model._circuit_layer_operator(rholabel, 'prep')
|
481
480
|
|
@@ -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,
|