Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making parameters @parameters #50

Closed
baggepinnen opened this issue May 10, 2022 · 8 comments
Closed

Making parameters @parameters #50

baggepinnen opened this issue May 10, 2022 · 8 comments

Comments

@baggepinnen
Copy link
Contributor

It would be nice if we could figure out a way to have the parameters of components be @parameters rather than hard-coded. Take this PID controller as an example

julia> pid
Model pid with 40 equations
States (42):
  reference₊u(t) [defaults to 0.0]
  measurement₊u(t) [defaults to 0.0]
  ctr_output₊u(t) [defaults to 0.0]
  addP₊input1₊u(t) [defaults to 0.0]
  addP₊input2₊u(t) [defaults to 0.0]
  addP₊output₊u(t) [defaults to 0.0]
  gainPID₊u(t) [defaults to 0.0]
  gainPID₊y(t) [defaults to 0.0]
  gainPID₊input₊u(t) [defaults to 0.0]
  gainPID₊output₊u(t) [defaults to 0.0]
  addPID₊input1₊u(t) [defaults to 0.0]

Parameters (19):
  addP₊k1 [defaults to 1]
  addP₊k2 [defaults to -1]
  gainPID₊k [defaults to 400]
  addPID₊k1 [defaults to 1]
  addPID₊k2 [defaults to 1]
  addPID₊k3 [defaults to 1]
  limiter₊y_max [defaults to 350]
  limiter₊y_min [defaults to -350]
  addSat₊k1 [defaults to 1]
  addSat₊k2 [defaults to -1]
  gainTrack₊k [defaults to 0.00176777]

where are k, Ti, Td that the user provided? They are likely in there somewhere, but not under their original names. I tried this a while back but ran into problems and made a comment
https://github.com/baggepinnen/ModelingToolkitStandardLibrary.jl/blob/281ee9715512bbeacd054240f4fb56165f9b1b98/src/Blocks/continuous.jl#L157

When models get more complicated, it would be good to

  1. Keep names of parameters similar to the arguments the user provide, in the PID case, k, Ti, Td
  2. make sure they appear once and only once in the parameter list, i.e., not several times. In the current PID implementation, Ti=3 leads to int₊k => 0.333333 being the parameter, while the input argument k influences multiple different parameters in the resulting system.

What I have in mind is workflows like parameter tuning etc. where the user must be able to specify which parameters to tune. It's going to be rather hard to figure out how to tune the PID controller if the PID parameters do not appear (directly) in the system equations.

@ValentinKaisermayer
Copy link
Contributor

Have you tested simply adding k, Ti, Td as @parameters to:

function LimPID(; name, k=1, Ti=false, Td=false, wp=1, wd=1,

They will end up as default values in other blocks, but that should not be a problem anymore:
https://github.com/SciML/ModelingToolkit.jl/blob/master/test/symbolic_parameters.jl

@baggepinnen
Copy link
Contributor Author

Ah cool, I didn't know that was fixed, thanks for pointing that out! Then we have one less problem to worry about. It currently appears to work for some parameters but not for others

julia> @parameters k=2 Ti=3 Td=4;

julia> @named pid = LimPID(; k) # works

julia> @named pid = LimPID(; k, Ti, Td)
ERROR: TypeError: non-boolean (Num) used in boolean context
Stacktrace:
 [1] top-level scope
   @ REPL[9]:1

It does not work for the time constants due to the argument checking

!isequal(Ti, false) && (Ti  0 || throw(ArgumentError("Ti out of bounds, got $(Ti) but expected Ti ≥ 0")))

I'm wondering if argument checking can be handled slightly differently. Either we can introduce some convenience functionality like a macro that only checks numerical values and leaves @parameters alone. Or we could somehow make use of the metadata system

julia> @parameters Ti [bounds=(0, Inf)]
1-element Vector{Num}:
 Ti

julia> getbounds(Ti)
(0, Inf)

and check parameter values once the final numerical values have been provided before the call to solve.

I would eventually like to add this kind of metadata everywhere it makes sense, it would make it really smooth when optimizing over parameters if trivial bounds like (0, Inf) were already in place by default. Not sure if it's the right tool for this kind of argument checking though. Suggestions welcome :)

@ValentinKaisermayer
Copy link
Contributor

For normal stuff (e.g. parameter must be positive,...) it might be easy to use such a system. But in this specific case the parameter is "misused" as an option as well. Ti can be a numeric value or a bool. I'm not sure that MTK can handle this and maybe it should not and this is simply a bad way to do it.

But it would be nice to use the parameter bounds and simply let MTK do the check if the provided default values is ok.

@ValentinKaisermayer
Copy link
Contributor

How could a relational check be done? e.g.
a <= b
where a and b are @parameters?

@baggepinnen
Copy link
Contributor Author

The following already works, so maybe a function that checks parameters before solving could evaluate any symbolic expressions appearing in the bounds using the numerical values provided in the varmap.

julia> @parameters T [bounds = (0, Inf)]
1-element Vector{Num}:
 T

julia> @parameters k [bounds = (0, T^2+1)]
1-element Vector{Num}:
 k

julia> getbounds(k)
(0, 1 + T^2)

@ValentinKaisermayer
Copy link
Contributor

You mean somewhere like here ?

@baggepinnen
Copy link
Contributor Author

Exactly, the check could probably be performed as soon as numerical values are known for all parameters?

@jaakkor2
Copy link
Contributor

jaakkor2 commented Oct 7, 2022

Similar problem with Limiter

using ModelingToolkit
using ModelingToolkitStandardLibrary.Blocks: Limiter
@parameters y1=1 y2=2
Limiter(name=:foo, y_min=y1, y_max=y2)

giving

ERROR: TypeError: non-boolean (Num) used in boolean context
Stacktrace:
 [1] Limiter(; name::Symbol, y_max::Num, y_min::Num)
   @ ModelingToolkitStandardLibrary.Blocks C:\Users\jaakkor2\.julia\packages\ModelingToolkitStandardLibrary\iRfHC\src\Blocks\nonlinear.jl:18
 [2] top-level scope
   @ REPL[13]:1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants