Source code for biogeme.expressions.calculator

""" Interface with the C++ implementation

:author: Michel Bierlaire
:date: Sat Sep  9 15:25:07 2023

"""
import logging
from typing import TYPE_CHECKING
import cythonbiogeme.cythonbiogeme as ee
from biogeme.exceptions import BiogemeError

if TYPE_CHECKING:
    from .base_expressions import Expression
    from biogeme.database import Database

logger = logging.getLogger(__name__)


[docs] def calculate_function_and_derivatives( the_expression: 'Expression', database: 'Database', calculate_gradient: bool, calculate_hessian: bool, calculate_bhhh: bool, aggregation: bool, ): """Interface with the C++ implementation calculating the expression :param the_expression: expression to calculate for each entry in the database. :param database: database. If no database is provided, the expression must not contain any variable. :param calculate_gradient: If True, the gradient is calculated. :param calculate_hessian: if True, the hessian is calculated. :param calculate_bhhh: if True, the BHHH matrix is calculated. :param aggregation: if a database is provided, and this parameter is True, the expression is applied on each entry of the database, and all values are aggregated, so that the sum is returned. If False, the list of all values is returned. :raise BiogemeError: if a database is needed and not available. """ the_cpp = ee.pyEvaluateOneExpression() if database is not None: the_cpp.setData(database.data) if the_expression.embedExpression('PanelLikelihoodTrajectory'): if database is None: raise BiogemeError('No database has been provided') if database.isPanel(): database.buildPanelMap() the_cpp.setDataMap(database.individualMap) else: error_msg = ( 'The expression involves ' '"PanelLikelihoodTrajectory" ' 'that requires panel data' ) raise BiogemeError(error_msg) if the_expression.requiresDraws(): if database is None: raise BiogemeError('No database has been provided') the_cpp.setDraws(database.theDraws) the_cpp.setExpression(the_expression.getSignature()) the_cpp.setFreeBetas(the_expression.id_manager.free_betas_values) the_cpp.setFixedBetas(the_expression.id_manager.fixed_betas_values) the_cpp.setMissingData(the_expression.missingData) the_cpp.calculate( gradient=calculate_gradient, hessian=calculate_hessian, bhhh=calculate_bhhh, aggregation=aggregation, ) f, g, h, b = the_cpp.getResults() gres = g if calculate_gradient else None hres = h if calculate_hessian else None bhhhres = b if calculate_bhhh else None if aggregation: results = ( f[0], None if gres is None else g[0], None if hres is None else h[0], None if bhhhres is None else b[0], ) else: results = (f, gres, hres, bhhhres) return results