List Index Error when Starting from Negative Values

44 views Asked by At

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

1

There are 1 answers

0
M11X00 On

The issue is fixed now, i just had to import the math module and replace index = self.Fx.index(int(x)) with index = 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