diff --git a/pygsti/modelmembers/operations/experrorgenop.py b/pygsti/modelmembers/operations/experrorgenop.py index 142ee2c21..53e0a474a 100644 --- a/pygsti/modelmembers/operations/experrorgenop.py +++ b/pygsti/modelmembers/operations/experrorgenop.py @@ -24,6 +24,7 @@ from pygsti.modelmembers.errorgencontainer import ErrorGeneratorContainer as _ErrorGeneratorContainer from pygsti.baseobjs.polynomial import Polynomial as _Polynomial from pygsti.tools import matrixtools as _mt +from pygsti.tools import optools as _ot IMAG_TOL = 1e-7 # tolerance for imaginary part being considered zero MAX_EXPONENT = _np.log(_np.finfo('d').max) - 10.0 # so that exp(.) doesn't overflow @@ -180,11 +181,22 @@ def to_dense(self, on_space='minimal'): """ if self._rep_type == 'dense': # Then self._rep contains a dense version already - return self._rep.base # copy() unnecessary since we set to readonly + superop = self._rep.base # copy() unnecessary since we set to readonly else: # Construct a dense version from scratch (more time consuming) - return _spl.expm(self.errorgen.to_dense(on_space)) + superop = _spl.expm(self.errorgen.to_dense(on_space)) + + # Attempt to cast down to unitary, if requested + if on_space == 'Hilbert' or (on_space == 'minimal' and self.evotype.minimal_space == 'Hilbert'): + try: + U = _ot.superop_to_unitary(superop, self.errorgen.matrix_basis, True) + except ValueError as e: + raise ValueError("Could not convert to unitary. Check that only Hamiltonian errors are provided.") from e + + return U + + return superop #FUTURE: maybe remove this function altogether, as it really shouldn't be called def to_sparse(self, on_space='minimal'): diff --git a/pygsti/modelmembers/operations/lindbladerrorgen.py b/pygsti/modelmembers/operations/lindbladerrorgen.py index e0b42df6e..7dcba2511 100644 --- a/pygsti/modelmembers/operations/lindbladerrorgen.py +++ b/pygsti/modelmembers/operations/lindbladerrorgen.py @@ -761,25 +761,14 @@ def to_dense(self, on_space='minimal'): numpy.ndarray """ if self._rep_type == 'lindblad errorgen': - # assert(on_space in ('minimal', 'HilbertSchmidt')) + assert(on_space in ('minimal', 'HilbertSchmidt')) lnd_error_gen = sum([_np.tensordot(blk.block_data.flat, Lterm_superops, (0, 0)) for blk, (Lterm_superops, _) in zip(self.coefficient_blocks, self.lindblad_term_superops_and_1norms)]) assert(_np.isclose(_np.linalg.norm(lnd_error_gen.imag), 0)), \ "Imaginary error gen norm: %g" % _np.linalg.norm(lnd_error_gen.imag) - superop = lnd_error_gen.real - - if on_space == 'Hilbert' or (on_space == 'minimal' and self.evotype.minimal_space == 'Hilbert'): - # Attempt to cast down to unitary - try: - U = _ot.superop_to_unitary(lnd_error_gen.real, self.matrix_basis, True) - except ValueError as e: - raise ValueError("Could not convert to unitary. Check that only Hamiltonian errors are provided.") from e - - return U - - return superop + return lnd_error_gen.real elif self._rep_type == 'sparse superop': return self.to_sparse(on_space).toarray()