An error without actually explaining what's wrong - matlab

Ok, so I've defined the function MetBisectiei which has the following code:
function [xaprox] = MetBisectiei(Fun,a,b,eps)
Fa = Fun(a);
Fb = Fun(b);
if Fa*Fb>0
xaprox = ('Error: The function has the same sign at points a and b.');
else
N=ceil((log10(b-a)-log10(eps))/log10(2));
for i = 1:n
xaprox = (a+b)/2;
Fxaprox=Fun(xaprox);
if(Fxaprox == 0)
break
end
if Fa*Fxaprox<0
b=Fxaprox;
else
a=xaprox;
Fa=Fxaprox;
end
end
end
And when I try to actually use the function to find the solution of an equation, I get the following error, which doesn't actually explain what's wrong:
Error in tema2_2 (line 8)
xaprox = MetBisectiei(f,0,1,eps);
The code to find the solution of the equation is this one:
syms x
f = x^3-7*x^2+14*x-6;
f = matlabFunction(f);
x = 0:4;
y = f(x);
plot(x,y);
eps = 10^(-5);
xaprox = MetBisectiei(f,0,1,eps);

I see few mistakes here. First you should terminate
function [xaprox] = MetBisectiei(Fun,a,b,eps)
with end, the one visible in your example just close if statement. The second problem is that n is not defined, probably you miss that matlab is case-sensitive, and N is not equal to n. So you should:
n=ceil((log10(b-a)-log10(eps))/log10(2));
If you fix this two things - your codes finish without any errors, (xaprox = 0.5210) tested on Matlab R2017b.

Related

This if is not working on Octave/Matlab

I have the code divided on three functions:
f.m (This function works)
function y=f(x)
y = x^2;
endfunction
df.m (The function that return the derivate of y=x^2. This function works)
function y=df(i)
syms x,diff(f(x),x);
subs(ans,x,i);
y = ans;
endfunction
newton.m (maxIt = max of tries)
function [x1,nIt] = newton (f,df,x0,tol,maxIt)
k=0;
x=x0;
nIt = 0;
while (k<maxIt)
if(df(x)== 0)
fprintf("La derivada, da resultado 0");
k=maxIt;
else
i = x - (f(x)/df(x))
x = i;
nIt = nIt + 1
k=k+1;
endif
end
endfunction
Ok, I executed the command newton(#f,#df,0,10,2). Two-thirds of the program works OK, but if I do df(0), the result is 0 but the if doesn't work. I verified that df(0) returns 0, and it's OK.
I´m new in MATLAB/Octave.
You have several mistakes in your code. Not all of them are directly relevant, but fixing all of them will make your code more readable and robust.
The function f if fine.
The function df assumes that f is known somehow, but it's not a good practice. you better pass f too to this function. Also, don't use ans as a variable, store your intermediate result in different variables. This is how df should look:
function y = df(f,a)
syms x
d = diff(f(x),x);
y = subs(d,x,a);
end
Now you have to change all the calls to df in your newton function to df(f,x). I'm not sure what is your final goal, but right now, the variables x1 and tol are not in use in any way.
Hope it solves the problem ;)

Nested calls to integral and integral2 in Matlab

I have some code here which illustrates the nested nature of some integrals that I want to perform in matlab. When I run the following code I get the error
Error using .*
Matrix dimensions must agree.
Error in fun1/integrand (line 7)
f = x.^2.*t;
it seems that the way I have set it up now does not allow for vectorized output of the integral function. What can I do to make my code run? I have commented below what I want the functions to do.
My code is as follows:
%Main script:
z = linspace(0,10,10);
I = zeros(10,1);
for i = 1:10
I(i) = fun2(z(i));
end
%Function 1 in separate file:
function I = fun1(x)
I = integral(#integrand,-1,1);
function f = integrand(t)
f = x.^2.*t;
end
end
%Function 2 in separate file:
function I = fun2(z)
I = integral2(#integrand,-1,1,-1,1);
function f = integrand(x,y)
f = z.*fun1(x).*y; // here fun1 should return the value for all x that is swept through by integral2 during its call.
end
end
The problem with your code is you are using integral2 and integral1 in a combination. This way integral2 generates a grid for x and y and integral1 generates the t values. This way the t and x values don't match in size, and even if they would they are part of a different grid.
As already discussed, using ingetral3 is the right choice. Alternatively you could simply "fix" this introducing a loop, but this results in much slower code:
function I = fun1(x)
I=nan(size(x));
for ix=1:numel(x)
I(ix) = integral(#(t)integrand(x(ix),t),-1,1);
end
function f = integrand(x,t)
f = x.^2.*t;
end
end

What is wrong with my Simpson algorithm?

I was trying to write an algorithm to approximate integrals with Simpson's method. When I try to plot it in a loglog plot, however, I don't get the correct order of accuracy which is O(h^4) (I get O(n)). I can't find any errors though. This is my code:
%Reference solution with Simpson's method (the reference solution works well)
yk = 0;
yj = 0;
href = 0.0001;
mref = (b-a)/href;
for k=2:2:mref-1
yk=yk+y(k*href+a);
end
for j=1:2:mref
yj=yj+y(href*j+a);
end
Iref=(href/3)*(y(a)+y(b)+2*yk+4*yj);
%Simpson's method
iter = 1;
Ehmatrix = 0;
for n = 0:nmax
h = b/(2^n+1);
x = a:h:b;
xodd = x(2:2:end-1);
xeven = x(3:2:end);
yodd = y(xodd);
yeven = y(xeven);
Isimp = (h/3)*(y(x(1))+4*sum(yodd)+2*sum(yeven)+y(b));
E = abs(Isimp-Iref);
Ehmatrix([iter],1) = [E];
Ehmatrix([iter],2) = [h];
iter = iter + 1;
end
figure
loglog(Ehmatrix(:,2),Ehmatrix(:,1))
a and b are the integration limits and y is the integrand that we want to approximate.
Djamillah - your code looks fine though the initialization of h is probably valid only for the case where a==0, so you may want to change this line of code to
h = (b-a)/(2^n+1);
I wonder if x = a:h:b; will always be valid - sometimes b may be included in the list, and sometimes it might not be, depending upon h. You may want to reconsider and use linspace instead
x = linspace(a,b,2^n+1);
which will guarantee that x has 2^n+1 points distributed evenly in the interval [a,b]. h could then be initialized as
h = x(2)-x(1);
Also, when determining the even and odd indices, we need to ignore the last element of x for both even and odd. So instead of
xodd = x(2:2:end-1);
xeven = x(3:2:end);
do
xodd = x(2:2:end-1);
xeven = x(3:2:end-1);
Finally, rather than using a vector y (how is this set?) I might just use the function handle to the function that I'm integrating instead and replace the calculation above as
Isimp = delta/3*(func(x(1)) + 4*sum(func(xodd)) + 2*sum(func(xeven)) + ...
func(x(end)));
Other than these tiny things (which are probably negligible), there is nothing in your algorithm to indicate a problem. It produced similar results to a version that I have.
As for the order of convergence, should it be O(n^4) or O(h^4)?
Taking into account Geoff's suggestions, and making a few other changes, it all works as expected.
%Reference solution with Simpson's method (the reference solution works well)
a=0;
b=1;
y=#(x) cos(x);
nmax=10;
%Simpson's method
Ehmatrix = [];
for n = 0:nmax
x = linspace(a,b,2^n+1);
h = x(2)-x(1);
xodd = x(2:2:end-1);
xeven = x(3:2:end-1);
yodd = y(xodd);
yeven = y(xeven);
Isimp = (h/3)*(y(x(1))+4*sum(yodd)+2*sum(yeven)+y(b));
E = abs(Isimp-integral(y,0,1));
Ehmatrix(n+1,:) = [E h];
end
loglog(Ehmatrix(:,2),Ehmatrix(:,1))
P=polyfit(log(Ehmatrix(:,2)),log(Ehmatrix(:,1)),1);
OrderofAccuracy=P(1)
You were getting O(h) accuracy because xeven=x(3:2:end) was wrong. Replacing it by xeven=x(3:e:end-1) fixes the code, and thus the accuracy.

correct function handle for integral2 in matlab

I created a function in matlab that returns a vector like
function w = W_1D(x,pos,h)
w=zeros(1,length(x));
if (h~=0)
xmpos = x-pos;
inds1 = (-h <= xmpos) & (xmpos < 0);
w(inds1) = xmpos(inds1)./h + 1;
inds2 = (0 <= xmpos) & (xmpos <= h);
w(inds2) = -xmpos(inds2)./h + 1;
else
error('h shouldn't be 0')
end
end
Thus, in the end, there is a vector w of size length(x).
Now i created a second function like
function f = W_2D(x,y,pos_1,pos_2,h)
w_x = W_1D(x,pos_1,h);
w_y = W_1D(y,pos_2,h);
f = w_x'*w_y;
end
where length(x)=length(y). Thus, the function W_2D obviously returns a matrix.
But when I now try to evaluate the integral over a rectangular domain like e.g.
V = integral2(#(x,y) W_2D(x,y,2,3,h),0,10,0,10);
matlab returns some errors:
Error using integral2Calc>integral2t/tensor (line 242)
Integrand output size does not match the input size.
Error in integral2Calc>integral2t (line 56)
[Qsub,esub] = tensor(thetaL,thetaR,phiB,phiT);
Error in integral2Calc (line 10)
[q,errbnd] = integral2t(fun,xmin,xmax,ymin,ymax,optionstruct);
Error in integral2 (line 107)
Q = integral2Calc(fun,xmin,xmax,yminfun,ymaxfun,opstruct);
I also tried to vary something in the W_2D-function: instead of f = w_x'*w_y;
I tried f = w_x.'*w_y;
or w_y = transpose(w_y); f = kron(w_x,w_y);, but there is always this error with the Integrand output size-stuff.
Can anyone explain, where my fault is?
EDIT: After Werner's hint with the keyboard debugging method, I can tell you the following.
The first step returns w_x of type <1x154 double>, w_y is <1x192 double>, x and y are both <14x14 double>. In the next step, f appears with a value of <154x192 double>. Then everything disappears, except x and y and the matlab-function integral2Calc.m appears in the editor and it jumps to the Function Call Stack integral2t/tensor and after some more steps, the error occurs here
Z = FUN(X,Y); NFE = NFE + 1;
if FIRSTFUNEVAL
if ~isfloat(Z)
error(message('MATLAB:integral2:UnsupportedClass',class(Z)));
end
% Check that FUN is properly vectorized. This is important here
% because we (otherwise) always pass in square matrices, which
% reduces the probability of the user generating an error by
% using matrix functions instead of elementwise functions.
Z1 = FUN(X(VTSTIDX),Y(VTSTIDX)); NFE = NFE + 1;
if ~isequal(size(Z),size(X)) || ~isequal(size(Z1),size(VTSTIDX))
% Example:
% integral2(#(x,y)1,0,1,0,1)
error(message('MATLAB:integral2:funSizeMismatch'));
end
Hope that information is detailed enough...I have no idea what happenes, because my example is exact as it is given on the mathworks site about integral2, isn't it?
Maybe I should precise a bit more, what I wanna do: since W_2D gives me a surface w(x,y) of a compactly supported 2-dimensional hat-function, stored in a matrix w, I want to calculate the volume between the (x,y)-plane and the surface z=w(x,y)...
EDIT2: I still do not understand how to handle the problem, that integral2 creates matrices as inputs for my W_1D-functions, which are called in W_2D and intended to have a <1xn double>-valued input and return a <1xn double> output, but at least I can simply use the following to solve the integration over the tensor product by using two one-dimensional integral-calls, that is
V = integral(#(x)integral(#(y)W_1D(y,3,h),0,10).*W_1D(x,2,h),0,10);
This first function is quite wrong. You are not indexing the array positions while you are doing w = x inside for.
Besides, if that would work, you are returning a line vector, that is, size 1xlength(x) and when you do w_x'*w_y you are doing length(x)x1 times 1xlength(y), which would give you a matrix length(x)*length(y).
Consider correcting your function:
function w = W_1D(x,pos)
w = zeros(length(x),1); % Allocate w as column vector, so that the product gives a scalar (as I suppose that it is what you want.
for ii=1:length(x) % Here, so that is indexes w and x elements as you need
w(ii)=x(ii) - pos; % I changed your code to something that makes sense, but I don't know if that is what you want to do, you have to adapt it to work correctly.
end
end
You may also want to debug your functions, consider adding keyboard before your operations and check what they are returning using dbstep. I.e:
function f = W_2D(x,y,pos_1,pos_2)
w_x = W_1D(x,pos_1);
w_y = W_1D(y,pos_2);
keyboard
f = w_x'*w_y;
end
Execution will stop at keyboard, then you can check w_x size, w_y size, and do dbstep to go after f = w_x'*w_y and see what it returned. After you finish debug, you can do dbcont so that it will continue execution.
This answer is a draft as it is quite difficult to help you with the information you have provided. But I think you can start working the things out with this. If you have more doubts feel free to ask.

Ignoring a warning in a loop and continuing

I have three vectors A, B, and C. For each value in these vectors I would like to solve the equation C^x = A^x + B^x. Unfortunately this is an equation that I have found to be solvable only iteratively, so I am attempting to use MATLAB's "solve" function to find a solution for each case. My code is as follows:
exponents = zeros(100,1);
syms x
A = rand(100,1);
B = rand(100,1);
C = rand(100,1);
for i = 1:100
exponents(i) = eval(solve(C(i)^x == A(i)^x + B(i)^x));
end
Sometimes, however, the solution is unobtainable, which leads to the error message, "Warning: Explicit solution could not be found." I am okay with this, but if I run into an unsolvable equation, I would like to simply leave the "exponents(i)" unchanged for that iteration and move onto the next one, instead of having my code abruptly stop. Any suggestions?
If you put the statement that causes the occasional error inside a try/catch statement, then the error will not cause execution to stop. For example, you could try:
for i = 1:100
try
exponents(i) = eval(solve(C(i)^x == A(i)^x + B(i)^x));
catch
exponents(i) = NaN;
end;
end
There is not a direct way in MATLAB for catching warnings (at least a documented way). It is not elegant in the slightest, if not downright ugly, you can try polling the output of lastwarn.
...
exponents(i) = eval(solve(C(i)^x == A(i)^x + B(i)^x));
[~, msgid] = lastwarn;
if strcmp(msgid, YOURWARNINGID)
continue;
end
There is a similar post here, except the poster was getting an error.