<p>假设<code>qi>0</code>斜率实际上是正的,所以我没有选择<code>-0.003</code>。而且我认为导数是错的。
可以精确计算坡度达到临界值的值。
根据我的经验,你有两个选择。如果您自己定义分段函数,通常会遇到使用numpy数组的函数调用问题。我通常将<code>scipy.optimize.leastsq</code>与自定义的残差函数一起使用。第二个选择是在两个功能之间进行连续转换。根据定义,只要值和斜率已经适合,就可以使其尽可能的锐利。
这两种解决方案如下所示</p>
<p>进口matplotlib.pyplot作为plt
将numpy作为np导入</p>
<pre><code>def hy(x,b,qi,di):
return qi*(1.0-b*di*x)**(-1.0/b)
def abshy(x,b,qi,di):#same as hy but defined for all x
return qi*abs(1.0-b*di*x)**(-1.0/b)
def dhy(x,b,qi,di):#derivative of hy
return qi*di*(1.0-b*di*x)**(-(b+1.0)/b)
def get_x_from_slope(s,b,qi,di):#self explaining
return (1.0-(s/(qi*di))**(-b/(b+1.0)))/(b*di)
def exh(x,xlim,qlim,dlim):#exponential part (actually no free parameters)
return qlim*np.exp(dlim*(x-xlim))
def trans(x,b,qi,di, s0):#piecewise function
x0=get_x_from_slope(s0,b,qi,di)
if x<x0:
out= hy(x,b,qi,di)
else:
H0=hy(x0,b,qi,di)
out=exh(x,x0,H0,s0/H0)
return out
def no_if_trans(x,b,qi,di, s0,sharpness=10):#continuous transition between the two functions
x0=get_x_from_slope(s0,b,qi,di)
H0=hy(x0,b,qi,di)
weight=0.5*(1+np.tanh(sharpness*(x-x0)))
return weight*exh(x,x0,H0,s0/H0)+(1.0-weight)*abshy(x,b,qi,di)
xList=np.linspace(0,5.5,90)
hyList=np.fromiter(( hy(x,2.2,1.2,.1) for x in xList ) ,np.float)
t1List=np.fromiter(( trans(x,2.2,1.2,.1,3.59) for x in xList ) ,np.float)
nt1List=np.fromiter(( no_if_trans(x,2.2,1.2,.1,3.59) for x in xList ) ,np.float)
fig1=plt.figure(1)
ax=fig1.add_subplot(1,1,1)
ax.plot(xList,hyList)
ax.plot(xList,t1List,linestyle=' ')
ax.plot(xList,nt1List,linestyle=':')
ax.set_ylim([1,10])
ax.set_yscale('log')
plt.show()
</code></pre>
<p><a href="https://i.stack.imgur.com/onOhj.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/onOhj.png" alt="Testfunctions"/></a></p>
<p>这两种解决方案几乎没有区别,但是使用<code>scipy</code>拟合函数的选项略有不同。第二个解决方案应该很容易与<code>curve_fit</code>配合使用</p>