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

scipy.optimize的fsolve求解向量值函数根返回错误结果问题

问题原因

你的目标函数包含np.abs非光滑项,而scipy.optimize.fsolve底层调用的是MINPACK的hybrd算法,属于基于雅可比矩阵的光滑优化算法,在非光滑点附近无法获得有效梯度信息,会出现迭代停滞,最终返回未收敛的局部点,也就是你看到的RuntimeWarning和错误解。

解决方案
  • 方案1:改用适配非光滑场景的求解器
    推荐使用scipy.optimize.least_squares,它将求根问题转化为残差平方和最小化问题,支持非光滑目标,鲁棒性更强,示例代码如下:
import numpy as np 
from scipy.optimize import least_squares

def AMOC(amoc_state,
         gamma= 2.3,
         theta = 1,
         mu = 7.5,
         sigma = 0.85):
    T = amoc_state[0]
    S = amoc_state[1]
    dT = -gamma * (T-theta) - T * (1+ mu*np.abs(T-S)) 
    dS = sigma - S*(1+mu*np.abs(T-S))
    return np.array([dT, dS]) 

res = least_squares(AMOC, x0=(0.8, 0.3), xtol=1e-7, max_nfev=1000)
# 输出结果与残差验证
print("求解得到的根:", res.x)
print("对应残差:", AMOC(res.x))

运行后可以得到残差在1e-12量级的收敛解,符合根的要求。

  • 方案2:拆分非光滑问题为光滑子问题
    你可以根据T和S的大小关系,将原问题拆分为两个独立的光滑子问题,分别用fsolve求解后验证:

    1. 子问题1:假设T >= S,将np.abs(T-S)替换为T - S,传入fsolve求解
    2. 子问题2:假设T < S,将np.abs(T-S)替换为S - T,传入fsolve求解
      拆分后的子问题都是光滑函数,fsolve可以正常收敛。
  • 方案3:优化初始猜测值
    fsolve是局部求解器,初始值距离真实根过远也会导致收敛失败,你可以先在合理的T、S取值范围内做粗粒度网格搜索,找到残差最小的点作为初始值再传入fsolve,也能提高收敛概率。

注意事项

求解完成后建议先检查求解器返回的收敛状态:比如调用fsolve时设置full_output=True,查看返回的ier参数,仅当ier=1时才代表求解收敛,避免直接使用未收敛的错误结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 17:06:05