This if is not working on Octave/Matlab - 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 ;)

Related

Single point Bisection Method - f(x)=e^(-x) -x

I want to find the root of f(x)=e^(-x) -x using the bisection method for a single point. I Was given c = sgn f(a)(b − a) I will use this later on the main program and
So first of all I have the following program in MATLAB:
function [y] =f(x)
y=exp(-x)-x;
end
then for my sgn which is the wheather the f(x) is negative or positive:
function [z] =sgn(x)
w=f(x);
if (w>0)
z=1;
elseif(w==0)
z=0;
else
z=-1;
endif
end
So implementing these in my final program I have the following code:
function [root,i,e]=bisection_mod(a,b,tol)
a=-1;b=2;
i=0;
xold= a;
xnew=0;
tol = 10^(-8);
e = abs(xnew-xold);
sgn(f(a))
c=sgn(f(a))*(b-a)
while (abs(xnew-xold) > tol)
if (i>1)
xold = xnew;
endif
cc=c*sgn(f(xold));
par=(2^(i+1));
xnew = xold + cc./par
e = abs(xnew-xold)
i=i+1;
if (i>100)
break
endif
endwhile
i
root=xnew
endfunction
the root of the function im trying to examin is 0.567
but my program gives back 0.2246.
Could I have some info about what I’m doing wrong or some corrections to my code?
Just a couple of tiny mistakes:
Your sgn function is computing sgn(f(f(x)))! You give it f(x) as input, and the first thing you do inside is do f(x) again! remote it from inside the function, make w=x.
You are not updating xold for the first 2 iterations! The first skip is OK, but in the second iteration i==1, therefore the condition should read if (i>=1) or better if(i>0).

Storing and accessing matrix operated inside a function parallelized by pararrayfun of Octave/Matlab

Pararrayfun is used this way
pkg load parallel;
# fun is the function to apply
fun = #(x) x^2;
vector_x = 1:10000;
vector_y = pararrayfun(16, fun, vector_x);
I intend to apply it to a function with this form
fun = #(i) zz(1:100,i+1) = z.^2;
where z is a column vector, and zz is a 100xi matrix. I want to get the matrix zz out after the pararrayfun() but I get nothing back. I dont know if I am using the right code or the right argument as I have just started using octave a month ago. Any help would really be appreciated.
Here is my attempted "full" code:
pkg load parallel;
z = linspace(-1,10,100).';
fun = #(i) zz(1:100,i+1) = z.^2;
i = 0:9999;
pararrayfun(16, fun, i);
I tried to use global zz but I still get nothing.
The first answer is that the zz variable inside you fun is a local variable. It would have to be declared as global, but this is not possible inside an anonymous function (defined with #() ...).
One might be tempted to try to define fun with
pkg load parallel;
z = linspace(-1,10,100).';
global zz
zz = zeros(100, 10000);
function fun1(idx, z)
global zz
zz(:, idx) = z.^2;
endfunction
fun = #(idx) fun1(idx, z)
idx = 1:10000;
pararrayfun(nproc, fun, idx);
But the zz is not modified. Probably because each thread has its own context.
This is a good thing, because otherwise modifying a global variable inside a pararrayfun call would lead to potential race conditions.
Here is a safer way:
pkg load parallel;
z = linspace(-1,10,100).';
fun = #(i) z.^2;
idx = 1:10000;
zz = pararrayfun(nproc, fun, idx);
As a side note, for this example,
zz = repmat(z, 1, 10000);
would be much faster.

MATLAB function handles and parameters

When I type help gmres in MATLAB I get the following example:
n = 21; A = gallery('wilk',n); b = sum(A,2);
tol = 1e-12; maxit = 15;
x1 = gmres(#(x)afun(x,n),b,10,tol,maxit,#(x)mfun(x,n));
where the two functions are:
function y = afun(x,n)
y = [0; x(1:n-1)] + [((n-1)/2:-1:0)'; (1:(n-1)/2)'].*x+[x(2:n); 0];
end
and
function y = mfun(r,n)
y = r ./ [((n-1)/2:-1:1)'; 1; (1:(n-1)/2)'];
end
I tested it and it works great. My question is in both those functions what is the value for x since we never give it one?
Also shouldn't the call to gmres be written like this: (y in the #handle)
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
Function handles are one way to parametrize functions in MATLAB. From the documentation page, we find the following example:
b = 2;
c = 3.5;
cubicpoly = #(x) x^3 + b*x + c;
x = fzero(cubicpoly,0)
which results in:
x =
-1.0945
So what's happening here? fzero is a so-called function function, that takes function handles as inputs, and performs operations on them -- in this case, finds the root of the given function. Practically, this means that fzero decides which values for the input argument x to cubicpoly to try in order to find the root. This means the user just provides a function - no need to give the inputs - and fzero will query the function with different values for x to eventually find the root.
The function you ask about, gmres, operates in a similar manner. What this means is that you merely need to provide a function that takes an appropriate number of input arguments, and gmres will take care of calling it with appropriate inputs to produce its output.
Finally, let's consider your suggestion of calling gmres as follows:
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
This might work, or then again it might not -- it depends whether you have a variable called x in the workspace of the function eventually calling either afun or mfun. Notice that now the function handles take one input, y, but its value is nowhere used in the expression of the function defined. This means it will not have any effect on the output.
Consider the following example to illustrate what happens:
f = #(y)2*x+1; % define a function handle
f(1) % error! Undefined function or variable 'x'!
% the following this works, and g will now use x from the workspace
x = 42;
g = #(y)2*x+1; % define a function handle that knows about x
g(1)
g(2)
g(3) % ...but the result will be independent of y as it's not used.

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

Why can't I pass a function handle to fsolve, but I can write an equivalent anonymous function in fsolve?

I find this somewhat odd. I am currently writing a simple function to solve a system of equations using fsolve. Here is what I have:
%Variable Declarations
I0 = 10e-12;
n = 1;
Vt = 0.0259;
R = 10e3;
Vs = 3;
%Function 1 (Some may recognize that this is the Shockley Diode Equation, if anyone cares...)
i1 = #(v1)(I0) * (exp((v1)/(n*Vt))-1);
%Function 2
i2 = #(v1) ((Vs-v1)/R);
%This is what I originally tried
h = #(v1) i1(v1)-i2(v1);
fsolve(h(v1), 1)
%After running this, I receive "Undefined function or variable 'v1.'"
% However, if I write
fsolve(#(v1)i1(v1)-i2(v1),1)
%The function works. With the result, I plugged that value into h(v1), and it produces the expected result (very close to 0)
That said, why doesn't matlab allow me to pass a function handle to fsolve?
You want to pass a function handle, which is h, not h(v1). h(v1) itself can't be evaluated because v1 is not defined.
Try fsolve(h, 1)