Header menu logo bristlecone

ScriptNotebook

Model Fitting

Model fitting in Bristlecone is the process of estimating model parameters from data using a chosen estimation engine.
This page provides a high‑level overview of the workflow, the objects involved, and how to interpret the results.

Bristlecone fits require three components whose types must align:

Once these are defined, fitting is performed with Bristlecone.fit or Bristlecone.tryFit.

Before undertaking fits to real data, Bristlecone also provides a model testing framework to check that the model and engine can recover parameters from synthetic data. Although testing is optional, it is strongly recommended to ensure that the model is identifiable in the given model fitting method.

Testing a model and engine (recommended)

Before relying on a model–engine combination, Bristlecone provides a built‑in testing framework:

open Bristlecone

Bristlecone.testModel
Bristlecone.tryTestModel

Testing works by generating random parameter sets (θ), simulating synthetic time‑series from the model, attempting to re‑estimate θ from the synthetic data, and finally comparing the recovered parameters to the true ones.

Examination of the test result will indicate:

If the recovered parameters diverge strongly from the true values, this indicates a model identifiability issue, an optimisation configuration problem, or a mismatch between data resolution and model structure.

The Test.* module and functions provides a way to scaffold a test using pre-determined criteria for the synthetic data, creation of observation error around the time-series, and other core testing parameters. A fully worked example of a model test may be seen in the predator-prey example.

Fitting the model with real data

Once the model and engine have been validated (or if you choose to skip testing), fitting is performed with:

fun engine endCondition data model ->

    let result1 = Bristlecone.fit engine endCondition data model
    let result2  = Bristlecone.tryFit engine endCondition data model
    ()

As with testing, the try fit function returns a Result type instead of an exception on error. The endCondition controls when the optimiser or sampler stops (e.g. number of iterations, convergence criteria).

The esimtation result

Model-fitting returns an EstimationResult, which contains:

Accessing estimated parameter values

To access parameter values from an EstimationResult, you may use the .Get or .TryGet members to retrieve parameter estimates in their original units of measure. You must pass the original parameter as declared in the model to access individual values in this way.

open Bristlecone.Language
open FSharp.Data.UnitSystems.SI.UnitNames

let exampleParameter = parameter "e" Positive 0.01<watt/second> 0.10<watt/second>

fun (result:ModelSystem.EstimationResult<'a,'c,'b>) ->

    let e = result.Parameters.Get exampleParameter
    let eR = result.Parameters.TryGet exampleParameter
    ()

Here, you can see that the units of the retrieved parameters after estimation are watts per second, as defined in the original model's parameters.

Multiple items
module Bristlecone from Bristlecone
<namespacedoc><summary>The core library of Bristlecone, containing model-fitting functions.</summary></namespacedoc>
Main functionality of Bristlecone, including functions to scaffold `ModelSystem`s and for model-fitting (tests and real fits).


--------------------
namespace Bristlecone
val testModel: engine: EstimationEngine.EstimationEngine<'date,'timespan,'modelTimeUnit,'state> -> endCondition: EstimationEngine.EndCondition -> settings: Test.TestSettings<'state,'date,'yearUnit,'timespan> -> model: ModelSystem.ModelSystem<'modelTimeUnit> -> Test.TestResult<'date,'yearUnit,'timespan,ModelSystem.state> (requires comparison and comparison)
<summary>Test that the specified estimation engine can correctly estimate known parameters. Random parameter sets are generated from the given model system.</summary>
<param name="engine">An estimation engine containing the method used for model-fitting.</param>
<param name="settings">Test settings that define how the test will be conducted.</param>
<param name="model">The model system to test against the estimation engine.</param>
<returns>A test result that indicates differences between the expected and actual fit.</returns>
val tryTestModel: engine: EstimationEngine.EstimationEngine<'date,'timespan,'modelTimeUnit,'state> -> endCondition: EstimationEngine.EndCondition -> settings: Test.TestSettings<'state,'date,'timeunit,'timespan> -> model: ModelSystem.ModelSystem<'modelTimeUnit> -> Result<Test.TestResult<'date,'timeunit,'timespan,ModelSystem.state>,string> (requires comparison and comparison)
<summary>Tests that the specified estimation engine can correctly estimate known parameters given specfici test settings. Random parameter sets and resultant fake time-series data are generated for the model system by using the rules and noise generation settings in the stated test settings.</summary>
<param name="engine"></param>
<param name="settings"></param>
<param name="model"></param>
<returns>A test result that indicates the error structure. It is wrapped in an F# Result, indicating if the procedure was successful or not.</returns>
val engine: EstimationEngine.EstimationEngine<'a,'b,'u,'v> (requires comparison and comparison)
val endCondition: EstimationEngine.EndCondition
val data: CodedMap<Time.TimeSeries<float<'v>,'a,'c,'b>> (requires comparison and comparison)
val model: ModelSystem.ModelSystem<'u>
val result1: ModelSystem.EstimationResult<'a,'c,'b> (requires comparison and comparison)
val fit: engine: EstimationEngine.EstimationEngine<'a,'b,'modelTimeUnit,'u> -> endCondition: EstimationEngine.EndCondition -> timeSeriesData: CodedMap<Time.TimeSeries<float<'u>,'a,'c,'b>> -> model: ModelSystem.ModelSystem<'modelTimeUnit> -> ModelSystem.EstimationResult<'a,'c,'b> (requires comparison and comparison)
<summary>Fit a time-series model to data.</summary>
<param name="engine">An estimation engine configured and tested for the given model.</param>
<param name="endCondition">The condition at which optimisation should cease.</param>
<param name="timeSeriesData">Time-series dataset that contains a series for each equation in the model system.</param>
<param name="model">A model system of equations, likelihood function, estimatible parameters, and optional measures.</param>
<returns>The result of the model-fitting procedure. If an error occurs, throws an exception.</returns>
val result2: Result<ModelSystem.EstimationResult<'a,'c,'b>,string> (requires comparison and comparison)
val tryFit: engine: EstimationEngine.EstimationEngine<'date,'timespan,'modelTimeUnit,'stateUnit> -> endCondition: EstimationEngine.EndCondition -> observedSeries: CodedMap<Time.TimeSeries<float<'stateUnit>,'date,'yearType,'timespan>> -> model: ModelSystem.ModelSystem<'modelTimeUnit> -> Result<ModelSystem.EstimationResult<'date,'yearType,'timespan>,string> (requires comparison and comparison)
<summary> Fit a time-series model to data. Please note: it is strongly recommended that you test that the given `EstimationEngine` can correctly identify known parameters for your model. Refer to the `Bristlecone.testModel` function, which can be used to generate known data and complete this process. </summary>
<param name="engine">The engine encapsulates all settings that form part of the estimation method. Importantly, this includes the random number generator used for all stages of the analysis; if this is set using a fixed seed, the result will be reproducable.</param>
<param name="endCondition">You must specify a stopping condition, after which the optimisation process will cease. Bristlecone includes built-in end conditions in the `Bristlecone.Optimisation.EndConditions` module.</param>
<param name="timeSeriesData"></param>
<param name="model"></param>
<returns></returns>
module Language from Bristlecone
<summary> An F# Domain Specific Language (DSL) for scripting with Bristlecone. </summary>
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Data
namespace Microsoft.FSharp.Data.UnitSystems
namespace Microsoft.FSharp.Data.UnitSystems.SI
namespace Microsoft.FSharp.Data.UnitSystems.SI.UnitNames
val exampleParameter: IncludedParameter<watt/second>
Multiple items
val parameter: code: string -> con: Parameter.Constraint<'u> -> lower: float<'u> -> upper: float<'u> -> IncludedParameter<'u>
<summary> Define an estimatable parameter for a Bristlecone model. </summary>

--------------------
[<Measure>] type parameter
val Positive: Parameter.Constraint<'u>
[<Measure>] type watt = joule/second
[<Measure>] type second
val result: ModelSystem.EstimationResult<'a,'c,'b>
module ModelSystem from Bristlecone
<summary> Represents an ordinary differential equation model system and its likelihood as an objective function that may be optimised. </summary>
type EstimationResult<'date,'timeunit,'timespan> = { ResultId: Guid Likelihood: float<-logL> Parameters: ParameterPool Series: CodedMap<FitSeries<'date,'timeunit,'timespan>> Trace: Trace list InternalDynamics: CodedMap<float<state> array> option Metadata: List<string * string> }
<summary> An estimated model fit for a time-series model. </summary>
'a
'c
'b
val e: float<watt/second>
ModelSystem.EstimationResult.Parameters: Parameter.Pool.ParameterPool
member Parameter.Pool.ParameterPool.Get: included: IncludedParameter<'u> -> float<'u>
val eR: float<watt/second> option
member Parameter.Pool.ParameterPool.TryGet: included: IncludedParameter<'u> -> float<'u> option

Type something to start searching.