-
Notifications
You must be signed in to change notification settings - Fork 156
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
add flag for activating robust calculation of expand_derivatives #1353
Conversation
Codecov ReportAttention: Patch coverage is
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## master #1353 +/- ##
===========================================
+ Coverage 3.98% 79.01% +75.03%
===========================================
Files 50 51 +1
Lines 4771 4880 +109
===========================================
+ Hits 190 3856 +3666
+ Misses 4581 1024 -3557 ☔ View full report in Codecov by Sentry. |
Why is a recalculation of occursin required? That seems like a bug that should just be addressed directly. |
It definitely is a bug, but no one was able to fix it until now, maybe because of #1126 (comment). I spent two nights trying to pin down the problem, but not being able to print intermediate values without affecting the process itself makes this really tedious/complicated. I decided implementing this workaround is much simpler and I think necessary, until some hero hunts this one down. I think the Problem is, that there actually are cases where recalculation is necessary because the expression tree can change between the creation of Line 189 in 8c518c2
Line 257 in 8c518c2
Line 186 in 8c518c2
After that point, |
Have you tried debugging/reproducing this by using the sorted arguments instead of unsorted? |
I think the occursin tree code can just be removed, but that changes the time complexity of this function... If you want to find more cases, I'd look into running more tests using fuzz.jl and fuzzlib.jl right now I believe it just runs simplify tests.. |
I agree that trying to debug the issue would be the best solution. But I don't know when somebody will do that and until then I would like to have a working way to calculate my derivatives, which currently is not possible. |
I did a take on actually solving the problem. I think the Problem is that subtrees of a differential are themself expanded multiple times, once before the differential is executed and then another time to execute the chain rule for the differential on the subtrees. I removed the second expansion by moving the actual execution of a differential to a separate function This fixes the test cases and the results with and without the robust flag agree. There are still two calls to |
I removed the robust flag and cleaned up the code. |
@shashi can you review? |
Hello. I am not fully following the discussion here. Issue #1262 has made Julia Symbolics unusable for me. If there exists a "temporary" workaround so that expand_derivatives function works properly, I would appreciate that getting into prod. I spent a while trying to debug this issue, and it seems like others have, and the bug has been outstanding for months or possibly years. Thanks. |
I'm not sure why it's a given this is actually a fix or a workaround. This kind of change has some other implications and adds a lot of other complications. It fixes one case but this kind of recomputation complexity very easily hides much harder to debug issues and the exponential complexity can be considered a bug itself. So if someone really wants a fix now they should look into fixing the real bug. Shortcuts to solve one issue at the expense of many others will lead to much pain down the line. If @shashi thinks it's safe I'd merge but it is definitely risky |
For clarification, in the current state of this PR there is no recalculation happening anymore. The complexity of expanding derivatives with this PR should be the same or lower than without this PR. I used this PR for my working code during the last weeks. I hadn't any issues with wrong derivatives or trying to access an outdated However, I did encounter some stack overflows when expanding derivatives that involved complex symbolics. I hadn't the time to test if they also occur without this PR nor had a deeper look at the cause. But if they are caused by this PR my guess would be an infinite loop in Lines 196 to 211 in 3bf685a
And I have to admit that I neither understand those lines nor handling of complex numbers very well yet. |
So, in terms of risk, IMHO the expand_derivatives() function is currently broken to the point where it should probably be disabled. (there are like 4 or 5 issues about it, granted 2 are mine). I've had to replace symbolic differentiation with taylor-based AD in a package because of that. For reference the issues are #1369 #1281 #1262 #1126 #634 (the last from Jun2022) . Based on my attempt to debug this, I believe but I am not certain that the whole problem comes from "occurences" or "occursin" which is an optimization. If it is possible to just remove that optimization and get a version of expand_derivatives which passes all existing tests and resolves the issues referenced it seems like a clear win. I see above that this PR is failing some tests; I don't know how much they matter. I apologize in advance if I'm misunderstanding the issue, Julia is not my main language. Thanks for looking in any case. |
Can you do this test and add those to the test set? That would be a big factor here. |
I had missed this change, the code does look a lot more reasonable now. I think if you test the part with the stack overflows that would be helpful, but I don't see why this change would cause an infinite recursion where the other had not. In fact, |
a119204
into
JuliaSymbolics:master
This provides a workaround for issues #1126 and #1262 by adding a flag
robust
that if set, forces expand_derivatives to always recalculateoccurrences
.It also adds tests that check if the examples from the issues are actually solved. These tests also show that
expand_derivatives
can return a wrong result without throwing any error. Line 372 to 375 intests/diff.jl
:I set the robust flag to false per default but since the result of the non-robust version is not reliable it should be considered if setting it to true should be the default.