Symbolic indefinite integral of piecewise function gives wrong results

I encountered this somewhat strange behaviour, where I seem to get an erroneous result.
Consider the piecewise function defined by:
x=sym('x');
f=piecewise(abs(x)<0.5,1,0);
which is a simple rectangular pulse.
Attempting to calculate the indefinite integral,
F=int(f);
and plotting it gives this result:
which obviously is not a correct antiderivative of the given function.
I also tried to calculate a definite integral with a variable in the limit, with mixed results:
F=int(f,-Inf,x)
seems to work and gives the expected result:
However trying it with 0 as the lower limit gives a wrong result again:
F=int(f,0,x);
Is this a bug in Matlab, or somehow a mistake on my side?

2 Comments

I just spent 20 minutes typing up a very nicely detailed answer, then my computer arbitrarily refreshed the page and I lost it all. I'm not particularly motivated to start over, but in short:
I think you're confusing yourself (and the anti-derivatives) by using x as an integration bound.
I disagree with that hypothesis. I just tested substituting the x in the bound with another symbolic variabel that does not coincide with the integration variable. The result is still the same.

Sign in to comment.

Answers (3)

I disagree that the second attached image "obviously is not a correct antiderivative of the given function." If you take its derivative (simply look at the slope of the line), you get 0 outside x = +/- 1/2, and 1 inside. That smells like a proper answer to me.
As for your "definite integrals," I'm not entirely sure what's going on. But, if you manually integrate a few discrete values, it gives a proper area-under-the-curve (from what I can tell).
area_curve = []; % I NEVER recommend growing loops this way...
for ival = -2:.05:2
area_curve(end+1,1) = int(f,x,[0,ival]);
end
figure;
plot(area_curve);

5 Comments

As near as I can tell after further investigation, the pseudo-definite integral is not correctly enforcing the x = 0 when x < -.5 portion of the piecewise definition. I would be concerned enough to submit a support ticket - maybe MathWorks tech support will know something we don't.
While it is true, that the derivative is the original function almost everywhere, this does not mean that the result is a correct antiderivative. In general, an antiderivative function is always continuous (except when dealing with things like dirac "functions").
If you were trying to determine the area under the original curve between 0.4 and 0.6, you would get a negative result if you go by the result above. So, I still do not think that it is a correct answer.
I just reminded myself of the fundamental theorem of calculus, which starts with the basic assumption that your function is continuous. You've explicitly defined your function as piece wise, with discontinuities at +/- .5, therefore it is not suitable for integration.
However, if my calculus memory serves, you can split it into 3 continuous functions for integration. Since your function is zero everywhere outside .5, you can ignore those 2 functions. Now, you're left with f = 1 for all -.5 < x < .5, so all you have to do is limit your integration bounds to that window.
If you truly want to integrate from -2 to +2, do 3 separate integrations as I said above, and add the 3 results. Which gives you 0 + int(f,x,[-.5,.5]) + 0. But again, just ignore the f = 0 pieces from the beginning as they don't contribute.
The function, yes. The antiderivative however should not include discontinuities.
Is there a better answer, yes. Does that make your answer wrong? Maybe not.

Sign in to comment.

syms x a b
f = piecewise(abs(x)<0.5,1,0);
F = int(f, a, b);
FF = subs(F, a, 0);
fplot(FF, [0 2])

3 Comments

The result of that code is this plot:
Which still does not seem like a correct answer, and also has an undefined interval between -0.5 and 0.
Also, I’m not so much interested in obtaining the answer to this particular problem. Rather I’m interested in understanding which circumstances cause the integration to go wrong like this.
The plot is intended for the case where the lower bound, a, is set to 0, corresponding to your
F=int(f,0,x);
Remember if you were to try to plot that below 0 then you would be plotting with a lower bound larger than the upper bound, and the definition for that would involve negatives.
The basic plot is the case
FF = subs(F, a, -2);
fplot(FF, [-2 2])
After rechecking the documentation, I noticed that the documentation for "int" says:
"If one or both integration bounds a and b are not numeric, int assumes that a <= b unless you explicitly specify otherwise.",
so the plot I get for int(f,0,x) is actually conforming to what the documentation says. However, I still do not understand why the indefinite integral without the given limits gives the wrong answer.

Sign in to comment.

Personally, I'd suggest trying to define a piecewise function using abs is a dangerous thing, something that will only get you into trouble. I would suggest a more direct approach, one that will be far more readable, and so safer for all concerned. Thus...
syms x
f = piecewise(x<-0.5,0,x >= -0.5 & x < 0.5,1,x >= .5,0)
f =
piecewise(x < -1/2, 0, x in Dom::Interval([-1/2], 1/2), 1, 1/2 <= x, 0)
Which as you see, MATLAB translates into a simple expression, where it recognizes the explicit domains each segment lives on.
MATLAB has no trouble with a definite integral here, a matter of no dispute.
int(f,[-2,-.4])
ans =
1/10
But what happens when you just use int, in an indefinite form?
g = int(f)
g =
piecewise(x < -1/2, 0, x in Dom::Interval([-1/2], 1/2), x, 1/2 <= x, 0)
So each segment of the integral is correct, on its own, except that MATLAB does not introduce a constant of integration. That is consistent with how MATLAB works. It never writes in that blasted constant as we were taught to do in beginning calc. Thus, the integral of each term is...
int(0) = C1
int(1) = x + C2
But since this is a piecewise function, MATLAB integrates each piece separately, as we see in g, but again, we don't see those blasted constants. Now, what happens when we try to turn that indefinite integral into a definite one? Again, we learned in early calc to do so simply, substituting the limits of integration in, and subtracting the results.
subs(g,-.4) - subs(g,-2)
ans =
-2/5
So why does this fail? Because MATLAB forgot that those constants of integration were actually important. In fact, the piecewise integral should arguably have been:
g = piecewise(x < -1/2, 0, x in Dom::Interval([-1/2], 1/2), x + 1/2, 1/2 <= x, 1)
The difference is purely in the constants of integration, so easily ignored and so easily forgotten. Each constant of integration in an interval should be adjusted based on the constant from the prior segment, and the integral of the function over the prior segment.
Is this a bug? Perhaps. At least, it is a significant feature. ;-) You say potato, others say worm ridden tuber.
Now, lets go back to my initial comment, that use of piecewise properly is a far better thing to do. As you should see, there are two segments in this expression where f was constant, at 0. A proper definition of this integral as a piecewise function will have a DIFFERENT constant of integration in each interval, in order that the integral be well defined. So we would properly have g defined as:
g(x) = { C1 where x < -0.5
x+C2 where -.5 <= x < .5
C3 where x >= 0.5}
(I've used an easier to read form to write g here, although not valid MATLAB syntax.) This applies for unknown constants C1,C2,C3. A careful choice of constants to make the above expression consistent and continuous would now yield this well-posed indefinite integral expression
g(x) = { 0 where x < -0.5
x+.5 where -.5 <= x < .5
1 where x >= 0.5}
As you can see, we needed to have different constants of integration in the two distinct sub-intervals where f(x) was zero.
However, when you tried to get tricky, you created a function with only TWO explicit intervals, depending on where abs(x) lives. The problem is that constant of integration needs to change, depending on where x actually lives.
So, as I said, even if we ignore the issue that MATLAB's int command seems to have a problem for piecewise functions, by defining the function in a tricky way, int will never be able to get the answer right. At the very least, you are asking for trouble.

Products

Release

R2018a

Asked:

on 28 Aug 2018

Edited:

on 3 Dec 2018

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!