error in two dimensional secand method - matlab

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)];

Related

Using fmincon in Matlab with script function

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

function in matlab- undefined input argument error

I can't understand what the problem is with this code. If anyone can help I will be thankful.
function [out] = detj(in1)
%DETJ Summary of this function goes here
%Detailed explanation goes here: N is 2*50 matrix and in1 is scaler
global N
out=(1/8)*(N(1,in1));
end
The error is :
Input argument "in1" is undefined.
Error in ==> detj at 7
out=(1/8)*(N(1,in1));
I defined N in another file
N=importdata('Nodes.txt'); %Matrix of nodes
No thing wrong with your code, you just used the function the wrong way.
To use a Function in Matlab you need to call it, NOT to run it directly.
This is your original function code
function [out] = detj(in1,in2,in3,in4)
%DETJ Summary of this function goes here
% Detailed explanation goes here %N is 2*50 Matrix
global N r s
out=zeros(2,2);
for m=1:2
for n=1:2
out(m,n)=(1/8)*(((N(1,in1)-N(1,in3))*(N(2,in2)-N(2,in4))-(N(2,in1)-N(2,in3))*(N(1,in2)-N(1,in4)))-r(1,m)*((N(1,in3)-N(1,in4))*(N(2,in1)-N(2,in2))-(N(2,in3)-N(2,in4))*(N(1,in1)-N(1,in2)))+s(1,n)*((N(1,in2)-N(1,in3))*(N(2,in1)-N(2,in4))-(N(2,in2)-N(2,in3))*(N(1,in1)-N(1,in4))));
end
end
end
To use your function I tried a simple code,
clc;clear;
global N
global r
global s
N=ones(2,50);
r=ones(2,2);
s=ones(2,2);
detj(1,2,3,4)
And I got answer as
ans =
0 0
0 0
So no thing wrong with your function, just you need to know how to use it.
Let me know if my answer is not clear else good luck.

MATLAB - properly defining function and running script

I am trying to write a program for the Bisection method, but I am not fully understanding how to properly define a function and run the script. I have searched google and watched YouTube videos and MATLAB tutorials on this stuff, but I just don't get it. I hope someone here can help me once I present my code, and the error messages I am getting, as well as what I should expect to see...
Code:
function [f] = Bisection(a,b,Nmax,TOL)
f(x)= x^3 - x^2 + x;
i=1;
BisectA=f(a);
while i <= Nmax
p=a+(b-a)/2;
BisectP=f(p);
if BisectP == 0 || (b-a)/2 < TOL
disp('p');
end
i=i+1;
if BisectA*BisectP > 0
a=p;
BisectA=BisectP;
else
b=p;
end
end
disp('Method failed after num2str(Nmax) iterations, Nmax=', Nmax);
When I run this code, I get the error message:
??? Undefined function or variable 'x'.
Error in ==> Bisection at 2
f(x)= x^3 - x^2 + x;
I am unable to figure out how to define 'x'?? Also, should I create more than one function? I would like to have them all in one file.
Thanks.
You error is occurring because x is indeed undefined. If you'r trying to create an anonymous function that takes x as an argument, you'd do that like this:
f = #(x)x.^3-x.^2+x;
Then you can call f(a) as you do later on. Another potential issue is that your Bisection function is returning f. Do you want it to return the function handle?

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 using fzero in Matlab: Undefined function or method 'det' for input arguments of type 'function_handle'

I have the same kind of problem described in this topic:
Using fzero: Undefined function or method 'isfinite' for input arguments of type 'sym'
Their answers really helped me, but I am still stuck.
I also have to find the zeros of a function of w, this function is defined in several steps:
So the only unknown is w, and I defined other objects such as:
lambda= #(w) ((16*rho(i)*A(i)*w^2*Lprime(i)^2)/(E(j)*I(i)))^0.25;
beta=#(w) lambda*b(i)^0.5;
gamma=#(w) lambda*Lprime(i)^0.5;
Then, I define a 4*4 matrix M2:
M2=#(w) [besselj(4,beta) bessely(4,beta) besseli(4,beta) besselk(4,beta);
besselj(3,beta) bessely(3,beta) besseli(3,beta) -besselk(3,beta);
besselj(2,gamma) bessely(2,gamma) besseli(2,gamma) besselk(2,gamma);
besselj(4,gamma) bessely(4,gamma) besseli(4,gamma) besselk(4,gamma)];
Then the equation to be solved is: det(M2)=0. But w=0 is one of the solutions, and I want the first non-zero solution, so I wrote:
delta = #(w) det(M2);
S(i,j)=fzero(delta,500);
Then I run the program, and Matlab says:
??? Error using ==> fzero at 235
FZERO cannot continue because user supplied function_handle ==> #(w)det(M2)
failed with the error below.
Undefined function or method 'det' for input arguments of type 'function_handle'.
Error in ==> frequencies at 57
S(i,j)=fzero(delta,500);
I also tried with the subs and the eval methods, and they don't work either, the error messages are in those cases:
??? Undefined function or method 'isfinite' for input arguments of type 'sym'.
Error in ==> fzero at 323
elseif ~isfinite(fx) || ~isreal(fx)
Error in ==> frequencies at 58
S(i,j)=fzero(#(w) subs(delta,'w',w),500);
Which is the same error as edio's I guess. And:
??? Error using ==> fzero at 307
FZERO cannot continue because user supplied function_handle ==> #(w)eval(delta)
failed with the error below.
Undefined function or method 'eval' for input arguments of type 'function_handle'.
Error in ==> frequencies at 59
S(i,j)=fzero(#(w)eval(delta),500);
Can you help me please?
Your problem appears to be that you are never evaluating your anonymous functions when you place them within other anonymous functions. For example, you define the function lambda as such:
lambda = #(w) ((16*rho(i)*A(i)*w^2*Lprime(i)^2)/(E(j)*I(i)))^0.25;
But when you use it in beta, you need to evaluate it using the input value for w, like so:
beta = #(w) lambda(w)*b(i)^0.5;
%# ^--------------Pass w to lambda to evaluate the function
As such, I believe your other anonymous functions should be defined as follows:
gamma = #(w) lambda(w)*Lprime(i)^0.5;
M2 = #(w) [besselj(4,beta(w)) bessely(4,beta(w)) besseli(4,beta(w)) ...
besselk(4,beta(w)); ...
besselj(3,beta(w)) bessely(3,beta(w)) besseli(3,beta(w)) ...
-besselk(3,beta(w)); ...
besselj(2,gamma(w)) bessely(2,gamma(w)) besseli(2,gamma(w)) ...
besselk(2,gamma(w)); ...
besselj(4,gamma(w)) bessely(4,gamma(w)) besseli(4,gamma(w)) ...
besselk(4,gamma(w))];
delta = #(w) det(M2(w));
A note about efficiency...
There is a GLARING efficiency problem I'm noticing here. By using anonymous functions instead of any other type of function (primary functions, nested functions, or subfunctions) you are going to end up evaluating the same function with the same input multiple times over.
For example, each time you evaluate M2 to create your matrix you will be evaluating both beta and gamma 8 times with the same input! Notice the improvement you could make by placing M2 in a function and passing as input w and the two function handles beta and gamma:
function newMatrix = M2(w,betaFcn,gammaFcn)
bw = betaFcn(w); %# Evaluate the beta function once
gw = gammaFcn(w); %# Evaluate the gamma function once
newMatrix = [besselj(4,bw) bessely(4,bw) besseli(4,bw) besselk(4,bw); ...
besselj(3,bw) bessely(3,bw) besseli(3,bw) -besselk(3,bw); ...
besselj(2,gw) bessely(2,gw) besseli(2,gw) besselk(2,gw); ...
besselj(4,gw) bessely(4,gw) besseli(4,gw) besselk(4,gw)];
end
And your new delta function would look like this:
delta = #(w) det(M2(w,beta,gamma));
Hi thank you very much for your help.
It works, but the last line has to change, obviously (it still took me 10 minuts for figure it out):
lambda= #(w) ((16*rho(i)*A(i)*w^2*Lprime(i)^2)/(E(j)*I(i)))^0.25;
beta=#(w) lambda(w)*b(i)^0.5;
gamma=#(w) lambda(w)*Lprime(i)^0.5;
M2=#(w) [besselj(4,beta(w)) bessely(4,beta(w)) besseli(4,beta(w)) besselk(4,beta(w));
besselj(3,beta(w)) bessely(3,beta(w)) besseli(3,beta(w)) -besselk(3,beta(w));
besselj(2,gamma(w)) bessely(2,gamma(w)) besseli(2,gamma(w)) besselk(2,gamma(w));
besselj(4,gamma(w)) bessely(4,gamma(w)) besseli(4,gamma(w)) besselk(4,gamma(w))];
delta = #(w) det(M2(w));
S(i,j)=fzero(#(w) delta(w),500);
And now it is really faster than before, in another case where the function solve could handle the resolution, it took like 10 seconds for each loop, now it's like 0.06 seconds
I will try your other solution to see the improvements.
Thank you a lot.