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

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# ------------------------------------------------------------------------------ 

19 

20"""Implements :class:`ExponentialCone`.""" 

21 

22import operator 

23from collections import namedtuple 

24 

25from .. import glyphs 

26from ..apidoc import api_end, api_start 

27from ..constraints import ExpConeConstraint 

28from .cone import Cone 

29from .exp_affine import AffineExpression 

30 

31_API_START = api_start(globals()) 

32# ------------------------------- 

33 

34 

35class ExponentialCone(Cone): 

36 r"""The exponential cone. 

37 

38 Represents the convex cone 

39 :math:`\operatorname{cl}\{(x,y,z): y \exp(\frac{z}{y}) \leq x, x,y > 0\}`. 

40 """ 

41 

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 ])))) 

52 

53 Cone.__init__(self, 3, typeStr, symbStr) 

54 

55 def _get_mutables(self): 

56 return frozenset() 

57 

58 def _replace_mutables(self): 

59 return self 

60 

61 Subtype = namedtuple("Subtype", ()) 

62 

63 def _get_subtype(self): 

64 return self.Subtype() 

65 

66 @classmethod 

67 def _predict(cls, subtype, relation, other): 

68 assert isinstance(subtype, cls.Subtype) 

69 

70 if relation == operator.__rshift__: 

71 if issubclass(other.clstype, AffineExpression): 

72 if other.subtype.dim == 3: 

73 return ExpConeConstraint.make_type() 

74 

75 return Cone._predict_base(cls, subtype, relation, other) 

76 

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.") 

82 

83 return ExpConeConstraint(element) 

84 

85 # Handle scenario uncertainty for all cones. 

86 return Cone._rshift_base(self, element) 

87 

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.") 

94 

95 

96# -------------------------------------- 

97__all__ = api_end(_API_START, globals())