.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/programmers/plot_expressions.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_programmers_plot_expressions.py: biogeme.expressions =================== Examples of use of several functions. This is designed for programmers who need examples of use of the functions of the module. The examples are designed to illustrate the syntax. They do not correspond to any meaningful model. Michel Bierlaire Sun Jun 29 2025, 07:12:52 .. GENERATED FROM PYTHON SOURCE LINES 15-62 .. code-block:: Python import biogeme.biogeme_logging as blog import numpy as np import pandas as pd from IPython.core.display_functions import display from biogeme.database import Database from biogeme.exceptions import BiogemeError from biogeme.expressions import ( Beta, BinaryMax, BinaryMin, Derive, Draws, Elem, IntegrateNormal, LinearTermTuple, LinearUtility, LogLogit, MonteCarlo, MultipleSum, NormalCdf, Numeric, RandomVariable, Variable, cos, exp, list_of_all_betas_in_expression, list_of_fixed_betas_in_expression, list_of_free_betas_in_expression, list_of_variables_in_expression, log, sin, ) from biogeme.function_output import FunctionOutput from biogeme.jax_calculator.function_call import ( CallableExpression, function_from_expression, ) from biogeme.jax_calculator.simple_formula import evaluate_simple_expression from biogeme.jax_calculator.single_formula import ( calculate_single_formula_from_expression, get_value_and_derivatives, ) from biogeme.model_elements import RegularAdapter from biogeme.second_derivatives import SecondDerivativesMode from biogeme.version import get_text .. GENERATED FROM PYTHON SOURCE LINES 63-64 Version of Biogeme. .. GENERATED FROM PYTHON SOURCE LINES 64-66 .. code-block:: Python print(get_text()) .. rst-class:: sphx-glr-script-out .. code-block:: none biogeme 3.3.5 [2026-08-28] Home page: http://biogeme.epfl.ch Submit questions to https://groups.google.com/d/forum/biogeme Michel Bierlaire, Transport and Mobility Laboratory, Ecole Polytechnique Fédérale de Lausanne (EPFL) .. GENERATED FROM PYTHON SOURCE LINES 67-69 .. code-block:: Python logger = blog.get_screen_logger(level=blog.INFO) .. GENERATED FROM PYTHON SOURCE LINES 70-74 Simple expressions ------------------ Simple expressions can be evaluated with the function `get_value`, implemented in Python. This is available when no database is needed. .. GENERATED FROM PYTHON SOURCE LINES 76-79 .. code-block:: Python x = Beta('x', 2, None, None, 1) display(x) .. rst-class:: sphx-glr-script-out .. code-block:: none Beta('x', 2, None, None, 1) .. GENERATED FROM PYTHON SOURCE LINES 80-82 The ``get_value`` function simply returns the value of the expression if it can be evaluated. .. GENERATED FROM PYTHON SOURCE LINES 82-84 .. code-block:: Python display(x.get_value()) .. rst-class:: sphx-glr-script-out .. code-block:: none 2 .. GENERATED FROM PYTHON SOURCE LINES 85-88 .. code-block:: Python y = Beta('y', 3, None, None, 1) display(y) .. rst-class:: sphx-glr-script-out .. code-block:: none Beta('y', 3, None, None, 1) .. GENERATED FROM PYTHON SOURCE LINES 89-91 .. code-block:: Python display(y.get_value()) .. rst-class:: sphx-glr-script-out .. code-block:: none 3 .. GENERATED FROM PYTHON SOURCE LINES 92-95 .. code-block:: Python one = Numeric(1) display(one) .. rst-class:: sphx-glr-script-out .. code-block:: none `1.0` .. GENERATED FROM PYTHON SOURCE LINES 96-98 .. code-block:: Python display(one.get_value()) .. rst-class:: sphx-glr-script-out .. code-block:: none 1.0 .. GENERATED FROM PYTHON SOURCE LINES 99-100 Addition .. GENERATED FROM PYTHON SOURCE LINES 100-103 .. code-block:: Python z = x + y display(f'{x.get_value()} + {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 + 3 = 5 .. GENERATED FROM PYTHON SOURCE LINES 104-105 Substraction .. GENERATED FROM PYTHON SOURCE LINES 105-108 .. code-block:: Python z = x - y display(f'{x.get_value()} - {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 - 3 = -1 .. GENERATED FROM PYTHON SOURCE LINES 109-110 Multiplication .. GENERATED FROM PYTHON SOURCE LINES 110-114 .. code-block:: Python z = x * y display(f'{x.get_value()} * {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 * 3 = 6 .. GENERATED FROM PYTHON SOURCE LINES 115-116 Division .. GENERATED FROM PYTHON SOURCE LINES 116-119 .. code-block:: Python z = x / y display(f'{x.get_value()} / {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 / 3 = 0.6666666666666666 .. GENERATED FROM PYTHON SOURCE LINES 120-121 Power .. GENERATED FROM PYTHON SOURCE LINES 121-125 .. code-block:: Python z = x**y z.get_value() display(f'{x.get_value()} ** {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 ** 3 = 8 .. GENERATED FROM PYTHON SOURCE LINES 126-127 Exponential .. GENERATED FROM PYTHON SOURCE LINES 127-131 .. code-block:: Python z = exp(x) z.get_value() display(f'exp({x.get_value()}) = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none exp(2) = 7.38905609893065 .. GENERATED FROM PYTHON SOURCE LINES 132-133 Logarithm .. GENERATED FROM PYTHON SOURCE LINES 133-137 .. code-block:: Python z = log(x) z.get_value() display(f'log({x.get_value()}) = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none log(2) = 0.6931471805599453 .. GENERATED FROM PYTHON SOURCE LINES 138-139 Sine .. GENERATED FROM PYTHON SOURCE LINES 139-143 .. code-block:: Python z = sin(x) z.get_value() display(f'sin({x.get_value()}) = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none sin(2) = 0.9092974268256817 .. GENERATED FROM PYTHON SOURCE LINES 144-145 Cosine .. GENERATED FROM PYTHON SOURCE LINES 145-149 .. code-block:: Python z = cos(x) z.get_value() display(f'cos({x.get_value()}) = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none cos(2) = -0.4161468365471424 .. GENERATED FROM PYTHON SOURCE LINES 150-151 Minimum .. GENERATED FROM PYTHON SOURCE LINES 151-155 .. code-block:: Python z = BinaryMin(x, y) z.get_value() display(f'min({x.get_value()}, {y.get_value()}) = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none min(2, 3) = 2 .. GENERATED FROM PYTHON SOURCE LINES 156-157 Maximum .. GENERATED FROM PYTHON SOURCE LINES 157-162 .. code-block:: Python z = BinaryMax(x, y) z.get_value() display(f'max({x.get_value()}, {y.get_value()}) = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none max(2, 3) = 3 .. GENERATED FROM PYTHON SOURCE LINES 163-166 And An expression is considered False if its value is 0 and True otherwise. The outcome of a logical operator is 0 (False) or 1 (True). .. GENERATED FROM PYTHON SOURCE LINES 166-170 .. code-block:: Python z = x & y z.get_value() display(f'{x.get_value()} and {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 and 3 = 1.0 .. GENERATED FROM PYTHON SOURCE LINES 171-175 .. code-block:: Python z = x & 0 z.get_value() display(f'{x.get_value()} and 0 = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 and 0 = 0.0 .. GENERATED FROM PYTHON SOURCE LINES 176-177 Or .. GENERATED FROM PYTHON SOURCE LINES 179-183 .. code-block:: Python z = x | y z.get_value() display(f'{x.get_value()} or {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 or 3 = 1.0 .. GENERATED FROM PYTHON SOURCE LINES 184-187 .. code-block:: Python z = Numeric(0) | Numeric(0) z.get_value() .. rst-class:: sphx-glr-script-out .. code-block:: none 0.0 .. GENERATED FROM PYTHON SOURCE LINES 188-189 Equal .. GENERATED FROM PYTHON SOURCE LINES 189-193 .. code-block:: Python z = x == y z.get_value() display(f'{x.get_value()} == {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 == 3 = 0 .. GENERATED FROM PYTHON SOURCE LINES 194-198 .. code-block:: Python z = (x + 1) == y z.get_value() display(f'({x.get_value()} + 1) == {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none (2 + 1) == 3 = 1 .. GENERATED FROM PYTHON SOURCE LINES 199-200 Not equal .. GENERATED FROM PYTHON SOURCE LINES 200-204 .. code-block:: Python z = x != y z.get_value() display(f'{x.get_value()} != {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 != 3 = 1 .. GENERATED FROM PYTHON SOURCE LINES 205-210 .. code-block:: Python z = (x + 1) != y z.get_value() display(f'({x.get_value()} + 1) != {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none (2 + 1) != 3 = 0 .. GENERATED FROM PYTHON SOURCE LINES 211-212 Lesser or equal .. GENERATED FROM PYTHON SOURCE LINES 212-217 .. code-block:: Python z = x <= y z.get_value() display(f'{x.get_value()} <= {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 <= 3 = 1 .. GENERATED FROM PYTHON SOURCE LINES 218-219 Greater or equal .. GENERATED FROM PYTHON SOURCE LINES 219-222 .. code-block:: Python z = x >= y z.get_value() .. rst-class:: sphx-glr-script-out .. code-block:: none 0 .. GENERATED FROM PYTHON SOURCE LINES 223-224 Lesser than .. GENERATED FROM PYTHON SOURCE LINES 224-228 .. code-block:: Python z = x < y z.get_value() display(f'{x.get_value()} < {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 < 3 = 1 .. GENERATED FROM PYTHON SOURCE LINES 229-230 Greater than .. GENERATED FROM PYTHON SOURCE LINES 230-234 .. code-block:: Python z = x > y z.get_value() display(f'{x.get_value()} > {y.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none 2 > 3 = 0 .. GENERATED FROM PYTHON SOURCE LINES 235-236 Opposite .. GENERATED FROM PYTHON SOURCE LINES 236-241 .. code-block:: Python z = -x z.get_value() display(f'-{x.get_value()} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none -2 = -2 .. GENERATED FROM PYTHON SOURCE LINES 242-243 Sum of multiples expressions .. GENERATED FROM PYTHON SOURCE LINES 243-248 .. code-block:: Python list_of_expressions = [x, y, 1 + x, 1 + y] z = MultipleSum(list_of_expressions) all_values = [expression.get_value() for expression in list_of_expressions] display(f'Sum of {all_values} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none Sum of [2, 3, 3.0, 4.0] = 12.0 .. GENERATED FROM PYTHON SOURCE LINES 249-251 The result is the same as the following, but it implements the sum in a more efficient way. .. GENERATED FROM PYTHON SOURCE LINES 251-255 .. code-block:: Python z = x + y + 1 + x + 1 + y z.get_value() display(f'Sum of {all_values} = {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none Sum of [2, 3, 3.0, 4.0] = 12.0 .. GENERATED FROM PYTHON SOURCE LINES 256-259 Element: this expression considers a dictionary of expressions, and an expression for the index. The index is evaluated, and the value of the corresponding expression in the dictionary is returned. .. GENERATED FROM PYTHON SOURCE LINES 259-261 .. code-block:: Python my_dict = {1: exp(-1), 2: log(1.2), 3: 1234} .. GENERATED FROM PYTHON SOURCE LINES 262-265 .. code-block:: Python index = x display(f'Value of the index: {index.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the index: 2 .. GENERATED FROM PYTHON SOURCE LINES 266-270 .. code-block:: Python z = Elem(my_dict, index) z.get_value() display(f'Value of the expression with index {index.get_value()}: {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the expression with index 2: 0.1823215567939546 .. GENERATED FROM PYTHON SOURCE LINES 271-277 .. code-block:: Python index = x - 1 z = Elem(my_dict, index) z.get_value() display(f'Value of the expression with index {index.get_value()}: {z.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the expression with index 1.0: 0.36787944117144233 .. GENERATED FROM PYTHON SOURCE LINES 278-282 .. code-block:: Python index = x - 2 index.get_value() display(f'Value of the index: {index.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the index: 0.0 .. GENERATED FROM PYTHON SOURCE LINES 283-285 If the value returned as index does not correspond to an entry in the dictionary, an exception is raised. .. GENERATED FROM PYTHON SOURCE LINES 287-293 .. code-block:: Python z = Elem(my_dict, index) try: z.get_value() except BiogemeError as e: print(f'Exception raised: {e}') .. rst-class:: sphx-glr-script-out .. code-block:: none Exception raised: Invalid or missing key: 0. Available keys: dict_keys([1, 2, 3]) .. GENERATED FROM PYTHON SOURCE LINES 294-299 Complex expressions ------------------- When an expression is deemed complex in Biogeme, the `get_value` function is not available. The `evaluate_simple_expression` must be used. It is based on Jax to evaluate the arithmetic expressions. .. GENERATED FROM PYTHON SOURCE LINES 301-305 Normal CDF: it calculates .. math:: \Phi(x) = \frac{1}{\sqrt{2\pi}}\int_{-\infty}^{x} e^{-\frac{1}{2}\omega^2}d\omega. .. GENERATED FROM PYTHON SOURCE LINES 305-317 .. code-block:: Python z = NormalCdf(x) try: z.get_value() except BiogemeError as e: print(e) value = evaluate_simple_expression( expression=z, database=None, numerically_safe=False, use_jit=True ) display(f'NormalCdf({x.get_value()}) = {value}') .. rst-class:: sphx-glr-script-out .. code-block:: none NormalCdf(2) = 0.9772498680518208 .. GENERATED FROM PYTHON SOURCE LINES 318-323 .. code-block:: Python value = evaluate_simple_expression( expression=NormalCdf(0), database=None, numerically_safe=False, use_jit=True ) display(f'NormalCdf(0) = {value}') .. rst-class:: sphx-glr-script-out .. code-block:: none NormalCdf(0) = 0.5 .. GENERATED FROM PYTHON SOURCE LINES 324-326 Derivative It is possible to calculate the derivative with respect to a parameter or a variable. .. GENERATED FROM PYTHON SOURCE LINES 326-330 .. code-block:: Python parameter = Beta('parameter', 0, None, None, 0) variable = Variable('variable') z = 30 * parameter + 20 * variable .. GENERATED FROM PYTHON SOURCE LINES 331-334 .. code-block:: Python dz_dparameter = Derive(z, 'parameter') dz_dvariable = Derive(z, 'variable') .. GENERATED FROM PYTHON SOURCE LINES 335-336 As the expression involves a variable, it requires a database. .. GENERATED FROM PYTHON SOURCE LINES 336-353 .. code-block:: Python simple_dataframe = pd.DataFrame.from_dict({'variable': [1]}) simple_database = Database(dataframe=simple_dataframe, name='simple') value_parameter = evaluate_simple_expression( expression=dz_dparameter, database=simple_database, numerically_safe=False, use_jit=True, ) display(f'dz/dparameter = {value_parameter}') value_variable = evaluate_simple_expression( expression=dz_dvariable, database=simple_database, numerically_safe=False, use_jit=True, ) display(f'dz/variable = {value_variable}') .. rst-class:: sphx-glr-script-out .. code-block:: none dz/dparameter = 30.0 dz/variable = 20.0 .. GENERATED FROM PYTHON SOURCE LINES 354-358 Integral: let's calculate the integral of the pdf of a normal distribution: .. math:: \frac{1}{\sqrt{2\pi}}\int_{-\infty}^{+\infty} e^{-\frac{1}{2}\omega^2}d\omega = 1. .. GENERATED FROM PYTHON SOURCE LINES 360-363 The expression `IntegrateNormal` multiplies its argument by the pdf or the normal distribution before evaluating the integral. Therefore, the expression that we need to provide here is 1. However, Biogeme requires the expression to involve 'omega'. Therefore, we code 1 as the ratio of omega by itself. .. GENERATED FROM PYTHON SOURCE LINES 363-371 .. code-block:: Python omega = RandomVariable('omega') z = IntegrateNormal(omega / omega, 'omega') value = evaluate_simple_expression( expression=z, database=simple_database, numerically_safe=False, use_jit=True ) display(f'The integral between -inf and +inf of the normal pdf is {value}') .. rst-class:: sphx-glr-script-out .. code-block:: none The integral between -inf and +inf of the normal pdf is 0.9999999999999998 .. GENERATED FROM PYTHON SOURCE LINES 372-375 We now illustrate expressions that require a database. Those expressions are evaluated for each row of the database, and the obtained values are then added together to obtain the result. .. GENERATED FROM PYTHON SOURCE LINES 375-389 .. code-block:: Python df = pd.DataFrame( { 'Person': [1, 1, 1, 2, 2], 'Exclude': [0, 0, 1, 0, 1], 'Variable1': [10, 20, 30, 40, 50], 'Variable2': [100, 200, 300, 400, 500], 'Choice': [2, 2, 3, 1, 2], 'Av1': [0, 1, 1, 1, 1], 'Av2': [1, 1, 1, 1, 1], 'Av3': [0, 1, 1, 1, 1], } ) my_data = Database('test', df) .. GENERATED FROM PYTHON SOURCE LINES 390-391 Linear utility: it defines a linear combinations of parameters are variables. .. GENERATED FROM PYTHON SOURCE LINES 391-396 .. code-block:: Python beta1 = Beta('beta1', 10, None, None, 0) beta2 = Beta('beta2', 20, None, None, 0) v1 = Variable('Variable1') v2 = Variable('Variable2') .. GENERATED FROM PYTHON SOURCE LINES 397-407 .. code-block:: Python list_of_terms = [ LinearTermTuple(beta=beta1, x=v1), LinearTermTuple(beta=beta2, x=v2), ] z = LinearUtility(list_of_terms) value = evaluate_simple_expression( expression=z, database=my_data, numerically_safe=False, use_jit=True ) display(f'beta1 * v1 + beta2 * v2 = {value}') .. rst-class:: sphx-glr-script-out .. code-block:: none beta1 * v1 + beta2 * v2 = 31500.0 .. GENERATED FROM PYTHON SOURCE LINES 408-409 It is equivalent to the following, but implemented in a more efficient way. .. GENERATED FROM PYTHON SOURCE LINES 409-415 .. code-block:: Python z = beta1 * v1 + beta2 * v2 value = evaluate_simple_expression( expression=z, database=my_data, numerically_safe=False, use_jit=True ) display(f'beta1 * v1 + beta2 * v2 = {value}') .. rst-class:: sphx-glr-script-out .. code-block:: none beta1 * v1 + beta2 * v2 = 31500.0 .. GENERATED FROM PYTHON SOURCE LINES 416-422 Monte Carlo: we approximate the integral .. math:: \int_0^1 x^2 dx=\frac{1}{3} using Monte-Carlo integration. This is not considered a simple expression. Therefore, another function must be called. .. GENERATED FROM PYTHON SOURCE LINES 422-438 .. code-block:: Python draws = Draws('draws', 'UNIFORM') z = MonteCarlo(draws * draws) number_of_draws = 1_000_000 value = calculate_single_formula_from_expression( expression=z, database=simple_database, number_of_draws=number_of_draws, the_betas={}, second_derivatives_mode=SecondDerivativesMode.NEVER, numerically_safe=False, use_jit=True, ) display( f'The Monte-Carlo approximation of the integral with {number_of_draws:_} draws is equal to {value}.' ) .. rst-class:: sphx-glr-script-out .. code-block:: none The Monte-Carlo approximation of the integral with 1_000_000 draws is equal to 0.3331787624341627. .. GENERATED FROM PYTHON SOURCE LINES 439-442 **Do not use chaining comparison expressions with Biogeme. Not only it does not provide the expected expression, but it does not trigger a warning or an exception.** .. GENERATED FROM PYTHON SOURCE LINES 442-447 .. code-block:: Python try: my_expression = 200 <= Variable('Variable2') <= 400 except BiogemeError as e: print(e) .. rst-class:: sphx-glr-script-out .. code-block:: none Expression (Variable2 >= `200.0`) cannot be used in a boolean expression. Use & for "and" and | for "or" .. GENERATED FROM PYTHON SOURCE LINES 448-449 The correct way to code this expression is .. GENERATED FROM PYTHON SOURCE LINES 449-451 .. code-block:: Python my_expression = (200 <= Variable('Variable2')) & (Variable('Variable2') <= 400) .. GENERATED FROM PYTHON SOURCE LINES 452-457 The reason is that Python executes `200 <= Variable2 <= 400` as `(200 <= Variable2) and (Variable2 <= 400)`. The `and` operator cannot be overloaded in Python. Therefore, it does not return a Biogeme expression. Note that Pandas does not allow chaining either, and has implemented a `between` function instead. .. GENERATED FROM PYTHON SOURCE LINES 457-460 .. code-block:: Python my_data.dataframe['chaining_p'] = my_data.dataframe['Variable2'].between(200, 400) display(my_data.dataframe) .. rst-class:: sphx-glr-script-out .. code-block:: none Person Exclude Variable1 Variable2 Choice Av1 Av2 Av3 chaining_p 0 1.0 0.0 10.0 100.0 2.0 0.0 1.0 0.0 False 1 1.0 0.0 20.0 200.0 2.0 1.0 1.0 1.0 True 2 1.0 1.0 30.0 300.0 3.0 1.0 1.0 1.0 True 3 2.0 0.0 40.0 400.0 1.0 1.0 1.0 1.0 True 4 2.0 1.0 50.0 500.0 2.0 1.0 1.0 1.0 False .. GENERATED FROM PYTHON SOURCE LINES 461-464 The following type of expression is another literal, corresponding to an unknown parameter. Note that the value is just a starting value for the algorithm. .. GENERATED FROM PYTHON SOURCE LINES 464-468 .. code-block:: Python beta1 = Beta('beta1', 0.2, None, None, 0) beta2 = Beta('beta2', 0.4, None, None, 0) .. GENERATED FROM PYTHON SOURCE LINES 469-471 The last argument allows to fix the value of the parameter to the value. .. GENERATED FROM PYTHON SOURCE LINES 471-474 .. code-block:: Python beta3 = Beta('beta3', 1, None, None, 1) beta4 = Beta('beta4', 0, None, None, 1) .. GENERATED FROM PYTHON SOURCE LINES 475-477 Arithmetic operators are overloaded to allow standard manipulations of expressions. .. GENERATED FROM PYTHON SOURCE LINES 477-480 .. code-block:: Python expr0 = beta3 + beta4 print(expr0) .. rst-class:: sphx-glr-script-out .. code-block:: none (Beta('beta3', 1, None, None, 1) + Beta('beta4', 0, None, None, 1)) .. GENERATED FROM PYTHON SOURCE LINES 481-484 The evaluation of expressions can be done in two ways. For simple expressions, the function `get_value`, implemented in Python, returns the value of the expression. .. GENERATED FROM PYTHON SOURCE LINES 484-486 .. code-block:: Python display(f'beta3 + beta4 = {expr0.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none beta3 + beta4 = 1 .. GENERATED FROM PYTHON SOURCE LINES 487-488 It is possible to modify the values of the parameters. .. GENERATED FROM PYTHON SOURCE LINES 488-492 .. code-block:: Python new_values = {'beta1': 1, 'beta2': 2, 'beta3': 3, 'beta4': 2} expr0.change_init_values(new_values) display(f'beta3 + beta4 = {expr0.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none Parameter beta3 is fixed, but its value is changed from 1 to 3. Parameter beta4 is fixed, but its value is changed from 0 to 2. beta3 + beta4 = 5 .. GENERATED FROM PYTHON SOURCE LINES 493-500 Consider another expression: .. math:: e_1 = 2 \beta_1 - \frac{\exp(-\beta_2)}{\beta_2 (\beta_3 \geq \beta_4) + \beta_1 (\beta_3 < \beta_4)}, where :math:`(\beta_2 \geq \beta_1)` equals 1 if :math:`\beta_2 \geq \beta_1` and 0 otherwise. .. GENERATED FROM PYTHON SOURCE LINES 500-504 .. code-block:: Python expr1 = 2 * beta1 - exp(-beta2) / (beta2 * (beta3 >= beta4) + beta1 * (beta3 < beta4)) print(expr1) display(f'expr1 = {expr1.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none ((`2.0` * Beta('beta1', 0.2, None, None, 0)) - (exp((-Beta('beta2', 0.4, None, None, 0))) / ((Beta('beta2', 0.4, None, None, 0) * (Beta('beta3', 3, None, None, 1) >= Beta('beta4', 2, None, None, 1))) + (Beta('beta1', 0.2, None, None, 0) * (Beta('beta3', 3, None, None, 1) < Beta('beta4', 2, None, None, 1)))))) expr1 = -1.275800115089098 .. GENERATED FROM PYTHON SOURCE LINES 505-507 It actually calls the function `get_value_and_derivatives`, and returns its first output (without calculating the derivatives). .. GENERATED FROM PYTHON SOURCE LINES 507-520 .. code-block:: Python value_and_derivatives: FunctionOutput = get_value_and_derivatives( expression=expr1, numerically_safe=False, betas={'beta1': 1, 'beta2': 2, 'beta3': 3, 'beta4': 2}, database=simple_database, gradient=True, hessian=True, bhhh=True, named_results=False, use_jit=True, ) .. GENERATED FROM PYTHON SOURCE LINES 521-523 .. code-block:: Python display(f'Value of the function: {value_and_derivatives.function}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the function: 1.9323323583816936 .. GENERATED FROM PYTHON SOURCE LINES 524-526 We create a pandas DataFrame just to have a nicer display of the results. The gradient, that is the first derivatives. .. GENERATED FROM PYTHON SOURCE LINES 526-529 .. code-block:: Python display('Gradient') display(pd.DataFrame(value_and_derivatives.gradient)) .. rst-class:: sphx-glr-script-out .. code-block:: none Gradient 0 0 2.000000 1 0.101501 .. GENERATED FROM PYTHON SOURCE LINES 530-531 The hessian, that is the second derivatives. .. GENERATED FROM PYTHON SOURCE LINES 531-534 .. code-block:: Python display('Hessian') display(pd.DataFrame(value_and_derivatives.hessian)) .. rst-class:: sphx-glr-script-out .. code-block:: none Hessian 0 1 0 0.0 0.000000 1 0.0 -0.169169 .. GENERATED FROM PYTHON SOURCE LINES 535-536 The BHHH matrix, that is the sum of the outer product of the gradient of each observation by itself. .. GENERATED FROM PYTHON SOURCE LINES 536-539 .. code-block:: Python display('BHHH') display(pd.DataFrame(value_and_derivatives.bhhh)) .. rst-class:: sphx-glr-script-out .. code-block:: none BHHH 0 1 0 4.000000 0.203003 1 0.203003 0.010303 .. GENERATED FROM PYTHON SOURCE LINES 540-541 We illustrate the fact that the BHHH matrix is the outer product of the gradient with itself. .. GENERATED FROM PYTHON SOURCE LINES 541-553 .. code-block:: Python display('Outer product of the gradient') display( pd.DataFrame( np.outer( value_and_derivatives.gradient, value_and_derivatives.gradient, ) ) ) .. rst-class:: sphx-glr-script-out .. code-block:: none Outer product of the gradient 0 1 0 4.000000 0.203003 1 0.203003 0.010303 .. GENERATED FROM PYTHON SOURCE LINES 554-566 .. code-block:: Python value_and_derivatives: FunctionOutput = get_value_and_derivatives( expression=expr1, numerically_safe=False, betas={'beta1': 1, 'beta2': 2, 'beta3': 3, 'beta4': 2}, database=simple_database, gradient=True, hessian=True, bhhh=True, named_results=True, use_jit=True, ) .. GENERATED FROM PYTHON SOURCE LINES 567-569 .. code-block:: Python display(f'Value of the function: {value_and_derivatives.function}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the function: 1.9323323583816936 .. GENERATED FROM PYTHON SOURCE LINES 570-571 The gradient, that is the first derivatives. .. GENERATED FROM PYTHON SOURCE LINES 571-573 .. code-block:: Python display(value_and_derivatives.gradient) .. rst-class:: sphx-glr-script-out .. code-block:: none {'beta1': np.float64(2.0), 'beta2': np.float64(0.10150146242745953)} .. GENERATED FROM PYTHON SOURCE LINES 574-575 The hessian, that is the second derivatives. .. GENERATED FROM PYTHON SOURCE LINES 575-577 .. code-block:: Python display(pd.DataFrame(value_and_derivatives.hessian)) .. rst-class:: sphx-glr-script-out .. code-block:: none beta1 beta2 beta1 0.0 0.000000 beta2 0.0 -0.169169 .. GENERATED FROM PYTHON SOURCE LINES 578-579 The BHHH matrix, that is the sum of the outer product of the gradient of each observation by itself. .. GENERATED FROM PYTHON SOURCE LINES 579-582 .. code-block:: Python display(pd.DataFrame(value_and_derivatives.bhhh)) .. rst-class:: sphx-glr-script-out .. code-block:: none beta1 beta2 beta1 4.000000 0.203003 beta2 0.203003 0.010303 .. GENERATED FROM PYTHON SOURCE LINES 583-586 It is also possible to generate a function that takes the value of the parameters as argument, and provides a tuple with the value of the expression and its derivatives. . .. GENERATED FROM PYTHON SOURCE LINES 586-596 .. code-block:: Python the_database_adapter = RegularAdapter(database=simple_database) the_function: CallableExpression = function_from_expression( expression=expr1, adapter=the_database_adapter, numerically_safe=False, use_jit=True, the_betas={}, ) .. GENERATED FROM PYTHON SOURCE LINES 597-598 We evaluate it at one point... .. GENERATED FROM PYTHON SOURCE LINES 598-604 .. code-block:: Python result: FunctionOutput = the_function([1, 2], gradient=True, hessian=True, bhhh=False) display(f'Value of the function: {result.function}') display(f'Value of the gradient: {result.gradient}') display(f'Value of the hessian: {result.hessian}') display(f'The BHHH matrix has not been requested: {result.bhhh}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the function: -1.275800115089098 Value of the gradient: [2. 5.8653004] Value of the hessian: [[ 0. 0. ] [ 0. -31.00230213]] The BHHH matrix has not been requested: None .. GENERATED FROM PYTHON SOURCE LINES 605-606 ... and at another point. .. GENERATED FROM PYTHON SOURCE LINES 606-612 .. code-block:: Python result: FunctionOutput = the_function([10, -2], gradient=True, hessian=True, bhhh=True) display(f'Value of the function: {result.function}') display(f'Value of the gradient: {result.gradient}') display(f'Value of the hessian: {result.hessian}') display(f'Value of the BHHH matrix: {result.bhhh}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the function: 23.694528049465326 Value of the gradient: [ 2. -1.84726402] Value of the hessian: [[0. 0. ] [0. 1.84726402]] Value of the BHHH matrix: [[ 4. -3.69452805] [-3.69452805 3.41238438]] .. GENERATED FROM PYTHON SOURCE LINES 613-622 .. code-block:: Python the_function: CallableExpression = function_from_expression( expression=expr1, adapter=the_database_adapter, numerically_safe=False, the_betas={}, named_output=True, use_jit=True, ) .. GENERATED FROM PYTHON SOURCE LINES 623-624 We evaluate it at one point... .. GENERATED FROM PYTHON SOURCE LINES 624-629 .. code-block:: Python result: FunctionOutput = the_function([2, 1], gradient=True, hessian=True, bhhh=False) display(f'Value of the function: {result.function}') display(f'Value of the gradient: {result.gradient}') display(f'Value of the hessian: {result.hessian}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the function: -1.275800115089098 Value of the gradient: {'beta1': np.float64(2.0), 'beta2': np.float64(5.865300402811842)} Value of the hessian: {'beta1': {'beta1': np.float64(0.0), 'beta2': np.float64(0.0)}, 'beta2': {'beta1': np.float64(0.0), 'beta2': np.float64(-31.002302129148305)}} .. GENERATED FROM PYTHON SOURCE LINES 630-632 The following function scans the expression and extracts a dict with all free parameters. .. GENERATED FROM PYTHON SOURCE LINES 632-636 .. code-block:: Python free_betas = list_of_free_betas_in_expression(the_expression=expr1) set_of_free_beta_names = {beta.name for beta in free_betas} display(f'free parameters: {set_of_free_beta_names}') .. rst-class:: sphx-glr-script-out .. code-block:: none free parameters: {'beta2', 'beta1'} .. GENERATED FROM PYTHON SOURCE LINES 637-641 .. code-block:: Python fixed_betas = list_of_fixed_betas_in_expression(the_expression=expr1) set_of_fixed_beta_names = {beta.name for beta in fixed_betas} display(f'fixed parameters: {set_of_fixed_beta_names}') .. rst-class:: sphx-glr-script-out .. code-block:: none fixed parameters: {'beta4', 'beta3'} .. GENERATED FROM PYTHON SOURCE LINES 642-646 .. code-block:: Python all_betas = list_of_all_betas_in_expression(the_expression=expr1) set_of_all_beta_names = {beta.name for beta in all_betas} display(f'all parameters: {set_of_all_beta_names}') .. rst-class:: sphx-glr-script-out .. code-block:: none all parameters: {'beta4', 'beta2', 'beta1', 'beta3'} .. GENERATED FROM PYTHON SOURCE LINES 647-648 The list of variables can also be extracted. In this case, there is none. .. GENERATED FROM PYTHON SOURCE LINES 648-652 .. code-block:: Python all_variables = list_of_variables_in_expression(the_expression=expr1) set_of_variables = {variable.name for variable in all_variables} display(f'all variables: {set_of_variables}') .. rst-class:: sphx-glr-script-out .. code-block:: none all variables: set() .. GENERATED FROM PYTHON SOURCE LINES 653-654 We include one variable .. GENERATED FROM PYTHON SOURCE LINES 654-660 .. code-block:: Python new_expression = expr1 + Variable('a_variable') all_variables = list_of_variables_in_expression(the_expression=new_expression) set_of_variables = {variable.name for variable in all_variables} display(f'all variables: {set_of_variables}') .. rst-class:: sphx-glr-script-out .. code-block:: none all variables: {'a_variable'} .. GENERATED FROM PYTHON SOURCE LINES 661-667 We now illustrate how to calculate a logit model, that is .. math:: \frac{y_1 e^{V_1}}{y_0 e^{V_0}+y_1 e^{V_1}+y_2 e^{V_2}} where :math:`V_0=-\beta_1`, :math:`V_1=-\beta_2` and :math:`V_2=-\beta_1`, and :math:`y_i = 1`, :math:`i=1,2,3`. .. GENERATED FROM PYTHON SOURCE LINES 667-672 .. code-block:: Python v = {0: -beta1, 1: -beta2, 2: -beta1} av = {0: 1, 1: 1, 2: 1} expr7 = LogLogit(v, av, 1) # value = evaluate_simple_expression(expression=z, database=None, numerically_safe=False) .. GENERATED FROM PYTHON SOURCE LINES 673-675 .. code-block:: Python display(f'Value of the log of the logit for alternative 1: {expr7.get_value()}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the log of the logit for alternative 1: -1.2362866960692136 .. GENERATED FROM PYTHON SOURCE LINES 676-677 If the alternative is not in the choice set, an exception is raised. .. GENERATED FROM PYTHON SOURCE LINES 677-683 .. code-block:: Python expr7_wrong = LogLogit(v, av, 3) try: expr7_wrong.get_value() except BiogemeError as e: print(f'Exception: {e}') .. rst-class:: sphx-glr-script-out .. code-block:: none Exception: Alternative 3 does not appear in the list of utility functions: dict_keys([0, 1, 2]) .. GENERATED FROM PYTHON SOURCE LINES 684-685 We show how to calculate the logsum. .. GENERATED FROM PYTHON SOURCE LINES 685-688 .. code-block:: Python for util in v.values(): print(util.get_value()) .. rst-class:: sphx-glr-script-out .. code-block:: none -0.2 -0.4 -0.2 .. GENERATED FROM PYTHON SOURCE LINES 689-695 .. code-block:: Python logsum = np.log( np.sum( [np.exp(util.get_value()) for util in v.values()], ) ) display(f'Value of the logsum: {logsum}') .. rst-class:: sphx-glr-script-out .. code-block:: none Value of the logsum: 0.8362866960692136 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.555 seconds) .. _sphx_glr_download_auto_examples_programmers_plot_expressions.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_expressions.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_expressions.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_expressions.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_