Search code examples
pythonwhile-loopstring-length

While condition in python doest stop the loop when true


I made a loop that needs to stop once the list U has no values in it. Once it reaches that point, the loop doesnt stop and it gives an error, because there is a value by 0 (the len(U) in the last loop)

def ATC(instance,K):
    pi=[]
    U = [i for i in range(instance.jobs)]
    t=0
    p= sum(instance.pt) / len(U)
    while len(U)!=0:
        I=[]
        for j in U:
            I.append((instance.w[j]/instance.pt[j])*exp(-(max(instance.dd[j]-instance.pt[j]-t,0))/(K*p)))
        k = np.argmax(I)        
        pi.append(U[k])         
        U.pop(k)                
        print(U,len(U))
        t = instance.Cmax(pi)         
        p = sum([instance.pt[i] for i in U])/len(U) ################################
        obj = instance.SumWjTj(pi)
    return pi,obj

enter image description here

Here the print of the list U and len(U) during the loop, showing it reaches 0 but the while condition doesnt work:

[0, 1, 2, 3, 4, 5, 7, 8, 9] 9
[0, 1, 2, 4, 5, 7, 8, 9] 8
[0, 1, 4, 5, 7, 8, 9] 7
[0, 1, 4, 7, 8, 9] 6
[0, 1, 4, 7, 9] 5
[0, 1, 4, 7] 4
[1, 4, 7] 3
[4, 7] 2
[7] 1
[] 0

Using a If len(U)!=0: p = sum([instance.pt[i] for i in U])/len(U) works, but I don't understand why the while isn't enough


Solution

  • The loop doesn't exit as soon as len(U) is zero and will go on to complete that current iteration of the loop. So, in your case, once U is empty it will still try do the lines:

    t = instance.Cmax(pi)         
    p = sum([instance.pt[i] for i in U])/len(U) ################################
    obj = instance.SumWjTj(pi)
    

    before it re-tests for len(U)!=0 and exits. So, when calculating p it'll try and divide by zero, which I assume is the error you are getting.

    Instead you could put a break clause in your loop like:

    while True:
        I=[]
        for j in U:
            I.append((instance.w[j]/instance.pt[j])*exp(-(max(instance.dd[j]-instance.pt[j]-t,0))/(K*p)))
        k = np.argmax(I)        
        pi.append(U[k])         
        U.pop(k)                
        print(U,len(U))
    
        # break out the loop here
        if len(U) == 0:
            break
    
        t = instance.Cmax(pi)         
        p = sum([instance.pt[i] for i in U])/len(U) ################################
        obj = instance.SumWjTj(pi)