fmincon
В этом примере показано, как сгенерировать код для fmincon
решатель оптимизации. Для генерации кода требуется MATLAB® Coder™ лицензию. Для получения дополнительной информации о требованиях к генерации кода смотрите Code Generation в fmincon Background.
В примере используется следующая простая целевая функция. Чтобы использовать эту целевую функцию в собственной проверке, скопируйте код в файл с именем 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
Следуя некоторым предложениям в Optimization Code Generation для приложений реального времени, установите строение сгенерированного кода, чтобы иметь меньше проверок и использовать статическое выделение памяти.
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
.
fmincon
| optimoptions
| codegen
(MATLAB CODER)