4

我在 Python 中有一个有趣的问题,我有两个函数(任意),我想找到它们之间的公切线,以及公切线接触每个函数的 x 轴上的点。理想情况下,会有一个函数给出所有坐标(想象一组非常弯曲的函数,具有多种解决方案)。

所以,我有一些可行的方法,但它非常粗糙。我所做的是将每个函数放入一个矩阵中,因此M[h,0]包含 x 值,M[h,1]是 function1 y 值,M[h,2]是 function2 y 值。然后我找到导数并将其放在一个新矩阵中D[h,1]并且D[h,2](span 比 小一M[h,:]。我的想法是基本上“绘制”x 轴上的斜率和 y 轴上的截距,并搜索所有这些点对于最接近的对,然后给出值。

这里有两个问题:

  1. 程序不知道最接近的对是否是解决方案,并且

  2. 它非常缓慢(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)

这在材料科学中有很多应用,在寻找多个吉布函数之间的公切线以计算相图。如果能有一个强大的功能供所有人使用,那就太好了……

4

2 回答 2

1

您可以通过曲线 A 的点,并在每个点绘制切线并计算它与曲线 B 交叉的次数。如果交叉的次数向上或向下跳跃两次,那么您知道您刚刚通过了相互切线。这仍然很粗略,但我想它会比你原来的提议快一些,只是因为你不需要曲线 B 上的很多样本点来计算曲线穿过给定切线的次数。(只需计算曲线 B 在线上方和下方切换的次数。)

(当然,如果您的样本太少,您可能会错过双切线附近的一对交叉点,但这很好,您仍然会接近双切线。您可以并且应该添加单独的估计 -一旦你非常接近真正的双切线,你就可以使用细化算法。你可以使用类似于牛顿法、递归二分法等的东西。)

如果你更认真,我发现这个更复杂的讨论

于 2012-04-22T19:11:42.283 回答
0

您可以使用勒让德变换将问题转换为解决两条曲线的交点,而不是解决公切问题。一旦你这样做了,你可以通过使用你找到的相等性作为两个原始函数必须满足的条件来获得“公共切线区域”。

于 2017-10-16T22:21:48.867 回答