pyGSTi 0.9.12.1__cp310-cp310-win32.whl → 0.9.13__cp310-cp310-win32.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 +197 -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.cp310-win32.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.cp310-win32.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.cp310-win32.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.cp310-win32.pyd +0 -0
  39. pygsti/evotypes/densitymx/effectreps.pyx +1 -1
  40. pygsti/evotypes/densitymx/opreps.cp310-win32.pyd +0 -0
  41. pygsti/evotypes/densitymx/opreps.pyx +2 -2
  42. pygsti/evotypes/densitymx/statereps.cp310-win32.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.cp310-win32.pyd +0 -0
  49. pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
  50. pygsti/evotypes/stabilizer/opreps.cp310-win32.pyd +0 -0
  51. pygsti/evotypes/stabilizer/opreps.pyx +0 -4
  52. pygsti/evotypes/stabilizer/statereps.cp310-win32.pyd +0 -0
  53. pygsti/evotypes/stabilizer/statereps.pyx +1 -5
  54. pygsti/evotypes/stabilizer/termreps.cp310-win32.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.cp310-win32.pyd +0 -0
  60. pygsti/evotypes/statevec/effectreps.pyx +1 -1
  61. pygsti/evotypes/statevec/opreps.cp310-win32.pyd +0 -0
  62. pygsti/evotypes/statevec/opreps.pyx +2 -2
  63. pygsti/evotypes/statevec/statereps.cp310-win32.pyd +0 -0
  64. pygsti/evotypes/statevec/statereps.pyx +1 -1
  65. pygsti/evotypes/statevec/termreps.cp310-win32.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.cp310-win32.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.cp310-win32.pyd +0 -0
  84. pygsti/forwardsims/termforwardsim_calc_statevec.cp310-win32.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.cp310-win32.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
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp310-cp310-win32
5
5
 
pygsti/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.9.12.1'
16
- __version_tuple__ = version_tuple = (0, 9, 12, 1)
15
+ __version__ = version = '0.9.13'
16
+ __version_tuple__ = version_tuple = (0, 9, 13)
@@ -358,7 +358,7 @@ def _contract_to_valid_spam(model, verbosity=0):
358
358
 
359
359
  # ** assumption: only the first vector element of pauli vectors has nonzero trace
360
360
  dummyVec = _np.zeros((model.dim, 1), 'd'); dummyVec[0, 0] = 1.0
361
- firstElTrace = _np.real(_tools.trace(_tools.ppvec_to_stdmx(dummyVec))) # == sqrt(2)**nQubits
361
+ firstElTrace = _np.real(_np.trace(_tools.ppvec_to_stdmx(dummyVec))) # == sqrt(2)**nQubits
362
362
  diff = 0
363
363
 
364
364
  # rhoVec must be positive semidefinite and trace = 1
pygsti/algorithms/core.py CHANGED
@@ -31,8 +31,9 @@ from pygsti.modelmembers import instruments as _instrument
31
31
  from pygsti.modelmembers import states as _state
32
32
  from pygsti.circuits.circuitlist import CircuitList as _CircuitList
33
33
  from pygsti.baseobjs.resourceallocation import ResourceAllocation as _ResourceAllocation
34
- from pygsti.optimize.customlm import CustomLMOptimizer as _CustomLMOptimizer
35
- from pygsti.optimize.customlm import Optimizer as _Optimizer
34
+ from pygsti.optimize.simplerlm import Optimizer as _Optimizer, SimplerLMOptimizer as _SimplerLMOptimizer
35
+ from pygsti import forwardsims as _fwdsims
36
+ from pygsti import layouts as _layouts
36
37
 
37
38
  _dummy_profiler = _DummyProfiler()
38
39
 
@@ -247,7 +248,10 @@ def run_lgst(dataset, prep_fiducials, effect_fiducials, target_model, op_labels=
247
248
  circuit = rhostr
248
249
  dsRow_fractions = dataset[circuit].fractions
249
250
  # outcome labels should just be effect labels (no instruments!)
250
- EVec[0, i] = dsRow_fractions[(effectLabel,)]
251
+ # when using a sparse data set format it might not be the case
252
+ # that all effect labels are present (only ones with non-zero counts are)
253
+ # so return 0 for the fraction in that case.
254
+ EVec[0, i] = dsRow_fractions.get((effectLabel,), 0)
251
255
  EVec_p = _np.dot(_np.dot(EVec, Vd), Pj) # truncate Evec => Evec', shape (1,trunc)
252
256
  povm_effects.append((effectLabel, _np.transpose(EVec_p)))
253
257
  lgstModel.povms[povmLabel] = _povm.UnconstrainedPOVM(povm_effects, evotype='default')
@@ -262,7 +266,10 @@ def run_lgst(dataset, prep_fiducials, effect_fiducials, target_model, op_labels=
262
266
  # try without prepLabel since it will be the default
263
267
  circuit = estr
264
268
  dsRow_fractions = dataset[circuit].fractions
265
- rhoVec[eoff:eoff + povmLen, 0] = [dsRow_fractions[(ol,)] for ol in target_model.povms[povmLbl]]
269
+ # when using a sparse data set format it might not be the case
270
+ # that all effect labels are present (only ones with non-zero counts are)
271
+ # so return 0 for the fraction in that case.
272
+ rhoVec[eoff:eoff + povmLen, 0] = [dsRow_fractions.get((ol,),0) for ol in target_model.povms[povmLbl]]
266
273
  eoff += povmLen
267
274
  rhoVec_p = _np.dot(Pjt, _np.dot(Ud, rhoVec)) # truncate rhoVec => rhoVec', shape (trunc, 1)
268
275
  rhoVec_p = _np.dot(invABMat_p, rhoVec_p)
@@ -394,7 +401,7 @@ def _construct_ab(prep_fiducials, effect_fiducials, model, dataset, op_label_ali
394
401
  for j, rhostr in enumerate(prep_fiducials):
395
402
  opLabelString = rhostr + estr # LEXICOGRAPHICAL VS MATRIX ORDER
396
403
  dsStr = opLabelString.replace_layers_with_aliases(op_label_aliases)
397
- expd_circuit_outcomes = opLabelString.expand_instruments_and_separate_povm(model)
404
+ expd_circuit_outcomes = model.expand_instruments_and_separate_povm(opLabelString)
398
405
  assert(len(expd_circuit_outcomes) == 1), "No instruments are allowed in LGST fiducials!"
399
406
  unique_key = next(iter(expd_circuit_outcomes.keys()))
400
407
  outcomes = expd_circuit_outcomes[unique_key]
@@ -423,7 +430,7 @@ def _construct_x_matrix(prep_fiducials, effect_fiducials, model, op_label_tuple,
423
430
  for j, rhostr in enumerate(prep_fiducials):
424
431
  opLabelString = rhostr + _circuits.Circuit(op_label_tuple, line_labels=rhostr.line_labels) + estr
425
432
  dsStr = opLabelString.replace_layers_with_aliases(op_label_aliases)
426
- expd_circuit_outcomes = opLabelString.expand_instruments_and_separate_povm(model)
433
+ expd_circuit_outcomes = model.expand_instruments_and_separate_povm(opLabelString)
427
434
  dsRow_fractions = dataset[dsStr].fractions
428
435
  assert(len(expd_circuit_outcomes) == nVariants)
429
436
 
@@ -611,7 +618,7 @@ def run_gst_fit_simple(dataset, start_model, circuits, optimizer, objective_func
611
618
  model : Model
612
619
  the best-fit model.
613
620
  """
614
- optimizer = optimizer if isinstance(optimizer, _Optimizer) else _CustomLMOptimizer.cast(optimizer)
621
+ optimizer = optimizer if isinstance(optimizer, _Optimizer) else _SimplerLMOptimizer.cast(optimizer)
615
622
  objective_function_builder = _objfns.ObjectiveFunctionBuilder.cast(objective_function_builder)
616
623
  array_types = optimizer.array_types + \
617
624
  objective_function_builder.compute_array_types(optimizer.called_objective_methods, start_model.sim)
@@ -658,7 +665,7 @@ def run_gst_fit(mdc_store, optimizer, objective_function_builder, verbosity=0):
658
665
  objfn_store : MDCObjectiveFunction
659
666
  the objective function and store containing the best-fit model evaluated at the best-fit point.
660
667
  """
661
- optimizer = optimizer if isinstance(optimizer, _Optimizer) else _CustomLMOptimizer.cast(optimizer)
668
+ optimizer = optimizer if isinstance(optimizer, _Optimizer) else _SimplerLMOptimizer.cast(optimizer)
662
669
  comm = mdc_store.resource_alloc.comm
663
670
  profiler = mdc_store.resource_alloc.profiler
664
671
  printer = VerbosityPrinter.create_printer(verbosity, comm)
@@ -671,16 +678,10 @@ def run_gst_fit(mdc_store, optimizer, objective_function_builder, verbosity=0):
671
678
  if _np.linalg.norm(mdc_store.model.to_vector() - v_cmp) > 1e-6:
672
679
  raise ValueError("MPI ERROR: *different* MC2GST start models"
673
680
  " given to different processors!") # pragma: no cover
674
-
675
- #MEM from ..baseobjs.profiler import Profiler
676
- #MEM debug_prof = Profiler(comm)
677
- #MEM debug_prof.print_memory("run_gst_fit1", True)
678
-
681
+
679
682
  if objective_function_builder is not None:
680
683
  objective_function_builder = _objfns.ObjectiveFunctionBuilder.cast(objective_function_builder)
681
- #MEM debug_prof.print_memory("run_gst_fit2", True)
682
684
  objective = objective_function_builder.build_from_store(mdc_store, printer) # (objective is *also* a store)
683
- #MEM debug_prof.print_memory("run_gst_fit3", True)
684
685
  else:
685
686
  assert(isinstance(mdc_store, _objfns.ObjectiveFunction)), \
686
687
  "When `objective_function_builder` is None, `mdc_store` must be an objective fn!"
@@ -699,14 +700,8 @@ def run_gst_fit(mdc_store, optimizer, objective_function_builder, verbosity=0):
699
700
 
700
701
  printer.log("Completed in %.1fs" % (_time.time() - tStart), 1)
701
702
 
702
- #if target_model is not None:
703
- # target_vec = target_model.to_vector()
704
- # targetErrVec = _objective_func(target_vec)
705
- # return minErrVec, soln_gs, targetErrVec
706
703
  profiler.add_time("do_mc2gst: total time", tStart)
707
- #TODO: evTree.permute_computation_to_original(minErrVec) #Doesn't work b/c minErrVec is flattened
708
- # but maybe best to just remove minErrVec from return value since this isn't very useful
709
- # anyway?
704
+
710
705
  return opt_result, objective
711
706
 
712
707
 
@@ -847,7 +842,7 @@ def iterative_gst_generator(dataset, start_model, circuit_lists,
847
842
  (an "evaluated" model-dataset-circuits store).
848
843
  """
849
844
  resource_alloc = _ResourceAllocation.cast(resource_alloc)
850
- optimizer = optimizer if isinstance(optimizer, _Optimizer) else _CustomLMOptimizer.cast(optimizer)
845
+ optimizer = optimizer if isinstance(optimizer, _Optimizer) else _SimplerLMOptimizer.cast(optimizer)
851
846
  comm = resource_alloc.comm
852
847
  profiler = resource_alloc.profiler
853
848
  printer = VerbosityPrinter.create_printer(verbosity, comm)
@@ -882,10 +877,30 @@ def iterative_gst_generator(dataset, start_model, circuit_lists,
882
877
  #The ModelDatasetCircuitsStore
883
878
  printer.log('Precomputing CircuitOutcomeProbabilityArray layouts for each iteration.', 2)
884
879
  precomp_layouts = []
880
+
881
+ #pre-compute a dictionary caching completed circuits for layout construction performance.
882
+ unique_circuits = list({ckt for circuit_list in circuit_lists for ckt in circuit_list})
883
+ if isinstance(mdl.sim, (_fwdsims.MatrixForwardSimulator, _fwdsims.MapForwardSimulator)):
884
+ precomp_layout_circuit_cache = mdl.sim.create_copa_layout_circuit_cache(unique_circuits, mdl, dataset=dataset)
885
+ else:
886
+ precomp_layout_circuit_cache = None
887
+
885
888
  for i, circuit_list in enumerate(circuit_lists):
886
889
  printer.log(f'Layout for iteration {i}', 2)
887
- precomp_layouts.append(mdl.sim.create_layout(circuit_list, dataset, resource_alloc, array_types, verbosity= printer - 1))
888
-
890
+ precomp_layouts.append(mdl.sim.create_layout(circuit_list, dataset, resource_alloc, array_types, verbosity= printer - 1,
891
+ layout_creation_circuit_cache = precomp_layout_circuit_cache))
892
+
893
+ #precompute a cache of possible outcome counts for each circuits to accelerate MDC store creation
894
+ if isinstance(mdl, _models.model.OpModel):
895
+ if precomp_layout_circuit_cache is not None: #then grab the split circuits from there.
896
+ expanded_circuit_outcome_list = mdl.bulk_expand_instruments_and_separate_povm(unique_circuits,
897
+ completed_circuits= precomp_layout_circuit_cache['completed_circuits'].values())
898
+ else:
899
+ expanded_circuit_outcome_list = mdl.bulk_expand_instruments_and_separate_povm(unique_circuits)
900
+ outcome_count_by_circuit_cache = {ckt: len(outcome_tup) for ckt,outcome_tup in zip(unique_circuits, expanded_circuit_outcome_list)}
901
+ else:
902
+ outcome_count_by_circuit_cache = {ckt: mdl.compute_num_outcomes(ckt) for ckt in unique_circuits}
903
+
889
904
  with printer.progress_logging(1):
890
905
  for i in range(starting_index, len(circuit_lists)):
891
906
  circuitsToEstimate = circuit_lists[i]
@@ -902,7 +917,8 @@ def iterative_gst_generator(dataset, start_model, circuit_lists,
902
917
  mdl.basis = start_model.basis # set basis in case of CPTP constraints (needed?)
903
918
  initial_mdc_store = _objfns.ModelDatasetCircuitsStore(mdl, dataset, circuitsToEstimate, resource_alloc,
904
919
  array_types=array_types, verbosity=printer - 1,
905
- precomp_layout = precomp_layouts[i])
920
+ precomp_layout = precomp_layouts[i],
921
+ outcome_count_by_circuit=outcome_count_by_circuit_cache)
906
922
  mdc_store = initial_mdc_store
907
923
 
908
924
  for j, obj_fn_builder in enumerate(iteration_objfn_builders):
@@ -1133,8 +1149,6 @@ def find_closest_unitary_opmx(operation_mx):
1133
1149
  # d = _np.sqrt(operation_mx.shape[0])
1134
1150
  # I = _np.identity(d)
1135
1151
 
1136
- #def getu_1q(basisVec): # 1 qubit version
1137
- # return _spl.expm( 1j * (basisVec[0]*_tools.sigmax + basisVec[1]*_tools.sigmay + basisVec[2]*_tools.sigmaz) )
1138
1152
  def _get_gate_mx_1q(basis_vec): # 1 qubit version
1139
1153
  return _tools.single_qubit_gate(basis_vec[0],
1140
1154
  basis_vec[1],
@@ -409,13 +409,6 @@ def find_fiducials(target_model, omit_identity=True, eq_thresh=1e-6,
409
409
  return prepFidList, measFidList
410
410
 
411
411
 
412
- #def bool_list_to_ind_list(boolList):
413
- # output = _np.array([])
414
- # for i, boolVal in boolList:
415
- # if boolVal == 1:
416
- # output = _np.append(i)
417
- # return output
418
-
419
412
  def xor(*args):
420
413
  """
421
414
  Implements logical xor function for arbitrary number of inputs.
@@ -2013,7 +2006,23 @@ def create_candidate_fiducial_list(target_model, omit_identity= True, ops_to_omi
2013
2006
  else:
2014
2007
  availableFidList.extend(_circuits.list_random_circuits_onelen(
2015
2008
  fidOps, fidLength, count, seed=candidate_seed))
2016
- return availableFidList
2009
+
2010
+ #force the line labels on each circuit to match the state space labels for the target model.
2011
+ #this is suboptimal for many-qubit models, so will probably want to revisit this. #TODO
2012
+ finalFidList = []
2013
+ for ckt in availableFidList:
2014
+ if ckt._static:
2015
+ new_ckt = ckt.copy(editable=True)
2016
+ new_ckt.line_labels = target_model.state_space.state_space_labels
2017
+ new_ckt.done_editing()
2018
+
2019
+ finalFidList.append(new_ckt)
2020
+ else:
2021
+ ckt.line_labels = target_model.state_space.state_space_labels
2022
+
2023
+ finalFidList.append(ckt)
2024
+
2025
+ return finalFidList
2017
2026
 
2018
2027
 
2019
2028
 
@@ -290,7 +290,7 @@ def gaugeopt_custom(model, objective_fn, gauge_group=None,
290
290
  gaugeGroupEl = gauge_group.compute_element(x0) # re-used element for evals
291
291
 
292
292
  def _call_objective_fn(gauge_group_el_vec, oob_check=False):
293
- # Note: oob_check can be True if oob_check_interval>=1 is given to the custom_leastsq below
293
+ # Note: oob_check can be True if oob_check_interval>=1 is given to the simplish_leastsq below
294
294
  gaugeGroupEl.from_vector(gauge_group_el_vec)
295
295
  return objective_fn(gaugeGroupEl, oob_check)
296
296
 
@@ -309,7 +309,7 @@ def gaugeopt_custom(model, objective_fn, gauge_group=None,
309
309
  assert(_call_jacobian_fn is not None), "Cannot use 'ls' method unless jacobian is available"
310
310
  ralloc = _baseobjs.ResourceAllocation(comm) # FUTURE: plumb up a resource alloc object?
311
311
  test_f = _call_objective_fn(x0)
312
- solnX, converged, msg, _, _, _, _, _ = _opt.custom_leastsq(
312
+ solnX, converged, msg, _, _, _, _ = _opt.simplish_leastsq(
313
313
  _call_objective_fn, _call_jacobian_fn, x0, f_norm2_tol=tol,
314
314
  jac_norm_tol=tol, rel_ftol=tol, rel_xtol=tol,
315
315
  max_iter=maxiter, resource_alloc=ralloc,
@@ -27,6 +27,7 @@ from pygsti.tools import mpitools as _mpit
27
27
  from pygsti.baseobjs.statespace import ExplicitStateSpace as _ExplicitStateSpace
28
28
  from pygsti.baseobjs.statespace import QuditSpace as _QuditSpace
29
29
  from pygsti.models import ExplicitOpModel as _ExplicitOpModel
30
+ from pygsti.forwardsims import MatrixForwardSimulator as _MatrixForwardSimulator
30
31
 
31
32
  FLOATSIZE = 8 # in bytes: TODO: a better way
32
33
 
@@ -57,10 +58,8 @@ def find_germs(target_model, randomize=True, randomization_strength=1e-2,
57
58
 
58
59
  Parameters
59
60
  ----------
60
- target_model : Model or list of Model
61
- The model you are aiming to implement, or a list of models that are
62
- copies of the model you are trying to implement (either with or
63
- without random unitary perturbations applied to the models).
61
+ target_model : Model
62
+ The model you are aiming to implement.
64
63
 
65
64
  randomize : bool, optional
66
65
  Whether or not to add random unitary perturbations to the model(s)
@@ -188,8 +187,14 @@ def find_germs(target_model, randomize=True, randomization_strength=1e-2,
188
187
  A list containing the germs making up the germ set.
189
188
  """
190
189
  printer = _baseobjs.VerbosityPrinter.create_printer(verbosity, comm)
190
+
191
+ if not isinstance(target_model.sim, _MatrixForwardSimulator):
192
+ target_model = target_model.copy()
193
+ target_model.sim = 'matrix'
194
+
191
195
  modelList = _setup_model_list(target_model, randomize,
192
196
  randomization_strength, num_gs_copies, seed)
197
+
193
198
  gates = list(target_model.operations.keys())
194
199
  availableGermsList = []
195
200
  if candidate_germ_counts is None: candidate_germ_counts = {6: 'all upto'}
@@ -1351,6 +1356,10 @@ def test_germ_set_finitel(model, germs_to_test, length, weights=None,
1351
1356
  eigenvalues (from small to large) of the jacobian^T * jacobian
1352
1357
  matrix used to determine parameter amplification.
1353
1358
  """
1359
+ if not isinstance(model.sim, _MatrixForwardSimulator):
1360
+ model = model.copy()
1361
+ model.sim = 'matrix'
1362
+
1354
1363
  # Remove any SPAM vectors from model since we only want
1355
1364
  # to consider the set of *gate* parameters for amplification
1356
1365
  # and this makes sure our parameter counting is correct
@@ -3295,80 +3304,81 @@ def symmetric_low_rank_spectrum_update(update, orig_e, U, proj_U, force_rank_inc
3295
3304
  #return the new eigenvalues
3296
3305
  return new_evals, True
3297
3306
 
3298
- #Note: This function won't work for our purposes because of the assumptions
3299
- #about the rank of the update on the nullspace of the matrix we're updating,
3300
- #but keeping this here commented for future reference.
3301
- #Function for doing fast calculation of the updated inverse trace:
3302
- #def riedel_style_inverse_trace(update, orig_e, U, proj_U, force_rank_increase=True):
3303
- # """
3304
- # input:
3305
- #
3306
- # update : ndarray
3307
- # symmetric low-rank update to perform.
3308
- # This is the first half the symmetric rank decomposition s.t.
3309
- # update@update.T= the full update matrix.
3310
- #
3311
- # orig_e : ndarray
3312
- # Spectrum of the original matrix. This is a 1-D array.
3313
- #
3314
- # proj_U : ndarray
3315
- # Projector onto the complement of the column space of the
3316
- # original matrix's eigenvectors.
3317
- #
3318
- # output:
3319
- #
3320
- # trace : float
3321
- # Value of the trace of the updated psuedoinverse matrix.
3322
- #
3323
- # updated_rank : int
3324
- # total rank of the updated matrix.
3325
- #
3326
- # rank_increase_flag : bool
3327
- # a flag that is returned to indicate is a candidate germ failed to amplify additional parameters.
3328
- # This indicates things short circuited and so the scoring function should skip this germ.
3329
- # """
3330
- #
3331
- # #First we need to for the matrix P, whose column space
3332
- # #forms an orthonormal basis for the component of update
3333
- # #that is in the complement of U.
3334
- #
3335
- # proj_update= proj_U@update
3336
- #
3337
- # #Next take the RRQR decomposition of this matrix:
3338
- # q_update, r_update, _ = _sla.qr(proj_update, mode='economic', pivoting=True)
3339
- #
3340
- # #Construct P by taking the columns of q_update corresponding to non-zero values of r_A on the diagonal.
3341
- # nonzero_indices_update= _np.nonzero(_np.diag(r_update)>1e-10) #HARDCODED (threshold is hardcoded)
3342
- #
3343
- # #if the rank doesn't increase then we can't use the Riedel approach.
3344
- # #Abort early and return a flag to indicate the rank did not increase.
3345
- # if len(nonzero_indices_update[0])==0 and force_rank_increase:
3346
- # return None, None, False
3347
- #
3348
- # P= q_update[: , nonzero_indices_update[0]]
3349
- #
3350
- # updated_rank= len(orig_e)+ len(nonzero_indices_update[0])
3351
- #
3352
- # #Now form the matrix R_update which is given by P.T @ proj_update.
3353
- # R_update= P.T@proj_update
3354
- #
3355
- # #R_update gets concatenated with U.T@update to form
3356
- # #a block column matrixblock_column= np.concatenate([U.T@update, R_update], axis=0)
3357
- #
3358
- # Uta= U.T@update
3359
- #
3360
- # try:
3361
- # RRRDinv= R_update@_np.linalg.inv(R_update.T@R_update)
3362
- # except _np.linalg.LinAlgError as err:
3363
- # print('Numpy thinks this matrix is singular, condition number is: ', _np.linalg.cond(R_update.T@R_update))
3364
- # print((R_update.T@R_update).shape)
3365
- # raise err
3366
- # pinv_orig_e_mat= _np.diag(1/orig_e)
3367
- #
3368
- # trace= _np.sum(1/orig_e) + _np.trace( RRRDinv@(_np.eye(Uta.shape[1]) + Uta.T@pinv_orig_e_mat@Uta)@RRRDinv.T )
3369
- #
3370
- # return trace, updated_rank, True
3307
+ # Note: Th function below won't work for our purposes because of the assumptions
3308
+ # about the rank of the update on the nullspace of the matrix we're updating,
3309
+ # but keeping this here commented for future reference.
3310
+ '''
3311
+ def riedel_style_inverse_trace(update, orig_e, U, proj_U, force_rank_increase=True):
3312
+ """
3313
+ input:
3314
+
3315
+ update : ndarray
3316
+ symmetric low-rank update to perform.
3317
+ This is the first half the symmetric rank decomposition s.t.
3318
+ update@update.T= the full update matrix.
3319
+
3320
+ orig_e : ndarray
3321
+ Spectrum of the original matrix. This is a 1-D array.
3322
+
3323
+ proj_U : ndarray
3324
+ Projector onto the complement of the column space of the
3325
+ original matrix's eigenvectors.
3326
+
3327
+ output:
3328
+
3329
+ trace : float
3330
+ Value of the trace of the updated psuedoinverse matrix.
3331
+
3332
+ updated_rank : int
3333
+ total rank of the updated matrix.
3334
+
3335
+ rank_increase_flag : bool
3336
+ a flag that is returned to indicate is a candidate germ failed to amplify additional parameters.
3337
+ This indicates things short circuited and so the scoring function should skip this germ.
3338
+ """
3371
3339
 
3340
+ #First we need to for the matrix P, whose column space
3341
+ #forms an orthonormal basis for the component of update
3342
+ #that is in the complement of U.
3343
+
3344
+ proj_update= proj_U@update
3345
+
3346
+ #Next take the RRQR decomposition of this matrix:
3347
+ q_update, r_update, _ = _sla.qr(proj_update, mode='economic', pivoting=True)
3348
+
3349
+ #Construct P by taking the columns of q_update corresponding to non-zero values of r_A on the diagonal.
3350
+ nonzero_indices_update= _np.nonzero(_np.diag(r_update)>1e-10) #HARDCODED (threshold is hardcoded)
3351
+
3352
+ #if the rank doesn't increase then we can't use the Riedel approach.
3353
+ #Abort early and return a flag to indicate the rank did not increase.
3354
+ if len(nonzero_indices_update[0])==0 and force_rank_increase:
3355
+ return None, None, False
3356
+
3357
+ P= q_update[: , nonzero_indices_update[0]]
3358
+
3359
+ updated_rank= len(orig_e)+ len(nonzero_indices_update[0])
3360
+
3361
+ #Now form the matrix R_update which is given by P.T @ proj_update.
3362
+ R_update= P.T@proj_update
3363
+
3364
+ #R_update gets concatenated with U.T@update to form
3365
+ #a block column matrixblock_column= np.concatenate([U.T@update, R_update], axis=0)
3366
+
3367
+ Uta= U.T@update
3368
+
3369
+ try:
3370
+ RRRDinv= R_update@_np.linalg.inv(R_update.T@R_update)
3371
+ except _np.linalg.LinAlgError as err:
3372
+ print('Numpy thinks this matrix is singular, condition number is: ', _np.linalg.cond(R_update.T@R_update))
3373
+ print((R_update.T@R_update).shape)
3374
+ raise err
3375
+ pinv_orig_e_mat= _np.diag(1/orig_e)
3376
+
3377
+ trace= _np.sum(1/orig_e) + _np.trace( RRRDinv@(_np.eye(Uta.shape[1]) + Uta.T@pinv_orig_e_mat@Uta)@RRRDinv.T )
3378
+
3379
+ return trace, updated_rank, True
3380
+ '''
3381
+
3372
3382
  def minamide_style_inverse_trace(update, orig_e, U, proj_U, force_rank_increase=False):
3373
3383
  """
3374
3384
  This function performs a low-rank update to the components of