-
-
Notifications
You must be signed in to change notification settings - Fork 53
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
Incorrect instantiation order with nested dependency injection #632
Comments
Thank you for reporting! I will look at it. |
Any updates on this issue? I have run into it multiple times by now. Let me know if I can help to fix it. |
I did have a look at this. I noticed that when adding links an directed acyclic graph (DAG) is used to check that the links make sense. But during instantiation a DAG is not used to determine the order. Adding the DAG to the instantiation is a complex task. I haven't had time to work on it. If you want to help, you could take a look at the code and maybe describe here a potential proposal on how to implement it. But as I said, it is not simple. I do wonder why only you have reported this problem. It is quite an obvious bug, but it seems in practice it doesn't happen often. |
Thanks for the quick response. Correct me if I am wrong, but the topological sort of the constructed DAG is used to determine the instantiation order of components in In my example, the call to Based on the action-link-order, the components are reordered to Following this order, the Before the class itself is instantiated, At this point inside In general, this looks like:
If I understand this quite complex logic correctly, there are at least three rules we have to consider:
The last rule is the critical in our case, which is not enforced by any mechanism. Looking at the logic described above, we need to make sure that the sources of action-links to stateDiagram-v2
nested_param --> root.strategy.init_args.nested
root.strategy.init_args.nested --> root.strategy
param --> root.strategy
Instead of the one posted above. I hope you made it this far and this rather long description makes some sense :) |
Oh, you are right. Not sure why I had this in mind. I must have gotten confused with something else. I will take another look. |
I created pull request #662 with hopefully the fix. Please review and test. The code snippet above had some issues so I had to change it a bit. See the test https://github.com/omni-us/jsonargparse/pull/662/files#diff-911b02ee18fa5c88fe775f9d0de98b387b537757ec95af835f485649ed3a86f7 |
Awesome, that fixes my issue 👍. Sorry for the malformed example ^^ |
Thank you for the great analysis! Certainly made fixing it way easier. |
🐛 Bug report
First of all, this is a really cool project, and I am enjoying it a lot 👍 .
This might be quite niche to be honest, but I encountered unexpected behavior when working on nested classes.
In my use case, the user can choose from multiple loss classes (
Strategy
in the example), which on their own have another nested dependency injection (NestedStrategy
).Furthermore, some arguments of the loss are linked to (
StrategyParameter
) and the nested strategy has also arguments provided from somewhere else (NestedParameter
).Now in this setting I found that the instantiation order induced by the topological sort of the dependency graph does not enforce that
NestedParameter
is instantiated beforeStrategy
.But when instantiating the
Strategy
object, all actions which target the nested strategy are triggered too.So in particular the link
is triggered however before
NestedStrategy
was instantiated and so the compute_fn is called with theNamespace
object.I am not sure whether the graph should contain the dependency or the instantiation logic should not instantiate the actions leading to the nested class?
In
ActionLink.apply_instantiation_links
there is this predicateis_nested_instantiation_link
(returning False) which hints at the second case being true?This is how the dependency graph looks like as constructed in
ActionLink.instantiation_order
:To reproduce
I tried to keep the example as small as possible.
We have two dependency injected classes
Strategy
andNestedStrategy
and two objects which are used for linkingStrategyParameter
andNestedParameter
.Output
Expected behavior
The
NestedParameter
class is instantiated before passed as parameter to thecompute_fn
.Note, the
compute_fn
is only to showcase the problem but not necessary to reproduce the bug.Environment
The text was updated successfully, but these errors were encountered: