Skip to content

Commit 54b6b16

Browse files
authored
Merge pull request #616 from sandialabs/errorgens-gaugeopt-and-more
New gauge group, plus minor changes to error generator classes
2 parents 341b279 + b13cfa8 commit 54b6b16

File tree

7 files changed

+247
-65
lines changed

7 files changed

+247
-65
lines changed

pygsti/modelmembers/operations/embeddederrorgen.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import warnings as _warnings
1515

1616
from pygsti.modelmembers.operations.embeddedop import EmbeddedOp as _EmbeddedOp
17+
from pygsti.modelmembers.operations.lindbladerrorgen import LindbladErrorgen as _LinbladErrorGen
1718

1819

1920
# Idea:
@@ -50,7 +51,7 @@ class EmbeddedErrorgen(_EmbeddedOp):
5051
of the EmbeddedErrorgen.
5152
"""
5253

53-
def __init__(self, state_space, target_labels, errgen_to_embed):
54+
def __init__(self, state_space, target_labels, errgen_to_embed: _LinbladErrorGen):
5455
_EmbeddedOp.__init__(self, state_space, target_labels, errgen_to_embed)
5556

5657
# set "API" error-generator members (to interface properly w/other objects)

pygsti/modelmembers/operations/experrorgenop.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,19 @@
1212

1313
import warnings as _warnings
1414
import math
15+
from typing import Union
1516

1617
import numpy as _np
1718
import scipy.linalg as _spl
1819
import scipy.sparse as _sps
1920
import scipy.sparse.linalg as _spsl
2021

2122
from pygsti.modelmembers.operations.linearop import LinearOperator as _LinearOperator
22-
from pygsti.modelmembers.operations.lindbladerrorgen import LindbladParameterization as _LindbladParameterization
23+
from pygsti.modelmembers.operations.lindbladerrorgen import LindbladErrorgen as _LindbladErrorgen
24+
from pygsti.modelmembers.operations.embeddederrorgen import EmbeddedErrorgen as _EmbeddedErrorGen
2325
from pygsti.modelmembers import modelmember as _modelmember, term as _term
2426
from pygsti.modelmembers.errorgencontainer import ErrorGeneratorContainer as _ErrorGeneratorContainer
2527
from pygsti.baseobjs.polynomial import Polynomial as _Polynomial
26-
from pygsti.tools import matrixtools as _mt
2728

2829
IMAG_TOL = 1e-7 # tolerance for imaginary part being considered zero
2930
MAX_EXPONENT = _np.log(_np.finfo('d').max) - 10.0 # so that exp(.) doesn't overflow
@@ -44,7 +45,7 @@ class ExpErrorgenOp(_LinearOperator, _ErrorGeneratorContainer):
4445
operator is `exp(L)`.
4546
"""
4647

47-
def __init__(self, errorgen):
48+
def __init__(self, errorgen : Union[_LindbladErrorgen, _EmbeddedErrorGen]):
4849
# Extract superop dimension from 'errorgen'
4950
state_space = errorgen.state_space
5051
self.errorgen = errorgen # don't copy (allow object reuse)

pygsti/modelmembers/operations/fulltpop.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,16 @@ class FullTPOp(_DenseOperator, _Torchable):
3535
An operation matrix that is fully parameterized except for
3636
the first row, which is frozen to be [1 0 ... 0] so that the action
3737
of the operation, when interpreted in the Pauli or Gell-Mann basis, is
38-
trace preserving (TP).
38+
trace preserving (TP). Bases other than Pauli or Gell-Mann are supported
39+
only if their first element is the identity matrix.
3940
4041
Parameters
4142
----------
4243
m : array_like or LinearOperator
4344
a square 2D array-like or LinearOperator object representing the operation action.
4445
The shape of m sets the dimension of the operation.
4546
46-
basis : Basis or {'pp','gm','std'} or None
47+
basis : Basis or {'pp','gm'} or None
4748
The basis used to construct the Hilbert-Schmidt space representation
4849
of this state as a super-operator. If None, certain functionality,
4950
such as access to Kraus operators, will be unavailable.
@@ -71,8 +72,12 @@ def __init__(self, m, basis=None, evotype="default", state_space=None):
7172
_DenseOperator.__init__(self, mx, basis, evotype, state_space)
7273
assert(self._rep.base.flags['C_CONTIGUOUS'] and self._rep.base.flags['OWNDATA'])
7374
assert(isinstance(self._ptr, _ProtectedArray))
74-
self._paramlbls = _np.array(["MxElement %d,%d" % (i, j) for i in range(1, self.dim) for j in range(self.dim)],
75-
dtype=object)
75+
self._paramlbls = _np.array(
76+
["MxElement %d,%d" % (i, j) for i in range(1, self.dim) for j in range(self.dim)], dtype=object
77+
)
78+
if self._basis is not None:
79+
assert self._basis.first_element_is_identity # type: ignore
80+
return
7681

7782
@property
7883
def _ptr(self):

pygsti/modelmembers/operations/lindbladcoefficients.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ def set_elementary_errorgens(self, elementary_errorgens, on_missing='ignore', tr
528528
raise ValueError("Missing entry for %s in dictionary of elementary errorgens." % str(eeg_lbl))
529529
flat_data[i] = val
530530

531-
self.block_data[(slice(None, None),) * self.block_data.ndim] = flat_data.reshape(self.block_data.shape)
531+
self.block_data[:] = flat_data.reshape(self.block_data.shape)
532532
self._truncate_block_data(truncate)
533533

534534
#set a flag to indicate that the coefficients (as returned by elementary_errorgens)
@@ -652,7 +652,7 @@ def _block_data_to_params(self, truncate=False):
652652
in the case of `'other'` blocks.
653653
"""
654654
if truncate is False:
655-
ttol = -1e-15 # (was -1e-12) # truncation tolerance
655+
ttol = -1e-14 # (was -1e-12) # truncation tolerance
656656
elif truncate is True:
657657
ttol = -_np.inf
658658
else:
@@ -725,25 +725,24 @@ def _block_data_to_params(self, truncate=False):
725725
nonzero_block_data = perm_block_data[0:num_nonzero, 0:num_nonzero]
726726
assert(_np.isclose(_np.linalg.norm(self.block_data), _np.linalg.norm(nonzero_block_data)))
727727

728-
#evals, U = _np.linalg.eigh(nonzero_block_data) # works too (assert hermiticity above)
729-
evals, U = _np.linalg.eig(nonzero_block_data)
728+
evals, U = _np.linalg.eigh(nonzero_block_data)
730729

731730
assert(all([ev > ttol for ev in evals])), \
732731
("Lindblad coefficients are not CPTP (truncate == %s)! (largest neg = %g)"
733-
% (str(truncate), min(evals.real)))
732+
% (str(truncate), min(evals)))
734733

735734
if ttol < 0: # if we're truncating and assert above allows *negative* eigenvalues
736735
#push any slightly negative evals of other_projs positive so that
737736
# the Cholesky decomp will work.
738-
Ui = _np.linalg.inv(U)
737+
Ui = U.T.conj()
739738
pos_evals = evals.clip(1e-16, None)
740-
nonzero_block_data = _np.dot(U, _np.dot(_np.diag(pos_evals), Ui))
739+
nonzero_block_data = U @ (pos_evals[:, None] * Ui)
741740
try:
742741
nonzero_Lmx = _np.linalg.cholesky(nonzero_block_data)
743742
# if Lmx not postitive definite, try again with 1e-12 (same lines as above)
744-
except _np.linalg.LinAlgError: # pragma: no cover
743+
except _np.linalg.LinAlgError: # pragma: no cover
745744
pos_evals = evals.clip(1e-12, 1e100) # pragma: no cover
746-
nonzero_block_data = _np.dot(U, _np.dot(_np.diag(pos_evals), Ui)) # pragma: no cover
745+
nonzero_block_data = U @ (pos_evals[:, None] * Ui) # pragma: no cover
747746
nonzero_Lmx = _np.linalg.cholesky(nonzero_block_data)
748747
else: # truncate == False or == 0 case
749748
nonzero_Lmx = _np.linalg.cholesky(nonzero_block_data)
@@ -753,15 +752,15 @@ def _block_data_to_params(self, truncate=False):
753752
Lmx = perm.T @ perm_Lmx @ perm
754753

755754
for i in range(num_bels):
756-
assert(_np.linalg.norm(_np.imag(Lmx[i, i])) < IMAG_TOL)
755+
assert(_np.abs(Lmx[i, i].imag) < IMAG_TOL)
757756
params[i, i] = Lmx[i, i].real
758757
for j in range(i):
759758
params[i, j] = Lmx[i, j].real
760759
params[j, i] = Lmx[i, j].imag
761760

762761
elif self._param_mode == "elements": # params mx stores block_data (hermitian) directly
763762
for i in range(num_bels):
764-
assert(_np.linalg.norm(_np.imag(self.block_data[i, i])) < IMAG_TOL)
763+
assert(_np.abs(self.block_data[i, i].imag) < IMAG_TOL)
765764
params[i, i] = self.block_data[i, i].real
766765
for j in range(i):
767766
params[i, j] = self.block_data[i, j].real
@@ -1257,4 +1256,4 @@ def __str__(self):
12571256

12581257
@lru_cache(maxsize=16)
12591258
def cached_diag_indices(n):
1260-
return _np.diag_indices(n)
1259+
return _np.diag_indices(n)

pygsti/modelmembers/operations/lindbladerrorgen.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,9 +465,9 @@ def from_elementary_errorgens(cls, elementary_errorgens, parameterization='auto'
465465
if parameterization == "auto" else LindbladParameterization.cast(parameterization)
466466

467467
eegs_by_typ = {
468-
'ham': {eeglbl: v for eeglbl, v in elementary_errorgens.items() if eeglbl.errorgen_type == 'H'},
469-
'other_diagonal': {eeglbl: v for eeglbl, v in elementary_errorgens.items() if eeglbl.errorgen_type == 'S'},
470-
'other': {eeglbl: v for eeglbl, v in elementary_errorgens.items() if eeglbl.errorgen_type != 'H'}
468+
'ham': {eeglbl: v for eeglbl, v in elementary_errorgens.items() if eeglbl.errorgen_type == 'H' },
469+
'other_diagonal': {eeglbl: v for eeglbl, v in elementary_errorgens.items() if eeglbl.errorgen_type == 'S' },
470+
'other': {eeglbl: v for eeglbl, v in elementary_errorgens.items() if eeglbl.errorgen_type != 'H' }
471471
}
472472

473473
blocks = []

0 commit comments

Comments
 (0)