[ANN] SymbolicRegression.jl 1.0.0 - Distributed High-Performance Symbolic Regression in Julia

…but it does not give as output the actual equations listen by, say,

In other words, it does not respond with \alpha_1(x), \alpha_2(x), but instead with f(\alpha_1(x), \alpha_2(x)) , whatever the structure of f(\cdot) is.

OK – I understand it, I think.

Yeah this is the interface. If you call

(ex::AbstractExpression)(X::AbstractMatrix)

It should always return a vector, with each element corresponding to a column of X. And similar for string_tree - it will just return a single String.

This is true for Expression, ParametricExpression, TemplateExpression, and ComposableExpression.

The purpose of this uniform interface is so that you can just plug in whatever custom expression type you want, and the search code should be mostly compatible.

But this also means that to get individual pieces of a TemplateExpression you need to do so manually, with get_contents (and sometimes get_metadata, like to extract parameters from ParametricExpression)

1 Like

I just tried this… it seems to work until I try to fit the “machine”: then I get an error message of type NamedTuple has no field structure

Here is my attempt:

const R = 8.314
const F = 9.648e4
const T = 273.15 + 80

u_data = data_oer[:,2]
i_data = data_oer[:,1]

function form_1((; i₀, α₁, α₂), (u,))
    k₁ = α₁(u) * F/R/T * u
    k₂ = α₂(u) * F/R/T * u
    i₀() * (exp(k₁) - exp(-k₂))
end
structure_1 = TemplateStructure{(:i₀,:α₁,:α₂)}(form_1)

model_oer_1 = SRRegressor(
    batching=true,
    niterations=400,
    binary_operators=[+,-,*],
    maxsize=30,
    timeout_in_seconds=60.0 *5, 
    save_to_file=false,    # causes no report file to be written
    expression_type = TemplateExpression,
    expression_options=(;structure_1),
)

mach_1 = machine(model_oer_1, X, i_data)

fit!(mach_1)

which leads to

 Info: Training machine(SRRegressor(defaults = nothing, …), …).
└ @ MLJBase C:\Users\Bernt_Lie\.julia\packages\MLJBase\7nGJF\src\machines.jl:499
┌ Error: Problem fitting the machine machine(SRRegressor(defaults = nothing, …), …). 
└ @ MLJBase C:\Users\Bernt_Lie\.julia\packages\MLJBase\7nGJF\src\machines.jl:694
┌ Info: Running type checks... 
└ @ MLJBase C:\Users\Bernt_Lie\.julia\packages\MLJBase\7nGJF\src\machines.jl:699
┌ Info: Type checks okay. 
└ @ MLJBase C:\Users\Bernt_Lie\.julia\packages\MLJBase\7nGJF\src\machines.jl:703
type NamedTuple has no field structure

Stacktrace:
  [1] getproperty
    @ .\Base.jl:49 [inlined]
  [2] create_expression(t::Node{Float64}, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5}, dataset::Dataset{Float64, Float64, Matrix{Float64}, Vector{Float64}, Nothing, @NamedTuple{}, Nothing, Nothing, Nothing, Nothing}, ::Type{Node}, ::Type{TemplateExpression}, ::Val{false})
    @ SymbolicRegression.TemplateExpressionModule C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\TemplateExpression.jl:236
  [3] create_expression(t::Float64, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5}, dataset::Dataset{Float64, Float64, Matrix{Float64}, Vector{Float64}, Nothing, @NamedTuple{}, Nothing, Nothing, Nothing, Nothing}, ::Type{Node}, ::Type{TemplateExpression}, ::Val{false})
    @ SymbolicRegression.ExpressionBuilderModule C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\ExpressionBuilder.jl:53
  [4] create_expression(t::Float64, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5}, dataset::Dataset{Float64, Float64, Matrix{Float64}, Vector{Float64}, Nothing, @NamedTuple{}, Nothing, Nothing, Nothing, Nothing}, ::Val{false})
    @ SymbolicRegression.ExpressionBuilderModule C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\ExpressionBuilder.jl:23
  [5] create_expression(t::Float64, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5}, dataset::Dataset{Float64, Float64, Matrix{Float64}, Vector{Float64}, Nothing, @NamedTuple{}, Nothing, Nothing, Nothing, Nothing})
    @ SymbolicRegression.ExpressionBuilderModule C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\ExpressionBuilder.jl:23
  [6] update_baseline_loss!(dataset::Dataset{Float64, Float64, Matrix{Float64}, Vector{Float64}, Nothing, @NamedTuple{}, Nothing, Nothing, Nothing, Nothing}, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5})
    @ SymbolicRegression.LossFunctionsModule C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\LossFunctions.jl:248
  [7] _validate_options(datasets::Vector{Dataset{Float64, Float64, Matrix{Float64}, Vector{Float64}, Nothing, @NamedTuple{}, Nothing, Nothing, Nothing, Nothing}}, ropt::SymbolicRegression.SearchUtilsModule.RuntimeOptions{:multithreading, 1, true, Nothing}, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5})
    @ SymbolicRegression C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\SymbolicRegression.jl:561
  [8] _equation_search(datasets::Vector{Dataset{Float64, Float64, Matrix{Float64}, Vector{Float64}, Nothing, @NamedTuple{}, Nothing, Nothing, Nothing, Nothing}}, ropt::SymbolicRegression.SearchUtilsModule.RuntimeOptions{:multithreading, 1, true, Nothing}, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5}, saved_state::Nothing)
    @ SymbolicRegression C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\SymbolicRegression.jl:531
  [9] equation_search(datasets::Vector{Dataset{Float64, Float64, Matrix{Float64}, Vector{Float64}, Nothing, @NamedTuple{}, Nothing, Nothing, Nothing, Nothing}}; options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5}, saved_state::Nothing, runtime_options::Nothing, runtime_options_kws::@Kwargs{niterations::Int64, parallelism::Symbol, numprocs::Nothing, procs::Nothing, addprocs_function::Nothing, heap_size_hint_in_bytes::Nothing, runtests::Bool, return_state::Bool, run_id::Nothing, verbosity::Int64, logger::Nothing, progress::Nothing, v_dim_out::Val{1}})
    @ SymbolicRegression C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\SymbolicRegression.jl:525
 [10] equation_search(X::Matrix{Float64}, y::Matrix{Float64}; niterations::Int64, weights::Nothing, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5}, variable_names::Vector{String}, display_variable_names::Vector{String}, y_variable_names::Nothing, parallelism::Symbol, numprocs::Nothing, procs::Nothing, addprocs_function::Nothing, heap_size_hint_in_bytes::Nothing, runtests::Bool, saved_state::Nothing, return_state::Bool, run_id::Nothing, loss_type::Type{Nothing}, verbosity::Int64, logger::Nothing, progress::Nothing, X_units::Nothing, y_units::Nothing, extra::@NamedTuple{}, v_dim_out::Val{1}, multithreaded::Nothing)
    @ SymbolicRegression C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\SymbolicRegression.jl:476
 [11] equation_search(X::Matrix{Float64}, y::Vector{Float64}; kw::@Kwargs{niterations::Int64, weights::Nothing, variable_names::Vector{String}, display_variable_names::Vector{String}, options::Options{SymbolicRegression.CoreModule.OptionsStructModule.ComplexityMapping{Int64, Int64}, DynamicExpressions.OperatorEnumModule.OperatorEnum{Tuple{typeof(+), typeof(-), typeof(*)}, Tuple{}}, Node, TemplateExpression, @NamedTuple{structure_1::TemplateStructure{(:i₀, :α₁, :α₂), typeof(form_1), @NamedTuple{i₀::Int64, α₁::Int64, α₂::Int64}}}, MutationWeights, false, false, nothing, Nothing, 5}, parallelism::Symbol, numprocs::Nothing, procs::Nothing, addprocs_function::Nothing, heap_size_hint_in_bytes::Nothing, runtests::Bool, saved_state::Nothing, return_state::Bool, run_id::Nothing, loss_type::DataType, X_units::Nothing, y_units::Nothing, verbosity::Int64, extra::@NamedTuple{}, logger::Nothing, v_dim_out::Val{1}})
    @ SymbolicRegression C:\Users\Bernt_Lie\.julia\packages\SymbolicRegression\44X04\src\SymbolicRegression.jl:499
...
    @ C:\Users\Bernt_Lie\.julia\packages\MLJBase\7nGJF\src\machines.jl:789 [inlined]
 [19] fit!(mach::MLJBase.Machine{SRRegressor{DynamicQuantities.SymbolicDimensions{DynamicQuantities.FixedRational{Int32, 25200}}, DataType}, SRRegressor{DynamicQuantities.SymbolicDimensions{DynamicQuantities.FixedRational{Int32, 25200}}, DataType}, true})
    @ MLJBase C:\Users\Bernt_Lie\.julia\packages\MLJBase\7nGJF\src\machines.jl:786
 [20] top-level scope
    @ c:\Users\Bernt_Lie\OneDrive\Documents\booksBLSOL\ModDynSyst\Project\Project_2024\Code\jl_notebook_cell_df34fa98e69747e1a8f8a730347b8e2f_Y354sZmlsZQ==.jl:1

Ah… the problem disappears if I change the name of structure_1 to structure. But isn’t this just a name??

In Julia, the syntax (; structure) is shorthand for (; structure=structure). So you would have to do (; structure=structure_1) in your case

julia> a = 1;

julia> (; a)
(a = 1,)

julia> (; b=a)
(b = 1,)
3 Likes