How to set lower bound lb as a function of optimization variable.

I am solving one optimization using fmincon. Objectives function is a variable of x1,x2,x3.
B= 0; c =[ 0 0.1736 0.0693; 0 0 0.1736]
c = 2x3
0 0.1736 0.0693 0 0 0.1736
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
l_op = 6.3247;
rho = 1.225;
R=37.5; A = pi * R^2;
Z = 8;
n =3;
k= 0.1;
Th = sym('Th', [1, n]);
x = sym('x', [1, n]);
Lam = sym('Lam', [1, n]);
Pt = sym('P_opt', [1, n]);
Per = sym('Per', [1, n]);
z = sym('z', [1, n]);
z(1) = Z;
for i = 1:n
if i > 1
term_sum = 0;
for j = 1:i-1
term_sum = term_sum + ((1 - sqrt(1 - Th(j))) * c(j, i))^2;
end
z(i) = Z * (1 - sqrt(term_sum));
end
Lam(i) = (x(i) * R) / z(i);
Th(i) = (0.000086 * B - 0.0026) * Lam(i)^3 + (-0.0018 * B + 0.0481) * Lam(i)^2 + (0.008 * B - 0.165) * Lam(i) + (-0.0116 * B + 0.3);
Per(i) = 0.22 * (116 / (Lam(i) + 0.08 * B) - 4.06 / (B^3 + 1) - 0.4 * B - 5) * exp(-12.5 / (Lam(i) + 0.08 * B) + 0.4375 / (B^3 + 1));
Pt(i) = 0.5 * rho * A * Per(i) * z(i)^3;
end
objective = -sum(Pt)
objective = 
Obj = matlabFunction(objective, 'Vars', {x});
% Lower and upper bounds
lb = 0.1687 * z(i) % z(i) is a function of x(i) *corrected
Unrecognized function or variable 'v'.
ub = 1.6867*ones(1,n);
% Initial guess
x0 = ones(1,n);
% Constraints
Aeq = [];
beq = [];
% Optimization using fmincon
options = optimoptions('fmincon', 'Display', 'iter', 'Algorithm', 'interior-point');
% % Optimize the objective function
[x_opt, fval_opt] = fmincon(Obj, x0, [], [], Aeq, beq, lb, ub, [], options);
In my optimization lower bound of the optimization is a function of optimaztion variables. How can I solve it? fmincon can be able to do it or another optimization tools can be chosen?

2 Comments

That is not a "bound" constraint. It is an inequality constraint.
How can I modify it? Becuase z(i) is the function of x(i)? @John D'Errico

Sign in to comment.

Answers (1)

Torsten
Torsten on 10 May 2024
Edited: Torsten on 10 May 2024
Use function "nonlcon" to define nonlinear equality and inequality constraints.
If v(i) depends linearly on the solution variable vector x, you could also use A and b in the call to "fmincon":

17 Comments

I corrected the mistake there. How can I formulate nonlcon? lb = 0.1687 * z(i) where z(i) is a function of x(i) and explicit form. If that is nonlinear inequality constraint then what will be written in lb? Is lb = [] ?
Another thing is how did you wrote objective function in a beautiful way? Any matlab command to write or simplify my objective function? For small 2-3 variables it is easy to write manually but for large variable it is difficult. @Torsten
How can I formulate nonlcon? lb = 0.1687 * z(i) where z(i) is a function of x(i) and explicit form. If that is nonlinear inequality constraint then what will be written in lb? Is lb = [] ?
Set c(i) in nonlcon as the expression that you want to have <= 0. E.g. if you wanted to have x(i) >= 0.1687*v(i) for i = 1,2,3, compute v(i) and set c(1:3) = 0.1687*v(1:3) - x(1:3).
Another thing is how did you wrote objective function in a beautiful way? Any matlab command to write or simplify my objective function? For small 2-3 variables it is easy to write manually but for large variable it is difficult.
I did nothing - it's the usual display style for MATLAB Online.
B= 0; cw =[ 0 0.1736 0.0693; 0 0 0.1736]
cw = 2x3
0 0.1736 0.0693 0 0 0.1736
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
l_op = 6.3247;
rho = 1.225;
R=37.5; A = pi * R^2;
Z = 8;
n =3;
k= 0.1;
Th = sym('Th', [1, n]);
x = sym('x', [1, n]);
Lam = sym('Lam', [1, n]);
Pt = sym('P_opt', [1, n]);
Per = sym('Per', [1, n]);
z = sym('z', [1, n]);
z(1) = Z;
for i = 1:n
if i > 1
term_sum = 0;
for j = 1:i-1
term_sum = term_sum + ((1 - sqrt(1 - Th(j))) * cw(j, i))^2;
end
z(i) = Z * (1 - sqrt(term_sum));
end
Lam(i) = (x(i) * R) / z(i);
Th(i) = (0.000086 * B - 0.0026) * Lam(i)^3 + (-0.0018 * B + 0.0481) * Lam(i)^2 + (0.008 * B - 0.165) * Lam(i) + (-0.0116 * B + 0.3);
Per(i) = 0.22 * (116 / (Lam(i) + 0.08 * B) - 4.06 / (B^3 + 1) - 0.4 * B - 5) * exp(-12.5 / (Lam(i) + 0.08 * B) + 0.4375 / (B^3 + 1));
Pt(i) = 0.5 * rho * A * Per(i) * z(i)^3;
end
objective = -sum(Pt)
objective = 
Obj = matlabFunction(objective, 'Vars', {x});
% Define nonlinear constraint functions for each variable
c = cell(1, n);
for i = 1:n
c{i} = @(x) 0.1687 * v(i) - x(i);
end
% Lower and upper bounds
lb = [];
ub = 1.6867 * ones(1, n);
% Initial guess
x0 = ones(1, n);
% Constraints
Aeq = [];
beq = [];
% Optimization using fmincon
options = optimoptions('fmincon', 'Display', 'iter', 'Algorithm', 'interior-point');
% Optimize the objective function
[x_opt, fval, exitflag, output] = fmincon(Obj, x0, [], [], Aeq, beq, [], ub, nonlcon, options);
Unrecognized function or variable 'x0'.
I am getting error. What should I do here? @Torsten
You really need to look further into your lb being empty. lb being empty means the same as -infinity as the lower bound. However, you have division by several of your variables, so you would pass through infinity at 0.
B= 0; cw =[ 0 0.1736 0.0693; 0 0 0.1736]
cw = 2x3
0 0.1736 0.0693 0 0 0.1736
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
l_op = 6.3247;
rho = 1.225;
R=37.5; A = pi * R^2;
Z = 8;
n =3;
k= 0.1;
Th = sym('Th', [1, n]);
x = sym('x', [1, n]);
Lam = sym('Lam', [1, n]);
Pt = sym('P_opt', [1, n]);
Per = sym('Per', [1, n]);
z = sym('z', [1, n]);
z(1) = Z;
for i = 1:n
if i > 1
term_sum = 0;
for j = 1:i-1
term_sum = term_sum + ((1 - sqrt(1 - Th(j))) * cw(j, i))^2;
end
z(i) = Z * (1 - sqrt(term_sum));
end
Lam(i) = (x(i) * R) / z(i);
Th(i) = (0.000086 * B - 0.0026) * Lam(i)^3 + (-0.0018 * B + 0.0481) * Lam(i)^2 + (0.008 * B - 0.165) * Lam(i) + (-0.0116 * B + 0.3);
Per(i) = 0.22 * (116 / (Lam(i) + 0.08 * B) - 4.06 / (B^3 + 1) - 0.4 * B - 5) * exp(-12.5 / (Lam(i) + 0.08 * B) + 0.4375 / (B^3 + 1));
Pt(i) = 0.5 * rho * A * Per(i) * z(i)^3;
end
objective = -sum(Pt)
objective = 
Obj = matlabFunction(objective, 'Vars', {x});
c = cell(1, n);
for i = 1:n
c{i} = @(x) 0.1687 * v(i) - x(i);
end
lb = [];
ub = 1.6867 * ones(1, n);
% Initial guess
w0 = ones(1, n);
% Constraints
Aeq = [];
beq = [];
%added
x0 = [.1, .2, .3];
nonlcon = [];
% Optimization using fmincon
options = optimoptions('fmincon', 'Display', 'iter', 'Algorithm', 'interior-point');
% Optimize the objective function
[x_opt, fval, exitflag, output] = fmincon(Obj, x0, [], [], Aeq, beq, [], ub, nonlcon, options);
First-order Norm of Iter F-count f(x) Feasibility optimality step 0 4 -5.332679e+03 0.000e+00 8.704e+04 Objective function returned complex; trying a new point... 1 12 -5.118628e+05 0.000e+00 3.377e+05 1.381e+00 2 16 -1.393827e+06 0.000e+00 4.918e+05 2.165e+00 Objective function returned complex; trying a new point... 3 22 -1.404491e+06 0.000e+00 6.320e+05 5.980e-01 4 27 -1.410640e+06 0.000e+00 7.113e+05 5.000e-01 5 32 -1.597991e+06 0.000e+00 2.592e+05 7.208e-01 6 38 -1.609659e+06 0.000e+00 2.175e+05 1.637e-01 7 45 -1.630059e+06 0.000e+00 1.653e+05 3.450e-01 8 49 -1.641995e+06 0.000e+00 2.363e+04 1.519e-01 9 53 -1.642236e+06 0.000e+00 2.077e+03 1.828e-02 10 57 -1.642238e+06 0.000e+00 3.969e+01 1.745e-03 11 61 -1.642238e+06 0.000e+00 9.937e-01 4.049e-05 12 65 -1.642238e+06 0.000e+00 1.398e-01 8.400e-07 13 69 -1.642238e+06 0.000e+00 1.000e-01 9.049e-08 14 73 -1.642238e+06 0.000e+00 4.100e-02 2.187e-07 15 77 -1.642238e+06 0.000e+00 2.894e-02 2.661e-08 16 81 -1.642238e+06 0.000e+00 7.093e-02 1.317e-08 Local minimum possible. Constraints satisfied. fmincon stopped because the size of the current step is less than the value of the step size tolerance and constraints are satisfied to within the value of the constraint tolerance.
x_opt
x_opt = 1x3
1.2516 1.1989 1.2815
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
fval
fval = -1.6422e+06
Why did you provide nonlinear inequality is none?
nonlcon = [];
Here nonlcon is
c = cell(1, n);
for i = 1:n
c{i} = @(x) 0.1687 * z(i) - x(i);
end
since as you informed early this is nonlinear inequality so lb constrained shifted there, it means lb = [].
You cannot use a cell array of function handles as the non-linear function.
You can provide
nonlcon = @(x) cellfun(@(C) C(x), c);
You have the problem that v is not defined.
B= 0; cw =[ 0 0.1736 0.0693; 0 0 0.1736]
cw = 2x3
0 0.1736 0.0693 0 0 0.1736
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
l_op = 6.3247;
rho = 1.225;
R=37.5; A = pi * R^2;
Z = 8;
n =3;
k= 0.1;
Th = sym('Th', [1, n]);
x = sym('x', [1, n]);
Lam = sym('Lam', [1, n]);
Pt = sym('P_opt', [1, n]);
Per = sym('Per', [1, n]);
z = sym('z', [1, n]);
z(1) = Z;
for i = 1:n
if i > 1
term_sum = 0;
for j = 1:i-1
term_sum = term_sum + ((1 - sqrt(1 - Th(j))) * cw(j, i))^2;
end
z(i) = Z * (1 - sqrt(term_sum));
end
Lam(i) = (x(i) * R) / z(i);
Th(i) = (0.000086 * B - 0.0026) * Lam(i)^3 + (-0.0018 * B + 0.0481) * Lam(i)^2 + (0.008 * B - 0.165) * Lam(i) + (-0.0116 * B + 0.3);
Per(i) = 0.22 * (116 / (Lam(i) + 0.08 * B) - 4.06 / (B^3 + 1) - 0.4 * B - 5) * exp(-12.5 / (Lam(i) + 0.08 * B) + 0.4375 / (B^3 + 1));
Pt(i) = 0.5 * rho * A * Per(i) * z(i)^3;
end
objective = -sum(Pt)
objective = 
Obj = matlabFunction(objective, 'Vars', {x});
c = cell(1, n);
for i = 1:n
c{i} = @(x) 0.1687 * v(i) - x(i);
end
lb = [];
ub = 1.6867 * ones(1, n);
% Initial guess
w0 = ones(1, n);
% Constraints
Aeq = [];
beq = [];
%added
x0 = [.1, .2, .3];
nonlcon = @(x) cellfun(@(C) C(x), c);
% Optimization using fmincon
options = optimoptions('fmincon', 'Display', 'iter', 'Algorithm', 'interior-point');
% Optimize the objective function
[x_opt, fval, exitflag, output] = fmincon(Obj, x0, [], [], Aeq, beq, [], ub, nonlcon, options);
Unrecognized function or variable 'v'.

Error in solution>@(x)0.1687*v(i)-x(i) (line 33)
c{i} = @(x) 0.1687 * v(i) - x(i);

Error in solution>@(C)C(x) (line 46)
nonlcon = @(x) cellfun(@(C) C(x), c);

Error in solution>@(x)cellfun(@(C)C(x),c) (line 46)
nonlcon = @(x) cellfun(@(C) C(x), c);

Error in constrfunEvaluator (line 5)
[cin, ceq] = feval(Nonlcon, x, self.FunArgs.AdditionalParameters{:});

Error in OptimFunctions/constraints (line 415)
[cin_,ceq_,cingrad_,ceqgrad_] = self.ConstraintFunAndGrad(self,self.ConFcn{3},...

Error in OptimFunctions/constraint_first_eval (line 662)
[cin,ceq,self] = self.constraints(X0);

Error in fmincon (line 516)
funObj.constraint_first_eval(X);
x_opt
fval
If the v are constant, then 0.1687 * v(i) - x(i) <= 0 is the same as 0.1687*v(i) <= x(i)
That in turn would be the same as setting lb = 0.1687*v with no nonlcon used.
Thans for the reply @Walter Roberson. v(i) is a typo error. v(i) should be replaced to z(i), and z(i) is a function of x(i).
I think the error is here.
c = cell(1, n);
for i = 1:n
c{i} = @(x) 0.1687 * z(i) - x(i);
end
But I am getting
c =
1×3 cell array
{@(x)0.1687*z(i)-x(i)} {@(x)0.1687*z(i)-x(i)} {@(x)0.1687*z(i)-x(i)}
but my constraint is
{@(x1)0.1687*z(1)-x(1)} {@(x2)0.1687*z(2)-x(2)} {@(x3)0.1687*z(3)-x(3)}
here z(1) is constant, z(2) is a function of x(1) and z(3) is a function of x(1) and x(2).
z(1) =8;
z(2) =8 - 8*(((217*((8775*x1^3)/32768 - (4329*x1^2)/4096 + (99*x1)/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) ;
z(3) = 8 - 8*(((217*(7/10 - (4329*x2^2)/(64*(8*(((217*((8775*x1^3)/32768 - (4329*x1^2)/4096 + (99*x1)/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)^2) - (8775*x2^3)/(64*(8*(((217*((8775*x1^3)/32768 - (4329*x1^2)/4096 + (99*x1)/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)^3) - (99*x2)/(16*(8*(((217*((8775*x1^3)/32768 - (4329*x1^2)/4096 + (99*x1)/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)))^(1/2))/1250 - 217/1250)^2 + ((693*((8775*x1^3)/32768 - (4329*x1^2)/4096 + (99*x1)/128 + 7/10)^(1/2))/10000 - 693/10000)^2)^(1/2) ;
% Lower and upper bounds
lb = [];
ub = 1.6867*ones(1,n);
% Initial guess
x0 = ones(1,n);
% Constraints
Aeq = [];
beq = [];
% Optimization using fmincon
options = optimoptions('fmincon', 'Display', 'iter', 'Algorithm', 'interior-point');
% % Optimize the objective function
[x_opt, fval, exitflag, output] = fmincon(Obj, x0, [], [], Aeq, beq, [], ub, @nonlcon, options)
function [c,ceq] = nonlcon(x)
z(1) = 8;
z(2) = 8 - 8*(((217*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) ;
z(3) = 8 - 8*(((217*(7/10 - (4329*x(2)^2)/(64*(8*(((217*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)^2) - (8775*x(2)^3)/(64*(8*(((217*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)^3) - (99*x(2))/(16*(8*(((217*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)))^(1/2))/1250 - 217/1250)^2 + ((693*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/10000 - 693/10000)^2)^(1/2) ;
c(1) = 0.1687*z(1)-x(1);
c(2) = 0.1687*z(2)-x(2);
c(3) = 0.1687*z(3)-x(3);
ceq = [];
end
I already addressed or expressed z(i) in the code, why should I again define here?
Then do everything in the script part:
z = @(x)[8;...
8 - 8*(((217*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) ;...
8 - 8*(((217*(7/10 - (4329*x(2)^2)/(64*(8*(((217*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)^2) - (8775*x(2)^3)/(64*(8*(((217*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)^3) - (99*x(2))/(16*(8*(((217*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/1250 - 217/1250)^2)^(1/2) - 8)))^(1/2))/1250 - 217/1250)^2 + ((693*((8775*x(1)^3)/32768 - (4329*x(1)^2)/4096 + (99*x(1))/128 + 7/10)^(1/2))/10000 - 693/10000)^2)^(1/2) ];
nonlcon = @(x)deal(0.1687*z(x)-x,[])
[x_opt, fval, exitflag, output] = fmincon(Obj, x0, [], [], Aeq, beq, [], ub, nonlcon, options)
I'm not sure if the input x-vector to "nonlcon" is a column vector. If it's a row vector, you will have to transpose either x or z in the above code fragment.
but my constraint is
{@(x1)0.1687*z(1)-x(1)} {@(x2)0.1687*z(2)-x(2)} {@(x3)0.1687*z(3)-x(3)}
The first of those accepts a parameter that for the purposes of the function will be referred to ax x1 . It proceeds to ignore that parameter and to try to calculate 0.1687*z(1)-x(1) . It happens that x(1) is defined because of the
x = sym('x', [1, n]);
so you are defining an anonymous function that refers to unresolved symbolic variables. That will fail at evaluation time, as the result of the nonlinear constraints must be numeric and not contain any unresolved symbolic functions.
I suspect that what you are trying to say is that you expect
{@(x)0.1687*z(1)-x(1)} {@(x)0.1687*z(2)-x(2)} {@(x)0.1687*z(3)-x(3)}
but instead you are seeing
{@(x)0.1687*z(i)-x(i)} {@(x)0.1687*z(i)-x(i)} {@(x)0.1687*z(i)-x(i)}
What you have to realize is that at that point, i is a captured variable. The first of those expressions evaluates to approximately
> functions(c{1})
struct with fields:
function: '@(x)0.1687*z(i)-x(i)'
type: 'anonymous'
file: ''
workspace: {[1×1 struct]}
within_file_path: ''
>> ans.workspace{1}
ans =
struct with fields:
z: [0.814723686393179 0.905791937075619 0.126986816293506]
i: 1
When a @() expression is constructed, the code after the @() expression is saved literally (except with extra spaces taken out and with commas inserted into lists), along with copies of the current values of all variables that have been mentioned by name; when the anonymous function is executed, the saved workspace is inserted and the code is executed.
To be explicit, when a @() expression is constructed, MATLAB does not evaluate any of the terms -- MATLAB would not construct
@(x) 0.1687*0.814723686393179-x(1)
@Walter Roberson what will be the resolution in that case? I want to generalize my system in that situation I want to use z(i) generalize.
Although you see
{@(x)0.1687*z(i)-x(i)}
the function handle that is stored will record z and i and will use the recorded z and i at the time of execution, so that at execution time it will get the correct values. It will execute without problem; you do not need to change it.
I just saw that z is defined in your loop. In this case, simply use
zfun = matlabFunction(z,'Vars',{x})
nonlcon = @(x)deal(0.1687*zfun(x)-x,[])
Here it is assumed that the x passed from "fmincon" to "nonlcon" is a row vector.
Thanks a lot for your valuable input regarding this. @Torsten @Walter Roberson.

Sign in to comment.

Asked:

on 10 May 2024

Commented:

on 12 May 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!