Parameters guide

Note

All the AIBECS tutorials and how-to guides are available as Jupyter notebooks. You can view them with nbvieweror execute them online with binder by clicking on the badges above! (Note that binder can be slow to launch and its memory caps can be a problem when running.)

Here we will describe the AIBECS interface. This guide will take you through some examples of setting up model parameters.

Note

The parameters features in AIBECS essentially come from other packages. These include Parameters.jl, FieldMetadata.jl, Flatten.jl, Unitful.jl.

As usual, make sure you are using AIBECS

using AIBECS

Abstract parameters type

The AIBECS provides a set of features to create and use parameters. This features are implemented as functions that must be provided with a parameters type. But each set of parameters is different, and AIBECS cannot know beforehand what parameters you want to use. The AIBECS thus provides an abstract parameters type, called AbstractParameters, upon which all the AIBECS functionality is built. This is why when you create a set of parameters in AIBECS, you must declare it as a subtype of AbstractParameters. Here is an example.

struct SimpleParams{T} <: AbstractParameters{T}
    α::T
    β::T
end

Once the type, which here simply defines the symbols (α and β), is constructed, we can instantiate a parameter variable.

p = SimpleParams(1.0, 2.0)
 Row │ Symbol  Value
     │ Symbol  Float64
─────┼─────────────────
   1 │ α           1.0
   2 │ β           2.0

As you can see, the AIBECS will display p as a table. This is because the show method converts p to a table (a DataFrame to be specific) under the hood:

AIBECS.table(p)

2 rows × 2 columns

SymbolValue
SymbolFloat64
1α1.0
2β2.0

If you do not remember the order in which you created the parameters (α is first, β is second), AIBECS has got your back: keyword arguments are supported.

p = SimpleParams(β = 2.0, α = 1.0)
 Row │ Symbol  Value
     │ Symbol  Float64
─────┼─────────────────
   1 │ α           1.0
   2 │ β           2.0

Unpacking

Probably the most useful feature in AIBECS is the ability to elegantly unpack parameters, thanks to Parameters.jl.

@unpack α, β = p
α, β
(1.0, 2.0)

unpacks the parameters on the left (α and β) from the parameter type p.

Units

One of the main features of parameters in AIBECS is that you can use units and let AIBECS do the conversions for you. Before you use units, though, you must import the @units and units functions from AIBECS. Here is an example.

import AIBECS: @units, units
@units struct UnitfulParams{T} <: AbstractParameters{T}
    α::T | u"m/s"
    β::T | u"d"
end
units (generic function with 37 methods)

Cretaing an instance is just as easy

p = UnitfulParams(1.0, 2.0)
 Row │ Symbol  Value    Unit
     │ Symbol  Float64  FreeUnit…
─────┼────────────────────────────
   1 │ α           1.0  m s⁻¹
   2 │ β           2.0  d

And in this case the parameters are shown with units. You can rely on AIBECS to convert units on the fly.

p = UnitfulParams(3.0u"km/hr", 24.0u"hr")
 Row │ Symbol  Value     Unit
     │ Symbol  Float64   FreeUnit…
─────┼─────────────────────────────
   1 │ α       0.833333  m s⁻¹
   2 │ β       1.0       d

And use keyword arguments

p = UnitfulParams(β = 24.0u"hr", α = 3.0u"km/hr")
 Row │ Symbol  Value     Unit
     │ Symbol  Float64   FreeUnit…
─────┼─────────────────────────────
   1 │ α       0.833333  m s⁻¹
   2 │ β       1.0       d

Unpacking parameters that have units first converts them to SI units.

@unpack β = p
β
86400.0

and β (which is equal to 1 day) here is expressed in seconds after being unpacked.

Initial values

Another useful feature is to set initial (or default) values. Again, you must import the functions for them to work properly

import AIBECS: @initial_value, initial_value
@initial_value struct ParamsWithInitialValue{T} <: AbstractParameters{T}
    α::T | 1.0
    β::T | 2.0
end
initial_value (generic function with 33 methods)

This is handy in many applications.

You can instantiate p with the initial values as, well, its values.

p = ParamsWithInitialValue()
 Row │ Symbol  Value    Initial value
     │ Symbol  Float64  Float64
─────┼────────────────────────────────
   1 │ α           1.0            1.0
   2 │ β           2.0            2.0

You could also just set one parameter to a different value

p = ParamsWithInitialValue(β = 10.0)
 Row │ Symbol  Value    Initial value
     │ Symbol  Float64  Float64
─────┼────────────────────────────────
   1 │ α           1.0            1.0
   2 │ β          10.0            2.0

Combining initial values and units

You can combine both features in parameters.

@initial_value @units struct UnitfulParamsWithInitialValue{T} <: AbstractParameters{T}
    α::T | 1.0 | u"m/s"
    β::T | 2.0 | u"d"
end
initial_value (generic function with 35 methods)

And instantiate p from just one parameter with its unit

p = UnitfulParamsWithInitialValue(β = 1.0u"yr")
 Row │ Symbol  Value    Initial value  Unit
     │ Symbol  Float64  Float64        FreeUnit…
─────┼───────────────────────────────────────────
   1 │ α          1.0             1.0  m s⁻¹
   2 │ β        365.25            2.0  d

Optimizable parameters

import AIBECS: @flattenable, flattenable
@flattenable struct OptimizableParams{T} <: AbstractParameters{T}
    α::T | true
    β::T | false
    γ::T | true
end
flattenable (generic function with 18 methods)

Then the "flattenable" parameters will be the only ones to remain when converting OptimizableParams to a vector

p = OptimizableParams(1.0, 2.0, 3.0)
v = vec(p)
2-element Vector{Float64}:
 1.0
 3.0

The vec function uses the @unpack function in AIBECS, so that units are converted when vectorizing. Here is an example of that by first combining units and flattenable.

@initial_value @units @flattenable struct OptimizableParamsWithUnits{T} <: AbstractParameters{T}
    α::T | 1.0 | u"m/s" | true
    β::T | 2.0 | u"d"   | false
    γ::T | 3.0 | u"km"  | true
end
p = OptimizableParamsWithUnits()
 Row │ Symbol  Value    Initial value  Unit       Optimizable
     │ Symbol  Float64  Float64        FreeUnit…  Bool
─────┼────────────────────────────────────────────────────────
   1 │ α           1.0            1.0  m s⁻¹             true
   2 │ β           2.0            2.0  d                false
   3 │ γ           3.0            3.0  km                true

And then vectorizing the parameters

vec(p)
2-element Vector{Float64}:
    1.0
 3000.0

Note how γ (the third parameter, but the second flattenable one), is converted to meters.

Other features

Coming soon!


This page was generated using Literate.jl.