<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def _compile_aggregation_expression(self,
                                        expr: Expression,
                                        scope: Dict[str, TensorFluent],
                                        batch_size: Optional[int] = None,
                                        noise: Optional[List[tf.Tensor]] = None) -> TensorFluent:
        '''Compile an aggregation expression `expr` into a TensorFluent
        in the given `scope` with optional batch size.

        Args:
            expr (:obj:`rddl2tf.expr.Expression`): A RDDL aggregation expression.
            scope (Dict[str, :obj:`rddl2tf.fluent.TensorFluent`]): A fluent scope.
            batch_size (Optional[size]): The batch size.

        Returns:
            :obj:`rddl2tf.fluent.TensorFluent`: The compiled expression as a TensorFluent.
        '''
        etype = expr.etype
        args = expr.args

        typed_var_list = args[:-1]
        vars_list = [var for _, (var, _) in typed_var_list]
        expr = args[-1]

        x = self._compile_expression(expr, scope)

        etype2aggr = {
            'sum':     x.sum,
            'prod':    x.prod,
            'avg':     x.avg,
            'maximum': x.maximum,
            'minimum': x.minimum,
            'exists':  x.exists,
            'forall':  x.forall
        }

        if etype[1] not in etype2aggr:
            raise ValueError('Invalid aggregation expression {}.'.format(expr))

        aggr = etype2aggr[etype[1]]
        fluent = aggr(vars_list=vars_list)

        return fluent