Skip to content

Commit

Permalink
remove EmbeddedBasis class that accidentally was kept during a rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
rileyjmurray committed Jan 17, 2025
1 parent a351c31 commit 0346cca
Showing 1 changed file with 1 addition and 279 deletions.
280 changes: 1 addition & 279 deletions pygsti/baseobjs/basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1761,6 +1761,7 @@ def create_simple_equivalent(self, builtin_basis_name=None):
builtin_basis_name = first_comp_name # if all components have the same name
return BuiltinBasis(builtin_basis_name, self.elsize, sparse=self.sparse)


class OuterProdBasis(TensorProdBasis):

def __init__(self, component_bases, name=None, longname=None, squeeze=True):
Expand Down Expand Up @@ -1832,282 +1833,3 @@ def create_equivalent(self, builtin_basis_name):
def create_simple_equivalent(self, builtin_basis_name=None):
raise NotImplementedError()


class EmbeddedBasis(LazyBasis):
"""
A basis that embeds a basis for a smaller state space within a larger state space.
The elements of an EmbeddedBasis are therefore just embedded versions
of the elements of the basis that is embedded.
Parameters
----------
basis_to_embed : Basis
The basis being embedded.
state_space_labels : StateSpaceLabels
An object describing the struture of the entire state space.
target_labels : list or tuple
The labels contained in `stateSpaceLabels` which demarcate the
portions of the state space acted on by `basis_to_embed`.
name : str, optional
The name of this basis. If `None`, the names of `basis_to_embed`
is joined with ':' characters to the elements of `target_labels`.
longname : str, optional
A longer description of this basis. If `None`, then a long name is
automatically generated.
"""

@classmethod
def embed_label(cls, lbl, target_labels):
"""
Gets the EmbeddedBasis label for `lbl`.
Convenience method that gives the EmbeddedBasis label for `lbl`
without needing to construct the `EmbeddedBasis`. E.g. `"XX:1,2"`.
Parameters
----------
lbl : str
Un-embedded basis element label, e.g. `"XX"`.
target_labels : tuple
The target state space labels upon which this basis element
will be embedded, e.g. `(1,2)`
Returns
-------
str
The embedded-basis-element label as an EmbeddedBasis would
assign it. E.g. `"XX:1,2"`.
"""
return "%s:%s" % (lbl, ",".join(map(str, target_labels)))

@classmethod
def unembed_label(cls, lbl, target_labels):
"""
Convenience method that performs the reverse of :meth:`embed_label`
Parameters
----------
lbl : str
Embedded basis element label, e.g. `"XX:1,2"`.
target_labels : tuple
The target state space labels upon which this basis element
will be embedded, e.g. `(1,2)`
Returns
-------
str
The un-embedded label, e.g. `"XX"`.
"""
suffix = ":" + ",".join(map(str, target_labels))
if lbl.endswith(suffix):
return lbl[:-len(suffix)]
else:
raise ValueError("Cannot unembed '%s' - doesn't end in '%s'!" % (lbl, suffix))

def __init__(self, basis_to_embed, state_space, target_labels, name=None, longname=None):
'''
Create a new EmbeddedBasis.
Parameters
----------
basis_to_embed : Basis
The basis being embedded.
state_space : StateSpace
An object describing the struture of the entire state space.
target_labels : list or tuple
The labels contained in `stateSpaceLabels` which demarcate the
portions of the state space acted on by `basis_to_embed`.
name : str, optional
The name of this basis. If `None`, the names of `basis_to_embed`
is joined with ':' characters to the elements of `target_labels`.
longname : str, optional
A longer description of this basis. If `None`, then a long name is
automatically generated.
'''
from pygsti.baseobjs.statespace import StateSpace as _StateSpace
self.embedded_basis = basis_to_embed
self.target_labels = target_labels
self.state_space = _StateSpace.cast(state_space)

if name is None:
name = ':'.join((basis_to_embed.name,) + tuple(map(str, target_labels)))
if longname is None:
longname = "Embedded %s basis as %s within %s" % \
(basis_to_embed.name, ':'.join(map(str, target_labels)), str(self.state_space))

real = basis_to_embed.real
sparse = basis_to_embed.sparse

super(EmbeddedBasis, self).__init__(name, longname, real, sparse)

def _to_nice_serialization(self):
state = super()._to_nice_serialization()
state.update({'name': self.name,
'longname': self.longname,
'state_space': self.state_space.to_nice_serialization(),
'embedded_basis': self.embedded_basis.to_nice_serialization()
})
return state

@classmethod
def _from_nice_serialization(cls, state):
basis_to_embed = Basis.from_nice_serialization(state['embedded_basis'])
state_space = _StateSpace.from_nice_serialization(state['state_space'])
return cls(basis_to_embed, state_space, state['target_labels'], state['name'], state['longname'])

@property
def dim(self):
"""
The dimension of the vector space this basis fully or partially
spans. Equivalently, the length of the `vector_elements` of the
basis.
"""
return self.state_space.dim

@property
def size(self):
"""
The number of elements (or vector-elements) in the basis.
"""
return self.embedded_basis.size

@property
def elshape(self):
"""
The shape of each element. Typically either a length-1 or length-2
tuple, corresponding to vector or matrix elements, respectively.
Note that *vector elements* always have shape `(dim,)` (or `(dim,1)`
in the sparse case).
"""
elndim = self.embedded_basis.elndim
if elndim == 2: # a "matrix" basis
d = int(_np.sqrt(self.dim))
assert(d**2 == self.dim), \
"Dimension of state_space must be a perfect square when embedding a matrix basis"
elshape = (d, d)
elif elndim == 1:
elshape = (self.dim,)
else:
raise ValueError("Can only embed bases with .elndim == 1 or 2 (received %d)!" % elndim)
return elshape

def __hash__(self):
return hash(tuple(hash(self.embedded_basis), self.target_labels, self.state_space))

def _lazy_build_elements(self):
""" Take a dense or sparse basis matrix and embed it. """
#LAZY building of elements (in case we never need them)
if self.elndim == 2: # then use EmbeddedOp to do matrix
from ..modelmembers.operations import StaticArbitraryOp
from ..modelmembers.operations import EmbeddedOp
sslbls = self.state_space.copy()
sslbls.reduce_dims_densitymx_to_state_inplace() # because we're working with basis matrices not gates

if self.sparse:
self._elements = []
for spmx in self.embedded_basis.elements:
mxAsOp = StaticArbitraryOp(spmx.to_dense(), evotype='statevec')
self._elements.append(EmbeddedOp(sslbls, self.target_labels,
mxAsOp).to_sparse())
else:
self._elements = _np.zeros((self.size,) + self.elshape, 'complex')
for i, mx in enumerate(self.embedded_basis.elements):
self._elements[i] = EmbeddedOp(
sslbls, self.target_labels, StaticArbitraryOp(mx, evotype='statevec')
).to_dense(on_space='HilbertSchmidt')
else:
# we need to perform embedding using vectors rather than matrices - doable, but
# not needed yet, so defer implementation to later.
raise NotImplementedError("Embedding *vector*-type bases not implemented yet")

def _lazy_build_labels(self):
self._labels = [EmbeddedBasis.embed_label(lbl, self.target_labels)
for lbl in self.embedded_basis.labels]

def _copy_with_toggled_sparsity(self):
return EmbeddedBasis(self.embedded_basis._copy_with_toggled_sparsity(),
self.state_space,
self.target_labels,
self.name, self.longname)

def is_equivalent(self, other, sparseness_must_match=True):
"""
Tests whether this basis is equal to another basis, optionally ignoring sparseness.
Parameters
-----------
other : Basis or str
The basis to compare with.
sparseness_must_match : bool, optional
If `False` then comparison ignores differing sparseness, and this function
returns `True` when the two bases are equal except for their `.sparse` values.
Returns
-------
bool
"""
otherIsBasis = isinstance(other, EmbeddedBasis)
if not otherIsBasis: return False # can't be equal to a non-EmbeddedBasis
if self.target_labels != other.target_labels or self.state_space != other.state_space:
return False
return self.embedded_basis.is_equivalent(other.embedded_basis, sparseness_must_match)

def create_equivalent(self, builtin_basis_name):
"""
Create an equivalent basis with components of type `builtin_basis_name`.
Create a Basis that is equivalent in structure & dimension to this
basis but whose simple components (perhaps just this basis itself) is
of the builtin basis type given by `builtin_basis_name`.
Parameters
----------
builtin_basis_name : str
The name of a builtin basis, e.g. `"pp"`, `"gm"`, or `"std"`. Used to
construct the simple components of the returned basis.
Returns
-------
EmbeddedBasis
"""
equiv_embedded = self.embedded_basis.create_equivalent(builtin_basis_name)
return EmbeddedBasis(equiv_embedded, self.state_space, self.target_labels)

def create_simple_equivalent(self, builtin_basis_name=None):
"""
Create a basis of type `builtin_basis_name` whose elements are compatible with this basis.
Create a simple basis *and* one without components (e.g. a
:class:`TensorProdBasis`, is a simple basis w/components) of the
builtin type specified whose dimension is compatible with the
*elements* of this basis. This function might also be named
"element_equivalent", as it returns the `builtin_basis_name`-analogue
of the standard basis that this basis's elements are expressed in.
Parameters
----------
builtin_basis_name : str, optional
The name of the built-in basis to use. If `None`, then a
copy of this basis is returned (if it's simple) or this
basis's name is used to try to construct a simple and
component-free version of the same builtin-basis type.
Returns
-------
Basis
"""
if builtin_basis_name is None:
builtin_basis_name = self.embedded_basis.name # default
return BuiltinBasis(builtin_basis_name, self.elsize, sparse=self.sparse)

0 comments on commit 0346cca

Please sign in to comment.