Arsibalt
Arsibalt

Reputation: 707

Julia: changing mutable struct attribute of choice in function

I am creating a simple stochastic optimisation function in Julia and am using a mutable struct to store the parameter values. Basically, I change a parameter in the mutable struct, pass these parameters through the performance function and update the parameter based on the performance.

I have a version that works when I manually specify which parameters I would like to change. However, I would like to generalise this so I can choose to change any given parameter. For example, denoting the mutable struct of parameters as "args", and I am changing parameter "P", the key section of my current code looks like this:

args.P = P_new
loss_new = performance_function(args)
if loss_new < loss_old # performance better, keep the new value
    loss_old = loss_new
else # performance worse, go back to old value
    args.P = P_old
end

I would like to generalise this into a function:

update_parameter(args,P,performance_function)

so that I can use any set of args, change any parameter P in args, and be able to use an arbitrary performance function. To illustrate if args is defined as being of type Parameter,

mutable struct Parameter
    a::Float64
    b::Float64
end

args = Parameter(1,2)

Then I would like to update a then b using the same function,

update_parameter(args,a,performance_function)
update_parameter(args,b,performance_function)

I can't work out how this can be done. Is there some clever way using dictionaries? Or a better way that satisfies what I want avoiding the direct manipulation of mutable structs altogether? Thanks

Upvotes: 1

Views: 1831

Answers (1)

fredrikekre
fredrikekre

Reputation: 10984

You can use setfield! with the fieldname given as a Symbol:

julia> mutable struct Parameter
           a::Float64
           b::Float64
       end

julia> function update!(parameters::Parameter, name::Symbol)
           setfield!(parameters, name, 5.0)
           return P
       end
update! (generic function with 1 method)

julia> P = Parameter(1, 2)
Parameter(1.0, 2.0)

julia> update!(P, :a)
Parameter(5.0, 2.0)

julia> update!(P, :b)
Parameter(5.0, 5.0)

However, if I understand your use case correctly, it seems that a dictionary would be simpler, since you would not have to change the type definition of your Parameter type if you add more parameters.

Upvotes: 2

Related Questions