Objective functions¶
Cost, error, regularizer, and constraint schemas used inside
FittingObjective / DesignObjective. Mirrors
ionworkspipeline.data_fits.objective_functions and the regularizers in
ionworkspipeline.priors.
Schemas for objective_functions.
- class ionworks_schema.objective_functions.ChiSquare(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, normalization: str | int | float | None = None, scale: str | int | float | None = None, variable_standard_deviations: dict[str, float])¶
Bases:
ErrorFunctionChi-square cost function that measures the weighted sum of squared differences between observed and expected values, normalized by their standard deviations.
The chi-square statistic is calculated as: chi2 = sum((observed - expected) / sigma)**2 where sigma is the standard deviation for each variable.
Parameters¶
- variable_standard_deviationsdict
Dictionary mapping variable names to their standard deviations. For example: {“a”: 0.5, “b”: 0.3} means variable “a” has sigma=0.5 and variable “b” has sigma=0.3.
Notes¶
For a dataset with N points, if the model fits the data well and the errors are normally distributed, the chi-square value should be approximately N (the number of degrees of freedom).
Extends:
ionworks_schema.objective_functions.objective_functions.ErrorFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.Constraint(fun, regularizer_weight=None)¶
Bases:
RegularizerEquality or inequality constraint evaluated at fit time.
Inequality constraints use
pybammHeaviside operators (<=,>=); equality constraints use apybamm.Symbolthat evaluates to zero when satisfied.Parameters¶
- funpybamm.Symbol or Number
Constraint expression. For inequality constraints, a Heaviside of the form
g(x) <= h(x). For equality constraints,f(x)evaluating to zero when satisfied.- regularizer_weightfloat, optional
Weight applied to the constraint term. Default is 1.0.
Examples¶
>>> import pybamm >>> x0, x1 = pybamm.InputParameter("x0"), pybamm.InputParameter("x1") >>> con = iws.objective_functions.Constraint(fun=x0 - 0.5 * x1) >>> obj = iws.objectives.OCPHalfCell( ... electrode="positive", data_input="path/to/ocp.csv", ... constraints=[con], ... )
Extends:
ionworks_schema.objective_functions.regularizers.Regularizer- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.DesignFunction(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None)¶
Bases:
ObjectiveFunctionA generalized design cost function for optimization problems.
This class serves as a base for design optimization objectives where the goal is to maximize (or minimize) certain design metrics like energy density, power density, etc.
Parameters¶
- objective_weightsdict, optional
Dictionary of {name: weight} pairs for each objective in the cost function. If None, all objectives are weighted equally. If a name is not in the dictionary, it is given a weight of 1.
Extends:
ionworks_schema.objective_functions.objective_functions.ObjectiveFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.ErrorFunction(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, normalization: str | int | float | None = None, scale: str | int | float | None = None)¶
Bases:
ObjectiveFunctionBase for residual-based error measures (also known as distance functions).
Adds
normalization(and the deprecatedscalealias) on top ofObjectiveFunction.RMSE,MAE,MSE,Max,SSE,ChiSquare, andMultiCostall inherit from here.Parameters¶
- normalizationstr or float, optional
How to normalize the model and data for each variable in the cost.
"mean"(default): use the mean of the data."identity": use 1 (no normalization)."range": use the range of the data."sum_squares": use the sum of squares of the data."mean_squares": use the mean of the sum of squares ofthe data.
"root_mean_squares": use the root mean square of thedata.
float: use that fixed value.
- nan_valuesstr or float, optional
How to replace NaN values in the model output — see
ObjectiveFunction.- objective_weightsdict[str, float], optional
Per-objective weights — see
ObjectiveFunction.- variable_weightsdict[str, float], optional
Per-variable weights — see
ObjectiveFunction.- scalestr or float, optional
Deprecated alias for
normalization. Usenormalizationinstead.
Extends:
ionworks_schema.objective_functions.objective_functions.ObjectiveFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.GaussianLogLikelihood(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, sigma: dict[str, int | float | str])¶
Bases:
ObjectiveFunctionGaussian negative log-likelihood cost function.
Computes the Gaussian NLL:
NLL = 0.5 * Σ_vars [ N_i * log(2π * σ_i²) + Σ_j (y_ij - ŷ_ij)² / σ_i² ]
This enables MLE with noise estimation, MAP estimation, and Bayesian posterior sampling (MCMC).
Parameters¶
- sigmadict[str, float | str]
Mapping of variable names to noise standard deviations (σ). Values can be:
A float: fixed known noise standard deviation.
A string: name of a fitting parameter to be optimised (looked up from the current inputs at evaluation time via
set_current_inputs).
- nan_valuesstr or float, optional
How to handle NaN values in model output. Options: a float constant (default: 1e10), “mean”, or “min”. The default fills NaN with a large penalty value to ensure solver failures produce high costs.
Examples¶
>>> cost = iws.costs.GaussianLogLikelihood(sigma={"Voltage [V]": 0.005}) >>> fit = iws.DataFit( ... objectives={"cycle": iws.objectives.CurrentDriven(data_input="path/to/cycle.csv")}, ... parameters={"x": iws.Parameter("x", initial_value=1.0, bounds=(0.0, 2.0))}, ... cost=cost, ... )
Extends:
ionworks_schema.objective_functions.objective_functions.ObjectiveFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.MAE(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, normalization: str | int | float | None = None, scale: str | int | float | None = None)¶
Bases:
ErrorFunctionMean-absolute-error cost function.
Instead of squaring residuals, this cost function uses the absolute values, which makes it less sensitive to outliers compared to squared-error metrics.
For scalar output, it returns the sum of absolute residuals divided by the number of points. For array output, it returns the signed square root of the absolute residuals, normalized by the square root of the number of points.
Examples¶
>>> cost = iws.costs.MAE() >>> val = iws.Validation( ... objectives={"cycle": iws.objectives.CurrentDriven(data_input="path/to/cycle.csv")}, ... summary_stats=[cost], ... )
Extends:
ionworks_schema.objective_functions.objective_functions.ErrorFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.MSE(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, normalization: str | int | float | None = None, scale: str | int | float | None = None)¶
Bases:
ErrorFunctionMean-square-error cost function.
Similar to SSE, but normalizes by the number of data points. This makes the cost independent of the number of data points.
For scalar output, it returns the sum of squared residuals divided by the number of points. For array output, it returns the SSE residuals divided by the square root of the number of points.
Extends:
ionworks_schema.objective_functions.objective_functions.ErrorFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.Max(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, normalization: str | int | float | None = None, scale: str | int | float | None = None)¶
Bases:
ErrorFunctionCost function that reports the maximum error between the model and the data.
For scalar output, it returns the maximum absolute value of any residual. For array output, it returns a single-element array containing the square root of the maximum error.
Useful when you want to minimize the worst-case error rather than an average.
Examples¶
>>> cost = iws.costs.Max() >>> val = iws.Validation( ... objectives={"cycle": iws.objectives.CurrentDriven(data_input="path/to/cycle.csv")}, ... summary_stats=[cost], ... )
Extends:
ionworks_schema.objective_functions.objective_functions.ErrorFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.MultiCost(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, normalization: str | int | float | None = None, scale: str | int | float | None = None, costs: list[dict[str, Any]] | dict[Any, float], accumulator: Any | None = None)¶
Bases:
ErrorFunctionCost function that is a combination of multiple costs
Parameters¶
- costsdict of {cost: weight}
Dict of costs and their weights.
- accumulatorfunction, optional
The function to use to combine the costs. Default is sum.
Notes¶
All constituent costs must support the output mode (scalar or residuals) selected by the optimizer. The default accumulator (sum) combines the weighted costs by addition.
Extends:
ionworks_schema.objective_functions.objective_functions.ErrorFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.ObjectiveFunction(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None)¶
Bases:
BaseSchemaBase class for all cost / objective functions.
Concrete cost classes (
RMSE,MAE,Max,ChiSquare,GaussianLogLikelihood,DesignFunction, …) all inherit from this base, so anywhere the schema needs to type “a list of costs” (e.g.Validation.summary_stats) the type islist[ObjectiveFunction].Parameters¶
- objective_weightsdict[str, float], optional
Mapping of objective name to weight in the combined cost. If None, all objectives are weighted equally. Objectives not listed in the dict get a weight of 1.
- variable_weightsdict[str, float], optional
Mapping of variable name to weight. If None, all variables are weighted equally. Variables not listed in the dict get a weight of 1.
- nan_valuesstr or float, optional
How to replace NaN values in the model output.
"mean": use the mean of the non-NaN model values."min": use the minimum of the non-NaN model values.float: use that fixed value.
Defaults to
"mean".
Extends:
ionworks_schema.base.BaseSchema- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.Penalty(fun, regularizer_weight=None)¶
Bases:
RegularizerSoft penalty term added to the fit cost.
Parameters¶
- funpybamm.Symbol or Number
Penalty expression as a
pybamm.Symbolor a constant number.- regularizer_weightfloat, optional
Weight applied to the penalty term. Default is 1.0.
Examples¶
>>> import pybamm >>> x = pybamm.InputParameter("x") >>> pen = iws.objective_functions.Penalty(fun=x ** 2, regularizer_weight=0.1) >>> obj = iws.objectives.OCPHalfCell( ... electrode="positive", data_input="path/to/ocp.csv", ... penalties=[pen], ... )
Extends:
ionworks_schema.objective_functions.regularizers.Regularizer- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.Prior(name, distribution, regularizer_weight=None)¶
Bases:
RegularizerRegularization prior on a parameter.
Parameters¶
- namestr or list of str
Parameter name(s) the prior applies to.
- distributionionworks_schema.stats.Distribution
Probability distribution describing prior beliefs about the parameter(s).
- regularizer_weightfloat, optional
Weight applied to the prior’s contribution to the cost. Default is 1.0.
Examples¶
>>> prior = iws.priors.Prior("Q_pe", iws.stats.Normal(mean=3.0, std=0.2)) >>> fit = iws.DataFit( ... objectives={"ocp": iws.objectives.OCPHalfCell( ... electrode="positive", data_input="path/to/ocp.csv", ... )}, ... priors={"Q_pe": prior}, ... )
Extends:
ionworks_schema.objective_functions.regularizers.Regularizer- distribution: Annotated[dict[str, Any] | Distribution | Any, FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])]¶
- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.RMSE(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, normalization: str | int | float | None = None, scale: str | int | float | None = None)¶
Bases:
ErrorFunctionRoot-mean-square-error cost function.
Takes the square root of the MSE to provide a value in the same units as the original data. This is often used in scientific and engineering applications when the magnitude of error in the original units is important.
This cost function only supports scalar output.
Examples¶
>>> cost = iws.costs.RMSE() >>> # slot into a DataFit's `cost` or a Validation's `summary_stats` >>> val = iws.Validation( ... objectives={"cycle": iws.objectives.CurrentDriven(data_input="path/to/cycle.csv")}, ... summary_stats=[cost], ... )
Extends:
ionworks_schema.objective_functions.objective_functions.ErrorFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class ionworks_schema.objective_functions.SSE(*, objective_weights: dict[str, float] | None = None, variable_weights: dict[str, float] | None = None, nan_values: str | int | float | None = None, normalization: str | int | float | None = None, scale: str | int | float | None = None)¶
Bases:
ErrorFunctionSum-of-squared-errors cost function.
Calculates the sum of squared differences between model and data: SSE = Σ(model - data)²
Extends:
ionworks_schema.objective_functions.objective_functions.ErrorFunction- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].