Integral function (x,y) in python - python

I have a function like:
(np.sqrt((X)**2 + (Y)**2))/(np.sqrt((X)**2 + (Y)**2 + d**2))
I wrote a program for calculating integral by using series:
for i in range (num): # for X
print i
Y=(-distance)
for j in range(num): # for Y
f=(np.sqrt((X)**2 + (Y)**2))/(np.sqrt((X)**2 + (Y)**2 + d**2))
Y=Y+delta
sum+=(f*(delta**2))/((2*distance)**2)
X=X+delta
print sum
And It works fine for me.. But it takes too long for some complex function.
Is there any python module for integrating this function when -2.0 < X and Y < 2.0? (or something else)

I guess that you want to integrate fun between x equals a and b and y equals c and d. In this case what you have to do is:
import numpy as np
# Define 'd' to whatever value you need
d = 1.
# Function to integrate
fun = lambda x, y: np.sqrt(x**2. + y**2.) / np.sqrt(x**2. + y**2. + d**2.)
# Limits of integration
a, b = -2., 2.
c, d = -2., 2.
gfun = lambda x: c
hfun = lambda x: d
# Perform integration
from scipy.integrate import dblquad
int, err = dblquad(fun, a, b, gfun, hfun)
If you need more complex limits of integration you just need to change gfun and hfun. If you are interested in more advanced feature you can take a look at the documentation of dblquad: http://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.dblquad.html#scipy.integrate.dblquad

There's a library for this, scipy.integrate.
This should be pretty straightforward to do:
func = lambda y: (np.sqrt((X)**2 + (Y)**2))/(np.sqrt((X)**2 + (Y)**2 + d**2)) and a == -2 and b == 2
from scipy import integrate
integrate.quad(func, a b)
This should do it. I would consult the documentation for SciPy for more info.
Edit: If there are issues, make sure you're using floats instead of ints.

Related

evalf and subs in sympy on single variable expression returns expression instead of expected float value

I'm new to sympy and I'm trying to use it to get the values of higher order Greeks of options (basically higher order derivatives). My goal is to do a Taylor series expansion. The function in question is the first derivative.
f(x) = N(d1)
N(d1) is the P(X <= d1) of a standard normal distribution. d1 in turn is another function of x (x in this case is the price of the stock to anybody who's interested).
d1 = (np.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*np.sqrt(0.5))
As you can see, d1 is a function of only x. This is what I have tried so far.
import sympy as sp
from math import pi
from sympy.stats import Normal,P
x = sp.symbols('x')
u = (sp.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*np.sqrt(0.5))
N = Normal('N',0,1)
f = sp.simplify(P(N <= u))
print(f.evalf(subs={x:100})) # This should be 0.5155
f1 = sp.simplify(sp.diff(f,x))
f1.evalf(subs={x:100}) # This should also return a float value
The last line of code however returns an expression, not a float value as I expected like in the case with f. I feel like I'm making a very simple mistake but I can't find out why. I'd appreciate any help.
Thanks.
If you define x with positive=True (which is implied by the log in the definition of u assuming u is real which is implied by the definition of f) it looks like you get almost the expected result (also using f1.subs({x:100}) in the version without the positive x assumption shows the trouble is with unevaluated polar_lift(0) terms):
import sympy as sp
from sympy.stats import Normal, P
x = sp.symbols('x', positive=True)
u = (sp.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*sp.sqrt(0.5)) # changed np to sp
N = Normal('N',0,1)
f = sp.simplify(P(N <= u))
print(f.evalf(subs={x:100})) # 0.541087287864516
f1 = sp.simplify(sp.diff(f,x))
print(f1.evalf(subs={x:100})) # 0.0510177033783834

How to know whether a function is continuous with sympy?

I need to define a function that checks if the input function is continuous at a point with sympy.
I searched the sympy documents with the keyword "continuity" and there is no existing function for that.
I think maybe I should consider doing it with limits, but I'm not sure how.
def check_continuity(f, var, a):
try:
f = sympify(f)
except SympifyError:
return("Invaild input")
else:
x1 = Symbol(var, positive = True)
x2 = Symbol(var, negative = True)
//I don't know what to do after this
I would suggest you use the function continuous_domain. This is defined in the calculus.util module.
Example usage:
>>> from sympy import Symbol, S
>>> from sympy.calculus.util import continuous_domain
>>> x = Symbol("x")
>>> f = sin(x)/x
>>> continuous_domain(f, x, S.Reals)
Union(Interval.open(-oo, 0), Interval.open(0, oo))
This is documented in the SymPy docs here. You can also view the source code here.
Yes, you need to use the limits.
The formal definition of continuity at a point has three conditions that must be met.
A function f(x) is continuous at a point where x = c if
lim x —> c f(x) exists
f(c) exists (That is, c is in the domain of f.)
lim x —> c f(x) = f(c)
SymPy can compute symbolic limits with the limit function.
>>> limit(sin(x)/x, x, 0)
1
See: https://docs.sympy.org/latest/tutorial/calculus.html#limits
Here is a more simple way to check if a function is continues for a specific value:
import sympy as sp
x = sp.Symbol("x")
f = 1/x
value = 0
def checkifcontinus(func,x,symbol):
return (sp.limit(func, symbol, x).is_real)
print(checkifcontinus(f,value,x))
This code output will be - False

Writing a function for x * sin(3/x) in python

I have to write a function, s(x) = x * sin(3/x) in python that is capable of taking single values or vectors/arrays, but I'm having a little trouble handling the cases when x is zero (or has an element that's zero). This is what I have so far:
def s(x):
result = zeros(size(x))
for a in range(0,size(x)):
if (x[a] == 0):
result[a] = 0
else:
result[a] = float(x[a] * sin(3.0/x[a]))
return result
Which...doesn't work for x = 0. And it's kinda messy. Even worse, I'm unable to use sympy's integrate function on it, or use it in my own simpson/trapezoidal rule code. Any ideas?
When I use integrate() on this function, I get the following error message: "Symbol" object does not support indexing.
This takes about 30 seconds per integrate call:
import sympy as sp
x = sp.Symbol('x')
int2 = sp.integrate(x*sp.sin(3./x),(x,0.000001,2)).evalf(8)
print int2
int1 = sp.integrate(x*sp.sin(3./x),(x,0,2)).evalf(8)
print int1
The results are:
1.0996940
-4.5*Si(zoo) + 8.1682775
Clearly you want to start the integration from a small positive number to avoid the problem at x = 0.
You can also assign x*sin(3./x) to a variable, e.g.:
s = x*sin(3./x)
int1 = sp.integrate(s, (x, 0.00001, 2))
My original answer using scipy to compute the integral:
import scipy.integrate
import math
def s(x):
if abs(x) < 0.00001:
return 0
else:
return x*math.sin(3.0/x)
s_exact = scipy.integrate.quad(s, 0, 2)
print s_exact
See the scipy docs for more integration options.
If you want to use SymPy's integrate, you need a symbolic function. A wrong value at a point doesn't really matter for integration (at least mathematically), so you shouldn't worry about it.
It seems there is a bug in SymPy that gives an answer in terms of zoo at 0, because it isn't using limit correctly. You'll need to compute the limits manually. For example, the integral from 0 to 1:
In [14]: res = integrate(x*sin(3/x), x)
In [15]: ans = limit(res, x, 1) - limit(res, x, 0)
In [16]: ans
Out[16]:
9⋅π 3⋅cos(3) sin(3) 9⋅Si(3)
- ─── + ──────── + ────── + ───────
4 2 2 2
In [17]: ans.evalf()
Out[17]: -0.164075835450162

Dynamically build a lambda function in python

Supose that I want to generate a function to be later incorporated in a set of equations to be solved with scipy nsolve function. I want to create a function like this:
xi + xi+1 + xi+3 = 1
in which the number of variables will be dependent on the number of components. For example, if I have 2 components:
f = lambda x: x[0] + x[1] - 1
for 3:
f = lambda x: x[0] + x[1] + x[2] - 1
I specify the components as an array within the arguments of the function to be called:
def my_func(components):
for component in components:
.....
.....
return f
I can't just find a way of doing this. I've to be able to make it this way as this function and other functions need to be solved together with nsolve:
x0 = scipy.optimize.fsolve(f, [0, 0, 0, 0 ....])
Any help would be appreciated
Thanks!
Since I'm not sure which is the best way of doing this I will fully explain what I'm trying to do:
-I'm trying to generate this two functions to be later nsolved:
So I want to create a function teste([list of components]) that can return me this two equations (Psat(T) is a function I can call depending on the component and P is a constant(value = 760)).
Example:
teste(['Benzene','Toluene'])
would return:
xBenzene + xToluene = 1
xBenzenePsat('Benzene') + xToluenePsat('Toluene') = 760
in the case of calling:
teste(['Benzene','Toluene','Cumene'])
it would return:
xBenzene + xToluene + xCumene = 1
xBenzenePsat('Benzene') + xToluenePsat('Toluene') + xCumene*Psat('Cumene') = 760
All these x values are not something I can calculate and turn into a list I can sum. They are variables that are created as a function ofthe number of components I have in the system...
Hope this helps to find the best way of doing this
A direct translation would be:
f = lambda *x: sum(x) - 1
But not sure if that's really what you want.
You can dynamically build a lambda with a string then parse it with the eval function like this:
a = [1, 2, 3]
s = "lambda x: "
s += " + ".join(["x[" + str(i) + "]" for i in xrange(0, 3)]) # Specify any range
s += " - 1"
print s
f = eval(s)
print f(a)
I would take advantage of numpy and do something like:
def teste(molecules):
P = np.array([Psat(molecule) for molecule in molecules])
f1 = lambda x: np.sum(x) - 1
f2 = lambda x: np.dot(x, P) - 760
return f1, f2
Actually what you are trying to solve is a possibly underdetermined system of linear equations, of the form A.x = b. You can construct A and b as follows:
A = np.vstack((np.ones((len(molecules),)),
[Psat(molecule) for molecule in molecules]))
b = np.array([1, 760])
And you could then create a single lambda function returning a 2 element vector as:
return lambda x: np.dot(A, x) - b
But I really don´t think that is the best approach to solving your equations: either you have a single solution you can get with np.linalg.solve(A, b), or you have a linear system with infinitely many solutions, in which case what you want to find is a base of the solution space, not a single point in that space, which is what you will get from a numerical solver that takes a function as input.
If you really want to define a function by building it up iteratively, you can. I can't think of any situation where this would be the best answer, or even a reasonable one, but it's what you asked for, so:
def my_func(components):
f = lambda x: -1
for component in components:
def wrap(f):
return lambda x: component * x[0] + f(x[1:])
f = wrap(f)
return f
Now:
>>> f = my_func([1, 2, 3])
>>> f([4,5,6])
44
Of course this will be no fun to debug. For example, look at the traceback from calling f([4,5]).
def make_constraint_function(components):
def constraint(vector):
return sum(vector[component] for component in components) - 1
return constraint
You could do it with a lambda, but a named function may be more readable. deffed functions can do anything lambdas can and more. Make sure to give the function a good docstring, and use variable and function names appropriate for your program.

Find roots of a function a x^n + bx - c = 0 where n isn't an integer with Numpy?

I'm writing a program in python and in it I need to find the roots of a function that is:
a*x^n + b*x -c = 0
where a and b are constants that are calculated earlier in the program but there are several thousand of them.
I need to repeat this equation twice for all values of a and b once with n = 77/27 and once with n = 3.
How can i do this in python?
I checked numpy.roots(p) and that would work for when n = 3 I think. But for n = 77/27 how would I be able to do that?
I think your beast choice is scipy.optimize.brentq():
def f(x, n, a, b, c):
return a * x**n + b * x - c
print scipy.optimize.brentq(
f, 0.0, 100.0, args=(77.0/27.0, 1.0, 1.0, 10.0))
prints
2.0672035922580592
Look here and here.
I'm so proud of myself, I still remember the specifics (without reading the link!) :)
If you don't get that, look here.
I would use fsolve from scipy,
from scipy.optimize import fsolve
def func(x,a,b,c,n):
return a*x**n + b*x - c
a,b,c = 11.,23.,31.
n = 77./27.
guess = [4.0,]
print fsolve(func,guess,args=(a,b,c,n)) # 0.94312258329
This of course gives you a root, not necessarily all roots.
Edit: Use brentq, it's much faster
from timeit import timeit
sp = """
from scipy.optimize import fsolve
from scipy.optimize import brentq
from numpy.random import uniform
from numpy import zeros
m = 10**3
z = zeros((m,4))
z[:,:3] = uniform(1,50,size=(m,3))
z[:,3] = uniform(1,10,m)
def func(x,a,b,c,n):
return a*x**n + b*x - c
"""
s = "[fsolve(func,1.0,args=tuple(i)) for i in z]"
t = "[brentq(func,0.,10.,args=tuple(i)) for i in z]"
runs = 10**2
print 'fsolve\t', timeit(s,sp,number=runs)
print 'brentq\t', timeit(t,sp,number=runs)
gives me,
fsolve 15.5562820435
brentq 3.84963393211
You need a root finding algorithm like Newton's method. All root finding algorithms will work with non-integer powers. They need not even be rational numbers.

Categories

Resources