[docs]classMultipleSum(Expression):"""This expression returns the sum of several other expressions. It is a generalization of 'Plus' for more than two terms """def__init__(self,list_of_expressions:list[ExpressionOrNumeric]|dict[Any:ExpressionOrNumeric],):"""Constructor :param list_of_expressions: list of objects representing the terms of the sum. :type list_of_expressions: list(biogeme.expressions.Expression) :raise BiogemeError: if one of the expressions is invalid, that is neither a numeric value nor a biogeme.expressions.Expression object. :raise BiogemeError: if the list of expressions is empty :raise BiogemeError: if the list of expressions is neither a dict nor a list """ifnotlist_of_expressions:raiseBiogemeError('The argument of MultipleSum cannot be empty')super().__init__()ifisinstance(list_of_expressions,dict):items=list_of_expressions.values()elifisinstance(list_of_expressions,list):items=list_of_expressionselse:raiseBiogemeError('Argument of MultipleSum must be a dict or a list.')forexpressioninitems:self.children.append(validate_and_convert(expression))
[docs]defdeep_flat_copy(self)->MultipleSum:"""Provides a copy of the expression. It is deep in the sense that it generates copies of the children. It is flat in the sense that any `MultipleExpression` is transformed into the currently selected expression. The flat part is irrelevant for this expression. """copy_list_of_expressions=[expression.deep_flat_copy()forexpressioninself.children]returntype(self)(list_of_expressions=copy_list_of_expressions)
[docs]defget_value(self)->float:"""Evaluates the value of the expression :return: value of the expression :rtype: float """result=0.0foreinself.get_children():result+=e.get_value()returnresult
[docs]defrecursive_construct_pymc_model_builder(self)->PymcModelBuilderType:""" PyMC builder for MultipleSum: - evaluate all children - stack along a new axis - sum over that axis """child_builders=[c.recursive_construct_pymc_model_builder()forcinself.get_children()]defbuilder(dataframe:pd.DataFrame)->pt.TensorVariable:terms=[cb(dataframe=dataframe)forcbinchild_builders]iflen(terms)==1:returnterms[0]try:returnpt.sum(pt.stack(terms,axis=0),axis=0)except(TypeError,ValueError)ase:shapes=[getattr(getattr(t,"type",None),"shape",None)fortinterms]raiseBiogemeError(f"MultipleSum terms are not shape-compatible. Got shapes: {shapes}. ""All terms must be broadcastable to a common shape.")fromereturnbuilder