Commit 5da67fad authored by kerry-he's avatar kerry-he
Browse files

Cleaned up constraints

parent 588bf417
Loading
Loading
Loading
Loading
Loading
+127 −281
Original line number Diff line number Diff line
@@ -28,12 +28,9 @@ from .constraint import Constraint
_API_START = api_start(globals())
# -------------------------------

class TrRenyiEntrEpiConstraint(Constraint):
    """Upper bound of a convex trace function for Renyi entropies.

    This is the upper bound on a convex trace function for Renyi entropies,
    represented by :class:`~picos.expressions.TrRenyiEntropy`.
    """
class BaseRenyiEntrConstraint(Constraint):
    """Base class representing general Renyi entropy constraints."""

    def __init__(self, divergence, upperBound):
        """Construct a :class:`TrRenyiEntrEpiConstraint`.
@@ -43,29 +40,36 @@ class TrRenyiEntrEpiConstraint(Constraint):
        :param ~picos.expressions.AffineExpression upperBound:
            Upper bound on the expression.
        """
        from ..expressions import AffineExpression, TrRenyiEntropy
        from ..expressions import AffineExpression
        required_divergence = self._required_divergence()
        required_type = self._required_type()

        assert isinstance(divergence, TrRenyiEntropy)
        assert isinstance(divergence, required_divergence)
        assert isinstance(upperBound, AffineExpression)
        assert len(upperBound) == 1
        assert (-1 <= divergence.alpha and divergence.alpha <= 0) or \
               ( 1 <= divergence.alpha and divergence.alpha <= 2)
        assert self._is_valid_alpha(divergence.alpha)

        self.divergence = divergence
        self.upperBound = upperBound

        required_type = self._required_type()

        assert isinstance(divergence.X, required_type)
        assert isinstance(divergence.Y, required_type)

        super(TrRenyiEntrEpiConstraint, self).__init__(divergence._typeStr)
        super(BaseRenyiEntrConstraint, self).__init__(divergence._typeStr)

    def _required_type(self):
        from ..expressions import AffineExpression

        return AffineExpression

    @property
    def u(self):
        """The :math:`u` of the divergence."""
        # TODO: Allow u to be an arbitrary affine expression
        from ..expressions import Constant

        return Constant(1.0)

    @property
    def X(self):
        """The :math:`X` of the divergence."""
@@ -89,7 +93,7 @@ class TrRenyiEntrEpiConstraint(Constraint):
    @classmethod
    def _cost(cls, subtype):
        n = subtype.argdim
        return n * (n + 1) + 1
        return n * (n + 1) + 2

    def _expression_names(self):
        yield "divergence"
@@ -100,104 +104,51 @@ class TrRenyiEntrEpiConstraint(Constraint):

    def _get_size(self):
        n = self.X.shape[0]
        return (2 * n * n + 1, 1)
        return (2 * n * n + 1, 2)

    def _get_slack(self):
        return self.upperBound.safe_value - self.divergence.safe_value

class RenyiEntrConstraint(BaseRenyiEntrConstraint):
    """Upper bound of Renyi entropies.

class ComplexTrRenyiEntrEpiConstraint(TrRenyiEntrEpiConstraint):
    """Upper bound of trace of a complex convex trace function for Renyi entropies."""

    # TODO: Implement real conversion of matrix geometric mean cone

    def _required_type(self):
        from ..expressions import ComplexAffineExpression

        return ComplexAffineExpression


class TrRenyiEntrHypoConstraint(Constraint):
    """Lower bound of a concave trace function for Renyi entropies.

    This is the lower bound on the trace of a concave matrix geometric mean,
    represented by :class:`~picos.expressions.TrRenyiEntropy`.
    This is the upper bound on Renyi entropies, represented by 
    :class:`~picos.expressions.RenyiEntropy`.
    """

    def __init__(self, divergence, lowerBound):
        """Construct a :class:`RenyiEntrEpiConstraint`.
    def _required_divergence(self):
        from ..expressions import RenyiEntropy

        :param ~picos.expressions.TrRenyiEntropy divergence:
            Constrained expression.
        :param ~picos.expressions.AffineExpression lowerBound:
            Lower bound on the expression.
        """
        from ..expressions import AffineExpression, TrRenyiEntropy

        assert isinstance(divergence, TrRenyiEntropy)
        assert isinstance(lowerBound, AffineExpression)
        assert len(lowerBound) == 1
        assert 0 <= divergence.alpha and divergence.alpha <= 1

        self.divergence = divergence
        self.lowerBound = lowerBound
        return RenyiEntropy

        required_type = self._required_type()

        assert isinstance(divergence.X, required_type)
        assert isinstance(divergence.Y, required_type)
    def _is_valid_alpha(self, alpha):
        return 0 <= alpha and alpha < 1

        super(TrRenyiEntrHypoConstraint, self).__init__(divergence._typeStr)
class ComplexRenyiEntrConstraint(RenyiEntrConstraint):
    """Upper bound of complex Renyi entropies."""

    def _required_type(self):
        from ..expressions import AffineExpression

        return AffineExpression

    @property
    def X(self):
        """The :math:`X` of the divergence."""
        return self.divergence.X

    @cached_property
    def Y(self):
        """The :math:`Y` of the divergence."""
        return self.divergence.Y

    @cached_property
    def alpha(self):
        r"""The parameter :math:`\alpha`."""
        return self.divergence.alpha

    Subtype = namedtuple("Subtype", ("argdim",))

    def _subtype(self):
        return self.Subtype(self.X.shape[0] ** 2)

    @classmethod
    def _cost(cls, subtype):
        n = subtype.argdim
        return n * (n + 1) + 1
        from ..expressions import ComplexAffineExpression

    def _expression_names(self):
        yield "divergence"
        yield "lowerBound"
        return ComplexAffineExpression

    def _str(self):
        return glyphs.ge(self.divergence.string, self.lowerBound.string)
class SandRenyiEntrConstraint(BaseRenyiEntrConstraint):
    """Upper bound of sandwiched Renyi entropies.

    def _get_size(self):
        n = self.X.shape[0]
        return (2 * n * n + 1, 1)
    This is the upper bound on sandwiched Renyi entropies, represented by 
    :class:`~picos.expressions.SandRenyiEntropy`.
    """

    def _get_slack(self):
        return self.lowerBound.safe_value - self.divergence.safe_value
    def _required_divergence(self):
        from ..expressions import SandRenyiEntropy

        return SandRenyiEntropy

class ComplexTrRenyiEntrHypoConstraint(TrRenyiEntrHypoConstraint):
    """Lower bound of a complex concave trace function for Renyi entropies."""
    def _is_valid_alpha(self, alpha):
        return 0.5 <= alpha and alpha < 1

    # TODO: Implement real conversion of matrix geometric mean cone
class ComplexSandRenyiEntrConstraint(SandRenyiEntrConstraint):
    """Upper bound of complex sandwiched Renyi entropies."""

    def _required_type(self):
        from ..expressions import ComplexAffineExpression
@@ -205,51 +156,43 @@ class ComplexTrRenyiEntrHypoConstraint(TrRenyiEntrHypoConstraint):
        return ComplexAffineExpression


class RenyiEntrConstraint(Constraint):
    """Upper bound of a convex trace function for Renyi entropies.
# ----------------

    This is the upper bound on a convex trace function for Renyi entropies,
    represented by :class:`~picos.expressions.TrRenyiEntropy`.
class BaseTrRenyiEntrEpiConstraint(Constraint):
    """Base class representing general upper bound on convex trace functions
    used to define Renyi entropies.
    """

    def __init__(self, divergence, upperBound):
        """Construct a :class:`TrRenyiEntrEpiConstraint`.
        """Construct a :class:`BaseTrRenyiEntrEpiConstraint`.

        :param ~picos.expressions.TrRenyiEntropy divergence:
            Constrained expression.
        :param ~picos.expressions.AffineExpression upperBound:
            Upper bound on the expression.
        """
        from ..expressions import AffineExpression, RenyiEntropy
        from ..expressions import AffineExpression
        required_divergence = self._required_divergence()
        required_type = self._required_type()

        assert isinstance(divergence, RenyiEntropy)
        assert isinstance(divergence, required_divergence)
        assert isinstance(upperBound, AffineExpression)
        assert len(upperBound) == 1
        assert 0 <= divergence.alpha and divergence.alpha < 1
        assert self._is_valid_alpha(divergence.alpha)

        self.divergence = divergence
        self.upperBound = upperBound

        required_type = self._required_type()

        assert isinstance(divergence.X, required_type)
        assert isinstance(divergence.Y, required_type)

        super(RenyiEntrConstraint, self).__init__(divergence._typeStr)
        super(BaseRenyiEntrConstraint, self).__init__(divergence._typeStr)

    def _required_type(self):
        from ..expressions import AffineExpression

        return AffineExpression

    @property
    def u(self):
        """The :math:`u` of the divergence."""
        # TODO: Allow u to be an arbitrary affine expression
        from ..expressions import Constant

        return Constant(1.0)

    @property
    def X(self):
        """The :math:`X` of the divergence."""
@@ -290,115 +233,66 @@ class RenyiEntrConstraint(Constraint):
        return self.upperBound.safe_value - self.divergence.safe_value


class ComplexRenyiEntrConstraint(RenyiEntrConstraint):
    """Upper bound of trace of a complex convex trace function for Renyi entropies."""

    # TODO: Implement real conversion of matrix geometric mean cone

    def _required_type(self):
        from ..expressions import ComplexAffineExpression

        return ComplexAffineExpression



# --------------------------------
class TrRenyiEntrEpiConstraint(BaseTrRenyiEntrEpiConstraint):
    """Upper bound of trace function used to define Renyi entropies.


class TrSandRenyiEntrEpiConstraint(Constraint):
    """Upper bound of a convex trace function for Renyi entropies.

    This is the upper bound on a convex trace function for Renyi entropies,
    represented by :class:`~picos.expressions.TrRenyiEntropy`.
    This is the upper bound on convex trace functions used to define Renyi 
    entropies, represented by :class:`~picos.expressions.TrRenyiEntropy`.
    """

    def __init__(self, divergence, upperBound):
        """Construct a :class:`TrRenyiEntrEpiConstraint`.
    def _required_divergence(self):
        from ..expressions import TrRenyiEntropy

        :param ~picos.expressions.TrRenyiEntropy divergence:
            Constrained expression.
        :param ~picos.expressions.AffineExpression upperBound:
            Upper bound on the expression.
        """
        from ..expressions import AffineExpression, TrSandRenyiEntropy

        assert isinstance(divergence, TrSandRenyiEntropy)
        assert isinstance(upperBound, AffineExpression)
        assert len(upperBound) == 1
        assert (-1 <= divergence.alpha and divergence.alpha <= 0) or \
               ( 1 <= divergence.alpha and divergence.alpha <= 2)

        self.divergence = divergence
        self.upperBound = upperBound
        return TrRenyiEntropy

        required_type = self._required_type()
    def _is_valid_alpha(self, alpha):
        return (-1 <= alpha and alpha <= 0) or (1 <= alpha and alpha <= 2)

        assert isinstance(divergence.X, required_type)
        assert isinstance(divergence.Y, required_type)

        super(TrSandRenyiEntrEpiConstraint, self).__init__(divergence._typeStr)
class ComplexTrRenyiEntrEpiConstraint(TrRenyiEntrEpiConstraint):
    """Upper bound of complex convex trace function used to define Renyi 
    entropies.
    """

    def _required_type(self):
        from ..expressions import AffineExpression

        return AffineExpression

    @property
    def X(self):
        """The :math:`X` of the divergence."""
        return self.divergence.X

    @cached_property
    def Y(self):
        """The :math:`Y` of the divergence."""
        return self.divergence.Y

    @cached_property
    def alpha(self):
        r"""The parameter :math:`\alpha`."""
        return self.divergence.alpha
        from ..expressions import ComplexAffineExpression

    Subtype = namedtuple("Subtype", ("argdim",))
        return ComplexAffineExpression
    
    def _subtype(self):
        return self.Subtype(self.X.shape[0] ** 2)

    @classmethod
    def _cost(cls, subtype):
        n = subtype.argdim
        return n * (n + 1) + 1
class TrSandRenyiEntrEpiConstraint(BaseTrRenyiEntrEpiConstraint):
    """Upper bound of trace function used to define sandwiched Renyi entropies.

    def _expression_names(self):
        yield "divergence"
        yield "upperBound"

    def _str(self):
        return glyphs.le(self.divergence.string, self.upperBound.string)
    This is the upper bound on convex trace functions used to define sandwiched 
    Renyi entropies, represented by 
    :class:`~picos.expressions.TrSandRenyiEntropy`.
    """

    def _get_size(self):
        n = self.X.shape[0]
        return (2 * n * n + 1, 1)
    def _required_divergence(self):
        from ..expressions import TrSandRenyiEntropy

    def _get_slack(self):
        return self.upperBound.safe_value - self.divergence.safe_value
        return TrSandRenyiEntropy

    def _is_valid_alpha(self, alpha):
        return 1 <= alpha and alpha <= 2

class ComplexTrSandRenyiEntrEpiConstraint(TrSandRenyiEntrEpiConstraint):
    """Upper bound of trace of a complex convex trace function for Renyi entropies."""

    # TODO: Implement real conversion of matrix geometric mean cone
class ComplexTrSandRenyiEntrEpiConstraint(TrRenyiEntrEpiConstraint):
    """Upper bound of complex convex trace function used to define sandwiched  
    Renyi entropies.
    """

    def _required_type(self):
        from ..expressions import ComplexAffineExpression

        return ComplexAffineExpression

# --------------

class TrSandRenyiEntrHypoConstraint(Constraint):
    """Lower bound of a concave trace function for Renyi entropies.

    This is the lower bound on the trace of a concave matrix geometric mean,
    represented by :class:`~picos.expressions.TrRenyiEntropy`.
class BaseTrRenyiEntrHypoConstraint(Constraint):
    """Base class representing general lower bound on concave trace functions
    used to define Renyi entropies.
    """

    def __init__(self, divergence, lowerBound):
@@ -409,12 +303,14 @@ class TrSandRenyiEntrHypoConstraint(Constraint):
        :param ~picos.expressions.AffineExpression lowerBound:
            Lower bound on the expression.
        """
        from ..expressions import AffineExpression, TrSandRenyiEntropy
        from ..expressions import AffineExpression
        required_divergence = self._required_divergence()
        required_type = self._required_type()

        assert isinstance(divergence, TrSandRenyiEntropy)
        assert isinstance(divergence, required_divergence)
        assert isinstance(lowerBound, AffineExpression)
        assert len(lowerBound) == 1
        assert 0 <= divergence.alpha and divergence.alpha <= 1
        assert self._is_valid_alpha(divergence.alpha)

        self.divergence = divergence
        self.lowerBound = lowerBound
@@ -424,7 +320,7 @@ class TrSandRenyiEntrHypoConstraint(Constraint):
        assert isinstance(divergence.X, required_type)
        assert isinstance(divergence.Y, required_type)

        super(TrSandRenyiEntrHypoConstraint, self).__init__(divergence._typeStr)
        super(BaseTrRenyiEntrHypoConstraint, self).__init__(divergence._typeStr)

    def _required_type(self):
        from ..expressions import AffineExpression
@@ -470,109 +366,59 @@ class TrSandRenyiEntrHypoConstraint(Constraint):
    def _get_slack(self):
        return self.lowerBound.safe_value - self.divergence.safe_value

class TrRenyiEntrHypoConstraint(BaseTrRenyiEntrHypoConstraint):
    """Lower bound of trace function used to define Renyi entropies.

class ComplexTrSandRenyiEntrHypoConstraint(TrSandRenyiEntrHypoConstraint):
    """Lower bound of a complex concave trace function for Renyi entropies."""

    # TODO: Implement real conversion of matrix geometric mean cone

    def _required_type(self):
        from ..expressions import ComplexAffineExpression

        return ComplexAffineExpression


class SandRenyiEntrConstraint(Constraint):
    """Upper bound of a convex trace function for Renyi entropies.

    This is the upper bound on a convex trace function for Renyi entropies,
    represented by :class:`~picos.expressions.TrRenyiEntropy`.
    """

    def __init__(self, divergence, upperBound):
        """Construct a :class:`TrRenyiEntrEpiConstraint`.

        :param ~picos.expressions.TrRenyiEntropy divergence:
            Constrained expression.
        :param ~picos.expressions.AffineExpression upperBound:
            Upper bound on the expression.
    This is the lower bound on concave trace functions used to define Renyi 
    entropies, represented by :class:`~picos.expressions.TrRenyiEntropy`.
    """
        from ..expressions import AffineExpression, SandRenyiEntropy

        assert isinstance(divergence, SandRenyiEntropy)
        assert isinstance(upperBound, AffineExpression)
        assert len(upperBound) == 1
        assert 0 <= divergence.alpha and divergence.alpha < 1
    def _required_divergence(self):
        from ..expressions import TrRenyiEntropy

        self.divergence = divergence
        self.upperBound = upperBound
        return TrRenyiEntropy

        required_type = self._required_type()
    def _is_valid_alpha(self, alpha):
        return 0 <= alpha and alpha <= 1

        assert isinstance(divergence.X, required_type)
        assert isinstance(divergence.Y, required_type)

        super(SandRenyiEntrConstraint, self).__init__(divergence._typeStr)
class ComplexTrRenyiEntrHypoConstraint(TrRenyiEntrHypoConstraint):
    """Lower bound of complex concave trace function used to define Renyi 
    entropies.
    """

    def _required_type(self):
        from ..expressions import AffineExpression

        return AffineExpression

    @property
    def u(self):
        """The :math:`u` of the divergence."""
        # TODO: Allow u to be an arbitrary affine expression
        from ..expressions import Constant

        return Constant(1.0)

    @property
    def X(self):
        """The :math:`X` of the divergence."""
        return self.divergence.X

    @cached_property
    def Y(self):
        """The :math:`Y` of the divergence."""
        return self.divergence.Y

    @cached_property
    def alpha(self):
        r"""The parameter :math:`\alpha`."""
        return self.divergence.alpha
        from ..expressions import ComplexAffineExpression

    Subtype = namedtuple("Subtype", ("argdim",))
        return ComplexAffineExpression
    
    def _subtype(self):
        return self.Subtype(self.X.shape[0] ** 2)

    @classmethod
    def _cost(cls, subtype):
        n = subtype.argdim
        return n * (n + 1) + 2
class TrSandRenyiEntrHypoConstraint(BaseTrRenyiEntrHypoConstraint):
    """Lower bound of trace function used to define sandwiched Renyi entropies.

    def _expression_names(self):
        yield "divergence"
        yield "upperBound"
    This is the lower bound on concave trace functions used to define sandwiched 
    Renyi entropies, represented by 
    :class:`~picos.expressions.TrSandRenyiEntropy`.
    """

    def _str(self):
        return glyphs.le(self.divergence.string, self.upperBound.string)
    def _required_divergence(self):
        from ..expressions import TrSandRenyiEntropy

    def _get_size(self):
        n = self.X.shape[0]
        return (2 * n * n + 1, 2)
        return TrSandRenyiEntropy

    def _get_slack(self):
        return self.upperBound.safe_value - self.divergence.safe_value
    def _is_valid_alpha(self, alpha):
        return 0.5 <= alpha and alpha <= 1


class ComplexSandRenyiEntrConstraint(SandRenyiEntrConstraint):
    """Upper bound of trace of a complex convex trace function for Renyi entropies."""

    # TODO: Implement real conversion of matrix geometric mean cone
class ComplexTrSandRenyiEntrHypoConstraint(TrSandRenyiEntrHypoConstraint):
    """Lower bound of complex concave trace function used to define sandwiched  
    Renyi entropies.
    """

    def _required_type(self):
        from ..expressions import ComplexAffineExpression

        return ComplexAffineExpression
    
# --------------------------------------
__all__ = api_end(_API_START, globals())
+24 −19
Original line number Diff line number Diff line
@@ -223,7 +223,7 @@ class RenyiEntropy(BaseRenyiEntropy):

        \frac{1}{\alpha-1}\log(\operatorname{Tr}[ X^\alpha Y^{1-\alpha} ]),

    for some :math:`\alpha\in[-1, 2]`.
    for some :math:`\alpha\in[0, 1)`.

    .. warning::

@@ -259,7 +259,8 @@ class RenyiEntropy(BaseRenyiEntropy):
        Dy, Uy = numpy.linalg.eigh(Y)
        Y_beta = Uy @ numpy.diag(numpy.power(Dy, 1 - self._alpha)) @ Uy.conj().T

        s = numpy.log(numpy.sum(X_alpha * Y_beta.conj()).real) / (self._alpha - 1)
        t = numpy.sum(X_alpha * Y_beta.conj()).real
        s = numpy.log(t) / (self._alpha - 1)

        return cvxopt.matrix(s)

@@ -286,9 +287,10 @@ class SandRenyiEntropy(BaseRenyiEntropy):

    .. math::

        \frac{1}{\alpha-1}\log(\operatorname{Tr}[ X^\alpha Y^{1-\alpha} ]),
        \frac{1}{\alpha-1}\log(\operatorname{Tr}[ (Y^{\frac{1-\alpha}{2\alpha} 
        X Y^{\frac{1-\alpha}{2\alpha})^\alpha ]),

    for some :math:`\alpha\in[-1, 2]`.
    for some :math:`\alpha\in[1/2, 1)`.

    .. warning::

@@ -324,7 +326,8 @@ class SandRenyiEntropy(BaseRenyiEntropy):

        Dyxy = numpy.linalg.eigvalsh(Y_beta @ X @ Y_beta)

        s = numpy.log(numpy.sum(numpy.power(Dyxy, self._alpha))) / (self._alpha - 1)
        t = numpy.sum(numpy.power(Dyxy, self._alpha))
        s = numpy.log(t) / (self._alpha - 1)

        return cvxopt.matrix(s)

@@ -350,7 +353,7 @@ class BaseTrRenyiEntropy(Expression):

    @convert_and_refine_arguments("X", "Y")
    def __init__(self, X, Y, alpha):
        """Construct an :class:`MatrixGeometricMean`.
        """Construct an :class:`BaseTrRenyiEntropy`.

        :param X: The affine expression :math:`X`.
        :type X: ~picos.expressions.AffineExpression
@@ -487,22 +490,23 @@ class BaseTrRenyiEntropy(Expression):
        isconvex = (-1 <= subtype.alpha and subtype.alpha <= 0) or \
                   ( 1 <= subtype.alpha and subtype.alpha <= 2)
        isconcave = 0 <= subtype.alpha and subtype.alpha <= 1
        argdim = subtype.argdim

        if relation == operator.__le__ and isconvex:
            if subtype.iscomplex or not issubclass(
                other.clstype, AffineExpression
            ):
                return cls._ComplexEpiConstraint().make_type(argdim=subtype.argdim)
                return cls._ComplexEpiConstraint().make_type(argdim=argdim)
            else:
                return cls._RealEpiConstraint().make_type(argdim=subtype.argdim)
                return cls._RealEpiConstraint().make_type(argdim=argdim)

        if relation == operator.__ge__ and isconcave:
            if subtype.iscomplex or not issubclass(
                other.clstype, AffineExpression
            ):
                return cls._ComplexHypoConstraint().make_type(argdim=subtype.argdim)
                return cls._ComplexHypoConstraint().make_type(argdim=argdim)
            else:
                return cls._RealHypoConstraint().make_type(argdim=subtype.argdim)
                return cls._RealHypoConstraint().make_type(argdim=argdim)

        return NotImplemented

@@ -531,7 +535,7 @@ class BaseTrRenyiEntropy(Expression):
            return NotImplemented
        
class TrRenyiEntropy(BaseTrRenyiEntropy):
    r"""Renyi entropy of an affine expression.
    r"""Trace Renyi entropy of an affine expression.

    :Definition:

@@ -540,7 +544,7 @@ class TrRenyiEntropy(BaseTrRenyiEntropy):

    .. math::

        \frac{1}{\alpha-1}\log(\operatorname{Tr}[ X^\alpha Y^{1-\alpha} ]),
        \operatorname{Tr}[ X^\alpha Y^{1-\alpha} ],

    for some :math:`\alpha\in[-1, 2]`.

@@ -561,8 +565,8 @@ class TrRenyiEntropy(BaseTrRenyiEntropy):
        
    def _get_strings(self):
        typeStr = "Trace Renyi Entropy"
        xStr = glyphs.power(self._X.string, str(self._alpha))
        yStr = glyphs.power(self._Y.string, str(1 - self._alpha))
        xStr = glyphs.power(self._X.string, "a")
        yStr = glyphs.power(self._Y.string, "1-a")
        symbStr = glyphs.trace(glyphs.mul(xStr, yStr))
        return typeStr, symbStr

@@ -606,7 +610,7 @@ class TrRenyiEntropy(BaseTrRenyiEntropy):
    

class TrSandRenyiEntropy(BaseTrRenyiEntropy):
    r"""Renyi entropy of an affine expression.
    r"""Trace sandwiched Renyi entropy of an affine expression.

    :Definition:

@@ -615,9 +619,10 @@ class TrSandRenyiEntropy(BaseTrRenyiEntropy):

    .. math::

        \frac{1}{\alpha-1}\log(\operatorname{Tr}[ X^\alpha Y^{1-\alpha} ]),
        \operatorname{Tr}[ (Y^{\frac{1-\alpha}{2\alpha} X 
        Y^{\frac{1-\alpha}{2\alpha})^\alpha ],

    for some :math:`\alpha\in[-1, 2]`.
    for some :math:`\alpha\in[1/2, 2]`.

    .. warning::

@@ -631,8 +636,8 @@ class TrSandRenyiEntropy(BaseTrRenyiEntropy):
    # --------------------------------------------------------------------------

    def _is_valid_alpha(self, alpha):
        if not (numpy.isscalar(alpha) and 0 <= alpha and alpha <= 2):
            raise TypeError("The exponent alpha must be a scalar in [0, 2]")
        if not (numpy.isscalar(alpha) and 0.5 <= alpha and alpha <= 2):
            raise TypeError("The exponent alpha must be a scalar in [1/2, 2]")
        
    def _get_strings(self):
        typeStr = "Trace Sandwiched Renyi Entropy"
+5 −0

File changed.

Preview size limit exceeded, changes collapsed.