How do I set up fmincon correctly for parallel computation? "Supplied objective function must return a scalar value"
显示 更早的评论
I have an expensive objective function which takes in multiple parameters, while the contraints are constant. It looks something like this:
out1, out2 = obj_func(in1, in2)
in1 has 1000 different cases. For each possible value of in1, I want to minimize out1 by adjusting in2. At the same time, out2 has to be < 1 in all cases. Because obj_func takes a while to run, I want to parallelize the computation, either by calculating several gradients at the same time, or solve the problem for several in1.
Below is my simplified code:
nPoints = length(INVARS(:,1));
odInputNames = {'DISA'; 'ALT'; 'MACH'};
% Number of batches depending on given batch size:
sizeBatch = 20;
nBatch = floor( nPoints/sizeBatch ) + 1; % Last batch contains remaining points
% Define constraints
CONSTR = struct(...
'param_A', '...',...
'param_B', '...',...
'param_C', '...',...
CONSTR_REQ = [ 1800; ...
1.10; ...
1.15; ...
];
for i = 1:nBatch
% Create batchwise input vectors
for iODVar = 1:length(odInputNames)
if i < nBatch
OD.(odInputNames{iODVar}) = INVARS(sizeBatch*(i-1)+1:sizeBatch*i, iODVar);
else
OD.(odInputNames{iODVar}) = INVARS(sizeBatch*(i-1)+1:end, iODVar); % Last batch has fewer points
end
end
% Setup of FMINCON Optimizer
% ---------------------------------------------------------------------
A = [];
b = [];
Aeq = [];
beq = [];
lb = ones(size(OD.DISA)) * 80;
ub = ones(size(OD.DISA)) * 120;
options = optimoptions(@fmincon, ...
'Algorithm', 'active-set',...
'MaxIter', 200,...
'ConstraintTolerance', 1e-8,...
'OptimalityTolerance', 1e-8,...
'Display', 'off',...
'UseParallel', true);
x0 = ones(size(OD.DISA)) * 85;
% Declare constraint results to be shared between obj_fun and con_fun
constr_fields = fieldnames(CONSTR);
con_res = zeros(length(constr_fields), length(OD.DISA));
% Execute Optimizer
[PLA_max, obj_min,exitflag,~,~] = fmincon( @(x)obj_fun(x), x0, A, b, Aeq, beq, lb, ub, @(x)con_fun(), options );
% Objective:
function [obj] = obj_fun( PLA )
OD.PLA = PLA;
[OD.OUT, OD.IN] = expensive_function( DES, OD );
obj = - OD.OUT.param_obj;
for i=1:length(constr_fields)
con_res(i,:) = eval(['OD.' CONSTR.(constr_fields{i})]);
end
end
% Constraints:
function [c,ceq] = con_fun()
exp_CONSTR_REQ = repmat(CONSTR_REQ, 1, length(OD.DISA));
c = (con_res - exp_CONSTR_REQ); % Non-Equality constraint ( !<= 0 )
ceq = [];
end
It works fine when I solve one case at a time, but when I try to parallelize it I got this error. How can I fix it?
Error using fmincon (line 348)
Supplied objective function must return a scalar value.
2 个评论
Why is lb > ub ?
lb = ones(size(OD.DISA)) * 120;
ub = ones(size(OD.DISA)) * 80;
Why does the error message report something about fminunc ? It is not referenced in your code.
Shao-Yu
2025-1-22
采纳的回答
更多回答(1 个)
Catalytic
2025-1-24
0 个投票
There are other acceleration strategies that may be superior to parallelization.
I notice in your examples that the in1,in2 pairs change by small amounts. You also appear to believe that the final solutions for PLA will be close to each other, otherwise why initialize the optimization with the same x0? Those being the case, it may be worthwile to go back to the strategy of optimizing one PLA at a time. However, you would use the optimized PLA from the N-th optimization as the x0 for the next optimization. This might cut down on the number of iterations you need to get the solution, and reduce the number of calls to expensive function.
类别
在 帮助中心 和 File Exchange 中查找有关 Get Started with Optimization Toolbox 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


