Проблема с оптимизацией функции, содержащей циклы
У меня проблема с оптимизацией функции, содержащей циклы. Я начинаю с определенного 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
...
Но потратив немного времени, чтобы начать писать это, это сразу же кажется неправильным.
- Я не могу поверить, что ты имел в виду
.0025
, скорее, чемk * .0025
, как нижняя граница. - Предположим, добавлен некоторый случайный шум, а не
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
Режим выхода предлагает диагностический совет о том, что пошло не так.