0

So, my professor asked me to create a program that will use the Runge-Kutta Method (2nd order) to solve the problem. But I get an IndexError: list index out of range which goes back to my first function. I don't completely understand what is the mistake here and will be glad if someone explained it to me

import numpy as np

def f(a, rec, inf, j, b, q):
    f = b*(1-inf[j]-rec[j])*(a[j][0]*inf[0]+a[j][1]*inf[1]+a[j][2]*inf[2]+a[j][3]*inf[3]+a[j][4]*inf[4]+a[j][5]*inf[5]+a[j][6]*inf[6]+a[j][7]*inf[7]+a[j][8]*inf[8]+a[j][9]*inf[9]) - q*inf[j]
    return f

def rk2a(I, R, b, q):
    beta = b
    sigma = q
    I.astype(float)
    R.astype(float)
    n = len(I)
    S = 1 - I - R
    A = np.array([[0,1,1,1,0,0,0,0,0,0], 
    [1,0,1,1,1,0,0,0,0,0],
    [1,1,0,1,1,1,0,0,0,0],
    [1,1,1,0,1,1,1,0,0,0],
    [0,1,1,1,0,1,1,1,0,0],
    [0,0,1,1,1,0,1,1,1,0],
    [0,0,0,1,1,1,0,1,1,1],
    [0,0,0,0,1,1,1,0,1,0],
    [0,0,0,0,0,1,1,1,0,1],
    [0,0,0,0,0,0,1,0,1,0]])
    y_coef = []
    old_I = []
    for i in range(0,50,1):
        print(I.transpose())
        for j in range(0,n-1,1):
            k1 = f(A,R,I,j,beta,sigma)
            y_coef.append(I[j])
            old_I.append(I[j])
            y_coef[j] = I[j]+(k1/2)
            k2 = f(A, R, y_coef, j, beta, sigma)
            I[j] = old_I[j] + k2
        return None

infect = np.array([0, 1, 0, 0, 0, 0, 0, 1, 0, 0]) 
recov = np.array([0,0, 0, 0, 0, 0, 0, 0, 0, 0]) 
rk2a(infect, recov, 0.3, 0.1)
Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51
  • 2
    Use pdb and step thru your code. You are accessing an array index that does not exist. – sureshvv Apr 29 '20 at 07:25
  • Can you clarify which part you’re struggling with? Have you done any debugging? – AMC Apr 29 '20 at 07:52
  • Is your model correct? As implemented, by the structure of `A` infection only happens from carriers from the 3 locations to each side, never from the same location. The initial condition is that 2 locations are completely 100% infected. – Lutz Lehmann Apr 30 '20 at 09:22

2 Answers2

0

try run with:

def f(a, rec, inf, j, b, q):
    print('---- DEBUG -----')
    print('a', a, 'rec', rec, 'inf', inf, 'j', j, 'b', b, 'q', q, sep="\n")
    print('---------------')
    f = b*(1-inf[j])*(a[j][0]*inf[0]+a[j][1]*inf[1]+a[j][2]*inf[2]+a[j][3]*inf[3]+a[j][4]*inf[4]+a[j][5]*inf[5]+a[j][6]*inf[6]+a[j][7]*inf[7]+a[j][8]*inf[8]+a[j][9]*inf[9]) - q*inf[j]
    return f

you are passing a inf array wrong...

Daniel A R F
  • 127
  • 7
0

Leave the indices out totally. All numpy array arithmetic operations are cell-by-cell. The linear-algebraic matrix-vector product is numpy.dot or the .dot method of arrays. So you could rewrite

def f(inf, rec, A,b,q)
    susc = 1-inf-rec           # computes the susceptibles in every node
    trans = b*susc*A.dot(inf)  # newly infected in time span
    recov = q*inf              # recovered in time span
    return trans-recov, recov

and then iterate

for t in time[:-1]:
    k1i, k1r = f(inf,rec,A,b,q)
    k2i, k2r = f(inf+k1i*dt/2,rec+k1r*dt/2,A,b,q)
    inf, rec = inf + k2i*dt, rec+k2r*dt
    I.append(inf); R.append(rec);
Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51