The Bristlecone Language: Writing Models

Bristlecone includes a language for expressing mathematical models, and combining these to form hypotheses for testing. You can use the language by opening it's namespace:

open Bristlecone            // Opens Bristlecone core library and estimation engine
open Bristlecone.Language   // Open the language for writing Bristlecone models

Writing mathematical expressions

In Bristlecone, mathematical expressions to be used within a model may be written using simple terms. Consider the following example of an ordinary differential equation of logistic growth:

let dNdt = Parameter "r" * This * (Constant 1. - (This / Parameter "K"))

Here, we have used the following model expressions:

You can use all standard mathematical operators * / + - % ** to build your model. There are additional model expressions that may be used to build up more complex expressions (which are defined in the ModelExpression discriminated union).

Additional model expressions

Time-varying parameters

Often, a time-series model needs to take account of environmental variability. For example, changes in temperature and precipitation may influence the growth rate of a plant over time. Bristlecone supports time-varying parameters in equations using the form:

Environment "T[min]"

Here, we have defined the minimum temperature (T[min]) as a time-varying (or environment) parameter. Unlike Paramater items, T[min] will not be estimated during model-fitting, but will be read from the environmental properties for the appropriate time interval.


You can define a conditional model fragment by using the Conditional term. A Conditional model expression takes a function with one argument - a function that represents the future computation of the model expression (compute - with signature ModelExpression -> float). Within this function, you can then evaluate the answer of any model expressions by passing them as the argument to the compute function. Please see the below example:

let linear =
    Conditional(fun compute ->
        if compute (Parameter "a" * Constant 5.) < 1e-12 
        then Invalid 
        else Parameter "a" * This)

In this example, the function is limited such that the combination of parameter value a with a theoretical value of This at 5.0 cannot result in an answer that is less than 1e-12. If this is the case, the result of the model is Invalid.


The Invalid keyword is useful in combination with the Conditional keyword, as demonstrated above. When any model expression returns Invalid, the model fails. During optimisation, this is useful to constrain the search within parameter space to values that do not tend to infinity, or where values may be theoretically implausable.


Sometimes, a complex sub-model may need to be inserted where you do not wish to rewrite it into the Bristlecone language. You may also not have access to the original source, or be calling from an external library. In these cases, you can use the Arbitrary model expression to wrap the function for Bristlecone. Helper functions are included to simplify this process within the Arbitrary module:

/// x: population size
/// t: current time
/// z: some environmental value
let someArbitraryFn x t z =
    x + t * 1.0 - z

// TODO Insert example here


The Time keyword simply retrives the current time index; as such, it can be used to formulate time-dependent models.

namespace Bristlecone
Multiple items
module Bristlecone from Bristlecone

namespace Bristlecone
module Language from Bristlecone
<summary> An F# Domain Specific Language (DSL) for scripting with Bristlecone. </summary>
val dNdt : ModelExpression
Multiple items
union case ModelExpression.Parameter: string -> ModelExpression

module Parameter from Bristlecone
union case ModelExpression.This: ModelExpression
union case ModelExpression.Constant: float -> ModelExpression
union case ModelExpression.Environment: string -> ModelExpression
val linear : ModelExpression
union case ModelExpression.Conditional: ((ModelExpression -> float) -> ModelExpression) -> ModelExpression
val compute : (ModelExpression -> float)
union case ModelExpression.Invalid: ModelExpression
val someArbitraryFn : x:float -> t:float -> z:float -> float
 x: population size
 t: current time
 z: some environmental value
val x : float
val t : float
val z : float