-
-
Notifications
You must be signed in to change notification settings - Fork 210
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
Handle inhomogeneous parameters using a Tuple of Vectors #2231
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AI-Maintainer Review for PR - Handle inhomogeneous parameters using a Tuple of Vectors
Title and Description ⚠️
Scope of Changes 👍
Testing ⚠️
Code Documentation 👍
Suggested Changes
Please provide a detailed description of the changes made in the pull request. This should include the motivation behind the changes, the approach taken, and any relevant details.
Additionally, please provide details on how the changes were tested. This could include specific test cases used, any additional testing frameworks employed, and the results of these tests.
Thank you for your contribution!
Reviewed with AI Maintainer
We still need to update all the rest of the |
OK sure thing, I'll finish it up. |
I've updated to support If the parameter defaults and map contains...
I'm assuming the other systems |
Still work to do, need to support jacobians, etc... |
@YingboMa I added a observables test at the end of test/split_parameters.jl. I'm struggling to figure out how observables need to be modified to work with the new Tuple parameter type. Can you have a look? |
Will any aspect of this be user facing? If so, some docs would be welcome. I understand that these changes are to some extent brought by the desire to pass input signals
|
It shouldn't necessarily be user-facing, no. The exact type that is used by MTK to hold onto parameters shouldn't matter to a user, since they shouldn't be relying on indexing anyways.
Yes, any interpolation function works, even a custom user one. This change just makes it so you can have any struct as parameters, and you can do anything with the values that you want.
There is no conflation, just unification. In MTK, every simulatable model must be closed, as in all input signals are defined. This functionality gives the user the ability to define components with "strange" parameters, which makes it easier to close models and have them change things around without recompilation.
The fact that they are vectors does not mean they are input signals. Another common use for this would be an array of parameters like
Yes, the documented interfaces of And note that even before this you weren't supposed to rely on parameter ordering, since that could also change. |
This is getting overly complicated and I can see a few ways to easily break it. Let's keep it simple, it's gotten complex because this is not solving the problem at the root cause. So let's get to one rule: trust that the user didn't lie to you. How do we do that? We go by the types of the variables. Recall that Now the one thing that we have to figure out then is what to do about
We have implicitly did (1) since we did not necessarily have a way to handle integer values well before, and so the implementation essentially "accidentally" handled it through promotion. So (1) is there because it was easy, not because it was a well thought out thing that should be staying. I'd argue that it's probably a bad choice for this context and that either (2) or (3) would be better. I would actually prefer (3) to make it explicit: using integers as a parameter value in a model is really a choice and has consequences. For example, if you have an integer valued parameter, then you cannot differentiate with respect to it. These live as structural parameter which are somewhat separate from other parameters: Therefore I think we should do Therefore, we can now trust the user's input, and no rule is required. Use the variable as defined. You can look at the types of the variables and know "I have 5 floats, 2 integers, and 2 arrays of floats" and build the tuple from that. It's safe, free of complications, and predictable. |
I take "users" to include downstream library writers, which might need to know how to call the built functions since they are called in different contexts.
Nice, I need this!
This is correct, but in my world there are lots of things to do with a model that is not simulation. If the type information is kept, such that an input signal is typed as
I understand this requirement and it's always possible to work with, but users are likely to write code that interfaces with external (to MTK) functionality where the order is important. Currently, the onus is on the user to write transformations between MTK and the rest of the world to make sure all variables have the correct order. Examples of this includes any use of linear algebra, e.g., covariance matrices for state estimators etc., numerical scaling for optimizers, external data, C-code etc. Relying on indexing is never a good solution, but the fact remains that sooner or later you have to pick an order to work with, and right now it's easy to make mistakes somewhere in this pipeline. The currently suggested |
I think that covers most of the discussion, but let me add one last piece on the end here. What do we do about "inputs" and "unifying inputs"? Let's really take stalk of where this will let us land. Let's say we have a plant model The unified way to do this is to keep things simple and have only two forms: completed models and uncompleted models. The Now let's talk about the extended functionality. Let's say we want to perform parameter estimation using data from 5 different inputs? Now let's say we want to go ahead and want to drive the system with a bunch of different defined control functions. You can just make a component Finally, to have a single unified and simple input format that everyone could use, functionality that analyzes models with respect to inputs would either just leave the system open and accept We have different tooling today wanting those two forms, and this is thus a direct generalization that is flexible and only requires a minimal change to the MTK codegen in order to correctly (i.e. this PR). |
See if my later post clarifies that. Indeed I think the thing that's missing here is type information on subsystems, which @YingboMa we've talked about a bit before and that shouldn't be hard (?).
With |
It does
This ties in with the concept of "replacing" subsystems, which requires the replacement to implement the same interface, provided that the connection can be made between a system type and the interfaces it implements.
exactly this is needed |
The |
So, just to clarify @ChrisRackauckas idea, if we have the following system... vars = @variables x::Int=1
pars = @parameters A::Vector{Real}=[1.0, 2.0, 3.0]
@named sys = ODESystem(Equation[], t, vars, pars)
prob = ODEProblem(sys) If one tries to do
Is that right? |
@YingboMa That code wasn't supposed to be there, all fixed, last line should now give an error while getting an observable. |
Needs SciML/ModelingToolkitStandardLibrary.jl#211