pyGSTi 0.9.12__cp39-cp39-win32.whl → 0.9.13__cp39-cp39-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 +197 -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.cp39-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.cp39-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.cp39-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.cp39-win32.pyd +0 -0
- pygsti/evotypes/densitymx/effectreps.pyx +1 -1
- pygsti/evotypes/densitymx/opreps.cp39-win32.pyd +0 -0
- pygsti/evotypes/densitymx/opreps.pyx +2 -2
- pygsti/evotypes/densitymx/statereps.cp39-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.cp39-win32.pyd +0 -0
- pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
- pygsti/evotypes/stabilizer/opreps.cp39-win32.pyd +0 -0
- pygsti/evotypes/stabilizer/opreps.pyx +0 -4
- pygsti/evotypes/stabilizer/statereps.cp39-win32.pyd +0 -0
- pygsti/evotypes/stabilizer/statereps.pyx +1 -5
- pygsti/evotypes/stabilizer/termreps.cp39-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.cp39-win32.pyd +0 -0
- pygsti/evotypes/statevec/effectreps.pyx +1 -1
- pygsti/evotypes/statevec/opreps.cp39-win32.pyd +0 -0
- pygsti/evotypes/statevec/opreps.pyx +2 -2
- pygsti/evotypes/statevec/statereps.cp39-win32.pyd +0 -0
- pygsti/evotypes/statevec/statereps.pyx +1 -1
- pygsti/evotypes/statevec/termreps.cp39-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.cp39-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.cp39-win32.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.cp39-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.cp39-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
@@ -14,6 +14,7 @@ import collections as _collections
|
|
14
14
|
|
15
15
|
# from .. import modelmember as _mm
|
16
16
|
from pygsti.modelmembers.povms.povm import POVM as _POVM
|
17
|
+
from pygsti.modelmembers.povms import ComposedPOVMEffect as _ComposedPOVMEffect
|
17
18
|
from pygsti.modelmembers.povms.staticeffect import StaticPOVMEffect as _StaticPOVMEffect
|
18
19
|
from pygsti.baseobjs.statespace import StateSpace as _StateSpace
|
19
20
|
from pygsti.baseobjs.label import Label as _Label
|
@@ -193,8 +194,8 @@ class MarginalizedPOVM(_POVM):
|
|
193
194
|
effect_vec = e.to_dense()
|
194
195
|
else:
|
195
196
|
effect_vec += e.to_dense()
|
196
|
-
|
197
|
-
|
197
|
+
rep = e.effect_vec._rep if isinstance(e, _ComposedPOVMEffect) else e._rep
|
198
|
+
effect = _StaticPOVMEffect(effect_vec, rep.basis, self._evotype)
|
198
199
|
assert(effect.allocate_gpindices(0, self.parent) == 0) # functional! (do not remove)
|
199
200
|
_collections.OrderedDict.__setitem__(self, key, effect)
|
200
201
|
return effect
|
@@ -206,85 +207,6 @@ class MarginalizedPOVM(_POVM):
|
|
206
207
|
self.sslbls_after_marginalizing),
|
207
208
|
{'_gpindices': self._gpindices}) # preserve gpindices (but not parent)
|
208
209
|
|
209
|
-
#May need to implement this in future if we allow non-static MarginalizedPOVMs
|
210
|
-
#def allocate_gpindices(self, starting_index, parent, memo=None):
|
211
|
-
# """
|
212
|
-
# Sets gpindices array for this object or any objects it
|
213
|
-
# contains (i.e. depends upon). Indices may be obtained
|
214
|
-
# from contained objects which have already been initialized
|
215
|
-
# (e.g. if a contained object is shared with other
|
216
|
-
# top-level objects), or given new indices starting with
|
217
|
-
# `starting_index`.
|
218
|
-
#
|
219
|
-
# Parameters
|
220
|
-
# ----------
|
221
|
-
# starting_index : int
|
222
|
-
# The starting index for un-allocated parameters.
|
223
|
-
#
|
224
|
-
# parent : Model or ModelMember
|
225
|
-
# The parent whose parameter array gpindices references.
|
226
|
-
#
|
227
|
-
# memo : set, optional
|
228
|
-
# Used to prevent duplicate calls and self-referencing loops. If
|
229
|
-
# `memo` contains an object's id (`id(self)`) then this routine
|
230
|
-
# will exit immediately.
|
231
|
-
#
|
232
|
-
# Returns
|
233
|
-
# -------
|
234
|
-
# num_new: int
|
235
|
-
# The number of *new* allocated parameters (so
|
236
|
-
# the parent should mark as allocated parameter
|
237
|
-
# indices `starting_index` to `starting_index + new_new`).
|
238
|
-
# """
|
239
|
-
# if memo is None: memo = set()
|
240
|
-
# if id(self) in memo: return 0
|
241
|
-
# memo.add(id(self))
|
242
|
-
#
|
243
|
-
# assert(self.base_povm.num_params == 0) # so no need to do anything w/base_povm
|
244
|
-
# num_new_params = self.error_map.allocate_gpindices(starting_index, parent, memo) # *same* parent as self
|
245
|
-
# _mm.ModelMember.set_gpindices(
|
246
|
-
# self, self.error_map.gpindices, parent)
|
247
|
-
# return num_new_params
|
248
|
-
|
249
|
-
#def relink_parent(self, parent): # Unnecessary?
|
250
|
-
# """
|
251
|
-
# Sets the parent of this object *without* altering its gpindices.
|
252
|
-
#
|
253
|
-
# In addition to setting the parent of this object, this method
|
254
|
-
# sets the parent of any objects this object contains (i.e.
|
255
|
-
# depends upon) - much like allocate_gpindices. To ensure a valid
|
256
|
-
# parent is not overwritten, the existing parent *must be None*
|
257
|
-
# prior to this call.
|
258
|
-
# """
|
259
|
-
# self.povm_to_marginalize.relink_parent(parent)
|
260
|
-
# _mm.ModelMember.relink_parent(self, parent)
|
261
|
-
|
262
|
-
#def set_gpindices(self, gpindices, parent, memo=None):
|
263
|
-
# """
|
264
|
-
# Set the parent and indices into the parent's parameter vector that
|
265
|
-
# are used by this ModelMember object.
|
266
|
-
#
|
267
|
-
# Parameters
|
268
|
-
# ----------
|
269
|
-
# gpindices : slice or integer ndarray
|
270
|
-
# The indices of this objects parameters in its parent's array.
|
271
|
-
#
|
272
|
-
# parent : Model or ModelMember
|
273
|
-
# The parent whose parameter array gpindices references.
|
274
|
-
#
|
275
|
-
# Returns
|
276
|
-
# -------
|
277
|
-
# None
|
278
|
-
# """
|
279
|
-
# if memo is None: memo = set()
|
280
|
-
# elif id(self) in memo: return
|
281
|
-
# memo.add(id(self))
|
282
|
-
#
|
283
|
-
# assert(self.base_povm.num_params == 0) # so no need to do anything w/base_povm
|
284
|
-
# self.error_map.set_gpindices(gpindices, parent, memo)
|
285
|
-
# self.terms = {} # clear terms cache since param indices have changed now
|
286
|
-
# _mm.ModelMember._set_only_my_gpindices(self, gpindices, parent)
|
287
|
-
|
288
210
|
def simplify_effects(self, prefix=""):
|
289
211
|
"""
|
290
212
|
Creates a dictionary of simplified effect vectors.
|
@@ -10,11 +10,23 @@ Defines the TPPOVM class
|
|
10
10
|
# http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
|
11
11
|
#***************************************************************************************************
|
12
12
|
|
13
|
+
from __future__ import annotations
|
14
|
+
from typing import Tuple, TYPE_CHECKING
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
import torch as _torch
|
17
|
+
try:
|
18
|
+
import torch as _torch
|
19
|
+
except ImportError:
|
20
|
+
pass
|
21
|
+
|
22
|
+
import numpy as _np
|
23
|
+
from pygsti.modelmembers.torchable import Torchable as _Torchable
|
13
24
|
from pygsti.modelmembers.povms.basepovm import _BasePOVM
|
14
|
-
from pygsti.modelmembers.povms.
|
25
|
+
from pygsti.modelmembers.povms.fulleffect import FullPOVMEffect as _FullPOVMEffect
|
26
|
+
import warnings
|
15
27
|
|
16
28
|
|
17
|
-
class TPPOVM(_BasePOVM):
|
29
|
+
class TPPOVM(_BasePOVM, _Torchable):
|
18
30
|
"""
|
19
31
|
A POVM whose sum-of-effects is constrained to what, by definition, we call the "identity".
|
20
32
|
|
@@ -37,6 +49,23 @@ class TPPOVM(_BasePOVM):
|
|
37
49
|
The state space for this POVM. If `None`, the space is inferred
|
38
50
|
from the first effect vector. If `len(effects) == 0` in this case,
|
39
51
|
an error is raised.
|
52
|
+
|
53
|
+
Notes
|
54
|
+
-----
|
55
|
+
Just like TPState, we're restricted to the Pauli-product or Gell-Mann basis.
|
56
|
+
|
57
|
+
We inherit from BasePOVM, which inherits from POVM, which inherits from OrderedDict.
|
58
|
+
|
59
|
+
A TPPOVM "p" has an attribute p.complement_label that's set during construction.
|
60
|
+
This label is such that e = p[p.complement_label] is a ComplementPOVMEffect, with
|
61
|
+
an associated FullState object given in e.identity. If v = e.identity.to_vector(),
|
62
|
+
then e's vector representation is
|
63
|
+
|
64
|
+
v - sum(all non-complement effects in p).
|
65
|
+
|
66
|
+
Under typical conditions v will be proportional to the first standard basis vector,
|
67
|
+
and, in fact, if v is length "d," then we'll have v[0] == d ** 0.25. However,
|
68
|
+
neither of these conditions is strictly required by the API.
|
40
69
|
"""
|
41
70
|
|
42
71
|
def __init__(self, effects, evotype=None, state_space=None, called_from_reduce=False):
|
@@ -56,3 +85,46 @@ class TPPOVM(_BasePOVM):
|
|
56
85
|
|
57
86
|
return (TPPOVM, (effects, self.evotype, self.state_space, True),
|
58
87
|
{'_gpindices': self._gpindices, '_submember_rpindices': self._submember_rpindices})
|
88
|
+
|
89
|
+
@property
|
90
|
+
def dim(self):
|
91
|
+
effect = next(iter(self.values()))
|
92
|
+
return effect.dim
|
93
|
+
|
94
|
+
def to_vector(self):
|
95
|
+
effect_vecs = []
|
96
|
+
for i, (lbl, effect) in enumerate(self.items()):
|
97
|
+
if lbl != self.complement_label:
|
98
|
+
assert isinstance(effect, _FullPOVMEffect)
|
99
|
+
effect_vecs.append(effect.to_vector())
|
100
|
+
else:
|
101
|
+
assert i == len(self) - 1
|
102
|
+
vec = _np.concatenate(effect_vecs)
|
103
|
+
return vec
|
104
|
+
|
105
|
+
def stateless_data(self) -> Tuple[int, _np.ndarray]:
|
106
|
+
num_effects = len(self)
|
107
|
+
complement_effect = self[self.complement_label]
|
108
|
+
identity = complement_effect.identity.to_vector()
|
109
|
+
return (num_effects, identity)
|
110
|
+
|
111
|
+
@staticmethod
|
112
|
+
def torch_base(sd: Tuple[int, _np.ndarray], t_param: _torch.Tensor) -> _torch.Tensor:
|
113
|
+
num_effects, identity = sd
|
114
|
+
dim = identity.size
|
115
|
+
|
116
|
+
first_basis_vec = _np.zeros(dim)
|
117
|
+
first_basis_vec[0] = dim ** 0.25
|
118
|
+
TOL = 1e-15 * _np.sqrt(dim)
|
119
|
+
if _np.linalg.norm(first_basis_vec - identity) > TOL:
|
120
|
+
# Don't error out. The documentation for the class
|
121
|
+
# clearly indicates that the meaning of "identity"
|
122
|
+
# can be nonstandard.
|
123
|
+
warnings.warn('Unexpected normalization!')
|
124
|
+
|
125
|
+
identity = identity.reshape((1, -1)) # make into a row vector
|
126
|
+
t_identity = _torch.from_numpy(identity)
|
127
|
+
t_param_mat = t_param.reshape((num_effects - 1, dim))
|
128
|
+
t_func = t_identity - t_param_mat.sum(axis=0, keepdim=True)
|
129
|
+
t = _torch.row_stack((t_param_mat, t_func))
|
130
|
+
return t
|
@@ -15,8 +15,6 @@ import scipy.linalg as _spl
|
|
15
15
|
import scipy.optimize as _spo
|
16
16
|
import warnings as _warnings
|
17
17
|
|
18
|
-
from numpy.lib.arraysetops import isin
|
19
|
-
|
20
18
|
from pygsti.modelmembers.povms.computationalpovm import ComputationalBasisPOVM
|
21
19
|
|
22
20
|
from .composedstate import ComposedState
|
@@ -426,17 +424,16 @@ def optimize_state(vec_to_optimize, target_vec):
|
|
426
424
|
return
|
427
425
|
|
428
426
|
from pygsti import optimize as _opt
|
429
|
-
from pygsti.tools import matrixtools as _mt
|
430
427
|
assert(target_vec.dim == vec_to_optimize.dim) # vectors must have the same overall dimension
|
431
428
|
targetVector = target_vec.to_dense() if isinstance(target_vec, State) else target_vec
|
432
429
|
|
433
430
|
def _objective_func(param_vec):
|
434
431
|
vec_to_optimize.from_vector(param_vec)
|
435
|
-
return
|
432
|
+
return _np.linalg.norm(vec_to_optimize.to_dense() - targetVector)
|
436
433
|
|
437
434
|
x0 = vec_to_optimize.to_vector()
|
438
435
|
minSol = _opt.minimize(_objective_func, x0, method='BFGS', maxiter=10000, maxfev=10000,
|
439
436
|
tol=1e-6, callback=None)
|
440
437
|
|
441
438
|
vec_to_optimize.from_vector(minSol.x)
|
442
|
-
|
439
|
+
return
|
@@ -43,323 +43,6 @@ class ComposedState(_State): # , _ErrorMapContainer
|
|
43
43
|
parameters with other gates and spam vectors.)
|
44
44
|
"""
|
45
45
|
|
46
|
-
#@classmethod
|
47
|
-
#def _from_spamvec_obj(cls, spamvec, typ, param_type="GLND", purevec=None,
|
48
|
-
# proj_basis="pp", mx_basis="pp", truncate=True,
|
49
|
-
# lazy=False):
|
50
|
-
# """
|
51
|
-
# Creates a LindbladSPAMVec from an existing SPAMVec object and some additional information.
|
52
|
-
#
|
53
|
-
# This function is different from `from_spam_vector` in that it assumes
|
54
|
-
# that `spamvec` is a :class:`SPAMVec`-derived object, and if `lazy=True`
|
55
|
-
# and if `spamvec` is already a matching LindbladSPAMVec, it
|
56
|
-
# is returned directly. This routine is primarily used in spam vector
|
57
|
-
# conversion functions, where conversion is desired only when necessary.
|
58
|
-
#
|
59
|
-
# Parameters
|
60
|
-
# ----------
|
61
|
-
# spamvec : SPAMVec
|
62
|
-
# The spam vector object to "convert" to a
|
63
|
-
# `LindbladSPAMVec`.
|
64
|
-
#
|
65
|
-
# typ : {"prep","effect"}
|
66
|
-
# Whether this is a state preparation or POVM effect vector.
|
67
|
-
#
|
68
|
-
# param_type : str, optional
|
69
|
-
# The high-level "parameter type" of the gate to create. This
|
70
|
-
# specifies both which Lindblad parameters are included and what
|
71
|
-
# type of evolution is used. Examples of valid values are
|
72
|
-
# `"CPTP"`, `"H+S"`, `"S terms"`, and `"GLND clifford terms"`.
|
73
|
-
#
|
74
|
-
# purevec : numpy array or SPAMVec object, optional
|
75
|
-
# A SPAM vector which represents a pure-state, taken as the "ideal"
|
76
|
-
# reference state when constructing the error generator of the
|
77
|
-
# returned `LindbladSPAMVec`. Note that this vector
|
78
|
-
# still acts on density matrices (if it's a SPAMVec it should have
|
79
|
-
# a "densitymx", "svterm", or "cterm" evolution type, and if it's
|
80
|
-
# a numpy array it should have the same dimension as `spamvec`).
|
81
|
-
# If None, then it is taken to be `spamvec`, and so `spamvec` must
|
82
|
-
# represent a pure state in this case.
|
83
|
-
#
|
84
|
-
# proj_basis : {'std', 'gm', 'pp', 'qt'}, list of matrices, or Basis object
|
85
|
-
# The basis used to construct the Lindblad-term error generators onto
|
86
|
-
# which the SPAM vector's error generator is projected. Allowed values
|
87
|
-
# are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
|
88
|
-
# and Qutrit (qt), list of numpy arrays, or a custom basis object.
|
89
|
-
#
|
90
|
-
# mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object
|
91
|
-
# The source and destination basis, respectively. Allowed
|
92
|
-
# values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
|
93
|
-
# and Qutrit (qt) (or a custom basis object).
|
94
|
-
#
|
95
|
-
# truncate : bool, optional
|
96
|
-
# Whether to truncate the projections onto the Lindblad terms in
|
97
|
-
# order to meet constraints (e.g. to preserve CPTP) when necessary.
|
98
|
-
# If False, then an error is thrown when the given `spamvec` cannot
|
99
|
-
# be realized by the specified set of Lindblad projections.
|
100
|
-
#
|
101
|
-
# lazy : bool, optional
|
102
|
-
# If True, then if `spamvec` is already a LindbladSPAMVec
|
103
|
-
# with the requested details (given by the other arguments), then
|
104
|
-
# `spamvec` is returned directly and no conversion/copying is
|
105
|
-
# performed. If False, then a new object is always returned.
|
106
|
-
#
|
107
|
-
# Returns
|
108
|
-
# -------
|
109
|
-
# LindbladSPAMVec
|
110
|
-
# """
|
111
|
-
#
|
112
|
-
# if not isinstance(spamvec, SPAMVec):
|
113
|
-
# spamvec = StaticSPAMVec(spamvec, typ=typ) # assume spamvec is just a vector
|
114
|
-
#
|
115
|
-
# if purevec is None:
|
116
|
-
# purevec = spamvec # right now, we don't try to extract a "closest pure vec"
|
117
|
-
# # to spamvec - below will fail if spamvec isn't pure.
|
118
|
-
# elif not isinstance(purevec, SPAMVec):
|
119
|
-
# purevec = StaticSPAMVec(purevec, typ=typ) # assume spamvec is just a vector
|
120
|
-
#
|
121
|
-
# #Break param_type in to a "base" type and an evotype
|
122
|
-
# from .operation import LindbladOp as _LPGMap
|
123
|
-
# bTyp, evotype, nonham_mode, param_mode = _LPGMap.decomp_paramtype(param_type)
|
124
|
-
#
|
125
|
-
# ham_basis = proj_basis if (("H" == bTyp) or ("H+" in bTyp) or bTyp in ("CPTP", "GLND")) else None
|
126
|
-
# nonham_basis = None if bTyp == "H" else proj_basis
|
127
|
-
#
|
128
|
-
# def beq(b1, b2):
|
129
|
-
# """ Check if bases have equal names """
|
130
|
-
# b1 = b1.name if isinstance(b1, _Basis) else b1
|
131
|
-
# b2 = b2.name if isinstance(b2, _Basis) else b2
|
132
|
-
# return b1 == b2
|
133
|
-
#
|
134
|
-
# def normeq(a, b):
|
135
|
-
# if a is None and b is None: return True
|
136
|
-
# if a is None or b is None: return False
|
137
|
-
# return _mt.safe_norm(a - b) < 1e-6 # what about possibility of Clifford gates?
|
138
|
-
#
|
139
|
-
# if isinstance(spamvec, LindbladSPAMVec) \
|
140
|
-
# and spamvec._evotype == evotype and spamvec.typ == typ \
|
141
|
-
# and beq(ham_basis, spamvec.error_map.ham_basis) and beq(nonham_basis, spamvec.error_map.other_basis) \
|
142
|
-
# and param_mode == spamvec.error_map.param_mode and nonham_mode == spamvec.error_map.nonham_mode \
|
143
|
-
# and beq(mx_basis, spamvec.error_map.matrix_basis) and lazy:
|
144
|
-
# #normeq(gate.pure_state_vec,purevec) \ # TODO: more checks for equality?!
|
145
|
-
# return spamvec # no creation necessary!
|
146
|
-
# else:
|
147
|
-
# #Convert vectors (if possible) to SPAMVecs
|
148
|
-
# # of the appropriate evotype and 0 params.
|
149
|
-
# bDiff = spamvec is not purevec
|
150
|
-
# spamvec = _convert_to_lindblad_base(spamvec, typ, evotype, mx_basis)
|
151
|
-
# purevec = _convert_to_lindblad_base(purevec, typ, evotype, mx_basis) if bDiff else spamvec
|
152
|
-
# assert(spamvec._evotype == evotype)
|
153
|
-
# assert(purevec._evotype == evotype)
|
154
|
-
#
|
155
|
-
# return cls.from_spam_vector(
|
156
|
-
# spamvec, purevec, typ, ham_basis, nonham_basis,
|
157
|
-
# param_mode, nonham_mode, truncate, mx_basis, evotype)
|
158
|
-
#
|
159
|
-
#@classmethod
|
160
|
-
#def from_spam_vector(cls, spam_vec, pure_vec, typ,
|
161
|
-
# ham_basis="pp", nonham_basis="pp", param_mode="cptp",
|
162
|
-
# nonham_mode="all", truncate=True, mx_basis="pp",
|
163
|
-
# evotype="densitymx"):
|
164
|
-
# """
|
165
|
-
# Creates a Lindblad-parameterized spamvec from a state vector and a basis.
|
166
|
-
#
|
167
|
-
# The basis specifies how to decompose (project) the vector's error generator.
|
168
|
-
#
|
169
|
-
# Parameters
|
170
|
-
# ----------
|
171
|
-
# spam_vec : SPAMVec
|
172
|
-
# the SPAM vector to initialize from. The error generator that
|
173
|
-
# tranforms `pure_vec` into `spam_vec` forms the parameterization
|
174
|
-
# of the returned LindbladSPAMVec.
|
175
|
-
#
|
176
|
-
# pure_vec : numpy array or SPAMVec
|
177
|
-
# An array or SPAMVec in the *full* density-matrix space (this
|
178
|
-
# vector will have the same dimension as `spam_vec` - 4 in the case
|
179
|
-
# of a single qubit) which represents a pure-state preparation or
|
180
|
-
# projection. This is used as the "base" preparation/projection
|
181
|
-
# when computing the error generator that will be parameterized.
|
182
|
-
# Note that this argument must be specified, as there is no natural
|
183
|
-
# default value (like the identity in the case of gates).
|
184
|
-
#
|
185
|
-
# typ : {"prep","effect"}
|
186
|
-
# Whether this is a state preparation or POVM effect vector.
|
187
|
-
#
|
188
|
-
# ham_basis: {'std', 'gm', 'pp', 'qt'}, list of matrices, or Basis object
|
189
|
-
# The basis is used to construct the Hamiltonian-type lindblad error
|
190
|
-
# Allowed values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
|
191
|
-
# and Qutrit (qt), list of numpy arrays, or a custom basis object.
|
192
|
-
#
|
193
|
-
# nonham_basis: {'std', 'gm', 'pp', 'qt'}, list of matrices, or Basis object
|
194
|
-
# The basis is used to construct the Stochastic-type lindblad error
|
195
|
-
# Allowed values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
|
196
|
-
# and Qutrit (qt), list of numpy arrays, or a custom basis object.
|
197
|
-
#
|
198
|
-
# param_mode : {"unconstrained", "cptp", "depol", "reldepol"}
|
199
|
-
# Describes how the Lindblad coefficients/projections relate to the
|
200
|
-
# SPAM vector's parameter values. Allowed values are:
|
201
|
-
# `"unconstrained"` (coeffs are independent unconstrained parameters),
|
202
|
-
# `"cptp"` (independent parameters but constrained so map is CPTP),
|
203
|
-
# `"reldepol"` (all non-Ham. diagonal coeffs take the *same* value),
|
204
|
-
# `"depol"` (same as `"reldepol"` but coeffs must be *positive*)
|
205
|
-
#
|
206
|
-
# nonham_mode : {"diagonal", "diag_affine", "all"}
|
207
|
-
# Which non-Hamiltonian Lindblad projections are potentially non-zero.
|
208
|
-
# Allowed values are: `"diagonal"` (only the diagonal Lind. coeffs.),
|
209
|
-
# `"diag_affine"` (diagonal coefficients + affine projections), and
|
210
|
-
# `"all"` (the entire matrix of coefficients is allowed).
|
211
|
-
#
|
212
|
-
# truncate : bool, optional
|
213
|
-
# Whether to truncate the projections onto the Lindblad terms in
|
214
|
-
# order to meet constraints (e.g. to preserve CPTP) when necessary.
|
215
|
-
# If False, then an error is thrown when the given `gate` cannot
|
216
|
-
# be realized by the specified set of Lindblad projections.
|
217
|
-
#
|
218
|
-
# mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object
|
219
|
-
# The source and destination basis, respectively. Allowed
|
220
|
-
# values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
|
221
|
-
# and Qutrit (qt) (or a custom basis object).
|
222
|
-
#
|
223
|
-
# evotype : {"densitymx","svterm","cterm"}
|
224
|
-
# The evolution type of the spamvec being constructed. `"densitymx"` is
|
225
|
-
# usual Lioville density-matrix-vector propagation via matrix-vector
|
226
|
-
# products. `"svterm"` denotes state-vector term-based evolution
|
227
|
-
# (spamvec is obtained by evaluating the rank-1 terms up to
|
228
|
-
# some order). `"cterm"` is similar but stabilizer states.
|
229
|
-
#
|
230
|
-
# Returns
|
231
|
-
# -------
|
232
|
-
# LindbladSPAMVec
|
233
|
-
# """
|
234
|
-
# #Compute a (errgen, pure_vec) pair from the given
|
235
|
-
# # (spam_vec, pure_vec) pair.
|
236
|
-
#
|
237
|
-
# assert(pure_vec is not None), "Must supply `pure_vec`!" # since there's no good default?
|
238
|
-
#
|
239
|
-
# if not isinstance(spam_vec, SPAMVec):
|
240
|
-
# spam_vec = StaticSPAMVec(spam_vec, evotype, typ) # assume spamvec is just a vector
|
241
|
-
# if not isinstance(pure_vec, SPAMVec):
|
242
|
-
# pure_vec = StaticSPAMVec(pure_vec, evotype, typ) # assume spamvec is just a vector
|
243
|
-
# d2 = pure_vec.dim
|
244
|
-
#
|
245
|
-
# #Determine whether we're using sparse bases or not
|
246
|
-
# sparse = None
|
247
|
-
# if ham_basis is not None:
|
248
|
-
# if isinstance(ham_basis, _Basis): sparse = ham_basis.sparse
|
249
|
-
# elif not isinstance(ham_basis, str) and len(ham_basis) > 0:
|
250
|
-
# sparse = _sps.issparse(ham_basis[0])
|
251
|
-
# if sparse is None and nonham_basis is not None:
|
252
|
-
# if isinstance(nonham_basis, _Basis): sparse = nonham_basis.sparse
|
253
|
-
# elif not isinstance(nonham_basis, str) and len(nonham_basis) > 0:
|
254
|
-
# sparse = _sps.issparse(nonham_basis[0])
|
255
|
-
# if sparse is None: sparse = False # the default
|
256
|
-
#
|
257
|
-
# if spam_vec is None or spam_vec is pure_vec:
|
258
|
-
# if sparse: errgen = _sps.csr_matrix((d2, d2), dtype='d')
|
259
|
-
# else: errgen = _np.zeros((d2, d2), 'd')
|
260
|
-
# else:
|
261
|
-
# #Construct "spam error generator" by comparing *dense* vectors
|
262
|
-
# pvdense = pure_vec.to_dense()
|
263
|
-
# svdense = spam_vec.to_dense()
|
264
|
-
# errgen = _ot.spam_error_generator(svdense, pvdense, mx_basis)
|
265
|
-
# if sparse: errgen = _sps.csr_matrix(errgen)
|
266
|
-
#
|
267
|
-
# assert(pure_vec._evotype == evotype), "`pure_vec` must have evotype == '%s'" % evotype
|
268
|
-
#
|
269
|
-
# from .operation import LindbladErrorgen as _LErrorgen
|
270
|
-
# from .operation import LindbladOp as _LPGMap
|
271
|
-
# from .operation import LindbladDenseOp as _LPOp
|
272
|
-
#
|
273
|
-
# errgen = _LErrorgen.from_error_generator(errgen, ham_basis,
|
274
|
-
# nonham_basis, param_mode, nonham_mode,
|
275
|
-
# mx_basis, truncate, evotype)
|
276
|
-
# errcls = _LPOp if (pure_vec.dim <= 64 and evotype == "densitymx") else _LPGMap
|
277
|
-
# errmap = errcls(None, errgen)
|
278
|
-
#
|
279
|
-
# return cls(pure_vec, errmap, typ)
|
280
|
-
|
281
|
-
#@classmethod
|
282
|
-
#def from_lindblad_terms(cls, pure_vec, lindblad_term_dict, typ, basisdict=None,
|
283
|
-
# param_mode="cptp", nonham_mode="all", truncate=True,
|
284
|
-
# mx_basis="pp", evotype="densitymx"):
|
285
|
-
# """
|
286
|
-
# Create a Lindblad-parameterized spamvec with a given set of Lindblad terms.
|
287
|
-
#
|
288
|
-
# Parameters
|
289
|
-
# ----------
|
290
|
-
# pure_vec : numpy array or SPAMVec
|
291
|
-
# An array or SPAMVec in the *full* density-matrix space (this
|
292
|
-
# vector will have dimension 4 in the case of a single qubit) which
|
293
|
-
# represents a pure-state preparation or projection. This is used as
|
294
|
-
# the "base" preparation or projection that is followed or preceded
|
295
|
-
# by, respectively, the parameterized Lindblad-form error generator.
|
296
|
-
#
|
297
|
-
# lindblad_term_dict : dict
|
298
|
-
# A dictionary specifying which Linblad terms are present in the gate
|
299
|
-
# parameteriztion. Keys are `(termType, basisLabel1, <basisLabel2>)`
|
300
|
-
# tuples, where `termType` can be `"H"` (Hamiltonian), `"S"`
|
301
|
-
# (Stochastic), or `"A"` (Affine). Hamiltonian and Affine terms always
|
302
|
-
# have a single basis label (so key is a 2-tuple) whereas Stochastic
|
303
|
-
# tuples with 1 basis label indicate a *diagonal* term, and are the
|
304
|
-
# only types of terms allowed when `nonham_mode != "all"`. Otherwise,
|
305
|
-
# Stochastic term tuples can include 2 basis labels to specify
|
306
|
-
# "off-diagonal" non-Hamiltonian Lindblad terms. Basis labels can be
|
307
|
-
# strings or integers. Values are complex coefficients (error rates).
|
308
|
-
#
|
309
|
-
# typ : {"prep","effect"}
|
310
|
-
# Whether this is a state preparation or POVM effect vector.
|
311
|
-
#
|
312
|
-
# basisdict : dict, optional
|
313
|
-
# A dictionary mapping the basis labels (strings or ints) used in the
|
314
|
-
# keys of `lindblad_term_dict` to basis matrices (numpy arrays or Scipy sparse
|
315
|
-
# matrices).
|
316
|
-
#
|
317
|
-
# param_mode : {"unconstrained", "cptp", "depol", "reldepol"}
|
318
|
-
# Describes how the Lindblad coefficients/projections relate to the
|
319
|
-
# SPAM vector's parameter values. Allowed values are:
|
320
|
-
# `"unconstrained"` (coeffs are independent unconstrained parameters),
|
321
|
-
# `"cptp"` (independent parameters but constrained so map is CPTP),
|
322
|
-
# `"reldepol"` (all non-Ham. diagonal coeffs take the *same* value),
|
323
|
-
# `"depol"` (same as `"reldepol"` but coeffs must be *positive*)
|
324
|
-
#
|
325
|
-
# nonham_mode : {"diagonal", "diag_affine", "all"}
|
326
|
-
# Which non-Hamiltonian Lindblad projections are potentially non-zero.
|
327
|
-
# Allowed values are: `"diagonal"` (only the diagonal Lind. coeffs.),
|
328
|
-
# `"diag_affine"` (diagonal coefficients + affine projections), and
|
329
|
-
# `"all"` (the entire matrix of coefficients is allowed).
|
330
|
-
#
|
331
|
-
# truncate : bool, optional
|
332
|
-
# Whether to truncate the projections onto the Lindblad terms in
|
333
|
-
# order to meet constraints (e.g. to preserve CPTP) when necessary.
|
334
|
-
# If False, then an error is thrown when the given dictionary of
|
335
|
-
# Lindblad terms doesn't conform to the constrains.
|
336
|
-
#
|
337
|
-
# mx_basis : {'std', 'gm', 'pp', 'qt'} or Basis object
|
338
|
-
# The source and destination basis, respectively. Allowed
|
339
|
-
# values are Matrix-unit (std), Gell-Mann (gm), Pauli-product (pp),
|
340
|
-
# and Qutrit (qt) (or a custom basis object).
|
341
|
-
#
|
342
|
-
# evotype : {"densitymx","svterm","cterm"}
|
343
|
-
# The evolution type of the spamvec being constructed. `"densitymx"` is
|
344
|
-
# usual Lioville density-matrix-vector propagation via matrix-vector
|
345
|
-
# products. `"svterm"` denotes state-vector term-based evolution
|
346
|
-
# (spamvec is obtained by evaluating the rank-1 terms up to
|
347
|
-
# some order). `"cterm"` is similar but stabilizer states.
|
348
|
-
#
|
349
|
-
# Returns
|
350
|
-
# -------
|
351
|
-
# LindbladOp
|
352
|
-
# """
|
353
|
-
# #Need a dimension for error map construction (basisdict could be completely empty)
|
354
|
-
# if not isinstance(pure_vec, SPAMVec):
|
355
|
-
# pure_vec = StaticSPAMVec(pure_vec, evotype, typ) # assume spamvec is just a vector
|
356
|
-
# d2 = pure_vec.dim
|
357
|
-
#
|
358
|
-
# from .operation import LindbladOp as _LPGMap
|
359
|
-
# errmap = _LPGMap(d2, lindblad_term_dict, basisdict, param_mode, nonham_mode,
|
360
|
-
# truncate, mx_basis, evotype)
|
361
|
-
# return cls(pure_vec, errmap, typ)
|
362
|
-
|
363
46
|
def __init__(self, static_state, errormap):
|
364
47
|
evotype = errormap._evotype
|
365
48
|
#from .operation import LindbladOp as _LPGMap
|
@@ -88,7 +88,7 @@ class ComputationalBasisState(_State, _NoErrorGeneratorInterface):
|
|
88
88
|
|
89
89
|
for zvals in _itertools.product(*([(0, 1)] * nqubits)):
|
90
90
|
testvec = _functools.reduce(_np.kron, [v[i] for i in zvals])
|
91
|
-
if _np.allclose(testvec, vec.
|
91
|
+
if _np.allclose(testvec, vec.ravel()):
|
92
92
|
return cls(zvals, basis, evotype, state_space)
|
93
93
|
raise ValueError(("Given `vec` is not a z-basis product state - "
|
94
94
|
"cannot construct ComputationalBasisState"))
|
@@ -128,7 +128,7 @@ class ComputationalBasisState(_State, _NoErrorGeneratorInterface):
|
|
128
128
|
v = (_np.array([1, 0], 'd'), _np.array([0, 1], 'd')) # (v0,v1)
|
129
129
|
for zvals in _itertools.product(*([(0, 1)] * nqubits)):
|
130
130
|
testvec = _functools.reduce(_np.kron, [v[i] for i in zvals])
|
131
|
-
if _np.allclose(testvec, purevec.
|
131
|
+
if _np.allclose(testvec, purevec.ravel()):
|
132
132
|
return cls(zvals, basis, evotype, state_space)
|
133
133
|
raise ValueError(("Given `purevec` must be a z-basis product state - "
|
134
134
|
"cannot construct ComputationalBasisState"))
|
@@ -140,7 +140,7 @@ class ComputationalBasisState(_State, _NoErrorGeneratorInterface):
|
|
140
140
|
else _statespace.StateSpace.cast(state_space)
|
141
141
|
basis = _Basis.cast(basis, state_space) # basis for Hilbert-Schmidt (superop) space
|
142
142
|
|
143
|
-
evotype = _Evotype.cast(evotype)
|
143
|
+
evotype = _Evotype.cast(evotype, state_space=state_space)
|
144
144
|
self._evotype = evotype # set this before call to _State.__init__ so self.to_dense() can work...
|
145
145
|
rep = evotype.create_computational_state_rep(self._zvals, basis, state_space)
|
146
146
|
_State.__init__(self, rep, evotype)
|
@@ -84,7 +84,7 @@ class CPTPState(_DenseState):
|
|
84
84
|
state_space = _statespace.default_space_for_dim(len(vector)) if (state_space is None) \
|
85
85
|
else _statespace.StateSpace.cast(state_space)
|
86
86
|
|
87
|
-
evotype = _Evotype.cast(evotype)
|
87
|
+
evotype = _Evotype.cast(evotype, state_space=state_space)
|
88
88
|
_DenseState.__init__(self, vector, basis, evotype, state_space)
|
89
89
|
self._paramlbls = _np.array(labels, dtype=object)
|
90
90
|
|
@@ -150,7 +150,7 @@ class CPTPState(_DenseState):
|
|
150
150
|
Lmx = _np.linalg.cholesky(density_mx)
|
151
151
|
|
152
152
|
#check TP condition: that diagonal els of Lmx squared add to 1.0
|
153
|
-
Lmx_norm = _np.
|
153
|
+
Lmx_norm = _np.linalg.norm(Lmx) # = sqrt(tr(Lmx' Lmx))
|
154
154
|
assert(_np.isclose(Lmx_norm, 1.0)), \
|
155
155
|
"Cholesky decomp didn't preserve trace=1!"
|
156
156
|
|
@@ -180,7 +180,7 @@ class CPTPState(_DenseState):
|
|
180
180
|
for j in range(i):
|
181
181
|
self.Lmx[i, j] = (self.params[i * dmDim + j] + 1j * self.params[j * dmDim + i]) / paramNorm
|
182
182
|
|
183
|
-
Lmx_norm = _np.
|
183
|
+
Lmx_norm = _np.linalg.norm(self.Lmx) # = sqrt(tr(Lmx' Lmx))
|
184
184
|
assert(_np.isclose(Lmx_norm, 1.0)), "Violated trace=1 condition!"
|
185
185
|
|
186
186
|
#The (complex, Hermitian) density matrix is build by
|
@@ -192,7 +192,7 @@ class CPTPState(_DenseState):
|
|
192
192
|
# write density matrix in given basis: = sum_i alpha_i B_i
|
193
193
|
# ASSUME that basis is orthogonal, i.e. Tr(Bi^dag*Bj) = delta_ij
|
194
194
|
basis_mxs = _np.rollaxis(self.basis_mxs, 2) # shape (dmDim, dmDim, len(vec))
|
195
|
-
vec = _np.array([_np.
|
195
|
+
vec = _np.array([_np.vdot(M, density_mx) for M in basis_mxs])
|
196
196
|
|
197
197
|
#for now, assume Liouville vector should always be real (TODO: add 'real' flag later?)
|
198
198
|
assert(_np.linalg.norm(_np.imag(vec)) < IMAG_TOL)
|
@@ -166,9 +166,11 @@ class DenseState(DenseStateInterface, _State):
|
|
166
166
|
|
167
167
|
def __init__(self, vec, basis, evotype, state_space):
|
168
168
|
vec = _State._to_vector(vec)
|
169
|
-
|
170
|
-
|
171
|
-
|
169
|
+
if state_space is None:
|
170
|
+
state_space = _statespace.default_space_for_dim(vec.shape[0])
|
171
|
+
else:
|
172
|
+
state_space = _statespace.StateSpace.cast(state_space)
|
173
|
+
evotype = _Evotype.cast(evotype, state_space=state_space)
|
172
174
|
self._basis = _Basis.cast(basis, state_space.dim)
|
173
175
|
rep = evotype.create_dense_state_rep(vec, self._basis, state_space)
|
174
176
|
|
@@ -263,15 +265,16 @@ class DensePureState(DenseStateInterface, _State):
|
|
263
265
|
purevec = purevec.astype(complex)
|
264
266
|
state_space = _statespace.default_space_for_udim(purevec.shape[0]) if (state_space is None) \
|
265
267
|
else _statespace.StateSpace.cast(state_space)
|
266
|
-
evotype = _Evotype.cast(evotype)
|
268
|
+
evotype = _Evotype.cast(evotype, state_space=state_space)
|
267
269
|
basis = _Basis.cast(basis, state_space.dim) # basis for Hilbert-Schmidt (superop) space
|
268
|
-
|
269
|
-
#Try to create a dense pure rep. If this fails, see if a dense
|
270
|
+
|
271
|
+
#Try to create a dense pure rep. If this fails, see if a dense superket rep
|
270
272
|
# can be created, as this type of rep can also hold arbitrary pure states.
|
271
273
|
try:
|
272
274
|
rep = evotype.create_pure_state_rep(purevec, basis, state_space)
|
273
275
|
self._reptype = 'pure'
|
274
|
-
self._purevec =
|
276
|
+
self._purevec = None
|
277
|
+
self._basis = basis #this was previously being set as None, not sure why.
|
275
278
|
except Exception:
|
276
279
|
if len(purevec) == basis.dim and _np.linalg.norm(purevec.imag) < 1e-10:
|
277
280
|
# Special case when a *superket* was provided instead of a purevec
|
@@ -350,7 +353,6 @@ class DensePureState(DenseStateInterface, _State):
|
|
350
353
|
|
351
354
|
mm_dict['dense_state_vector'] = self._encodemx(self.to_dense('Hilbert'))
|
352
355
|
mm_dict['basis'] = self._basis.to_nice_serialization() if (self._basis is not None) else None
|
353
|
-
|
354
356
|
return mm_dict
|
355
357
|
|
356
358
|
@classmethod
|