Open zsunberg opened 1 year ago
Or, perhaps, having both GeneratedModel
and ModelParameters
is a bit redundant.
Instead, you could just have a single PRONTO.SymbolicModel{ID}
type that can be dispatched on. The constructor would do all the work currently done by generate_model
, so, if the user just wants to give a dynamics function without any explicitly-defined parameters, usage would look something like
model = PRONTO.SymbolicModel((4, 1), dynamics, stagecost, termcost, regQ, regR)
Or, if the user wanted their own parameters type, they could still do
@kwdef struct Spin2 <: FieldVector{3, Float64}
kl::Float64 # stage cost gain
kr::Float64 # regulator r gain
kq::Float64 # regulator q gain
end
model = PRONTO.SymbolicModel((4, 1), dynamics, stagecost, termcost, regQ, regR, params=Spin2(0.01, 1.0, 1.0))
SymbolicModel
could either be immutable and users could create a new model if they wanted to change the params, or you could provide setparams!(model, params)
.
(I think this is a much better idea than what I described above)
EDIT: See comment below - I think it is a much better idea.
Currentlygenerate_model
works by adding new methods for functions in the PRONTO module that dispatch on the current user-definedModel
type. This is somewhat implicit (explicit is better) and modifies the global state of the program and the user doesn't have anything concrete to "hold on to" that represents all the new code that has been created.One alternative would be to return an object fromgenerate_model
. (Of course there might be better names for all of this, and I have renamed the currentPRONTO.Model
toModelParameters
).~~struct GeneratedModel{ID, P<:ModelParameters} params::P
other data and options could also go here
end~~
The ID parameter could be aUUID
, or anInt
, or there could be an option for the user to name it something they like, or it could be aSymbol
starting with the name of the function and some random characters.Then, the built functions could dispatch on this object, i.e. the generated method would have the signaturePRONTO.lxx(m::GeneratedModel{UUID("dc5e5d6a-fcac-11ed-152d-8b59e1851479")}, x, u, t)
or justPRONTO.lxx(m::GeneratedModel{1}, x, u, t)
This gives the user an object that they can use in the solver, get information from, etc. It also might allow for more flexibility and options in the future. E.g. there could be an option to use symbolic differentiation or autodiff, and you could compare the results with twoGeneratedModel
s created with the sameModelParameters
and dynamics function.Other options would be to include the built functions as members ofGeneratedModel
, but this would result in a lot of type parameters inGeneratedModel
.