Coverage for picos/constraints/con_log.py: 97.78%

45 statements  

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

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

2# Copyright (C) 2018-2019 Maximilian Stahlberg 

3# 

4# This file is part of PICOS. 

5# 

6# PICOS is free software: you can redistribute it and/or modify it under the 

7# terms of the GNU General Public License as published by the Free Software 

8# Foundation, either version 3 of the License, or (at your option) any later 

9# version. 

10# 

11# PICOS is distributed in the hope that it will be useful, but WITHOUT ANY 

12# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 

13# A PARTICULAR PURPOSE. See the GNU General Public License for more details. 

14# 

15# You should have received a copy of the GNU General Public License along with 

16# this program. If not, see <http://www.gnu.org/licenses/>. 

17# ------------------------------------------------------------------------------ 

18 

19"""Implementation of :class:`LogConstraint`.""" 

20 

21from collections import namedtuple 

22 

23from .. import glyphs 

24from ..apidoc import api_end, api_start 

25from .constraint import Constraint, ConstraintConversion 

26 

27_API_START = api_start(globals()) 

28# ------------------------------- 

29 

30 

31class LogConstraint(Constraint): 

32 """Lower bound on a logarithm.""" 

33 

34 class ExpConeConversion(ConstraintConversion): 

35 """Bound on a logarithm to exponential cone constraint conversion.""" 

36 

37 @classmethod 

38 def predict(cls, subtype, options): 

39 """Implement :meth:`~.constraint.ConstraintConversion.predict`.""" 

40 from . import AffineConstraint, ExpConeConstraint 

41 

42 yield ("con", AffineConstraint.make_type(dim=1, eq=False), 1) 

43 yield ("con", ExpConeConstraint.make_type(), 1) 

44 

45 @classmethod 

46 def convert(cls, con, options): 

47 """Implement :meth:`~.constraint.ConstraintConversion.convert`.""" 

48 from ..expressions import ExponentialCone 

49 from ..modeling import Problem 

50 

51 x = con.log.x 

52 t = con.lb 

53 

54 P = Problem() 

55 P.add_constraint(x >= 0) 

56 P.add_constraint((x // 1 // t) << ExponentialCone()) 

57 return P 

58 

59 def __init__(self, log, lowerBound): 

60 """Construct a :class:`LogConstraint`. 

61 

62 :param ~picos.expressions.Logarithm log: 

63 Constrained expression. 

64 :param ~picos.expressions.AffineExpression lowerBound: 

65 Lower bound on the expression. 

66 """ 

67 from ..expressions import AffineExpression, Logarithm 

68 

69 assert isinstance(log, Logarithm) 

70 assert isinstance(lowerBound, AffineExpression) 

71 assert len(lowerBound) == 1 

72 

73 self.log = log 

74 self.lb = lowerBound 

75 

76 super(LogConstraint, self).__init__("Logarithmic") 

77 

78 Subtype = namedtuple("Subtype", ()) 

79 

80 def _subtype(self): 

81 return self.Subtype() 

82 

83 @classmethod 

84 def _cost(cls, subtype): 

85 return 2 

86 

87 def _expression_names(self): 

88 yield "log" 

89 yield "lb" 

90 

91 def _str(self): 

92 return glyphs.ge(self.log.string, self.lb.string) 

93 

94 def _get_slack(self): 

95 return self.log.safe_value - self.lb.safe_value 

96 

97 

98# -------------------------------------- 

99__all__ = api_end(_API_START, globals())