我在Python中有一个有趣的问题,我有两个函数(任意),我想找到它们之间的公共切线,以及x轴上公共切线触及每个函数的点。理想情况下,会有一个函数给出所有坐标(想象一组非常弯曲的函数和多个解决方案)。
所以,我有一些有用的东西,但它非常粗糙。我所做的是将每个函数放入矩阵中,因此M[h,0]
包含x值,M[h,1]
是function1 y值,M[h,2]
是function2 y值。然后我找到了导数并将其放在一个新的矩阵D[h,1]
和D[h,2]
中(跨度比M[h,:]
小一个。我的想法是基本上“绘制”x轴上的斜率,以及y轴上的截距,并搜索所有这些点以获得最近的一对,然后给出值。
这里有两个问题:
程序不知道最近的一对是否是解决方案
它的速度很慢(numb_of_points ^ 2搜索)。我意识到一些优化库可能有所帮助,但我担心他们会磨练一个解决方案并忽略其余的。
有人想到最好的方法吗? 我的“代码”在这里:
def common_tangent(T):
x_points = 600
x_start = 0.0001
x_end = 0.9999
M = zeros(((x_points+1),5) )
for h in range(M.shape[0]):
M[h,0] = x_start + ((x_end-x_start)/x_points)*(h) # populate matrix
""" Some function 1 """
M[h,1] = T*M[h,0]**2 + 56 + log(M[h,0])
""" Some function 2 """
M[h,2] = 5*T*M[h,0]**3 + T*M[h,0]**2 - log(M[h,0])
der1 = ediff1d(M[:,1])*x_points # derivative of the first function
der2 = ediff1d(M[:,2])*x_points # derivative of the second function
D = zeros(((x_points),9) )
for h in range(D.shape[0]):
D[h,0] = (M[h,0]+M[h+1,0])/2 # for the der matric, find the point between
D[h,1] = der1[h] # slope m_1 at this point
D[h,2] = der2[h] # slope m_2 at this point
D[h,3] = (M[h,1]+M[h+1,1])/2# average y_1 here
D[h,4] = (M[h,2]+M[h+1,2])/2# average y_2 here
D[h,5] = D[h,3] - D[h,1]*D[h,0] # y-intercept 1
D[h,6] = D[h,4] - D[h,2]*D[h,0] # y-intercept 2
monitor_distance = 5000 # some starting number
for h in range(D.shape[0]):
for w in range(D.shape[0]):
distance = sqrt( #in "slope intercept space" find distance
(D[w,6] - D[h,5])**2 +
(D[w,2] - D[h,1])**2
)
if distance < monitor_distance: # do until the closest is found
monitor_distance = distance
fraction1 = D[h,0]
fraction2 = D[w,0]
slope_02 = D[w,2]
slope_01 = D[h,1]
intercept_01 = D[h,5]
intercept_02 = D[w,6]
return (fraction1, fraction2)
这在材料科学中有很多应用,可以在多个Gibb函数之间找到共同的切线来计算相图。为所有人提供强大的功能真是太好了......
答案 0 :(得分:1)
您可以浏览曲线A的点,并在每个点绘制切线并计算它穿过曲线B的次数。如果交叉次数上下跳过两次,那么你知道你只是通过相互切线。这仍然相当粗糙,但我想它会比原始提案快一些,因为你不需要在曲线B上有很多采样点来计算曲线穿过给定切线的次数。 (只计算曲线B在线上方与线下方之间切换的次数。)
(当然,如果你的样本太少,你可能会错过双切线附近的一对交叉点,但没关系,你仍然会接近双切线。你可以而且应该添加一个一旦你非常接近真正的双正切,你就可以使用单独的估计精化算法。你可以使用类似于牛顿方法,递归二分法等的东西。)
如果你更认真,我找到this more sophisticated discussion。
答案 1 :(得分:0)
您可以使用Legendre transform将问题转换为求解两条曲线的交集,而不是解决常见的切线问题。一旦你这样做,你就可以获得#34;公共切线区域&#34;通过使用您发现的相等性作为两个原始函数必须满足的条件。