Проблема с оптимизацией функции, содержащей циклы

У меня проблема с оптимизацией функции, содержащей циклы. Я начинаю с определенного 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 и целевая функция из 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 ответ

Вы написали:

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
    ...

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

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

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

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

Другие вопросы по тегам