Dear all,
I am trying to include for-loop to define gradient nested within objective function of fmincon as below.
However, I am getting an error saying the number of elements for the gradient has to be 10. How can properly incorporate for-loop in the gradient nested in the objective function?
clc
clear
%%
n = 10;
Q0 = 0;
x0 = zeros(n, 1) + 25;
p0 = 1;
I = 50;
p1 = 1.25;
A1 = -diag(ones(n, 1));
%%
A2 = zeros(n/2, n);
for i = 1:n/2
w = A2(i, :);
j = 2*i;
w(1:2:j) = 1;
w(2:2:j) = -1;
A2(i, :) = w;
end
%%
A3 = zeros(n/2, n);
for i = 1:n/2
w = A3(i, :);
j = 2*i;
w(j) = 1;
A3(i, :) = w;
end
%%
A12 = vertcat(A1, A2);
A = vertcat(A12, A3);
%%
b = zeros(2*n, 1);
for i = 1:2*n
if i <= n
b(i) = 0;
elseif i > n && i <= n + n/2
b(i) = Q0;
elseif i > n + n/2 && i <= n + n/2 + floor((n/2)/2) + 1
b(i) = I/p0;
else
b(i) = I/p1;
end
end
Aeq = [];
beq = [];
lb = [];
ub = [];
nonlcon=[];
options = optimoptions('fmincon','SpecifyObjectiveGradient',true);
sol = fmincon(@myobj,x0,A,b, Aeq, beq, lb, ub, [], options);
%---------------------------------------------------------
function [f, g] = myobj(x)
global I
global p0
global p1
global n
q0 = x(2:2:n/2+1);
a0 = x(1:2:n/2+1);
c0 = ones(length(q0), 1).*I - q0.*p0;
u0= a0.^(1/2).*c0.^(1/2);
q1 = x(n/2+3:2:n);
a1 = x(n/2+2:2:n);
c1 = ones(length(q1), 1).*I - q1.*p1;
u1= a1.^(1/2).*c1.^(1/2);
f = -1*(sum(u0 + u1));
% if nargout > 1
% g = -x;
% end
if nargout > 1
g = [];
for i = 1:n
if mod(i,2)==0
dx = -(1/2 * 1/sqrt(x(i)));
elseif (mod(i,2) ~= 0) && (i <= n/2 + 1)
dx = -(1/2 * (-p0)/sqrt((I - p0*x(i))));
elseif (mod(i,2) ~= 0) && (i > n/2 + 1)
dx = -(1/2 * (-p1)/sqrt((I - p1*x(i))));
end
g = [g;dx];
end
end
end
%---------------------------------------------------------