pyGSTi 0.9.12.1__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.
Files changed (221) hide show
  1. pyGSTi-0.9.13.dist-info/METADATA +185 -0
  2. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +207 -217
  3. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/WHEEL +1 -1
  4. pygsti/_version.py +2 -2
  5. pygsti/algorithms/contract.py +1 -1
  6. pygsti/algorithms/core.py +42 -28
  7. pygsti/algorithms/fiducialselection.py +17 -8
  8. pygsti/algorithms/gaugeopt.py +2 -2
  9. pygsti/algorithms/germselection.py +87 -77
  10. pygsti/algorithms/mirroring.py +0 -388
  11. pygsti/algorithms/randomcircuit.py +165 -1333
  12. pygsti/algorithms/rbfit.py +0 -234
  13. pygsti/baseobjs/basis.py +94 -396
  14. pygsti/baseobjs/errorgenbasis.py +0 -132
  15. pygsti/baseobjs/errorgenspace.py +0 -10
  16. pygsti/baseobjs/label.py +52 -168
  17. pygsti/baseobjs/opcalc/fastopcalc.cp38-win_amd64.pyd +0 -0
  18. pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
  19. pygsti/baseobjs/polynomial.py +13 -595
  20. pygsti/baseobjs/statespace.py +1 -0
  21. pygsti/circuits/__init__.py +1 -1
  22. pygsti/circuits/circuit.py +682 -505
  23. pygsti/circuits/circuitconstruction.py +0 -4
  24. pygsti/circuits/circuitlist.py +47 -5
  25. pygsti/circuits/circuitparser/__init__.py +8 -8
  26. pygsti/circuits/circuitparser/fastcircuitparser.cp38-win_amd64.pyd +0 -0
  27. pygsti/circuits/circuitstructure.py +3 -3
  28. pygsti/circuits/cloudcircuitconstruction.py +1 -1
  29. pygsti/data/datacomparator.py +2 -7
  30. pygsti/data/dataset.py +46 -44
  31. pygsti/data/hypothesistest.py +0 -7
  32. pygsti/drivers/bootstrap.py +0 -49
  33. pygsti/drivers/longsequence.py +2 -1
  34. pygsti/evotypes/basereps_cython.cp38-win_amd64.pyd +0 -0
  35. pygsti/evotypes/chp/opreps.py +0 -61
  36. pygsti/evotypes/chp/statereps.py +0 -32
  37. pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
  38. pygsti/evotypes/densitymx/effectreps.cp38-win_amd64.pyd +0 -0
  39. pygsti/evotypes/densitymx/effectreps.pyx +1 -1
  40. pygsti/evotypes/densitymx/opreps.cp38-win_amd64.pyd +0 -0
  41. pygsti/evotypes/densitymx/opreps.pyx +2 -2
  42. pygsti/evotypes/densitymx/statereps.cp38-win_amd64.pyd +0 -0
  43. pygsti/evotypes/densitymx/statereps.pyx +1 -1
  44. pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
  45. pygsti/evotypes/densitymx_slow/opreps.py +16 -23
  46. pygsti/evotypes/densitymx_slow/statereps.py +10 -3
  47. pygsti/evotypes/evotype.py +39 -2
  48. pygsti/evotypes/stabilizer/effectreps.cp38-win_amd64.pyd +0 -0
  49. pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
  50. pygsti/evotypes/stabilizer/opreps.cp38-win_amd64.pyd +0 -0
  51. pygsti/evotypes/stabilizer/opreps.pyx +0 -4
  52. pygsti/evotypes/stabilizer/statereps.cp38-win_amd64.pyd +0 -0
  53. pygsti/evotypes/stabilizer/statereps.pyx +1 -5
  54. pygsti/evotypes/stabilizer/termreps.cp38-win_amd64.pyd +0 -0
  55. pygsti/evotypes/stabilizer/termreps.pyx +0 -7
  56. pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
  57. pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
  58. pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
  59. pygsti/evotypes/statevec/effectreps.cp38-win_amd64.pyd +0 -0
  60. pygsti/evotypes/statevec/effectreps.pyx +1 -1
  61. pygsti/evotypes/statevec/opreps.cp38-win_amd64.pyd +0 -0
  62. pygsti/evotypes/statevec/opreps.pyx +2 -2
  63. pygsti/evotypes/statevec/statereps.cp38-win_amd64.pyd +0 -0
  64. pygsti/evotypes/statevec/statereps.pyx +1 -1
  65. pygsti/evotypes/statevec/termreps.cp38-win_amd64.pyd +0 -0
  66. pygsti/evotypes/statevec/termreps.pyx +0 -7
  67. pygsti/evotypes/statevec_slow/effectreps.py +0 -3
  68. pygsti/evotypes/statevec_slow/opreps.py +0 -5
  69. pygsti/extras/__init__.py +0 -1
  70. pygsti/extras/drift/stabilityanalyzer.py +3 -1
  71. pygsti/extras/interpygate/__init__.py +12 -0
  72. pygsti/extras/interpygate/core.py +0 -36
  73. pygsti/extras/interpygate/process_tomography.py +44 -10
  74. pygsti/extras/rpe/rpeconstruction.py +0 -2
  75. pygsti/forwardsims/__init__.py +1 -0
  76. pygsti/forwardsims/forwardsim.py +14 -55
  77. pygsti/forwardsims/mapforwardsim.py +69 -18
  78. pygsti/forwardsims/mapforwardsim_calc_densitymx.cp38-win_amd64.pyd +0 -0
  79. pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
  80. pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
  81. pygsti/forwardsims/matrixforwardsim.py +63 -15
  82. pygsti/forwardsims/termforwardsim.py +8 -110
  83. pygsti/forwardsims/termforwardsim_calc_stabilizer.cp38-win_amd64.pyd +0 -0
  84. pygsti/forwardsims/termforwardsim_calc_statevec.cp38-win_amd64.pyd +0 -0
  85. pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
  86. pygsti/forwardsims/torchfwdsim.py +265 -0
  87. pygsti/forwardsims/weakforwardsim.py +2 -2
  88. pygsti/io/__init__.py +1 -2
  89. pygsti/io/mongodb.py +0 -2
  90. pygsti/io/stdinput.py +6 -22
  91. pygsti/layouts/copalayout.py +10 -12
  92. pygsti/layouts/distlayout.py +0 -40
  93. pygsti/layouts/maplayout.py +103 -25
  94. pygsti/layouts/matrixlayout.py +99 -60
  95. pygsti/layouts/prefixtable.py +1534 -52
  96. pygsti/layouts/termlayout.py +1 -1
  97. pygsti/modelmembers/instruments/instrument.py +3 -3
  98. pygsti/modelmembers/instruments/tpinstrument.py +2 -2
  99. pygsti/modelmembers/modelmember.py +0 -17
  100. pygsti/modelmembers/operations/__init__.py +2 -4
  101. pygsti/modelmembers/operations/affineshiftop.py +1 -0
  102. pygsti/modelmembers/operations/composederrorgen.py +1 -1
  103. pygsti/modelmembers/operations/composedop.py +1 -24
  104. pygsti/modelmembers/operations/denseop.py +5 -5
  105. pygsti/modelmembers/operations/eigpdenseop.py +2 -2
  106. pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
  107. pygsti/modelmembers/operations/embeddedop.py +0 -1
  108. pygsti/modelmembers/operations/experrorgenop.py +2 -2
  109. pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
  110. pygsti/modelmembers/operations/fullcptpop.py +2 -2
  111. pygsti/modelmembers/operations/fulltpop.py +28 -6
  112. pygsti/modelmembers/operations/fullunitaryop.py +5 -4
  113. pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
  114. pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
  115. pygsti/modelmembers/operations/linearop.py +7 -27
  116. pygsti/modelmembers/operations/opfactory.py +1 -1
  117. pygsti/modelmembers/operations/repeatedop.py +1 -24
  118. pygsti/modelmembers/operations/staticstdop.py +1 -1
  119. pygsti/modelmembers/povms/__init__.py +3 -3
  120. pygsti/modelmembers/povms/basepovm.py +7 -36
  121. pygsti/modelmembers/povms/complementeffect.py +4 -9
  122. pygsti/modelmembers/povms/composedeffect.py +0 -320
  123. pygsti/modelmembers/povms/computationaleffect.py +1 -1
  124. pygsti/modelmembers/povms/computationalpovm.py +3 -1
  125. pygsti/modelmembers/povms/effect.py +3 -5
  126. pygsti/modelmembers/povms/marginalizedpovm.py +0 -79
  127. pygsti/modelmembers/povms/tppovm.py +74 -2
  128. pygsti/modelmembers/states/__init__.py +2 -5
  129. pygsti/modelmembers/states/composedstate.py +0 -317
  130. pygsti/modelmembers/states/computationalstate.py +3 -3
  131. pygsti/modelmembers/states/cptpstate.py +4 -4
  132. pygsti/modelmembers/states/densestate.py +6 -4
  133. pygsti/modelmembers/states/fullpurestate.py +0 -24
  134. pygsti/modelmembers/states/purestate.py +1 -1
  135. pygsti/modelmembers/states/state.py +5 -6
  136. pygsti/modelmembers/states/tpstate.py +28 -10
  137. pygsti/modelmembers/term.py +3 -6
  138. pygsti/modelmembers/torchable.py +50 -0
  139. pygsti/modelpacks/_modelpack.py +1 -1
  140. pygsti/modelpacks/smq1Q_ZN.py +3 -1
  141. pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
  142. pygsti/modelpacks/smq2Q_XY.py +3 -3
  143. pygsti/modelpacks/smq2Q_XYI.py +2 -2
  144. pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
  145. pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
  146. pygsti/modelpacks/smq2Q_XYXX.py +1 -1
  147. pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
  148. pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
  149. pygsti/modelpacks/stdtarget.py +0 -121
  150. pygsti/models/cloudnoisemodel.py +1 -2
  151. pygsti/models/explicitcalc.py +3 -3
  152. pygsti/models/explicitmodel.py +3 -13
  153. pygsti/models/fogistore.py +5 -3
  154. pygsti/models/localnoisemodel.py +1 -2
  155. pygsti/models/memberdict.py +0 -12
  156. pygsti/models/model.py +800 -65
  157. pygsti/models/modelconstruction.py +4 -4
  158. pygsti/models/modelnoise.py +2 -2
  159. pygsti/models/modelparaminterposer.py +1 -1
  160. pygsti/models/oplessmodel.py +1 -1
  161. pygsti/models/qutrit.py +15 -14
  162. pygsti/objectivefns/objectivefns.py +73 -138
  163. pygsti/objectivefns/wildcardbudget.py +2 -7
  164. pygsti/optimize/__init__.py +1 -0
  165. pygsti/optimize/arraysinterface.py +28 -0
  166. pygsti/optimize/customcg.py +0 -12
  167. pygsti/optimize/customlm.py +129 -323
  168. pygsti/optimize/customsolve.py +2 -2
  169. pygsti/optimize/optimize.py +0 -84
  170. pygsti/optimize/simplerlm.py +841 -0
  171. pygsti/optimize/wildcardopt.py +19 -598
  172. pygsti/protocols/confidenceregionfactory.py +28 -14
  173. pygsti/protocols/estimate.py +31 -14
  174. pygsti/protocols/gst.py +142 -68
  175. pygsti/protocols/modeltest.py +6 -10
  176. pygsti/protocols/protocol.py +9 -37
  177. pygsti/protocols/rb.py +450 -79
  178. pygsti/protocols/treenode.py +8 -2
  179. pygsti/protocols/vb.py +108 -206
  180. pygsti/protocols/vbdataframe.py +1 -1
  181. pygsti/report/factory.py +0 -15
  182. pygsti/report/fogidiagram.py +1 -17
  183. pygsti/report/modelfunction.py +12 -3
  184. pygsti/report/mpl_colormaps.py +1 -1
  185. pygsti/report/plothelpers.py +8 -2
  186. pygsti/report/reportables.py +41 -37
  187. pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
  188. pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
  189. pygsti/report/workspace.py +2 -14
  190. pygsti/report/workspaceplots.py +326 -504
  191. pygsti/tools/basistools.py +9 -36
  192. pygsti/tools/edesigntools.py +124 -96
  193. pygsti/tools/fastcalc.cp38-win_amd64.pyd +0 -0
  194. pygsti/tools/fastcalc.pyx +35 -81
  195. pygsti/tools/internalgates.py +151 -15
  196. pygsti/tools/jamiolkowski.py +5 -5
  197. pygsti/tools/lindbladtools.py +19 -11
  198. pygsti/tools/listtools.py +0 -114
  199. pygsti/tools/matrixmod2.py +1 -1
  200. pygsti/tools/matrixtools.py +173 -339
  201. pygsti/tools/nameddict.py +1 -1
  202. pygsti/tools/optools.py +154 -88
  203. pygsti/tools/pdftools.py +0 -25
  204. pygsti/tools/rbtheory.py +3 -320
  205. pygsti/tools/slicetools.py +64 -12
  206. pyGSTi-0.9.12.1.dist-info/METADATA +0 -155
  207. pygsti/algorithms/directx.py +0 -711
  208. pygsti/evotypes/qibo/__init__.py +0 -33
  209. pygsti/evotypes/qibo/effectreps.py +0 -78
  210. pygsti/evotypes/qibo/opreps.py +0 -376
  211. pygsti/evotypes/qibo/povmreps.py +0 -98
  212. pygsti/evotypes/qibo/statereps.py +0 -174
  213. pygsti/extras/rb/__init__.py +0 -13
  214. pygsti/extras/rb/benchmarker.py +0 -957
  215. pygsti/extras/rb/dataset.py +0 -378
  216. pygsti/extras/rb/io.py +0 -814
  217. pygsti/extras/rb/simulate.py +0 -1020
  218. pygsti/io/legacyio.py +0 -385
  219. pygsti/modelmembers/povms/denseeffect.py +0 -142
  220. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
  221. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
@@ -27,6 +27,7 @@ from pygsti.circuits.circuitlist import CircuitList as _CircuitList
27
27
  from pygsti.objectivefns.objectivefns import PoissonPicDeltaLogLFunction as _PoissonPicDeltaLogLFunction
28
28
  from pygsti.objectivefns.objectivefns import Chi2Function as _Chi2Function
29
29
  from pygsti.objectivefns.objectivefns import FreqWeightedChi2Function as _FreqWeightedChi2Function
30
+ from pygsti.models.explicitmodel import ExplicitOpModel as _ExplicitOpModel
30
31
 
31
32
 
32
33
  # NON-MARKOVIAN ERROR BARS
@@ -482,9 +483,15 @@ class ConfidenceRegionFactory(_NicelySerializable):
482
483
  label = projection_type
483
484
 
484
485
  model = self.parent.models[self.model_lbl]
485
- nongauge_space, gauge_space = model.compute_nongauge_and_gauge_spaces()
486
- self.nNonGaugeParams = nongauge_space.shape[1]
487
- self.nGaugeParams = model.num_params - self.nNonGaugeParams
486
+
487
+ if projection_type != 'none':
488
+ nongauge_space, gauge_space = model.compute_nongauge_and_gauge_spaces()
489
+ self.nNonGaugeParams = nongauge_space.shape[1]
490
+ self.nGaugeParams = model.num_params - self.nNonGaugeParams
491
+ else:
492
+ # no projection means we take the entire space as non-gauge
493
+ self.nNonGaugeParams = model.num_params
494
+ self.nGaugeParams = 0
488
495
 
489
496
  #Project Hessian onto non-gauge space
490
497
  if projection_type == 'none':
@@ -691,13 +698,13 @@ class ConfidenceRegionFactory(_NicelySerializable):
691
698
  sub_crf.project_hessian('none')
692
699
  crfv = sub_crf.view(level)
693
700
 
694
- operationCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(gl).flatten()
701
+ operationCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(gl).ravel()
695
702
  for gl in model.operations])
696
703
  return _np.sqrt(_np.sum(operationCIs**2))
697
704
 
698
705
  #Run Minimization Algorithm
699
706
  startM = _np.zeros((self.nNonGaugeParams, self.nGaugeParams), 'd')
700
- x0 = startM.flatten()
707
+ x0 = startM.ravel()
701
708
  print_obj_func = _opt.create_objfn_printer(_objective_func)
702
709
  minSol = _opt.minimize(_objective_func, x0,
703
710
  method=method, maxiter=maxiter,
@@ -727,7 +734,7 @@ class ConfidenceRegionFactory(_NicelySerializable):
727
734
  self.circuit_list_lbl, projected_hessian, 0.0)
728
735
  sub_crf.project_hessian('none')
729
736
  crfv = sub_crf.view(level)
730
- operationCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(gl).flatten()
737
+ operationCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(gl).ravel()
731
738
  for gl in model.operations])
732
739
  op_intrinsic_err = _np.sqrt(_np.mean(operationCIs**2))
733
740
 
@@ -738,7 +745,7 @@ class ConfidenceRegionFactory(_NicelySerializable):
738
745
  self.circuit_list_lbl, projected_hessian, 0.0)
739
746
  sub_crf.project_hessian('none')
740
747
  crfv = sub_crf.view(level)
741
- spamCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(sl).flatten()
748
+ spamCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(sl).ravel()
742
749
  for sl in _itertools.chain(iter(model.preps),
743
750
  iter(model.povms))])
744
751
  spam_intrinsic_err = _np.sqrt(_np.mean(spamCIs**2))
@@ -755,9 +762,9 @@ class ConfidenceRegionFactory(_NicelySerializable):
755
762
  sub_crf.project_hessian('none')
756
763
  crfv = sub_crf.view(level)
757
764
 
758
- operationCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(gl).flatten()
765
+ operationCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(gl).ravel()
759
766
  for gl in model.operations])
760
- spamCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(sl).flatten()
767
+ spamCIs = _np.concatenate([crfv.retrieve_profile_likelihood_confidence_intervals(sl).ravel()
761
768
  for sl in _itertools.chain(iter(model.preps),
762
769
  iter(model.povms))])
763
770
  op_err = _np.sqrt(_np.mean(operationCIs**2))
@@ -1068,11 +1075,18 @@ class ConfidenceRegionFactoryView(object):
1068
1075
  else:
1069
1076
  # copy objects because we add eps to them below
1070
1077
  typ, lbl = dependency
1071
- if typ == "gate": modelObj = mdl.operations[lbl]
1072
- elif typ == "prep": modelObj = mdl.preps[lbl]
1073
- elif typ == "povm": modelObj = mdl.povms[lbl]
1074
- elif typ == "instrument": modelObj = mdl.instruments[lbl]
1075
- else: raise ValueError("Invalid dependency type: %s" % typ)
1078
+ if isinstance(mdl, _ExplicitOpModel):
1079
+ if typ == "gate": modelObj = mdl.operations[lbl]
1080
+ elif typ == "prep": modelObj = mdl.preps[lbl]
1081
+ elif typ == "povm": modelObj = mdl.povms[lbl]
1082
+ elif typ == "instrument": modelObj = mdl.instruments[lbl]
1083
+ else: raise ValueError("Invalid dependency type: %s" % typ)
1084
+ else:
1085
+ if typ == "gate": modelObj = mdl.operation_blks['gates'][lbl]
1086
+ elif typ == "prep": modelObj = mdl.prep_blks['layers'][lbl]
1087
+ elif typ == "povm": modelObj = mdl.povm_blks['layers'][lbl]
1088
+ elif typ == "instrument": modelObj = mdl.instrument_blks['layers'][lbl]
1089
+ else: raise ValueError("Invalid dependency type: %s" % typ)
1076
1090
  all_gpindices.extend(modelObj.gpindices_as_array())
1077
1091
 
1078
1092
  vec0 = mdl.to_vector()
@@ -87,7 +87,6 @@ class Estimate(_MongoSerializable):
87
87
 
88
88
  @classmethod
89
89
  def _create_obj_from_doc_and_mongodb(cls, doc, mongodb, quick_load=False):
90
- #def from_mongodb(cls, mongodb_collection, doc_id, ):
91
90
  ret = cls.__new__(cls)
92
91
  _MongoSerializable.__init__(ret, doc.get('_id', None))
93
92
  ret.__dict__.update(_io.read_auxtree_from_mongodb_doc(mongodb, doc, 'auxfile_types', quick_load=quick_load))
@@ -277,7 +276,10 @@ class Estimate(_MongoSerializable):
277
276
  Model
278
277
  """
279
278
  goparams_list = [goparams] if hasattr(goparams, 'keys') else goparams
280
- return goparams_list[0].get('model', self.models['final iteration estimate'])
279
+ if goparams_list:
280
+ return goparams_list[0].get('model', self.models['final iteration estimate'])
281
+ else:
282
+ return None
281
283
 
282
284
  def add_gaugeoptimized(self, goparams, model=None, label=None, comm=None, verbosity=None):
283
285
  """
@@ -331,8 +333,14 @@ class Estimate(_MongoSerializable):
331
333
  label = "go%d" % i; i += 1
332
334
  if (label not in self._gaugeopt_suite.gaugeopt_argument_dicts) and \
333
335
  (label not in self.models): break
334
-
335
- goparams_list = [goparams] if hasattr(goparams, 'keys') else goparams
336
+ if hasattr(goparams, 'keys'):
337
+ goparams_list = [goparams]
338
+ elif goparams is None:
339
+ goparams_list = []
340
+ #since this will be empty much of the code/iteration below will
341
+ #be skipped.
342
+ else:
343
+ goparams_list = goparams
336
344
  ordered_goparams = []
337
345
  last_gs = None
338
346
 
@@ -350,11 +358,14 @@ class Estimate(_MongoSerializable):
350
358
  printer = _VerbosityPrinter.create_printer(max_vb, printer_comm)
351
359
  printer.log("-- Adding Gauge Optimized (%s) --" % label)
352
360
 
353
- for i, gop in enumerate(goparams_list):
354
-
355
- if model is not None:
356
- last_gs = model # just use user-supplied result
357
- else:
361
+ if model is not None:
362
+ last_gs = model # just use user-supplied result
363
+ #sort the parameters by name for consistency
364
+ for gop in goparams_list:
365
+ ordered_goparams.append(_collections.OrderedDict(
366
+ [(k, gop[k]) for k in sorted(list(gop.keys()))]))
367
+ else:
368
+ for i, gop in enumerate(goparams_list):
358
369
  from ..algorithms import gaugeopt_to_target as _gaugeopt_to_target
359
370
  default_model = default_target_model = False
360
371
  gop = gop.copy() # so we don't change the caller's dict
@@ -398,14 +409,20 @@ class Estimate(_MongoSerializable):
398
409
  if default_model: del gop['model']
399
410
  if default_target_model: del gop['target_model']
400
411
 
401
- #sort the parameters by name for consistency
402
- ordered_goparams.append(_collections.OrderedDict(
403
- [(k, gop[k]) for k in sorted(list(gop.keys()))]))
412
+ #sort the parameters by name for consistency
413
+ ordered_goparams.append(_collections.OrderedDict(
414
+ [(k, gop[k]) for k in sorted(list(gop.keys()))]))
404
415
 
405
416
  assert(last_gs is not None)
406
417
  self.models[label] = last_gs
407
- self._gaugeopt_suite.gaugeopt_argument_dicts[label] = ordered_goparams \
408
- if len(goparams_list) > 1 else ordered_goparams[0]
418
+
419
+ if goparams_list: #only do this if goparams_list wasn't empty to begin with.
420
+ #which would be the case except for the special case where the label is 'none'.
421
+ self._gaugeopt_suite.gaugeopt_argument_dicts[label] = ordered_goparams \
422
+ if len(goparams_list) > 1 else ordered_goparams[0]
423
+ else:
424
+ self._gaugeopt_suite.gaugeopt_argument_dicts[label] = None
425
+
409
426
 
410
427
  def add_confidence_region_factory(self,
411
428
  model_label='final iteration estimate',
pygsti/protocols/gst.py CHANGED
@@ -38,6 +38,7 @@ from pygsti import baseobjs as _baseobjs
38
38
  from pygsti.processors import QuditProcessorSpec as _QuditProcessorSpec
39
39
  from pygsti.modelmembers import operations as _op
40
40
  from pygsti.models import Model as _Model
41
+ from pygsti.models.explicitmodel import ExplicitOpModel as _ExplicitOpModel
41
42
  from pygsti.models.gaugegroup import GaugeGroup as _GaugeGroup, GaugeGroupElement as _GaugeGroupElement
42
43
  from pygsti.objectivefns import objectivefns as _objfns, wildcardbudget as _wild
43
44
  from pygsti.circuits.circuitlist import CircuitList as _CircuitList
@@ -595,7 +596,7 @@ class GSTBadFitOptions(_NicelySerializable):
595
596
  Actions to take when a GST fit is unsatisfactory. Allowed actions include:
596
597
 
597
598
  * 'wildcard': Find an admissable wildcard model.
598
- * 'ddist_wildcard': Fits a single parameter wildcard model in which
599
+ * 'wildcard1d': Fits a single parameter wildcard model in which
599
600
  the amount of wildcard error added to an operation is proportional
600
601
  to the diamond distance between that operation and the target.
601
602
  * 'robust': scale data according out "robust statistics v1" algorithm,
@@ -639,10 +640,8 @@ class GSTBadFitOptions(_NicelySerializable):
639
640
 
640
641
  wildcard_methods: tuple, optional
641
642
  A list of the methods to use to optimize the wildcard error vector. Default is `("neldermead",)`.
642
- Options include `"neldermead"`, `"barrier"`, `"cvxopt"`, `"cvxopt_smoothed"`, `"cvxopt_small"`,
643
- and `"cvxpy_noagg"`. So many methods exist because different convex solvers behave differently
644
- (unfortunately). Leave as the default as a safe option, but `"barrier"` is pretty reliable and much
645
- 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.
646
645
 
647
646
  wildcard_inadmissable_action: {"print", "raise"}, optional
648
647
  What to do when an inadmissable wildcard error vector is found. The default just prints this
@@ -841,7 +840,9 @@ class GSTGaugeOptSuite(_NicelySerializable):
841
840
  - "varyValidSpamWt" : varies spam weight with SPAM penalty == 1.
842
841
  - "toggleValidSpam" : toggles spame penalty (0 or 1); fixed SPAM wt.
843
842
  - "unreliable2Q" : adds branch to a spam suite that weights 2Q gates less
844
- - "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).
845
846
 
846
847
  gaugeopt_argument_dicts : dict, optional
847
848
  A dictionary whose string-valued keys label different gauge optimizations (e.g. within a
@@ -872,8 +873,11 @@ class GSTGaugeOptSuite(_NicelySerializable):
872
873
  def __init__(self, gaugeopt_suite_names=None, gaugeopt_argument_dicts=None, gaugeopt_target=None):
873
874
  super().__init__()
874
875
  if gaugeopt_suite_names is not None:
875
- self.gaugeopt_suite_names = (gaugeopt_suite_names,) \
876
- if isinstance(gaugeopt_suite_names, str) else tuple(gaugeopt_suite_names)
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)
877
881
  else:
878
882
  self.gaugeopt_suite_names = None
879
883
 
@@ -951,6 +955,8 @@ class GSTGaugeOptSuite(_NicelySerializable):
951
955
  if hasattr(goparams, 'keys'): # goparams is a simple dict
952
956
  gaugeopt_suite_dict[lbl] = goparams.copy()
953
957
  gaugeopt_suite_dict[lbl].update({'verbosity': printer})
958
+ elif goparams is None:
959
+ gaugeopt_suite_dict[lbl] = None
954
960
  else: # assume goparams is an iterable
955
961
  assert(isinstance(goparams, (list, tuple))), \
956
962
  "If not a dictionary, gauge opt params should be a list or tuple of dicts!"
@@ -963,7 +969,13 @@ class GSTGaugeOptSuite(_NicelySerializable):
963
969
  if self.gaugeopt_target is not None:
964
970
  assert(isinstance(self.gaugeopt_target, _Model)), "`gaugeopt_target` must be None or a Model"
965
971
  for goparams in gaugeopt_suite_dict.values():
966
- goparams_list = [goparams] if hasattr(goparams, 'keys') else goparams
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
+
967
979
  for goparams_dict in goparams_list:
968
980
  if 'target_model' in goparams_dict:
969
981
  _warnings.warn(("`gaugeOptTarget` argument is overriding"
@@ -1088,8 +1100,8 @@ class GSTGaugeOptSuite(_NicelySerializable):
1088
1100
  elif suite_name == "unreliable2Q":
1089
1101
  raise ValueError(("unreliable2Q is no longer a separate 'suite'. You should precede it with the suite"
1090
1102
  " name, e.g. 'stdgaugeopt-unreliable2Q' or 'varySpam-unreliable2Q'"))
1091
- elif suite_name == "none":
1092
- pass # add nothing
1103
+ elif suite_name == 'none':
1104
+ gaugeopt_suite_dict[root_lbl] = None
1093
1105
  else:
1094
1106
  raise ValueError("Unknown gauge-optimization suite '%s'" % suite_name)
1095
1107
 
@@ -1122,6 +1134,9 @@ class GSTGaugeOptSuite(_NicelySerializable):
1122
1134
  for lbl, goparams in self.gaugeopt_argument_dicts.items():
1123
1135
  goparams_list = [goparams] if hasattr(goparams, 'keys') else goparams
1124
1136
  serialize_list = []
1137
+ if lbl == 'trivial_gauge_opt':
1138
+ dicts_to_serialize[lbl] = None
1139
+ continue
1125
1140
  for goparams_dict in goparams_list:
1126
1141
  to_add = goparams_dict.copy()
1127
1142
  if 'target_model' in to_add:
@@ -1153,6 +1168,9 @@ class GSTGaugeOptSuite(_NicelySerializable):
1153
1168
  def _from_nice_serialization(cls, state): # memo holds already de-serialized objects
1154
1169
  gaugeopt_argument_dicts = {}
1155
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
1156
1174
  goparams_list = []
1157
1175
  for serialized_goparams in serialized_goparams_list:
1158
1176
  to_add = serialized_goparams.copy()
@@ -1232,15 +1250,16 @@ class GateSetTomography(_proto.Protocol):
1232
1250
 
1233
1251
  if isinstance(optimizer, _opt.Optimizer):
1234
1252
  self.optimizer = optimizer
1235
- if isinstance(optimizer, _opt.CustomLMOptimizer) and optimizer.first_fditer is None:
1236
- #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"
1237
1255
  self.optimizer = _copy.deepcopy(optimizer) # don't mess with caller's optimizer
1238
1256
  self.optimizer.first_fditer = default_first_fditer
1239
1257
  else:
1240
- if optimizer is None: optimizer = {}
1258
+ if optimizer is None:
1259
+ optimizer = {}
1241
1260
  if 'first_fditer' not in optimizer: # then add default first_fditer value
1242
1261
  optimizer['first_fditer'] = default_first_fditer
1243
- self.optimizer = _opt.CustomLMOptimizer.cast(optimizer)
1262
+ self.optimizer = _opt.SimplerLMOptimizer.cast(optimizer)
1244
1263
 
1245
1264
  self.objfn_builders = GSTObjFnBuilders.cast(objfn_builders)
1246
1265
 
@@ -1439,10 +1458,13 @@ class GateSetTomography(_proto.Protocol):
1439
1458
  target_model = self.gaugeopt_suite.gaugeopt_target
1440
1459
  elif self.initial_model.target_model is not None:
1441
1460
  target_model = self.initial_model.target_model.copy()
1442
- elif self.initial_model.model is not None and self.gaugeopt_suite.is_empty() is False:
1461
+ elif self.initial_model.model is not None:
1443
1462
  # when we desparately need a target model but none have been specifically given: use initial model
1444
1463
  target_model = self.initial_model.model.copy()
1445
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)
1446
1468
  target_model = None
1447
1469
 
1448
1470
  if target_model is not None and simulator is not None:
@@ -1451,10 +1473,22 @@ class GateSetTomography(_proto.Protocol):
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
- return _add_gaugeopt_and_badfit(ret, self.name, target_model,
1455
- self.gaugeopt_suite, self.unreliable_ops,
1456
- self.badfit_options, self.optimizer, resource_alloc, printer)
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
- return _add_gaugeopt_and_badfit(ret, self.name, target_model, self.gaugeopt_suite,
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):
@@ -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.CustomLMOptimizer.cast(optimizer)
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 a CustomLMOptimizer above.
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,11 +1772,6 @@ 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
- #def run_using_germs_and_fiducials(self, dataset, target_model, prep_fiducials, meas_fiducials, germs, max_lengths):
1717
- # design = StandardGSTDesign(target_model, prep_fiducials, meas_fiducials, germs, max_lengths)
1718
- # data = _proto.ProtocolData(design, dataset)
1719
- # return self.run(data)
1720
-
1721
1775
  def run(self, data, memlimit=None, comm=None, checkpoint=None, checkpoint_path=None,
1722
1776
  disable_checkpointing=False, simulator: Optional[ForwardSimulator.Castable]=None):
1723
1777
  """
@@ -1864,7 +1918,7 @@ class StandardGST(_proto.Protocol):
1864
1918
 
1865
1919
  #Try to interpret `mode` as a parameterization
1866
1920
  parameterization = mode # for now, 1-1 correspondence
1867
- initial_model = target_model
1921
+ initial_model = target_model.copy()
1868
1922
 
1869
1923
  try:
1870
1924
  initial_model.set_all_parameterizations(parameterization)
@@ -1961,7 +2015,7 @@ def _add_gaugeopt_and_badfit(results, estlbl, target_model, gaugeopt_suite,
1961
2015
  profiler = resource_alloc.profiler
1962
2016
 
1963
2017
  #Do final gauge optimization to *final* iteration result only
1964
- if gaugeopt_suite:
2018
+ if gaugeopt_suite is not None and not gaugeopt_suite.is_empty():
1965
2019
  model_to_gaugeopt = results.estimates[estlbl].models['final iteration estimate']
1966
2020
  if gaugeopt_suite.gaugeopt_target is None: # add a default target model to gauge opt if needed
1967
2021
  #TODO: maybe make these two lines into a method of GSTGaugeOptSuite for adding a target model?
@@ -1970,7 +2024,7 @@ def _add_gaugeopt_and_badfit(results, estlbl, target_model, gaugeopt_suite,
1970
2024
  _add_gauge_opt(results, estlbl, gaugeopt_suite,
1971
2025
  model_to_gaugeopt, unreliable_ops, comm, printer - 1)
1972
2026
  profiler.add_time('%s: gauge optimization' % estlbl, tref); tref = _time.time()
1973
-
2027
+
1974
2028
  _add_badfit_estimates(results, estlbl, badfit_options, optimizer, resource_alloc, printer, gaugeopt_suite= gaugeopt_suite)
1975
2029
  profiler.add_time('%s: add badfit estimates' % estlbl, tref); tref = _time.time()
1976
2030
  else:
@@ -2039,26 +2093,31 @@ def _add_gauge_opt(results, base_est_label, gaugeopt_suite, starting_model,
2039
2093
 
2040
2094
  printer.log("-- Performing '%s' gauge optimization on %s estimate --" % (go_label, base_est_label), 2)
2041
2095
 
2042
- #Get starting model
2043
- results.estimates[base_est_label].add_gaugeoptimized(goparams, None, go_label, comm, printer - 3)
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
2044
2103
  mdl_start = results.estimates[base_est_label].retrieve_start_model(goparams)
2045
-
2046
- #Gauge optimize data-scaled estimate also
2047
- for suffix in ROBUST_SUFFIX_LIST:
2048
- robust_est_label = base_est_label + suffix
2049
- if robust_est_label in results.estimates:
2050
- mdl_start_robust = results.estimates[robust_est_label].retrieve_start_model(goparams)
2051
-
2052
- if mdl_start_robust.frobeniusdist(mdl_start) < 1e-8:
2053
- printer.log("-- Conveying '%s' gauge optimization from %s to %s estimate --" %
2054
- (go_label, base_est_label, robust_est_label), 2)
2055
- params = results.estimates[base_est_label].goparameters[go_label] # no need to copy here
2056
- gsopt = results.estimates[base_est_label].models[go_label].copy()
2057
- results.estimates[robust_est_label].add_gaugeoptimized(params, gsopt, go_label, comm, printer - 3)
2058
- else:
2059
- printer.log("-- Performing '%s' gauge optimization on %s estimate --" %
2060
- (go_label, robust_est_label), 2)
2061
- results.estimates[robust_est_label].add_gaugeoptimized(goparams, None, go_label, comm, printer - 3)
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)
2062
2121
 
2063
2122
 
2064
2123
  def _add_badfit_estimates(results, base_estimate_label, badfit_options,
@@ -2301,9 +2360,16 @@ def _compute_wildcard_budget_1d_model(estimate, objfn_cache, mdc_objfn, paramete
2301
2360
  if gaugeopt_suite is None or gaugeopt_suite.gaugeopt_suite_names is None:
2302
2361
  gaugeopt_labels = None
2303
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
+
2304
2367
  else:
2305
2368
  gaugeopt_labels = gaugeopt_suite.gaugeopt_suite_names
2306
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.")
2307
2373
 
2308
2374
  if gaugeopt_labels is None:
2309
2375
  wcm = _wild.PrimitiveOpsSingleScaleWildcardBudget(primitive_ops, [ref[k] for k in primitive_ops],
@@ -2328,21 +2394,38 @@ def _compute_1d_reference_values_and_name(estimate, badfit_options, gaugeopt_sui
2328
2394
  if gaugeopt_suite is None or gaugeopt_suite.gaugeopt_suite_names is None:
2329
2395
  final_model = estimate.models['final iteration estimate']
2330
2396
  target_model = estimate.models['target']
2331
- gaugeopt_model = _alg.gaugeopt_to_target(final_model, target_model)
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
+
2332
2415
  dd = {}
2333
- for key, op in gaugeopt_model.operations.items():
2334
- dd[key] = 0.5 * _tools.diamonddist(op.to_dense(), target_model.operations[key].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())
2335
2418
  if dd[key] < 0: # indicates that diamonddist failed (cvxpy failure)
2336
2419
  _warnings.warn(("Diamond distance failed to compute %s reference value for 1D wildcard budget!"
2337
2420
  " Falling back to trace distance.") % str(key))
2338
- dd[key] = _tools.jtracedist(op.to_dense(), target_model.operations[key].to_dense())
2421
+ dd[key] = _tools.jtracedist(op.to_dense(), targetops_dict[key].to_dense())
2339
2422
 
2340
2423
  spamdd = {}
2341
- for key, op in gaugeopt_model.preps.items():
2424
+ for key, op in preps_dict.items():
2342
2425
  spamdd[key] = _tools.tracedist(_tools.vec_to_stdmx(op.to_dense(), 'pp'),
2343
- _tools.vec_to_stdmx(target_model.preps[key].to_dense(), 'pp'))
2426
+ _tools.vec_to_stdmx(targetpreps_dict[key].to_dense(), 'pp'))
2344
2427
 
2345
- for key in gaugeopt_model.povms.keys():
2428
+ for key in povmops_dict.keys():
2346
2429
  spamdd[key] = 0.5 * _tools.optools.povm_diamonddist(gaugeopt_model, target_model, key)
2347
2430
 
2348
2431
  dd['SPAM'] = sum(spamdd.values())
@@ -2589,23 +2672,14 @@ def _compute_wildcard_budget(objfn_cache, mdc_objfn, parameters, badfit_options,
2589
2672
  elif method_name == "barrier":
2590
2673
  _opt.optimize_wildcard_budget_barrier(budget, L1weights, mdc_objfn, two_dlogl_threshold,
2591
2674
  redbox_threshold, printer, **method_options)
2592
- elif method_name == "cvxopt":
2593
- _opt.optimize_wildcard_budget_cvxopt(budget, L1weights, mdc_objfn, two_dlogl_threshold,
2594
- redbox_threshold, printer, **method_options)
2595
- elif method_name == "cvxopt_smoothed":
2596
- _opt.optimize_wildcard_budget_cvxopt_smoothed(budget, L1weights, mdc_objfn,
2597
- two_dlogl_threshold, redbox_threshold,
2598
- printer, **method_options)
2599
- elif method_name == "cvxopt_small":
2600
- _opt.optimize_wildcard_budget_cvxopt_zeroreg(budget, L1weights, mdc_objfn,
2601
- two_dlogl_threshold, redbox_threshold, printer,
2602
- **method_options)
2603
2675
  elif method_name == "cvxpy_noagg":
2604
2676
  _opt.optimize_wildcard_budget_percircuit_only_cvxpy(budget, L1weights, mdc_objfn,
2605
2677
  redbox_threshold, printer,
2606
2678
  **method_options)
2607
2679
  elif method_name == "none":
2608
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.")
2609
2683
  else:
2610
2684
  raise ValueError("Invalid wildcard method name: %s" % method_name)
2611
2685
 
@@ -100,6 +100,7 @@ class ModelTest(_proto.Protocol):
100
100
  set_trivial_gauge_group=True, verbosity=2, name=None):
101
101
 
102
102
  from .gst import GSTBadFitOptions as _GSTBadFitOptions
103
+ from .gst import GSTGaugeOptSuite as _GSTGaugeOptSuite
103
104
 
104
105
  if set_trivial_gauge_group:
105
106
  model_to_test = model_to_test.copy()
@@ -109,7 +110,7 @@ class ModelTest(_proto.Protocol):
109
110
  super().__init__(name)
110
111
  self.model_to_test = model_to_test
111
112
  self.target_model = target_model
112
- self.gaugeopt_suite = gaugeopt_suite
113
+ self.gaugeopt_suite = _GSTGaugeOptSuite.cast(gaugeopt_suite)
113
114
  self.badfit_options = _GSTBadFitOptions.cast(badfit_options)
114
115
  self.verbosity = verbosity
115
116
 
@@ -127,12 +128,6 @@ class ModelTest(_proto.Protocol):
127
128
  self.circuit_weights = None
128
129
  self.unreliable_ops = ('Gcnot', 'Gcphase', 'Gms', 'Gcn', 'Gcx', 'Gcz')
129
130
 
130
- #def run_using_germs_and_fiducials(self, model, dataset, target_model, prep_fiducials,
131
- # meas_fiducials, germs, maxLengths):
132
- # from .gst import StandardGSTDesign as _StandardGSTDesign
133
- # design = _StandardGSTDesign(target_model, prep_fiducials, meas_fiducials, germs, maxLengths)
134
- # return self.run(_proto.ProtocolData(design, dataset))
135
-
136
131
  def run(self, data, memlimit=None, comm=None, checkpoint=None, checkpoint_path=None, disable_checkpointing=False,
137
132
  simulator: Optional[ForwardSimulator.Castable]=None):
138
133
  """
@@ -179,6 +174,7 @@ class ModelTest(_proto.Protocol):
179
174
  the_model = self.model_to_test
180
175
  if simulator is not None:
181
176
  the_model.sim = simulator
177
+
182
178
  target_model = self.target_model # can be None; target model isn't necessary
183
179
 
184
180
  #Create profiler
@@ -281,8 +277,8 @@ class ModelTest(_proto.Protocol):
281
277
  models['target'] = target_model
282
278
  ret.add_estimate(_Estimate(ret, models, parameters, extra_parameters=extra_parameters), estimate_key=self.name)
283
279
 
284
- #Add some better handling for when gauge optimization is turned off (current code path isn't working.
285
- if self.gaugeopt_suite is not None:
280
+ #Add some better handling for when gauge optimization is turned off (current code path isn't working.)
281
+ if not self.gaugeopt_suite.is_empty():
286
282
  ret= _add_gaugeopt_and_badfit(ret, self.name, target_model, self.gaugeopt_suite,
287
283
  self.unreliable_ops, self.badfit_options,
288
284
  None, resource_alloc, printer)
@@ -293,8 +289,8 @@ class ModelTest(_proto.Protocol):
293
289
  #and add a key for this to the goparameters dict (this is what the report
294
290
  #generation looks at to determine the names of the gauge optimized models).
295
291
  #Set the value to None as a placeholder.
296
- from .gst import GSTGaugeOptSuite
297
292
  ret.estimates[self.name].goparameters['trivial_gauge_opt']= None
293
+
298
294
  return ret
299
295
 
300
296