Skip to main content
 首页 » 编程设计

python之为什么 scipy.optimize.root 收敛到错误的解决方案

2025年05月04日10mayingbao

我正在做一个项目,在这个项目中,我使用根求解器来查找曲线的一些参数,这些参数会导致曲线的端点位于具有特定切向量的特定位置 x1 n1。我使用的参数适用于 Frenet-Serret 曲线,以防它有助于理解问题。

这是我试图找到根的函数:

def f(x): 
  k0, k2, t0, t1, t2 = x 
 
  # s0, s1, and s2 are references into curve 
  s0.curvature = k0 
  s2.curvature = k2 
  s0.torsion = t0 
  s1.torsion = t1 
  s2.torsion = t2 
 
  r = curve.end_point(basis=True) 
  n1t, x1t = r[0][0], r[1] 
  dx = x1t-x1 
  dn = n1t-n1 
  return [dx[0], dx[1], dx[2], sum(dn), sum(dn**2)] 

由于输入是一个 5 向量,它期望一个 5 向量作为输出,并且没有一种真正自然的方法来选择 5 个方程。我使用位置差的分量,因为这很有意义,而且法向量的绝对差似乎足够强。我只是加入了 sum(dn) 部分,希望能为求解器提供更多信息。

我知道我正在对此处的曲线进行就地修改,因此如果求解器不收敛,它会使该曲线处于令人讨厌的状态;这些实际上是副本,我在接受输出之前检查是否收敛。现在我相当确定这不是现在的问题,因为我的问题发生在收敛过程中,所以我认为这与我设置终止条件的方式有关。

问题是绝大多数时候我都能得到很好的解决方案,但偶尔,求解器会认为它找到了解决方案,而曲线的终点就在很远的地方。或者,有时,求解器会陷入僵局,顺序出现多个解决方案会非常糟糕。我错过了什么吗?是我条件不够好还是其他问题?

编辑:

有人询问有关 scipy 给我的结果对象的更多信息。我用 xtol=1e-6 运行了这个试验,直到计算出的终点和终点切线似乎距离目标远超过 0.1 个单位。

******************************************************************************* 
Something seems to be the matter! 
******************************************************************************* 
 
The solution did converge yet... 
 
- The absolute difference in the end point is 0.0108799344285  
- The absolute difference in the end tangent is 0.225645622344 
 
Here is the result from scipy: 
 
  status: 1 
 success: True 
     qtf: array([-0.05326282, -0.02382437,  0.14675375, -0.01343988,  0.04837993]) 
    nfev: 51 
       r: array([  4.10027838e-01,   2.80055126e-04,   2.72346438e-01, 
         1.88121754e-02,   3.03986277e-03,   3.76073132e-02, 
        -3.91459070e-03,  -5.44385807e-02,  -3.82769383e-02, 
         1.41418659e-01,  -5.02200767e-02,  -8.25093288e-03, 
         6.76335001e-02,   1.14316378e-02,   6.38501029e-05]) 
     fun: array([-0.06421218,  0.10206985,  0.04248109,  0.07709824,  0.071918  ]) 
       x: array([ -5.47581391e-02,   2.00109990e+07,   2.11915236e+01, 
         6.61899661e+05,  -2.22193886e+07]) 
 message: 'The solution converged.' 
    fjac: array([[-0.3207226 , -0.75566902,  0.53250215, -0.19842636, -0.05630082], 
       [-0.02198464, -0.00102108,  0.06437769,  0.4629469 , -0.88377108], 
       [-0.73103662,  0.31989562,  0.22322297,  0.48119372,  0.28614045], 
       [-0.44804528,  0.39203066, -0.01871625, -0.71533847, -0.36538741], 
       [ 0.40186388,  0.41586301,  0.81370645, -0.05523237,  0.01986423]]) 
 
x_calc: array([ 6.25753046,  2.99378609,  9.8221681 ]) 
x_target: array([ 6.31937831,  2.93663   ,  9.76062169]) 
t_calc: array([ 0.75316478, -0.59352174,  0.28368074]) 
t_target: array([ 0.40709037, -0.69479177,  0.59290963]) 

请您参考如下方法:

scipy.optimize.root 函数返回 OptimizeResult目的。

我很好奇,scipy.optimize.root 返回的 OptimizeResult 对象中的“成功”、“状态”和“消息”字段的值是什么?

例如,消息可能是这样的:

  • “根据最近十次迭代的改进衡量,迭代没有取得良好进展。”

顺便看看minpack.py查看您可能遇到的其他一些可能的问题。