Генерация кода для основ оптимизации

Сгенерируйте код для fmincon

В этом примере показано, как сгенерировать код для fmincon решатель оптимизации. Генерация кода требует MATLAB® Лицензия Coder™. Для получения дополнительной информации требований генерации кода, смотрите Генерацию кода в fmincon Фоне.

Пример использует следующую простую целевую функцию. Чтобы использовать эту целевую функцию в вашем собственном тестировании, скопируйте код в файл с именем rosenbrockwithgrad.m. Сохраните файл на своем пути MATLAB.

function [f,g] = rosenbrockwithgrad(x)
% Calculate objective f
f = 100*(x(2) - x(1)^2)^2 + (1 - x(1))^2;

if nargout > 1 % gradient required
    g = [-400*(x(2) - x(1)^2)*x(1) - 2*(1 - x(1));
        200*(x(2) - x(1)^2)];
end

Сгенерировать код с помощью rosenbrockwithgrad целевая функция, создайте файл с именем test_rosen.m содержа этот код:

function [x,fval] = test_rosen
opts = optimoptions('fmincon','Algorithm','sqp');
[x fval] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],[-3,-3],[3,3],[],opts)

Сгенерируйте код для test_rosen файл.

codegen -config:mex test_rosen

Через какое-то время, codegen создает файл MEX под названием test_rosen_mex.mexw64 (расширение файла будет варьироваться, в зависимости от вашей системы). Можно запустить получившийся код С путем ввода test_rosen_mex. Результаты следующие или подобны:

x =

    1.0000    1.0000


fval =

   1.3346e-11


ans =

    1.0000    1.0000

Измените пример для КПД

После некоторых предложений в Генерации кода Оптимизации для Приложений реального времени, набор настройка сгенерированного кода, чтобы иметь меньше проверок и использовать выделение статического ЗУ.

cfg = coder.config('mex');
cfg.IntegrityChecks = false;
cfg.SaturateOnIntegerOverflow = false;
cfg.DynamicMemoryAllocation = 'Off';

Сожмите границы на проблеме от [-3,3] к [-2,2]. Кроме того, установите более свободную погрешность оптимальности, чем 1e-6 по умолчанию.

function [x,fval] = test_rosen2
opts = optimoptions('fmincon','Algorithm','sqp',...
    'OptimalityTolerance',1e-5);
[x fval eflag output] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],...
    [-2,-2],[2,2],[],opts)

Сгенерируйте код для test_rosen2 файл.

codegen -config cfg test_rosen2

Запустите получившийся код.

test_rosen2_mex
x =

    1.0000    1.0000


fval =

   2.0057e-11


eflag =

     2


output = 

  struct with fields:

         iterations: 40
          funcCount: 155
          algorithm: 'sqp'
    constrviolation: 0
           stepsize: 5.9344e-08
       lssteplength: 1


ans =

    1.0000    1.0000

Это решение почти так же хорошо как предыдущее решение с fval выведите вокруг 2e-11 по сравнению с предыдущим 1e-11.

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

function [x,fval] = test_rosen3
options = optimoptions('fmincon','Algorithm','sqp',...
    'MaxIterations',20);
[x fval eflag output] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],...
    [-2,-2],[2,2],[],options)

Запустите test_rosen3 в MATLAB.

test_rosen3
x =

    0.2852    0.0716


fval =

    0.5204


eflag =

     0


output = 

  struct with fields:

         iterations: 20
          funcCount: 91
          algorithm: 'sqp'
            message: '↵Solver stopped prematurely.↵↵fmincon stopped because it exceeded the iteration limit,↵options.MaxIterations = 2.000000e+01.↵↵'
    constrviolation: 0
           stepsize: 0.0225
       lssteplength: 1
      firstorderopt: 1.9504


ans =

    0.2852    0.0716

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

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

function [x,fval] = test_rosen4
options = optimoptions('fmincon','Algorithm','sqp',...
    'SpecifyObjectiveGradient',true);
[x fval eflag output] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],...
    [-2,-2],[2,2],[],options)

Сгенерируйте код для test_rosen4 использование той же настройки как в test_rosen2.

codegen -config cfg test_rosen4

Запустите получившийся код.

test_rosen4_mex
x =

    1.0000    1.0000


fval =

   3.3610e-20


eflag =

     2


output = 

  struct with fields:

         iterations: 40
          funcCount: 113
          algorithm: 'sqp'
    constrviolation: 0
           stepsize: 9.6356e-08
       lssteplength: 1


ans =

    1.0000    1.0000

По сравнению с test_rosen2, количество итераций является тем же самым в 40, но количество вычислений функции ниже в 113 вместо 155. Результат имеет лучшее (более низкое) значение целевой функции 3e-20 по сравнению с 2e-11.

Смотрите также

| (MATLAB Coder) |

Похожие темы