Как определить разрывные границы в SciPy.optimize.minimize - PullRequest
0 голосов
/ 15 мая 2018

Я использую метод scipy.optimize.minimize 'SLSQP', согласно документации:

границы: последовательность, необязательно

Границы для переменных (только для L-BFGS-B, TNC и SLSQP). (min, max) пары для> каждого элемента в x, определяя границы для этого параметра. Используйте None для значения min> или max, если в этом направлении нет границы.

Я хотел бы знать, возможно ли определить границу, которая НЕ является непрерывной для переменной x, как (0,15) & (30,50); (х от 0 до 15 и от 30 до 50)

Или есть другие лучшие способы для достижения этой цели?

Заранее спасибо, ребята!

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Вот попытка реализации подхода к хохолку , описанного Эрвином Кальвелагеном .

Сначала построим полином с корнями в 0, 15, 30 и 50 который является положительным в нужном регионе:

In [123]: x = np.linspace(-1, 51, 100)

In [124]: plt.plot(x,-(x-0)*(x-15)*(x-30)*(x-50))
Out[124]: [<matplotlib.lines.Line2D at 0x7fa01d65b748>]

In [125]: plt.axhline(color='red')
Out[145]: <matplotlib.lines.Line2D at 0x7fa01d6620b8>

In [146]: plt.show()

enter image description here

Теперь вы можете использовать этот многочлен в качестве ограничения:

import numpy as np
import scipy.optimize as optimize

cons = (
    {'type': 'ineq', 'fun': lambda x: -(x-0)*(x-15)*(x-30)*(x-50)}, )

def f(x):
    return (x-20)**2

res = optimize.basinhopping(f, [40], minimizer_kwargs={'method':'SLSQP', 'constraints': cons}, niter=10, stepsize=20)
print(res)

выходы

 message: 'Optimization terminated successfully.'
    nfev: 13
     nit: 4
    njev: 4
  status: 0
 success: True
       x: array([15.])
                    message: ['requested number of basinhopping iterations completed successfully']
      minimization_failures: 0
                       nfev: 178
                        nit: 10
                       njev: 56
                          x: array([15.])

Обратите внимание, что первоначальное предположение было на 40, и все же optimize.basinhopping удалось найти минимум в другом несмежном интервале на x = 15. Использование размера шага, порядка порядка расстояния между двумя интервалами, важно, чтобы дать basinhopping возможность выборки из обоих интервалов.

Без обхода бассейна, optimize.minimize с использованием SLSQP с невыпуклым ограничением может не дать выборку из всех допустимых интервалов. Например,

import scipy.optimize as optimize

cons = ({'type': 'ineq', 'fun': lambda x: -(x-0)*(x-15)*(x-30)*(x-50)}, )

def f(x):
    return (x-20)**2

res = optimize.minimize(
    f, [40], method='SLSQP', constraints=cons)
print(res.x)
# [30.]

res = optimize.minimize(
    f, [5], method='SLSQP', constraints=cons)
print(res.x)
# [15.]

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

0 голосов
/ 15 мая 2018

x находится между 0 и 15 и между 30 и 50

Это сделает модель недопустимой.Нет такого x.Вы, вероятно, имеете в виду:

x - от 0 до 15 ИЛИ - от 30 до 50

Это не выпукло, поэтому стандартные локальные решатели имеют проблемы с этим.Он часто моделируется с помощью дополнительной двоичной переменной:

30 δ ≤ x ≤ 15(1-δ) + 50 δ  
δ ∈ {0,1}

Конечно, это предполагает, что вы можете обрабатывать двоичные переменные (SLSQP не может).Модели с двоичными переменными и нелинейными ограничениями (или целевой функцией) называются моделями MINLP (смешанное целочисленное нелинейное программирование).Решатели для этого типа моделей легко доступны.

Некоторые другие подходы, которые могут работать:

  • Решите проблему дважды.Один раз с 0 ≤ x ≤ 15 и один раз с 30 ≤ x ≤ 50.Затем выберите лучшее решение.
  • Используйте глобальный решатель scipy.optimize.basinhopping, чтобы помочь вам выбраться из локального оптимума.Это не строгий алгоритм (без гарантий), но он может помочь.

Некоторые подходы, которые обычно не работают:

  • вместо двоичной переменной δ ∈ {0,1} используйте непрерывную переменную δ ∈ [0,1] и добавьте ограничение δ(1-δ)=0.Обычно это застревает.
  • Полиномиальный подход в другом ответе: это также невыпукло и не очень подходит для SLSQP.Вы застрянете в локальном оптимуме.
  • Добавьте штраф к цели, если x ∈ [15,30].Это также не работает с локальным решателем.
...