Как я могу перехватить эту ошибку приближения в моем сценарии Matlab?

Я пытаюсь найти минимум функции, используя этот алгоритм. Это не оптимальный алгоритм, но мне сейчас все равно.

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

Обвиняемый алгоритм

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) есть какая-то ошибка, но я не знаю, как это доказать.

Вопрос

Наконец, мои вопросы

  1. Можем ли мы в этот момент быть уверены, что ошибка совершена при вычислении одного из f(c) или f(d)?
  2. Можем ли мы доказать это какой-нибудь строкой кода? Или, лучше, можем ли мы написать алгоритм так, чтобы он возвращался, когда должен?

Как работает алгоритм (не присуще вопросу)

Это итеративный алгоритм. По сути, идея состоит в том, чтобы сгенерировать последовательность интервалов, содержащих решение, начиная с начального интервала [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, алгоритм возвращает среднюю точку последнего интервала как приближение к минимальному значению.


ИЗМЕНИТЬ

Я вижу, что есть один человек, который хочет закрыть этот вопрос, потому что он слишком широк. Пожалуйста, сэр, вы можете уточнить в комментариях?


person doplumi    schedule 26.04.2015    source источник
comment
Вы пытались установить точку останова и выполнить код?   -  person Martin J.H.    schedule 26.04.2015
comment
Можете ли вы привести пример f, для которого этот алгоритм не работает? Я использовал f = @(x) x^2, и, к моему удивлению, он работает. Конечно, это простой пример, не имеющий локальных минимумов.   -  person Martin J.H.    schedule 26.04.2015
comment
@МартинДж.Х. Проблема в том, что у меня нет стратегии для проверки через точки останова. Я бы проверил fc и fd в этот момент, но я не мог отличить хорошие значения от плохих в этой ситуации. Что касается второго комментария, возможно, с x^2 он не работает (дает значение больше, чем error_max) с меньшим error_max. Вместо этого попробуйте 1e-11 или 1e-12... Если он по-прежнему не даст сбой, сообщите, я дам вам свою тестовую функцию как можно скорее.   -  person doplumi    schedule 26.04.2015
comment
@MrE Я новичок в MATLAB, я до сих пор не знаю, как их писать. Кроме того, какие тесты вы бы написали здесь? Что бы вы проверили?   -  person doplumi    schedule 26.04.2015


Ответы (1)


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

person Lutz Lehmann    schedule 26.04.2015
comment
Алгоритм работает. Он работает не только в том случае, если функция выпуклая, он работает с более широкой гипотезой, называемой унимодальностью. гипотеза. Прочитайте последний раздел, где я объясняю алгоритм. Это может помочь. - person doplumi; 27.04.2015
comment
Все множества уровня, также называемые квазивыпуклыми, компактны (в одномерных одиночных интервалах). Тем не менее не отменяет аргумент о нескольких минимумах. - person Lutz Lehmann; 27.04.2015
comment
Оно делает. Если функция унимодальна на интервале или (квази)выпукла, как вы говорите, она не может иметь более одного минимума на этом интервале. - person doplumi; 27.04.2015
comment
Я этого не говорил. У вас есть унимодальные функции, в которых работает алгоритм, за исключением возможных проблем с вычислением с плавающей запятой, и больше осциллирующих функций, где достижение глобального минимума является случайным событием. -- Чтобы ответить на ваш первоначальный вопрос, вам все равно нужно, как требовалось несколько раз, предоставить функции и интервалы, которые дали вам неправильные результаты. Алгоритм, останавливающийся на неминимуме, также может быть проблемой с плавающей запятой. - person Lutz Lehmann; 27.04.2015