项目场景:
几日前,在研究某双核期刊的某篇论文时,发现论文上的函数图像绘制得似乎有些不精确。原函数方程为:(0.2045*y)^2+(3/4*y^3-2*x*y)^2-0.45^2=0。论文原文中函数图像如下图:
问题描述
可以很明显地看出,极值点附近的曲线显得很不平滑,根据论文作者提供的数据,该极值点的横坐标X=1.62335。
原因分析:
初步分析可能是作者绘图过程中,对函数的迭代次数设置得过低导致的。
解决方案:
于是我计划利用Python自己绘制一遍函数图像,并找到极值点。目前中文网上关于隐函数图像绘制的代码有博客可以借鉴,但是没有关于如何得到隐函数极值点的相关博客,求极值的内容基本围绕显函数展开。接下来我的代码将展示如何用Python绘制隐函数(0.2045*y)^2+(3/4*y^3-2*x*y)^2-0.45^2=0的图像,并找到该函数在X的取值范围为[-2,2]时的极大值点。代码如下:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.pyplot import MultipleLocator
iteration=500 # 迭代次数
x=np.linspace(-2,2,iteration)
y=np.linspace(0,2.5,iteration)
x,y=np.meshgrid(x,y) # 生成x,y轴网
z=(0.2045*y)**2+(3/4*y**3-2*x*y)**2-0.45**2 # 隐函数方程
# 设置刻度
x_major_locator=MultipleLocator(0.5) # 0.5表示x轴一格的值为0.5
y_major_locator=MultipleLocator(0.2)
ax=plt.gca() # ax为两条坐标轴的实例
ax.xaxis.set_major_locator(x_major_locator)
ax.yaxis.set_major_locator(y_major_locator)
# 画图
test=plt.contour(x,y,z,0)
points = test.allsegs[1][0] # 组成这条函数图像的每个点
sorted_list = sorted(points, key=lambda x: x[1], reverse=True) # 对这些点按照点的y坐标
x_max=sorted_list[0][0] # 极值点x坐标 # 降序排列
y_max=sorted_list[0][1] # 极值点y坐标
print(f"x_max={sorted_list[0][0]}\n",f"y_max={sorted_list[0][1]}")
plt.scatter(x_max, y_max, c='r', marker='o') # 在点(x_max, y_max)上绘制红色圆点
plt.annotate(f'X coordinate of extremum:{x_max},\nY coordinate of extremum:{y_max},\nIteration:{iteration}'
, xy=(x_max, y_max)
, xytext=(x_max-3.5, y_max+0.35)
,arrowprops=dict(facecolor='black', shrink=0.05)
,xycoords='data'
) # 在点上添加文字说明,其中 xytext 代表文字说明和点xy的距离
plt.show()
上文代码中,我设置的迭代次数为500次。为了分析出论文作者,可能设置的迭代次数,我分别迭代了71,72,73,74,75,500,5000,10000次,并分析这些次数下极大值的X,Y坐标变化规律。输出的图像分别如下:
分析可知:论文作者的X,Y迭代次数不一样,因为我设定的X,Y迭代次数一致,并且迭代次数在74,75次时,X的坐标分别为1.61644和1.67567,而作者提供的极值点X坐标为1.62335。即,作者设定的X,Y的迭代次数最大值应该不超过100左右(包括X的迭代次数小于100,Y迭代次数远远大于100的情况,这都会使得极值点的X坐标位于[1.61644,1.67567]左右)。如果要保证精确到小数点后四位,那么至少要迭代5000次左右。
结束语:
该论文将该方程用于描述周期性风险的反馈控制模型,但是对方程所描述的函数的极值点求解显得不那么严谨。风险管控本身是一件周密而严肃的管理活动,尤其是对描述风险管理的模型应该更加严格的校核、审查。该论文通过仅仅迭代百次不到的函数描述模型,多少有些不妥。