Оптимизация Scipy для системы с ограниченной ними

StackOverflow https://stackoverflow.com/questions/9342734

Вопрос

Мне часто приходится решать нелинейные задачи, в которых количество переменных превышает количество ограничений (или иногда наоборот). Обычно некоторые из ограничений или переменных избыточны сложными. Есть ли способ решить такие проблемы?

Большинство решателей Scipy, похоже, предполагают, что количество ограничений равняется количеству переменных, и что якобиан не является неинсулярным. 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(), но я не думаю, что это оптимальное решение.

Это было полезно?

Решение

Как насчет изменения размера массива возврата с 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top