Error in code, a method to compute sqrt (a) - matlab

One of the methods to compute sqrt(a), a>0 is
X(n+1) = (a + (X(n)*X(n-1))/(X(n)+X(n-1)), n = 1, 2, …,
with X0=1 and X1=a (That is, it is known that lim n-> infin of Xn = sqrt(a)
Write a function [sqa, nitr] = mySqrt(a) which implements this calculation. The function should use a while-loop, terminate when the difference between Xn+1 and Xn becomes smaller than eps(10*a), and output Xn+1 in sqa and the value of n at which the while-loop was terminated in nitr. Test your function for a = 103041.
I have written this but it does not work
function [sqa, nitr] = mySqrt (a)
%[sqa, nitr] = mySqrt (a)
% computes square root of a
% sqa = a;
sqaprev = a;
nitr = 0;
X(n+1) = (a + (X(n)*X(n-1))/(X(n)+X(n-1))); %find the second term
sqa= X(n+1)
while abs (sqaprev-sqa) >= eps (10*a)
sqaprev = sqa;
sqa = (1/2) *(sqaprev+ (a/sqaprev));
nitr = nitr + 1;
end %while
end
i get the error:
Unrecognized function or variable 'X'.
Error in mySqrt (line 7)
X(n+1) = (a + (X(n)*X(n-1))/(X(n)+X(n-1))); %find the second term
Could someone help me ?

You should start with declaring your variables and assigning them values
X(1)=1;
X(2)=a;
n=2;
Then in the loop you apply the given recursion formula, not the Heron/Babylonian formula that got from somewhere else.

According to the algorithm you presented for the square root, you can try the code below
function [sqa, n] = mySqrt(a)
n = 2; % start from 2
X = [1,a]; % initial value for sequence X
while true % repeat procedure until termination condition is reached
X(n+1) = (a + (X(n)*X(n-1)))/(X(n)+X(n-1)); % update sequence X by assigning new values
if abs(X(n+1)-X(n)) <= eps(10*a) % termination condition
break;
end
n = n + 1;
end
sqa = X(end); % return the last element of X as the square root
end
such that
>> [sqa,n] = mySqrt(a)
sqa = 321.00
n = 20

Related

How to increase number in range set till it gives a specific answer?

I've wrote a rungekutta code and there is a specific x range that it should calculate up to it. The problem is that the prof. wants a code that keeps on adding up by itself till it reaches the required answer.
I tried using the 'if' function but it only works once and no more (thus, even creating a mismatch in array lengths.
Code:
h=0.5;% step size
z=0.5;
x = 0:h:z;% the range of x
y = zeros(1,length(x));
y(1) = 50;% initial condition
F_xy = #(t,x) (37.5-3.5*x);%function
for i=1:(length(x)-1)% calculation loop
k_1 = F_xy(x(i),y(i));
k_2 = F_xy(x(i)+h,y(i)+h*k_1);
y(i+1) = y(i) + (h/2)*(k_1+k_2);% main equation
if y(i+1)>11
x=0:h:z+1;
end
end
disp (y(i+1))
Error of arrays length (shows that if function only works once)
41.4063
Error using plot
Vectors must be the same length.
Error in code6rungekutta2ndorder (line 30)
plot(x,y), grid on
it should keep on increasing by +1 in the 'z' variable till the answer of y(i+1) is less than 11. (correct z should be 9.5)
As #medicine_man suggested, you need a while loop:
h=0.5;% step size
z=0.5;
x = 0;
y = 50;% initial condition
F_xy = #(t,x) (37.5-3.5*x);%function
m = 0;
while y(m+1) > 11
m = m+1;
x = x+h;
k_1 = F_xy(x,y(m));
k_2 = F_xy(x+h,y(m)+h*k_1);
y(m+1) = y(m) + (h/2)*(k_1+k_2);% main equation
end
figure;
plot(0:h:x, y);
Your terminate condition, which is y(m+1) > 11, is checked at the beginning of each iteration of the while loop. In the loop, you can increment the value of x and update your y array. The loop runs until the terminate condition is met.
The result of the above code:

Trying to get a MATLAB function to take an array of inputs

I'm trying to call a numerical integration function (namely one that uses the trapazoidal method) to compute a definite integral. However, I want to pass more than one value of 'n' to the following function,
function I = traprule(f, a, b, n)
if ~isa(f, 'function_handle')
error('Your first argument was not a function handle')
end
h = (b-a)./ n;
x = a:h:b;
S = 0;
for j = 2:n
S = S + f(x(j));
end
I = (h/2)*(f(a) + 2*S + f(b)); %computes indefinite integral
end
I'm using; f = #(x) 1/x, a = 1 and b = 2. I'm trying to pass n = 10.^(1:10) too, however, I get the following output for I when I do so,
I =
Columns 1 through 3
0.693771403175428 0.069377140317543 0.006937714031754
Columns 4 through 6
0.000693771403175 0.000069377140318 0.000006937714032
Columns 7 through 9
0.000000693771403 0.000000069377140 0.000000006937714
Column 10
0.000000000693771
Any ideas on how to get the function to take n = 10.^(1:10) so I get an output something like,
I = 0.693771403175428, 0.693153430481824, 0.693147243059937 ... and so on for increasing powers of 10?
In the script where you are calling this from, simply iterate over n
k = 3;
f = #(x)1./x;
a = 1; b = 2;
I = zeros(k,1);
for n = 1:k
I(n) = traprule(f, a, b, 10^n);
end
% output: I = 0.693771403175428
% 0.693153430481824
% 0.693147243059937
Then I will contain all of the outputs. Alternatively you can adapt your function to use the same logic to loop over the elements of n if it is passed
as a vector.
Note, you can improve the efficiency of your traprule code by removing the for loop:
% This loop operates on every element of x individually, and is inefficient
S = 0;
for j = 2:n
S = S + f(x(j));
end
% If you ensure you use element-wise equations like f=#(x)1./x instead of f=#(x)1/x
% Then you can use this alternative:
S = sum(f(x(2:n)));

Implementing a filter in Matlab

I am trying to implement the following filter on a discrete signal x:
I'm supposed to write a MATLAB function that takes a length-M (> N) vector x and a scalar N as input. The output should be a length-M vector y.
I should then test the filter with M = 50, x[n]=cos(n*pi/5)+dirac[n-30]-dirac[n-35] and N = 4, 8, 12.
Here is my try, which returns Inf with the given input and N:
function y = filt( x, N )
% filter function
if(~isvector(x))
error('Input must be a vector')
end
y = zeros(1,length(x));
temp = zeros(1,length(x));
n=1;
for v = x(:)
temp(n) = v(n);
if(n <= N-1)
y(n) = max(x);
n = n+1;
elseif(n >= N-1)
y(n) = max(temp);
end
end
end
I also tried using the built-in filter function but I can't get it to work.
Code for using the filter:
p = zeros(1,50);
for i=0:50
p(i+1)= cos(i*pi/5)+dirac(i-30)-dirac(i-35)
end
y = filt(p,4)
Thanks in advance.
That's because dirac(0) gives you Inf. This will happen in two places in your signal, where n=30 and n=35. I'm assuming you want the unit impulse instead. As such, create a signal where at n = 31 and n = 36, the output is 1, then add this with your cosine signal. This is because MATLAB starts indexing at 1 and not 0, and so dirac[0] would mean that the first point of your signal is non-zero, so translating this over by 30: dirac[n-30] would mean that the 31st point is non-zero. Similar case for dirac[n-35], so the 36th point is non-zero:
p = zeros(1,50);
p(31) = 1; p(36) = 1;
p = p + cos((0:49)*pi/5);
y = filt(p,4);
I also have some reservations with your code. It doesn't do what you think it's doing. Specifically, I'm looking at this section:
n=1;
for v = x(:)
temp(n) = v(n);
if(n <= N-1)
y(n) = max(x);
n = n+1;
elseif(n >= N-1)
y(n) = max(temp);
end
end
Doing v = x(:) would produce a column vector, and using a loop with a column vector will have unintentional results. Specifically, this loop will only execute once, with v being the entire signal. You also aren't checking the conditions properly for each window. You are doing max(x), which applies the maximum to the entire signal, and not the window.
If I can suggest a rewrite, this is what you should be doing instead:
function y = filt( x, N )
% filter function
if(~isvector(x))
error('Input must be a vector')
end
y = zeros(1,length(x));
%///// CHANGE
for n = 1 : numel(x)
if (n <= N)
y(n) = max(x(1:n));
else
y(n) = max(x(n:-1:n-N+1));
end
end
end
Take note that the if statement is n <= N. This is because in MATLAB, we start indexing at 1, but the notation in your equation starts indexing at 0. Therefore, instead of checking for n <= N-1, it must now be n <= N.

Trying to solve Simultaneous equations in matlab, cannot work out how to format the functions

I was given a piece of Matlab code by a lecturer recently for a way to solve simultaneous equations using the Newton-Raphson method with a jacobian matrix (I've also left in his comments). However, although he's provided me with the basic code I cannot seem to get it working no matter how hard I try. I've spent many hours trying to introduce the 'func' function but to no avail, frequently getting the message that there aren't enough inputs. Any help would be greatly appreciated, especially with how to write the 'func' function.
function root = newtonRaphson2(func,x,tol)
% Newton-Raphson method of finding a root of simultaneous
% equations fi(x1,x2,...,xn) = 0, i = 1,2,...,n.
% USAGE: root = newtonRaphson2(func,x,tol)
% INPUT:
% func = handle of function that returns[f1,f2,...,fn].
% x = starting solution vector [x1,x2,...,xn].
% tol = error tolerance (default is 1.0e4*eps).
% OUTPUT:
% root = solution vector.
if size(x,1) == 1; x = x'; end % x must be column vector
for i = 1:30
[jac,f0] = jacobian(func,x);
if sqrt(dot(f0,f0)/length(x)) < tol
root = x; return
end
dx = jac\(-f0);
x = x + dx;
if sqrt(dot(dx,dx)/length(x)) < tol
root = x; return
end
end
error('Too many iterations')
function [jac,f0] = jacobian(func,x)
% Returns the Jacobian matrix and f(x).
h = 1.0e-4;
n = length(x);
jac = zeros(n);
f0 = feval(func,x);
for i =1:n
temp = x(i);
x(i) = temp + h;
f1 = feval(func,x);
x(i) = temp;
jac(:,i) = (f1 - f0)/h;
end
The simultaneous equations to be solved are:
sin(x)+y^2+ln(z)-7=0
3x+2^y-z^3+1=0
x+y+Z-=0
with the starting point (1,1,1).
However, these are arbitrary and can be replaced with anything, I mainly just need to know the general format.
Many thanks, I know this may be a very simple task but I've only recently started teaching myself Matlab.
You need to create a new file called myfunc.m (or whatever name you like) which takes a single input parameter - a column vector x - and returns a single output vector - a column vector y such that y = f(x).
For example,
function y = myfunc(x)
y = zeros(3, 1);
y(1) = sin(x(1)) + x(2)^2 + log(x(3)) - 7;
y(2) = 3*x(1) + 2^x(2) - x(3)^3 + 1;
y(3) = x(1) + x(2) + x(3);
end
You can then refer to this function as #myfunc as in
>> newtonRaphson2(#myfunc, [1;1;1], 1e-6);
The reason for the special notation is that Matlab allows you to call a function with no parameters by omitting the parens () that follow it. So for example, Matlab interprets myfunc as you calling the function with no arguments (so it tries to replace it with its result) whereas #myfunc refers to the function itself, rather than its result.
Alternatively you can write a function directly using the # notation, as in
>> newtonRaphson2(#(x) exp(x) - 3*x, 2, 1e-2)
ans =
1.5315
>> newtonRaphson2(#(x) exp(x) - 3*x, 1, 1e-2)
ans =
0.6190
which are the two roots of the equation exp(x) - 3 * x = 0.
Edit - as an aside, your professor has terrible coding style (if the code in your question is a direct copy-paste of what he gave you, and you haven't mangled it along the way). It would be better to write the code like this, with indentation making it clear what the structure of the code is.
function root = newtonRaphson2(func, x, tol)
% Newton-Raphson method of finding a root of simultaneous
% equations fi(x1,x2,...,xn) = 0, i = 1,2,...,n.
%
% USAGE: root = newtonRaphson2(func,x,tol)
%
% INPUT:
% func = handle of function that returns[f1,f2,...,fn].
% x = starting solution vector [x1,x2,...,xn].
% tol = error tolerance (default is 1.0e4*eps).
%
% OUTPUT:
% root = solution vector.
if size(x, 1) == 1; % x must be column vector
x = x';
end
for i = 1:30
[jac, f0] = jacobian(func, x);
if sqrt(dot(f0, f0) / length(x)) < tol
root = x; return
end
dx = jac \ (-f0);
x = x + dx;
if sqrt(dot(dx, dx) / length(x)) < tol
root = x; return
end
end
error('Too many iterations')
end
function [jac, f0] = jacobian(func,x)
% Returns the Jacobian matrix and f(x).
h = 1.0e-4;
n = length(x);
jac = zeros(n);
f0 = feval(func,x);
for i = 1:n
temp = x(i);
x(i) = temp + h;
f1 = feval(func,x);
x(i) = temp;
jac(:,i) = (f1 - f0)/h;
end
end

MATLAB - how to count the number of function calls

Currently I'm doing a code on the Secant Method, and so far the code runs ok.
However, I still have to update my "count.funcCount" by counting the number of function calls that I used in the "secant" function. How should I modify my code ?
This is what I have so far for the code:
function [ root, fcneval, count ] = secant(f, x0, x1, my_options)
my_options = optimset('MaxIter', 50, 'TolFun', 1.0e-5);
count = struct('iterations',0,'funcCount',0,'message',{'empty'});
xp = x0; %# Initialize xp and xc to match with
xc = x1; %# x0 and x1, respectively
MaxIter = 100;
TolFun = 1.0e-5;
%# Secant Method Loop
for i = 2:MaxIter
fd = f(xc) - f(xp); %# Together, the ratio of d and fd yields
d = xc - xp; %# the slope of the secant line going through xc and xp
xn = ((xc * fd) - (f(xc) * d)) / fd; %# Secant Method step
if (abs(xc - xn) < TolFun) && (abs(f(xn)) < TolFun) %# Stopping condition
break;
elseif i > MaxIter %# If still can't find a root after maximum
%# 100 iterations, consider not converge
count.message = sprintf('Do not converge');
end
xp = xc; % Update variables xc and xp
xc = xn;
end
%# Get outputs:
root = xn;
fcneval = f(root);
count.iterations = i;
end %# end function
---------------------------------------
function [f] = fun(x)
f = cos(x) + x;
end
Please help me, thank you in advance
Although I did not understand your question but still I think you can use a counter. Initialize it with zero and increment it every time your function is called. You are using an inbuilt function, just make necessary changes in its source code( FYI :you can do this in matlab) then save it with a new name and then use it in your main code.
You could create a nested function which have access to the variables of its parent function (including the function f and the counter count.funcCount). This function would call the actual method which does the computation, and then increment the counter.
Here is a rather silly example to illustrate the concept:
function [output,count] = myAlgorithm(f, x0)
count = 0;
output = x0;
while rand()<0.99 %# simulate a long loop
output = output + fcn(x0);
end
%# nested function with closure
function y = fcn(x)
%# access `f` and `count` inside the parent function
y = f(x); %# call the function
count = count + 1; %# increment counter
end
end
Now you call it as:
[output,count] = myAlgorithm(#(x)cos(x)+x, 1)