SENSITIVITY

Overview

The SENSITIVITY function computes the sensitivity of a scalar mathematical model with respect to its parameters using algorithmic differentiation. Sensitivity analysis quantifies how changes in input parameters affect the output of a model, providing critical insights for optimization, uncertainty quantification, and model calibration.

This implementation uses CasADi, an open-source framework for nonlinear optimization and algorithmic differentiation. CasADi provides efficient symbolic computation and automatic differentiation capabilities, making it well-suited for computing exact sensitivities of complex mathematical expressions. For more details, see the CasADi documentation.

The function computes the Jacobian matrix of the model output with respect to the specified parameters. For a scalar model f(x_1, \ldots, x_n; a_1, \ldots, a_m), the sensitivity with respect to each parameter a_j is the partial derivative:

\frac{\partial f}{\partial a_j} \bigg|_{x, a}

These partial derivatives are evaluated at the specified variable values and parameter values, returning a row vector of sensitivities—one for each parameter. This allows users to identify which parameters have the most significant impact on the model’s output at a given operating point.

Interpreting sensitivities is often simplest in terms of local, absolute units: larger magnitudes of \partial f/\partial a_j mean the output changes more per unit change in the parameter near the evaluation point. When parameters have very different scales or units, it can also be useful to compare scaled sensitivities (for example, multiplying by a parameter scale factor) so that “one unit” is comparable across parameters. This is particularly important in engineering and physical sciences where parameters may represent vastly different physical quantities.

Sensitivity analysis is fundamental in many applications:

  • Optimization: Understanding how objective functions respond to parameter changes, which helps in selecting appropriate optimization algorithms and tuning their parameters.
  • Uncertainty quantification: Identifying which parameters most influence model outputs, allowing researchers to focus their data collection efforts on the most critical parameters.
  • Model calibration: Determining parameter importance for fitting models to data, ensuring that the most influential parameters are accurately estimated.
  • Engineering design: Evaluating robustness of designs to parameter variations, which is essential for ensuring that a design performs reliably under a range of conditions.

The function supports user-defined variable and parameter names, allowing intuitive model expressions like a*x^2 + b*x + c. Excel’s exponentiation operator (^) is automatically converted to Python’s ** operator, and all CasADi mathematical functions are available through the ca namespace (e.g., ca.sin(x), ca.exp(x)).

This example function is provided as-is without any representation of accuracy.

Excel Usage

=SENSITIVITY(model, variables, parameters, variable_names, parameter_names)
  • model (str, required): String expression representing the model output (supports CasADi functions via ca namespace and Excel exponentiation via ^)
  • variables (list[list], required): Single row containing the evaluation point for each independent variable
  • parameters (list[list], required): Single row containing the parameter values at which sensitivity is evaluated
  • variable_names (list[list], optional, default: null): Optional names of the variables in order (defaults to x1, x2, … if omitted)
  • parameter_names (list[list], optional, default: null): Optional names of the parameters in order (defaults to a1, a2, … if omitted)

Returns (list[list]): 2D list of partial derivatives, or error message string.

Examples

Example 1: Demo case 1

Inputs:

model variables parameters variable_names parameter_names
x1^2 + a1*x1 2 3 x1 a1

Excel formula:

=SENSITIVITY("x1^2 + a1*x1", 2, 3, "x1", "a1")

Expected output:

Result
2

Example 2: Demo case 2

Inputs:

model variables parameters variable_names parameter_names
ca.exp(ax) + by^2 1 2 0.5 2 x y a b

Excel formula:

=SENSITIVITY("ca.exp(a*x) + b*y^2", {1,2}, {0.5,2}, {"x","y"}, {"a","b"})

Expected output:

Result
1.649 4

Example 3: Demo case 3

Inputs:

model variables parameters variable_names parameter_names
ax^3 + bx^2 + c*x 2 1 2 3 x a b c

Excel formula:

=SENSITIVITY("a*x^3 + b*x^2 + c*x", 2, {1,2,3}, "x", {"a","b","c"})

Expected output:

Result
8 4 2

Example 4: Demo case 4

Inputs:

model variables parameters variable_names parameter_names
x^2 + a*ca.sin(x) + b 1 2 5 x a b

Excel formula:

=SENSITIVITY("x^2 + a*ca.sin(x) + b", 1, {2,5}, "x", {"a","b"})

Expected output:

Result
0.8415 1

Python Code

import re
import casadi as ca

def sensitivity(model, variables, parameters, variable_names=None, parameter_names=None):
    """
    Compute the sensitivity of a scalar model with respect to its parameters using CasADi.

    See: https://web.casadi.org/docs/

    This example function is provided as-is without any representation of accuracy.

    Args:
        model (str): String expression representing the model output (supports CasADi functions via ca namespace and Excel exponentiation via ^)
        variables (list[list]): Single row containing the evaluation point for each independent variable
        parameters (list[list]): Single row containing the parameter values at which sensitivity is evaluated
        variable_names (list[list], optional): Optional names of the variables in order (defaults to x1, x2, ... if omitted) Default is None.
        parameter_names (list[list], optional): Optional names of the parameters in order (defaults to a1, a2, ... if omitted) Default is None.

    Returns:
        list[list]: 2D list of partial derivatives, or error message string.
    """
    # Helper to normalize values that may be passed as scalars by Excel for single-cell ranges.
    def to2d(x):
        return [[x]] if not isinstance(x, list) else x

    if not isinstance(model, str) or model.strip() == "":
        return "Invalid input: model must be a non-empty string."

    # Normalize inputs that may be passed as scalars.
    variables = to2d(variables)
    parameters = to2d(parameters)

    # Validate and convert variable values
    try:
        variable_values = [float(v) for v in variables[0]]
    except (ValueError, TypeError, IndexError):
        return "Invalid input: variables must contain numeric values."

    # Validate and convert parameter values
    try:
        parameter_values = [float(p) for p in parameters[0]]
    except (ValueError, TypeError, IndexError):
        return "Invalid input: parameters must contain numeric values."

    if len(variable_values) == 0:
        return "Invalid input: variables must include at least one value."
    if len(parameter_values) == 0:
        return "Invalid input: parameters must include at least one value."

    # Validate and normalize names
    if variable_names is not None:
        variable_names = to2d(variable_names)
        try:
            var_names_list = variable_names[0]
        except (IndexError, TypeError):
            return "Invalid input: variable_names must be a valid list."
        if len(var_names_list) != len(variable_values):
            return "Invalid input: number of variable names must match number of variable values."
        if not all(isinstance(n, str) and n.strip() for n in var_names_list):
            return "Invalid input: variable_names must contain non-empty strings."
    else:
        var_names_list = [f"x{i+1}" for i in range(len(variable_values))]

    if parameter_names is not None:
        parameter_names = to2d(parameter_names)
        try:
            param_names_list = parameter_names[0]
        except (IndexError, TypeError):
            return "Invalid input: parameter_names must be a valid list."
        if len(param_names_list) != len(parameter_values):
            return "Invalid input: number of parameter names must match number of parameter values."
        if not all(isinstance(n, str) and n.strip() for n in param_names_list):
            return "Invalid input: parameter_names must contain non-empty strings."
    else:
        param_names_list = [f"a{i+1}" for i in range(len(parameter_values))]

    # Create CasADi symbols
    variable_symbols = [ca.MX.sym(n) for n in var_names_list]
    parameter_symbols = [ca.MX.sym(n) for n in param_names_list]

    # Build evaluation context for eval() so user can reference variable and parameter names
    evaluation_context = {
        **{name: variable_symbols[idx] for idx, name in enumerate(var_names_list)},
        **{name: parameter_symbols[idx] for idx, name in enumerate(param_names_list)},
        "ca": ca
    }

    # Convert Excel exponentiation (^) to Python exponentiation (**)
    model = re.sub(r'\^', '**', model)

    try:
        expression = eval(model, {"__builtins__": {}}, evaluation_context)
    except (SyntaxError, NameError, TypeError, AttributeError) as exc:
        return f"Invalid model expression: {exc}"
    except Exception as exc:
        return f"Error evaluating model expression: {exc}"

    try:
        jac = ca.jacobian(expression, ca.vertcat(*parameter_symbols))
        sensitivity_fn = ca.Function("sensitivity_fn", variable_symbols + parameter_symbols, [jac])
        casadi_result = sensitivity_fn(*(variable_values + parameter_values))
    except (RuntimeError, TypeError, ValueError) as exc:
        return f"Error during CasADi calculation: {exc}"
    except Exception as exc:
        return f"Unexpected error during CasADi calculation: {exc}"

    # casadi_result is typically a DM; return as nested Python lists
    try:
        if isinstance(casadi_result, ca.DM):
            return casadi_result.full().tolist()
        # Some CasADi versions return a list/tuple with one element
        if isinstance(casadi_result, (list, tuple)) and len(casadi_result) == 1 and isinstance(casadi_result[0], ca.DM):
            return casadi_result[0].full().tolist()
    except (AttributeError, TypeError) as exc:
        return f"Error converting CasADi result to list: {exc}"

    return "Error during CasADi calculation: Unexpected result type."

Online Calculator