Coverage for picos/expressions/cone_expcone.py: 84.62%
39 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-26 07:46 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-26 07:46 +0000
1# ------------------------------------------------------------------------------
2# Copyright (C) 2019 Maximilian Stahlberg
3# Based on the original picos.expressions module by Guillaume Sagnol.
4#
5# This file is part of PICOS.
6#
7# PICOS is free software: you can redistribute it and/or modify it under the
8# terms of the GNU General Public License as published by the Free Software
9# Foundation, either version 3 of the License, or (at your option) any later
10# version.
11#
12# PICOS is distributed in the hope that it will be useful, but WITHOUT ANY
13# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along with
17# this program. If not, see <http://www.gnu.org/licenses/>.
18# ------------------------------------------------------------------------------
20"""Implements :class:`ExponentialCone`."""
22import operator
23from collections import namedtuple
25from .. import glyphs
26from ..apidoc import api_end, api_start
27from ..constraints import ExpConeConstraint
28from .cone import Cone
29from .exp_affine import AffineExpression
31_API_START = api_start(globals())
32# -------------------------------
35class ExponentialCone(Cone):
36 r"""The exponential cone.
38 Represents the convex cone
39 :math:`\operatorname{cl}\{(x,y,z): y \exp(\frac{z}{y}) \leq x, x,y > 0\}`.
40 """
42 def __init__(self):
43 """Construct an exponential cone."""
44 typeStr = "Exponential Cone"
45 symbStr = glyphs.closure(glyphs.set(glyphs.sep(
46 glyphs.col_vectorize("x", "y", "z"), ", ".join([
47 glyphs.le(
48 glyphs.mul("y", glyphs.exp(glyphs.div("z", "y"))), "x"),
49 glyphs.gt("x", 0),
50 glyphs.gt("y", 0)
51 ]))))
53 Cone.__init__(self, 3, typeStr, symbStr)
55 def _get_mutables(self):
56 return frozenset()
58 def _replace_mutables(self):
59 return self
61 Subtype = namedtuple("Subtype", ())
63 def _get_subtype(self):
64 return self.Subtype()
66 @classmethod
67 def _predict(cls, subtype, relation, other):
68 assert isinstance(subtype, cls.Subtype)
70 if relation == operator.__rshift__:
71 if issubclass(other.clstype, AffineExpression):
72 if other.subtype.dim == 3:
73 return ExpConeConstraint.make_type()
75 return Cone._predict_base(cls, subtype, relation, other)
77 def _rshift_implementation(self, element):
78 if isinstance(element, AffineExpression):
79 if len(element) != 3:
80 raise TypeError("Elements of the exponential cone must be "
81 "three-dimensional.")
83 return ExpConeConstraint(element)
85 # Handle scenario uncertainty for all cones.
86 return Cone._rshift_base(self, element)
88 @property
89 def dual_cone(self):
90 """Implement :attr:`.cone.Cone.dual_cone`."""
91 raise NotImplementedError(
92 "PICOS does not have an explicit representation for the dual of "
93 "the exponential cone yet.")
96# --------------------------------------
97__all__ = api_end(_API_START, globals())