This code is supposed to approximate the values of a function knowing only the value of the function at some arbitrary points and its derivative at said points.
Here is the code:
class Expand:
def __init__(self, fx: list, fy: list, dfy: list):
self.Fx = fx
self.Fy = fy
self.dFy = dfy
def get_value(self, x: float | int) -> float:
index = self.Fx.index(int(x))
if float(x).is_integer():
return self.Fy[index]
Ai = index
Bi = index + 1
Ax, Bx = self.Fx[Ai], self.Fx[Bi]
Ay, By = self.Fy[Ai], self.Fy[Bi]
dAy, dBy = self.dFy[Ai], self.dFy[Bi]
if dAy == dBy:
Vx = (Ax + Bx)/2
Vy = (Ay + By)/2
else:
Vx = (By - Ay + dAy*Ax - dBy*Bx)/(dAy - dBy)
Vy = Ay + dAy*(Vx - Ax)
denominator = (Ax - Bx)**2
p = (Ax - 2*Vx + Bx)/denominator
if p != 0:
q = 2*(Ax*Vx - 2*Ax*Bx + Vx*Bx)/denominator
x = ((4*p*(x - Ax*Bx*p) + q*q)**0.5 - q)/(2*p)
y = (Ay*((Bx - x)**2) + (Ax - x)*(Ax*By - 2*Vy*(Bx - x) - By*x))/((Ax - Bx)**2)
return y
def __call__(self, density: int):
Ex, Ey = [], []
for x in range(self.Fx[0]*density, self.Fx[-1]*density + 1):
x /= density
Ex.append(x)
Ey.append(self.get_value(x))
return (Ex, Ey)
if __name__ == "__main__":
import matplotlib.pyplot as plt
fx, fy, dfy = [-3, -2, -1, 0], [1, 1, 2, 6], [-0.577215664902, 0.422784335098, 1.8455686702, 7.53670601059]
G = Expand(fx, fy, dfy)
gx, gy = G(2)
plt.plot(fx, fy, color="b")
plt.plot(gx, gy, color="r")
plt.show()
The code seems to work properly when the list of x values of the points of the initial function fx start at a positive value, but if i shift those values by a negative amount (which on paper would only shift the output values to the left) the resulting approximation gets distorted near some values if its shifted by a small amount or an indexing error pops up otherwise.
This is the error message:
Traceback (most recent call last):
File "c:\Users\marco\Documents\My Programs\Personal\Expand.py", line 53, in <module>
gx, gy = G(2)
^^^^
File "c:\Users\marco\Documents\My Programs\Personal\Expand.py", line 42, in __call__
Ey.append(self.get_value(x))
^^^^^^^^^^^^^^^^^
File "c:\Users\marco\Documents\My Programs\Personal\Expand.py", line 16, in get_value
Ax, Bx = self.Fx[Ai], self.Fx[Bi]
~~~~~~~^^^^
IndexError: list index out of range
I have checked the values of the variables Ax, Bx, Ay, By, dAy, dBy, Vx, Vx, denominator, p, q, x & y but that doesn't seem to be the problem since the formulas for obtaining each variable work correctly.
I think the error must either come from the __call__ method or the way i find the variable index
The issue is fixed now, i just had to import the math module and replace
index = self.Fx.index(int(x))withindex = self.Fx.index(math.floor(x))It turns out that the function int(x) effectively works like floor(x) for positive values but not for negative ones, for example:
int(2.5) = 2
floor(2.5) = 2
int(-2.5) = -2
floor(-2.5) = -3