2014-01-23 3 views
1

Я пытаюсь свести к минимуму функцию в заданном интервале; в моем случае интервал [-pi/2, pi/2].Минимизировать функцию в заданном интервале с помощью scipy.optimize.brute

Вот что я писал в моем сценарии:

ranges = slice(-pi/2, pi/2, pi/200) 
res = optimize.brute(g, (ranges,)) 

с

def g(x): 
    # z and a are global 
    (-(z+1) * (((a/4) * (3*cos(x/3) + cos(3*x/2)) + 
       (b/4) * (-3*sin(x/2)-3*sin(3*x/2)))**2 + 
       ((a/4‌​) * (sin(x/3) + sin(3*x/2)) + (b/4)* 
       (cos(x/2) + 3*cos(3*x/2)))**2) + 4*(c*cos(x/2))**2) 

и результатом res является

array([-3.14159265]) 

Проблемой я встречаю во время черчения моих решений является то, что некоторые из решений минимизации находятся за пределами интервала [-pi/2, pi/2]. Любая помощь?

+0

У вас есть практический пример 'g', когда решение превышает интервал? И ценность результатов? – Evert

+0

Чтобы ответить на мой собственный комментарий, выглядит как 'def g (x): return sin (0.5 * x)' уже соответствует счету. – Evert

+0

вот моя функция: - (z + 1) * (((a/4) * (3 * cos (x/3) + cos (3 * x/2)) + (b/4) * (- 3 * Sin (х/2) -3 * Sin (3 * х/2))) ** 2 + ((а/4) * (син (х/3) + Sin (3 * х/2)) + (b/4) * (cos (x/2) + 3 * cos (3 * x/2))) ** 2) + 4 * (c * cos (x/2)) ** 2 – Abdallah

ответ

7

«Проблема» с функцией «отделки» по умолчанию: brute имеет возможность предоставления функции минимизации завершения. Он делает это так, что метод грубой силы может использоваться как первая догадка, а затем результат может быть «отполирован» с использованием лучшей функции минимизации.

Если для этой функции установлено значение Нет, ничего не происходит, что, скорее всего, вам нужно здесь. К сожалению, в этом случае по умолчанию установлено значение fmin, что является методом простого наклона (Nelder-Mead), и это просто игнорирует любую спецификацию диапазона/сетки. Таким образом, для функции, такой как sin(0.5 * x), она начнется с самой низкой точки, которую обнаружит функция brute (-pi/2), и продолжайте оттуда, найдя -pi, чтобы быть (ближайшим) глобальным минимумом.

Решение простое:

res = optimize.brute(g, (ranges,), finish=None) 

даст то, что вы хотите.

Обязательная ссылка на scipy.optimize.brute documentation.

+1

+1. Это не первый случай, когда кто-то удивился поведением по умолчанию 'brute', где' finish = fmin': https://github.com/scipy/scipy/issues/1613 –

+0

@WarrenWeckesser Спасибо. Я собирался искать это (я не использую «грубую», поэтому я был удивлен, увидев это). К сожалению, очевидная причина того, что в качестве значения по умолчанию не используется 'finish = None', является обратная совместимость. Без релиза 1.0 его можно было бы изменить (но да, многие ученые были бы удивлены или даже не заметили бы неправильных результатов, так как я не ожидаю, что большинство скупых пользователей внимательно прочитает примечания к выпуску между версиями). – Evert

+0

Невозможно установить ограничения на fmin и сделать их по умолчанию? – endolith

0

Вы можете просто написать целевую функцию, чтобы вернуть np.inf, если передаваемый параметр находится за пределами желаемого диапазона. Так, например:

def g(x, x_limit): 

if x > x_limit: 
    return np.inf 
else: 
    return (-(z+1) * (((a/4) * (3*cos(x/3) + cos(3*x/2)) + 
      (b/4) * (-3*sin(x/2)-3*sin(3*x/2)))**2 + 
      ((a/4‌​) * (sin(x/3) + sin(3*x/2)) + (b/4)* 
      (cos(x/2) + 3*cos(3*x/2)))**2) + 4*(c*cos(x/2))**2) 
Смежные вопросы