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
« 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# ------------------------------------------------------------------------------
19"""Implementation of :class:`LogConstraint`."""
21from collections import namedtuple
23from .. import glyphs
24from ..apidoc import api_end, api_start
25from .constraint import Constraint, ConstraintConversion
27_API_START = api_start(globals())
28# -------------------------------
31class LogConstraint(Constraint):
32 """Lower bound on a logarithm."""
34 class ExpConeConversion(ConstraintConversion):
35 """Bound on a logarithm to exponential cone constraint conversion."""
37 @classmethod
38 def predict(cls, subtype, options):
39 """Implement :meth:`~.constraint.ConstraintConversion.predict`."""
40 from . import AffineConstraint, ExpConeConstraint
42 yield ("con", AffineConstraint.make_type(dim=1, eq=False), 1)
43 yield ("con", ExpConeConstraint.make_type(), 1)
45 @classmethod
46 def convert(cls, con, options):
47 """Implement :meth:`~.constraint.ConstraintConversion.convert`."""
48 from ..expressions import ExponentialCone
49 from ..modeling import Problem
51 x = con.log.x
52 t = con.lb
54 P = Problem()
55 P.add_constraint(x >= 0)
56 P.add_constraint((x // 1 // t) << ExponentialCone())
57 return P
59 def __init__(self, log, lowerBound):
60 """Construct a :class:`LogConstraint`.
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
69 assert isinstance(log, Logarithm)
70 assert isinstance(lowerBound, AffineExpression)
71 assert len(lowerBound) == 1
73 self.log = log
74 self.lb = lowerBound
76 super(LogConstraint, self).__init__("Logarithmic")
78 Subtype = namedtuple("Subtype", ())
80 def _subtype(self):
81 return self.Subtype()
83 @classmethod
84 def _cost(cls, subtype):
85 return 2
87 def _expression_names(self):
88 yield "log"
89 yield "lb"
91 def _str(self):
92 return glyphs.ge(self.log.string, self.lb.string)
94 def _get_slack(self):
95 return self.log.safe_value - self.lb.safe_value
98# --------------------------------------
99__all__ = api_end(_API_START, globals())