fmincon for multiple variables
이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
이전 댓글 표시
1 개 추천
Hi,
I want to perform a constrained optimization,that makes fmincon a good option.
However, it returns the error '' fmincon requires all values returned by the functions to be of data type double''.
Y is the objective that I want to optimize,with three variables a1,a2,a3.
function Y = optfun(z)
a1 = z(1);
a2 = z(2);
a3 = z(3);
y1 = abs(vpa("0.129")*a1*sym(1i) + vpa("0.01")*a2*sym(1i) + vpa("8.57e-4")*a3*sym(1i) - vpa("2410.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) - vpa("2410.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) - vpa("2410.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("25.0") + vpa("96.4i"))/abs(vpa("0.129")*a1*sym(1i) + vpa("0.01")*a2*sym(1i) + vpa("8.57e-4")*a3*sym(1i) + vpa("2410.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) + vpa("2410.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) + vpa("2410.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("125.0") + vpa("96.4i"));
y2 = abs(vpa("0.173")*a1*sym(1i) + vpa("0.0135")*a2*sym(1i) + vpa("0.00115")*a3*sym(1i) - vpa("3250.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) - vpa("3250.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) - vpa("3250.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("25.0") + vpa("130.0i"))/abs(vpa("0.173")*a1*sym(1i) + vpa("0.0135")*a2*sym(1i) + vpa("0.00115")*a3*sym(1i) + vpa("3250.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) + vpa("3250.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) + vpa("3250.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("125.0") + vpa("130.0i"));
y3 = abs(vpa("0.197")*a1*sym(1i) + vpa("0.0153")*a2*sym(1i) + vpa("0.00131")*a3*sym(1i) - vpa("3690.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) - vpa("3690.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) - vpa("3690.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("25.0") + vpa("148.0i"))/abs(vpa("0.197")*a1*sym(1i) + vpa("0.0153")*a2*sym(1i) + vpa("0.00131")*a3*sym(1i) + vpa("3690.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) + vpa("3690.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) + vpa("3690.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("125.0") + vpa("148.0i"));
Y = (1-y1)+(1-y3)+(y2);
end
By the way,I want to know is there possibilities to add constration to my objective value?
For example, 0<[y1,y2,y3]<1.
Any help will be appreciate,thx!
댓글 수: 1
Stephen23
2023년 8월 23일
Note: the context is explained in the comments here:
채택된 답변
Y = double( (1-y1)+(1-y3)+(y2) );
But I don't see why you are using vpa and other sym operations. I don't think it really increases precision for you since all your coefficients have substantially less than 32 decimal places.
댓글 수: 20
By the way,I want to know is there possibilities to add constration to my objective value? For example, 0<[y1,y2,y3]<1.
Of course! That's why it's called fmincon. For the constraints you describe, you would need to use the nonlcon argument.
I want to add them on y1 y2 y3.
Yes, you will need a nonlinear constraint for that.
I have not used the optimization app, but presumably the "Nonlinear" button will prompt you to provide a constraint function handle as described here:
I think maybe I can create a constraint function like this:
function [c,ceq] = constraintFcn(z)
% Example:
% Constrain a solution to the region
% x^2 + y^2 <= 5
% x^2 + y^2 >= 2
% y = x^3
% Edit the lines below with your calculation
% Note, if no inequality constraints, specify c = []
% Note, if no equality constraints, specify ceq = []
y1 = z(1);
y2 = z(2);
y3 = z(3);
c(1) = y1-1;
c(2) = y3-1;
ceq=[];
end
Matt J
2023년 8월 23일
Yes, although this only implements 2 of the 6 bounds you said you wanted.
@Matt J Hi,sorry to bother you again.
After I try my constraint function,the value didn't meet my requirement.(y1,y2,y3 returns the values of 0.2 0.2 0.2,respectively)
I'm trying to add constraint to my output function,not variables.
Is it correct to write the code like this?
function [c,ceq] = constraintFcn(z)
% My Constraint
% 0.9 <= y1 <= 1
% 0 <= y2 <= 0.1
% 0.9 <= y3 <= 1
y1 = z(1);
y2 = z(2);
y3 = z(3);
c(1) = -y1+0.9;
c(2) = y2-0.1;
c(3) = -y3+0.9;
c(4) = y1-1;
c(5) = y2;
c(6) = y3-1;
ceq=[];
end
All these constraints can be set in the arrays "lb" and "ub" which are direct inputs to "fmincon":
lb = [0.9 0 0.9];
ub = [1 0.1 1]
And c(5) = y2 is incorrect because it sets y2 <= 0, not y2 >= 0.
Guan Hao
2023년 8월 24일
Thanks for your reply.
Isn't that setting bounds for the variables (a1 a2 a3)?
I want to set constrait to y1 y2 y3,which are functions of a1 a2 a3.
Torsten
2023년 8월 24일
Yes, you are right.
But c(5) should be -y2, not y2.
But you set the constraints on the parameters to be fitted, not on y1, y2 and y3 which you claim are functions of a1, a2 and a3. The vector z in "constraintFcn" is the vector (a1,a2,a3) from which you first have to compute y1,y2 and y3 (whatever they are). That's why I said that its the same as setting
lb = [0.9 0 0.9];
ub = [1 0.1 1]
And as I can see from your output: the vector x returned from "fmincon" satisfies lb <= x <= ub.
Compute y1, y2 and y3 in "constraintFcn" from the z-vector and set the constraints as you did:
y = fun_z_to_y(z);
y1 = y(1);
y2 = y(2);
y3 = y(3);
c(1) = -y1+0.9;
c(2) = y2-0.1;
c(3) = -y3+0.9;
c(4) = y1-1;
c(5) = -y2;
c(6) = y3-1;
@Torsten Thanks for your patience.
Did you mean something like this? It returns a error message that '' fmincon requires all values returned by the functions to be of data type double''.
Sorry,I must misunderstand your meaning...
function [c,ceq] = constraintFcn_new(z)
% My Constraint
% 0.9 <= y1 <= 1
% 0 <= y2 <= 0.1
% 0.9 <= y3 <= 1
a1 = z(1);
a2 = z(2);
a3 = z(3);
y = [abs(- vpa("0.122")*a1*sym(1i) - vpa("0.00895")*a2*sym(1i) - vpa("7.32e-4")*a3*sym(1i) + vpa("1530.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("1530.0i")/(vpa("50.0") + vpa("8.0e-6")*a3 + vpa("4.0e-4")*a2 + vpa("0.02")*a1) + vpa("1530.0i")/(vpa("50.0") + vpa("6.4e-5")*a3 + vpa("0.0016")*a2 + vpa("0.04")*a1) + vpa("1530.0i")/(vpa("50.0") + vpa("5.12e-4")*a3 + vpa("0.0064")*a2 + vpa("0.08")*a1) + vpa("1530.0i")/(vpa("50.0") + vpa("2.16e-4")*a3 + vpa("0.0036")*a2 + vpa("0.06")*a1) - vpa("25.0") - vpa("102.0i"))/abs(vpa("0.122")*a1*sym(1i) + vpa("0.00895")*a2*sym(1i) + vpa("7.32e-4")*a3*sym(1i) + vpa("1530.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("1530.0i")/(vpa("50.0") + vpa("8.0e-6")*a3 + vpa("4.0e-4")*a2 + vpa("0.02")*a1) + vpa("1530.0i")/(vpa("50.0") + vpa("6.4e-5")*a3 + vpa("0.0016")*a2 + vpa("0.04")*a1) + vpa("1530.0i")/(vpa("50.0") + vpa("5.12e-4")*a3 + vpa("0.0064")*a2 + vpa("0.08")*a1) + vpa("1530.0i")/(vpa("50.0") + vpa("2.16e-4")*a3 + vpa("0.0036")*a2 + vpa("0.06")*a1) + vpa("125.0") + vpa("102.0i"));
abs(- vpa("0.176")*a1*sym(1i) - vpa("0.0129")*a2*sym(1i) - vpa("0.00106")*a3*sym(1i) + vpa("2200.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("2200.0i")/(vpa("50.0") + vpa("8.0e-6")*a3 + vpa("4.0e-4")*a2 + vpa("0.02")*a1) + vpa("2200.0i")/(vpa("50.0") + vpa("6.4e-5")*a3 + vpa("0.0016")*a2 + vpa("0.04")*a1) + vpa("2200.0i")/(vpa("50.0") + vpa("5.12e-4")*a3 + vpa("0.0064")*a2 + vpa("0.08")*a1) + vpa("2200.0i")/(vpa("50.0") + vpa("2.16e-4")*a3 + vpa("0.0036")*a2 + vpa("0.06")*a1) - vpa("25.0") - vpa("147.0i"))/abs(vpa("0.176")*a1*sym(1i) + vpa("0.0129")*a2*sym(1i) + vpa("0.00106")*a3*sym(1i) + vpa("2200.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("2200.0i")/(vpa("50.0") + vpa("8.0e-6")*a3 + vpa("4.0e-4")*a2 + vpa("0.02")*a1) + vpa("2200.0i")/(vpa("50.0") + vpa("6.4e-5")*a3 + vpa("0.0016")*a2 + vpa("0.04")*a1) + vpa("2200.0i")/(vpa("50.0") + vpa("5.12e-4")*a3 + vpa("0.0064")*a2 + vpa("0.08")*a1) + vpa("2200.0i")/(vpa("50.0") + vpa("2.16e-4")*a3 + vpa("0.0036")*a2 + vpa("0.06")*a1) + vpa("125.0") + vpa("147.0i"));
abs(- vpa("0.223")*a1*sym(1i) - vpa("0.0163")*a2*sym(1i) - vpa("0.00134")*a3*sym(1i) + vpa("2790.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("2790.0i")/(vpa("50.0") + vpa("8.0e-6")*a3 + vpa("4.0e-4")*a2 + vpa("0.02")*a1) + vpa("2790.0i")/(vpa("50.0") + vpa("6.4e-5")*a3 + vpa("0.0016")*a2 + vpa("0.04")*a1) + vpa("2790.0i")/(vpa("50.0") + vpa("5.12e-4")*a3 + vpa("0.0064")*a2 + vpa("0.08")*a1) + vpa("2790.0i")/(vpa("50.0") + vpa("2.16e-4")*a3 + vpa("0.0036")*a2 + vpa("0.06")*a1) - vpa("25.0") - vpa("186.0i"))/abs(vpa("0.223")*a1*sym(1i) + vpa("0.0163")*a2*sym(1i) + vpa("0.00134")*a3*sym(1i) + vpa("2790.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("2790.0i")/(vpa("50.0") + vpa("8.0e-6")*a3 + vpa("4.0e-4")*a2 + vpa("0.02")*a1) + vpa("2790.0i")/(vpa("50.0") + vpa("6.4e-5")*a3 + vpa("0.0016")*a2 + vpa("0.04")*a1) + vpa("2790.0i")/(vpa("50.0") + vpa("5.12e-4")*a3 + vpa("0.0064")*a2 + vpa("0.08")*a1) + vpa("2790.0i")/(vpa("50.0") + vpa("2.16e-4")*a3 + vpa("0.0036")*a2 + vpa("0.06")*a1) + vpa("125.0") + vpa("186.0i"));];
y1 = y(1);
y2 = y(2);
y3 = y(3);
c(1) = -y1+0.9;
c(2) = y2-0.1;
c(3) = -y3+0.9;
c(4) = y1-1;
c(5) = -y2;
c(6) = y3-1;
ceq=[];
end
Insert the line
y = double(y)
before you assign
y1 = y(1);
y2 = y(2);
y3 = y(3);
...
I wonder why you need symbolic variables to define y. Using numerical variables will usually speed up the numerical solver "fmincon" remarkably.
Rather than duplicating your objective function's code in your constraint function, I'd define your objective function to return multiple outputs (the second and later ones being the quantities you're trying to constraint) and call it with multiple outputs in your constraint function.
Note that as per the description of the fun input argument on the fmincon documentation page, if you're using the SpecifyObjectiveGradient and HessianFcn options you may need to push these "supplementary outputs" later in the output list.
Y = optfun([1; 2; 3])
Y = 1.8024
confun([1; 2; 3])
Y is 1.80239
y1 is 0.198814
y2 is 0.198692
y3 is 0.197487
check: 1.80239
function [Y, y1, y2, y3] = optfun(z)
a1 = z(1);
a2 = z(2);
a3 = z(3);
y1 = abs(vpa("0.129")*a1*sym(1i) + vpa("0.01")*a2*sym(1i) + vpa("8.57e-4")*a3*sym(1i) - vpa("2410.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) - vpa("2410.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) - vpa("2410.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("25.0") + vpa("96.4i"))/abs(vpa("0.129")*a1*sym(1i) + vpa("0.01")*a2*sym(1i) + vpa("8.57e-4")*a3*sym(1i) + vpa("2410.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) + vpa("2410.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) + vpa("2410.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("125.0") + vpa("96.4i"));
y2 = abs(vpa("0.173")*a1*sym(1i) + vpa("0.0135")*a2*sym(1i) + vpa("0.00115")*a3*sym(1i) - vpa("3250.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) - vpa("3250.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) - vpa("3250.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("25.0") + vpa("130.0i"))/abs(vpa("0.173")*a1*sym(1i) + vpa("0.0135")*a2*sym(1i) + vpa("0.00115")*a3*sym(1i) + vpa("3250.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) + vpa("3250.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) + vpa("3250.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("125.0") + vpa("130.0i"));
y3 = abs(vpa("0.197")*a1*sym(1i) + vpa("0.0153")*a2*sym(1i) + vpa("0.00131")*a3*sym(1i) - vpa("3690.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) - vpa("3690.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) - vpa("3690.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("25.0") + vpa("148.0i"))/abs(vpa("0.197")*a1*sym(1i) + vpa("0.0153")*a2*sym(1i) + vpa("0.00131")*a3*sym(1i) + vpa("3690.0i")/(vpa("50.0") + vpa("3.7e-5")*a3 + vpa("0.00111")*a2 + vpa("0.0333")*a1) + vpa("3690.0i")/(vpa("50.0") + vpa("2.96e-4")*a3 + vpa("0.00444")*a2 + vpa("0.0667")*a1) + vpa("3690.0i")/(vpa("50.0") + vpa("0.001")*a3 + vpa("0.01")*a2 + vpa("0.1")*a1) + vpa("125.0") + vpa("148.0i"));
% Converting to double after the fact is simpler to type for this example
% than removing all your vpa and sym calls, but for your real code I'd
% perform the removal to avoid involving Symbolic Math Toolbox at all
y1 = double(y1);
y2 = double(y2);
y3 = double(y3);
Y = (1-y1)+(1-y3)+(y2);
end
function confun(z)
% Reuse rather than duplicating
[Y, y1, y2, y3] = optfun(z);
fprintf(" Y is %g\n y1 is %g\n y2 is %g\n y3 is %g\n", Y, y1, y2, y3)
fprintf("check: %g\n", (1-y1)+(1-y3)+y2)
end
Matt J
2023년 8월 24일
Or better still, follow the guidelines here,
for avoiding repeated computations in the constraint and objective function code.
This is all of my code,it removes all vpa and sym things.
However,when I run the optimization,it seems that the constraints are on a1,a2,a3 again.

function [Y, y1, y2, y3] = optfun_new(z)
Z01=50;
Z02=75;
v=3e+8;
section=100;
L=0.1;
a=L/section;
a0=Z01;
f1=1e+9;
f2=2e+9;
w1=2*pi*f1;
w2=2*pi*f2;
syms w
beta=w/v;
a1 = z(1);
a2 = z(2);
a3 = z(3);
% ABCD Matrix
for m=1:1:section
l=m*a;
Z0=a0+(a1*l)+(a2*(l^2))+(a3*(l^3));
B(m)=1i*Z0*sin(beta*a);
C(m)=1i*(1/Z0)*sin(beta*a);
end
Bsum=sum(B);
Csum=sum(C);
ABCD=[1 Bsum ; Csum 1];
% Convert into S11
S11=((ABCD(1,2)-ABCD(2,1)*Z01*Z02)+((ABCD(1,1)*Z02)-(ABCD(2,2)*Z01)))/((ABCD(1,2)+ABCD(2,1)*Z01*Z02)+((ABCD(1,1)*Z02)+(ABCD(2,2)*Z01)));
gamma=abs(S11);
% Optimize objective
y1=subs(gamma,w,w1);
y2=subs(gamma,w,((w1+w2)/2));
y3=subs(gamma,w,w2);
% Converting to double after the fact is simpler to type for this example
% than removing all your vpa and sym calls, but for your real code I'd
% perform the removal to avoid involving Symbolic Math Toolbox at all
y1 = double(y1);
y2 = double(y2);
y3 = double(y3);
Y = (1-y1)+(1-y3)+(y2);
end
function [c,ceq] = constraintFcn_new(z)
% Reuse rather than duplicating
[Y, y1, y2, y3] = optfun(z);
fprintf(" Y is %g\n y1 is %g\n y2 is %g\n y3 is %g\n", Y, y1, y2, y3)
fprintf("check: %g\n", (1-y1)+(1-y3)+y2)
y1 = z(1);
y2 = z(2);
y3 = z(3);
c(1) = -y1+0.9;
c(2) = y2-0.1;
c(3) = -y3+0.9;
c(4) = y1-1;
c(5) = -y2;
c(6) = y3-1;
ceq=[];
end
You're calling the optfun to generate the intermediate values of your objective function, then after the fprintf lines (which I added just to show you that the constraint function had correctly obtained the values from the objective function) you throw away those intermediate values and replace them with elements of the input with which fmincon called the constraint function. Don't do that. Delete these lines from your constraint function:
y1 = z(1);
y2 = z(2);
y3 = z(3);
Guan Hao
2023년 8월 25일
@Steven Lord Thank you sir !!! It's working now.
추가 답변 (0개)
카테고리
도움말 센터 및 File Exchange에서 Linear Least Squares에 대해 자세히 알아보기
태그
참고 항목
웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)


