Jupyter Notebook中Pyplot滑块无法更新绘图曲线的问题排查
四阶Runge-Kutta(RK4)求解ODE系统的交互式滑块修复
我使用四阶Runge-Kutta(RK4)方法近似求解一阶常微分方程(ODE)系统,RK4实现生成的绘图形态正确,但该方法依赖常数c、d、h,我希望通过滑块交互调整这些常数以观察解的变化。目前滑块可拖动但绘图不更新,已为c滑块绑定Slider.on_changed事件,重新调用RK4并设置曲线数据,但无效果且无报错。参考Matplotlib官方滑块示例在环境中可正常运行,排除环境交互问题。
最终定位到两个核心问题:
- 曲线实例化方式错误
- RK4未正确传递滑块参数
初始代码
%matplotlib notebook import matplotlib.pyplot as plt from matplotlib.widgets import Slider, Button import math y_inits = [95, 5, 0] c = 1 d = 5 fStepSize = 0.01 iLower = 0 iUpper = 1 tDerivatives = [ lambda t, y1, y2, y3: -c*y1*y2, lambda t, y1, y2, y3: (c*y1*y2) - (d*y2), lambda t, y1, y2, y3: d*y2 ] tColors = ["blue", "red", "yellow", "green", "black", "purple"] def RK4(c, d, fStepSize): tY_est = [ [y_inits[i]] for i in range(len(tDerivatives)) ] tT = [iLower] iRange = iUpper - iLower n = math.ceil(iRange / fStepSize) for i in range(n+1)[1:]: fT_last = tT[i-1] fT_new = fT_last + fStepSize tK = [] for j in range(len(tDerivatives)): Derivative = tDerivatives[j] fK1 = fStepSize * Derivative(fT_last, *[tY_est[k][i-1] for k in range(len(tY_est))]) tK.append(["y'"+str(j+1), fK1]) for j in range(len(tDerivatives)): Derivative = tDerivatives[j] fK2 = fStepSize * Derivative(fT_last + (fStepSize/2), *[tY_est[k][i-1] + (tK[k][1]/2) for k in range(len(tY_est))]) tK[j].append(fK2) for j in range(len(tDerivatives)): Derivative = tDerivatives[j] fK3 = fStepSize * Derivative(fT_last + (fStepSize/2), *[tY_est[k][i-1] + (tK[k][2]/2) for k in range(len(tY_est))]) tK[j].append(fK3) for j in range(len(tDerivatives)): Derivative = tDerivatives[j] fK4 = fStepSize * Derivative(fT_new, *[tY_est[k][i-1] + tK[k][3] for k in range(len(tY_est))]) tK[j].append(fK4) for j in range(len(tY_est)): fY_est_new = tY_est[j][i-1] + (( tK[j][1] + (2*tK[j][2]) + (2*tK[j][3]) + tK[j][4] )/6) tY_est[j].append(fY_est_new) tT.append(fT_new) return tT, tY_est fig, ax = plt.subplots() plt.subplots_adjust(left=0.25, bottom=0.25) tT_init, tY_est_init = RK4(c, d, fStepSize) tPlots = [ ax.plot(tT_init, tY_est_init[i], marker=".", color=tColors[i]) for i in range(len(tDerivatives)) ] plt.xlabel('t') plt.ylabel('y(t)') plt.title('h = '+str(fStepSize)) axfreq = fig.add_axes([0.25, 0.1, 0.65, 0.03]) c_slider = Slider( ax=axfreq, label='c', valmin=0.1, valmax=30, valinit=c, ) def Update(val): tT, tY_est = RK4(c_slider.val, d, fStepSize) for i in range(len(tPlots)): tPlots[i].set_data(tT, tY_est[i]) fig.canvas.draw() c_slider.on_changed(Update)
修正后的完整代码
%matplotlib notebook import matplotlib.pyplot as plt from matplotlib.widgets import Slider, Button import math y_inits = [95, 5, 0] c_init = 1 d_init = 5 fStepSize = 0.01 iLower = 0 iUpper = 1 tDerivatives = [ lambda c, d, t, y1, y2, y3: -c*y1*y2, lambda c, d, t, y1, y2, y3: (c*y1*y2) - (d*y2), lambda c, d, t, y1, y2, y3: d*y2 ] tColors = ["blue", "red", "yellow", "green", "black", "purple"] def RK4(c, d, fStepSize): tY_est = [ [y_inits[i]] for i in range(len(tDerivatives)) ] tT = [iLower] iRange = iUpper - iLower n = math.ceil(iRange / fStepSize) for i in range(n+1)[1:]: fT_last = tT[i-1] fT_new = fT_last + fStepSize tK = [] for j in range(len(tDerivatives)): Derivative = tDerivatives[j] fK1 = fStepSize * Derivative(c, d, fT_last, *[tY_est[k][i-1] for k in range(len(tY_est))]) tK.append(["y'"+str(j+1), fK1]) for j in range(len(tDerivatives)): Derivative = tDerivatives[j] fK2 = fStepSize * Derivative(c, d, fT_last + (fStepSize/2), *[tY_est[k][i-1] + (tK[k][1]/2) for k in range(len(tY_est))]) tK[j].append(fK2) for j in range(len(tDerivatives)): Derivative = tDerivatives[j] fK3 = fStepSize * Derivative(c, d, fT_last + (fStepSize/2), *[tY_est[k][i-1] + (tK[k][2]/2) for k in range(len(tY_est))]) tK[j].append(fK3) for j in range(len(tDerivatives)): Derivative = tDerivatives[j] fK4 = fStepSize * Derivative(c, d, fT_new, *[tY_est[k][i-1] + tK[k][3] for k in range(len(tY_est))]) tK[j].append(fK4) for j in range(len(tY_est)): fY_est_new = tY_est[j][i-1] + (( tK[j][1] + (2*tK[j][2]) + (2*tK[j][3]) + tK[j][4] )/6) tY_est[j].append(fY_est_new) tT.append(fT_new) return tT, tY_est fig, ax = plt.subplots() plt.subplots_adjust(left=0.25, bottom=0.25) plt.xlabel('t') plt.ylabel('y(t)') plt.title('h = '+str(fStepSize)) c_slider = Slider( ax=fig.add_axes([0.25, 0.1, 0.65, 0.03]), label='c', valmin=0.1, valmax=5, valinit=c_init, ) d_slider = Slider( ax=fig.add_axes([0.25, 0.06, 0.65, 0.03]), label='d', valmin=0.1, valmax=10, valinit=d_init, ) h_slider = Slider( ax=fig.add_axes([0.25, 0.02, 0.65, 0.03]), label='h', valmin=0.001, valmax=0.1, valinit=fStepSize, ) tPlots = [ax.plot([], [], marker=".", color=tColors[i])[0] for i in range(len(tDerivatives))] def Update(val): fStepSize = h_slider.val tT, tY_est = RK4(c_slider.val, d_slider.val, fStepSize) for i in range(len(tPlots)): tPlots[i].set_data(tT, tY_est[i]) fig.canvas.draw_idle() ax.relim() ax.autoscale_view() c_slider.on_changed(Update) d_slider.on_changed(Update) h_slider.on_changed(Update) tT_init, tY_est_init = RK4(c_init, d_init, fStepSize) for i in range(len(tPlots)): tPlots[i].set_data(tT_init, tY_est_init[i]) ax.relim() ax.autoscale_view() plt.show()
内容的提问来源于stack exchange,提问作者Arcaeca
相关产品推荐
相关产品推荐

