integrate(sin(pi*(x - S(1)/2))**2, x) hangs

32 views
Skip to first unread message

Ondřej Čertík

unread,
Apr 30, 2013, 6:43:32 PM4/30/13
to sympy
Hi,

Today I needed to do some 3d integral, and it hangs [1], but I managed
to isolate the problem
to this very simple example:

integrate(sin(pi*(x - S(1)/2))**2, x)

The correct solution is not complicated [2]. Any ideas how to fix this
simple problem?
It will probably also fix the more difficult and messy 3D integral
from [1], but even if it doesn't, it'd be nice to be able to do this
simple integral anyway.

Thanks,
Ondrej


[1] http://code.google.com/p/sympy/issues/detail?id=3793
[2] http://www.wolframalpha.com/input/?i=integrate%28sin%28pi*%28x+-+1%2F2%29%29**2%2C+x%29

Aaron Meurer

unread,
Apr 30, 2013, 7:01:19 PM4/30/13
to sy...@googlegroups.com
All integrate() hanging is due to heurisch(), which means that none of
the other algorithms could do the integral. There is some hope that
when the matrices and the new polys are reworked by Mateusz that
heurisch will become faster, but ultimately, I would like to
completely replace it with better algorithms.

The risch algorithm can handle trigonometric functions, but they are
not implemented yet. However, it can integrate exponentials, so if
you first do .rewrite(exp) to convert it to complex exponentials, it
will integrate instantly. In this case, rewriting back to sin and
simplifying gives a nice answer. In general, it doesn't, though, so we
still need to work on that.

In [6]: integrate((sin(pi*(x - S(1)/2))**2).rewrite(exp),
x).rewrite(cos).simplify()
Out[6]:
2⋅π⋅x + sin(2⋅π⋅x)
──────────────────
4⋅π

Another option that is really easy, even if you don't know anything
about the Risch algorithm, is to extend David Li's new
manualintegrate, which just integrates the function as you would by
hand. In this case, the way you integrate sin**2 or cos**2 is to first
rewrite them using the double angle formula. So you should add this
rule to manualintegrate.py. The other benefit of this is that rules
in manual integrate translate directly to step-by-step integration
like at https://github.com/sympy/sympy_gamma/pull/11 (see for example
http://sympy-gamma-li.appspot.com/input/?i=integrate%28x*exp%28x%29%2C+x%29).

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy?hl=en-US.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Aaron Meurer

unread,
Apr 30, 2013, 7:02:18 PM4/30/13
to sy...@googlegroups.com
This one can also be done if you call trigsimp on the input first.

Aaron Meurer

Chris Smith

unread,
Apr 30, 2013, 9:13:12 PM4/30/13
to sympy
I left comments about using expand successfully on the issues page [1]

Aaron Meurer

unread,
Apr 30, 2013, 10:22:00 PM4/30/13
to sy...@googlegroups.com
I found the source of the issue. See the issue page for more details.
The fix is easy, I think, but to really be sure it is OK, we need to
test for performance regressions, which I don't have time to do right
now.

Basically, it boils down to the fact that heurisch is very sensitive
to the form of an expression. In this case, it has a hard time
recognizing -cos(pi*x) and sin(pi*(x - 1/2)) as the same thing (or the
derivative of one as the derivative of the other). I will be very glad
when the Risch algorithm is extended to work with trig functions,
because it has very nice decision procedures to rewrite expressions in
canonical ways so that it never gets confused about this sort of
thing. It will also be way faster just by the nature of the algorithm.

This sort of thing used to happen all the time with exponentials as
well. For example, look at how drastically different both the time and
the results used to be for exp(x + x*log(x)) and exp(x)*exp(x*log(x))
(which are mathematically exactly the same).

In [7]: from sympy.integrals.heurisch import heurisch

In [18]: %time heurisch(diff(exp(x)*exp(x*log(x))), x)
CPU times: user 4.52 s, sys: 66.2 ms, total: 4.59 s
Wall time: 4.55 s
Out[18]:
x x⋅log(x)
ℯ ⋅ℯ

In [19]: %time heurisch(diff(exp(x + x*log(x))), x)
CPU times: user 36.8 s, sys: 90 ms, total: 36.9 s
Wall time: 36.9 s
<no output>

In [20]: from sympy.integrals.risch import risch_integrate

In [21]: %time risch_integrate(diff(exp(x)*exp(x*log(x))), x)
CPU times: user 201 ms, sys: 38.2 ms, total: 240 ms
Wall time: 213 ms
Out[21]:
x x⋅log(x)
ℯ ⋅ℯ

In [22]: %time risch_integrate(diff(exp(x + x*log(x))), x)
CPU times: user 78 ms, sys: 16.7 ms, total: 94.7 ms
Wall time: 84.6 ms
Out[22]:
x⋅log(x) + x


I still think getting manualintegrate to do this integral would be a
good idea too.

Aaron Meurer

On Tue, Apr 30, 2013 at 7:13 PM, Chris Smith <smi...@gmail.com> wrote:
> I left comments about using expand successfully on the issues page [1]
>
Reply all
Reply to author
Forward
0 new messages