I'm encountering some problems using sympy, here is my code:
from sympy import integrate as inter
import sympy as sp
from sympy import symbols
def f(x):
f1 = (sp.exp(-x ** 2)) / (1 + x ** 2)
f2 = (2 * (sp.cos(x)) ** 2) / (1 + (x - 4) ** 2)
f = f1 + f2
return(f)
def integrate_f_from0(b):
x = symbols('x')
a = inter(f(x), (x, 0, b))
return(a)
The error I get upon running the integrate_f_from0 function is:
AttributeError: module 'sympy' has no attribute 'polys'
What is causing this error?
In SymPy 1.1.1 your code works as expected: integrate_f_from0(3) returns
Integral((2*x**2*exp(x**2)*cos(x)**2 + x**2 - 8*x + 2*exp(x**2)*cos(x)**2 + 17)*exp(-x**2)/((x**2 + 1)*(x**2 - 8*x + 17)), (x, 0, 3))
Which means, SymPy could not find a symbolic expression for that integral, so it returns it unevaluated (although transformed in the process of searching for antiderivative).
A quick check with Wolfram Alpha confirms there is no antiderivative in terms of elementary functions.
Suggestions:
If you have the sum of two complicated functions, try integrating it one term at a time. It does not help in this case, but in general you'll at least have an idea of what part of the expression fails to have an elementary antiderivative.
To find the integral numerically, use N(Integral(f(x), (x, 0, 3))) (returns 1.24063...) though of course, for numeric integration one is more likely to use SciPy.
Related
I am trying to solve the hyperbolic equation in the following way to find x and y. I wanted to know if it made sense to use the same equation twice in fsolve to find first x and then y. My code is as follows:
from scipy.optimize import *
from numpy import *
import math
a = 1/(a_6**2)
b = 1/(b_6**2)
def function_hyper(loc):
x = loc[0]
y = loc[1]
F = empty((2))
F[0] = a*pow(x, 2) - b*pow(y, 2) - 1
F[1] = a*pow(x, 2) - b*pow(y, 2) - 1
return F1
loc_Guess = np.array([0.0141, 0.107])
location = fsolve(function_hyper, loc_Guess)
Here, a_6 and b_6 are variables calculated from previous steps. a and b are co-efficients for solving hyperbolic equation of x^2/a^2 - y^2/b^2 = 1. This is the equation I have written in F[0] and F[1]. empty is to define F before using it. So after having values for F, empty gets replaced. pow is to define a power of 2 for squaring x and y.
According to the documentation, fsolve is just a Wrapper around MINPACK's hybrd routine:
The purpose of HYBRD is to find a zero of a system of N non-linear functions in N variables by a modification of the Powell hybrid method. The user must provide a subroutine which calculates the functions. The Jacobian is then calculated by a forward-difference approximation.
Consequently, you need N equations to find the root of a function in N variables. Hence, in case one wants to find the root of a function f: R^N -> R one could either solve the system of N equations (f(x), ..., f(x)) = (0, ..., 0) (like you did) or simply (f(x), 0, ..., 0) = (0, ..., 0). The latter looks like this in code:
import numpy as np
a = 1/(a_6**2)
b = 1/(b_6**2)
def function_hyper(loc):
x, y = loc[0], loc[1]
F = np.zeros(2)
F[0] = a * x**2 - b * y**2 - 1
return F
I am carrying out inverse lapalce transform for various complicated expressions with sympy, and they usually end up with ValueError: gamma function pole. What can be done to aviod such error, and reach the result successfully ?
I had tried to decompose the expression by using sympy.apart function, and even rounded coefficients in the expression, but they all cannot guarantee the success of the code.
from sympy import *
s = symbols('s')
w = symbols('w', real =True)
t = symbols('t', positive = True)
f = 3.36/(2.564549826*s+1)/s + 5/(2.2654984123*s+1)/s
print(print(inverse_laplace_transform(f,s,t=100).evalf()))
The error information is ValueError: gamma function pole
It's best to avoid using Floats in sympy but actually using Rational here means the integral hangs (takes a long time). If you use symbols instead you can get the answer quickly:
from sympy import *
s = symbols('s')
w = symbols('w', real =True)
t = symbols('t', positive = True)
a, b, c = symbols('a, b, c', real=True)
f = a/(b*s+1)/s + 5/(c*s+1)/s
pprint(f)
pprint(inverse_laplace_transform(f,s,t=100))
That gives
a 5
─────────── + ───────────
s⋅(b⋅s + 1) s⋅(c⋅s + 1)
-100 -100
───── ─────
b c
a - a⋅ℯ + 5 - 5⋅ℯ
You can the substitute to get the answer you want:
In [22]: ilt = inverse_laplace_transform(f,s,t=100)
In [23]: ilt.subs({a: 3.36, b:2.564549826, c:2.2654984123})
Out[23]: 8.36000000000000
I am trying to apply a Runge Kutta method for solving an ODE. The problem is, python somewhere keeps rounding like a madman and I don't understand why or is something syntactically telling python to round everything? I've tried converting everything to float () to no avail. What should I do to have python compute everything satisfying some accuracy demand?
import numpy as np
def fn(x,y):
return x-y
def rk3 (y0,x):
n = len (x)
y = np.array([y0]*n)
for j in range(n-1):
h = x[j+1]-x[j]
k1 = h * fn(x[j],y[j])
k2 = h * fn(x[j] + h / 3.0, y[j] + k1 / 3.0)
k3 = h * fn(x[j] + 2.0*h /3.0, y[j] + 2.0*k2 /3.0)
y[j+1] = y[j] + k1*1.0/4.0 + k3 *3.0/4.0
return y
v = rk3(1, np.linspace(0,5,500))
The mistake is passing an integer in rk3(1,np.linspace(0,5,500)). If one changes to 1.0 all further operations are regarded as float point arithmetic as required.
For my latest project in my coding class (python), we need to program and compute a cubic function. So something like 3x^3+2x^2+7x+1. I cannot figure out how to code in the different x powers. I know this is a very simple question, but I can't find what I am looking for on the internet and have searched. How would I write out this polynomial given the 3,2,7 & 1 values? I assume I need to use numpy but can only figure that out with a degree one polynomial.
powers can be represented with ** in python (there is also a more sophisticated pow) function:
def f(x):
return 3*x**3 + 2*x**2 + 7*x + 1
(in python ^ is the xor operator; if you use your expression python would not complain but just not calculate what you want)
if you need to be able to do symbolic math, i suggest you install the sympy package:
from sympy import symbols
def f(x):
return 3*x**3 + 2*x**2 + 7*x + 1
x = symbols('x')
print(f(x)) # 3*x**3 + 2*x**2 + 7*x + 1
print(f(x).subs(x, 5)) # 461
You can also create a custom function like this example:
def cubic(x, args):
args_len = len(args)
for k in args:
yield k * x ** (args_len-1)
args_len -=1
Demo:
user_input = [3, 2, 7, 1]
user_var_x = 1
somme = sum(cubic(user_var_x, user_input))
print(somme)
Output:
13
I'm using power function from numpy and i'm obtaining a warning message. This is the code:
import numpy as np
def f(x, n):
factor = n / (1. + n)
exponent = 1. + (1. / n)
f1_x = factor * np.power(0.5, exponent) - np.power(0.5 - x, exponent)
f2_x = factor * np.power(0.5, exponent) - np.power(x - 0.5, exponent)
return np.where((0 <= x) & (x <= 0.5), f1_x, f2_x)
fv = np.vectorize(f, otypes='f')
x = np.linspace(0., 1., 20)
print(fv(x, 0.23))
And this is the warning message:
E:\ProgramasPython3\LibroCientifico\partesvectorizada.py:8:
RuntimeWarning: invalid value encountered in power f2_x = factor *
np.power(0.5, exponent) - np.power(x - 0.5, exponent)
E:\ProgramasPython3\LibroCientifico\partesvectorizada.py:7:
RuntimeWarning: invalid value encountered in power f1_x = factor *
np.power(0.5, exponent) - np.power(0.5 - x, exponent) [-0.0199636
-0.00895462 -0.0023446 0.00136486 0.003271 0.00414007
0.00447386 0.00457215 0.00459036 0.00459162 0.00459162 0.00459036
0.00457215 0.00447386 0.00414007 0.003271 0.00136486 -0.0023446 -0.00895462 -0.0199636 ]
I don't know what is the invalid value. And I don't know how to specify that with where numpy function f2_x is only valid for values between >0.5 and <= 1.0.
Thanks
The reason this happens is because you are trying to take a non-integer power of a negative number. Apparently this doesn't work in earlier versions of Python/Numpy if you don't explicitly cast the value to be complex. So you will have to do something like
np.power(complex(0.5 - x), exponent).real
EDIT : Since your values will be truly complex (not some real number + some tiny imag part), I think you would want to either use the complex (but then the <=) later on gets kind of difficult, or you would want to catch the case where the base is negative in some other way.
Ok, thanks a lot everyone, here's the solution using a piecewise function against where from numpy, and using np.complex128 as mentioned #Saullo
import numpy as np
def f(x, n):
factor = n / (1. + n)
exponent = (n + 1.) / n
f1_x = lambda x: factor * \
np.power(2., -exponent) - np.power((1. - 2. * x) / 2., exponent)
f2_x = lambda x: factor * \
np.power(2., -exponent) - np.power(-(1. - 2. * x) / 2., exponent)
conditions = [(0. <= x) & (x <= 0.5), (0.5 < x) & (x <= 1.)]
functions = [f1_x, f2_x]
result = np.piecewise(x, conditions, functions)
return np.real(result)
x = np.linspace(0., 1., 20)
x = x.astype(np.complex128)
print(f(x, 0.23))
The problem is when the base from a power is negative then np.power doesn't work fine and you obtain the warning message. I expect this is useful for everyone.