You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求解两条三次曲线公切线:约束求解范围的技术问题

解决带约束的函数公切线求解问题

看起来你已经把公切线的数学模型推导得很清楚了——方程组的逻辑完全没问题,问题出在数值求解时的约束设置和初始值选择上。我来分享几个能在指定数据范围内找到有效解的实用方法:

1. 问题根源分析

  • SymPy求解失败大概率是因为你的函数是非线性的,不存在解析解,所以必须用数值方法;
  • scipy.fsolve本身不支持边界约束,所以很容易跳出你需要的数据范围;
  • least_squares没得到正确结果,可能是初始值选得不好,或者没处理x1=x2导致的除以0问题。

2. 具体解决方案:带约束的最小化/根求解

我们可以把方程组转化为残差最小化问题,同时给x1和x2加上边界约束,用支持约束的求解器来处理。

方法一:用scipy.optimize.minimize(L-BFGS-B/SLSQP方法)

这个方法适合将残差的平方和作为目标函数,同时通过bounds参数限制变量范围。

举个具体的代码例子(假设你的函数是f(x)=x²和g(x)=e^x,数据范围x1∈[0,2],x2∈[0,2]):

import numpy as np
from scipy.optimize import minimize

# 定义目标函数和导数
def f(x):
    return x**2

def f_prime(x):
    return 2*x

def g(x):
    return np.exp(x)

def g_prime(x):
    return np.exp(x)

# 构造残差平方和函数:避免x1=x2导致除以0
def residual_sum(params):
    x1, x2 = params
    if np.abs(x1 - x2) < 1e-8:
        return 1e10  # 返回极大值,让求解器避开这种情况
    res1 = f_prime(x1) - g_prime(x2)
    res2 = (f(x1) - g(x2))/(x1 - x2) - f_prime(x1)
    return res1**2 + res2**2

# 设置初始猜测和边界约束
initial_guess = [1.0, 0.5]  # 选在数据范围内的合理值,也可以多试几个不同初始点
bounds = [(0, 2), (0, 2)]   # x1和x2的范围

# 求解
result = minimize(residual_sum, initial_guess, bounds=bounds, method='L-BFGS-B')

# 输出结果
if result.success:
    x1_opt, x2_opt = result.x
    slope = f_prime(x1_opt)
    print(f"找到有效切点:x1={x1_opt:.4f}, x2={x2_opt:.4f}")
    print(f"公切线斜率:{slope:.4f}")
    print(f"斜率验证:两点连线斜率 = {(f(x1_opt)-g(x2_opt))/(x1_opt-x2_opt):.4f}")
else:
    print(f"求解失败:{result.message}")
方法二:用scipy.optimize.least_squares(支持边界约束)

如果你更倾向于直接最小化残差向量(而非平方和),可以用这个方法,它同样支持bounds参数:

from scipy.optimize import least_squares

def residual_vector(params):
    x1, x2 = params
    if np.abs(x1 - x2) < 1e-8:
        return [1e5, 1e5]  # 返回大残差避免除以0
    res1 = f_prime(x1) - g_prime(x2)
    res2 = (f(x1) - g(x2))/(x1 - x2) - f_prime(x1)
    return [res1, res2]

result_ls = least_squares(residual_vector, initial_guess, bounds=([0, 0], [2, 2]))

if result_ls.success:
    x1_opt, x2_opt = result_ls.x
    # 后续验证和输出同上

3. 关键注意事项

  • 初始值很重要:如果你的函数有多个极值点或者可能的公切线,多试几个不同的初始猜测(比如函数的极值点附近、交点附近),避免陷入局部最优;
  • 避免除以0:一定要在残差函数里处理x1=x2的情况,否则求解器可能会遇到数值崩溃;
  • 检查求解状态:每次求解后都要查看success标志和message,如果失败,调整初始值或者尝试其他求解方法(比如把method换成SLSQP)。

内容的提问来源于stack exchange,提问作者DavidC.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:44:39