5

I'm trying to integrate a piecewise function using Sagemath, and finding it to be impossible. My original code is below, but it's wrong due to accidental evaluation described here.

def f(x):
    if(x < 0):
        return 3 * x + 3
    else:
        return -3 * x + 3

g(x) = integrate(f(t), t, 0, x)

The fix for plotting mentioned on the website is to use f instead of f(t), but this is apparently unsupported for the integrate() function since a TypeError is raised.

Is there a fix for this that I'm unaware of?

2 Answers2

3

Instead of defining a piecewise function via def, use the built-in piecewise class:

f = Piecewise([[(-infinity, 0), 3*x+3],[(0, infinity), -3*x+3]]) 
f.integral()

Output:

Piecewise defined function with 2 parts, [[(-Infinity, 0), x |--> 3/2*x^2 + 3*x], [(0, +Infinity), x |--> -3/2*x^2 + 3*x]]

The piecewise functions have their own methods, such as .plot(). Plotting does not support infinite intervals, though. A plot can be obtained with finite intervals

f = Piecewise([[(-5, 0), 3*x+3],[(0, 5), -3*x+3]]) 
g = f.integral()
g.plot()

But you also want to subtract g(0) from g. This is not as straightforward as g-g(0), but not too bad, either: get the list of pieces with g.list(), subtract g(0) from each function, then recombine.

g0 = Piecewise([(piece[0], piece[1] - g(0)) for piece in g.list()])
g0.plot()

And there you have it:

plot

By extending this approach, we don't even need to put finite intervals in f from the beginning. The following plots g - g(0) on a given interval [a,b], by modifying the domain:

a = -2
b = 3
g0 = Piecewise([((max(piece[0][0], a), min(piece[0][1], b)), piece[1] - g(0)) for piece in g.list()])
g.plot()

plotrange

  • I've looked into the Piecewise class, and it honestly seems to be next to useless. It doesn't extend the functionality of expressions, so I can't do basic things like add a constant or use it as part of another expression. As a result, I can't accomplish my original goal of plotting the definite integral, since I would need to subtract g(0). –  Apr 17 '16 at 23:53
  • I now explained how to subtract a constant. –  Apr 18 '16 at 00:19
  • The bottom line is: the class is underdeveloped, but one can do more with it by dropping down to Python list level, and coming back. –  Apr 18 '16 at 00:30
  • Thanks! The whole Piecewise class still seems like a hack though, and having to redefine a function each time I want to plot it is a bit annoying. At the very least, the plot function should be extended to include optional left and right bounds. I've also figured how to solve this using Python functions, which I will post as a separate answer. –  Apr 18 '16 at 00:35
1

In addition to using the Piecewise class, this can easily be fixed by defining g(x) as a Python function as well:

def f(x):
    if(x < 0):
        return 3 * x + 3
    else:
        return -3 * x + 3

def g(x):
    (y, e) = integral_numerical(f, 0, x)
    return y

Then plot(g) works just fine.