pyGSTi 0.9.12__cp310-cp310-win_amd64.whl → 0.9.13__cp310-cp310-win_amd64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (225) hide show
  1. pyGSTi-0.9.13.dist-info/METADATA +197 -0
  2. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +211 -220
  3. {pyGSTi-0.9.12.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 +62 -35
  7. pygsti/algorithms/fiducialpairreduction.py +95 -110
  8. pygsti/algorithms/fiducialselection.py +17 -8
  9. pygsti/algorithms/gaugeopt.py +2 -2
  10. pygsti/algorithms/germselection.py +87 -77
  11. pygsti/algorithms/mirroring.py +0 -388
  12. pygsti/algorithms/randomcircuit.py +165 -1333
  13. pygsti/algorithms/rbfit.py +0 -234
  14. pygsti/baseobjs/basis.py +94 -396
  15. pygsti/baseobjs/errorgenbasis.py +0 -132
  16. pygsti/baseobjs/errorgenspace.py +0 -10
  17. pygsti/baseobjs/label.py +52 -168
  18. pygsti/baseobjs/opcalc/fastopcalc.cp310-win_amd64.pyd +0 -0
  19. pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
  20. pygsti/baseobjs/polynomial.py +13 -595
  21. pygsti/baseobjs/protectedarray.py +72 -132
  22. pygsti/baseobjs/statespace.py +1 -0
  23. pygsti/circuits/__init__.py +1 -1
  24. pygsti/circuits/circuit.py +753 -504
  25. pygsti/circuits/circuitconstruction.py +0 -4
  26. pygsti/circuits/circuitlist.py +47 -5
  27. pygsti/circuits/circuitparser/__init__.py +8 -8
  28. pygsti/circuits/circuitparser/fastcircuitparser.cp310-win_amd64.pyd +0 -0
  29. pygsti/circuits/circuitstructure.py +3 -3
  30. pygsti/circuits/cloudcircuitconstruction.py +27 -14
  31. pygsti/data/datacomparator.py +4 -9
  32. pygsti/data/dataset.py +51 -46
  33. pygsti/data/hypothesistest.py +0 -7
  34. pygsti/drivers/bootstrap.py +0 -49
  35. pygsti/drivers/longsequence.py +46 -10
  36. pygsti/evotypes/basereps_cython.cp310-win_amd64.pyd +0 -0
  37. pygsti/evotypes/chp/opreps.py +0 -61
  38. pygsti/evotypes/chp/statereps.py +0 -32
  39. pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
  40. pygsti/evotypes/densitymx/effectreps.cp310-win_amd64.pyd +0 -0
  41. pygsti/evotypes/densitymx/effectreps.pyx +1 -1
  42. pygsti/evotypes/densitymx/opreps.cp310-win_amd64.pyd +0 -0
  43. pygsti/evotypes/densitymx/opreps.pyx +2 -2
  44. pygsti/evotypes/densitymx/statereps.cp310-win_amd64.pyd +0 -0
  45. pygsti/evotypes/densitymx/statereps.pyx +1 -1
  46. pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
  47. pygsti/evotypes/densitymx_slow/opreps.py +16 -23
  48. pygsti/evotypes/densitymx_slow/statereps.py +10 -3
  49. pygsti/evotypes/evotype.py +39 -2
  50. pygsti/evotypes/stabilizer/effectreps.cp310-win_amd64.pyd +0 -0
  51. pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
  52. pygsti/evotypes/stabilizer/opreps.cp310-win_amd64.pyd +0 -0
  53. pygsti/evotypes/stabilizer/opreps.pyx +0 -4
  54. pygsti/evotypes/stabilizer/statereps.cp310-win_amd64.pyd +0 -0
  55. pygsti/evotypes/stabilizer/statereps.pyx +1 -5
  56. pygsti/evotypes/stabilizer/termreps.cp310-win_amd64.pyd +0 -0
  57. pygsti/evotypes/stabilizer/termreps.pyx +0 -7
  58. pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
  59. pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
  60. pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
  61. pygsti/evotypes/statevec/effectreps.cp310-win_amd64.pyd +0 -0
  62. pygsti/evotypes/statevec/effectreps.pyx +1 -1
  63. pygsti/evotypes/statevec/opreps.cp310-win_amd64.pyd +0 -0
  64. pygsti/evotypes/statevec/opreps.pyx +2 -2
  65. pygsti/evotypes/statevec/statereps.cp310-win_amd64.pyd +0 -0
  66. pygsti/evotypes/statevec/statereps.pyx +1 -1
  67. pygsti/evotypes/statevec/termreps.cp310-win_amd64.pyd +0 -0
  68. pygsti/evotypes/statevec/termreps.pyx +0 -7
  69. pygsti/evotypes/statevec_slow/effectreps.py +0 -3
  70. pygsti/evotypes/statevec_slow/opreps.py +0 -5
  71. pygsti/extras/__init__.py +0 -1
  72. pygsti/extras/drift/signal.py +1 -1
  73. pygsti/extras/drift/stabilityanalyzer.py +3 -1
  74. pygsti/extras/interpygate/__init__.py +12 -0
  75. pygsti/extras/interpygate/core.py +0 -36
  76. pygsti/extras/interpygate/process_tomography.py +44 -10
  77. pygsti/extras/rpe/rpeconstruction.py +0 -2
  78. pygsti/forwardsims/__init__.py +1 -0
  79. pygsti/forwardsims/forwardsim.py +50 -93
  80. pygsti/forwardsims/mapforwardsim.py +78 -20
  81. pygsti/forwardsims/mapforwardsim_calc_densitymx.cp310-win_amd64.pyd +0 -0
  82. pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
  83. pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
  84. pygsti/forwardsims/matrixforwardsim.py +72 -17
  85. pygsti/forwardsims/termforwardsim.py +9 -111
  86. pygsti/forwardsims/termforwardsim_calc_stabilizer.cp310-win_amd64.pyd +0 -0
  87. pygsti/forwardsims/termforwardsim_calc_statevec.cp310-win_amd64.pyd +0 -0
  88. pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
  89. pygsti/forwardsims/torchfwdsim.py +265 -0
  90. pygsti/forwardsims/weakforwardsim.py +2 -2
  91. pygsti/io/__init__.py +1 -2
  92. pygsti/io/mongodb.py +0 -2
  93. pygsti/io/stdinput.py +6 -22
  94. pygsti/layouts/copalayout.py +10 -12
  95. pygsti/layouts/distlayout.py +0 -40
  96. pygsti/layouts/maplayout.py +103 -25
  97. pygsti/layouts/matrixlayout.py +99 -60
  98. pygsti/layouts/prefixtable.py +1534 -52
  99. pygsti/layouts/termlayout.py +1 -1
  100. pygsti/modelmembers/instruments/instrument.py +3 -3
  101. pygsti/modelmembers/instruments/tpinstrument.py +2 -2
  102. pygsti/modelmembers/modelmember.py +0 -17
  103. pygsti/modelmembers/operations/__init__.py +3 -4
  104. pygsti/modelmembers/operations/affineshiftop.py +206 -0
  105. pygsti/modelmembers/operations/composederrorgen.py +1 -1
  106. pygsti/modelmembers/operations/composedop.py +1 -24
  107. pygsti/modelmembers/operations/denseop.py +5 -5
  108. pygsti/modelmembers/operations/eigpdenseop.py +2 -2
  109. pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
  110. pygsti/modelmembers/operations/embeddedop.py +0 -1
  111. pygsti/modelmembers/operations/experrorgenop.py +5 -2
  112. pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
  113. pygsti/modelmembers/operations/fullcptpop.py +2 -2
  114. pygsti/modelmembers/operations/fulltpop.py +28 -6
  115. pygsti/modelmembers/operations/fullunitaryop.py +5 -4
  116. pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
  117. pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
  118. pygsti/modelmembers/operations/linearop.py +7 -27
  119. pygsti/modelmembers/operations/opfactory.py +1 -1
  120. pygsti/modelmembers/operations/repeatedop.py +1 -24
  121. pygsti/modelmembers/operations/staticstdop.py +1 -1
  122. pygsti/modelmembers/povms/__init__.py +3 -3
  123. pygsti/modelmembers/povms/basepovm.py +7 -36
  124. pygsti/modelmembers/povms/complementeffect.py +4 -9
  125. pygsti/modelmembers/povms/composedeffect.py +0 -320
  126. pygsti/modelmembers/povms/computationaleffect.py +1 -1
  127. pygsti/modelmembers/povms/computationalpovm.py +3 -1
  128. pygsti/modelmembers/povms/effect.py +3 -5
  129. pygsti/modelmembers/povms/marginalizedpovm.py +3 -81
  130. pygsti/modelmembers/povms/tppovm.py +74 -2
  131. pygsti/modelmembers/states/__init__.py +2 -5
  132. pygsti/modelmembers/states/composedstate.py +0 -317
  133. pygsti/modelmembers/states/computationalstate.py +3 -3
  134. pygsti/modelmembers/states/cptpstate.py +4 -4
  135. pygsti/modelmembers/states/densestate.py +10 -8
  136. pygsti/modelmembers/states/fullpurestate.py +0 -24
  137. pygsti/modelmembers/states/purestate.py +1 -1
  138. pygsti/modelmembers/states/state.py +5 -6
  139. pygsti/modelmembers/states/tpstate.py +28 -10
  140. pygsti/modelmembers/term.py +3 -6
  141. pygsti/modelmembers/torchable.py +50 -0
  142. pygsti/modelpacks/_modelpack.py +1 -1
  143. pygsti/modelpacks/smq1Q_ZN.py +3 -1
  144. pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
  145. pygsti/modelpacks/smq2Q_XY.py +3 -3
  146. pygsti/modelpacks/smq2Q_XYI.py +2 -2
  147. pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
  148. pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
  149. pygsti/modelpacks/smq2Q_XYXX.py +1 -1
  150. pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
  151. pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
  152. pygsti/modelpacks/stdtarget.py +0 -121
  153. pygsti/models/cloudnoisemodel.py +1 -2
  154. pygsti/models/explicitcalc.py +3 -3
  155. pygsti/models/explicitmodel.py +3 -13
  156. pygsti/models/fogistore.py +5 -3
  157. pygsti/models/localnoisemodel.py +1 -2
  158. pygsti/models/memberdict.py +0 -12
  159. pygsti/models/model.py +801 -68
  160. pygsti/models/modelconstruction.py +4 -4
  161. pygsti/models/modelnoise.py +2 -2
  162. pygsti/models/modelparaminterposer.py +1 -1
  163. pygsti/models/oplessmodel.py +1 -1
  164. pygsti/models/qutrit.py +15 -14
  165. pygsti/objectivefns/objectivefns.py +75 -140
  166. pygsti/objectivefns/wildcardbudget.py +2 -7
  167. pygsti/optimize/__init__.py +1 -0
  168. pygsti/optimize/arraysinterface.py +28 -0
  169. pygsti/optimize/customcg.py +0 -12
  170. pygsti/optimize/customlm.py +129 -323
  171. pygsti/optimize/customsolve.py +2 -2
  172. pygsti/optimize/optimize.py +0 -84
  173. pygsti/optimize/simplerlm.py +841 -0
  174. pygsti/optimize/wildcardopt.py +19 -598
  175. pygsti/protocols/confidenceregionfactory.py +28 -14
  176. pygsti/protocols/estimate.py +31 -14
  177. pygsti/protocols/gst.py +238 -142
  178. pygsti/protocols/modeltest.py +19 -12
  179. pygsti/protocols/protocol.py +9 -37
  180. pygsti/protocols/rb.py +450 -79
  181. pygsti/protocols/treenode.py +8 -2
  182. pygsti/protocols/vb.py +108 -206
  183. pygsti/protocols/vbdataframe.py +1 -1
  184. pygsti/report/factory.py +0 -15
  185. pygsti/report/fogidiagram.py +1 -17
  186. pygsti/report/modelfunction.py +12 -3
  187. pygsti/report/mpl_colormaps.py +1 -1
  188. pygsti/report/plothelpers.py +11 -3
  189. pygsti/report/report.py +16 -0
  190. pygsti/report/reportables.py +41 -37
  191. pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
  192. pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
  193. pygsti/report/workspace.py +2 -14
  194. pygsti/report/workspaceplots.py +328 -505
  195. pygsti/tools/basistools.py +9 -36
  196. pygsti/tools/edesigntools.py +124 -96
  197. pygsti/tools/fastcalc.cp310-win_amd64.pyd +0 -0
  198. pygsti/tools/fastcalc.pyx +35 -81
  199. pygsti/tools/internalgates.py +151 -15
  200. pygsti/tools/jamiolkowski.py +5 -5
  201. pygsti/tools/lindbladtools.py +19 -11
  202. pygsti/tools/listtools.py +0 -114
  203. pygsti/tools/matrixmod2.py +1 -1
  204. pygsti/tools/matrixtools.py +173 -339
  205. pygsti/tools/nameddict.py +1 -1
  206. pygsti/tools/optools.py +154 -88
  207. pygsti/tools/pdftools.py +0 -25
  208. pygsti/tools/rbtheory.py +3 -320
  209. pygsti/tools/slicetools.py +64 -12
  210. pyGSTi-0.9.12.dist-info/METADATA +0 -157
  211. pygsti/algorithms/directx.py +0 -711
  212. pygsti/evotypes/qibo/__init__.py +0 -33
  213. pygsti/evotypes/qibo/effectreps.py +0 -78
  214. pygsti/evotypes/qibo/opreps.py +0 -376
  215. pygsti/evotypes/qibo/povmreps.py +0 -98
  216. pygsti/evotypes/qibo/statereps.py +0 -174
  217. pygsti/extras/rb/__init__.py +0 -13
  218. pygsti/extras/rb/benchmarker.py +0 -957
  219. pygsti/extras/rb/dataset.py +0 -378
  220. pygsti/extras/rb/io.py +0 -814
  221. pygsti/extras/rb/simulate.py +0 -1020
  222. pygsti/io/legacyio.py +0 -385
  223. pygsti/modelmembers/povms/denseeffect.py +0 -142
  224. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
  225. {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
@@ -35,7 +35,7 @@ def _vinds_to_int(vinds, vindices_per_int, max_num_vars):
35
35
  return tuple(ret_tup)
36
36
 
37
37
 
38
- class FASTPolynomial(object):
38
+ class Polynomial(object):
39
39
  """
40
40
  A polynomial that behaves like a Python dict of coefficients.
41
41
 
@@ -136,7 +136,7 @@ class FASTPolynomial(object):
136
136
  rep = list_of_polys[0]._rep
137
137
  for p in list_of_polys[1:]:
138
138
  rep = rep.mult(p._rep)
139
- return FASTPolynomial.from_rep(rep)
139
+ return Polynomial.from_rep(rep)
140
140
 
141
141
  def __init__(self, coeffs=None, max_num_vars=100):
142
142
  """
@@ -161,7 +161,7 @@ class FASTPolynomial(object):
161
161
  have (x_0 to x_(`max_num_vars-1`)). This sets the maximum allowed
162
162
  variable index within this polynomial.
163
163
  """
164
- vindices_per_int = FASTPolynomial._vindices_per_int(max_num_vars)
164
+ vindices_per_int = Polynomial._vindices_per_int(max_num_vars)
165
165
 
166
166
  int_coeffs = {_vinds_to_int(k, vindices_per_int, max_num_vars): v for k, v in coeffs.items()}
167
167
  self._rep = _PolynomialRep(int_coeffs, max_num_vars, vindices_per_int)
@@ -245,7 +245,7 @@ class FASTPolynomial(object):
245
245
  del l[l.index(wrt_param)]
246
246
  dcoeffs[tuple(l)] = cnt * coeff
247
247
 
248
- return FASTPolynomial(dcoeffs, self.max_num_vars)
248
+ return Polynomial(dcoeffs, self.max_num_vars)
249
249
 
250
250
  @property
251
251
  def degree(self):
@@ -314,7 +314,7 @@ class FASTPolynomial(object):
314
314
  -------
315
315
  Polynomial
316
316
  """
317
- return FASTPolynomial.from_rep(self._rep.copy())
317
+ return Polynomial.from_rep(self._rep.copy())
318
318
 
319
319
  def map_indices(self, mapfn):
320
320
  """
@@ -335,7 +335,7 @@ class FASTPolynomial(object):
335
335
  -------
336
336
  Polynomial
337
337
  """
338
- return FASTPolynomial({mapfn(k): v for k, v in self.coeffs.items()}, self.max_num_vars)
338
+ return Polynomial({mapfn(k): v for k, v in self.coeffs.items()}, self.max_num_vars)
339
339
 
340
340
  def map_indices_inplace(self, mapfn):
341
341
  """
@@ -421,7 +421,7 @@ class FASTPolynomial(object):
421
421
  Polynomial
422
422
  The polynomial representing self * x.
423
423
  """
424
- return FASTPolynomial.from_rep(self._rep.mult(x._rep))
424
+ return Polynomial.from_rep(self._rep.mult(x._rep))
425
425
 
426
426
  def scale(self, x):
427
427
  """
@@ -488,7 +488,7 @@ class FASTPolynomial(object):
488
488
 
489
489
  def __add__(self, x):
490
490
  newpoly = self.copy()
491
- if isinstance(x, FASTPolynomial):
491
+ if isinstance(x, Polynomial):
492
492
  newpoly._rep.add_inplace(x._rep)
493
493
  else: # assume a scalar that can be added to values
494
494
  newpoly._rep.add_scalar_to_all_coeffs_inplace(x)
@@ -496,14 +496,14 @@ class FASTPolynomial(object):
496
496
 
497
497
  def __iadd__(self, x):
498
498
  """ Does self += x more efficiently """
499
- if isinstance(x, FASTPolynomial):
499
+ if isinstance(x, Polynomial):
500
500
  self._rep.add_inplace(x._rep)
501
501
  else: # assume a scalar that can be added to values
502
502
  self._rep.add_scalar_to_all_coeffs_inplace(x)
503
503
  return self
504
504
 
505
505
  def __mul__(self, x):
506
- if isinstance(x, FASTPolynomial):
506
+ if isinstance(x, Polynomial):
507
507
  return self.mult(x)
508
508
  else: # assume a scalar that can multiply values
509
509
  return self.scalar_mult(x)
@@ -511,23 +511,8 @@ class FASTPolynomial(object):
511
511
  def __rmul__(self, x):
512
512
  return self.__mul__(x)
513
513
 
514
- #Punt for now??
515
- #def __imul__(self, x):
516
- # if isinstance(x, Polynomial):
517
- # newcoeffs = {}
518
- # for k1, v1 in self.items():
519
- # for k2, v2 in x.items():
520
- # k = tuple(sorted(k1 + k2))
521
- # if k in newcoeffs: newcoeffs[k] += v1 * v2
522
- # else: newcoeffs[k] = v1 * v2
523
- # self.clear()
524
- # self.update(newcoeffs)
525
- # else:
526
- # self.scale(x)
527
- # return self
528
-
529
514
  def __pow__(self, n):
530
- ret = FASTPolynomial({(): 1.0}, self.max_num_vars) # max_order updated by mults below
515
+ ret = Polynomial({(): 1.0}, self.max_num_vars) # max_order updated by mults below
531
516
  cur = self
532
517
  for i in range(int(_np.floor(_np.log2(n))) + 1):
533
518
  rem = n % 2 # gets least significant bit (i-th) of n
@@ -555,575 +540,8 @@ class FASTPolynomial(object):
555
540
  return self._rep
556
541
 
557
542
 
558
- Polynomial = FASTPolynomial
559
-
560
-
561
- # class SLOWPolynomial(dict): # REMOVE THIS CLASS (just for reference)
562
- # """
563
- # Encapsulates a polynomial as a subclass of the standard Python dict.
564
- #
565
- # Variables are represented by integer indices, e.g. "2" means "x_2".
566
- # Keys are tuples of variable indices and values are numerical
567
- # coefficients (floating point or complex numbers). To specify a variable
568
- # to some power, its index is repeated in the key-tuple.
569
- #
570
- # E.g. x_0^2 + 3*x_1 + 4 is stored as {(0,0): 1.0, (1,): 3.0, (): 4.0}
571
- #
572
- # Parameters
573
- # ----------
574
- # coeffs : dict
575
- # A dictionary of coefficients. Keys are tuples of integers that
576
- # specify the polynomial term the coefficient value multiplies
577
- # (see above). If None, the zero polynomial (no terms) is created.
578
- #
579
- # max_num_vars : int
580
- # The maximum number of independent variables this polynomial can
581
- # hold. Placing a limit on the number of variables allows more
582
- # compact storage and efficient evaluation of the polynomial.
583
- # """
584
- #
585
- # @classmethod
586
- # def _vindices_per_int(cls, max_num_vars):
587
- # """
588
- # The number of variable indices that fit into a single int when there are at most `max_num_vars` variables.
589
- #
590
- # This quantity is needed to directly construct Polynomial representations
591
- # and is thus useful internally for forward simulators.
592
- #
593
- # Parameters
594
- # ----------
595
- # max_num_vars : int
596
- # The maximum number of independent variables.
597
- #
598
- # Returns
599
- # -------
600
- # int
601
- # """
602
- # return int(_np.floor(PLATFORM_BITS / _np.log2(max_num_vars + 1)))
603
- #
604
- # @classmethod
605
- # def from_rep(cls, rep):
606
- # """
607
- # Creates a Polynomial from a "representation" (essentially a lite-version) of a Polynomial.
608
- #
609
- # Note: usually we only need to convert from full-featured Python objects
610
- # to the lighter-weight "representation" objects. Polynomials are an
611
- # exception, since as the results of probability computations they need
612
- # to be converted back from "representation-form" to "full-form".
613
- #
614
- # Parameters
615
- # ----------
616
- # rep : PolynomialRep
617
- # A polynomial representation.
618
- #
619
- # Returns
620
- # -------
621
- # Polynomial
622
- # """
623
- # max_num_vars = rep.max_num_vars # one of the few/only cases where a rep
624
- # # max_order = rep.max_order # needs to expose some python properties
625
- #
626
- # def int_to_vinds(indx_tup):
627
- # ret = []
628
- # for indx in indx_tup:
629
- # while indx != 0:
630
- # nxt = indx // (max_num_vars + 1)
631
- # i = indx - nxt * (max_num_vars + 1)
632
- # ret.append(i - 1)
633
- # indx = nxt
634
- # #assert(len(ret) <= max_order) #TODO: is this needed anymore?
635
- # return tuple(sorted(ret))
636
- #
637
- # tup_coeff_dict = {int_to_vinds(k): val for k, val in rep.coeffs.items()}
638
- # ret = cls(tup_coeff_dict)
639
- # ret.fastpoly = FASTPolynomial.from_rep(rep)
640
- # ret._check_fast_polynomial()
641
- # return ret
642
- #
643
- # def __init__(self, coeffs=None, max_num_vars=100):
644
- # """
645
- # Initializes a new Polynomial object (a subclass of dict).
646
- #
647
- # Internally (as a dict) a Polynomial represents variables by integer
648
- # indices, e.g. "2" means "x_2". Keys are tuples of variable indices and
649
- # values are numerical coefficients (floating point or complex numbers).
650
- # A variable to a power > 1 has its index repeated in the key-tuple.
651
- #
652
- # E.g. x_0^2 + 3*x_1 + 4 is stored as `{(0,0): 1.0, (1,): 3.0, (): 4.0}`
653
- #
654
- # Parameters
655
- # ----------
656
- # coeffs : dict
657
- # A dictionary of coefficients. Keys are tuples of integers that
658
- # specify the polynomial term the coefficient value multiplies
659
- # (see above). If None, the zero polynomial (no terms) is created.
660
- #
661
- # max_num_vars : int
662
- # The maximum number of independent variables this polynomial can
663
- # hold. Placing a limit on the number of variables allows more
664
- # compact storage and efficient evaluation of the polynomial.
665
- # """
666
- # super(Polynomial, self).__init__()
667
- # if coeffs is not None:
668
- # self.update(coeffs)
669
- # self.max_num_vars = max_num_vars
670
- # self.fastpoly = FASTPolynomial(coeffs, max_num_vars)
671
- # self._check_fast_polynomial()
672
- #
673
- # def _check_fast_polynomial(self, raise_err=True):
674
- # """
675
- # Check that included FASTPolynomial has remained in-sync with this one.
676
- #
677
- # This is purely for debugging, to ensure that the FASTPolynomial
678
- # class implements its operations correctly.
679
- #
680
- # Parameters
681
- # ----------
682
- # raise_err : bool, optional
683
- # Whether to raise an AssertionError if the check fails.
684
- #
685
- # Returns
686
- # -------
687
- # bool
688
- # Whether or not the check has succeeded (True if the
689
- # fast and slow implementations are in sync).
690
- # """
691
- # if set(self.fastpoly.coeffs.keys()) != set(self.keys()):
692
- # print("FAST", self.fastpoly.coeffs, " != SLOW", dict(self))
693
- # if raise_err: assert(False), "STOP"
694
- # return False
695
- # for k in self.fastpoly.coeffs.keys():
696
- # if not _np.isclose(self.fastpoly.coeffs[k], self[k]):
697
- # print("FAST", self.fastpoly.coeffs, " != SLOW", dict(self))
698
- # if raise_err: assert(False), "STOP"
699
- # return False
700
- # if self.max_num_vars != self.fastpoly.max_num_vars:
701
- # print("#Var mismatch: FAST", self.fastpoly.max_num_vars, " != SLOW", self.max_num_vars)
702
- # if raise_err: assert(False), "STOP"
703
- # return False
704
- #
705
- # return True
706
- #
707
- # def deriv(self, wrt_param):
708
- # """
709
- # Take the derivative of this Polynomial with respect to a single variable.
710
- #
711
- # The result is another Polynomial.
712
- #
713
- # E.g. deriv(x_2^3 + 3*x_1, wrt_param=2) = 3x^2
714
- #
715
- # Parameters
716
- # ----------
717
- # wrt_param : int
718
- # The variable index to differentiate with respect to.
719
- # E.g. "4" means "differentiate w.r.t. x_4".
720
- #
721
- # Returns
722
- # -------
723
- # Polynomial
724
- # """
725
- # dcoeffs = {}
726
- # for ivar, coeff in self.items():
727
- # cnt = float(ivar.count(wrt_param))
728
- # if cnt > 0:
729
- # l = list(ivar)
730
- # del l[l.index(wrt_param)]
731
- # dcoeffs[tuple(l)] = cnt * coeff
732
- #
733
- # ret = Polynomial(dcoeffs, self.max_num_vars)
734
- # ret.fastpoly = self.fastpoly.deriv(wrt_param)
735
- # ret._check_fast_polynomial()
736
- # return ret
737
- #
738
- # def degree(self):
739
- # """
740
- # The largest sum-of-exponents for any term (monomial) within this polynomial.
741
- #
742
- # E.g. for x_2^3 + x_1^2*x_0^2 has degree 4.
743
- #
744
- # Returns
745
- # -------
746
- # int
747
- # """
748
- # ret = max((len(k) for k in self), default=0)
749
- # assert(self.fastpoly.degree == ret)
750
- # self._check_fast_polynomial()
751
- # return ret
752
- #
753
- # def evaluate(self, variable_values):
754
- # """
755
- # Evaluate this polynomial for a given set of variable values.
756
- #
757
- # Parameters
758
- # ----------
759
- # variable_values : array-like
760
- # An object that can be indexed so that `variable_values[i]` gives the
761
- # numerical value for i-th variable (x_i).
762
- #
763
- # Returns
764
- # -------
765
- # float or complex
766
- # Depending on the types of the coefficients and `variable_values`.
767
- # """
768
- # #FUTURE: make this function smarter (Russian peasant)
769
- # ret = 0
770
- # for ivar, coeff in self.items():
771
- # ret += coeff * _np.prod([variable_values[i] for i in ivar])
772
- # assert(_np.isclose(ret, self.fastpoly.evaluate(variable_values)))
773
- # self._check_fast_polynomial()
774
- # return ret
775
- #
776
- # def compact(self, complex_coeff_tape=True):
777
- # """
778
- # Generate a compact form of this polynomial designed for fast evaluation.
779
- #
780
- # The resulting "tapes" can be evaluated using
781
- # :func:`opcalc.bulk_eval_compact_polynomials`.
782
- #
783
- # Parameters
784
- # ----------
785
- # complex_coeff_tape : bool, optional
786
- # Whether the `ctape` returned array is forced to be of complex type.
787
- # If False, the real part of all coefficients is taken (even if they're
788
- # complex).
789
- #
790
- # Returns
791
- # -------
792
- # vtape, ctape : numpy.ndarray
793
- # These two 1D arrays specify an efficient means for evaluating this
794
- # polynomial.
795
- # """
796
- # #if force_complex:
797
- # # iscomplex = True
798
- # #else:
799
- # # iscomplex = any([abs(_np.imag(x)) > 1e-12 for x in self.values()])
800
- # iscomplex = complex_coeff_tape
801
- #
802
- # nTerms = len(self)
803
- # nVarIndices = sum(map(len, self.keys()))
804
- # vtape = _np.empty(1 + nTerms + nVarIndices, _np.int64) # "variable" tape
805
- # ctape = _np.empty(nTerms, complex if iscomplex else 'd') # "coefficient tape"
806
- #
807
- # i = 0
808
- # vtape[i] = nTerms; i += 1
809
- # for iTerm, k in enumerate(sorted(self.keys())):
810
- # l = len(k)
811
- # ctape[iTerm] = self[k] if iscomplex else _np.real(self[k])
812
- # vtape[i] = l; i += 1
813
- # vtape[i:i + l] = k; i += l
814
- # assert(i == len(vtape)), "Logic Error!"
815
- # fast_vtape, fast_ctape = self.fastpoly.compact(iscomplex)
816
- # assert(_np.allclose(fast_vtape, vtape) and _np.allclose(fast_ctape, ctape))
817
- # self._check_fast_polynomial()
818
- # return vtape, ctape
819
- #
820
- # def copy(self):
821
- # """
822
- # Returns a copy of this polynomial.
823
- #
824
- # Returns
825
- # -------
826
- # Polynomial
827
- # """
828
- # fast_cpy = self.fastpoly.copy()
829
- # ret = Polynomial(self, self.max_num_vars)
830
- # ret.fastpoly = fast_cpy
831
- # ret._check_fast_polynomial()
832
- # return ret
833
- #
834
- # def map_indices(self, mapfn):
835
- # """
836
- # Performs a bulk find & replace on this polynomial's variable indices.
837
- #
838
- # This is useful when the variable indices have external significance
839
- # (like being the indices of a gate's parameters) and one want to convert
840
- # to another set of indices (like a parent model's parameters).
841
- #
842
- # Parameters
843
- # ----------
844
- # mapfn : function
845
- # A function that takes as input an "old" variable-index-tuple
846
- # (a key of this Polynomial) and returns the updated "new"
847
- # variable-index-tuple.
848
- #
849
- # Returns
850
- # -------
851
- # Polynomial
852
- # """
853
- # ret = Polynomial({mapfn(k): v for k, v in self.items()}, self.max_num_vars)
854
- # ret.fastpoly = self.fastpoly.map_indices(mapfn)
855
- # self._check_fast_polynomial()
856
- # ret._check_fast_polynomial()
857
- # return ret
858
- #
859
- # def map_indices_inplace(self, mapfn):
860
- # """
861
- # Performs an in-place find & replace on this polynomial's variable indices.
862
- #
863
- # This is useful when the variable indices have external significance
864
- # (like being the indices of a gate's parameters) and one want to convert
865
- # to another set of indices (like a parent model's parameters).
866
- #
867
- # Parameters
868
- # ----------
869
- # mapfn : function
870
- # A function that takes as input an "old" variable-index-tuple
871
- # (a key of this Polynomial) and returns the updated "new"
872
- # variable-index-tuple.
873
- #
874
- # Returns
875
- # -------
876
- # None
877
- # """
878
- # self._check_fast_polynomial()
879
- # new_items = {mapfn(k): v for k, v in self.items()}
880
- # self.clear()
881
- # self.update(new_items)
882
- # self.fastpoly.map_indices_inplace(mapfn)
883
- # self._check_fast_polynomial()
884
- #
885
- # def mult(self, x):
886
- # """
887
- # Multiplies this polynomial by another polynomial `x`.
888
- #
889
- # Parameters
890
- # ----------
891
- # x : Polynomial
892
- # The polynomial to multiply by.
893
- #
894
- # Returns
895
- # -------
896
- # Polynomial
897
- # The polynomial representing self * x.
898
- # """
899
- # newpoly = Polynomial({}, self.max_num_vars)
900
- # for k1, v1 in self.items():
901
- # for k2, v2 in x.items():
902
- # k = tuple(sorted(k1 + k2))
903
- # if k in newpoly: newpoly[k] += v1 * v2
904
- # else: newpoly[k] = v1 * v2
905
- #
906
- # newpoly.fastpoly = self.fastpoly.mult(x.fastpoly)
907
- # self._check_fast_polynomial()
908
- # newpoly._check_fast_polynomial()
909
- # return newpoly
910
- #
911
- # def scale(self, x):
912
- # """
913
- # Scale this polynomial by `x` (multiply all coefficients by `x`).
914
- #
915
- # Parameters
916
- # ----------
917
- # x : float or complex
918
- # The value to scale by.
919
- #
920
- # Returns
921
- # -------
922
- # None
923
- # """
924
- # # assume a scalar that can multiply values
925
- # for k in tuple(self.keys()): # I think the tuple() might speed things up (why?)
926
- # self[k] *= x
927
- # self.fastpoly.scale(x)
928
- # self._check_fast_polynomial()
929
- #
930
- # def scalar_mult(self, x):
931
- # """
932
- # Multiplies this polynomial by a scalar `x`.
933
- #
934
- # Parameters
935
- # ----------
936
- # x : float or complex
937
- # The value to multiply by.
938
- #
939
- # Returns
940
- # -------
941
- # Polynomial
942
- # """
943
- # newpoly = self.copy()
944
- # newpoly.scale(x)
945
- # self._check_fast_polynomial()
946
- # newpoly._check_fast_polynomial()
947
- # return newpoly
948
- #
949
- # def __str__(self):
950
- # def fmt(x):
951
- # if abs(_np.imag(x)) > 1e-6:
952
- # if abs(_np.real(x)) > 1e-6: return "(%.3f+%.3fj)" % (x.real, x.imag)
953
- # else: return "(%.3fj)" % x.imag
954
- # else: return "%.3f" % x.real
955
- #
956
- # termstrs = []
957
- # sorted_keys = sorted(list(self.keys()))
958
- # for k in sorted_keys:
959
- # varstr = ""; last_i = None; n = 1
960
- # for i in sorted(k):
961
- # if i == last_i: n += 1
962
- # elif last_i is not None:
963
- # varstr += "x%d%s" % (last_i, ("^%d" % n) if n > 1 else "")
964
- # n = 1
965
- # last_i = i
966
- # if last_i is not None:
967
- # varstr += "x%d%s" % (last_i, ("^%d" % n) if n > 1 else "")
968
- # #print("DB: k = ",k, " varstr = ",varstr)
969
- # if abs(self[k]) > 1e-4:
970
- # termstrs.append("%s%s" % (fmt(self[k]), varstr))
971
- #
972
- # self._check_fast_polynomial()
973
- # if len(termstrs) > 0:
974
- # return " + ".join(termstrs)
975
- # else: return "0"
976
- #
977
- # def __repr__(self):
978
- # return "Poly[ " + str(self) + " ]"
979
- #
980
- # def __add__(self, x):
981
- # newpoly = self.copy()
982
- # if isinstance(x, Polynomial):
983
- # for k, v in x.items():
984
- # if k in newpoly: newpoly[k] += v
985
- # else: newpoly[k] = v
986
- # newpoly.fastpoly = self.fastpoly + x.fastpoly
987
- # else: # assume a scalar that can be added to values
988
- # for k in newpoly:
989
- # newpoly[k] += x
990
- # newpoly.fastpoly = self.fastpoly + x
991
- # self._check_fast_polynomial()
992
- # newpoly._check_fast_polynomial()
993
- # return newpoly
994
- #
995
- # def __iadd__(self, x):
996
- # """ Does self += x more efficiently """
997
- # if isinstance(x, Polynomial):
998
- # for k, v in x.items():
999
- # try:
1000
- # self[k] += v
1001
- # except KeyError:
1002
- # self[k] = v
1003
- # self.fastpoly += x.fastpoly
1004
- # else: # assume a scalar that can be added to values
1005
- # for k in self:
1006
- # self[k] += x
1007
- # self.fastpoly += x
1008
- # self._check_fast_polynomial()
1009
- # return self
1010
- #
1011
- # def __mul__(self, x):
1012
- # #if isinstance(x, Polynomial):
1013
- # # newpoly = Polynomial()
1014
- # # for k1,v1 in self.items():
1015
- # # for k2,v2 in x.items():
1016
- # # k = tuple(sorted(k1+k2))
1017
- # # if k in newpoly: newpoly[k] += v1*v2
1018
- # # else: newpoly[k] = v1*v2
1019
- # #else:
1020
- # # # assume a scalar that can multiply values
1021
- # # newpoly = self.copy()
1022
- # # for k in newpoly:
1023
- # # newpoly[k] *= x
1024
- # #return newpoly
1025
- # if isinstance(x, Polynomial):
1026
- # ret = self.mult(x)
1027
- # else: # assume a scalar that can multiply values
1028
- # ret = self.scalar_mult(x)
1029
- # self._check_fast_polynomial()
1030
- # ret._check_fast_polynomial()
1031
- # return ret
1032
- #
1033
- # def __rmul__(self, x):
1034
- # return self.__mul__(x)
1035
- #
1036
- # def __imul__(self, x):
1037
- # self._check_fast_polynomial()
1038
- # if isinstance(x, Polynomial):
1039
- # x._check_fast_polynomial()
1040
- # newcoeffs = {}
1041
- # for k1, v1 in self.items():
1042
- # for k2, v2 in x.items():
1043
- # k = tuple(sorted(k1 + k2))
1044
- # if k in newcoeffs: newcoeffs[k] += v1 * v2
1045
- # else: newcoeffs[k] = v1 * v2
1046
- # self.clear()
1047
- # self.update(newcoeffs)
1048
- # self.fastpoly *= x.fastpoly
1049
- # self._check_fast_polynomial()
1050
- # else:
1051
- # self.scale(x)
1052
- # self._check_fast_polynomial()
1053
- # return self
1054
- #
1055
- # def __pow__(self, n):
1056
- # ret = Polynomial({(): 1.0}, self.max_num_vars) # max_order updated by mults below
1057
- # cur = self
1058
- # for i in range(int(_np.floor(_np.log2(n))) + 1):
1059
- # rem = n % 2 # gets least significant bit (i-th) of n
1060
- # if rem == 1: ret *= cur # add current power of x (2^i) if needed
1061
- # cur = cur * cur # current power *= 2
1062
- # n //= 2 # shift bits of n right
1063
- # ret.fastpoly = self.fastpoly ** n
1064
- # ret._check_fast_polynomial()
1065
- # self._check_fast_polynomial()
1066
- # return ret
1067
- #
1068
- # def __copy__(self):
1069
- # ret = self.copy()
1070
- # ret._check_fast_polynomial()
1071
- # self._check_fast_polynomial()
1072
- # return ret
1073
- #
1074
- # def to_rep(self):
1075
- # """
1076
- # Construct a representation of this polynomial.
1077
- #
1078
- # "Representations" are lightweight versions of objects used to improve
1079
- # the efficiency of intensely computational tasks. Note that Polynomial
1080
- # representations must have the same `max_order` and `max_num_vars` in
1081
- # order to interact with each other (add, multiply, etc.).
1082
- #
1083
- # Parameters
1084
- # ----------
1085
- # max_num_vars : int, optional
1086
- # The maximum number of variables the represenatation is allowed to
1087
- # have (x_0 to x_(`max_num_vars-1`)). This sets the maximum allowed
1088
- # variable index within the representation.
1089
- #
1090
- # Returns
1091
- # -------
1092
- # PolynomialRep
1093
- # """
1094
- # # Set max_num_vars (determines based on coeffs if necessary)
1095
- # max_num_vars = self.max_num_vars
1096
- # default_max_vars = 0 if len(self) == 0 else \
1097
- # max([(max(k) + 1 if k else 0) for k in self.keys()])
1098
- # if max_num_vars is None:
1099
- # max_num_vars = default_max_vars
1100
- # else:
1101
- # assert(default_max_vars <= max_num_vars)
1102
- #
1103
- # vindices_per_int = Polynomial._vindices_per_int(max_num_vars)
1104
- #
1105
- # def vinds_to_int(vinds):
1106
- # """ Convert tuple index of ints to single int given max_numvars """
1107
- # ints_in_key = int(_np.ceil(len(vinds) / vindices_per_int))
1108
- # ret_tup = []
1109
- # for k in range(ints_in_key):
1110
- # ret = 0; m = 1
1111
- # for i in vinds[k * vindices_per_int:(k + 1) * vindices_per_int]: # last tuple index=most significant
1112
- # assert(i < max_num_vars), "Variable index exceed maximum!"
1113
- # ret += (i + 1) * m
1114
- # m *= max_num_vars + 1
1115
- # assert(ret >= 0), "vinds = %s -> %d!!" % (str(vinds), ret)
1116
- # ret_tup.append(ret)
1117
- # return tuple(ret_tup)
1118
- #
1119
- # int_coeffs = {vinds_to_int(k): v for k, v in self.items()}
1120
- #
1121
- # # (max_num_vars+1) ** vindices_per_int <= 2**PLATFORM_BITS, so:
1122
- # # vindices_per_int * log2(max_num_vars+1) <= PLATFORM_BITS
1123
- # vindices_per_int = int(_np.floor(PLATFORM_BITS / _np.log2(max_num_vars + 1)))
1124
- # self._check_fast_polynomial()
1125
- #
1126
- # return _PolynomialRep(int_coeffs, max_num_vars, vindices_per_int)
543
+ FASTPolynomial = Polynomial
544
+ # ^ That alias is deprecated and should be removed.
1127
545
 
1128
546
 
1129
547
  def bulk_load_compact_polynomials(vtape, ctape, keep_compact=False, max_num_vars=100):