python integral calculation without using for loop - python

I want to implement a python program, which can calculate this integral
I know how to make it using For Loop and it will look something like this
import numpy as np;
def numint(f,alpha,beta,N,b,c):
s = np.size(b);
x = np.linspace(alpha,beta,N);
h = x[1]-x[0];
result = 0;
result1 = 0;
for j in range(1,N+1):
for i in range(1,s+1):
result1+=b[i]*f(x[j-1]+h*c[i]);
result+=h*result1;
result1 = 0;
return result;
Without loop I think it should be something like this:
def numint(f,alpha,beta,N,b,c):
s = np.size(b);
x = np.linspace(alpha,beta,N);
h = np.ones(N,dtype=int)*(x[1] - x[0]);
result = 0;
result = np.sum(h[1:N+1] * np.sum(b*(f(x[0:N]+h[0]*c))));
return result;
But the second part of the result = np.sum ... is wrong and I dont know how to fix it . Any suggestions ?
EDIT :
def numint(f,alpha,beta,N,b,c):
s = np.size(b);
x = np.linspace(alpha,beta,N);
h = np.ones(N,dtype=int)*(x[1] - x[0]);
functionResult = f(x+h*c);
dif = np.diff(functionResult);
result = 0;
result = np.sum(h[1:N+1] * np.sum(b*dif.sum()));
return result;
As a tip : vectorize them
but I don't know how to use it

What you are looking for is the np.diff function.
Say you are looking for the integral from 0 to 10 for f(x) = x^2 with F(x) = (x^3)/3:
x = np.linspace(0, 10, 1000)
F = lambda x: x**3/3
b = F(x)
dif = np.diff(b)
sum = dif.sum()
print(sum)
333.33333333333326
Actual result is 333.3...
You can replace F by any function you want, but the key is np.diff which decreases the size of your array by one. Then, just sum the differences along your interval and you have your result.
You can improve the precision of your result by simply increasing the number of steps (1000 in my example).

Related

Converting Mathematica Fourier series code to Python

I have some simple Mathematica code that I'm struggling to convert to Python and could use some help:
a = ((-1)^(n))*4/(Pi*(2 n + 1));
f = a*Cos[(2 n + 1)*t];
sum = Sum[f, {n, 0, 10}];
Plot[sum, {t, -2 \[Pi], 2 \[Pi]}]
The plot looks like this:
For context, I have a function f(t):
I need to plot the sum of the first 10 terms. In Mathematica this was pretty straighforward, but for some reason I just can't seem to figure out how to make it work in Python. I've tried defining a function a(n), but when I try to set f(t) equal to the sum using my list of odd numbers, it doesn't work because t is not defined, but t is a variable. Any help would be much appreciated.
Below is a sample of one of the many different things I've tried. I know that it's not quite right in terms of getting the parity of the terms to alternate, but more important I just want to figure out how to get 'f' to be the sum of the first 10 terms of the summation:
n = list(range(1,20,2))
def a(n):
return ((-1)**(n))*4/(np.pi*n)
f = 0
for i in n:
f += a(i)*np.cos(i*t)
modifying your code, look the part which are different, mostly the mistake was in the part which you are not calculating based on n 0-10 :
n = np.arange(0,10)
t = np.linspace(-2 * np.pi, 2 *np.pi, 10000)
def a(n):
return ((-1)**(n))*4/(np.pi*(2*n+1))
f = 0
for i in n:
f += a(i)*np.cos((2*i +1) * t)
however you could write you could in matrix form, and avoid looping, using the vector and broadcasting:
n = np.arange(10)[:,None]
t = np.linspace(-2 * np.pi, 2 *np.pi, 10000)[:,None]
a = ((-1) ** n) * 4 / (np.pi*(2*n + 1))
f = (a * np.cos((2 * n + 1) * t.T )).sum(axis=0)

How do I run this function for multiple values of N?

I am trying to run the code below for N = np.linspace(20,250,47), but I get multiple errors when trying to change the N. I am new to python and am not sure how to get multiple values of this function using multiple values of N. Below is the code with N = 400 and it does work, but I am not sure how to make it work for multiple N's at the same time.
import matplotlib.pyplot as plt
import numpy as np
S0 = 9
K = 10
T = 3
r = 0.06
sigma = 0.3
N = 400
dt = T / N
u = exp(sigma*sqrt(dt)+(r-0.5*sigma**2)*dt)
d = exp(-sigma*sqrt(dt)+(r-0.5*sigma**2)*dt)
p = 0.5
def binomial_tree_put(N, T, S0, sigma, r, K, array_out=False):
dt = T / N
u = exp(sigma*sqrt(dt)+(r-0.5*sigma**2)*dt)
d = exp(-sigma*sqrt(dt)+(r-0.5*sigma**2)*dt)
p = 0.5
price_tree = np.zeros([N+1,N+1])
for i in range(N+1):
for j in range(i+1):
price_tree[j,i] = S0*(d**j)*(u**(i-j))
option = np.zeros([N+1,N+1])
option[:,N] = np.maximum(np.zeros(N+1), K - price_tree[:,N])
for i in np.arange(N-1, -1, -1):
for j in np.arange(0, i+1):
option[j, i] = np.exp(-r*dt)*(p*option[j, i+1]+(1-p)*option[j+1, i+1])
if array_out:
return [option[0,0], price_tree, option]
else:
return option[0,0]
Suppose you have a list of values for N e.g N = [400, 300, 500, 800], then you need to call the function for every value, you can use a loop for that.
For example,
for num in N:
binomial_tree_put(num, *other arguments*)
np.linspace() creates an np.array but the function expects a sinlge integer. If you want to execute a function for each element contained inside a array/list, you can do that inside a loop like this:
# your code as defined above goes here
for num in np.linspace(20,250,47):
N = int(num) # you could just put N in the line above - this is just to illustrate
binomial_tree_put(N, T, S0, sigma, r, K, array_out=False)
Be aware, depending on how long your function takes to execute and how many elements are in your iterable (e.g. 47 for your case), it may take a while to execute.
Edit: I also noticed you seem to be missing an import in your example code. exp() and sqrt() are part of the math module.
You can also use partial function, like this:
from functools import partial
N = [1, 2, ...] # all your N values
binom_fct = partial(binomial_tree_put, T=T, S0=S0, sigma=sigma, r=r, K=K, array_out=array_out)
for num in N:
binom_fct(num)
partial help here

How to find the sum of this series using loops

x - x^2/fact(2) + x^3/fact(3) ... -x^6/fact(6)
I tried various ways, even used nested 'for' loops, but I can't seem to figure out the code, any help?
you could try this; order defines how many terms should be taken into account:
def taylor(x, order=3):
x_n = x
fact = 1
sign = 1
res = 0
for n in range(2, order+2):
res += sign * x_n/fact
x_n *= x
fact *= n
sign = -sign
return res
for comparison (because this is the same function):
from math import exp
def real_funtion(x):
return 1-exp(-x)

How to do numerical integration in python?

I can't install anything new I need to use the default python library and I have to integrate a function. I can get the value for any f(x) and I need to integrate from 0 to 6 for my function f(x).
In discrete form, integration is just summation, i.e.
where n is the number of samples. If we let b-a/n be dx (the 'width' of our sample) then we can write this in python as such:
def integrate(f, a, b, dx=0.1):
i = a
s = 0
while i <= b:
s += f(i)*dx
i += dx
return s
Note that we make use of higher-order functions here. Specifically, f is a function that is passed to integrate. a, b are our bounds and dx is 1/10 by default. This allows us to apply our new integration function to any function we wish, like so:
# the linear function, y = x
def linear(x):
return x
integrate(linear, 1, 6) // output: 17.85
# or using lamdba function we can write it directly in the argument
# here is the quadratic function, y=x^2
integrate(lambda x: x**2, 0, 10) // output: 338.35
You can use quadpy (out of my zoo of packages):
import numpy
import quadpy
def f(x):
return numpy.sin(x) - x
val, err = quadpy.quad(f, 0.0, 6.0)
print(val)
-17.96017028290743
def func():
print "F(x) = 2x + 3"
x = int(raw_input('Enter an integer value for x: '))
Fx = 2 * x + 3
return Fx
print func()
using the input function in python, you can randomly enter any number you want and get the function or if hard coding this this necessary you can use a for loop and append the numbers to a list for example
def func2():
print "F(x) = 2x + 3"
x = []
for numbers in range(1,7):
x.append(numbers)
upd = 0
for i in x:
Fx = 2 * x[upd] + 3
upd +=1
print Fx
print func2()
EDIT: if you would like the numbers to start counting from 0 set the first value in range to 0 instead of 1

Theil Index Python vs R

I am trying to calculate the Theil index in python and R, but with the given functions, I am getting different answers. Here is the formula that I am trying to use:
Using the ineq package in R, I can easily get the Theil index:
library(ineq)
x=c(26.1,16.1,15.5,15.4,14.8,14.7,13.7,12.1,11.7,11.6,11,10.8,10.8,7.5)
Theil(x)
0.04152699
This implementation seems to make sense and I can look at the code provided to see what exact calculations that are happening and it seems to follow the formula (deleting zeros when I get have them in order to take the log):
getAnywhere(Theil )
Out[24]:
A single object matching ‘Theil’ was found
It was found in the following places
package:ineq
namespace:ineq
with value
function (x, parameter = 0, na.rm = TRUE)
{
if (!na.rm && any(is.na(x)))
return(NA_real_)
x <- as.numeric(na.omit(x))
if (is.null(parameter))
parameter <- 0
if (parameter == 0) {
x <- x[!(x == 0)]
Th <- x/mean(x)
Th <- sum(x * log(Th))
Th <- Th/sum(x)
}
else {
Th <- exp(mean(log(x)))/mean(x)
Th <- -log(Th)
}
Th
}
However, I see that this question has been answered previously before for python here . The code is here, but the answers do not match for some reason:
def T(x):
n = len(x)
maximum_entropy = math.log(n)
actual_entropy = H(x)
redundancy = maximum_entropy - actual_entropy
inequality = 1 - math.exp(-redundancy)
return redundancy,inequality
def Group_negentropy(x_i):
if x_i == 0:
return 0
else:
return x_i*math.log(x_i)
def H(x):
n = len(x)
entropy = 0.0
summ = 0.0
for x_i in x: # work on all x[i]
summ += x_i
group_negentropy = Group_negentropy(x_i)
entropy += group_negentropy
return -entropy
x=np.array([26.1,16.1,15.5,15.4,14.8,14.7,13.7,12.1,11.7,11.6,11,10.8,10.8,7.5])
T(x)
(512.62045438815949, 1.0)
It is not stated explicitly in the other question, but that implementation expects its input to be normalized, so that each x_i is a proportion of income, not an actual amount. (That's why the other code has that error_if_not_in_range01 function and raises an error if any x_i is not between 0 and 1.)
If you normalize your x, you'll get the same result as the R code:
>>> T(x/x.sum())
(0.041526988117662533, 0.0406765553418974)
(The first value there is what R is reporting.)

Categories