pyGSTi 0.9.12__cp38-cp38-win_amd64.whl → 0.9.13__cp38-cp38-win_amd64.whl
Sign up to get free protection for your applications and to get access to all the features.
- pyGSTi-0.9.13.dist-info/METADATA +185 -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.cp38-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.cp38-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.cp38-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.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/effectreps.pyx +1 -1
- pygsti/evotypes/densitymx/opreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/opreps.pyx +2 -2
- pygsti/evotypes/densitymx/statereps.cp38-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.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
- pygsti/evotypes/stabilizer/opreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/opreps.pyx +0 -4
- pygsti/evotypes/stabilizer/statereps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/statereps.pyx +1 -5
- pygsti/evotypes/stabilizer/termreps.cp38-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.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/effectreps.pyx +1 -1
- pygsti/evotypes/statevec/opreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/opreps.pyx +2 -2
- pygsti/evotypes/statevec/statereps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/statereps.pyx +1 -1
- pygsti/evotypes/statevec/termreps.cp38-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.cp38-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.cp38-win_amd64.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.cp38-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.cp38-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
pygsti/protocols/gst.py
CHANGED
@@ -20,6 +20,7 @@ import pathlib as _pathlib
|
|
20
20
|
|
21
21
|
import numpy as _np
|
22
22
|
from scipy.stats import chi2 as _chi2
|
23
|
+
from typing import Optional
|
23
24
|
|
24
25
|
from pygsti.baseobjs.profiler import DummyProfiler as _DummyProfiler
|
25
26
|
from pygsti.baseobjs.nicelyserializable import NicelySerializable as _NicelySerializable
|
@@ -37,6 +38,7 @@ from pygsti import baseobjs as _baseobjs
|
|
37
38
|
from pygsti.processors import QuditProcessorSpec as _QuditProcessorSpec
|
38
39
|
from pygsti.modelmembers import operations as _op
|
39
40
|
from pygsti.models import Model as _Model
|
41
|
+
from pygsti.models.explicitmodel import ExplicitOpModel as _ExplicitOpModel
|
40
42
|
from pygsti.models.gaugegroup import GaugeGroup as _GaugeGroup, GaugeGroupElement as _GaugeGroupElement
|
41
43
|
from pygsti.objectivefns import objectivefns as _objfns, wildcardbudget as _wild
|
42
44
|
from pygsti.circuits.circuitlist import CircuitList as _CircuitList
|
@@ -44,6 +46,7 @@ from pygsti.baseobjs.resourceallocation import ResourceAllocation as _ResourceAl
|
|
44
46
|
from pygsti.modelmembers import states as _states, povms as _povms
|
45
47
|
from pygsti.tools.legacytools import deprecate as _deprecated_fn
|
46
48
|
from pygsti.circuits import Circuit
|
49
|
+
from pygsti.forwardsims import ForwardSimulator
|
47
50
|
|
48
51
|
|
49
52
|
#For results object:
|
@@ -535,7 +538,7 @@ class GSTInitialModel(_NicelySerializable):
|
|
535
538
|
if comm is None or comm.Get_rank() == 0:
|
536
539
|
#Advanced Options can specify further manipulation of starting model
|
537
540
|
if self.contract_start_to_cptp:
|
538
|
-
mdl_start = _alg.contract(mdl_start, "
|
541
|
+
mdl_start = _alg.contract(mdl_start, "CPTPLND")
|
539
542
|
raise ValueError(
|
540
543
|
"'contractStartToCPTP' has been removed b/c it can change the parameterization of a model")
|
541
544
|
if self.depolarize_start > 0:
|
@@ -593,7 +596,7 @@ class GSTBadFitOptions(_NicelySerializable):
|
|
593
596
|
Actions to take when a GST fit is unsatisfactory. Allowed actions include:
|
594
597
|
|
595
598
|
* 'wildcard': Find an admissable wildcard model.
|
596
|
-
* '
|
599
|
+
* 'wildcard1d': Fits a single parameter wildcard model in which
|
597
600
|
the amount of wildcard error added to an operation is proportional
|
598
601
|
to the diamond distance between that operation and the target.
|
599
602
|
* 'robust': scale data according out "robust statistics v1" algorithm,
|
@@ -637,10 +640,8 @@ class GSTBadFitOptions(_NicelySerializable):
|
|
637
640
|
|
638
641
|
wildcard_methods: tuple, optional
|
639
642
|
A list of the methods to use to optimize the wildcard error vector. Default is `("neldermead",)`.
|
640
|
-
Options include `"neldermead"`, `"barrier"`,
|
641
|
-
and `"
|
642
|
-
(unfortunately). Leave as the default as a safe option, but `"barrier"` is pretty reliable and much
|
643
|
-
faster than `"neldermead"`, and is a good option so long as it runs.
|
643
|
+
Options include `"neldermead"`, `"barrier"`, and `"cvxpy_noagg"`. Leave as the default as a safe option,
|
644
|
+
but `"barrier"` is pretty reliable and much faster than `"neldermead"`, and is a good option so long as it runs.
|
644
645
|
|
645
646
|
wildcard_inadmissable_action: {"print", "raise"}, optional
|
646
647
|
What to do when an inadmissable wildcard error vector is found. The default just prints this
|
@@ -839,7 +840,9 @@ class GSTGaugeOptSuite(_NicelySerializable):
|
|
839
840
|
- "varyValidSpamWt" : varies spam weight with SPAM penalty == 1.
|
840
841
|
- "toggleValidSpam" : toggles spame penalty (0 or 1); fixed SPAM wt.
|
841
842
|
- "unreliable2Q" : adds branch to a spam suite that weights 2Q gates less
|
842
|
-
- "none" : no gauge optimizations are performed.
|
843
|
+
- "none" : no gauge optimizations are performed. When passed individually
|
844
|
+
(not in a list with other suite names) then this results in an empty
|
845
|
+
GSTGaugeOptSuite object (w/gaugeopt_suite_names set to None).
|
843
846
|
|
844
847
|
gaugeopt_argument_dicts : dict, optional
|
845
848
|
A dictionary whose string-valued keys label different gauge optimizations (e.g. within a
|
@@ -870,8 +873,11 @@ class GSTGaugeOptSuite(_NicelySerializable):
|
|
870
873
|
def __init__(self, gaugeopt_suite_names=None, gaugeopt_argument_dicts=None, gaugeopt_target=None):
|
871
874
|
super().__init__()
|
872
875
|
if gaugeopt_suite_names is not None:
|
873
|
-
|
874
|
-
|
876
|
+
if gaugeopt_suite_names == 'none':
|
877
|
+
self.gaugeopt_suite_names = None
|
878
|
+
else:
|
879
|
+
self.gaugeopt_suite_names = (gaugeopt_suite_names,) \
|
880
|
+
if isinstance(gaugeopt_suite_names, str) else tuple(gaugeopt_suite_names)
|
875
881
|
else:
|
876
882
|
self.gaugeopt_suite_names = None
|
877
883
|
|
@@ -949,6 +955,8 @@ class GSTGaugeOptSuite(_NicelySerializable):
|
|
949
955
|
if hasattr(goparams, 'keys'): # goparams is a simple dict
|
950
956
|
gaugeopt_suite_dict[lbl] = goparams.copy()
|
951
957
|
gaugeopt_suite_dict[lbl].update({'verbosity': printer})
|
958
|
+
elif goparams is None:
|
959
|
+
gaugeopt_suite_dict[lbl] = None
|
952
960
|
else: # assume goparams is an iterable
|
953
961
|
assert(isinstance(goparams, (list, tuple))), \
|
954
962
|
"If not a dictionary, gauge opt params should be a list or tuple of dicts!"
|
@@ -961,7 +969,13 @@ class GSTGaugeOptSuite(_NicelySerializable):
|
|
961
969
|
if self.gaugeopt_target is not None:
|
962
970
|
assert(isinstance(self.gaugeopt_target, _Model)), "`gaugeopt_target` must be None or a Model"
|
963
971
|
for goparams in gaugeopt_suite_dict.values():
|
964
|
-
|
972
|
+
if hasattr(goparams, 'keys'):
|
973
|
+
goparams_list = [goparams]
|
974
|
+
elif goparams is None: #edge case for 'none' suite
|
975
|
+
continue
|
976
|
+
else:
|
977
|
+
goparams_list = goparams
|
978
|
+
|
965
979
|
for goparams_dict in goparams_list:
|
966
980
|
if 'target_model' in goparams_dict:
|
967
981
|
_warnings.warn(("`gaugeOptTarget` argument is overriding"
|
@@ -1086,8 +1100,8 @@ class GSTGaugeOptSuite(_NicelySerializable):
|
|
1086
1100
|
elif suite_name == "unreliable2Q":
|
1087
1101
|
raise ValueError(("unreliable2Q is no longer a separate 'suite'. You should precede it with the suite"
|
1088
1102
|
" name, e.g. 'stdgaugeopt-unreliable2Q' or 'varySpam-unreliable2Q'"))
|
1089
|
-
elif suite_name ==
|
1090
|
-
|
1103
|
+
elif suite_name == 'none':
|
1104
|
+
gaugeopt_suite_dict[root_lbl] = None
|
1091
1105
|
else:
|
1092
1106
|
raise ValueError("Unknown gauge-optimization suite '%s'" % suite_name)
|
1093
1107
|
|
@@ -1120,6 +1134,9 @@ class GSTGaugeOptSuite(_NicelySerializable):
|
|
1120
1134
|
for lbl, goparams in self.gaugeopt_argument_dicts.items():
|
1121
1135
|
goparams_list = [goparams] if hasattr(goparams, 'keys') else goparams
|
1122
1136
|
serialize_list = []
|
1137
|
+
if lbl == 'trivial_gauge_opt':
|
1138
|
+
dicts_to_serialize[lbl] = None
|
1139
|
+
continue
|
1123
1140
|
for goparams_dict in goparams_list:
|
1124
1141
|
to_add = goparams_dict.copy()
|
1125
1142
|
if 'target_model' in to_add:
|
@@ -1151,6 +1168,9 @@ class GSTGaugeOptSuite(_NicelySerializable):
|
|
1151
1168
|
def _from_nice_serialization(cls, state): # memo holds already de-serialized objects
|
1152
1169
|
gaugeopt_argument_dicts = {}
|
1153
1170
|
for lbl, serialized_goparams_list in state['gaugeopt_argument_dicts'].items():
|
1171
|
+
if lbl == 'trivial_gauge_opt':
|
1172
|
+
gaugeopt_argument_dicts[lbl] = None
|
1173
|
+
continue
|
1154
1174
|
goparams_list = []
|
1155
1175
|
for serialized_goparams in serialized_goparams_list:
|
1156
1176
|
to_add = serialized_goparams.copy()
|
@@ -1230,15 +1250,16 @@ class GateSetTomography(_proto.Protocol):
|
|
1230
1250
|
|
1231
1251
|
if isinstance(optimizer, _opt.Optimizer):
|
1232
1252
|
self.optimizer = optimizer
|
1233
|
-
if
|
1234
|
-
#special behavior: can set optimizer's first_fditer to `None` to mean "fill with default"
|
1253
|
+
if hasattr(optimizer,'first_fditer') and optimizer.first_fditer is None:
|
1254
|
+
# special behavior: can set optimizer's first_fditer to `None` to mean "fill with default"
|
1235
1255
|
self.optimizer = _copy.deepcopy(optimizer) # don't mess with caller's optimizer
|
1236
1256
|
self.optimizer.first_fditer = default_first_fditer
|
1237
1257
|
else:
|
1238
|
-
if optimizer is None:
|
1258
|
+
if optimizer is None:
|
1259
|
+
optimizer = {}
|
1239
1260
|
if 'first_fditer' not in optimizer: # then add default first_fditer value
|
1240
1261
|
optimizer['first_fditer'] = default_first_fditer
|
1241
|
-
self.optimizer = _opt.
|
1262
|
+
self.optimizer = _opt.SimplerLMOptimizer.cast(optimizer)
|
1242
1263
|
|
1243
1264
|
self.objfn_builders = GSTObjFnBuilders.cast(objfn_builders)
|
1244
1265
|
|
@@ -1257,20 +1278,8 @@ class GateSetTomography(_proto.Protocol):
|
|
1257
1278
|
self.circuit_weights = None
|
1258
1279
|
self.unreliable_ops = ('Gcnot', 'Gcphase', 'Gms', 'Gcn', 'Gcx', 'Gcz')
|
1259
1280
|
|
1260
|
-
|
1261
|
-
|
1262
|
-
# design = StandardGSTDesign(target_model, prep_fiducials, meas_fiducials, germs, max_lengths)
|
1263
|
-
# return self.run(_proto.ProtocolData(design, dataset))
|
1264
|
-
#
|
1265
|
-
#def run_using_circuit_structures(self, target_model, circuit_structs, dataset):
|
1266
|
-
# design = StructuredGSTDesign(target_model, circuit_structs)
|
1267
|
-
# return self.run(_proto.ProtocolData(design, dataset))
|
1268
|
-
#
|
1269
|
-
#def run_using_circuit_lists(self, target_model, circuit_lists, dataset):
|
1270
|
-
# design = GateSetTomographyDesign(target_model, circuit_lists)
|
1271
|
-
# return self.run(_proto.ProtocolData(design, dataset))
|
1272
|
-
|
1273
|
-
def run(self, data, memlimit=None, comm=None, checkpoint=None, checkpoint_path=None, disable_checkpointing = False):
|
1281
|
+
def run(self, data, memlimit=None, comm=None, checkpoint=None, checkpoint_path=None, disable_checkpointing=False,
|
1282
|
+
simulator: Optional[ForwardSimulator.Castable]=None):
|
1274
1283
|
"""
|
1275
1284
|
Run this protocol on `data`.
|
1276
1285
|
|
@@ -1303,6 +1312,11 @@ class GateSetTomography(_proto.Protocol):
|
|
1303
1312
|
to disk during the course of this protocol. It is strongly recommended
|
1304
1313
|
that this be kept set to False without good reason to disable the checkpoints.
|
1305
1314
|
|
1315
|
+
simulator : ForwardSimulator.Castable or None
|
1316
|
+
Ignored if None. If not None, then we call
|
1317
|
+
fwdsim = ForwardSimulator.cast(simulator),
|
1318
|
+
and we set the .sim attribute of every Model we encounter to fwdsim.
|
1319
|
+
|
1306
1320
|
Returns
|
1307
1321
|
-------
|
1308
1322
|
ModelEstimateResults
|
@@ -1337,54 +1351,56 @@ class GateSetTomography(_proto.Protocol):
|
|
1337
1351
|
tnxt = _time.time(); profiler.add_time('GST: loading', tref); tref = tnxt
|
1338
1352
|
mdl_start = self.initial_model.retrieve_model(data.edesign, self.gaugeopt_suite.gaugeopt_target,
|
1339
1353
|
data.dataset, comm)
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1354
|
+
if simulator is not None:
|
1355
|
+
mdl_start.sim = simulator
|
1356
|
+
|
1357
|
+
if disable_checkpointing:
|
1358
|
+
seed_model = mdl_start.copy()
|
1359
|
+
mdl_lsgst_list = []
|
1360
|
+
starting_idx = 0
|
1361
|
+
else:
|
1362
|
+
# Set the checkpoint_path variable if None
|
1343
1363
|
if checkpoint_path is None:
|
1344
1364
|
checkpoint_path = _pathlib.Path('./gst_checkpoints/' + self.name)
|
1345
1365
|
else:
|
1346
|
-
#cast this to a pathlib path with the file extension (suffix) dropped
|
1366
|
+
# cast this to a pathlib path with the file extension (suffix) dropped
|
1347
1367
|
checkpoint_path = _pathlib.Path(checkpoint_path).with_suffix('')
|
1348
|
-
|
1349
|
-
#create the parent directory of the checkpoint if needed:
|
1368
|
+
|
1369
|
+
# create the parent directory of the checkpoint if needed:
|
1350
1370
|
checkpoint_path.parent.mkdir(parents=True, exist_ok=True)
|
1351
|
-
|
1352
|
-
#If there is no checkpoint we should start from with the seed model,
|
1353
|
-
#otherwise we should seed the next iteration with the last iteration's result.
|
1354
|
-
#If there is no checkpoint initialize mdl_lsgst_list and final_objfn to be empty,
|
1355
|
-
#otherwise re-initialize their values from the checkpoint
|
1371
|
+
|
1372
|
+
# If there is no checkpoint we should start from with the seed model,
|
1373
|
+
# otherwise we should seed the next iteration with the last iteration's result.
|
1374
|
+
# If there is no checkpoint initialize mdl_lsgst_list and final_objfn to be empty,
|
1375
|
+
# otherwise re-initialize their values from the checkpoint
|
1356
1376
|
if checkpoint is None:
|
1357
1377
|
seed_model = mdl_start.copy()
|
1358
1378
|
mdl_lsgst_list = []
|
1359
1379
|
checkpoint = GateSetTomographyCheckpoint()
|
1360
1380
|
elif isinstance(checkpoint, GateSetTomographyCheckpoint):
|
1361
|
-
#if the checkpoint's last completed iteration is non-negative
|
1362
|
-
#(i.e. the checkpoint actually has data in it)
|
1381
|
+
# if the checkpoint's last completed iteration is non-negative
|
1382
|
+
# (i.e. the checkpoint actually has data in it)
|
1363
1383
|
if checkpoint.last_completed_iter >= 0:
|
1364
1384
|
seed_model = checkpoint.mdl_list[-1]
|
1365
|
-
#otherwise seed with target
|
1385
|
+
# otherwise seed with target
|
1366
1386
|
else:
|
1367
1387
|
seed_model = mdl_start.copy()
|
1368
1388
|
mdl_lsgst_list = checkpoint.mdl_list
|
1369
1389
|
final_objfn = checkpoint.final_objfn
|
1370
|
-
#final_objfn initialized to None in the GateSetTomographyCheckpoint and will be overwritten
|
1371
|
-
#during the loop below unless the last completed iteration is the final iteration
|
1372
|
-
#in which case the loop should be skipped. If so I think it is ok that this gets
|
1373
|
-
#left set to None. There looks to be some logic for handling this and it looks
|
1374
|
-
#like the serialization routines effectively do this already, as the value
|
1375
|
-
#of this is lost between writing and reading.
|
1390
|
+
# final_objfn initialized to None in the GateSetTomographyCheckpoint and will be overwritten
|
1391
|
+
# during the loop below unless the last completed iteration is the final iteration
|
1392
|
+
# in which case the loop should be skipped. If so I think it is ok that this gets
|
1393
|
+
# left set to None. There looks to be some logic for handling this and it looks
|
1394
|
+
# like the serialization routines effectively do this already, as the value
|
1395
|
+
# of this is lost between writing and reading.
|
1376
1396
|
else:
|
1377
|
-
NotImplementedError(
|
1378
|
-
|
1379
|
-
|
1397
|
+
NotImplementedError(
|
1398
|
+
'The only currently valid checkpoint inputs are None and GateSetTomographyCheckpoint.')
|
1399
|
+
|
1400
|
+
# note the last_completed_iter value is initialized to -1 so the below line
|
1380
1401
|
# will have us correctly starting at 0 if this is a fresh checkpoint.
|
1381
1402
|
starting_idx = checkpoint.last_completed_iter + 1
|
1382
1403
|
|
1383
|
-
else:
|
1384
|
-
seed_model = mdl_start.copy()
|
1385
|
-
mdl_lsgst_list = []
|
1386
|
-
starting_idx = 0
|
1387
|
-
|
1388
1404
|
tnxt = _time.time(); profiler.add_time('GST: Prep Initial seed', tref); tref = tnxt
|
1389
1405
|
|
1390
1406
|
#Run Long-sequence GST on data
|
@@ -1404,18 +1420,18 @@ class GateSetTomography(_proto.Protocol):
|
|
1404
1420
|
#then do the final iteration slightly differently since the generator should
|
1405
1421
|
#give three return values.
|
1406
1422
|
if i==len(bulk_circuit_lists)-1:
|
1407
|
-
mdl_iter, opt_iter, final_objfn =
|
1423
|
+
mdl_iter, opt_iter, final_objfn = next(gst_iter_generator)
|
1408
1424
|
else:
|
1409
1425
|
mdl_iter, opt_iter = next(gst_iter_generator)
|
1410
1426
|
mdl_lsgst_list.append(mdl_iter)
|
1411
1427
|
optima_list.append(opt_iter)
|
1412
1428
|
|
1413
1429
|
if not disable_checkpointing:
|
1414
|
-
#update the checkpoint along the way:
|
1430
|
+
# update the checkpoint along the way:
|
1415
1431
|
checkpoint.mdl_list = mdl_lsgst_list
|
1416
1432
|
checkpoint.last_completed_iter += 1
|
1417
1433
|
checkpoint.last_completed_circuit_list = bulk_circuit_lists[i]
|
1418
|
-
#write the updated checkpoint to disk:
|
1434
|
+
# write the updated checkpoint to disk:
|
1419
1435
|
if resource_alloc.comm_rank == 0:
|
1420
1436
|
checkpoint.write(f'{checkpoint_path}_iteration_{i}.json')
|
1421
1437
|
|
@@ -1442,19 +1458,37 @@ class GateSetTomography(_proto.Protocol):
|
|
1442
1458
|
target_model = self.gaugeopt_suite.gaugeopt_target
|
1443
1459
|
elif self.initial_model.target_model is not None:
|
1444
1460
|
target_model = self.initial_model.target_model.copy()
|
1445
|
-
elif self.initial_model.model is not None
|
1461
|
+
elif self.initial_model.model is not None:
|
1446
1462
|
# when we desparately need a target model but none have been specifically given: use initial model
|
1447
1463
|
target_model = self.initial_model.model.copy()
|
1448
1464
|
else:
|
1465
|
+
msg = 'Could not identify a suitable target model, this may result'\
|
1466
|
+
+' in unexpected behavior or missing plots in reports.'
|
1467
|
+
_warnings.warn(msg)
|
1449
1468
|
target_model = None
|
1450
1469
|
|
1470
|
+
if target_model is not None and simulator is not None:
|
1471
|
+
target_model.sim = simulator
|
1472
|
+
|
1451
1473
|
estimate = _Estimate.create_gst_estimate(ret, target_model, mdl_start, mdl_lsgst_list, parameters)
|
1452
1474
|
ret.add_estimate(estimate, estimate_key=self.name)
|
1453
1475
|
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1476
|
+
#Add some better handling for when gauge optimization is turned off (current code path isn't working.)
|
1477
|
+
if not self.gaugeopt_suite.is_empty() or len(self.badfit_options.actions) > 0: # maybe add flag to do this even when empty?
|
1478
|
+
ret = _add_gaugeopt_and_badfit(ret, self.name, target_model,
|
1479
|
+
self.gaugeopt_suite, self.unreliable_ops,
|
1480
|
+
self.badfit_options, self.optimizer,
|
1481
|
+
resource_alloc, printer)
|
1482
|
+
else:
|
1483
|
+
#add a model to the estimate that we'll call the trivial gauge optimized model which
|
1484
|
+
#will be set to be equal to the final iteration estimate.
|
1485
|
+
ret.estimates[self.name].models['trivial_gauge_opt'] = mdl_lsgst_list[-1]
|
1486
|
+
#and add a key for this to the goparameters dict (this is what the report
|
1487
|
+
#generation looks at to determine the names of the gauge optimized models).
|
1488
|
+
#Set the value to None as a placeholder.
|
1489
|
+
ret.estimates[self.name].goparameters['trivial_gauge_opt'] = None
|
1490
|
+
|
1491
|
+
return ret
|
1458
1492
|
|
1459
1493
|
class LinearGateSetTomography(_proto.Protocol):
|
1460
1494
|
"""
|
@@ -1504,6 +1538,10 @@ class LinearGateSetTomography(_proto.Protocol):
|
|
1504
1538
|
self.oplabel_aliases = None
|
1505
1539
|
self.unreliable_ops = ('Gcnot', 'Gcphase', 'Gms', 'Gcn', 'Gcx', 'Gcz')
|
1506
1540
|
|
1541
|
+
self.auxfile_types['target_model'] = 'serialized-object'
|
1542
|
+
self.auxfile_types['gaugeopt_suite'] = 'serialized-object'
|
1543
|
+
self.auxfile_types['badfit_options'] = 'serialized-object'
|
1544
|
+
|
1507
1545
|
def check_if_runnable(self, data):
|
1508
1546
|
"""
|
1509
1547
|
Raises a ValueError if LGST cannot be run on data
|
@@ -1612,9 +1650,22 @@ class LinearGateSetTomography(_proto.Protocol):
|
|
1612
1650
|
'final iteration estimate': mdl_lgst},
|
1613
1651
|
parameters)
|
1614
1652
|
ret.add_estimate(estimate, estimate_key=self.name)
|
1615
|
-
|
1653
|
+
|
1654
|
+
#Add some better handling for when gauge optimization is turned off (current code path isn't working.)
|
1655
|
+
if not self.gaugeopt_suite.is_empty():
|
1656
|
+
ret = _add_gaugeopt_and_badfit(ret, self.name, target_model, self.gaugeopt_suite,
|
1616
1657
|
self.unreliable_ops, self.badfit_options,
|
1617
1658
|
None, resource_alloc, printer)
|
1659
|
+
else:
|
1660
|
+
#add a model to the estimate that we'll call the trivial gauge optimized model which
|
1661
|
+
#will be set to be equal to the final iteration estimate.
|
1662
|
+
ret.estimates[self.name].models['trivial_gauge_opt'] = mdl_lgst
|
1663
|
+
#and add a key for this to the goparameters dict (this is what the report
|
1664
|
+
#generation looks at to determine the names of the gauge optimized models).
|
1665
|
+
#Set the value to None as a placeholder.
|
1666
|
+
ret.estimates[self.name].goparameters['trivial_gauge_opt'] = None
|
1667
|
+
|
1668
|
+
return ret
|
1618
1669
|
|
1619
1670
|
|
1620
1671
|
class StandardGST(_proto.Protocol):
|
@@ -1629,13 +1680,13 @@ class StandardGST(_proto.Protocol):
|
|
1629
1680
|
parameterizations/constraints to apply to the estimated model.
|
1630
1681
|
The default value is usually fine. Allowed values are:
|
1631
1682
|
|
1632
|
-
- "full"
|
1633
|
-
- "TP"
|
1634
|
-
- "
|
1635
|
-
- "H+S"
|
1636
|
-
- "S"
|
1637
|
-
- "Target"
|
1638
|
-
- <model>
|
1683
|
+
- "full" : full (completely unconstrained)
|
1684
|
+
- "TP" : TP-constrained
|
1685
|
+
- "CPTPLND" : Lindbladian CPTP-constrained
|
1686
|
+
- "H+S" : Only Hamiltonian + Stochastic errors allowed (CPTP)
|
1687
|
+
- "S" : Only Stochastic errors allowed (CPTP)
|
1688
|
+
- "Target" : use the target (ideal) gates as the estimate
|
1689
|
+
- <model> : any key in the `models_to_test` argument
|
1639
1690
|
|
1640
1691
|
gaugeopt_suite : GSTGaugeOptSuite, optional
|
1641
1692
|
Specifies which gauge optimizations to perform on each estimate. Can also
|
@@ -1646,6 +1697,14 @@ class StandardGST(_proto.Protocol):
|
|
1646
1697
|
optimization (only), and is useful when you want to gauge optimize toward
|
1647
1698
|
something other than the *ideal* target gates.
|
1648
1699
|
|
1700
|
+
target_model : Model, optional (default None)
|
1701
|
+
If specified use this Model as the target model. Depending on other
|
1702
|
+
specified keyword arguments this model may be used as the target for
|
1703
|
+
the purposes of gauge optimization, report generation/analysis, and
|
1704
|
+
initial seeding for optimization. (For almost all of these it may be the
|
1705
|
+
case that other keyword argument values override this for certain
|
1706
|
+
tasks).
|
1707
|
+
|
1649
1708
|
models_to_test : dict, optional
|
1650
1709
|
A dictionary of Model objects representing (gate-set) models to
|
1651
1710
|
test against the data. These Models are essentially hypotheses for
|
@@ -1694,12 +1753,12 @@ class StandardGST(_proto.Protocol):
|
|
1694
1753
|
self.target_model = target_model
|
1695
1754
|
self.gaugeopt_suite = GSTGaugeOptSuite.cast(gaugeopt_suite)
|
1696
1755
|
self.objfn_builders = GSTObjFnBuilders.cast(objfn_builders) if (objfn_builders is not None) else None
|
1697
|
-
self.optimizer = _opt.
|
1756
|
+
self.optimizer = _opt.SimplerLMOptimizer.cast(optimizer)
|
1698
1757
|
self.badfit_options = GSTBadFitOptions.cast(badfit_options)
|
1699
1758
|
self.verbosity = verbosity
|
1700
1759
|
|
1701
1760
|
if not isinstance(optimizer, _opt.Optimizer) and isinstance(optimizer, dict) \
|
1702
|
-
and 'first_fditer' not in optimizer: # then a dict was cast into
|
1761
|
+
and 'first_fditer' not in optimizer: # then a dict was cast into an Optimizer above.
|
1703
1762
|
# by default, set special "first_fditer=auto" behavior (see logic in GateSetTomography.__init__)
|
1704
1763
|
self.optimizer.first_fditer = None
|
1705
1764
|
|
@@ -1713,12 +1772,8 @@ class StandardGST(_proto.Protocol):
|
|
1713
1772
|
#Advanced options that could be changed by users who know what they're doing
|
1714
1773
|
self.starting_point = {} # a dict whose keys are modes
|
1715
1774
|
|
1716
|
-
|
1717
|
-
|
1718
|
-
# data = _proto.ProtocolData(design, dataset)
|
1719
|
-
# return self.run(data)
|
1720
|
-
|
1721
|
-
def run(self, data, memlimit=None, comm=None, checkpoint= None, checkpoint_path=None, disable_checkpointing = False):
|
1775
|
+
def run(self, data, memlimit=None, comm=None, checkpoint=None, checkpoint_path=None,
|
1776
|
+
disable_checkpointing=False, simulator: Optional[ForwardSimulator.Castable]=None):
|
1722
1777
|
"""
|
1723
1778
|
Run this protocol on `data`.
|
1724
1779
|
|
@@ -1751,6 +1806,11 @@ class StandardGST(_proto.Protocol):
|
|
1751
1806
|
to disk during the course of this protocol. It is strongly recommended
|
1752
1807
|
that this be kept set to False without good reason to disable the checkpoints.
|
1753
1808
|
|
1809
|
+
simulator : ForwardSimulator.Castable or None
|
1810
|
+
Ignored if None. If not None, then we call
|
1811
|
+
fwdsim = ForwardSimulator.cast(simulator),
|
1812
|
+
and we set the .sim attribute of every Model we encounter to fwdsim.
|
1813
|
+
|
1754
1814
|
Returns
|
1755
1815
|
-------
|
1756
1816
|
ProtocolResults
|
@@ -1780,6 +1840,10 @@ class StandardGST(_proto.Protocol):
|
|
1780
1840
|
else:
|
1781
1841
|
target_model = None # Usually this path leads to an error being raised below.
|
1782
1842
|
|
1843
|
+
if target_model is not None:
|
1844
|
+
if simulator is not None:
|
1845
|
+
target_model.sim = simulator
|
1846
|
+
|
1783
1847
|
if not disable_checkpointing:
|
1784
1848
|
#Set the checkpoint_path variable if None
|
1785
1849
|
if checkpoint_path is None:
|
@@ -1813,8 +1877,12 @@ class StandardGST(_proto.Protocol):
|
|
1813
1877
|
with printer.progress_logging(1):
|
1814
1878
|
for i, mode in enumerate(modes):
|
1815
1879
|
printer.show_progress(i, len(modes), prefix='-- Std Practice: ', suffix=' (%s) --' % mode)
|
1816
|
-
if
|
1817
|
-
|
1880
|
+
if disable_checkpointing:
|
1881
|
+
checkpoint_path = None
|
1882
|
+
child_checkpoint = None
|
1883
|
+
else:
|
1884
|
+
child_checkpoint = checkpoint.children[mode]
|
1885
|
+
#The line below is for compatibility with Python 3.8 and lower.
|
1818
1886
|
checkpoint_path = checkpoint_path_base.with_name(f"{checkpoint_path_base.stem}_{mode.replace(' ', '_')}")
|
1819
1887
|
#The line below only works for python 3.9+
|
1820
1888
|
#checkpoint_path = checkpoint_path_base.with_stem(f"{checkpoint_path_base.stem}_{mode.replace(' ', '_')}")
|
@@ -1825,21 +1893,22 @@ class StandardGST(_proto.Protocol):
|
|
1825
1893
|
|
1826
1894
|
mdltest = _ModelTest(target_model, target_model, self.gaugeopt_suite,
|
1827
1895
|
mt_builder, self.badfit_options, verbosity=printer - 1, name=mode)
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
result = mdltest.run(data, memlimit, comm, disable_checkpointing=True)
|
1896
|
+
result = mdltest.run(data, memlimit, comm,
|
1897
|
+
disable_checkpointing=disable_checkpointing,
|
1898
|
+
checkpoint=child_checkpoint,
|
1899
|
+
checkpoint_path=checkpoint_path)
|
1833
1900
|
ret.add_estimates(result)
|
1834
1901
|
|
1835
1902
|
elif mode in models_to_test:
|
1836
|
-
|
1903
|
+
mdl = models_to_test[mode]
|
1904
|
+
if simulator is not None:
|
1905
|
+
mdl.sim = simulator
|
1906
|
+
mdltest = _ModelTest(mdl, target_model, self.gaugeopt_suite,
|
1837
1907
|
None, self.badfit_options, verbosity=printer - 1, name=mode)
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
result = mdltest.run(data, memlimit, comm, disable_checkpointing=True)
|
1908
|
+
result = mdltest.run(data, memlimit, comm,
|
1909
|
+
disable_checkpointing=disable_checkpointing,
|
1910
|
+
checkpoint=child_checkpoint,
|
1911
|
+
checkpoint_path=checkpoint_path)
|
1843
1912
|
ret.add_estimates(result)
|
1844
1913
|
|
1845
1914
|
else:
|
@@ -1849,7 +1918,7 @@ class StandardGST(_proto.Protocol):
|
|
1849
1918
|
|
1850
1919
|
#Try to interpret `mode` as a parameterization
|
1851
1920
|
parameterization = mode # for now, 1-1 correspondence
|
1852
|
-
initial_model = target_model
|
1921
|
+
initial_model = target_model.copy()
|
1853
1922
|
|
1854
1923
|
try:
|
1855
1924
|
initial_model.set_all_parameterizations(parameterization)
|
@@ -1858,13 +1927,14 @@ class StandardGST(_proto.Protocol):
|
|
1858
1927
|
% (mode, str(e)))
|
1859
1928
|
|
1860
1929
|
initial_model = GSTInitialModel(initial_model, self.starting_point.get(mode, None))
|
1930
|
+
if simulator is not None:
|
1931
|
+
initial_model.sim = simulator
|
1861
1932
|
gst = GST(initial_model, self.gaugeopt_suite, self.objfn_builders,
|
1862
1933
|
self.optimizer, self.badfit_options, verbosity=printer - 1, name=mode)
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
result = gst.run(data, memlimit, comm, disable_checkpointing=True)
|
1934
|
+
result = gst.run(data, memlimit, comm,
|
1935
|
+
disable_checkpointing=disable_checkpointing,
|
1936
|
+
checkpoint=child_checkpoint,
|
1937
|
+
checkpoint_path=checkpoint_path)
|
1868
1938
|
ret.add_estimates(result)
|
1869
1939
|
|
1870
1940
|
return ret
|
@@ -1945,7 +2015,7 @@ def _add_gaugeopt_and_badfit(results, estlbl, target_model, gaugeopt_suite,
|
|
1945
2015
|
profiler = resource_alloc.profiler
|
1946
2016
|
|
1947
2017
|
#Do final gauge optimization to *final* iteration result only
|
1948
|
-
if gaugeopt_suite:
|
2018
|
+
if gaugeopt_suite is not None and not gaugeopt_suite.is_empty():
|
1949
2019
|
model_to_gaugeopt = results.estimates[estlbl].models['final iteration estimate']
|
1950
2020
|
if gaugeopt_suite.gaugeopt_target is None: # add a default target model to gauge opt if needed
|
1951
2021
|
#TODO: maybe make these two lines into a method of GSTGaugeOptSuite for adding a target model?
|
@@ -1954,7 +2024,7 @@ def _add_gaugeopt_and_badfit(results, estlbl, target_model, gaugeopt_suite,
|
|
1954
2024
|
_add_gauge_opt(results, estlbl, gaugeopt_suite,
|
1955
2025
|
model_to_gaugeopt, unreliable_ops, comm, printer - 1)
|
1956
2026
|
profiler.add_time('%s: gauge optimization' % estlbl, tref); tref = _time.time()
|
1957
|
-
|
2027
|
+
|
1958
2028
|
_add_badfit_estimates(results, estlbl, badfit_options, optimizer, resource_alloc, printer, gaugeopt_suite= gaugeopt_suite)
|
1959
2029
|
profiler.add_time('%s: add badfit estimates' % estlbl, tref); tref = _time.time()
|
1960
2030
|
else:
|
@@ -2023,26 +2093,31 @@ def _add_gauge_opt(results, base_est_label, gaugeopt_suite, starting_model,
|
|
2023
2093
|
|
2024
2094
|
printer.log("-- Performing '%s' gauge optimization on %s estimate --" % (go_label, base_est_label), 2)
|
2025
2095
|
|
2026
|
-
#
|
2027
|
-
|
2096
|
+
#add logic for the case where no gauge optimization is performed.
|
2097
|
+
if go_label == 'none':
|
2098
|
+
results.estimates[base_est_label].add_gaugeoptimized(goparams, starting_model, go_label, comm, printer - 3)
|
2099
|
+
else:
|
2100
|
+
results.estimates[base_est_label].add_gaugeoptimized(goparams, None, go_label, comm, printer - 3)
|
2101
|
+
|
2102
|
+
#Get starting model for next stage
|
2028
2103
|
mdl_start = results.estimates[base_est_label].retrieve_start_model(goparams)
|
2029
|
-
|
2030
|
-
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2104
|
+
if mdl_start is not None:
|
2105
|
+
#Gauge optimize data-scaled estimate also
|
2106
|
+
for suffix in ROBUST_SUFFIX_LIST:
|
2107
|
+
robust_est_label = base_est_label + suffix
|
2108
|
+
if robust_est_label in results.estimates:
|
2109
|
+
mdl_start_robust = results.estimates[robust_est_label].retrieve_start_model(goparams)
|
2110
|
+
|
2111
|
+
if mdl_start_robust.frobeniusdist(mdl_start) < 1e-8:
|
2112
|
+
printer.log("-- Conveying '%s' gauge optimization from %s to %s estimate --" %
|
2113
|
+
(go_label, base_est_label, robust_est_label), 2)
|
2114
|
+
params = results.estimates[base_est_label].goparameters[go_label] # no need to copy here
|
2115
|
+
gsopt = results.estimates[base_est_label].models[go_label].copy()
|
2116
|
+
results.estimates[robust_est_label].add_gaugeoptimized(params, gsopt, go_label, comm, printer - 3)
|
2117
|
+
else:
|
2118
|
+
printer.log("-- Performing '%s' gauge optimization on %s estimate --" %
|
2119
|
+
(go_label, robust_est_label), 2)
|
2120
|
+
results.estimates[robust_est_label].add_gaugeoptimized(goparams, None, go_label, comm, printer - 3)
|
2046
2121
|
|
2047
2122
|
|
2048
2123
|
def _add_badfit_estimates(results, base_estimate_label, badfit_options,
|
@@ -2285,9 +2360,16 @@ def _compute_wildcard_budget_1d_model(estimate, objfn_cache, mdc_objfn, paramete
|
|
2285
2360
|
if gaugeopt_suite is None or gaugeopt_suite.gaugeopt_suite_names is None:
|
2286
2361
|
gaugeopt_labels = None
|
2287
2362
|
primitive_ops = list(ref.keys())
|
2363
|
+
if sum([v**2 for v in ref.values()]) < 1e-4:
|
2364
|
+
_warnings.warn("Reference values for 1D wildcard budget are all near-zero!"
|
2365
|
+
"This usually indicates an incorrect target model and will likely cause problems computing alpha.")
|
2366
|
+
|
2288
2367
|
else:
|
2289
2368
|
gaugeopt_labels = gaugeopt_suite.gaugeopt_suite_names
|
2290
2369
|
primitive_ops = list(ref[list(gaugeopt_labels)[0]].keys())
|
2370
|
+
if sum([v**2 for v in ref[list(gaugeopt_labels)[0]].values()]) < 1e-4:
|
2371
|
+
_warnings.warn("Reference values for 1D wildcard budget are all near-zero!"
|
2372
|
+
"This usually indicates an incorrect target model and will likely cause problems computing alpha.")
|
2291
2373
|
|
2292
2374
|
if gaugeopt_labels is None:
|
2293
2375
|
wcm = _wild.PrimitiveOpsSingleScaleWildcardBudget(primitive_ops, [ref[k] for k in primitive_ops],
|
@@ -2312,21 +2394,38 @@ def _compute_1d_reference_values_and_name(estimate, badfit_options, gaugeopt_sui
|
|
2312
2394
|
if gaugeopt_suite is None or gaugeopt_suite.gaugeopt_suite_names is None:
|
2313
2395
|
final_model = estimate.models['final iteration estimate']
|
2314
2396
|
target_model = estimate.models['target']
|
2315
|
-
|
2397
|
+
|
2398
|
+
if isinstance(final_model, _ExplicitOpModel):
|
2399
|
+
gaugeopt_model = _alg.gaugeopt_to_target(final_model, target_model)
|
2400
|
+
operations_dict = gaugeopt_model.operations
|
2401
|
+
targetops_dict = target_model.operations
|
2402
|
+
preps_dict = gaugeopt_model.preps
|
2403
|
+
targetpreps_dict = target_model.preps
|
2404
|
+
povmops_dict = gaugeopt_model.povms
|
2405
|
+
else:
|
2406
|
+
# Local/cloud noise models don't have default_gauge_group attribute and can't be gauge
|
2407
|
+
# optimized - at least not easily.
|
2408
|
+
gaugeopt_model = final_model
|
2409
|
+
operations_dict = gaugeopt_model.operation_blks['gates']
|
2410
|
+
targetops_dict = target_model.operation_blks['gates']
|
2411
|
+
preps_dict = gaugeopt_model.prep_blks['layers']
|
2412
|
+
targetpreps_dict = target_model.prep_blks['layers']
|
2413
|
+
povmops_dict = {} # HACK - need to rewrite povm_diamonddist below to work
|
2414
|
+
|
2316
2415
|
dd = {}
|
2317
|
-
for key, op in
|
2318
|
-
dd[key] = 0.5 * _tools.diamonddist(op.to_dense(),
|
2416
|
+
for key, op in operations_dict.items():
|
2417
|
+
dd[key] = 0.5 * _tools.diamonddist(op.to_dense(), targetops_dict[key].to_dense())
|
2319
2418
|
if dd[key] < 0: # indicates that diamonddist failed (cvxpy failure)
|
2320
2419
|
_warnings.warn(("Diamond distance failed to compute %s reference value for 1D wildcard budget!"
|
2321
2420
|
" Falling back to trace distance.") % str(key))
|
2322
|
-
dd[key] = _tools.jtracedist(op.to_dense(),
|
2421
|
+
dd[key] = _tools.jtracedist(op.to_dense(), targetops_dict[key].to_dense())
|
2323
2422
|
|
2324
2423
|
spamdd = {}
|
2325
|
-
for key, op in
|
2424
|
+
for key, op in preps_dict.items():
|
2326
2425
|
spamdd[key] = _tools.tracedist(_tools.vec_to_stdmx(op.to_dense(), 'pp'),
|
2327
|
-
_tools.vec_to_stdmx(
|
2426
|
+
_tools.vec_to_stdmx(targetpreps_dict[key].to_dense(), 'pp'))
|
2328
2427
|
|
2329
|
-
for key in
|
2428
|
+
for key in povmops_dict.keys():
|
2330
2429
|
spamdd[key] = 0.5 * _tools.optools.povm_diamonddist(gaugeopt_model, target_model, key)
|
2331
2430
|
|
2332
2431
|
dd['SPAM'] = sum(spamdd.values())
|
@@ -2573,23 +2672,14 @@ def _compute_wildcard_budget(objfn_cache, mdc_objfn, parameters, badfit_options,
|
|
2573
2672
|
elif method_name == "barrier":
|
2574
2673
|
_opt.optimize_wildcard_budget_barrier(budget, L1weights, mdc_objfn, two_dlogl_threshold,
|
2575
2674
|
redbox_threshold, printer, **method_options)
|
2576
|
-
elif method_name == "cvxopt":
|
2577
|
-
_opt.optimize_wildcard_budget_cvxopt(budget, L1weights, mdc_objfn, two_dlogl_threshold,
|
2578
|
-
redbox_threshold, printer, **method_options)
|
2579
|
-
elif method_name == "cvxopt_smoothed":
|
2580
|
-
_opt.optimize_wildcard_budget_cvxopt_smoothed(budget, L1weights, mdc_objfn,
|
2581
|
-
two_dlogl_threshold, redbox_threshold,
|
2582
|
-
printer, **method_options)
|
2583
|
-
elif method_name == "cvxopt_small":
|
2584
|
-
_opt.optimize_wildcard_budget_cvxopt_zeroreg(budget, L1weights, mdc_objfn,
|
2585
|
-
two_dlogl_threshold, redbox_threshold, printer,
|
2586
|
-
**method_options)
|
2587
2675
|
elif method_name == "cvxpy_noagg":
|
2588
2676
|
_opt.optimize_wildcard_budget_percircuit_only_cvxpy(budget, L1weights, mdc_objfn,
|
2589
2677
|
redbox_threshold, printer,
|
2590
2678
|
**method_options)
|
2591
2679
|
elif method_name == "none":
|
2592
2680
|
pass
|
2681
|
+
elif method_name in ("cvxopt", "cvxopt_smoothed", "cvxopt_small"):
|
2682
|
+
raise ValueError(f"Support for {method_name} was removed in pyGSTi release 0.9.13.")
|
2593
2683
|
else:
|
2594
2684
|
raise ValueError("Invalid wildcard method name: %s" % method_name)
|
2595
2685
|
|
@@ -2983,7 +3073,8 @@ class ModelEstimateResults(_proto.ProtocolResults):
|
|
2983
3073
|
self.estimates[estimate_key] = estimate
|
2984
3074
|
|
2985
3075
|
def add_model_test(self, target_model, themodel,
|
2986
|
-
estimate_key='test', gaugeopt_keys="auto", verbosity=2
|
3076
|
+
estimate_key='test', gaugeopt_keys="auto", verbosity=2,
|
3077
|
+
simulator: Optional[ForwardSimulator.Castable]=None):
|
2987
3078
|
"""
|
2988
3079
|
Add a new model-test (i.e. non-optimized) estimate to this `Results` object.
|
2989
3080
|
|
@@ -3010,6 +3101,11 @@ class ModelEstimateResults(_proto.ProtocolResults):
|
|
3010
3101
|
verbosity : int, optional
|
3011
3102
|
Level of detail printed to stdout.
|
3012
3103
|
|
3104
|
+
simulator : ForwardSimulator.Castable or None
|
3105
|
+
Ignored if None. If not None, then we call
|
3106
|
+
fwdsim = ForwardSimulator.cast(simulator),
|
3107
|
+
and we set the .sim attribute of every Model we encounter to fwdsim.
|
3108
|
+
|
3013
3109
|
Returns
|
3014
3110
|
-------
|
3015
3111
|
None
|
@@ -3030,7 +3126,7 @@ class ModelEstimateResults(_proto.ProtocolResults):
|
|
3030
3126
|
from .modeltest import ModelTest as _ModelTest
|
3031
3127
|
mdltest = _ModelTest(themodel, target_model, gaugeopt_suite,
|
3032
3128
|
objfn_builder, badfit_options, name=estimate_key, verbosity=verbosity)
|
3033
|
-
test_result = mdltest.run(self.data)
|
3129
|
+
test_result = mdltest.run(self.data, simulator=simulator)
|
3034
3130
|
self.add_estimates(test_result)
|
3035
3131
|
|
3036
3132
|
def view(self, estimate_keys, gaugeopt_keys=None):
|