我经常要解决非线性问题,其中变量的数量超过了约束的数量(或者有时反过来)。通常,一些约束或变量以复杂的方式冗余。有没有办法解决这些问题?
大多数scipy求解器似乎假设约束的数量等于变量的数量,并且Jacobian是非奇异的。 leastsq
有时可以工作,但是当约束少于变量数时它甚至都不会尝试。我意识到我可以在fmin
上运行linalg.norm(F)
,但这比使用雅可比行列式的方法效率低得多。
这是一个问题的例子,它说明了我在说什么。它显然有一个解决方案,但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()
,但我不认为这是最佳解决方案。
答案 0 :(得分:3)
如何将返回数组从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