"""Implements the Box-Cox model:author: Michel Bierlaire:date: Wed Oct 25 08:52:44 2023"""importloggingfrombiogeme.expressionsimport(Expression,Elem,Numeric,log,Beta,ExpressionOrNumeric,)logger=logging.getLogger(__name__)
[docs]defboxcox(x:ExpressionOrNumeric,ell:ExpressionOrNumeric)->Expression:"""Box-Cox transform .. math:: B(x, \\ell) = \\frac{x^{\\ell}-1}{\\ell}. It has the property that .. math:: \\lim_{\\ell \\to 0} B(x,\\ell)=\\log(x). To avoid numerical difficulties, if :math:`\\ell < 10^{-5}`, the McLaurin approximation is used: .. math:: \\log(x) + \\ell \\log(x)^2 + \\frac{1}{6} \\ell^2 \\log(x)^3 + \\frac{1}{24} \\ell^3 \\log(x)^4. :param x: a variable to transform. :param ell: parameter of the transformation. :return: the Box-Cox transform """ifisinstance(ell,Beta)and(ell.upper_boundisNoneorell.lower_boundisNone):warning_msg=(f'It is advised to set the bounds on parameter {ell.name}. 'f'A value of -10 and 10 should be appropriate: Beta("{ell.name}", 'f'{ell.init_value}, -10, 10, {ell.status})')logger.warning(warning_msg)regular=(x**ell-1.0)/ellmclaurin=(log(x)+ell*log(x)**2+ell**2*log(x)**3/6.0+ell**3*log(x)**4/24.0)close_to_zero=(ell<Numeric(1.0e-5))*(ell>-Numeric(1.0e-5))smooth=Elem({0:regular,1:mclaurin},close_to_zero)returnElem({0:smooth,1:Numeric(0)},x==0)