常用正切函数

use*_*763 5 python mathematical-optimization

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

所以,我有一些可行的东西,但它非常粗糙。我所做的是将每个函数放入一个矩阵中,以便M[h,0]包含 x 值、M[h,1]函数 1 的 y 值、M[h,2]函数 2 的 y 值。然后我找到导数并将其放入一个新矩阵中D[h,1]D[h,2]跨度小于 1)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)
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*nes 1

你可以遍历曲线A的点,在每个点画切线并计算它与曲线B相交的次数。如果相交的次数增加或减少了两次,那么你就知道你刚刚通过了一条共同点切线。这仍然很粗糙,但我想它会比您最初的提议更快一些,只是因为您不需要曲线 B 上的很多样本点来计算曲线穿过给定切线的次数。(只需计算曲线 B 在线上方和下方之间切换的次数即可。)

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

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