1from typing import TYPE_CHECKING, List, Tuple 2 3if TYPE_CHECKING: 4 from cvxpy.expressions.expression import Expression 5 6""" 7Copyright 2013 Steven Diamond 8 9Licensed under the Apache License, Version 2.0 (the "License"); 10you may not use this file except in compliance with the License. 11You may obtain a copy of the License at 12 13 http://www.apache.org/licenses/LICENSE-2.0 14 15Unless required by applicable law or agreed to in writing, software 16distributed under the License is distributed on an "AS IS" BASIS, 17WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18See the License for the specific language governing permissions and 19limitations under the License. 20""" 21 22 23def sum_signs(exprs: List['Expression']) -> Tuple[bool, bool]: 24 """Give the sign resulting from summing a list of expressions. 25 26 Args: 27 shapes: A list of sign (is pos, is neg) tuples. 28 29 Returns: 30 The sign (is pos, is neg) of the sum. 31 """ 32 is_pos = all(expr.is_nonneg() for expr in exprs) 33 is_neg = all(expr.is_nonpos() for expr in exprs) 34 return (is_pos, is_neg) 35 36 37def mul_sign(lh_expr: 'Expression', rh_expr: 'Expression') -> Tuple[bool, bool]: 38 """Give the sign resulting from multiplying two expressions. 39 40 Args: 41 lh_expr: An expression. 42 rh_expr: An expression. 43 44 Returns: 45 The sign (is pos, is neg) of the product. 46 """ 47 # ZERO * ANYTHING == ZERO 48 # POSITIVE * POSITIVE == POSITIVE 49 # NEGATIVE * POSITIVE == NEGATIVE 50 # NEGATIVE * NEGATIVE == POSITIVE 51 52 lh_nonneg = lh_expr.is_nonneg() 53 rh_nonneg = rh_expr.is_nonneg() 54 lh_nonpos = lh_expr.is_nonpos() 55 rh_nonpos = rh_expr.is_nonpos() 56 57 lh_zero = lh_nonneg and lh_nonpos 58 rh_zero = rh_nonneg and rh_nonpos 59 60 is_zero = lh_zero or rh_zero 61 62 is_pos = is_zero or (lh_nonneg and rh_nonneg) or (lh_nonpos and rh_nonpos) 63 is_neg = is_zero or (lh_nonneg and rh_nonpos) or (lh_nonpos and rh_nonneg) 64 return (is_pos, is_neg) 65