常用切线函数

时间:2012-04-22 16:48:47

标签: python mathematical-optimization

我在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轴上的截距,并搜索所有这些点以获得最近的一对,然后给出值。

这里有两个问题:

  1. 程序不知道最近的一对是否是解决方案

  2. 它的速度很慢(numb_of_points ^ 2搜索)。我意识到一些优化库可能有所帮助,但我担心他们会磨练一个解决方案并忽略其余的。

  3. 有人想到最好的方法吗? 我的“代码”在这里:

    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函数之间找到共同的切线来计算相图。为所有人提供强大的功能真是太好了......

2 个答案:

答案 0 :(得分:1)

您可以浏览曲线A的点,并在每个点绘制切线并计算它穿过曲线B的次数。如果交叉次数上下跳过两次,那么你知道你只是通过相互切线。这仍然相当粗糙,但我想它会比原始提案快一些,因为你不需要在曲线B上有很多采样点来计算曲线穿过给定切线的次数。 (只计算曲线B在线上方与线下方之间切换的次数。)

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

如果你更认真,我找到this more sophisticated discussion

答案 1 :(得分:0)

您可以使用Legendre transform将问题转换为求解两条曲线的交集,而不是解决常见的切线问题。一旦你这样做,你就可以获得#34;公共切线区域&#34;通过使用您发现的相等性作为两个原始函数必须满足的条件。