""" Arithmetic expressions accepted by Biogeme: binary operators
:author: Michel Bierlaire
:date: Sat Sep 9 15:18:27 2023
"""
from __future__ import annotations
import logging
from . import validate_and_convert
from .base_expressions import Expression, ExpressionOrNumeric
from ..deprecated import deprecated
logger = logging.getLogger(__name__)
[docs]
class BinaryOperator(Expression):
"""
Base class for arithmetic expressions that are binary operators.
This expression is the result of the combination of two expressions,
typically addition, subtraction, multiplication or division.
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
:raise BiogemeError: if one of the expressions is invalid, that is
neither a numeric value nor a
biogeme.expressions.Expression object.
"""
Expression.__init__(self)
self.left = validate_and_convert(left)
self.right = validate_and_convert(right)
self.children.append(self.left)
self.children.append(self.right)
[docs]
class Plus(BinaryOperator):
"""
Addition expression
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'({self.left} + {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
return self.left.get_value() + self.right.get_value()
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass
[docs]
class Minus(BinaryOperator):
"""
Substraction expression
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'({self.left} - {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
return self.left.get_value() - self.right.get_value()
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass
[docs]
class Times(BinaryOperator):
"""
Multiplication expression
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'({self.left} * {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
return self.left.get_value() * self.right.get_value()
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass
[docs]
class Divide(BinaryOperator):
"""
Division expression
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'({self.left} / {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
return self.left.get_value() / self.right.get_value()
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass
[docs]
class Power(BinaryOperator):
"""
Power expression
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'({self.left} ** {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
return self.left.get_value() ** self.right.get_value()
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass
[docs]
class bioMin(BinaryOperator):
"""
Minimum of two expressions
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'bioMin({self.left}, {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
if self.left.get_value() <= self.right.get_value():
return self.left.get_value()
return self.right.get_value()
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass
[docs]
class bioMax(BinaryOperator):
"""
Maximum of two expressions
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'bioMax({self.left}, {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
if self.left.get_value() >= self.right.get_value():
return self.left.get_value()
return self.right.get_value()
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass
[docs]
class And(BinaryOperator):
"""
Logical and
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'({self.left} and {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
if self.left.get_value() == 0.0:
return 0.0
if self.right.get_value() == 0.0:
return 0.0
return 1.0
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass
[docs]
class Or(BinaryOperator):
"""
Logical or
"""
def __init__(self, left: ExpressionOrNumeric, right: ExpressionOrNumeric):
"""Constructor
:param left: first arithmetic expression
:type left: biogeme.expressions.Expression
:param right: second arithmetic expression
:type right: biogeme.expressions.Expression
"""
BinaryOperator.__init__(self, left, right)
def __str__(self) -> str:
return f'({self.left} or {self.right})'
[docs]
def get_value(self) -> float:
"""Evaluates the value of the expression
:return: value of the expression
:rtype: float
"""
if self.left.get_value() != 0.0:
return 1.0
if self.right.get_value() != 0.0:
return 1.0
return 0.0
[docs]
@deprecated(get_value)
def getValue(self) -> float:
"""Kept for backward compatibility"""
pass