欠约束系统的SciPy优化



我经常要解决变量数量超过约束数量的非线性问题(有时反之亦然)。通常,一些约束或变量是以复杂的方式冗余的。有什么办法解决这些问题吗?

大多数scipy解算器似乎都假设约束的数量等于变量的数量,并且Jacobian是非奇异的。leastsq有时会起作用,但当约束小于变量数量时,它甚至不会尝试。我意识到我可以在linalg.norm(F)上运行fmin,但这比任何使用Jacobian的方法都效率低得多。

下面是一个问题的例子,它说明了我所说的内容。它显然有一个解决方案,但leastsq给出了一个错误。当然,这个例子很容易手工解决,我只是把它放在这里来演示这个问题。

import numpy as np
import scipy.optimize
mat = np.random.randn(5, 7)
def F(x):
    y = np.dot(mat, x)
    return np.array([ y[0]**2 + y[1]**3 + 12, y[2] + 17 ])
x0 = np.random.randn(7)
scipy.optimize.leastsq(F, x0)

我得到的错误信息是:

Traceback (most recent call last):
  File "question.py", line 13, in <module>
    scipy.optimize.leastsq(F, x0)
  File "/home/dstahlke/apps/scipy/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 278, in leastsq
    raise TypeError('Improper input: N=%s must not exceed M=%s' % (n,m))
TypeError: Improper input: N=7 must not exceed M=2

我在网上搜索答案,甚至在SciPy邮件列表上询问过,但没有得到回应。目前,我入侵了SciPy源,使newton_krylov求解器使用pinv(),但我不认为这是一个最佳解决方案。

如何将返回数组从F()调整为变量数:

import numpy as np
import scipy.optimize
mat = np.random.randn(5, 7)
def F(x):
    y = np.dot(mat, x)
    return np.resize(np.array([ y[0]**2 + y[1]**3 + 12, y[2] + 17]), 7)
while True:    
    x0 = np.random.randn(7)
    r = scipy.optimize.leastsq(F, x0)
    err = F(r[0])
    norm =  np.dot(err, err)
    if norm < 1e-6:
        break
print err