使用 matplotlib 动画库动画二分法

Animating bisection method with matplotlib animation library

我对数学演示很感兴趣。目前我正在研究 python 中数值方法的可视化,特别是二分法。以下是我到目前为止编写的代码。

import matplotlib.pyplot as plt 
import matplotlib.animation as animation
import numpy as np 

def sgn(x):
    if x > 0:
        return 1
    elif x < 0:
        return -1
    else:
        return 0

def bisect(f,a,b):
    fa = f(a)
    fb = f(b)
    p = a+(b-a)/2
    fp = f(p)
    if sgn(fa) == sgn(fp):
        return p, fp, b, fb
    else:
        return a, fa, p, fp

def f(x):
    return x**2-3

a, b = 1, 2

plt.figure()
plt.subplot(111)

a, fa, b, fb = bisect(f,a,b)
vf = np.vectorize(f)
x = np.linspace(a,b)
y = vf(x)

plt.plot(x, y, color='blue')
plt.plot([a,a], [0,fa], color='red', linestyle="--")
plt.plot([b,b], [0,fb], color='red', linestyle="--")
plt.grid()
plt.show()

我有三个问题想解决。首先,我希望能够多次调用 bisect 函数,每次我都想用新数据重新绘制绘图。其次,我想在应用 bisect 函数指定次数后重新启动动画。第三,我想在调用二分法之前保留图形的原始轴,即我想将 x 范围保持为 [1,2],将 y 范围保持为 $[-2,1]$。任何帮助将不胜感激。

您只需将代码更改为: plt.plot([a,a], [0,fa], color='red', linestyle="--",hold=TRUE) 这基本上允许您在不重置绘图的情况下绘制多个点一旦你绘制了很多次,你就可以使用 hold=FALSE 重置。希望这是有道理的。

通过反复试验,我找到了解决问题的方法。

import matplotlib.pyplot as plt 
from matplotlib import animation
import numpy as np 

def sgn(x):
    if x > 0:
        return 1
    elif x < 0:
        return -1
    else:
        return 0

def bisect(f,a,b):
    fa = f(a)
    fb = f(b)
    p = a+(b-a)/2
    fp = f(p)
    if sgn(fa) == sgn(fp):
        return p, b
    else:
        return a, p

def bisection_method(f,a,b,n):
    for i in range(n):
        a,b = bisect(f,a,b)
    return a,b

def f(x):
    return x**2-3

xmin, xmax = 1, 2
yrange = f(xmin), f(xmax)
ymin, ymax = min(yrange), max(yrange) 
vf = np.vectorize(f)
x = np.linspace(xmin,xmax)
y = vf(x)
epsilon = 0.1
# Initialize figure
fig = plt.figure()
ax = plt.axes(xlim=(xmin-epsilon,xmax+epsilon), ylim=(ymin,ymax))
curve, = ax.plot([],[], color='blue')
left, = ax.plot([],[],color='red')
right, = ax.plot([],[],color='red')

# Figure reset between frames
def init():
    left.set_data([],[])
    right.set_data([],[])
    curve.set_data([],[])
    return left, right, curve,

# Animation of bisection
def animate(i):
    a, b = bisection_method(f,xmin,xmax,i)
    left.set_data([a,a],[ymin,ymax])
    right.set_data([b,b],[ymin,ymax])
    curve.set_data(x,y)
    return left, right, curve,

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=15, interval=700, blit=True)

plt.grid()
plt.show()