How to use ~= operator as constraint function?

I have a function called "error" that I want to minimize with initial X0 = 1.34. The definition is:
function error = objectiveFcn(X,F)
D = 1.33;
M = 0.2;
error = (abs((((F)*(X/((F)*(1/M-1)+X))+(1-(X/((F)*(1/M-1)+X)))*X)-D)/D))*100;
end
The most straightforward answer is X=F=1.33 for which Error = 0 but I want X~=F.
I don't seem to be able to correctly include this under constraintFcn... Any suggestions?
UPDATE:
I have actually solved this in Excel, but I want to automate the process. This is how it looks like:
The exact solution is X=F=1.33 but this is not an accpetable result for me because X and F in reality can never be equal. The next best answer is X=1.265 and F=1.675 with an error of 0.01%.
F can be further defined as
F = (D-(1-V)*X)/V;
V=0.158;
Update 2: I realized this can be reduced to a single-variable problem. Here: but how do I extract the X for which X~=F. Is there a function for this?
D = 1.33;
M = 0.2;
V = 0.158;
err = @(X) (abs((((((D-(1-V)*X)/V))*(X/((((D-(1-V)*X)/V))*(1/M-1)+X))+(1-(X/((((D-(1-V)*X)/V))*(1/M-1)+X)))*X)-D)/D))*100;
fplot(err,[1.22,1.36])

3 Comments

The problem is ill-defined. Consider the simpler case of the 1D objective function f(x)=x.^2. What would be the minimum of this function subject to the constraint that x~=0?
Do not call a function "error", because error() is a very important built-in function. Shadowing it will cause serious troubles. By the way, your function is not called "error", but "objectiveFunction".
A nicer version of the formula:
err = 100 * abs((X / (1 / M - 1 + X / F) + (1 - X / (F / M - F + X)) * X - D) / D)
How do you search for a solution? With a local or global optimizer?
Thanks. I am using fmincon and it returns 1.33 as expected because whenever I add X=~F in the constraint, it won't run...

Sign in to comment.

 Accepted Answer

Here: but how do I extract the X for which X~=F. Is there a function for this?
Yes, but clearly you are not doing continuous optimization, so you should use min() rather than fmincon().
D = 1.33;
M = 0.2;
V = 0.158;
X=setdiff( 1.24:0.005:1.34 ,D);
err = (abs((((((D-(1-V).*X)./V)).*(X./((((D-(1-V).*X)./V)).*(1./M-1)+X))+(1-(X./((((D-(1-V).*X)./V)).*(1./M-1)+X))).*X)-D)./D)).*100;
[~,imin]=min(err);
X(imin)
ans = 1.2650

5 Comments

Thanks, but the answer shouldn't be 1.34. It should be 1.265 or something in that vicinity.
No, that was your original function. The function as of your updates looks different:
D = 1.33;
M = 0.2;
V = 0.158;
X=1.24:0.05:1.34;
err = (abs((((((D-(1-V)*X)/V))*(X/((((D-(1-V)*X)/V))*(1/M-1)+X))+(1-(X/((((D-(1-V)*X)/V))*(1/M-1)+X)))*X)-D)/D))*100;
plot(X,err)
Hmm... When I plot, this is what I get:
D = 1.33;
M = 0.2;
V = 0.158;
err = @(X) (abs((((((D-(1-V)*X)/V))*(X/((((D-(1-V)*X)/V))*(1/M-1)+X))+(1-(X/((((D-(1-V)*X)/V))*(1/M-1)+X)))*X)-D)/D))*100;
fplot(err,[1.22,1.36])
Warning: Function behaves unexpectedly on array inputs. To improve performance, properly vectorize your function to return an output with the same size and shape as the input arguments.
Never mind. I fixed my original answer. It now gives X=1.265
D = 1.33;
M = 0.2;
V = 0.158;
X=setdiff( 1.24:0.005:1.34 ,D);
err = (abs((((((D-(1-V).*X)./V)).*(X./((((D-(1-V).*X)./V)).*(1./M-1)+X))+(1-(X./((((D-(1-V).*X)./V)).*(1./M-1)+X))).*X)-D)./D)).*100;
[~,imin]=min(err);
X(imin)
ans = 1.2650
Perfect! Thanks a lot.

Sign in to comment.

More Answers (2)

For which solver? This is a 1-variable problem. If you want help, it does help if you explain more than you have done.
Note that ~= is not something you can specify for ANY solver, since that allows your solution to be infinitely close to equality, yet not exactly equal. And that makes your problem ill-posed.
Anyway, is this problem even meaningful?
D = 1.33;
M = 0.2;
F = 1.33;
err = @(X) (abs((((F)*(X/((F).*(1/M-1)+X))+(1-(X./((F)*(1/M-1)+X))).*X)-D)/D))*100;
fplot(err,[-3,50])
Warning: Function behaves unexpectedly on array inputs. To improve performance, properly vectorize your function to return an output with the same size and shape as the input arguments.
It looks like I missed a dot in there to vectorize it. Regardless, there seems to be only a single minimizer, at X == F. We can probably prove that to be the case with a little effort, merely by showing the behavior of this simple function as X grows large in both directions, that there are no points where the function has a zero derivative.
syms x
err(x)
ans = 
We could play with that and now look at the derivatives.
Or, is F also an unknown? If it is, then your objective is not formulated in a form that any solver in MATLAB will directly take. You seem to be treating F as a constant.

1 Comment

Thanks. Please see the details I have added to the original post. You are right, there's only one perfect solution and that is when X=F but since that's not acceptable for me, I'm searching for the next best combination of X and F that gives the lowest error.
F is not known. In general the problem is some constant X + some constant F should be as close as possible to D which is 1.33. But X cannot be equal to F.

Sign in to comment.

Asked:

on 7 Sep 2021

Commented:

on 7 Sep 2021

Community Treasure Hunt

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

Start Hunting!