如果我想绘制一个函数的曲线,比如 1/x,在 0.1 到 10 之间,我可以这样做:
xx = np.linspace(0.1,10,1000)
yy = 1.0/xx
plt.plot(xx,yy)
问题在于点之间的间距沿着曲线不平衡。具体来说,在曲线左侧,即 x
如何创建数组
xx
和 yy
(一般来说,不仅针对此特定函数),使得整个曲线上相邻点之间的间距相似?
如果评论中的解决方案不是您想要的,这里还有其他一些选择横坐标,使得点之间的距离沿着曲线是恒定的。它们都会生成与此在视觉上相似的图。
使用样条线:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import CubicSpline, PchipInterpolator
def f(x):
return 1/x
a, b = 0.1, 10
n = 100 # use more points for improved accuracy
# Generate interpolant for the curve and its derivative
# If you have the derivative, use it instead of dydx_spline
x0 = np.linspace(a, b, n)
y0 = f(x0)
y_spline = CubicSpline(x0, y0, extrapolate=False)
dydx_spline = y_spline.derivative()
# Generate interpolant for arc length `s` as function of `x`
dsdx = np.sqrt(1 + dydx_spline(x0)**2)
dsdx_spline = PchipInterpolator(x0, dsdx, extrapolate=False) # Pchip is monotonic
s_spline = dsdx_spline.antiderivative()
# Solve for `x` at specified arc distances
s = np.linspace(0, s_spline(b), 10)
x = np.asarray([a] + [s_spline.solve(si)[0] for si in s[1:-1]] + [b])
y = f(x)
# Plot the results
plt.plot(x0, y0, '-')
plt.plot(x, y, '*')
通过查找初始值问题的事件
from scipy.integrate import solve_ivp
# Assume we have the derivative of the function
# If not, we can use the spline approach above or use numerical differentiation
dydx = dydx_spline
def dsdx(x, s):
# derivative of arc length s with respect to x
return np.sqrt(1 + dydx(x)**2)
def event(x, s):
# event function crosses 0 when arc length is a multiple of ds
return (s - ds/2) % ds - ds/2
event.direction = 1
ds = s[1] - s[0]
sol = solve_ivp(dsdx, y0=np.asarray([0]), t_span=(x[0], x[-1]),
max_step=0.001, events=event)
x = np.ravel(sol.t_events)
x = np.append(x, b)
y = f(x)
# Plot the results
plt.plot(x0, y0, '-')
plt.plot(x, y, '*')
一个非常直接的解决方案。私有函数在 SciPy 1.11 中不可用,但它们将在 SciPy 1.12 中可用(您现在可以使用
https://anaconda.org/scientific-python-nightly-wheels/scipy
获得)。
<to be posted shortly>