Using fmincon in Matlab with script function - matlab

I am solving the following fmincon problem in Matlab
clear
rng default
XZW_temp=[0.5450 0.8175 -0.5451 0.2724];
X1_temp=[0 0.0852 0 -0.0852];
X2_temp=[2.0132 1.0066 -2.0132 -1.0066];
options = optimset('linprog');
options.Display = 'off';
fun=#(x)inner_max(x,XZW_temp, X1_temp, X2_temp, options);
ub=Inf*ones(4,1);
lb=zeros(4,1);
x0=ones(4,1);
[~, f]=fmincon(fun,x0,[],[],[],[],lb,ub);
where inner_max is the following
function i_m=inner_max(x,XZW_temp, X1_temp, X2_temp, options)
f=-[x'*XZW_temp.'; x'*X1_temp.'; x'*X2_temp.'];
Aeq=[1 0 0];
beq=1;
lb=-Inf*ones(3,1);
ub=Inf*ones(3,1);
[~,fval] = linprog(f,[],[],Aeq,beq,lb,ub,options);
i_m=-fval;
end
I get the following error
In an assignment A(:) = B, the number of elements in A and B must be the same.
Error in finitedifferences
Error in computeFinDiffGradAndJac
Error in barrier
Error in fmincon (line 798)
[X,FVAL,EXITFLAG,OUTPUT,LAMBDA,GRAD,HESSIAN] = barrier(funfcn,X,A,B,Aeq,Beq,l,u,confcn,options.HessFcn, ...
I do not understand what I'm doing wrong. Could you help?

I think you can write your anonymous function in fmincon like below, such that arguments XZW_temp, X1_temp,and X2_temp can be pass to fmincon from global environment, i.e.,
[~, f]=fmincon(#(x) inner_max(x,XZW_temp, X1_temp, X2_temp),x0,[],[],[],[],lb,ub);
such that
>> f
f = 1.0898
N.B.: I removed option from inner_max, so the function looks like
function i_m=inner_max(x,XZW_temp, X1_temp, X2_temp)
f=-[x'*XZW_temp.'; x'*X1_temp.'; x'*X2_temp.'];
Aeq=[1 0 0];
beq=1;
lb=-Inf*ones(3,1);
ub=Inf*ones(3,1);
[~,fval] = linprog(f,[],[],Aeq,beq,lb,ub);
i_m=-fval;
end

Related

Computing the Jacobian of an anonymous function - MATLAB

I'm trying to solve a system of non linear odes in Matlab as follows.
editparams %parameters
Tend = 50;
Nt = 100;
% Define RHS functions
RHS = #(t,x) ModelRHS(t,x,param); %anonymous function defining the set of equations
%Execution-----------------------------------------------------------------
x0 =[0.04;0.75;0.85]; %Initial condition
t = linspace(0,Tend,Nt); %TSPAN
[t x] = ode45(RHS, t, x0);
Now, I need to find the steady state of the system and I'm trying to create a function for this. I thought I'd calculate the steady state using the Jacobian. My equations are in an anonymous function which is defined as f in the code below. However, I realised that jacobian does not work for anonymous functions (or may be there is a way to do with anonymous functions) . so I thought I would convert the anonymous function to a symbolic function and try it. But
i still have a difficulty in getting that done. So any help is really appreciated!
function SS = SteadyState(param, E)
f = #(t,x)ModelRHS(t,x,param,E); %set of odes
SymbolicSystem = sym(f); %trying to make the anonymous function symbolic
SymbolicJacobian = jacobian(SymbolicSystem',x); %jacobian
Jacob = matlabFunction(SymbolicJacobian,x);
end
Also if there is any other way apart from finding the Jacobian, kindly let me know about that too.
I tried using 'fsolve' to calculate the steady-state as follows:
f = #(t,x)ModelRHS(t,x,param);
x0 =[0.04;0.75;0.85]';
options = optimoptions('fsolve','Display','iter'); % Option to display output
SS = fsolve(f,x0,options); % Call solver
but it returned an error
Not enough input arguments.
Error in #(t,x)ModelRHS(t,x,param)
Error in fsolve (line 242)
fuser = feval(funfcn{3},x,varargin{:});
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot continue.

Optimization with genetic algorithm in matlab

I have written a simple optimization code using genetic algorithm.I don't know why I get error during running the code.Here is my code:
f = #(x1,x2) 1-x1.^2+(x1-x2).^2;
A = [1 1;-1 2;2 1];
b =[2 2 3]' ;
Aeq = [];
beq = [];
Lb = [0 0]';
Ub = [];
[Xopt,Fval] = ga(f,2,A,b,Aeq,beq,Lb,Ub)
I don not know why matlab gives me error.I wrote this programm based on the "Genetic algorithm Documentation" bit still gives me error:
Error using #(x1,x2)1-x1.^2+(x1-x2).^2
Not enough input arguments.
Error in createAnonymousFcn>#(x)fcn(x,FcnArgs{:}) (line 11)
fcn_handle = #(x) fcn(x,FcnArgs{:});
Error in makeState (line 48)
firstMemberScore = FitnessFcn(state.Population(initScoreProvided+1,:));
Error in galincon (line 18)
state = makeState(GenomeLength,FitnessFcn,Iterate,output.problemtype,options);
Error in ga (line 351)
[x,fval,exitFlag,output,population,scores] = galincon(FitnessFcn,nvars, ...
Caused by:
Failure in initial user-supplied fitness function evaluation. GA cannot continue
Objective functions of all optimization methods in MATLAB only accept 1 argument. According to ga documents:
fun — Objective function
Objective
function, specified as a function handle or function name. Write the
objective function to accept a row vector of length nvars and return a
scalar value.
When the 'UseVectorized' option is true, write fun to accept a
pop-by-nvars matrix, where pop is the current population size. In this
case, fun returns a vector the same length as pop containing the
fitness function values. Ensure that fun does not assume any
particular size for pop, since ga can pass a single member of a
population even in a vectorized calculation.
Change you objective function and it should work:
f = #(x) 1-x(1).^2+(x(1)-x(2)).^2;

MATLAB function fminunc generates errors

I am facing an error when using the function fminunc in the context of a maximum-likelihood estimation. I am afraid that it is very straight forward however my experience with MATLAB is very limited.
The function "normal" contains the log-likelihood function. I seek to estimate the expectation and std. deviation of a normal distribution given the observations stored in the variable x.
function f = normal(X, theta)
mean = theta(1);
sigma = theta(2);
z = (X-mean)./sigma;
f = -(sum(-log(sigma) -(1/2).*z.^2 ));
I basically execute the following code:
theta = [1,1]
f = #(theta)normal(x, theta)
[est, fval, exitflag, output, grad, hessian] = fminunc('normal', x, theta)
The error is the following:
Warning: Struct field assignment overwrites a value with class "double". See MATLAB R14SP2 Release
Notes, Assigning Nonstructure Variables As Structures Displays Warning, for details.
In createOptionFeedback at 34
In prepareOptionsForSolver at 31
In fminunc at 157
Warning: Struct field assignment overwrites a value with class "double". See MATLAB R14SP2 Release
Notes, Assigning Nonstructure Variables As Structures Displays Warning, for details.
In fminunc at 203
Error using feval
Undefined function 'normal' for input arguments of type 'double'.
Error in fminunc (line 254)
f = feval(funfcn{3},x,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. FMINUNC cannot continue.
Unfortunately the manual did not help me to fix the code. Calling
[est, fval, exitflag, output, grad, hessian] = fminunc(f, x, theta)
did not help either. What am I doing wrong?
Thank you in advance!
You have called fminunc with the wrong sintax, please refer to the documentation.
A way to fix your code is by defining the function normal to accept only one parameter: theta.
function f = normal(theta)
global X
mean = theta(1);
sigma = theta(2);
z = (X-mean)./sigma;
f = -(sum(-log(sigma) -(1/2).*z.^2 ));
and call fminunc with
global X
X = randn(100, 1); % A possible time series.
theta0 = [1,1];
[est, fval, exitflag, output, grad, hessian] = fminunc(#normal, theta0);

Fitting model to data in matlab

i have some experimental data and a theoretical model which i would like to try and fit. i have made a function file with the model - the code is shown below
function [ Q,P ] = RodFit(k,C )
% Function file for the theoretical scattering from a Rod
% R = radius, L = length
R = 10; % radius in Å
L = 1000; % length in Å
Q = 0.001:0.0001:0.5;
fun = #(x) ( (2.*besselj(1,Q.*R.*sin(x)))./...
(Q.*R.*sin(x)).*...
(sin(Q.*L.*cos(x)./2))./...
(Q.*L.*cos(x)./2)...
).^2.*sin(x);
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
end
with Q being the x-values and P being the y-values. I can call the function fine from the matlab command line and it works fine e.g. [Q,P] = RodFit(1,0.001) gives me a result i can plot using plot(Q,P)
But i cannot figure how to best find the fit to some experimental data. Ideally, i would like to use the optimization toolbox and lsqcurvefit since i would then also be able to optimize the R and L parameters. but i do not know how to pass (x,y) data to lsqcurvefit. i have attempted it with the code below but it does not work
File = 30; % the specific observation you want to fit the model to
ydata = DataFiles{1,File}.data(:,2)';
% RAdius = linspace(10,1000,length(ydata));
% LEngth = linspace(100,10000,length(ydata));
Multiplier = linspace(1e-3,1e3,length(ydata));
Constant = linspace(0,1,length(ydata));
xdata = [Multiplier; Constant]; % RAdius; LEngth;
L = lsqcurvefit(#RodFit,[1;0],xdata,ydata);
it gives me the error message:
Error using *
Inner matrix dimensions must agree.
Error in RodFit (line 15)
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
Error in lsqcurvefit (line 199)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT cannot continue.
i have tried i) making all vectors/matrices the same length and ii) tried using .* instead. nothing works and i am giving the same error message
Any kind of help would be greatly appreciated, whether it is suggestion regading what method is should use, suggestions to my code or something third.
EDIT TO ANSWER Osmoses:
A really good point but i do not think that is the problem. just checked the size of the all the vectors/matrices and they should be alright
>> size(Q)
ans =
1 1780
>> size(P)
ans =
1 1780
>> size(xdata)
ans =
2 1780
>> size([1;0.001]) - the initial guess/start point for xdata (x0)
ans =
2 1
>> size(ydata)
ans =
1 1780
UPDATE
I think i have identified the problem. the function RodFit works fine when i specify the input directly e.g. [Q,P] = RodFit(1,0.001);.
however, if i define x0 as x0 = [1,0.001] i cannot pass x0 to the function
>> x0 = [1;0.001]
x0 =
1.0000
0.0010
>> RodFit(x0);
Error using *
Inner matrix dimensions must agree.
Error in RodFit (line 15)
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
The same happens if i use x0 = [1,0.001]
clearly, matlab is interpreting x0 as input for k only and attempts to multiplay a vector of length(ydata) and a vector of length(x0) which obviously fails.
So my problem is that i need to code so that lsqcurvefit understands that the first column of xdata and x0 is the k variable and the second column of xdata and x0 is the C variable. According to the documentation - Passing Matrix Arguments - i should be able to pass x0 as a matrix to the solver. The solver should then also pass the xdata in the same format as x0.
Have you tried (that's sometimes the mistake) looking at the orientation of your input data (e.g. if xdata & ydata are both row/column vectors?). Other than that your code looks like it should work.
I have been able to solve some of the problems. One mistake in my code was that the objective function did not use of vector a variables but instead took in two variables - k and C. changing the code to accept a vector solved this problem
function [ Q,P ] = RodFit(X)
% Function file for the theoretical scattering from a Rod
% R = radius, L = length
% Q = 0.001:0.0001:0.5;
Q = linspace(0.11198,4.46904,1780);
fun = #(x) ( (2.*besselj(1,Q.*R.*sin(x)))./...
(Q.*R.*sin(x)).*...
(sin(Q.*L.*cos(x)./2))./...
(Q.*L.*cos(x)./2)...
).^2.*sin(x);
P = (integral(fun,0,pi/2,'ArrayValued',true))*X(1)+X(2);
with the code above, i can define x0 as x0 = [1 0.001];, and pass that into RodFit and get a result. i can also pass xdata into the function and get a result e.g. [Q,P] = RodFit(xdata(2,:));
Notice i have changed the orientation of all vectors so that they are now row-vectors and xdata has size size(xdata) = 1780 2
so i thought i had solved the problem completely but i still run into problems when i run lsqcurvefit. i get the error message
Error using RodFit
Too many input arguments.
Error in lsqcurvefit (line 199)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT cannot continue.
i have no idea why - does anyone have any idea about why Rodfit recieves to many input arguments when i call lsqcurvefit but not when i run the function manual using xdata?

error in two dimensional secand method

i want to understand what is a error in the following code?code is given below
function x0=secand2d(f,g,x,dx,tol)
% find solution of f(x,y)=0 and g(x,y)=0
for i=1:20
x0=x;
f0=[feval(f,x0),feval(g,x0)];
x0=x+[dx(1),0];
fx=[feval(f,x0),feval(g,x0)];
fx=(fx-f0)/dx(1);
x0=x+[0 dx(2)];
fy=[feval(f,x0),feval(g,x0)];
fy=(fy-f0)/dx(2);
A=[fx;fy]+eps;
x=x+dx;
dx=(-A\f0'-dx')';
if(norm(dx)<tol) ;return; end;
end;
disp(norm(dx));
pause;
end
which represents of two dimensional secant method,where function f and g is defined by following form
f=#(x,y) (x-sin(x+y)); and g=#(x,y) y-cos(x-y);
i have also checked and these to function works fine on it's parameters
f(3,3)
ans =
3.2794
and
g(1,1)
ans =
0
also
x=[0.9 0.9];
dx=[0.1 0.1];
tol=1e-5;
but following code generated such kind of errors
secand2d(f,g,x,dx,tol)
Error using #(x,y)(x-sin(x+y))
Not enough input arguments.
Error in secand2d (line 5)
f0=[feval(f,x0),feval(g,x0)];
please help me to clarify reasons of this errors
You are getting that error because you are passing only x0 to f here:
f0=[feval(f,x0),feval(g,x0)];
f and g are expecting two inputs. You can fix the error like this:
f0=[feval(f,x0,y0),feval(g,x0,y0)];
If there is not a particular reason you are using feval you can do it like this:
f0 = [f(x0, y0) g(x0, y0)];