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

时间:2014-01-26 23:40:02

标签: python scipy mathematical-optimization

我正在开发一个项目,我正在使用根求解器来找到曲线的一些参数,这些参数会导致曲线的端点位于特定位置 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])

2 个答案:

答案 0 :(得分:1)

scipy.optimize.root函数返回一个OptimizeResult对象。

我很好奇,scipy.optimize.root返回的OptimizeResult对象中的'success','status'和'message'字段的值是什么?

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

  • '迭代并未取得良好进展,正如过去十次迭代的改进所证明的那样。'

顺便说一句,看看minpack.py,看看你可能遇到的其他一些问题。

答案 1 :(得分:0)

对于这个问题,它最终是一个不好的选择。