Hello, I am trying to implement a version of the cubic spline based on the artilce here: Click Here and while implementing it I find errors that my indices are out or range such as:

h[i]=(n[i+1]-n[i]) IndexError: list index out of range

Here's a part of the code:

a=[None]*(len(m)+1)
b=[None]*(len(n))
d=[None]*(len(n))
h=[None]*(len(n))
g=[None]*(len(n)) #Alpha
lo=[None]*(len(m)+1)
mo=[None]*(len(m)+1) #Mu
zo=[None]*(len(m)+1)
c=[None]*(len(m)+1)

#Steps 1 and 2

for i in range(0, len(n)):
    h[i]=(n[i+1]-n[i])
for i in range(1, len(n)):
    g[i]=((3/h[i])*(a[i+1]-a[i])) - ((3/h[i-1])*(a[i]-a[i-1]))

The main thing that confuses me is that the program needs a cardinality of n+1 but I'm only getting N points and so how would I acocunt for that in my coding?

m and n are undefined, the loop until len(n) as n[len(n)] does not exist. Also limit of len(n) on second loop does not make sense, as n is not used in loop. Also len(a) is not len(n), but len(m)+1.

Your array of n has a maximum index of len(n) - 1. Your counter i ranges from 0 to len(n) - 1. So far so good. However, at line 14, you're trying to access the (i+1)th element of array n. What happens once i = len(n)-1? i would be equal to len(n), which exceeds the maximum available index of len(n)-1, hence the index out of range.

@pyTony I think m and n are already defined, just not included in the "part" of the code s/he posted here. I may be wrong though.

Edited 4 Years Ago by scudzilla

Thanks for the help scudzilla and pyTony. Well I again go through the loop only to find the same out of index issue as well as mixed type issues between indices:

for j in range(len(n)-1,0, -1):

    c[j]=zo[j]-mo[j]*c[j+1];
    b[j]=(a[j+1]-a[j])/h[j]-h[j]*(c[j+1] + 2*c[j])/3;
    d[j]=(c[j+1]-c[j])/(3*h[j]);

It looks like out of index occurs with mo. The mix type multiplication (int with nonetype) is with a, c as well as h.

Thanks for the help once again!

Do arrays m and n have fixed sizes? If so, what are the sizes? If not, is it possible for len(m) to be greater than or equal to len(n) - 2?

M and N do not have fixed lenghts but both of them are checked for the same lenght.

while mismatch == 1:
    x= (raw_input("Please enter the number the coords for x: "))
    x_new= list(map(int, x.split()))
    n=x_new

    y= (raw_input("Please enter the number the coords for y: "))
    y_new= list(map(int, y.split()))
    m= y_new
    if len(n) == len(m):
        mismatch = 0

That may happen but that's because I take in input but they should be the same.

Hmm lemme compile the code. Unfortunately I'll have to recreate the rest of the code so it'll take some time.

Edited 4 Years Ago by scudzilla

On second thought, it's not definite that I could recreate those errors in my own code. Is it possible for you to post the rest of the code?

from Tkinter import *
from array import *
mismatch = 1

#Enter the the values
while mismatch == 1:
    x= (raw_input("Please enter the number the coords for x: "))
    x_new= list(map(int, x.split()))
    n=x_new

    y= (raw_input("Please enter the number the coords for y: "))
    y_new= list(map(int, y.split()))
    m= y_new
    if len(n) == len(m):
        mismatch = 0
a=[None]*(len(m)+1)
b=[None]*(len(n))
d=[None]*(len(n))
h=[None]*(len(n))
g=[None]*(len(n)) #Alpha
lo=[None]*(len(m)+1)
mo=[None]*(len(m)+1) #Mu
zo=[None]*(len(m)+1)
c=[None]*(len(m)+1)

#Steps 1 and 2

for i in range(len(m)):
    a[i]=m[i]
    print a[i]

for i in range(0, len(n)-1):
    h[i]=(n[i]-n[i-1])
    print h[i]
for i in range(1, len(n)-1):
    g[i]=((3/h[i])*(a[i+1]-a[i])) - ((3/h[i-1])*(a[i]-a[i-1]))

#Step 3

lo[0]=1
mo[0]=0
zo[0]=0

#Step 4

for i in range(1, len(n)-1):
    print i
    lo[i]=2*(n[i+1] - n[i-1]) - (h[i-1]*mo[i-1])
    mo[i]=h[i]/lo[i]
    zo[i]=(g[i]-(h[i-1]*zo[i-1]))/lo[i]

#Step 5
nl =len(n)
lo[nl]=1
zo[nl]=0
c[len(n)]=0


#Step 6

for j in range(len(n)-1,0, -1):

    c[j]=zo[j]-mo[j]*c[j+1];
    b[j]=(a[j+1]-a[j])/h[j]-h[j]*(c[j+1] + 2*c[j])/3;
    d[j]=(c[j+1]-c[j])/(3*h[j]);

 master = Tk()
 w = Canvas(master, width=1280, height=720)
 w.pack()
 for i in range(1, len(n)):
    print a
    yp = a[i-1] + b[i-1]*n[i-1]+ c[i-1]*n[i-1]*n[i-1] + d[i-1]*n[i-1]*n[i-1]*n[i-1]
    xp = n[i-1]
    yc = a[i] + b[i]*n[i]+ c[i]*n[i]*n[i] + d[i]*n[i]*n[i]*n[i]
    xc = n[i]
    w.create_line(xp,yp,xc,yc, dash=(4,4))

 mainloop()

Edited 4 Years Ago by Kirielson

Strange, I'm not encountering any error, except the unindent issues at lines 63 to 66.

That's weird, can you resend what you have? Right now I'm using a Mac with python 2.6.

lines 10 and 11 are weird, as you leave the loop without announcement immediately, if user enter same number of values. So you reinput the values, if they are equally many. Also you prompt is to give a single value of how many values for m and how many for n you have, but you do split for the input and do not ask about the values for them. Also you need only one value as other is supposed to be same or maybe one one more than other.

After input you put len(m) or len(n) to length of values instead of int(m) and int(n), like you prompted, and they are quaranteed to be one value, but values of them are not checked: m could be 1 and n 1000 for example. Or they could be not but many values and then int() would fail. So clearly you expect not number of values like you asked but the values themselves in variables m and n.

Edited 4 Years Ago by pyTony

Let me see if I'm understanding this correctly:
A) There's no proper announcemt to the user that they entered the wrong values in the loop statement
B)I'm improperly using the split command to accept one user input when I'm accepting multiple user commands.

Edited 4 Years Ago by Kirielson

Oh, now I know why you're getting out of ranges and nonetype elements. You confused the element number with the length. Suppose you create a list x with length 5. Wouldn't the contents of x be (0 to 4)? Or to put it another way, if you create a list x with elements (0 to 5), wouldn't the length be 6? Meaning, for any list x with elements (0 to n), len(x) = n+1. Let's go over the steps in the wikipedia page (note in the following statements, I renamed your list n to list x to avoid confusion with the element n):

Step 1:
a)Create array a with size n+1 (n being the index), or in other words, with size len(x). But you defined a with size len(x)+1

Step 2: arrays b and d with size n, or len(x)-1. But you defined them with size len(x)

Step 3: array h with size n, or len(x)-1 - same as step 2

Step 4: array g with size n - same as step 2

Step 5: arrays c, lo, mo, zo with size n+1 or len(x) - same as step 1

Step 6: you've done it ok

Step 7: for i = 1,...,n-1 which translates to for i in range(1,len(x)-2) but you wrote for i in range(1,len(x)-1)

Step 8: lo(n), zo(n) and c(n) or lo(len(x)-1), zo(len(x)-1) and c(len(x)-1) respectively, but you wrote lines 50 to 52 instead

Step 9: for j = n-1, n-2,...,0 which translates to for j in range(len(x)-2,-1,-1) but you wrote line 57 instead.

Hmm I think that's all. lol. Confusing, right?

Edited 4 Years Ago by scudzilla

And it would be more clear to use directly tuples, not the way wikipedia says it. It is natural that you should have equal number of each item which goes to the tuple.

Both Scudzilla and pyTom, thanks for helping. There's only one more problem, I'll post the code:

for j in range(len(n)-2,-1, -1):

    c[j]=zo[j]-mo[j-1]*c[j+1];
    b[j]=(a[j+1]-a[j])/h[j]-(h[j]*(c[j+1] + 2*c[j])/3);
    d[j]=(c[j+1]-c[j])/(3*h[j]);

Traceback (most recent call last):
File "inter.py", line 63, in <module>
c[j]=zo[j]-mo[j-1]*c[j+1];
TypeError: unsupported operand type(s) for -: 'NoneType' and 'float'

Edited 4 Years Ago by Kirielson: Excessive Code

This question has already been answered. Start a new discussion instead.