I have a problem with my MATLAB code that I write to minimize this function with two constraints (one of them is inequality and the other one is equality) with Lagrange Multipliers that use KKT conditions. This the Function :
MIN F = 2*x1^2 + 2*x2^2-6*x1*x2
ineq=x1+2*x2<=3
eq=3*x1+x2=9
I am personally suspect that my if Function(statement) has problem but don't know how to fix that .....
clc
warning off
syms x1 x2 u s lambda
f=2*x1^2+2*x2^2-6*x1*x2;
g1=sqrt(x1^2*x2)+s^2-0.25;
H1=x1*x2^2-0.1;
Lagrange=f+u*g1+lambda*H1;
Grad=gradient(Lagrange);
S=solve(Grad);
S=double([S.x1 S.x2 S.s S.u S.lambda]);M=size(S,1);
for i=M:-1:1
if imag(S(i,3))~=0 || S(i,1)<=0 || S(i,2)<=0
end
end
x1=S(:,1);x2=S(:,2);s=S(:,3);u=S(:,4);lambda=S(:,5);
out=table(x1,x2,s,u,lambda)
x0=[1 0.5 -0.75];
It seems I have a problem because it gives me both write and wrong answers can you help me with that ?
Just eliminate the corresponding row when if condition is satisfied using S(i,:)=[];
According to your formulation
The if condition should look like this
if imag(S(i,3))~=0 || S(i,1)<=0 || S(i,2)<=0
S(i,:)=[];
end
Solution
out =
1×5 table
x1 x2 s u lambda
______ _______ _ ______ _______
0.3393 0.54288 0 3.6349 -2.6402
From my point of view your equality and inequality constraints
formulation are wrong
ineq = x1 + 2*x2 <= 3 -------> g1 = x1 + 2*x2 - 3 + s^2
eq = 3*x1 + x2 = 9 -------> H1 = 3*x1 + x2 - 9
The if condition checks
if u(modifying g1) is less than zero or not
or
if s is real number or not
for i=M:-1:1
if imag(S(i,3))~=0 || S(i,4)<0
S(i,:)=[];
end
end
The entire code is as follow
syms x1 x2 u s lambda
f=2*x1^2+2*x2^2-6*x1*x2;
g1 = x1+2*x2-3 +s^2 ;
H1 = 3*x1+x2-9;
Lagrange=f+u*g1+lambda*H1;
Grad=gradient(Lagrange);
S=solve(Grad)
S=double([S.x1 S.x2 S.s S.u S.lambda]);M=size(S,1)
for i=M:-1:1
if imag(S(i,3))~=0 || S(i,4)<0
S(i,:)=[];
end
end
x1=S(:,1);x2=S(:,2);s=S(:,3);u=S(:,4);lambda=S(:,5);
out=table(x1,x2,s,u,lambda)
Solution
out =
1×5 table
x1 x2 s u lambda
__ __ _ ____ ______
3 0 0 13.2 -8.4
Check your answer using fmincon as follow
% Check your answer using fmincon
% Inequality constraint
%ineq = x1 + 2*x2 <= 3
A = [1, 2];
b = 3;
% Equality constraint
%eq = 3*x1 + x2 = 9
Aeq = [3, 1];
beq = 9;
%F = 2*x1^2 + 2*x2^2-6*x1*x2
F = #(x)2*x(1).^2 + 2*x(2).^2-6*x(1).*x(2);
x0 = [0,0];
[x_minimum, Feval] = fmincon(F, x0, A, b, Aeq, beq);
Solution
x_minimum =
3.0000 -0.0000
Feval =
18.0002
how can I solve this problem with MATLAB in the same way as above? Can I also show it on the chart?
fmin(x1,x2 )=(x1-1)^2+(x2-1)^2
H1=x1+x2-4=0;
H2=x1-x2-2=0
Related
I would like to apply loop over a function. I have the following "mother" code:
v = 1;
fun = #root;
x0 = [0,0]
options = optimset('MaxFunEvals',100000,'MaxIter', 10000 );
x = fsolve(fun,x0, options)
In addition, I have the following function in a separate file:
function D = root(x)
v = 1;
D(1) = x(1) + x(2) + v - 2;
D(2) = x(1) - x(2) + v - 1.8;
end
Now, I would like to find roots when v = sort(rand(1,1000)). In other words, I would like to iterate over function for each values of v.
You will need to modify root to accept an additional variable (v) and then change the function handle to root to an anonymous function which feeds in the v that you want
function D = root(x, v)
D(1) = x(1) + x(2) + v - 2;
D(2) = x(1) - x(2) + v - 1.8;
end
% Creates a function handle to root using a specific value of v
fun = #(x)root(x, v(k))
Just in case that equation is your actual equation (and not a dummy example): that equation is linear, meaning, you can solve it for all v with a simple mldivide:
v = sort(rand(1,1000));
x = [1 1; 1 -1] \ bsxfun(#plus, -v, [2; 1.8])
And, in case those are not your actual equations, you don't need to loop, you can vectorize the whole thing:
function x = solver()
options = optimset('Display' , 'off',...
'MaxFunEvals', 1e5,...
'MaxIter' , 1e4);
v = sort(rand(1, 1000));
x0 = repmat([0 0], numel(v), 1);
x = fsolve(#(x)root(x,v'), x0, options);
end
function D = root(x,v)
D = [x(:,1) + x(:,2) + v - 2
x(:,1) - x(:,2) + v - 1.8];
end
This may or may not be faster than looping, it depends on your actual equations.
It may be slower because fsolve will need to compute a Jacobian of 2000×2000 (4M elements), instead of 2×2, 1000 times (4k elements).
But, it may be faster because the startup cost of fsolve can be large, meaning, the overhead of many calls may in fact outweigh the cost of computing the larger Jacobian.
In any case, providing the Jacobian as a second output will speed everything up rather enormously:
function solver()
options = optimset('Display' , 'off',...
'MaxFunEvals', 1e5,...
'MaxIter' , 1e4,...
'Jacobian' , 'on');
v = sort(rand(1, 1000));
x0 = repmat([1 1], numel(v), 1);
x = fsolve(#(x)root(x,v'), x0, options);
end
function [D, J] = root(x,v)
% Jacobian is constant:
persistent J_out
if isempty(J_out)
one = speye(numel(v));
J_out = [+one +one
+one -one];
end
% Function values at x
D = [x(:,1) + x(:,2) + v - 2
x(:,1) - x(:,2) + v - 1.8];
% Jacobian at x:
J = J_out;
end
vvec = sort(rand(1,2));
x0 = [0,0];
for v = vvec,
fun = #(x) root(v, x);
options = optimset('MaxFunEvals',100000,'MaxIter', 10000 );
x = fsolve(fun, x0, options);
end
with function definition:
function D = root(v, x)
D(1) = x(1) + x(2) + v - 2;
D(2) = x(1) - x(2) + v - 1.8;
end
Assume we have three equations:
eq1 = x1 + (x1 - x2) * t - X == 0;
eq2 = z1 + (z1 - z2) * t - Z == 0;
eq3 = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1 == 0;
while six of known variables are:
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
So we are looking for three unknown variables that are:
X , Z and t
I wrote two method to solve it. But, since I need to run these code for 5.7 million data, it become really slow.
Method one (using "solve"):
tic
S = solve( eq1 , eq2 , eq3 , X , Z , t ,...
'ReturnConditions', true, 'Real', true);
toc
X = double(S.X(1))
Z = double(S.Z(1))
t = double(S.t(1))
results of method one:
X = 316190;
Z = 234060;
t = -2.9280;
Elapsed time is 0.770429 seconds.
Method two (using "fsolve"):
coeffs = [a,b,x1,x2,z1,z2]; % Known parameters
x0 = [ x2 ; z2 ; 1 ].'; % Initial values for iterations
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
options = optimoptions('fsolve','Display','none');
tic
M = fsolve(f_d,x0,options);
toc
results of method two:
X = 316190; % X = M(1)
Z = 234060; % Z = M(2)
t = -2.9280; % t = M(3)
Elapsed time is 0.014 seconds.
Although, the second method is faster, but it still needs to be improved. Please let me know if you have a better solution for that. Thanks
* extra information:
if you are interested to know what those 3 equations are, the first two are equations of a line in 2D and the third equation is an ellipse equation. I need to find the intersection of the line with the ellipse. Obviously, we have two points as result. But, let's forget about the second answer for simplicity.
My suggestion it's to use the second approce,which it's the recommended by matlab for nonlinear equation system.
Declare a M-function
function Y=mysistem(X)
%X(1) = X
%X(2) = t
%X(3) = Z
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
Y(1,1) = x1 + (x1 - x2) * X(2) - X(1);
Y(2,1) = z1 + (z1 - z2) * X(2) - X(3);
Y(3,1) = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1;
end
Then for solving use
x0 = [ x2 , z2 , 1 ];
M = fsolve(#mysistem,x0,options);
If you may want to reduce the default precision by changing StepTolerance (default 1e-6).
Also for more increare you may want to use the jacobian matrix for greater efficencies.
For more reference take a look in official documentation:
fsolve Nonlinear Equations with Analytic Jacobian
Basically giving the solver the Jacobian matrix of the system(and special options) you can increase method efficency.
Need to solve the system of nonlinear differential equations:
x1p = a1*u2*x1^1.3 + a2*u1 + a3*u3
x2p = (a4*u2 + a5)*x1^1.3 + a6*x2
x3p = (a7*u3 + (a8*u2-a9)*x1)/a10
x1p, x2p & x3p are time derivatives of x1, x2 & x3, i.e. dx1/dt, dx2/dt & dx3/dt.
we have descrete data of x1, x2 & x3 as well as of u1, u2 & u3. We need to solve the problem in order to get the unknown coefficients, a1, a2, …, a10.
Have checked many posts and can say the solution involves ODE45 (or other ODEX) and probably fsolve or fminsearch (Matlab), but have not managed to setup up the problem correctly, guess we don't understand the coding well. Please, suggestions.
you should replace x1p, x2p ,and x3p by using definition of derivative:
x1p = (x1(i+1) - x(i))/ dt , and like this for the others.
then use folowing algorithm (it is not complete):
descrete data of x1, x2 & x3 as well as of u1, u2 & u3
dt = 0.01
myFun = #(a,x1,x2,x3,u1,u2,u3)
[ (x1(i+1) - x1(i))/ dt = a(1)*u2(i)*x1(i)^1.3 + a(2)*u1(i) + a(3)*u3(i);
(x2(i+1) - x2(i))/ dt = (a(4)*u2(i) + a(5)*x1(i)^1.3 + a(6)*x2(i);
(x3(i+1) - x3(i))/ dt = (a(7)*u3(i) + (a(8)*u2(i)-a(9))*x1(i))/a(10) ]
A=[];
a0 = [0; 0; 0 ;0 ;.... ]
for i= 1:1: lenngth(x1)
a=fsolve(#(a)myFun(a,x1,x2,x3,u1,u2,u3),a0,options);
a0 = [ a(1,1) ; a(2,1); a(3,1) ; .......]
A = cat(1,A,a) ;
end
a1 = mean(A(1,:))
a2 = mean(A(2,:))
.
.
a10 = mean(A(10,:))
I am encountering a problem during an optimization exercise. I am trying to use fminsearch() in matlab to solve it. The following error is generated when the code is run:
The following error occurred converting from sym to double: Error
using symengine (line 59) DOUBLE cannot convert the input expression
into a double array. If the input expression contains a symbolic
variable, use VPA.
Error in fminsearch (line 190) fv(:,1) = funfcn(x,varargin{:});
Error in Optimization (line 22) sol2 = fminsearch(J, x0);
The script I use can be seen below. The f is the minimization problem where g1 & g2 are constraints. The p is there so that I can turn it into for loop later.
syms x1 x2 x3 x4;
syms p;
f = x1.^4 - x3.^2 + x1*x3 + x2*x4 - 5*x2 + 3;
g1 = x1.^2 + x2.^2 + x3.^2 + x4.^2 - 1;
g2 = x1 + x3 - 1;
x0 = [2 2 2 2];
p = 3;
J = #(x1,x2,x3,x4) sym(f + p * g1.^2 + g2.^2);
sol2 = fminsearch(J, x0);
This Stackoverflowpost has the same problem but in another perspective.According to this post it might be a problem with allocating the in a valid way. I tried a few different ways to solve my problem. I have tried matlabFunction() and putting the function in a seperate file.
If the input expression contains a symbolic variable, use the VPA function instead?
Thanks in advance for the help.
fminsearch is designed for numerical minimization. There is little point in using symbolic math in this case (it can be used, but it will be slower, complicate your code, and the results will still be in double precison). Second, if you read the documentation and look at the examples for fminsearch, you'll see that it requires a function that takes a single vector input (as opposed to four scalars in your case). Here's how you could rewrite your equations using anonymous functions:
f = #(x)x(1).^4 - x(3).^2 + x(1).*x(3) + x(2).*x(4) - 5*x(2) + 3;
g1 = #(x)x(1).^2 + x(2).^2 + x(3).^2 + x(4).^2 - 1;
g2 = #(x)x(1) + x(3) - 1;
x0 = [2 2 2 2];
p = 3;
J = #(x)f(x) + p*g1(x).^2 + g2(x).^2;
sol2 = fminsearch(J, x0)
this returns
sol2 =
0.149070165097281 1.101372214292880 0.326920462283209 -0.231885482601008
Using symbolic math and subs:
syms x1 x2 x3 x4;
f = x1^4 - x3^2 + x1*x3 + x2*x4 - 5*x2 + 3;
g1 = x1^2 + x2^2 + x3^2 + x4^2 - 1;
g2 = x1 + x3 - 1;
x0 = [2 2 2 2];
p = sym(3);
J = #(X)subs(f + p*g1^2 + g2^2,[x1 x2 x3 x4],X);
sol2 = fminsearch(J, x0)
which returns identical results.
I am trying to use minimization to calculate coefficients of the polynomial p(x) = 1 + c(1)x + c(2)x^2 to approximate e^x. I need to use points xi = 1 + i/n for natural numbers i on [1,n], first for n=5, then n=10, etc. The approach is to minimize the 1, 2, and inf norm(p(x) - e^x) using fminsearch. So the output should be the 2 coefficients for the 3 p(x)'s. Any suggestions is appreciated.
Well, if anyone was wondering, I did figure the question out finally.
for l = [1 2 inf]
fprintf('For norm %d\n', l)
fprintf('Coefficients c1 c2\n')
for n = [5 10 100]
i = 1:n ;
x = 1 + i/n ;
c = [1 1] ;
%Difference function that we want to minimize
g = #(c) x.*c(1) + x.^2.*c(2) + 1 - exp(x);
f_norm = #(c) norm(g(c), l) ;
C = fminsearch(f_norm, c);
fprintf('n = %d ', n)
fprintf('%f %f\n', C(1), C(2))
% Compare plot of e^x and p(x).
p = #(x) C(1)*x + C(2)*x.^2 + 1;
xx = linspace(1,2,1e5);
figure;
plot(xx, p(xx), '--r', xx, exp(xx));
str = sprintf('Plot with n = %d, for norm %d', n,l);
title(str,'FontSize',24)
xlabel('x','FontSize',20)
ylabel('y','FontSize',20)
legend('p2 approximation','exponential');
end
end
This worked in the end to answer the question.