pyGSTi 0.9.12__cp38-cp38-win32.whl → 0.9.13__cp38-cp38-win32.whl
Sign up to get free protection for your applications and to get access to all the features.
- pyGSTi-0.9.13.dist-info/METADATA +185 -0
- {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +211 -220
- {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/WHEEL +1 -1
- pygsti/_version.py +2 -2
- pygsti/algorithms/contract.py +1 -1
- pygsti/algorithms/core.py +62 -35
- pygsti/algorithms/fiducialpairreduction.py +95 -110
- pygsti/algorithms/fiducialselection.py +17 -8
- pygsti/algorithms/gaugeopt.py +2 -2
- pygsti/algorithms/germselection.py +87 -77
- pygsti/algorithms/mirroring.py +0 -388
- pygsti/algorithms/randomcircuit.py +165 -1333
- pygsti/algorithms/rbfit.py +0 -234
- pygsti/baseobjs/basis.py +94 -396
- pygsti/baseobjs/errorgenbasis.py +0 -132
- pygsti/baseobjs/errorgenspace.py +0 -10
- pygsti/baseobjs/label.py +52 -168
- pygsti/baseobjs/opcalc/fastopcalc.cp38-win32.pyd +0 -0
- pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
- pygsti/baseobjs/polynomial.py +13 -595
- pygsti/baseobjs/protectedarray.py +72 -132
- pygsti/baseobjs/statespace.py +1 -0
- pygsti/circuits/__init__.py +1 -1
- pygsti/circuits/circuit.py +753 -504
- pygsti/circuits/circuitconstruction.py +0 -4
- pygsti/circuits/circuitlist.py +47 -5
- pygsti/circuits/circuitparser/__init__.py +8 -8
- pygsti/circuits/circuitparser/fastcircuitparser.cp38-win32.pyd +0 -0
- pygsti/circuits/circuitstructure.py +3 -3
- pygsti/circuits/cloudcircuitconstruction.py +27 -14
- pygsti/data/datacomparator.py +4 -9
- pygsti/data/dataset.py +51 -46
- pygsti/data/hypothesistest.py +0 -7
- pygsti/drivers/bootstrap.py +0 -49
- pygsti/drivers/longsequence.py +46 -10
- pygsti/evotypes/basereps_cython.cp38-win32.pyd +0 -0
- pygsti/evotypes/chp/opreps.py +0 -61
- pygsti/evotypes/chp/statereps.py +0 -32
- pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
- pygsti/evotypes/densitymx/effectreps.cp38-win32.pyd +0 -0
- pygsti/evotypes/densitymx/effectreps.pyx +1 -1
- pygsti/evotypes/densitymx/opreps.cp38-win32.pyd +0 -0
- pygsti/evotypes/densitymx/opreps.pyx +2 -2
- pygsti/evotypes/densitymx/statereps.cp38-win32.pyd +0 -0
- pygsti/evotypes/densitymx/statereps.pyx +1 -1
- pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
- pygsti/evotypes/densitymx_slow/opreps.py +16 -23
- pygsti/evotypes/densitymx_slow/statereps.py +10 -3
- pygsti/evotypes/evotype.py +39 -2
- pygsti/evotypes/stabilizer/effectreps.cp38-win32.pyd +0 -0
- pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
- pygsti/evotypes/stabilizer/opreps.cp38-win32.pyd +0 -0
- pygsti/evotypes/stabilizer/opreps.pyx +0 -4
- pygsti/evotypes/stabilizer/statereps.cp38-win32.pyd +0 -0
- pygsti/evotypes/stabilizer/statereps.pyx +1 -5
- pygsti/evotypes/stabilizer/termreps.cp38-win32.pyd +0 -0
- pygsti/evotypes/stabilizer/termreps.pyx +0 -7
- pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
- pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
- pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
- pygsti/evotypes/statevec/effectreps.cp38-win32.pyd +0 -0
- pygsti/evotypes/statevec/effectreps.pyx +1 -1
- pygsti/evotypes/statevec/opreps.cp38-win32.pyd +0 -0
- pygsti/evotypes/statevec/opreps.pyx +2 -2
- pygsti/evotypes/statevec/statereps.cp38-win32.pyd +0 -0
- pygsti/evotypes/statevec/statereps.pyx +1 -1
- pygsti/evotypes/statevec/termreps.cp38-win32.pyd +0 -0
- pygsti/evotypes/statevec/termreps.pyx +0 -7
- pygsti/evotypes/statevec_slow/effectreps.py +0 -3
- pygsti/evotypes/statevec_slow/opreps.py +0 -5
- pygsti/extras/__init__.py +0 -1
- pygsti/extras/drift/signal.py +1 -1
- pygsti/extras/drift/stabilityanalyzer.py +3 -1
- pygsti/extras/interpygate/__init__.py +12 -0
- pygsti/extras/interpygate/core.py +0 -36
- pygsti/extras/interpygate/process_tomography.py +44 -10
- pygsti/extras/rpe/rpeconstruction.py +0 -2
- pygsti/forwardsims/__init__.py +1 -0
- pygsti/forwardsims/forwardsim.py +50 -93
- pygsti/forwardsims/mapforwardsim.py +78 -20
- pygsti/forwardsims/mapforwardsim_calc_densitymx.cp38-win32.pyd +0 -0
- pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
- pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
- pygsti/forwardsims/matrixforwardsim.py +72 -17
- pygsti/forwardsims/termforwardsim.py +9 -111
- pygsti/forwardsims/termforwardsim_calc_stabilizer.cp38-win32.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.cp38-win32.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
- pygsti/forwardsims/torchfwdsim.py +265 -0
- pygsti/forwardsims/weakforwardsim.py +2 -2
- pygsti/io/__init__.py +1 -2
- pygsti/io/mongodb.py +0 -2
- pygsti/io/stdinput.py +6 -22
- pygsti/layouts/copalayout.py +10 -12
- pygsti/layouts/distlayout.py +0 -40
- pygsti/layouts/maplayout.py +103 -25
- pygsti/layouts/matrixlayout.py +99 -60
- pygsti/layouts/prefixtable.py +1534 -52
- pygsti/layouts/termlayout.py +1 -1
- pygsti/modelmembers/instruments/instrument.py +3 -3
- pygsti/modelmembers/instruments/tpinstrument.py +2 -2
- pygsti/modelmembers/modelmember.py +0 -17
- pygsti/modelmembers/operations/__init__.py +3 -4
- pygsti/modelmembers/operations/affineshiftop.py +206 -0
- pygsti/modelmembers/operations/composederrorgen.py +1 -1
- pygsti/modelmembers/operations/composedop.py +1 -24
- pygsti/modelmembers/operations/denseop.py +5 -5
- pygsti/modelmembers/operations/eigpdenseop.py +2 -2
- pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
- pygsti/modelmembers/operations/embeddedop.py +0 -1
- pygsti/modelmembers/operations/experrorgenop.py +5 -2
- pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
- pygsti/modelmembers/operations/fullcptpop.py +2 -2
- pygsti/modelmembers/operations/fulltpop.py +28 -6
- pygsti/modelmembers/operations/fullunitaryop.py +5 -4
- pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
- pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
- pygsti/modelmembers/operations/linearop.py +7 -27
- pygsti/modelmembers/operations/opfactory.py +1 -1
- pygsti/modelmembers/operations/repeatedop.py +1 -24
- pygsti/modelmembers/operations/staticstdop.py +1 -1
- pygsti/modelmembers/povms/__init__.py +3 -3
- pygsti/modelmembers/povms/basepovm.py +7 -36
- pygsti/modelmembers/povms/complementeffect.py +4 -9
- pygsti/modelmembers/povms/composedeffect.py +0 -320
- pygsti/modelmembers/povms/computationaleffect.py +1 -1
- pygsti/modelmembers/povms/computationalpovm.py +3 -1
- pygsti/modelmembers/povms/effect.py +3 -5
- pygsti/modelmembers/povms/marginalizedpovm.py +3 -81
- pygsti/modelmembers/povms/tppovm.py +74 -2
- pygsti/modelmembers/states/__init__.py +2 -5
- pygsti/modelmembers/states/composedstate.py +0 -317
- pygsti/modelmembers/states/computationalstate.py +3 -3
- pygsti/modelmembers/states/cptpstate.py +4 -4
- pygsti/modelmembers/states/densestate.py +10 -8
- pygsti/modelmembers/states/fullpurestate.py +0 -24
- pygsti/modelmembers/states/purestate.py +1 -1
- pygsti/modelmembers/states/state.py +5 -6
- pygsti/modelmembers/states/tpstate.py +28 -10
- pygsti/modelmembers/term.py +3 -6
- pygsti/modelmembers/torchable.py +50 -0
- pygsti/modelpacks/_modelpack.py +1 -1
- pygsti/modelpacks/smq1Q_ZN.py +3 -1
- pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
- pygsti/modelpacks/smq2Q_XY.py +3 -3
- pygsti/modelpacks/smq2Q_XYI.py +2 -2
- pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
- pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
- pygsti/modelpacks/smq2Q_XYXX.py +1 -1
- pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
- pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
- pygsti/modelpacks/stdtarget.py +0 -121
- pygsti/models/cloudnoisemodel.py +1 -2
- pygsti/models/explicitcalc.py +3 -3
- pygsti/models/explicitmodel.py +3 -13
- pygsti/models/fogistore.py +5 -3
- pygsti/models/localnoisemodel.py +1 -2
- pygsti/models/memberdict.py +0 -12
- pygsti/models/model.py +801 -68
- pygsti/models/modelconstruction.py +4 -4
- pygsti/models/modelnoise.py +2 -2
- pygsti/models/modelparaminterposer.py +1 -1
- pygsti/models/oplessmodel.py +1 -1
- pygsti/models/qutrit.py +15 -14
- pygsti/objectivefns/objectivefns.py +75 -140
- pygsti/objectivefns/wildcardbudget.py +2 -7
- pygsti/optimize/__init__.py +1 -0
- pygsti/optimize/arraysinterface.py +28 -0
- pygsti/optimize/customcg.py +0 -12
- pygsti/optimize/customlm.py +129 -323
- pygsti/optimize/customsolve.py +2 -2
- pygsti/optimize/optimize.py +0 -84
- pygsti/optimize/simplerlm.py +841 -0
- pygsti/optimize/wildcardopt.py +19 -598
- pygsti/protocols/confidenceregionfactory.py +28 -14
- pygsti/protocols/estimate.py +31 -14
- pygsti/protocols/gst.py +238 -142
- pygsti/protocols/modeltest.py +19 -12
- pygsti/protocols/protocol.py +9 -37
- pygsti/protocols/rb.py +450 -79
- pygsti/protocols/treenode.py +8 -2
- pygsti/protocols/vb.py +108 -206
- pygsti/protocols/vbdataframe.py +1 -1
- pygsti/report/factory.py +0 -15
- pygsti/report/fogidiagram.py +1 -17
- pygsti/report/modelfunction.py +12 -3
- pygsti/report/mpl_colormaps.py +1 -1
- pygsti/report/plothelpers.py +11 -3
- pygsti/report/report.py +16 -0
- pygsti/report/reportables.py +41 -37
- pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
- pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
- pygsti/report/workspace.py +2 -14
- pygsti/report/workspaceplots.py +328 -505
- pygsti/tools/basistools.py +9 -36
- pygsti/tools/edesigntools.py +124 -96
- pygsti/tools/fastcalc.cp38-win32.pyd +0 -0
- pygsti/tools/fastcalc.pyx +35 -81
- pygsti/tools/internalgates.py +151 -15
- pygsti/tools/jamiolkowski.py +5 -5
- pygsti/tools/lindbladtools.py +19 -11
- pygsti/tools/listtools.py +0 -114
- pygsti/tools/matrixmod2.py +1 -1
- pygsti/tools/matrixtools.py +173 -339
- pygsti/tools/nameddict.py +1 -1
- pygsti/tools/optools.py +154 -88
- pygsti/tools/pdftools.py +0 -25
- pygsti/tools/rbtheory.py +3 -320
- pygsti/tools/slicetools.py +64 -12
- pyGSTi-0.9.12.dist-info/METADATA +0 -157
- pygsti/algorithms/directx.py +0 -711
- pygsti/evotypes/qibo/__init__.py +0 -33
- pygsti/evotypes/qibo/effectreps.py +0 -78
- pygsti/evotypes/qibo/opreps.py +0 -376
- pygsti/evotypes/qibo/povmreps.py +0 -98
- pygsti/evotypes/qibo/statereps.py +0 -174
- pygsti/extras/rb/__init__.py +0 -13
- pygsti/extras/rb/benchmarker.py +0 -957
- pygsti/extras/rb/dataset.py +0 -378
- pygsti/extras/rb/io.py +0 -814
- pygsti/extras/rb/simulate.py +0 -1020
- pygsti/io/legacyio.py +0 -385
- pygsti/modelmembers/povms/denseeffect.py +0 -142
- {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
- {pyGSTi-0.9.12.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
pygsti/baseobjs/basis.py
CHANGED
@@ -14,6 +14,7 @@ import copy as _copy
|
|
14
14
|
import itertools as _itertools
|
15
15
|
import warnings as _warnings
|
16
16
|
from functools import lru_cache
|
17
|
+
from typing import Union, Tuple, List
|
17
18
|
|
18
19
|
import numpy as _np
|
19
20
|
import scipy.sparse as _sps
|
@@ -154,126 +155,103 @@ class Basis(_NicelySerializable):
|
|
154
155
|
The "vectors" of this basis, always 1D (sparse or dense) arrays.
|
155
156
|
"""
|
156
157
|
|
158
|
+
# Implementation note: casting functions are classmethods, but current implementations
|
159
|
+
# could be static methods.
|
160
|
+
|
157
161
|
@classmethod
|
158
|
-
def
|
159
|
-
|
160
|
-
|
162
|
+
def cast_from_name_and_statespace(cls, name: str, state_space: _StateSpace, sparse=None):
|
163
|
+
tpbBases = []
|
164
|
+
block_labels = state_space.tensor_product_blocks_labels
|
165
|
+
if len(block_labels) == 1 and len(block_labels[0]) == 1:
|
166
|
+
# Special case when we can actually pipe state_space to the BuiltinBasis constructor
|
167
|
+
lbl = block_labels[0][0]
|
168
|
+
nm = name if (state_space.label_type(lbl) == 'Q') else 'cl'
|
169
|
+
tpbBases.append(BuiltinBasis(nm, state_space, sparse))
|
170
|
+
else:
|
171
|
+
#TODO: add methods to StateSpace that can extract a sub-*StateSpace* object for a given label.
|
172
|
+
for tpbLabels in block_labels:
|
173
|
+
if len(tpbLabels) == 1:
|
174
|
+
nm = name if (state_space.label_type(tpbLabels[0]) == 'Q') else 'cl'
|
175
|
+
tpbBases.append(BuiltinBasis(nm, state_space.label_dimension(tpbLabels[0]), sparse))
|
176
|
+
else:
|
177
|
+
tpbBases.append(TensorProdBasis([
|
178
|
+
BuiltinBasis(name if (state_space.label_type(l) == 'Q') else 'cl',
|
179
|
+
state_space.label_dimension(l), sparse) for l in tpbLabels]))
|
180
|
+
if len(tpbBases) == 1:
|
181
|
+
return tpbBases[0]
|
182
|
+
else:
|
183
|
+
return DirectSumBasis(tpbBases)
|
161
184
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
dim : int or StateSpace, optional
|
174
|
-
The dimension of the basis to create. Sometimes this can be
|
175
|
-
inferred based on `name_or_basis_or_matrices`, other times it must
|
176
|
-
be supplied. This is the dimension of the space that this basis
|
177
|
-
fully or partially spans. This is equal to the number of basis
|
178
|
-
elements in a "full" (ordinary) basis. When a `StateSpace`
|
179
|
-
object is given, a more detailed direct-sum-of-tensor-product-blocks
|
180
|
-
structure for the state space (rather than a single dimension) is
|
181
|
-
described, and a basis is produced for this space. For instance,
|
182
|
-
a `DirectSumBasis` basis of `TensorProdBasis` components can result
|
183
|
-
when there are multiple tensor-product blocks and these blocks
|
184
|
-
consist of multiple factors.
|
185
|
+
@classmethod
|
186
|
+
def cast_from_name_and_dims(cls, name: str, dim: Union[int,list,tuple], sparse=None):
|
187
|
+
if isinstance(dim, (list, tuple)): # list/tuple of block dimensions
|
188
|
+
tpbBases = []
|
189
|
+
for tpbDim in dim:
|
190
|
+
if isinstance(tpbDim, (list, tuple)): # list/tuple of tensor-product dimensions
|
191
|
+
tpbBases.append(
|
192
|
+
TensorProdBasis([BuiltinBasis(name, factorDim, sparse) for factorDim in tpbDim]))
|
193
|
+
else:
|
194
|
+
tpbBases.append(BuiltinBasis(name, tpbDim, sparse))
|
185
195
|
|
186
|
-
|
187
|
-
|
188
|
-
|
196
|
+
if len(tpbBases) == 1:
|
197
|
+
return tpbBases[0]
|
198
|
+
else:
|
199
|
+
return DirectSumBasis(tpbBases)
|
200
|
+
else:
|
201
|
+
return BuiltinBasis(name, dim, sparse)
|
202
|
+
|
203
|
+
@classmethod
|
204
|
+
def cast_from_basis(cls, basis, dim=None, sparse=None):
|
205
|
+
#then just check to make sure consistent with `dim` & `sparse`
|
206
|
+
if dim is not None:
|
207
|
+
if isinstance(dim, _StateSpace):
|
208
|
+
state_space = dim
|
209
|
+
if hasattr(basis, 'state_space'): # TODO - should *all* basis objects have a state_space?
|
210
|
+
assert(state_space.is_compatible_with(basis.state_space)), \
|
211
|
+
"Basis object has incompatible state space: %s != %s" % (str(state_space),
|
212
|
+
str(basis.state_space))
|
213
|
+
else: # assume dim is an integer
|
214
|
+
assert(dim == basis.dim or dim == basis.elsize), \
|
215
|
+
"Basis object has unexpected dimension: %d != %d or %d" % (dim, basis.dim, basis.elsize)
|
216
|
+
if sparse is not None:
|
217
|
+
basis = basis.with_sparsity(sparse)
|
218
|
+
return basis
|
189
219
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
220
|
+
@classmethod
|
221
|
+
def cast_from_arrays(cls, arrays, dim=None, sparse=None):
|
222
|
+
b = ExplicitBasis(arrays, sparse=sparse)
|
223
|
+
if dim is not None:
|
224
|
+
assert(dim == b.dim), "Created explicit basis has unexpected dimension: %d vs %d" % (dim, b.dim)
|
225
|
+
if sparse is not None:
|
226
|
+
assert(sparse == b.sparse), "Basis object has unexpected sparsity: %s" % (b.sparse)
|
227
|
+
return b
|
194
228
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
if name_or_basis_or_matrices is None: # special case of empty basis
|
202
|
-
return ExplicitBasis([], [], "*Empty*", "Empty (0-element) basis", False, sparse) # empty basis
|
203
|
-
elif isinstance(name_or_basis_or_matrices, Basis):
|
204
|
-
#then just check to make sure consistent with `dim` & `sparse`
|
205
|
-
basis = name_or_basis_or_matrices
|
206
|
-
if dim is not None:
|
207
|
-
if isinstance(dim, _StateSpace):
|
208
|
-
state_space = dim
|
209
|
-
if hasattr(basis, 'state_space'): # TODO - should *all* basis objects have a state_space?
|
210
|
-
assert(state_space.is_compatible_with(basis.state_space)), \
|
211
|
-
"Basis object has incompatible state space: %s != %s" % (str(state_space),
|
212
|
-
str(basis.state_space))
|
213
|
-
else: # assume dim is an integer
|
214
|
-
assert(dim == basis.dim or dim == basis.elsize), \
|
215
|
-
"Basis object has unexpected dimension: %d != %d or %d" % (dim, basis.dim, basis.elsize)
|
216
|
-
if sparse is not None:
|
217
|
-
basis = basis.with_sparsity(sparse)
|
218
|
-
return basis
|
219
|
-
elif isinstance(name_or_basis_or_matrices, str):
|
220
|
-
name = name_or_basis_or_matrices
|
229
|
+
@classmethod
|
230
|
+
def cast(cls, arg, dim=None, sparse=None):
|
231
|
+
#print("DB: CAST = ",arg,dim)
|
232
|
+
if isinstance(arg, Basis):
|
233
|
+
return cls.cast_from_basis(arg, dim, sparse)
|
234
|
+
if isinstance(arg, str):
|
221
235
|
if isinstance(dim, _StateSpace):
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
if len(tpbBases) == 1:
|
241
|
-
return tpbBases[0]
|
242
|
-
else:
|
243
|
-
return DirectSumBasis(tpbBases)
|
244
|
-
elif isinstance(dim, (list, tuple)): # list/tuple of block dimensions
|
245
|
-
tpbBases = []
|
246
|
-
for tpbDim in dim:
|
247
|
-
if isinstance(tpbDim, (list, tuple)): # list/tuple of tensor-product dimensions
|
248
|
-
tpbBases.append(
|
249
|
-
TensorProdBasis([BuiltinBasis(name, factorDim, sparse) for factorDim in tpbDim]))
|
250
|
-
else:
|
251
|
-
tpbBases.append(BuiltinBasis(name, tpbDim, sparse))
|
252
|
-
|
253
|
-
if len(tpbBases) == 1:
|
254
|
-
return tpbBases[0]
|
255
|
-
else:
|
256
|
-
return DirectSumBasis(tpbBases)
|
257
|
-
else:
|
258
|
-
return BuiltinBasis(name, dim, sparse)
|
259
|
-
elif isinstance(name_or_basis_or_matrices, (list, tuple, _np.ndarray)):
|
260
|
-
# assume a list/array of matrices or (name, dim) pairs
|
261
|
-
if len(name_or_basis_or_matrices) == 0: # special case of empty basis
|
262
|
-
return ExplicitBasis([], [], "*Empty*", "Empty (0-element) basis", False, sparse) # empty basis
|
263
|
-
elif isinstance(name_or_basis_or_matrices[0], _np.ndarray):
|
264
|
-
b = ExplicitBasis(name_or_basis_or_matrices, sparse=sparse)
|
265
|
-
if dim is not None:
|
266
|
-
assert(dim == b.dim), "Created explicit basis has unexpected dimension: %d vs %d" % (dim, b.dim)
|
267
|
-
if sparse is not None:
|
268
|
-
assert(sparse == b.sparse), "Basis object has unexpected sparsity: %s" % (b.sparse)
|
269
|
-
return b
|
270
|
-
else: # assume els are (name, dim) pairs
|
271
|
-
compBases = [BuiltinBasis(subname, subdim, sparse)
|
272
|
-
for (subname, subdim) in name_or_basis_or_matrices]
|
273
|
-
return DirectSumBasis(compBases)
|
236
|
+
return cls.cast_from_name_and_statespace(arg, dim, sparse)
|
237
|
+
return cls.cast_from_name_and_dims(arg, dim, sparse)
|
238
|
+
if (arg is None) or (hasattr(arg,'__len__') and len(arg) == 0):
|
239
|
+
return ExplicitBasis([], [], "*Empty*", "Empty (0-element) basis", False, sparse)
|
240
|
+
# ^ The original implementation would return this value under two conditions.
|
241
|
+
# Either arg was None, or isinstance(arg,(tuple,list,ndarray)) and len(arg) == 0.
|
242
|
+
# We're just slightly relaxing the type requirement by using this check instead.
|
243
|
+
|
244
|
+
# At this point, original behavior would check that arg is a tuple, list, or ndarray.
|
245
|
+
# Instead, we'll just require that arg[0] is well-defined. This is enough to discern
|
246
|
+
# between the two cases we can still support.
|
247
|
+
if isinstance(arg[0], _np.ndarray):
|
248
|
+
return cls.cast_from_arrays(arg, dim, sparse)
|
249
|
+
if len(arg[0]) == 2:
|
250
|
+
compBases = [BuiltinBasis(subname, subdim, sparse) for (subname, subdim) in arg]
|
251
|
+
return DirectSumBasis(compBases)
|
252
|
+
|
253
|
+
raise ValueError("Can't cast %s to be a basis!" % str(type(arg)))
|
274
254
|
|
275
|
-
else:
|
276
|
-
raise ValueError("Can't cast %s to be a basis!" % str(type(name_or_basis_or_matrices)))
|
277
255
|
|
278
256
|
def __init__(self, name, longname, real, sparse):
|
279
257
|
super().__init__()
|
@@ -387,6 +365,7 @@ class Basis(_NicelySerializable):
|
|
387
365
|
if self.sparse:
|
388
366
|
return [_sps.lil_matrix(el).reshape((self.elsize, 1)) for el in self.elements]
|
389
367
|
else:
|
368
|
+
# Use flatten (rather than ravel) to ensure a copy is made.
|
390
369
|
return [el.flatten() for el in self.elements]
|
391
370
|
|
392
371
|
def copy(self):
|
@@ -547,8 +526,7 @@ class Basis(_NicelySerializable):
|
|
547
526
|
"""
|
548
527
|
if self.elndim == 2:
|
549
528
|
for i, mx in enumerate(self.elements):
|
550
|
-
t = _np.
|
551
|
-
t = _np.real(t)
|
529
|
+
t = _np.linalg.norm(mx) # == sqrt(tr(mx mx))
|
552
530
|
if not _np.isclose(t, 1.0): return False
|
553
531
|
return True
|
554
532
|
elif self.elndim == 1:
|
@@ -1469,7 +1447,7 @@ class DirectSumBasis(LazyBasis):
|
|
1469
1447
|
if self.sparse:
|
1470
1448
|
vel = _sps.lil_matrix(el.reshape(-1, 1)) # sparse vector == sparse n x 1 matrix
|
1471
1449
|
else:
|
1472
|
-
vel = el.
|
1450
|
+
vel = el.ravel()
|
1473
1451
|
toSimpleStd[:, i] = vel
|
1474
1452
|
return toSimpleStd
|
1475
1453
|
|
@@ -1782,283 +1760,3 @@ class TensorProdBasis(LazyBasis):
|
|
1782
1760
|
if all([c.name == first_comp_name for c in self.component_bases]):
|
1783
1761
|
builtin_basis_name = first_comp_name # if all components have the same name
|
1784
1762
|
return BuiltinBasis(builtin_basis_name, self.elsize, sparse=self.sparse)
|
1785
|
-
|
1786
|
-
|
1787
|
-
class EmbeddedBasis(LazyBasis):
|
1788
|
-
"""
|
1789
|
-
A basis that embeds a basis for a smaller state space within a larger state space.
|
1790
|
-
|
1791
|
-
The elements of an EmbeddedBasis are therefore just embedded versions
|
1792
|
-
of the elements of the basis that is embedded.
|
1793
|
-
|
1794
|
-
Parameters
|
1795
|
-
----------
|
1796
|
-
basis_to_embed : Basis
|
1797
|
-
The basis being embedded.
|
1798
|
-
|
1799
|
-
state_space_labels : StateSpaceLabels
|
1800
|
-
An object describing the struture of the entire state space.
|
1801
|
-
|
1802
|
-
target_labels : list or tuple
|
1803
|
-
The labels contained in `stateSpaceLabels` which demarcate the
|
1804
|
-
portions of the state space acted on by `basis_to_embed`.
|
1805
|
-
|
1806
|
-
name : str, optional
|
1807
|
-
The name of this basis. If `None`, the names of `basis_to_embed`
|
1808
|
-
is joined with ':' characters to the elements of `target_labels`.
|
1809
|
-
|
1810
|
-
longname : str, optional
|
1811
|
-
A longer description of this basis. If `None`, then a long name is
|
1812
|
-
automatically generated.
|
1813
|
-
"""
|
1814
|
-
|
1815
|
-
@classmethod
|
1816
|
-
def embed_label(cls, lbl, target_labels):
|
1817
|
-
"""
|
1818
|
-
Gets the EmbeddedBasis label for `lbl`.
|
1819
|
-
|
1820
|
-
Convenience method that gives the EmbeddedBasis label for `lbl`
|
1821
|
-
without needing to construct the `EmbeddedBasis`. E.g. `"XX:1,2"`.
|
1822
|
-
|
1823
|
-
Parameters
|
1824
|
-
----------
|
1825
|
-
lbl : str
|
1826
|
-
Un-embedded basis element label, e.g. `"XX"`.
|
1827
|
-
|
1828
|
-
target_labels : tuple
|
1829
|
-
The target state space labels upon which this basis element
|
1830
|
-
will be embedded, e.g. `(1,2)`
|
1831
|
-
|
1832
|
-
Returns
|
1833
|
-
-------
|
1834
|
-
str
|
1835
|
-
The embedded-basis-element label as an EmbeddedBasis would
|
1836
|
-
assign it. E.g. `"XX:1,2"`.
|
1837
|
-
"""
|
1838
|
-
return "%s:%s" % (lbl, ",".join(map(str, target_labels)))
|
1839
|
-
|
1840
|
-
@classmethod
|
1841
|
-
def unembed_label(cls, lbl, target_labels):
|
1842
|
-
"""
|
1843
|
-
Convenience method that performs the reverse of :meth:`embed_label`
|
1844
|
-
|
1845
|
-
Parameters
|
1846
|
-
----------
|
1847
|
-
lbl : str
|
1848
|
-
Embedded basis element label, e.g. `"XX:1,2"`.
|
1849
|
-
|
1850
|
-
target_labels : tuple
|
1851
|
-
The target state space labels upon which this basis element
|
1852
|
-
will be embedded, e.g. `(1,2)`
|
1853
|
-
|
1854
|
-
Returns
|
1855
|
-
-------
|
1856
|
-
str
|
1857
|
-
The un-embedded label, e.g. `"XX"`.
|
1858
|
-
"""
|
1859
|
-
suffix = ":" + ",".join(map(str, target_labels))
|
1860
|
-
if lbl.endswith(suffix):
|
1861
|
-
return lbl[:-len(suffix)]
|
1862
|
-
else:
|
1863
|
-
raise ValueError("Cannot unembed '%s' - doesn't end in '%s'!" % (lbl, suffix))
|
1864
|
-
|
1865
|
-
def __init__(self, basis_to_embed, state_space, target_labels, name=None, longname=None):
|
1866
|
-
'''
|
1867
|
-
Create a new EmbeddedBasis.
|
1868
|
-
|
1869
|
-
Parameters
|
1870
|
-
----------
|
1871
|
-
basis_to_embed : Basis
|
1872
|
-
The basis being embedded.
|
1873
|
-
|
1874
|
-
state_space : StateSpace
|
1875
|
-
An object describing the struture of the entire state space.
|
1876
|
-
|
1877
|
-
target_labels : list or tuple
|
1878
|
-
The labels contained in `stateSpaceLabels` which demarcate the
|
1879
|
-
portions of the state space acted on by `basis_to_embed`.
|
1880
|
-
|
1881
|
-
name : str, optional
|
1882
|
-
The name of this basis. If `None`, the names of `basis_to_embed`
|
1883
|
-
is joined with ':' characters to the elements of `target_labels`.
|
1884
|
-
|
1885
|
-
longname : str, optional
|
1886
|
-
A longer description of this basis. If `None`, then a long name is
|
1887
|
-
automatically generated.
|
1888
|
-
'''
|
1889
|
-
from pygsti.baseobjs.statespace import StateSpace as _StateSpace
|
1890
|
-
self.embedded_basis = basis_to_embed
|
1891
|
-
self.target_labels = target_labels
|
1892
|
-
self.state_space = _StateSpace.cast(state_space)
|
1893
|
-
|
1894
|
-
if name is None:
|
1895
|
-
name = ':'.join((basis_to_embed.name,) + tuple(map(str, target_labels)))
|
1896
|
-
if longname is None:
|
1897
|
-
longname = "Embedded %s basis as %s within %s" % \
|
1898
|
-
(basis_to_embed.name, ':'.join(map(str, target_labels)), str(self.state_space))
|
1899
|
-
|
1900
|
-
real = basis_to_embed.real
|
1901
|
-
sparse = basis_to_embed.sparse
|
1902
|
-
|
1903
|
-
super(EmbeddedBasis, self).__init__(name, longname, real, sparse)
|
1904
|
-
|
1905
|
-
def _to_nice_serialization(self):
|
1906
|
-
state = super()._to_nice_serialization()
|
1907
|
-
state.update({'name': self.name,
|
1908
|
-
'longname': self.longname,
|
1909
|
-
'state_space': self.state_space.to_nice_serialization(),
|
1910
|
-
'embedded_basis': self.embedded_basis.to_nice_serialization()
|
1911
|
-
})
|
1912
|
-
return state
|
1913
|
-
|
1914
|
-
@classmethod
|
1915
|
-
def _from_nice_serialization(cls, state):
|
1916
|
-
basis_to_embed = Basis.from_nice_serialization(state['embedded_basis'])
|
1917
|
-
state_space = _StateSpace.from_nice_serialization(state['state_space'])
|
1918
|
-
return cls(basis_to_embed, state_space, state['target_labels'], state['name'], state['longname'])
|
1919
|
-
|
1920
|
-
@property
|
1921
|
-
def dim(self):
|
1922
|
-
"""
|
1923
|
-
The dimension of the vector space this basis fully or partially
|
1924
|
-
spans. Equivalently, the length of the `vector_elements` of the
|
1925
|
-
basis.
|
1926
|
-
"""
|
1927
|
-
return self.state_space.dim
|
1928
|
-
|
1929
|
-
@property
|
1930
|
-
def size(self):
|
1931
|
-
"""
|
1932
|
-
The number of elements (or vector-elements) in the basis.
|
1933
|
-
"""
|
1934
|
-
return self.embedded_basis.size
|
1935
|
-
|
1936
|
-
@property
|
1937
|
-
def elshape(self):
|
1938
|
-
"""
|
1939
|
-
The shape of each element. Typically either a length-1 or length-2
|
1940
|
-
tuple, corresponding to vector or matrix elements, respectively.
|
1941
|
-
Note that *vector elements* always have shape `(dim,)` (or `(dim,1)`
|
1942
|
-
in the sparse case).
|
1943
|
-
"""
|
1944
|
-
elndim = self.embedded_basis.elndim
|
1945
|
-
if elndim == 2: # a "matrix" basis
|
1946
|
-
d = int(_np.sqrt(self.dim))
|
1947
|
-
assert(d**2 == self.dim), \
|
1948
|
-
"Dimension of state_space must be a perfect square when embedding a matrix basis"
|
1949
|
-
elshape = (d, d)
|
1950
|
-
elif elndim == 1:
|
1951
|
-
elshape = (self.dim,)
|
1952
|
-
else:
|
1953
|
-
raise ValueError("Can only embed bases with .elndim == 1 or 2 (received %d)!" % elndim)
|
1954
|
-
return elshape
|
1955
|
-
|
1956
|
-
def __hash__(self):
|
1957
|
-
return hash(tuple(hash(self.embedded_basis), self.target_labels, self.state_space))
|
1958
|
-
|
1959
|
-
def _lazy_build_elements(self):
|
1960
|
-
""" Take a dense or sparse basis matrix and embed it. """
|
1961
|
-
#LAZY building of elements (in case we never need them)
|
1962
|
-
if self.elndim == 2: # then use EmbeddedOp to do matrix
|
1963
|
-
from ..modelmembers.operations import StaticArbitraryOp
|
1964
|
-
from ..modelmembers.operations import EmbeddedOp
|
1965
|
-
sslbls = self.state_space.copy()
|
1966
|
-
sslbls.reduce_dims_densitymx_to_state_inplace() # because we're working with basis matrices not gates
|
1967
|
-
|
1968
|
-
if self.sparse:
|
1969
|
-
self._elements = []
|
1970
|
-
for spmx in self.embedded_basis.elements:
|
1971
|
-
mxAsOp = StaticArbitraryOp(spmx.to_dense(), evotype='statevec')
|
1972
|
-
self._elements.append(EmbeddedOp(sslbls, self.target_labels,
|
1973
|
-
mxAsOp).to_sparse())
|
1974
|
-
else:
|
1975
|
-
self._elements = _np.zeros((self.size,) + self.elshape, 'complex')
|
1976
|
-
for i, mx in enumerate(self.embedded_basis.elements):
|
1977
|
-
self._elements[i] = EmbeddedOp(
|
1978
|
-
sslbls, self.target_labels, StaticArbitraryOp(mx, evotype='statevec')
|
1979
|
-
).to_dense(on_space='HilbertSchmidt')
|
1980
|
-
else:
|
1981
|
-
# we need to perform embedding using vectors rather than matrices - doable, but
|
1982
|
-
# not needed yet, so defer implementation to later.
|
1983
|
-
raise NotImplementedError("Embedding *vector*-type bases not implemented yet")
|
1984
|
-
|
1985
|
-
def _lazy_build_labels(self):
|
1986
|
-
self._labels = [EmbeddedBasis.embed_label(lbl, self.target_labels)
|
1987
|
-
for lbl in self.embedded_basis.labels]
|
1988
|
-
|
1989
|
-
def _copy_with_toggled_sparsity(self):
|
1990
|
-
return EmbeddedBasis(self.embedded_basis._copy_with_toggled_sparsity(),
|
1991
|
-
self.state_space,
|
1992
|
-
self.target_labels,
|
1993
|
-
self.name, self.longname)
|
1994
|
-
|
1995
|
-
def is_equivalent(self, other, sparseness_must_match=True):
|
1996
|
-
"""
|
1997
|
-
Tests whether this basis is equal to another basis, optionally ignoring sparseness.
|
1998
|
-
|
1999
|
-
Parameters
|
2000
|
-
-----------
|
2001
|
-
other : Basis or str
|
2002
|
-
The basis to compare with.
|
2003
|
-
|
2004
|
-
sparseness_must_match : bool, optional
|
2005
|
-
If `False` then comparison ignores differing sparseness, and this function
|
2006
|
-
returns `True` when the two bases are equal except for their `.sparse` values.
|
2007
|
-
|
2008
|
-
Returns
|
2009
|
-
-------
|
2010
|
-
bool
|
2011
|
-
"""
|
2012
|
-
otherIsBasis = isinstance(other, EmbeddedBasis)
|
2013
|
-
if not otherIsBasis: return False # can't be equal to a non-EmbeddedBasis
|
2014
|
-
if self.target_labels != other.target_labels or self.state_space != other.state_space:
|
2015
|
-
return False
|
2016
|
-
return self.embedded_basis.is_equivalent(other.embedded_basis, sparseness_must_match)
|
2017
|
-
|
2018
|
-
def create_equivalent(self, builtin_basis_name):
|
2019
|
-
"""
|
2020
|
-
Create an equivalent basis with components of type `builtin_basis_name`.
|
2021
|
-
|
2022
|
-
Create a Basis that is equivalent in structure & dimension to this
|
2023
|
-
basis but whose simple components (perhaps just this basis itself) is
|
2024
|
-
of the builtin basis type given by `builtin_basis_name`.
|
2025
|
-
|
2026
|
-
Parameters
|
2027
|
-
----------
|
2028
|
-
builtin_basis_name : str
|
2029
|
-
The name of a builtin basis, e.g. `"pp"`, `"gm"`, or `"std"`. Used to
|
2030
|
-
construct the simple components of the returned basis.
|
2031
|
-
|
2032
|
-
Returns
|
2033
|
-
-------
|
2034
|
-
EmbeddedBasis
|
2035
|
-
"""
|
2036
|
-
equiv_embedded = self.embedded_basis.create_equivalent(builtin_basis_name)
|
2037
|
-
return EmbeddedBasis(equiv_embedded, self.state_space, self.target_labels)
|
2038
|
-
|
2039
|
-
def create_simple_equivalent(self, builtin_basis_name=None):
|
2040
|
-
"""
|
2041
|
-
Create a basis of type `builtin_basis_name` whose elements are compatible with this basis.
|
2042
|
-
|
2043
|
-
Create a simple basis *and* one without components (e.g. a
|
2044
|
-
:class:`TensorProdBasis`, is a simple basis w/components) of the
|
2045
|
-
builtin type specified whose dimension is compatible with the
|
2046
|
-
*elements* of this basis. This function might also be named
|
2047
|
-
"element_equivalent", as it returns the `builtin_basis_name`-analogue
|
2048
|
-
of the standard basis that this basis's elements are expressed in.
|
2049
|
-
|
2050
|
-
Parameters
|
2051
|
-
----------
|
2052
|
-
builtin_basis_name : str, optional
|
2053
|
-
The name of the built-in basis to use. If `None`, then a
|
2054
|
-
copy of this basis is returned (if it's simple) or this
|
2055
|
-
basis's name is used to try to construct a simple and
|
2056
|
-
component-free version of the same builtin-basis type.
|
2057
|
-
|
2058
|
-
Returns
|
2059
|
-
-------
|
2060
|
-
Basis
|
2061
|
-
"""
|
2062
|
-
if builtin_basis_name is None:
|
2063
|
-
builtin_basis_name = self.embedded_basis.name # default
|
2064
|
-
return BuiltinBasis(builtin_basis_name, self.elsize, sparse=self.sparse)
|