簡體   English   中英

使用python的公切線

[英]Common tangent using python

我正在嘗試使用 python 找到兩條曲線的共同切線,但我無法解決它。
兩條曲線的方程很復雜,涉及對數。

python中有沒有一種方法可以計算兩條曲線共同的切線的x坐標。 如果我有 2 條曲線 f(x) 和 g(x),我想在公共切線上找到 x 坐標 x1 和 x2,其中 x1 在 f(x) 上,x2 在 g(x) 上。 我正在嘗試 f'(x1) = g'(x2) 和 f'(x1) = f(x1) - f(x2) / (x1 - x2) 來獲得 x1 和 x2 但我無法使用nonlinsolve 因為方程太復雜了。

我只想找到公切線的 x 坐標

任何人都可以提出更好的方法嗎?

import numpy as np
import sympy
from sympy import *
from matplotlib import pyplot as plt


x = symbols('x')
a, b, c, d, e, f = -99322.50019502985, -86864.87072433547, -96876.05627516498, -89703.35055202093, -3390.863799999999, -20942.518


def func(x):
    y1_1 = a - a*x + b*x
    y1_2 = c - c*x + d*x

    c1 = (1 - x) ** (1 - x)
    c2 = (x ** x)
    y2 = 12471 * (sympy.log((c1*c2)))

    y3 = 2*f*x**3 - x**2*(e + 3*f) + x*(e + f)
    eqn1 = y1_1 + y2 + y3
    eqn2 = y1_2 + y2 + y3
    return eqn1, eqn2


val = np.linspace(0, 1)
f1 = sympy.lambdify(x, func(x)[0])(val)
f2 = sympy.lambdify(x, func(x)[1])(val)

plt.plot(val, f1)
plt.plot(val, f2)
plt.show()

我正在嘗試這個

x1, x2 = sympy.symbols('x1 x2')

fun1 = func(x1)[0]
fun2 = func(x2)[0]
diff1 = diff(fun1,x1)
diff2 = diff(fun2,x2)
eq1 = diff1 - diff2
eq2 = diff1 - ((fun1 - fun2) / (x1 - x2))

sol = nonlinsolve([eq1, eq2], [x1, x2])

首先需要做的是減少公式

例如,第一個公式實際上是這樣的:

formula = x*(1 - x)*(17551.6542 - 41885.036*x) + x*(1 - x)*(41885.036*x - 24333.3818) + 12457.6294706944*x + log((x/(1 - x))**(12000*x)*(1 - x)**12000) - 99322.5001950298
formula = (x-x^2)*(17551.6542 - 41885.036*x) + (x-x^2)*(41885.036*x - 24333.3818) + 12457.6294706944*x + log((x/(1 - x))**(12000*x)*(1 - x)**12000) - 99322.5001950298

# constants
a = 41885.036
b = 17551.6542
c = 24333.3818
d = 12457.6294706944
e = 99322.5001950298
f = 12000

formula = (x-x^2)*(b - a*x) + (x-x^2)*(a*x - c) + d*x + log((x/(1 - x))**(f*x)*(1 - x)**f) - e
formula = (ax^3 -bx^2 + bx - ax^2) + (x-x^2)*(a*x - c) + d*x + log((x/(1 - x))**(f*x)*(1 - x)**f) - e
formula = ax^3 -bx^2 + bx - ax^2 -ax^3 + ax^2 + cx^2 -cx + d*x + log((x/(1 - x))**(f*x)*(1 - x)**f) - e

# collect x terms by power (note how the x^3 tern drops out, so its easier).
formula =  (c-b)*x^2 + (b-c+d)*x  + log((x/(1 - x))**(f*x)*(1 - x)**f) - e

這更干凈,並且是帶有對數項的二次方。 我希望您也可以在對數術語上做一些工作,但這是原始海報的練習

同樣,第二個公式可以以相同的方式進行簡化,這又是對原始海報的練習

由此,兩個方程都需要對 x 進行微分才能找到切線。 然后將兩個公式設置為彼此相等(對於公切線)。

這將徹底解決問題。

我真的想知道這到底是一個python問題還是一個純數學問題......

需要注意的重要一點是,由於導數是單調的,因此對於fun1的任何導數值,都有fun2的解。 如果您繪制兩個導數,則可以很容易地看到這一點。

因此,我們想要一個函數,給定一個x1 ,返回一個與之匹配的x2 我將使用數值解法,因為系統對於數值解法來說太麻煩了。

import scipy.optimize

def find_equal_value(f1, f2, x, x1):
    goal = f1.subs(x, x1)
    to_solve = sympy.lambdify(x, (f2 - goal)**2)  # Quadratic functions tend to be better behaved, and the result is the same
    sol = scipy.optimize.fmin(func=to_solve, x0=x1, ftol=1e-8, disp=False)  # The value for f1 is a good starting guess
    return sol[0]

我使用fmin作為上面的求解器,因為它有效,而且我知道如何使用它。 也許root_scalar可以給出更好的結果。

使用上面的函數,讓我們得到一些導數相等的對(x1, x2)

df1 = sympy.diff(func(x)[0])
df2 = sympy.diff(func(x)[1])

x1 = 0.25236537  # Close to the zero derivative
x2 = find_equal_value(df1, df2, x, x1)
print(f'Derivative of f1 in x1: {df1.subs(x, x1)}')
print(f'Derivative of f2 in x2: {df2.subs(x, x2)}')
print(f'Error: {df1.subs(x, x1) - df2.subs(x, x2)}')

這個結果是:

Derivative of f1 in x1: 0.0000768765858083498
Derivative of f2 in x2: 0.0000681969431752805
Error: 0.00000867964263306931

如果您想要幾個x1x2 (請注意,在某些情況下,求解器會遇到日志無效的值。始終檢查您的結果是否有效):

x1s = np.linspace(0.2, 0.8, 50)
x2s = [find_equal_value(df1, df2, x, x1) for x1 in x1s]
plt.plot(x1s, x2s); plt.grid(); plt.show()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM