Coverage for picos/expressions/cone.py: 88.24%

51 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-03-26 07:46 +0000

1# ------------------------------------------------------------------------------ 

2# Copyright (C) 2020 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"""Backend for mathematical set type implementations.""" 

21 

22import operator 

23from abc import abstractmethod 

24 

25from .. import glyphs 

26from ..apidoc import api_end, api_start 

27from ..constraints.uncertain import ScenarioUncertainConicConstraint 

28from .expression import ExpressionType 

29from .set import Set 

30 

31_API_START = api_start(globals()) 

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

33 

34 

35class Cone(Set): 

36 """Abstract base class for a cone.""" 

37 

38 def __init__(self, dim, typeStr, symbStr): 

39 """Perform basic initialization for :class:`Cone` instances. 

40 

41 :param int or None dim: Fixed member dimensionality, or :obj:`None`. 

42 :param str typeStr: Short string denoting the set type. 

43 :param str symbStr: Algebraic string description of the set. 

44 """ 

45 if dim: 

46 typeStr = "{}-dim. {}".format(dim, typeStr) 

47 

48 Set.__init__(self, typeStr, symbStr) 

49 

50 if dim is not None and not isinstance(dim, int): 

51 raise TypeError( 

52 "The cone's fixed dimensionality must be an integer or None.") 

53 

54 if dim == 0: 

55 raise ValueError("Zero-dimensional cones are not supported.") 

56 

57 self._dim = dim 

58 

59 @property 

60 def dim(self): 

61 """The fixed member dimensionality, or :obj:`None`. 

62 

63 If this is :obj:`None`, the instance represents any finite dimensional 

64 version of the cone. Such an abstract cone can not be used to define a 

65 :class:`~.cone_product.ProductCone`. 

66 """ 

67 return self._dim 

68 

69 @property 

70 @abstractmethod 

71 def dual_cone(self): 

72 """The dual cone.""" 

73 pass 

74 

75 def _check_dimension(self, element): 

76 if self.dim and self.dim != len(element): 

77 raise TypeError("The shape {} of {} does not match the fixed " 

78 "dimensionality {} of the cone {}.".format(glyphs.shape( 

79 element.shape), element.string, self.dim, self.string)) 

80 

81 @staticmethod 

82 def _predict_base(cls, subtype, relation, other): 

83 """Base :meth:`_predict` method for all cone types.""" 

84 from .uncertain.pert_scenario import ScenarioPerturbationSet 

85 from .uncertain.uexp_affine import UncertainAffineExpression 

86 

87 assert isinstance(subtype, cls.Subtype) 

88 

89 cone = ExpressionType(cls, subtype) 

90 

91 if relation == operator.__rshift__: 

92 if issubclass(other.clstype, UncertainAffineExpression) \ 

93 and not subtype.dim or subtype.dim == other.subtype.dim: 

94 universe = other.subtype.universe_type 

95 

96 if issubclass(universe.clstype, ScenarioPerturbationSet): 

97 return ScenarioUncertainConicConstraint.make_type( 

98 dim=other.subtype.dim, 

99 scenario_count=universe.subtype.scenario_count, 

100 cone_type=cone) 

101 

102 return NotImplemented 

103 

104 @staticmethod 

105 def _rshift_base(self, element): 

106 """Base :meth:`__rshift__` method for all cone types.""" 

107 from .uncertain.pert_scenario import ScenarioPerturbationSet 

108 from .uncertain.uexp_affine import UncertainAffineExpression 

109 

110 if isinstance(element, UncertainAffineExpression): 

111 self._check_dimension(element) 

112 

113 if isinstance(element.universe, ScenarioPerturbationSet): 

114 return ScenarioUncertainConicConstraint(element, self) 

115 

116 return NotImplemented 

117 

118 

119# -------------------------------------- 

120__all__ = api_end(_API_START, globals())