acturtle / cashflower

An open-source Python framework for actuarial cash flow models
https://cashflower.acturtle.com
MIT License
38 stars 9 forks source link

Check the call of my_var(-1) #350

Closed zchmielewska closed 9 months ago

zchmielewska commented 9 months ago

Check what happens if the model calls my_var(-1).

In Python, the negative index returns values from the list counting backwards. Results of a variable have a form of a list/array so it might be the same case.

my_lst = [1, 2, 3]
print(my_lst[-1])
# prints 3

To solve it, we need to unfortunately check it or solve it knowing the calculation direction. For example:

# Negative index represents counting backward from the end, so it doesn't raise any error
if t < 0:
    raise IndexError("")
zchmielewska commented 9 months ago

In terms of a single variable - a situation where this can happen is:

@variable()
def my_var(t):
    return my_var(t-1)

so in fact for t=0 there should be an error because there is no my_var(-1) but the package does not throw any error currently.

This is because results are initialized with np.empty which means that the results are filled with whatever is in the memory and for my_var(-1) the last value from results is taken.

I think we have two options:

  1. Add an if-statement checking if t>=0 but that's a bummer in terms of speed.
  2. Initialize results with np.zeros, then at least we have more sensible results (always zeros rather than some trash from the memory) - np.zeros is also slower than np.empty but better than if-statement.
zchmielewska commented 9 months ago

In terms of a cycle - this is a nice example:

@variable()
def a(t):
    return b(t-1)

@variable()
def b(t):
    return t
settings = {
    "T_MAX_CALCULATION": 3,
}

gives:

t,b,a
0,0.0,3.0
1,1.0,0.0
2,2.0,1.0
3,3.0,2.0

which is indeed a bug.

So, I'm afraid we need to add the check for t>=0.

zchmielewska commented 9 months ago

Implemented in 7fc9c19809fd721ea7e64b3e1edcb35dc1579cd1