Nonlinear parameters search - matlab

need to find a set of optimal parameters P of the system y = P(1)*exp(-P(2)*x) - P(3)*x where x and y are experimental values. I defined my function
f = #(P) P(1)*exp(-P(2)*x) - P(3)*x
and
guess = [1, 1, 1]
and tried
P = fminsearch(f,guess)
according to Help. I get an error
Subscripted assignment dimension mismatch.
Error in fminsearch (line 191)
fv(:,1) = funfcn(x,varargin{:});
I don't quite understand where my y values would fall in, as well as where the function takes P from. I unfortunately have no access to nlinfit or optimization toolboxes.

You should try the matlab function lsqnonlin(#testfun,[1;1;1])
But first make a function and save in an m-file that includes all the data points, lets say your y is A and x is x like here below:
function F = testfun(P)
A = [1;2;3;7;30;100];
x = [1;2;3;4;5;6];
F = A-P(1)*exp(-P(2)*x) - P(3)*x;
This minimized the 2-norm end gives you the best parameters.

Related

fmincon throwing error on input arguments

I am working on an optimization problem where I want to maximize utility while searching over variables lx_init and kx_init. Each time I solve an issue with fmincon another one pops up. The error right now is..
"Not enough input arguments."
"Failure in initial objective function evaluation. FMINCON cannot continue."
I have tried to trace back the error in debug mode but tracing back my error is proving difficult. The function is able to be evaluated on its own and spit back a value so I know the error is in the fmincon function. My Matlab experience is very minimal. I am sure there are other syntax errors I am guilty of and too naive to see. I will provide all variables so the code can be replicated.
A second question: I want to maximize my utility value here but also find the values of x and y given once the utility is maximized. However, we are also maximizing over lx_init and kx_init. How do I get the function to return x and y? Right now it is just returning the utility value.
Here is my function I am optimizing
function [utility, x, y] = utility_with_prod(gamma_X, gamma_Y, alpha_LX, alpha_KX, alpha_LY, alpha_KY, alpha_uX, sigma_U, sigma_X, sigma_Y, L_bar, K_bar, lx_init, kx_init)
% X's production function
x = gamma_X*((alpha_LX*lx_init^((sigma_X-1)/sigma_X)) + ((alpha_KX)*kx_init^((sigma_X-1)/sigma_X)))^(sigma_X/(sigma_X-1));
% Y's production function
y = gamma_Y*((alpha_LY*(L_bar-lx_init)^((sigma_Y-1)/sigma_Y)) + ((alpha_KY)*(K_bar-kx_init)^((sigma_Y-1)/sigma_Y)))^(sigma_Y/(sigma_Y-1));
% utility function with nested production function
utility = -(((alpha_uX*x^((sigma_U-1)/sigma_U)) + ((1-alpha_uX)*y^((sigma_U-1)/sigma_U)))^(sigma_U/(sigma_U-1)));
end
Here are my initial values
sigma_U= 0.5038;
sigma_X= 0.5029;
sigma_Y= 0.5029;
alpha_uX= 0.000236017865342454;
alpha_LX= 0.180813595922536;
alpha_KX= 0.819186404077464;
gamma_X= 1.768587207836113;
alpha_LY= 0.505368332690592;
alpha_KY= 0.494631667309408;
gamma_Y= 1.999942066647923;
lx_init = 1;
kx_init = 2;
L_bar = 3;
K_bar = 3;
x0 = [lx_init, kx_init];
and the optimization
utility = #(lx_init, kx_init)utility_with_prod(gamma_X, gamma_Y, alpha_LX, alpha_KX, alpha_LY, alpha_KY, alpha_uX, sigma_U, sigma_X, sigma_Y, L_bar, K_bar, lx_init, kx_init)
[optimal_lx_kx, utility_max, exitflag] = fmincon(utility, x0, [],[])
x0 in fmincon is a vector, that's an n by 1 matrix or 1 by n,
here 1 by 2 ---> x0 = [lx_init, kx_init];
Function handle #(lx_init, kx_init) is different from #([lx_init, kx_init]).
#([lx_init, kx_init])accepts only one input.
#(lx_init, kx_init) accepts only two inputs, no more, no less
Also input variable should not be predefined value
Change #(lx_init, kx_init) to #(x) where x(1) = lx_init and x(2) = kx_init
To sum up
utility = #(lx_init, kx_init)utility_with_prod(gamma_X, gamma_Y, alpha_LX,alpha_KX, alpha_LY, alpha_KY, alpha_uX, sigma_U, sigma_X, sigma_Y, L_bar, K_bar, lx_init, kx_init)
is replaced by
utility = #(x)utility_with_prod(gamma_X, gamma_Y, alpha_LX, alpha_KX, alpha_LY, alpha_KY, alpha_uX, sigma_U, sigma_X, sigma_Y, L_bar, K_bar, x(1), x(2))

Bessel's integral implementation

I'm trying to implement this integral representation of Bessel function of the first kind of order n.
here is what I tried:
t = -pi:0.1:pi;
n = 1;
x = 0:5:20;
A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
B(t) = integral(A(t),-pi,pi);
plot(A(t),x)
the plot i'm trying to get is as shown in the wikipedia page.
it said:
Error using * Inner matrix dimensions must agree.
Error in besselfn (line 8) A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
so i tried putting x-5;
and the output was:
Subscript indices must either be real positive integers or logicals.
Error in besselfn (line 8) A(t) = exp(sqrt(-1)*(n*t-x*sin(t)));
How to get this correct? what am I missing?
To present an anonymous function in MATLAB you can use (NOT A(t)=...)
A = #(t) exp(sqrt(-1)*(n*t-x.*sin(t)));
with element-by-element operations (here I used .*).
Additional comments:
You can use 1i instead of sqrt(-1).
B(t) cannot be the function of the t argument, because t is the internal variable for integration.
There are two independent variables in plot(A(t),x). Thus you can display plot just if t and x have the same size. May be you meant something like this plot(x,A(x)) to display the function A(x) or plot(A(x),x) to display the inverse function of A(x).
Finally you code can be like this:
n = 1;
x = 0:.1:20;
A = #(x,t) exp(sqrt(-1)*(n*t-x.*sin(t)));
B = #(x) integral(#(t) A(x,t),-pi,pi);
for n_x=1:length(x)
B_x(n_x) = B(x(n_x));
end
plot(x,real(B_x))

integral2 with fun calculated using vector

Im new to MATLAB. Want to use integral2 as follows
function num = numer(x)
fun=#(p,w) prod((p+1-p).*(1-w).*exp(w.*x.*x/2))
num= integral2(fun ,0,1,0,1)
end
I get several errors starting with
Error using .*
Matrix dimensions must agree.
Error in numer>#(p,w)prod(p+(1-w).*exp(w.*x.*x/2)) (line 5)
fun=#(p,w) prod(p+(1-w).*exp(w.*x.*x/2))
Can you please tell me what I do wrong.
Thanks
From the help for integral2:
All input functions must accept arrays as input and operate
elementwise. The function Z = FUN(X,Y) must accept arrays X and Y of
the same size and return an array of corresponding values.
When x was non-scalar, your function fun did not do this. By wrapping everything in prod, the function always returned a scalar. Assuming that your prod is in the right place to begin with and taking advantage of the properties of the exponential, I believe this version will do what you need for vector x:
x = [0 1];
lx = length(x);
fun = #(p,w)(p+1-p).^lx.*(1-w).^lx.*exp(w).^sum(x.*x/2);
num = integral2(fun,0,1,0,1)
Alternatively, fun = #(p,w)(p+1-p).^lx.*(1-w).^lx.*exp(sum(x.*x/2)).^w; could be used.

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?

Putting Two Arguments into UnifDist in MATLAB

Trying to compute the following expression,
quad(#(n)quad(#(m)unifpdf(m-n,0,1),-10,10),-10,10)
But I get a message saying:
??? Error using ==> minus
Matrix dimensions must agree.
Error in ==> #(m)unifpdf(m-n,0,1)
Can you please let me know how to fix this?
The problem here is the following requirement:
The function y = fun(x) should accept a vector argument x and return a vector result y, the integrand evaluated at each element of x.
unipdf seems to satisfy this requirement, but quad itself is not.
To fix this problem you need to write a wrapper function that accepts a vector argument x, evaluates inner integral using quad function, and return a vector of results:
function [r] = Test()
r = quad(#(n)InnerIntegral(n),-10,10);
end
function [y] = InnerIntegral(n)
y = zeros(size(n));
for i = 1 : length(n)
y(i) = quad(#(m)unifpdf(m - n(i), 0, 1), -10, 10);
end;
end