Я пытаюсь найти минимум функции, используя этот алгоритм. Это не оптимальный алгоритм, но мне сейчас все равно.
Кроме того, вам не нужно знать, как работает алгоритм, чтобы ответить, но если вам интересно, я расскажу об этом в конце этого поста. Это действительно не так сложно.
Обвиняемый алгоритм
function result = fmin(f,a,b,max_error)
if abs(b-a) < max_error
result = (a+b)/2;
else
r1 = a+(b-a)*rand(1,1); r2 = a+(b-a)*rand(1,1);
c = min([r1,r2]); d = max([r1,r2]);
fc = f(c); fd = f(d);
if fc <= fd
b = d;
else
a = c;
end
result = fmin(f,a,b,max_error);
end
Теперь проблема в том, что этот алгоритм возвращает минимум, который далек от фактического минимума (вычисленного с помощью предопределенной функции Matlab fminbnd
) для более чем max_error
, если я использую его со значениями max_error <= 1e-10
. Такая ситуация с теоретической точки зрения невозможна.
Будучи рекурсивным, алгоритм никогда не вернется, если условие abs(b-a) < max_error
никогда не будет выполнено.
Итак, я думаю, что есть некоторая ошибка, возникающая из-за аппроксимации чисел. Сначала я подумал, что r1
или r2
вычисляются неправильно. В какой-то момент два числа выйдут за пределы интервала [a,b]
, тем самым опровергнув гипотезу, на которой работает алгоритм.
Чтобы доказать это, я изменил приведенный выше алгоритм, включив в него проверку интервала, вычисляемого на каждой итерации:
Обвиняемый алгоритм 2 [Проверьте крайности]
function result = fmin(f,a,b,max_error)
if abs(b-a) < max_error
result = (a+b)/2;
else
r1 = a+(b-a)*rand(1,1); r2 = a+(b-a)*rand(1,1);
c = min([r1,r2]); d=max([r1,r2]);
% check that c and d are actually inside [a,b]
if ((c < a)||(d > b))
disp('Max precision reached');
result = (a+b)/2;
return;
end
fc = f(c); fd = f(d);
if fc <= fd
b = d;
else
a = c;
end
result = fmin(f,a,b,max_error);
end
Но я не получаю никакого дополнительного вывода из консоли.
Итак, я думаю, что в вычислении f(c)
или f(d)
есть какая-то ошибка, но я не знаю, как это доказать.
Вопрос
Наконец, мои вопросы
- Можем ли мы в этот момент быть уверены, что ошибка совершена при вычислении одного из
f(c)
илиf(d)
? - Можем ли мы доказать это какой-нибудь строкой кода? Или, лучше, можем ли мы написать алгоритм так, чтобы он возвращался, когда должен?
Как работает алгоритм (не присуще вопросу)
Это итеративный алгоритм. По сути, идея состоит в том, чтобы сгенерировать последовательность интервалов, содержащих решение, начиная с начального интервала [a,b], в котором заданная функция f
является унимодальной. На каждом шаге мы случайным образом выбираем два числа c
и d
так, чтобы a <= c <= d <= b
. Теперь, если мы обнаружим, что f(c) > f(d)
, это означает, что мы уверены, что можем отбросить значения, которые функция принимает до c
, как действительные кандидаты на минимум из-за унимодальности. Так что ограничиваем интервал и повторяем процедуру в интервале [c,b]
. Наоборот, если это f(c) < f(d)
, мы можем отбросить значения от d
до b
, поэтому повторяем процедуру в интервале [a,d]
.
С каждой итерацией интервал становится короче. Когда его длина меньше указанного значения max_error
, алгоритм возвращает среднюю точку последнего интервала как приближение к минимальному значению.
ИЗМЕНИТЬ
Я вижу, что есть один человек, который хочет закрыть этот вопрос, потому что он слишком широк. Пожалуйста, сэр, вы можете уточнить в комментариях?
f
, для которого этот алгоритм не работает? Я использовалf = @(x) x^2
, и, к моему удивлению, он работает. Конечно, это простой пример, не имеющий локальных минимумов. - person Martin J.H.   schedule 26.04.2015x^2
он не работает (дает значение больше, чемerror_max
) с меньшимerror_max
. Вместо этого попробуйте 1e-11 или 1e-12... Если он по-прежнему не даст сбой, сообщите, я дам вам свою тестовую функцию как можно скорее. - person doplumi   schedule 26.04.2015