Выбор переменных для scipy.optimize из предопределенного набора - PullRequest
0 голосов
/ 29 апреля 2020

Я пытаюсь свести к минимуму функцию с scipy.optimize с тремя входными переменными, две из которых ограничены, а одну нужно выбрать из набора значений. Чтобы убедиться, что третья переменная выбрана из предопределенного набора значений, я ввел следующее ограничение:

from scipy.optimize import rosin, shgo
import numpy as np

# Set from which the third variable to be optimized can hold 
Z = np.array([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1]) 

def Reson_Test(x):   # arbitrary objective function
     print (x)
     return rosen(x)**2 - np.sin(x[0]) 

def Cond_1(x):
     if x[2] in Z:
          return 1
     else:
          return -1

bounds = [(-512,512),]*3 
conds = ({'type': 'ineq' , 'fun' : Cond_1})


result = shgo(Rosen_Test, bounds, constraints=conds)
print (result)

Однако, глядя на результаты печати из Rosen_Test, очевидно, что условие не применяется - возможно, условие не определено правильно?

Мне было интересно, есть ли у кого-нибудь идеи по обеспечению выбора третьей переменной из набора.

Примечание. Использование метода shgo было выбрано таким образом, чтобы можно было вводить и изменять ограничения. Кроме того, я открыт для использования других пакетов оптимизации, если выполняется это условие

Спасибо за помощь !!

1 Ответ

1 голос
/ 29 апреля 2020

Ограничения неравенства не работают так.

Как упомянуто в документах , они определены как

g(x) <= 0

, и вам нужно написать g(x), работать так. В ваших случаях это не так. Вы возвращаете только один скаляр для одного измерения. Вам нужно вернуть вектор с тремя измерениями, формы (3,).

. В вашем случае вы можете попробовать вместо этого использовать ограничения равенства, поскольку это может позволить немного лучший взлом. Но я все еще не уверен, будет ли это работать, так как эти оптимизаторы не работают так. И все это, вероятно, оставит оптимизатор с довольно ухабистой и прерывистой целевой функцией. Вы можете прочитать о Смешанное целочисленное нелинейное программирование (MINLP), возможно, начать здесь .

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

Это иллюстрирует проблему:

import numpy as np

Z = np.array([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1])

print(0.7999999 in Z) # False, this is what the optimizer will find
print(0.8 in Z) # True, this is what you want

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

Но давайте посмотрим, как это может работать.

Ограничение равенства определяется как

h(x) == 0

Таким образом, вы можете использовать

def Cond_1(x):
    if x[2] in Z:
        return numpy.zeros_like(x)
    else:
        return numpy.ones_like(x) * 1.0 # maybe multiply with some scalar?

Идея состоит в том, чтобы вернуть массив [0.0, 0.0, 0.0], который удовлетворяет ограничению равенства, если число найдено. В противном случае верните [1.0, 1.0, 1.0], чтобы показать, что он не удовлетворен.

Предостережения :

1.) Возможно, вам придется настроить это так, чтобы он возвращал массив типа [0.0, 0.0, 1.0], чтобы показать оптимизатору, какое измерение вам не нравится, поэтому оптимизатор можно сделать более точные предположения, настроив только одно измерение.

2.) Возможно, вам придется вернуть большее значение, чем 1,0, чтобы установить невыполненное ограничение равенства. Это зависит от реализации. Оптимизатор может подумать, что 1.0 - это хорошо, так как он близок к 0.0. Так что, возможно, вам нужно что-то попробовать [0.0, 0.0, 999.0].

Это решает проблему с измерением. Но все равно не найдем никаких чисел, подходящих для упомянутой выше вещи с плавающей запятой.

Но мы можем попытаться взломать это, как

import numpy as np

Z = np.array([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1])

def Cond_1(x):

    # how close you want to get to the numbers in your array
    tolerance = 0.001 
    delta = np.abs(x[2] - Z)
    print(delta)
    print(np.min(delta) < tolerance)

    if np.min(delta) < tolerance:

        return np.zeros_like(x)

    else:

        # maybe you have to multiply this with some scalar
        # I have no clue how it is implemented
        # we need a value stating to the optimizer "NOT THIS ONE!!!"
        return np.ones_like(x) * 1.0


sol = np.array([0.5123, 0.234, 0.2])
print(Cond_1(sol)) # True

sol = np.array([0.5123, 0.234, 0.202])
print(Cond_1(sol)) # False

Здесь - некоторые рекомендации по оптимизации. Чтобы убедиться, что все работает надежно, попробуйте запустить оптимизацию с разными начальными значениями. Алгоритмы глобальной оптимизации могут не иметь начальных значений, если используются с границами. Оптимизатор каким-то образом дискретизирует пространство.

Что вы можете сделать, чтобы проверить надежность вашей оптимизации и улучшить общие результаты:

  • Оптимизация по всему региону [-512, 512] (для всех трех измерений)

  • Попробуйте 1/2 от этого: [-512, 0] и [0, 512] (8 дополнительных оптимизаций, 2 для каждого измерения)

  • Попробуйте 1/3 от этого: [-512, -171], [-171, 170], [170, 512] (27 субоптимизаций, 3 для каждого измерения)

  • Теперь сравните конвергентные результаты, чтобы увидеть, нашла ли полная глобальная оптимизация тот же результат

  • Если глобальный оптимизатор не нашел "настоящие" минимумы, а подоптимизацию:

    • ваша целевая функция слишком сложна для всего домена
    • попробуйте другой глобальный оптимизатор
    • настройте параметры (возможно, 999 для ограничения равенства)
    • Я часто использую субоптимизация как часть нормального процесса, а не только для тестирования. Специально для проблем с черным ящиком.

Пожалуйста, посмотрите также эти ответы:

Scipy.optimize Ограничение неравенства - Какая сторона неравенства считается?

функция минимизации Сципи

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