-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
Fix incorrect handling of periodic Piecewise functions in definite integrals #27396
base: master
Are you sure you want to change the base?
Conversation
…ntegrals Previously, the code incorrectly handled periodic functions like abs(cos(x)) when integration limits extended outside the interval [0, T] (where T is the period). The issue was caused by splitting piecewise functions only within the domain [0, T]. As a result, for limits outside this range, the integral evaluation returned incorrect results. This commit fixes the issue by transforming the integration limits to (0, b) using the transform function. The integration is then computed correctly using the formula: ∫(0 to b+nT) f(x) dx = ∫(0 to b) f(x) dx + n ∫(0 to T) f(x) dx. **Key changes:** - Added logic to detect periodicity using the `periodicity()` function. - Transformed the integration limits for periodic functions to the range (0, b) to align with the formula. - Properly handled integration direction and combined results for periodic segments and the remaining interval. **Example:** For abs(cos(x)), previously ∫(-π/2 to 0) abs(cos(x)) dx returned an incorrect value. With this fix, the integral is now calculated accurately.
✅ Hi, I am the SymPy bot. I'm here to help you write a release notes entry. Please read the guide on how to write release notes. Your release notes are in good order. Here is what the release notes will look like:
This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.14. Click here to see the pull request description that was parsed.
|
evalued = Add(*others)._eval_interval(x, a, b) | ||
evalued_pw = piecewise_fold(Add(*piecewises))._eval_interval(x, a, b) | ||
function = uneval + evalued + evalued_pw | ||
# Handles periodic functions by adjusting | ||
# integration limits and splitting the interval | ||
# into periodic segments and a remainder. Evaluates | ||
# the integral over one period and the | ||
# remainder, combining these results with proper | ||
# handling of integration direction. | ||
period = None | ||
if not isinstance(self.function, Poly) and x.kind is NumberKind: | ||
period = periodicity(self.function, x) |
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.
I don't think that calling periodicity here is the right fix. I think that the bug is in _eval_interval
and should be fixed there in the first instance rather than adding additional code here to work around it.
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.
the actual issue may be here:
# In the file `solvers/inequalities.py`, lines 509-511
if sup - inf is S.Infinity:
domain = Interval(0, period, False, True).intersect(_domain)
_domain = domain
As mentioned in the above code, the piecewise function is splitting only in (0 , period) which is causing incorrect value for the inegrals whose limits are outside (0,period) so i am using this formula ∫(0 to b+nT) f(x) dx = ∫(0 to b) f(x) dx + n ∫(0 to T) f(x) dx to calucalate the integral in the limits (0,period) so that the above splitting won't cause any issue. so here i need to change the code in doit function as i need to transform the function such that limits are changed to (0,b).
I believe that this may fix issue #27185. |
I don't think that this is the right fix because this is adding more code on top but there is no clear sign of where is the code that actually results in buggy output. Somewhere the wrong function is being called that produces the wrong result. A fix here should identify where that is and should then make sure that the wrong function is either fixed or is not being called. I am not interesting in trying to fix this by adding more code on top without identifying where the actual problem is. |
the bug is here which is a part of _eval_interval() : sympy/sympy/functions/elementary/piecewise.py Line 402 in b7e7de3
the output of self.interval(x) gives back the function which is split in (0,period) intervel only, but the real problem comes when the limits are outside this function which is not handled in _eval_interval() function. sympy/sympy/functions/elementary/piecewise.py Lines 407 to 422 in b7e7de3
In the above code the limits are compared with the interval of (0,period) using _clip() which causes issue when limits are outside the (0,period) interval. for example : In [2]: integrate(Abs(cos(x)),(x,0,5*pi))
Out[2]: 4 The correct ans is 10 but we got incorrect answer 4 because the output of
so I thought to tranform the function and use this formula ∫(0 to b+nT) f(x) dx = ∫(0 to b) f(x) dx + n ∫(0 to T) f(x) dx so that by just splitting the function correctly in (0,period) we get the correct result, so that we don't need to change anything in eval_interval() function. @oscarbenjamin If the above solution is not ideal, could you please suggest alternative approach to address this issue? |
The first thing needed is to prevent the Somewhere it is using some function that does not handle periodicity properly and either |
the _intervels() function is somehow calling solve_univariate_inequality() function and in that function it is given that for trignometric equations the inequality are restricted in its periodic interval as mentioned below. this causes issue when the limits are outside the periodic interval. sympy/sympy/solvers/inequalities.py Lines 411 to 413 in d60d9fe
So if we want to change _intervals function we need to somehow make a fix such that solve_univariate_inequality() function works properly for the interval consisting of limits instead of periodic interval but this degrades the performance for larger limits like (0,50pi) which can be easily computed using 50*(ans in the limits(0,pi)) if pi is the period using the formula. |
Exactly so this is a bug: In [1]: solve_univariate_inequality(cos(x) < 0, x)
Out[1]:
π 3⋅π
─ < x ∧ x < ───
2 2 Either that needs to be fixed or |
|
I don't think that there is. Something could be added though or
This formula is what |
I think it is better if i change the code in |
That seems reasonable.
If that means that it will continue to return incorrect results then no: either integrate should not use It is important here not to just put more code on top of bad code. The bad code should be fixed or removed or not used any more. The bug needs to be fixed first and then we can add non-buggy code that makes it possible to handle things that were previously handled by the buggy code. I am not interested in adding code in one place that tries to cancel a bug in another place while still leaving the bug there. The buggy code needs to be fixed so that each function only returns mathematically correct results. Putting new code on top of bad code without fixing the bugs makes everything more and more of a mess over time. It is not possible to predict what intervals will be handled correctly by |
i mean ._interval would continue to split only for periodic interval but it would give correct ans for the definite integrations whose limits are outside the periodic intervals as the formula above just needs a correct split in periodic intervals.
I agree that the buggy code should be fixed here first but here the
No, @oscarbenjamin can you tell me what were you expecting as the output of self._intervals is it to split the function correctly in the entire interval of limits correctly ? but to do this we need to change the arguments of the function to include the limits for intervals is it okay to change the arguments of ._interval function. |
Unless it is fixed so that it never returns incorrect results then it should not be used.
There isn't a way to represent that. Since
Yes. I would probably remove the I don't have confidence that either |
It could also raise an exception like NotImplementedError. It is documented that |
Then i will start creating a function in |
I think that the
The |
References to other Issues or PRs
Fixes #27379
Brief description of what is fixed or changed
Previously, the code incorrectly handled periodic functions like abs(cos(x)) when integration limits extended outside the interval
[0, T] (where T is the period). The issue was caused by splitting piecewise functions only within the domain [0, T]. As a result,
for limits outside this range, the integral evaluation returned incorrect results.
This commit fixes the issue by transforming the integration limits to (0, b) using the transform function.
The integration is then computed correctly using the formula:
∫(0 to b+nT) f(x) dx = ∫(0 to b) f(x) dx + n ∫(0 to T) f(x) dx.
Key changes:
periodicity()
function.Other comments
Release Notes