Pregunta

A menudo tengo que resolver problemas no lineales en los que el número de variables excede el número de restricciones (o a veces al revés). Por lo general, algunas de las restricciones o variables son redundantes de una manera complicada. ¿Hay alguna forma de resolver tales problemas?

La mayoría de los solucionadores Scipy parecen asumir que el número de restricciones es igual al número de variables, y que el jacobiano no es singular. leastsq A veces funciona, pero ni siquiera se intenta cuando las limitaciones son menos que el número de variables. Me doy cuenta de que podría correr fmin en linalg.norm(F), pero esto es mucho menos eficiente que cualquier método que utilice el jacobiano.

Aquí hay un ejemplo de un problema que demuestra de lo que estoy hablando. Obviamente tiene una solución, pero leastsq da un error. Por supuesto, este ejemplo es fácil de resolver a mano, solo lo pongo aquí para demostrar el problema.

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)

El mensaje de error que recibo es:

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

He recorrido la red para una respuesta e incluso he preguntado en la lista de correo escolar y no recibí respuesta. Por ahora pirateé la fuente de Scipy para que el newton_krylov Usos de solucionador pinv(), pero no creo que esta sea una solución óptima.

¿Fue útil?

Solución

¿Qué tal cambiar el tamaño de la matriz de retorno de f () al número de variables:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top