Reputation: 343
I'm just learning how to use sympy and I have tried a simple integration of a sin function. When the argument of sin()
has a constant phase constant the output of integrate()
gives the same value whatever is the phase: 0
from sympy import *
w = 0.01
phi = 0.3
k1 = integrate(sin(w*x), (x, 0.0, 10.0))
k2 = integrate(sin(w*x + 0.13), (x, 0.0, 10.0))
k3 = integrate(sin(w*x + phi),(x, 0.0, 10.0))
k1, k2, k3
(0.499583472197429, 0, 0)
Can somebody explain me why ?
Upvotes: 6
Views: 916
Reputation: 8172
Can I recommend using numpy
for numerical integration?
>>> import numpy as np
>>> w = 0.01
>>> phi = 0.3
>>> dt = 0.01
>>> t = 2*np.pi*np.arange(0,1,dt)
>>> np.sum( np.sin(t)*dt)
-1.0733601507606494e-17
>>> np.sum( np.sin(t+ phi)*dt)
2.5153490401663703e-17
These numbers are basically close to 0. The exact number is an artifact of our choice of mesh dt
and shift phi
(as well as the accuracy of np.sin
)
To be more consistent with your example:
>>> t = np.arange(0,10,dt)
>>> w = 0.01
>>> phi = 0.3
>>> np.sum( np.sin(w*t)*dt)
0.4990843046978698
>>> np.sum( np.sin(w*t + phi)*dt)
3.4270800187375658
>>> np.sum( np.sin(w*t + 0.13)*dt)
1.7890581525454512
As quoted in Integrating in Python using Sympy it's a bad idea to use a symbolic library for numerical work
Upvotes: 0
Reputation: 91660
I just ran your code in the development version of SymPy and I got (0.499583472197429, 1.78954987094131, 3.42754951227208)
. So it seems the bug will be fixed in the next version.
It also looks like this bug is in Python 2 only. When I use Python 3, even with the latest stable version (0.7.6.1) I get the same answer.
Upvotes: 0
Reputation: 26039
That seems to be a bug. A workaround solution could be to get a symbolic expression of your integral first (which seems to work fine), then evaluate it for each set of parameters at the upper and lower bound and calculate the difference:
import sympy as sp
x, w, phi = sp.symbols('x w phi')
# integrate function symbolically
func = sp.integrate(sp.sin(w * x + phi), x)
# define your parameters
para = [{'w': 0.01, 'phi': 0., 'lb': 0., 'ub': 10., 'res': 0.},
{'w': 0.01, 'phi': 0.13, 'lb': 0., 'ub': 10., 'res': 0.},
{'w': 0.01, 'phi': 0.3, 'lb': 0., 'ub': 10., 'res': 0.}]
# evaluate your function for all parameters using the function subs
for parai in para:
parai['res'] = func.subs({w: parai['w'], phi: parai['phi'], x: parai['ub']})
-func.subs({w: parai['w'], phi: parai['phi'], x: parai['lb']})
After this, para
looks then as follows:
[{'lb': 0.0, 'phi': 0.0, 'res': 0.499583472197429, 'ub': 10.0, 'w': 0.01},
{'lb': 0.0, 'phi': 0.13, 'res': 1.78954987094131, 'ub': 10.0, 'w': 0.01},
{'lb': 0.0, 'phi': 0.3, 'res': 3.42754951227208, 'ub': 10.0, 'w': 0.01}]
which seems to give reasonable results for the integration which are stored in res
Upvotes: 1