Этот пример показывает, как постараться не вызывать функцию дважды, когда он вычисляет значения и для цели и для ограничений с помощью основанного на проблеме подхода. Для основанного на решателе подхода смотрите Объективные и Нелинейные Ограничения в Той же Функции.
Вы обычно используете такую функцию в симуляции. Решатели обычно выполняют объективные и нелинейные ограничительные функции отдельно. Эта оценка расточительна, когда вы используете то же вычисление для обоих результатов.
Этот пример также показывает эффект параллельного вычисления на скорости решателя. Для длительных функций, вычисляя параллельно может ускорить решатель, как может, избегая вызывания длительной функции неоднократно в той же точке. Используя оба метода вместе ускоряет решатель больше всего.
Функция computeall
возвращает выходные параметры, которые являются частью объективных и нелинейных ограничений.
type computeall
function [f1,c1] = computeall(x) c1 = norm(x)^2 - 1; f1 = 100*(x(2) - x(1)^2)^2 + (1 - x(1))^2; pause(1) % simulate expensive computation end
Функция включает оператор pause(1)
, чтобы моделировать длительную функцию.
Эта проблема использует четырехэлементную переменную оптимизации.
x = optimvar('x',4);
'ReuseEvaluation'
Преобразуйте функцию computeall
в выражение оптимизации. Чтобы сэкономить время во время оптимизации, используйте пару "имя-значение" 'ReuseEvaluation'
. Чтобы сэкономить время для решателя, чтобы определить размеры выходного выражения (это происходит только однажды), устанавливает пару "имя-значение" 'OutputSize'
на [1 1]
, указывая, что и f
и c
являются scalar.
[f,c] = fcn2optimexpr(@computeall,x,'ReuseEvaluation',true,'OutputSize',[1 1]);
Создайте целевую функцию от выражения f
.
obj = f + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2;
Создайте нелинейное ограничение неравенства из выражения c
.
cons = c <= 0;
Создайте задачу оптимизации и включайте цель и ограничение.
prob = optimproblem('Objective',obj);
prob.Constraints.cons = cons;
showproblem(prob)
OptimizationProblem : minimize : ((arg3 + (20 .* (x(3) - x(4).^2).^2)) + (5 .* (1 - x(4)).^2)) where: [arg3,~] = generatedFunction_computeall_withReuse(x); subject to cons: arg_LHS <= 0 where: [~,arg_LHS] = generatedFunction_computeall_withReuse(x);
Контролируйте время, которое требуется, чтобы решить проблему, начинающую с начальной точки x0.x = [-1;1;1;2]
.
x0.x = [-1;1;1;2];
x0.x = x0.x/norm(x0.x); % Feasible initial point
tic
[sol,fval,exitflag,output] = solve(prob,x0)
Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance. <stopping criteria details>
sol = struct with fields:
x: [4×1 double]
fval = 0.7107
exitflag = OptimalSolution
output = struct with fields:
iterations: 25
funcCount: 149
constrviolation: 0
stepsize: 1.3715e-07
algorithm: 'interior-point'
firstorderopt: 4.0000e-07
cgiterations: 7
message: '↵Local minimum found that satisfies the constraints.↵↵Optimization completed because the objective function is non-decreasing in ↵feasible directions, to within the value of the optimality tolerance,↵and constraints are satisfied to within the value of the constraint tolerance.↵↵<stopping criteria details>↵↵Optimization completed: The relative first-order optimality measure, 2.909695e-07,↵is less than options.OptimalityTolerance = 1.000000e-06, and the relative maximum constraint↵violation, 0.000000e+00, is less than options.ConstraintTolerance = 1.000000e-06.↵↵'
solver: 'fmincon'
time1 = toc
time1 = 149.8888
Номер секунд для решения только по количеству функциональных оценок, которое указывает, что решатель вычислил каждую оценку только однажды.
fprintf("The number of seconds to solve was %g, and the number of evaluation points was %g.\n",time1,output.funcCount)
The number of seconds to solve was 149.889, and the number of evaluation points was 149.
Если, вместо этого, вы не вызываете fcn2optimexpr
с помощью 'ReuseEvaluation'
, то время решения удваивается.
[f2,c2] = fcn2optimexpr(@computeall,x,'ReuseEvaluation',false); obj2 = f2 + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2; cons2 = c2 <= 0; prob2 = optimproblem('Objective',obj2); prob2.Constraints.cons2 = cons2; tic [sol2,fval2,exitflag2,output2] = solve(prob2,x0);
Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance. <stopping criteria details>
time2 = toc
time2 = 298.4074
Если у вас есть Параллельная обработка лицензия Toolbox™, можно сэкономить еще больше времени путем вычисления параллельно. Для этого установите опции использовать параллельную обработку и вызывать solve
с опциями.
options = optimoptions(prob,'UseParallel',true); tic [sol3,fval3,exitflag3,output3] = solve(prob,x0,'Options',options);
Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance. <stopping criteria details>
time3 = toc
time3 = 74.0615
Используя параллельную обработку и 'ReuseEvaluation'
вместе предоставляет более быстрое решение, чем использование одного только 'ReuseEvaluation'
. Смотрите, сколько времени это берет, чтобы решить проблему с помощью одной только параллельной обработки.
tic
[sol4,fval4,exitflag4,output4] = solve(prob2,x0,'Options',options);
Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance. <stopping criteria details>
time4 = toc
time4 = 144.6696
Объедините результаты синхронизации в одну таблицу.
timingtable = table([time1;time2;time3;time4],... 'RowNames',["Reuse Serial";"No Reuse Serial";"Reuse Parallel";"No Reuse Parallel"])
timingtable=4×1 table
Var1
______
Reuse Serial 149.89
No Reuse Serial 298.41
Reuse Parallel 74.062
No Reuse Parallel 144.67
Для этой проблемы, на компьютере с 6 основными процессорами, вычисляющими в параллельных взятиях, приблизительно половина времени вычисления в последовательном, и вычисления с 'ReuseEvaluation'
берет приблизительно половину времени вычисления без 'ReuseEvaluation'
. Вычисление параллельно с 'ReuseEvaluation'
берет приблизительно четверть времени вычисления в сериале без 'ReuseEvaluation'
.