Проблема с оптимизацией функции, содержащей циклы - PullRequest
0 голосов
/ 19 мая 2019

У меня проблема с оптимизацией функции, содержащей циклы.Я начинаю с определенного значения lista=[0.002,0.006,0.003,0.02,0.008,0.006,0.05] с плавающей точкой и интервалов `(0, k * 0,0025), (0,005, k * 0,005), (0,005, k * 0,0125), где зависит верхняя граница.Таким образом, в зависимости от того, к какому из интервалов относится поплавок списка, я назначаю функции одно из значений k * 0,005, k * 0,01, k * 0,025 и k * 0,05, которые также зависят от k.

Я хочу минимизировать k так, чтобы сумма (новая скалярная функция) значений assign(k) или sum(assign(k)) была равна 0,32.

Я использовал scipy.optimize процедуру, чтобы сделать это.Мое ограничение - constraint=sum(assign(k))-0.32 и целевая функция iz fun(k)=k.Итак, я минимизировал k для удовлетворения ограничения.

import scipy
from scipy.optimize import minimize


lista=[0.002,0.006,0.003,0.02,0.008,0.006,0.05]

def assign(k):
    return list(map(lambda x:(k*0.005 if x in np.arange(0,k*0.0025,0.001) 
    else k*0.01 if x in np.arange(0.0025,k*0.005,0.001) else k*0.025 if x in 
    np.arange(0.005,k*0.0125,0.001) else k*0.05), lista))

def constraint(k):
    return sum(assign(k))-0.32

def fun(k):
    return k

k0=0
bnds=[(0,10)]
cons={'type':'eq','fun':constraint}
res=minimize(fun,k0,bounds=bnds,method='SLSQP',constraints=cons,options={'maxiter':2000})
print(res)

Я получил k = 1,1999 , что является странным результатом, он не удовлетворяет ограничению.Это должно быть 2, так как sum(assign(2))=0.52.Я также получил сообщение об ошибке:

  message: 'Iteration limit exceeded'

Кто-нибудь знает, как преодолеть это ограничение?Заранее спасибо!

1 Ответ

0 голосов
/ 27 мая 2019

Вы писали:

lambda x:(k*0.005 if x in np.arange(0,k*0.0025,0.001) 
else k*0.01 if x in np.arange(0.0025,k*0.005,0.001) else k*0.025 if x in 
np.arange(0.005,k*0.0125,0.001) else k*0.05)

Пожалуйста, не делайте этого.Короткая лямбда-функция хороша, но она достаточно длинна, чтобы заслужить имя и определение читаемой функции:

def assign1(x, k):
    if x in np.arange(0, k * 0.0025, 0.001):
        return k * .01
    if x in np.arange(0.0025, k * 0.005, 0.001):
        return k * .025
    ...

Но, потратив некоторое время, чтобы начать писать это, она сразу же кажется неправильной.

  1. Не могу поверить, что вы имели в виду .0025, а не k * .0025, как нижнюю границу.
  2. Предположим, добавлен некоторый случайный шум, поэтому вместо x мы имеемx + epsilon.Тогда ваша функция возвращает константу в 5% от k, что кажется плохим.

В общем, мы не ожидаем, что int(x * 1000) == x.Поэтому закодируйте его, используя правильные диапазоны:

def assign1(x, k):
    if 0 <= x < k * .0025:
        return k * .01
    if k * .0025 <= x < k * .0050:
        return k * .025
    ...

Укажите лучшее ограничение, и я верю, что вы будете более довольны сходством оптимизатора.

РЕДАКТИРОВАТЬ

Оптимизация tutorial предполагает, что для этого метода SLSQP вы должны передавать как fun, так и jac.

Кроме того, full_output=True режим выхода предлагает диагностический совет о том, чтопошло не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...