Python 公共切线函数

Python 公共切线函数,python,mathematical-optimization,Python,Mathematical Optimization,Python中有一个有趣的问题,我有两个函数(任意),我想找到它们之间的公共切线,以及公共切线与每个函数接触的x轴上的点。理想情况下,会有一个函数给出所有坐标(想象一组具有多个解的非常弯曲的函数) 所以,我有一些有效的方法,但非常粗糙。我所做的是将每个函数放入一个矩阵中,M[h,0]包含x值,M[h,1]是函数1y值,M[h,2]是函数2y值。然后我找到导数并将其放入一个新的矩阵D[h,1]和D[h,2](span比M[h,:]小一个)。我的想法基本上是“绘制”x轴上的斜率和y轴上的截距,然后搜

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

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

这里有两个问题:

  • 程序不知道最近的一对是否是解决方案,并且

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

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

    def公共切线(T):
    x_点=600
    x_开始=0.0001
    x_端=0.9999
    M=零((x_点+1,5))
    对于范围内的h(M.形状[0]):
    M[h,0]=x_开始+((x_结束-x_开始)/x_点)*(h)#填充矩阵
    “”“某些函数1”“”
    M[h,1]=T*M[h,0]**2+56+log(M[h,0])
    “某些函数2”
    M[h,2]=5*T*M[h,0]**3+T*M[h,0]**2-log(M[h,0])
    der1=ediff1d(M[:,1])*x_点#第一个函数的导数
    der2=ediff1d(M[:,2])*x_点#第二个函数的导数
    D=零(((x_点),9))
    对于范围内的h(D.形状[0]):
    D[h,0]=(M[h,0]+M[h+1,0])/2#对于阶矩阵,找到
    D[h,1]=der1[h]#此时的斜率m#1
    D[h,2]=der2[h]#此时的斜率m#2
    D[h,3]=(M[h,1]+M[h+1,1])/2#这里的平均y#1
    D[h,4]=(M[h,2]+M[h+1,2])/2#这里的平均y#2
    D[h,5]=D[h,3]-D[h,1]*D[h,0]#y截距1
    D[h,6]=D[h,4]-D[h,2]*D[h,0]#y截距2
    监控距离=5000#一些起始号码
    对于范围内的h(D.形状[0]):
    对于范围内的w(D.形状[0]):
    距离=sqrt(#在“坡度截距空间”中查找距离
    (D[w,6]-D[h,5])**2+
    (D[w,2]-D[h,1])**2
    )
    如果距离<监视器距离:#直到找到最近的距离
    监视器距离=距离
    分形1=D[h,0]
    分形2=D[w,0]
    斜率_02=D[w,2]
    斜率_01=D[h,1]
    截距_01=D[h,5]
    截距_02=D[w,6]
    返回值(分位数1、分位数2)
    

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

    你可以通过曲线a的点,在每个点上画出切线并计算出它的次数交叉曲线B。如果交叉点的数量上升或下降两倍,那么你就知道你刚刚通过了一个互切线。这仍然很粗糙,但我想它会比你最初的建议快一些,因为你不需要在曲线B上有太多的采样点来计算曲线通过给定切线的次数直线。(只需计算曲线B在直线上方和下方之间切换的次数。)

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


    如果你更认真的话,我发现。

    你可以用a将问题转化为求解两条曲线的交点,而不是解决公共切线问题。一旦你这样做,你就可以得到“公共切线区域”通过使用您发现的等式作为两个原始函数必须满足的条件。

    因此,如果我正确理解这一点,您会希望找到两个函数f(x)和g(x)的df/dx-dg/dx=0的所有解决方案?不完全正确。请参见下图:(from:)我认为这不会扩展到Python,但类似于这样的东西。f'(x1)-g'(x2)+f(x1)-g(x2)=0更准确吗?这是一个有趣的想法,我将尝试一下。也感谢文章链接。
    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)