用matplotlib动画库制作二等分方法的动画

n7taea2i  于 2023-05-18  发布在  其他
关注(0)|答案(3)|浏览(138)

我对数学演示很感兴趣。目前,我正在研究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()

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

xxslljrj

xxslljrj1#

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

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()
vaqhlq81

vaqhlq812#

您可以简单地将代码更改为:plt.plot([a,a],[0,fa],color ='red',linestyle="--",hold=TRUE),这基本上允许您绘制多个点而不重置图,一旦您绘制了多次,您可以使用hold=FALSE重置。希望这有意义。

yacmzcpb

yacmzcpb3#

我详细阐述了一个类似的问题,并计算和可视化它。

import math
import plotly.graph_objs as go
import plotly.io as pio

def f(x):
    return math.pow(2,x) - 4*math.pow(x,2) + x + 3

def bisection(a,b,tol):
    k = 0
    ak = a
    bk = b
    xk = (ak + bk)/2
    fxk = f(xk)
    print("Bisection Table for Negative Root of f(x) = 2^x - 4x^2 + x + 3")
    print(f"{'k':<5}{'ak':<10}{'bk':<10}{'xk':<20}{'f(xk)':<20}")
    print("-" * 65)
    
    while abs(fxk) > tol:
        k += 1
        if fxk > 0:
            bk = xk
        else:
            ak = xk
        xk = (ak + bk)/2
        fxk = f(xk)
        print(f"{k:<5}{ak:<10.5f}{bk:<10.5f}{xk:<20.5f}{fxk:<20.5f}")

    return xk

xk = bisection(-1,0,0.05)
print("-" * 65)
print("The approximation of the negative root with error tolerance of 0.05 is:", xk)

# Create a trace for the function
x_values = list(range(-5,5))
y_values = [f(x) for x in x_values]
f_trace = go.Scatter(x=x_values, y=y_values, name="f(x)")

# Create a trace for the root
root_trace = go.Scatter(x=[xk], y=[0], mode="markers", marker=dict(size=10, color="red"), name="Root")

# Combine the traces into a figure
fig = go.Figure([f_trace, root_trace])
fig.update_layout(title="Graph of f(x) and Root Found by Bisection Method",
                  xaxis_title="x",
                  yaxis_title="f(x)")
pio.show(fig)

或者将计算结果也显示为图示:

import math
import plotly.graph_objs as go

def f(x):
    return math.pow(2,x) - 4*math.pow(x,2) + x + 3

def bisection(a,b,tol):
    k = 0
    ak = a
    bk = b
    xk = (ak + bk)/2
    fxk = f(xk)

    fig = go.Figure()

    # Create a trace for the function f(x)
    x_vals = [i/10 for i in range(-30, 31)]
    y_vals = [f(x) for x in x_vals]
    trace_f = go.Scatter(x=x_vals, y=y_vals, mode='lines', name='f(x)')

    # Create a trace for the initial interval [a,b]
    trace_ab = go.Scatter(x=[a, b], y=[0, 0], mode='markers+lines', name='[a,b]')

    # Add the two traces to the figure
    fig.add_trace(trace_f)
    fig.add_trace(trace_ab)

    # Compute the midpoints and add them to the figure as vertical lines
    while abs(fxk) > tol:
        k += 1
        if fxk > 0:
            bk = xk
        else:
            ak = xk
        xk = (ak + bk)/2
        fxk = f(xk)

        # Add a trace for the vertical line corresponding to the midpoint
        trace_xk = go.Scatter(x=[xk, xk], y=[-10, 10], mode='lines',
                              line=dict(color='black', dash='dash'), name=f'x{k}')

        # Add the midpoint trace to the figure
        fig.add_trace(trace_xk)

        # Add the midpoint label to the figure
        fig.add_annotation(x=xk, y=f(xk), text=f'x{k}', showarrow=True, arrowhead=1)

    # Add a trace for the final approximation
    trace_final = go.Scatter(x=[xk], y=[f(xk)], mode='markers', name='Final Approximation')

    # Add the final approximation trace to the figure
    fig.add_trace(trace_final)

    # Update the layout to show the title and axis labels
    fig.update_layout(title='Bisection Method Visualization', xaxis_title='x', yaxis_title='y')

    # Show the figure
    fig.show()

    return xk

xk = bisection(-1,0,0.05)
print("The approximation of the negative root with error tolerance of 0.05 is:", xk)

相关问题