1

I have an original matrix

originalOD = np.array([[1,2,4], [3,2,3], [4,2,2]])

#### Now we can sum productions and attractions####
originalD=np.sum(originalOD,axis=0)
originalO=np.sum(originalOD,axis=1)

And would like to have original and original to converge to:

targetD=np.array([16,9,9])
targetO=np.array([14,8,12])

which I am trying to do in a loop using some converge criteria:

Convergence=0
while True: 
        xD=targetD/originalD
        newOD=originalOD*xD
        newD=np.sum(newOD,axis=0)
        xO=targetO/originalO
        newOD=originalOD*xO
        newO=np.sum(newOD,axis=1)

        Convergence = (sum(newO)/sum(targetO)+sum(newD)/sum(targetD))/2

        print('Converged:', Convergence)
        if Convergence<1.01 and Convergence>0.99:
            break
        else:
            continue

It is running, but it seems like the xD and xO are not changing in the subsequent loops, i.e.

Converged: 1.0220588235294117
Converged: 1.0220588235294117
Converged: 1.0220588235294117
Converged: 1.0220588235294117

Any ideas on what to change in the code?

  • your convergence measures are not using anything you are changing in the loop. So they are also not changing – KPLauritzen Sep 12 '19 at 09:09
  • @KPLauritzen Thanks - that was a helpful remark! I have now modified, but still not managing to change anything in the subsequent loops. – Kacper Rossa Sep 12 '19 at 11:49
  • Is there a reason you're using a loop for this? – Mad Physicist Sep 12 '19 at 11:59
  • @MadPhysicist Thanks for that! Yes - I've got a matrix of trips between zones (i.e. originalOD) and I also know what the total trips from and to zones have to be, i.e. targetD and targetO. That's why I'm trying to modify the original matrix so that it can match the target values. – Kacper Rossa Sep 12 '19 at 12:13

2 Answers2

1

Looks like you are failing to update the matrix (OD) and origin and destination totals within the while loop so currently on each loop you are just applying the same factors derived from the original matrix. Try the following:

newOD=originalOD
newD=np.sum(newOD,axis=0)
newO=np.sum(newOD,axis=1)
Convergence=0
while True: 
    xD=targetD/newD
    newOD=newOD*xD
    newD=np.sum(newOD,axis=0)
    xO=targetO/newO
    newOD=newOD*xO
    newO=np.sum(newOD,axis=1)

    Convergence = (sum(newO)/sum(targetO)+sum(newD)/sum(targetD))/2

    print('Converged:', Convergence)
    if Convergence<1.01 and Convergence>0.99:
        break
    else:
        continue

You also may want to consider adding a maximum number of iterations to your calculation as furness is not guaranteed to converge, especially if you have a sparse matrix.

0

Furness algorithm:

def Furness(originalOD,targetD,targetO):
    #balance
    
    targetD = np.sum(targetO)/np.sum(targetD) * targetD
    
    #Furness
    
    newOD=originalOD
    newD=np.sum(newOD,axis=0)
    newO=np.sum(newOD,axis=1)
    Error=1
    while True: 
        xD=targetD/newD
        newOD=newOD*xD
        newD=np.sum(newOD,axis=0)
        newO=np.sum(newOD,axis=1)
        Error = (sum(abs(newO-targetO))+sum(abs(newD-targetD)))/sum(newD)
        print('Error:', Error)
        if abs(Error)<0.01:
            break

        xO=targetO/newO
        newOD=(newOD.T*xO).T
        newO=np.sum(newOD,axis=1)
        newD=np.sum(newOD,axis=0)

        Error = (sum(abs(newO-targetO))+sum(abs(newD-targetD)))/sum(newD)
        print('Error:', Error)
        if abs(Error)<0.01:
            break
        print(xO[0],xD[0])    
    return newOD,round(abs(Error)*100,3)