简体   繁体   中英

How can I simplify this more?

I am trying to apply numpy to this code I wrote for trapezium rule integration:

def integral(a,b,n):
    delta = (b-a)/float(n)

    s = 0.0
    s+= np.sin(a)/(a*2)
    for i in range(1,n):
         s +=np.sin(a + i*delta)/(a + i*delta)
    s += np.sin(b)/(b*2.0)
    return s * delta

I am trying to get the return value from the new function something like this:

return delta *((2 *np.sin(x[1:-1])) +np.sin(x[0])+np.sin(x[-1]) )/2*x

I am trying for a long time now to make any breakthrough but all my attempts failed.

One of the things I attempted and I do not get is why the following code gives too many indices for array error?

 def integral(a,b,n):
      d = (b-a)/float(n)
      x = np.arange(a,b,d)
      J = np.where(x[:,1] < np.sin(x[:,0])/x[:,0])[0]

Every hint/advice is very much appreciated.

You forgot to sum over sin(x) :

>>> def integral(a, b, n):
...     x, delta = np.linspace(a, b, n+1, retstep=True)
...     y = np.sin(x)
...     y[0] /= 2
...     y[-1] /= 2
...     return delta * y.sum()
... 
>>> integral(0, np.pi / 2, 10000)
0.9999999979438324
>>> integral(0, 2 * np.pi, 10000)
0.0
>>> from scipy.integrate import quad
>>> quad(np.sin, 0, np.pi / 2)
(0.9999999999999999, 1.1102230246251564e-14)
>>> quad(np.sin, 0, 2 * np.pi)
(2.221501482512777e-16, 4.3998892617845996e-14)

I tried this meanwhile, too.

import numpy as np

def T_n(a, b, n, fun):
    delta = (b - a)/float(n)                # delta formula
    x_i = lambda a,i,delta: a + i * delta   # calculate x_i
    return 0.5 * delta * \
           (2 * sum(fun(x_i(a, np.arange(0, n + 1), delta))) \
            - fun(x_i(a, 0, delta)) \
            - fun(x_i(a, n, delta)))

Reconstructed the code using formulas at bottom of this page https://matheguru.com/integralrechnung/trapezregel.html

The summing over the range(0, n+1) - which gives [0, 1, ..., n] - is implemented using numpy. Usually, you would collect the values using a for loop in normal Python. But numpy's vectorized behaviour can be used here. np.arange(0, n+1) gives a np.array([0, 1, ...,n]).

If given as argument to the function (here abstracted as fun ) - the function formula for x_0 to x_n will be then calculated. and collected in a numpy-array. So fun(x_i(...)) returns a numpy-array of the function applied on x_0 to x_n . This array/list is summed up by sum() .

The entire sum() is multiplied by 2 , and then the function value of x_0 and x_n subtracted afterwards. (Since in the trapezoid formula only the middle summands, but not the first and the last, are multiplied by 2). This was kind of a hack.

The linked German page uses as a function fun(x) = x ^ 2 + 3 which can be nicely defined on the fly by using a lambda expression:

fun = lambda x: x ** 2 + 3
a = -2
b = 3
n = 6

You could instead use a normal function definition, too: defun fun(x): return x ** 2 + 3 . So I tested by typing the command:

T_n(a, b, n, fun)

Which correctly returned:

## Out[172]: 27.24537037037037

For your case, just allocate np.sin to fun and your values for a , b , and n into this function call.

Like:

fun = np.sin      # by that eveywhere where `fun` is placed in function, 
# it will behave as if `np.sin` will stand there - this is possible,
# because Python treats its functions as first class citizens
a   = #your value
b   = #your value
n   = #your value

Finally, you can call:

T_n(a, b, n, fun)

And it will work!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM