Parameters guide

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 30 methods)

Cretaing an instance is just as easy

p = UnitfulParams(1.0, 2.0)

│ Row │ Symbol │ Value   │ Unit     │
│     │ Symbol │ Float64 │ Unitful… │
├─────┼────────┼─────────┼──────────┤
│ 1   │ α      │ 1.0     │ m s^-1   │
│ 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  │ Unitful… │
├─────┼────────┼──────────┼──────────┤
│ 1   │ α      │ 0.833333 │ m s^-1   │
│ 2   │ β      │ 1.0      │ d        │

And use keyword arguments

p = UnitfulParams(β = 24.0u"hr", α = 3.0u"km/hr")

│ Row │ Symbol │ Value    │ Unit     │
│     │ Symbol │ Float64  │ Unitful… │
├─────┼────────┼──────────┼──────────┤
│ 1   │ α      │ 0.833333 │ m s^-1   │
│ 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 26 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.

@units @initial_value struct UnitfulParamsWithInitialValue{T} <: AbstractParameters{T}
    α::T | 1.0 | u"m/s"
    β::T | 2.0 | u"d"
end
units (generic function with 32 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       │ Unitful… │
├─────┼────────┼─────────┼───────────────┼──────────┤
│ 1   │ α      │ 1.0     │ 1.0           │ m s^-1   │
│ 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 Array{Float64,1}:
 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.

@flattenable @units @initial_value 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       │ Unitful… │ Bool        │
├─────┼────────┼─────────┼───────────────┼──────────┼─────────────┤
│ 1   │ α      │ 1.0     │ 1.0           │ m s^-1   │ 1           │
│ 2   │ β      │ 2.0     │ 2.0           │ d        │ 0           │
│ 3   │ γ      │ 3.0     │ 3.0           │ km       │ 1           │

And then vectorizing the parameters

vec(p)
2-element Array{Float64,1}:
    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.