I'm seeing "TypeError: 'tuple' object does not support item assignment" on spyder

I'm seeing "TypeError: 'tuple' object does not support item assignment" on spyder

这到底是什么意思?我不应该使用 for 循环吗?我需要另一个元组吗?

对于上下文:我正在尝试使用 Huen 的方法求解 dydt=y/((t+1)**2),在 t=0,0.2,0.4,0.6 时步长 h=0.2

#import libraries
import numpy as np
import matplotlib.pyplot as plt

def dydt(t,y):
    dfdt = y / ((t + 1) ** 2)
    return dfdt

def IVPsolver2(dydt_fun, y0, t0, t1, t2, tf, h):
    n = 50 #points
    h = (tf-t0)/(n-1) #step size
    t = np.linspace(t0,t1,t2,tf,n)
    y = np.zeros(n) #preallocate zeros
    yp = np.zeros(n)
    m = np.zeros(n)
    mc = np.zeros(n)
    yp[0] = y0 #first yp at y0
    y[0] = y0 #y is 0
    t[0] = 0 #t is 0
    for i in range(0,n-1):
        m[i] = dydt_fun(t[i-1],y[i-1]) #calculating slope
        yp[i] = y[i] + m[i]*h #calculating predicted y at slope y
        mc[i] = dydt_fun(t[i+1],yp[i]) #slope corrector, 2 step
        t[i+1] = t[i] + h #t going by stepsize
        y[i+1] = y[i] + ((m[i]+mc[i])/2)*h #corrected y
    return t, y

def main(): #plotting  
    x2, y2 = IVPsolver2(dydt, 1, 0, 0.2, 0.4, 0.6, 0.2)
    plt.plot(x2,y2, 'o', mfc = 'purple')

    return
main()

问题出在您的 np.linspace 语句上。这是 linspace 的文档。语法是:numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)。所以你只需要给出起点和终点,以及你想要的间隔数。所以在将你的程序更改为这个之后:

import numpy as np
import matplotlib.pyplot as plt

def dydt(t,y):
    dfdt = y / ((t + 1) ** 2)
    return dfdt

def IVPsolver2(dydt_fun, y0, t0, t1, t2, tf, h):
    n = 50 #points
    h = (tf-t0)/(n-1) #step size
    t = np.linspace(t0,tf,n) # <----- see change here ---- 
    y = np.zeros(n) #preallocate zeros
    yp = np.zeros(n)
    m = np.zeros(n)
    mc = np.zeros(n)
    yp[0] = y0 #first yp at y0
    y[0] = y0 #y is 0
    t[0] = 0 #t is 0
    for i in range(0,n-1):
        m[i] = dydt_fun(t[i-1],y[i-1]) #calculating slope
        yp[i] = y[i] + m[i]*h #calculating predicted y at slope y
        mc[i] = dydt_fun(t[i+1],yp[i]) #slope corrector, 2 step
        t[i+1] = t[i] + h #t going by stepsize
        y[i+1] = y[i] + ((m[i]+mc[i])/2)*h #corrected y
    return t, y

def main(): #plotting  
    x2, y2 = IVPsolver2(dydt, 1, 0, 0.2, 0.4, 0.6, 0.2)
    plt.plot(x2,y2, 'o', mfc = 'purple')
    plt.show()
    return
main()

你的程序给出了这个:

您可以随心所欲地使用 linspace,以满足您的标准。

Karl Heun 的梯形法(1900 年出版)是一种一步法。这意味着在 y[i+1] 的计算中,您只使用 t[i] 时的数据 y[i],循环中不应有 y[i-1]

此外,不需要 yp, m, mp 作为数组,因为在步骤中只使用步骤本地值,其他地方都没有。

对于接口,接受任意时间数组是有意义的,因为单步方法特别适合具有可变步长(即使作为特殊情况传递的数组具有恒定步长)。然后,这也允许以类似于 odeint.

的方式从 return 值中删除时间数组
def IVPsolver2(dydt_fun, y0, t):
    y = np.zeros(len(t)) #preallocate zeros
    y[0] = y0 #y is 0
    for i in range(0,len(t)-1):
        h = t[i+1] - t[i];
        m = dydt_fun(t[i],y[i]) #calculating slope
        yp = y[i] + m*h #calculating predicted y at slope y
        mc = dydt_fun(t[i+1],yp) #slope corrector, 2 step
        y[i+1] = y[i] + ((m+mc)/2)*h #corrected y
    return y

如果要在过程中保留时间数组构造,只需传递 t0, tf, h 并使用

t = np.arange(t0,tf+0.1*h, h);

增加的最终值需要在数组中具有接近 tf 的值,因为在构造算术序列时并不总是自动出现舍入误差,即使 [=20] =]是正等差数列的一个元素。

最后,您可以将此方法两次应用于给定的采样时间序列和更密集的序列,以提供更精确的解决方案

x1 = np.linspace(0,1,5+1);
y1 = IVPsolver2(dydt, 1, x1);
x2 = np.linspace(0,1,5*10+1);
y2 = IVPsolver2(dydt, 1, x2);
xe = np.linspace(t0,tf,152);
ye = np.exp(1-1/(1+xe));
plt.plot(xe,ye,c='lightgray', lw=6)
plt.plot(x2,y2, 'o', mfc = 'purple', ms=2)
plt.plot(x1,y1, '-o', mfc = 'red', ms=4)
plt.show()