-
Notifications
You must be signed in to change notification settings - Fork 0
/
integration.py
100 lines (81 loc) · 3.54 KB
/
integration.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
from vectors import *
from typing import *
from numpy import number
from numbers import Number
"""
"""
numeric = Union[Number, number]
def integrate(function : Callable[ [numeric] , numeric ], bounds : tuple[ numeric, numeric ], Δx = 0.0001, area_func = lambda function, x, Δx : function(x)*Δx ) -> numeric :
"""
Calculates the integral of an arbitrary function numerically using an arbitrary area function (the area function defaults to a basic
rectangular area, with no preference to circumscribing vs inscribing).
INPUTS:
function - like y = lambda x : x**2
bounds - 1D array with 2 elements, like (-5,100)
Δx - step size (i.e. width of areas). must be scalar
area_func - could be a function of any kind, but must be prepared to deal with array multiplication like Δx*(np.arange(0,10,1)**2)
RETURNS:
area - area of the integral
"""
from numpy import arange
return sum(area_func(function, arange(bounds[0],bounds[1],Δx), Δx))
def trap_integrate(function,bounds,Δx = 0.0001):
"""
Calculates the integral of an arbitrary function numerically using a trapezoidal area, implementing the integrate function
INPUTS:
function - like y = lambda x : x**2
bounds - 1D array with 2 elements, like [-5,100]
Δx - step size (i.e. width of areas). must be scalar
RETURNS:
area - area of the integral
"""
return integrate(function,bounds,Δx,lambda function, x, Δx: (function(x)+function(x+Δx))*Δx*0.5)
class optimizeIntegral():
"""
Use dynamic step size to ensure numerical integration has minimal eroneous values due to x-axis area cross over.
INPUTS:
function - like y = lambda x : x**2
bounds - 1D array with 2 elements, like [-5,100]
Δx - step size (i.e. width of areas). must be scalar
area_func - could be a function of any kind, but must be prepared to deal with array multiplication like Δx*(np.arange(0,10,1)**2)
RETURNS:
area - area of the integral
"""
import numpy as np
def __init__(self,function, bounds, Δx , area_func = lambda function, x, Δx : function(x)*Δx):
self.func = function
self.bounds = bounds
self.step = Δx
self.area_func = area_func
def areaAdd(self, x, Δx, areas):
"""
Appends to the area list the next area given scalar x, Δx, and the previous list of areas
Changes step size if the width of the initial Δx contains a cross over using functional recursion.
"""
funcx1 = self.func(x)
funcx2 = self.func(x+Δx)
if normalize(funcx1)==normalize(funcx2):
areas.append(self.area_func(self.func,x,Δx))
#print('m')
else:
Δx = Δx/2
self.areaAdd(x,Δx,areas)
return areas, x+Δx
def roughOptimum(self):
"""
Chops off cross-over values.
"""
step_list = np.arange(self.bounds[0],self.bounds[1],self.step)
area = sum([self.area_func(self.func,i,self.step) for i in step_list if (normalize(self.func(i))==normalize(self.func(i+self.step)))])
return area
def dynamicOptimum(self):
"""
Changes step size around cross-overs in order to ensure areas will be on oneside or the other of cross-overs
"""
step_list = np.arange(self.bounds[0],self.bounds[1],self.step)
areas = []
newx = step_list[0]
while newx <= step_list[-1]:
areas, newx = self.areaAdd(newx,self.step,areas)
#newx
return sum(areas)