Объективные и нелинейные ограничения в той же функции

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

Вы обычно используете такую функцию в симуляции. Решатели, такие как fmincon выполняют объективные и нелинейные ограничительные функции отдельно. Эта оценка расточительна, когда вы используете то же вычисление для обоих результатов.

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

Примечание

Из-за пути ga вызывает нелинейные ограничительные функции, метод в этом примере обычно не сокращает количество вызовов ограничительных функций или цели.

Шаг 1. Функция, которая вычисляет цель и ограничения.

Например, предположите, что computeall является дорогой (длительной) функцией, вызванной и целевой функцией и нелинейными ограничительными функциями. Предположим, что вы хотите использовать fmincon в качестве своего оптимизатора.

Запишите функцию, которая вычисляет фрагмент функционального f1 Розенброка и нелинейного ограничения c1, который сохраняет решение в диске радиуса 1 вокруг источника. Функция Розенброка

f(x)=100(x2x12)2+(1x1)2,

который имеет уникальное минимальное значение 0 в (1,1). Смотрите Решают Ограниченную Нелинейную проблему, Основанную на решателе.

В этом примере нет никакого нелинейного ограничения равенства, таким образом  , ceq1 = []. Добавьте оператор pause(1), чтобы моделировать дорогое вычисление.

function [f1,c1,ceq1] = computeall(x)
    ceq1 = [];
    c1 = norm(x)^2 - 1;
    f1 = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2;
    pause(1) % simulate expensive computation
end

Сохраните computeall.m как файл на вашем пути MATLAB®.

Шаг 2. Встройте функцию во вложенную функцию, которая сохраняет недавние значения.

Предположим, что целевая функция

y = 100 (x 2x 12) 2 + (1 – x 1) 2
+ 20* (x 3x 42) 2 + 5* (1 – x 4) 2.

computeall возвращает первую часть целевой функции. Встройте вызов computeall во вложенной функции:

function [x,f,eflag,outpt] = runobjconstr(x0,opts)

if nargin == 1 % No options supplied
    opts = [];
end

xLast = []; % Last place computeall was called
myf = []; % Use for objective at xLast
myc = []; % Use for nonlinear inequality constraint
myceq = []; % Use for nonlinear equality constraint

fun = @objfun; % the objective function, nested below
cfun = @constr; % the constraint function, nested below

% Call fmincon
[x,f,eflag,outpt] = fmincon(fun,x0,[],[],[],[],[],[],cfun,opts);

    function y = objfun(x)
        if ~isequal(x,xLast) % Check if computation is necessary
            [myf,myc,myceq] = computeall(x);
            xLast = x;
        end
        % Now compute objective function
        y = myf + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2;
    end

    function [c,ceq] = constr(x)
        if ~isequal(x,xLast) % Check if computation is necessary
            [myf,myc,myceq] = computeall(x);
            xLast = x;
        end
        % Now compute constraint functions
        c = myc; % In this case, the computation is trivial
        ceq = myceq;
    end

end

Сохраните вложенную функцию как файл с именем runobjconstr.m на вашем пути MATLAB.

Шаг 3. Время, чтобы запуститься с вложенной функцией.

Петляйте, синхронизируя вызов с tic и toc.

opts = optimoptions(@fmincon,'Algorithm','interior-point','Display','off');
x0 = [-1,1,1,2];
tic
[x,fval,exitflag,output] = runobjconstr(x0,opts);
toc
Elapsed time is 203.797275 seconds.

Шаг 4. Время, чтобы запуститься без вложенной функции.

Сравните времена, чтобы запустить решатель с и без вложенной функции. Для выполнения без вложенной функции сохраните myrosen2.m как файл целевой функции и constr.m как ограничение:

function y = myrosen2(x)
    f1 = computeall(x); % get first part of objective
    y = f1 + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2;
end

function [c,ceq] = constr(x)
    [~,c,ceq] = computeall(x);
end

Запустите fmincon, синхронизировав вызов с tic и toc.

tic
[x,fval,exitflag,output] = fmincon(@myrosen2,x0,...
                   [],[],[],[],[],[],@constr,opts);
toc
Elapsed time is 406.771978 seconds.

Решатель берет в два раза длиннее, чем прежде, потому что он оценивает цель и ограничение отдельно.

Шаг 5. Сэкономьте вычислительное время с параллельными вычислениями.

Если у вас есть лицензия Parallel Computing Toolbox™, можно сэкономить еще больше времени путем установки опции UseParallel на true.

parpool
Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers.

ans = 

 Pool with properties: 

            Connected: true
           NumWorkers: 4
              Cluster: local
        AttachedFiles: {}
          IdleTimeout: 30 minute(s) (30 minutes remaining)
          SpmdEnabled: true
opts = optimoptions(opts,'UseParallel',true);
tic
[x,fval,exitflag,output] = runobjconstr(x0,opts);
toc
Elapsed time is 97.528110 seconds.

В этом случае включение параллельных вычислений сокращает вычислительное время в половине.

Сравните выполнения с параллельными вычислениями, с и без вложенной функции:

tic
[x,fval,exitflag,output] = fmincon(@myrosen2,x0,...
                   [],[],[],[],[],[],@constr,opts);
toc
Elapsed time is 188.985178 seconds.

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

Похожие темы