问题描述:
已知两个平面曲线点集,一个取自y=x**2-2,x的区间为[-4,4],此点集存在列表X1,Y1中,另外一个取自y=-2*x,x的区间为[-5,5],此点集存在列表X2,Y2中,两条曲线将平面分成几个部分,现在要求两条曲线下面空间的边界线(包络线)。
方法:
为了找到两条离散曲线下的边界线,我们可以使用一种贪心算法,从左到右扫描,对于每个x值,我们检查两条曲线上的y值,选择较低的那个作为边界线上的点。由于两条曲线是离散的,同一个x值可能不对应两条曲线上的点,所以我们需要对曲线进行插值,以确保我们可以在任意x值上找到边界线上的点。
代码实现:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
# 定义x的区间和对应的y值
x1 = np.linspace(-4, 4, 400)
y1 = x1**2 - 2
x2 = np.linspace(-5, 5, 400)
y2 = -2 * x2
# 创建插值函数
interp_y1 = interp1d(x1, y1, kind='cubic', fill_value='extrapolate')
interp_y2 = interp1d(x2, y2, kind='cubic', fill_value='extrapolate')
# 定义一个较大的x区间用于扫描
x_scan = np.linspace(min(min(x1), min(x2)), max(max(x1), max(x2)), 1000)
# 找到边界线上的点
y_boundary = np.zeros_like(x_scan)
for i, x in enumerate(x_scan):
y_boundary[i] = min(interp_y1(x), interp_y2(x))
# 绘制曲线和边界线
plt.figure(figsize=(8, 6))
plt.plot(x1, y1, label='y = x**2 - 2')
plt.plot(x2, y2, label='y = -2*x')
plt.plot(x_scan, y_boundary, label='Boundary Line', color='red')
# 标记出边界线上的点
plt.plot(x_scan, y_boundary, 'ro')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.title('Boundary Line between Two Curves')
plt.grid(True)
plt.show()
优化后:
在下面优化后的代码中,我们使用 np.minimum 函数一次性比较了 interp_y1(x_scan) 和 interp_y2(x_scan) 的结果,从而避免了循环。这种方法利用了NumPy的向量化操作,可以显著提高性能,因为它减少了Python层面的循环,并利用了底层的优化。
此外,我们移除了 np.zeros_like 的使用,因为 np.minimum 函数直接返回了一个包含所需结果的数组。
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
# 定义x的区间和对应的y值
x1 = np.linspace(-4, 4, 400)
y1 = x1**2 - 2
x2 = np.linspace(-5, 5, 400)
y2 = -2 * x2
# 创建插值函数
interp_y1 = interp1d(x1, y1, kind='cubic', fill_value='extrapolate')
interp_y2 = interp1d(x2, y2, kind='cubic', fill_value='extrapolate')
# 定义一个较大的x区间用于扫描
x_scan = np.linspace(min(min(x1), min(x2)), max(max(x1), max(x2)), 1000)
# 向量化地找到边界线上的点
y_boundary = np.minimum(interp_y1(x_scan), interp_y2(x_scan))
# 绘制曲线和边界线
plt.figure(figsize=(8, 6))
plt.plot(x1, y1, label='y = x**2 - 2')
plt.plot(x2, y2, label='y = -2*x')
plt.plot(x_scan, y_boundary, label='Boundary Line', color='red')
# 标记出边界线上的点
plt.plot(x_scan, y_boundary, 'ro')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.title('Boundary Line between Two Curves')
plt.grid(True)
plt.show()