2

I have got this code to solve Newton's method. But it gives a zero division error. I cannot figure out what is wrong. Thank you.

import copy

tlist = [0.0, 0.12, 0.16, 0.2, 0.31, 0.34] # list of start time for the phonemes

w = w1 = w2 = w3 = w = 5

def time() :
    frame = 0.04
    for i, start_time in enumerate(tlist) :
        end_time = tlist[i]
        frame = frame * (i + 1)
        poly = poly_coeff(start_time, end_time, frame)
        Newton(poly) 

def poly_coeff(stime, etime, f) :
    """The equation is k6 * u^3 + k5 * u^2 + k4 * u + k0 = 0. Computing the coefficients for this polynomial."""
    """Substituting the required values we get the coefficients."""
    t_u = f
    t0 = stime
    t3 = etime
    t1 = t2 = (stime + etime) / 2
    w0 = w1 = w2 = w3 = w
    k0 = w0 * (t_u - t0)
    k1 = w1 * (t_u - t1)
    k2 = w2 * (t_u - t2)
    k3 = w3 * (t_u - t3)
    k4 = 3 * (k1 - k0)
    k5 = 3 * (k2 - 2 * k1 + k0)
    k6 = k3 - 3 * k2 + 3 * k1 -k0 

    return [[k6,3], [k5,2], [k4,1], [k0,0]]

def poly_differentiate(poly):
    """ Differentiate polynomial. """
    newlist = copy.deepcopy(poly)

    for term in newlist:
        term[0] *= term[1]
        term[1] -= 1

    return newlist

def poly_substitute(poly, x):
    """ Apply value to polynomial. """
    sum = 0.0 

    for term in poly:
        sum += term[0] * (x ** term[1])
    return sum

def Newton(poly):
    """ Returns a root of the polynomial"""
    poly_diff = poly_differentiate(poly) 
    counter = 0
    epsilon = 0.000000000001

    x = float(raw_input("Enter initial guess:"))

    while True:
        x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
        counter += 1
        if abs(x_n - x) < epsilon :
            break
        x = x_n
    print "Number of iterations:", counter
    print "The actual root is:", x_n
    return x_n

if __name__ == "__main__" :
    time()
Enter initial guess:0.5
Traceback (most recent call last):
  File "newton.py", line 79, in <module>
    time()
  File "newton.py", line 18, in time
    Newton(poly) 
  File "newton.py", line 67, in Newton
    x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
ZeroDivisionError: float division
Josh Lee
  • 149,877
  • 34
  • 253
  • 263
zingy
  • 791
  • 8
  • 18
  • 33

3 Answers3

6

You have a basic bug here:

for i, start_time in enumerate(tlist):
    end_time = tlist[i]

Because of the nature of enumerate, start_time and end_time have the same value. This means that poly_coeff will return [[0,3], [0,2], [0,1], [0,0]] every time. When this result is passed (through Newton) into poly_differentiate, the result will be [[0,2], [0,1], [0,0], [0,-1]].

This result, passed into poly_substitute will yield a sum of ZERO, because you multiply all list entries by term[0] (which happens to be zero) before summing them. Then, you divide - by zero.

SOLUTION (edited per your comment):

Use the correct start_time and end_time values. It looks like you want end_time = tlist[i+1]. The edge condition of this is to break out without evaluating the final list entry. What you really want is this:

for i, start_time in enumerate(tlist[:-1]):
    end_time = tlist[i+1]
Nate
  • 11,467
  • 5
  • 42
  • 59
  • The start time for the first iteration should be 0.0 and end time should be the next value which is 0.12. Then in the next iteration the start time would be 0.12 and the end time the number next to it which is 0.16 and so on.. – zingy Aug 12 '11 at 15:01
  • Note that, although this should fix this *specific* exception, I think your code might have some other, subtle issues. I've seen a lot of your questions (many of which seem to revolve around this phoneme problem - a project of yours?), and although you're moving in a better direction, I would like to encourage you to take the time out to learn good debugging techniques, and to get a solid understanding of the fundamentals of software engineering. They will be indispensable as you move forward, and will lead you toward creating more robust, capable designs in the future. – Nate Aug 12 '11 at 15:12
  • Thank you very much for the suggestion. I know I am not a programmer. Its the part of the project so I have to do it. But in future I would not dive into something I don't know before learning it well. Like you said this solved the problem. – zingy Aug 12 '11 at 15:30
3

I have copied your code and tried to debug it a bit.

In general it is because your code returns a zero value and then tried to use it during dividing.

If you will carefully review your code you will find that the following loop:

for i, start_time in enumerate(tlist) :
        end_time = tlist[i]

will give you start_time == 0.0 and endTime == 0.0 on the first iteration.

This leads the following line:

poly = poly_coeff(start_time, end_time, frame)

To return you:

>>> [[0.0, 3], [0.0, 2], [0.0, 1], [0.2, 0]]

This cause:

poly_substitute(poly_diff, x)

where you are using the following loop:

for term in poly:
    sum += term[0] * (x ** term[1])

to return you a zero since you are multiplying only zeroes.

So then you are trying to delete on 0 and getting a mentioned exception.

This means that if you will modify your code to safely check and set endTime to tList[i+1] you will eliminate this error - don't forget to check on 'i+1

Artsiom Rudzenka
  • 24,197
  • 3
  • 30
  • 49
  • Thank you. The start value and end value should be 0.0 and 0.12 for the first iteration which I have surely coded it wrong. – zingy Aug 12 '11 at 15:07
0

At the first sight

 poly_substitue(poly_diff,x) 

seems to be zero for a special x. Try to track the iteration by printing x before each update.

But I think the Exception is caused by a bug in your code: as the absolute coeff C*X^0 in a polynomial is differentiated to 0 * X^-1 your poly_substitute raises a ZeroDivisionException when x=0.

rocksportrocker
  • 6,639
  • 2
  • 28
  • 46