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)
Related
I'm working on my own Matlab code for the bisection method, and have defined an anonymous function I am trying to find the root for. It produces a simple graph and I know it could easily find the root if it would run properly.
When my code gets up to evaluating the function at a given x value, it returns:
Error using feval
Function to evaluate must be represented as a string scalar, character vector, or
function_handle object.
Error in bisection (line 3)
fa = feval(f, a);
My full code is:
function m=bisection(f,a,b,imax,tol)
fa = feval(f, a);
fb = feval(f, b);
i=0;
if fa*fb>0
disp('No root here: pick a new interval')
return
end
while abs(b-a) >= tol
i = i + 1;
m=(a+b)/2;
fm = feval(f, m);
if fa*fb<0
b = m;
else
a = m;
end
abs(fm);
end
% Show the last approximation considering the tolerance
w = feval(f, m);
fprintf('\n x = %f produces f(x) = %f \n %i iterations\n', m, fm, i-1);
fprintf(' Approximation with tolerance = %f \n', tol);
end
With my function being:
function [T] = freezing(x)
alpha = 0.138*10^-6;
Ti = 20;
Ts = -15;
t = 60*60*24*60;
tol = 10^-13;
%x = linspace(0,3);
T = #(x) (Ti-Ts)*erf(x./(2*sqrt(alpha*t)))+Ts;
dT = #(x) (Ti-Ts)*(1/sqrt(pi*alpha*t))*exp(-x.^2./(4*alpha*t));
T = T(x);
end
I'm really not sure what the issue is here – in my command window, I can easily input x values and get output. Any suggestions are much appreciated!
feval needs f to be a function handle. When you call bisection, I suspect you're passing the result of freezing to bisection instead of the function handle to freezing
You need to do bisection(#freezing, ...) instead of bisection(freezing(...), ...)
The #freezing creates a function handle that is passed to bisection. Doing the latter passes the result of freezing to bisection.
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
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
i have question,about which i am too much interested,suppose that i have two M-file in matlab, in the first one i have described following function for calculating peaks and peaks indeces
function [peaks,peak_indices] = find_peaks(row_vector)
A = [0 row_vector 0];
j = 1;
for i=1:length(A)-2
temp=A(i:i+2);
if(max(temp)==temp(2))
peaks(j) = row_vector(i);
peak_indices(j) = i;
j = j+1;
end
end
end
and in second M-file i have code for describing sinusoidal model for given data sample
function [ x ]=generate(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))';
wn = rand(length(t),1).*2 - 1;
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
end
my question is how to combine it together?one solution would be just create two M-file into folder,then call function from one M-file and made operation on given vector and get result,and then call second function from another M file on given result and finally get what we want,but i would like to build it in one big M-file,in c++,in java,we can create classes,but i am not sure if we can do same in matlab too,please help me to clarify everything and use find_peaks function into generate function
UPDATED:
ok now i would like to show simple change what i have made in my code
function [ x ] = generate(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = rand(length(t),1).*2 - 1;
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
[pks,locs] = findpeaks(x);
end
i used findpeaks built-in function in matlab,but i am getting following error
generate(1000,50,50)
Undefined function 'generate' for input arguments of type 'double'.
also i am interested what would be effective sampling rate to avoid alliasing?
You can simply put both in one file. The file must have the same name as the first function therein, and you will not be able to access subsequently defined functions from outside that file. See the MATLAB documentation on functions http://www.mathworks.co.uk/help/matlab/ref/function.html (particularly the examples section).
Also note that MATLAB has a built-in function findpeaks().
(By the way, you're still sampling at too low a frequency and will most certainly get aliasing - see http://en.wikipedia.org/wiki/Aliasing#Sampling_sinusoidal_functions )
Edit: As you requested it, here is some more information on the sampling theorem. A good and simple introduction to these basics is http://www.dspguide.com/ch3/2.htm and for further reading you should search for the Shannon/Nyquist sampling theorem.
Try with this, within a single MATLAB script
function test()
clc, clear all, close all
x = generate(1000,50,50);
[p,i] = find_peaks(x)
end
function x = generate(N,m,A3)
f1 = 100;
f2 = 200;
T = 1./f1;
t = (0:(N*T/m):(N*T))'; %'
wn = rand(length(t),1).*2 - 1;
x = 20.*sin(2.*pi.*f1.*t) + 30.*cos(2.*pi.*f2.*t) + A3.*wn;
end
function [peaks,peak_indices] = find_peaks(row_vector)
A = [0;row_vector;0];
j = 1;
for i=1:length(A)-2
temp=A(i:i+2);
if(max(temp)==temp(2))
peaks(j) = row_vector(i);
peak_indices(j) = i;
j = j+1;
end
end
end
My code works BUT I need to add 2 more things:
output- a vector containing the sequence of estimates including the initial guess x0,
input- max iterations
function [ R, E ] = myNewton( f,df,x0,tol )
i = 1;
while abs(f(x0)) >= tol
R(i) = x0;
E(i) = abs(f(x0));
i = i+1;
x0 = x0 - f(x0)/df(x0);
end
if abs(f(x0)) < tol
R(i) = x0;
E(i) = abs(f(x0));
end
end
well, everything you need is pretty much done already and you should be able to deal with it, btw..
max iteration is contained in the variable i, thus you need to return it; add this
function [ R, E , i] = myNewton( f,df,x0,tol )
Plot sequence of estimates:
plot(R); %after you call myNewton
display max number of iterations
disp(i); %after you call myNewton