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

如何从sympy.diff提取函数适配scipy.fsolve?导数根求解提速

问题分析与解决方案

你遇到的核心问题是:sympy.solve会尝试求解所有解析根,导致速度极慢,但你只需要靠近x0的单个数值根;而用scipy.fsolve时报错,是因为sympy的表达式对象(如Mul)不能直接作为可调用函数传入。

以下是几种高效的解决方法:

方案1:用sympy.lambdify转换表达式适配scipy.fsolve

把sympy的符号表达式转换成numpy兼容的可调用函数,就能直接给fsolve使用。同时可以优化求导逻辑,避免开根号简化计算:

import sympy
from scipy.optimize import fsolve

def diff_dist_func(a, b, c):
    x = sympy.Symbol('x')
    x0 = sympy.Symbol('x0')
    y0 = sympy.Symbol('y0')
    # 优化:直接对距离平方求导,和原距离导数为0的根完全一致,避免开根号
    dist_sq = (x - x0) ** 2 + (a * x ** 3 + b * x ** 2 + c * x - y0) ** 2
    return sympy.diff(dist_sq, x)

a = -0.00020129919480721813
b = 0.10107634020780536
c = -12.305150031126267
shortest_dist = diff_dist_func(a, b, c)

x0_val = 252.3007982720215
y0_val = 96.55526056735049
# 代入x0、y0的数值,保留x作为变量的符号表达式
expr = shortest_dist.subs({'x0': x0_val, 'y0': y0_val})
# 将符号表达式转成可调用的数值函数
func = sympy.lambdify(sympy.Symbol('x'), expr, 'numpy')
# 用fsolve求解,初始值设为x0_val,快速得到附近的根
solve_x = fsolve(func, x0_val)
print(solve_x)

方案2:直接用sympy.nsolve求数值解

如果不想依赖scipy,sympy自带的nsolve支持指定初始值,专门求解单个数值根,速度远快于solve:

import sympy

def diff_dist_func(a, b, c):
    x = sympy.Symbol('x')
    x0 = sympy.Symbol('x0')
    y0 = sympy.Symbol('y0')
    dist_sq = (x - x0) ** 2 + (a * x ** 3 + b * x ** 2 + c * x - y0) ** 2
    return sympy.diff(dist_sq, x)

a = -0.00020129919480721813
b = 0.10107634020780536
c = -12.305150031126267
shortest_dist = diff_dist_func(a, b, c)

x0_val = 252.3007982720215
y0_val = 96.55526056735049
expr = shortest_dist.subs({'x0': x0_val, 'y0': y0_val})
x = sympy.Symbol('x')
# 指定初始值x0_val,直接求解附近的根
solve_x = sympy.nsolve(expr, x, x0_val)
print(solve_x)

关键说明

  1. 为什么原代码报错:你用evalf(subs=...)得到的是sympy的数值表达式对象(如Mul),这不是可调用函数,fsolve需要的是能接受数值参数并返回数值的函数,lambdify就是做这个转换的。
  2. 求导优化的原因:原距离函数的导数为0,等价于距离平方的导数为0(因为距离是正数,链式法则推导可得),去掉根号后sympy的计算量大幅降低,求导和后续处理都更快。

内容的提问来源于stack exchange,提问作者xc-2021

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 11:08:10