I am trying to implement the secant method using Octave, and in particular I made a function called secant("function","x0","x1","tolerance"). I used the while-loop for calculate the root of a function and I think the problem is in the loop.
But the result that I get, it is not what I expect. The correct answer is x=0,49438.
My code is the following:
tol = 10.^(-5); # tolerance
x0 = 0.4; # initial point
x1 = 0.6; # initial point
syms x;
fun = #(x) exp(sin(x)) - 2/(1+x.^2); # f(x) = exp(sin(x)) - 2/(1+x^2)
fprintf("Function f(x)\n");
fun
fprintf("\n");
fprintf("initial points: %f\n",x0,x1);
function[raiz,errel,niter] = secant(fun,x0,x1,tol)
niter = 0; # steps number
errel = []; # the vector of relative errors
y0 = fun(x0); # f(x0)
y1 = fun(x1); # f(x1)
ra = 0.0; # ra is the variable of the function's root
while abs(ra-x1)>= tol
niter += 1;
ra = x1 - ((x1-x0)./(y1-y0)).*y0; # formula of the secant method
if abs((ra-x1))<tol
raiz = ra;
return;
endif
x0 = x1; y0 = y1; x1 = ra;
y1 = fun(ra);
errel(niter) = abs(ra-x1)/abs(ra); # Calcule of relative error
endwhile
if abs((ra-x1)/ra)<tol
fprintf ('The method is over\n');
fprintf ('\n');
endif
raiz = ra;
endfunction
[r,er,tot] = secant(fun,x0,x1,tol)
I appreciate the help you can give me
It makes little sense to use the secant root in the loop condition. At first it is not defined, and inside the loop it is shifted into the support points for the next secant. Note that at the end ra and x1 contain the same value, making the loop condition trivial, in a wrong way.
Next, the secant has the equation
y(x) = y1 + (y1-y0)/(x1-x0)*(x-x_1)
check that with this formula y(x0)=y0 and y(x1)=y1. Thus the secant root is to be found at
x = x1 - (x1-x0)/(y1-y0)*y1
Finally, at no point are symbolic expressions used, defining x as symbolic variable is superfluous.
The break-out test inside the loop is also redundant and prevents a coherent state after the loop. Just remove it and remember that x1 contains the last approximation.
With all this I get an execution log as follows:
Function f(x)
fun =
#(x) exp (sin (x)) - 2 / (1 + x .^ 2)
initial points: 0.400000
initial points: 0.600000
The method is over
r = 0.494379048216965
er =
2.182723270633349e-01 3.747373180587413e-03 5.220701832080676e-05 1.899377363987941e-08
tot = 4
I am trying to convert this FORTRAN program (motion of pendulum) to CUDA FORTRAN but I can use only 1 block with two threads. Is there any way to use more then 2 threads....
MODULE CB
REAL :: Q,B,W
END MODULE CB
PROGRAM PENDULUM
USE CB
IMPLICIT NONE
INTEGER, PARAMETER :: N=10,L=100,M=1
INTEGER :: I,count_rate,count_max,count(2)
REAL :: PI,H,T,Y1,Y2,G1,G1F,G2,G2F
REAL :: DK11,DK21,DK12,DK22,DK13,DK23,DK14,DK24
REAL, DIMENSION (2,N) :: Y
PI = 4.0*ATAN(1.0)
H = 3.0*PI/L
Q = 0.5
B = 0.9
W = 2.0/3.0
Y(1,1) = 0.0
Y(2,1) = 2.0
DO I = 1, N-1
T = H*I
Y1 = Y(1,I)
Y2 = Y(2,I)
DK11 = H*G1F(Y1,Y2,T)
DK21 = H*G2F(Y1,Y2,T)
DK12 = H*G1F((Y1+DK11/2.0),(Y2+DK21/2.0),(T+H/2.0))
DK22 = H*G2F((Y1+DK11/2.0),(Y2+DK21/2.0),(T+H/2.0))
DK13 = H*G1F((Y1+DK12/2.0),(Y2+DK22/2.0),(T+H/2.0))
DK23 = H*G2F((Y1+DK12/2.0),(Y2+DK22/2.0),(T+H/2.0))
DK14 = H*G1F((Y1+DK13),(Y2+DK23),(T+H))
DK24 = H*G2F((Y1+DK13),(Y2+DK23),(T+H))
Y(1,I+1) = Y(1,I)+(DK11+2.0*(DK12+DK13)+DK14)/6.0
Y(2,I+1) = Y(2,I)+(DK21+2.0*(DK22+DK23)+DK24)/6.0
! Bring theta back to the region [-pi,pi]
Y(1,I+1) = Y(1,I+1)-2.0*PI*NINT(Y(1,I+1)/(2.0*PI))
END DO
call system_clock ( count(2), count_rate, count_max )
WRITE (6,"(2F16.8)") (Y(1,I),Y(2,I),I=1,N,M)
END PROGRAM PENDULUM
FUNCTION G1F (Y1,Y2,T) RESULT (G1)
USE CB
IMPLICIT NONE
REAL :: Y1,Y2,T,G1
G1 = Y2
END FUNCTION G1F
FUNCTION G2F (Y1,Y2,T) RESULT (G2)
USE CB
IMPLICIT NONE
REAL :: Y1,Y2,T,G2
G2 = -Q*Y2-SIN(Y1)+B*COS(W*T)
END FUNCTION G2F
CUDA FORTRAN VERSION OF PROGRAM
MODULE KERNEL
CONTAINS
attributes(global) subroutine mykernel(Y_d,N,L,M)
INTEGER,value:: N,L,M
INTEGER ::tid
REAL:: Y_d(:,:)
REAL :: PI,H,T,G1,G1F,G2,G2F
REAL,shared :: DK11,DK21,DK12,DK22,DK13,DK23,DK14,DK24,Y1,Y2
PI = 4.0*ATAN(1.0)
H = 3.0*PI/L
Y_d(1,1) = 0.0
Y_d(2,1) = 2.0
tid=threadidx%x
DO I = 1, N-1
T = H*I
Y1 = Y_d(1,I)
Y2 = Y_d(2,I)
if(tid==1)then
DK11 = H*G1F(Y1,Y2,T)
else
DK21 = H*G2F(Y1,Y2,T)
endif
call syncthreads ()
if(tid==1)then
DK12 = H*G1F((Y1+DK11/2.0),(Y2+DK21/2.0),(T+H/2.0))
else
DK22 = H*G2F((Y1+DK11/2.0),(Y2+DK21/2.0),(T+H/2.0))
endif
call syncthreads ()
if(tid==1)then
DK13 = H*G1F((Y1+DK12/2.0),(Y2+DK22/2.0),(T+H/2.0))
else
DK23 = H*G2F((Y1+DK12/2.0),(Y2+DK22/2.0),(T+H/2.0))
endif
call syncthreads ()
if(tid==1)then
DK14 = H*G1F((Y1+DK13),(Y2+DK23),(T+H))
else
DK24 = H*G2F((Y1+DK13),(Y2+DK23),(T+H))
endif
call syncthreads ()
if(tid==1)then
Y_d(1,I+1) = Y1+(DK11+2.0*(DK12+DK13)+DK14)/6.0
else
Y_d(2,I+1) = Y2+(DK21+2.0*(DK22+DK23)+DK24)/6.0
endif
Y_d(1,I+1) = Y_d(1,I+1)-2.0*PI*NINT(Y_d(1,I+1)/(2.0*PI))
call syncthreads ()
END DO
end subroutine mykernel
attributes(device) FUNCTION G1F (Y1,Y2,T) RESULT (G1)
IMPLICIT NONE
REAL :: Y1,Y2,T,G1
G1 = Y2
END FUNCTION G1F
attributes(device) FUNCTION G2F (Y1,Y2,T) RESULT (G2)
IMPLICIT NONE
REAL :: Y1,Y2,T,G2
G2 = -0.5*Y2-SIN(Y1)+0.9*COS((2.0/3.0)*T)
END FUNCTION G2F
END MODULE KERNEL
PROGRAM PENDULUM
use cudafor
use KERNEL
IMPLICIT NONE
INTEGER, PARAMETER :: N=100000,L=1000,M=1
INTEGER :: I,d,count_max,count_rate
REAL,device :: Y_d(2,N)
REAL, DIMENSION (2,N) :: Y
INTEGER :: count(2)
call mykernel<<<1,2>>>(Y_d,N,L,M)
Y=Y_d
WRITE (6,"(2F16.8)") (Y(1,I),Y(2,I),I=1,N,M)
END PROGRAM PENDULUM
You can see that only two independent threads of execution are possible by doing a data-dependency analysis of your original serial code. It's easiest to think of this as an "outer" and an "inner" part.
The "outer" part is the dependence of Y(1:2,i+1) on Y(1:2,i). At each time step, you need to use the values of Y(1:2,i) to calculate Y(1:2,i+1), so it's not possible to perform the calculations for multiple time steps in parallel, simply because of the serial dependence structure -- you need to know what happens at time i to calculate what happens at time i+1, you need to know what happens at time i+1 to calculate what happens at time i+2, and so on. The best that you can hope to do is to calculate Y(1,i+1) and Y(2,i+1) in parallel, which is exactly what you do.
The "inner" part is based on the dependencies between the intermediate values in the Runge-Kutta scheme, the DK11, DK12, etc. values in your code. When calculating Y(1:2,i+1), each of the DK[n,m] depends on Y(1:2,i) and for m > 1, each of the DK[n,m] depends on both DK[1,m-1] and DK[2,m-1]. If you draw a graph of these dependencies (which my ASCII art skills aren't really good enough for!), you'll see that there are at each step of the calculation only two possible sub-calculations that can be performed in parallel.
The result of all this is that you cannot do better than two parallel threads for this calculation. As one of the commenters above said, you can certainly do much better if you're simulating a particle system or some other mechanical system with multiple independent degrees of freedom, which you can then integrate in parallel.
The point is to guess a random number choosen from an interval of integers and do it within a fixed numbers of attempts.
The main function asks the upper limit of the interval and the number of guesses the user can give. The core function then should return the guessed value so when the number is right the function should terminate immediately.
I put some print statement while debugging and I understood that the y value is not returned to the while statement from the core function.
# -*- coding: utf-8 -*-
def main():
from random import choice
p = input("choose upper limit: ")
t = input("how many attempts: ")
pool = range(p+1)
x = choice(pool)
i = 1
while ((x != y) and (i < t)):
core(x,y)
i += 1
def core(x,y):
y = input("choose a number: ")
if y == x:
print("You gussed the right number!")
return y
elif y > x:
print("The number is lower, try again")
return y
else:
print("The number is higher, try again")
return y
You want to assign the return value of core back to the local y variable, it's not passed by reference:
y = core(x)
You'll also need to set y before you go into the loop. Local variables in functions are not available in other functions.
As a result, you don't need to pass y to core(x) at all:
def core(x):
y = input("choose a number: ")
if y == x:
print("You gussed the right number!")
return y
elif y > x:
print("The number is lower, try again")
return y
else:
print("The number is higher, try again")
return y
and the loop becomes:
y = None
while (x != y) and (i < t):
y = core(x)
i += 1
It doesn't much matter what you set y to in the main() function to start with, as long as it'll never be equal to x before the user has made a guess.
y = -1
while ((x != y) and (i < t)):
y = core(x,y)
i += 1
You "initialize" y before the loop. Inside the loop you set y equal to the result of core() function.
In GNU Octave, would like to calculate an n-day exponential moving average of a vector without using a for-loop.
I am able to do this with a for loop but it is inefficient. I would like to use the filter function, however I am unsure how to get this to work correctly.
After piecing together the bits from this thread
http://octave.1599824.n4.nabble.com/vectorized-moving-average-td2132090.html
I built this function using Octave's filter function.
function meanV = movingEMean(V, window)
simpleAvg = mean(V(1:window));
alpha = 1/window;
X = V(window:end);
X(1) = simpleAvg;
meanV = filter(alpha, [1 alpha-1], X, simpleAvg*(1-alpha));
end
It starts with the simple moving average as the basis. V is the column vector of numbers to calculate the exponential moving average. window is an integer as a number of days. I used 12.
Here is a mathematical explanation of this function.
http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
Note that the page uses 2/(n+1) (where n is window or the number of days) as alpha, but I use 1/n because that value of alpha fits my needs. Adjust alpha as needed.
Alternatively, I sometimes need my input and output vector's dimensions to match. I fill invalid values with NaN by adding meanV = [NaN(window-1,1); meanV]; as the last line in the movingEMean function. You could also fill it with simpleAvg if you want a rough estimate.
Reinventing the wheel on octave exponential moving average for a vector is silly. Just copy and paste movavg.m function defined in the octave financial package here: https://octave.sourceforge.io/financial:
function [varargout] = movavg(asset, lead, lag, alpha = 0)
if nargin < 3 || nargin > 4
print_usage ();
endif
if lead > lag
error ("lead must be <= lag")
elseif ischar (alpha)
if ! strcmpi (alpha, "e")
error ("alpha must be 'e' if it is a char");
endif
elseif ! isnumeric (alpha)
error ("alpha must be numeric or 'e'")
endif
## Compute the weights
if ischar (alpha)
lead = exp(1:lead);
lag = exp(1:lag);
else
lead = (1:lead).^alpha;
lag = (1:lag).^alpha;
endif
## Adjust the weights to equal 1
lead = lead / sum (lead);
lag = lag / sum (lag);
short = asset;
long = asset;
for i = 1:length (asset)
if i < length (lead)
## Compute the run-in period
r = length (lead) - i + 1:length(lead);
short(i) = dot (asset(1:i), lead(r))./sum (lead(r));
else
short(i) = dot (asset(i - length(lead) + 1:i), lead);
endif
if i < length (lag)
r = length (lag) - i + 1:length(lag);
long(i) = dot (asset(1:i), lag(r))./sum (lag(r));
else
long(i) = dot (asset(i - length(lag) + 1:i), lag);
endif
endfor
if nargout > 0
varargout{1} = short;
else
plot((1:length(asset))', [asset(:), long(:), short(:)]);
endif
if nargout > 1
varargout{2} = long;
endif
endfunction
And invoke thustly:
foo = [NaN; 1;4;8;10;-3;3;4;0;0;3;4;5;6;7;8;9];
lead = 7
lag = 7
alpha = 'e'
movavg(foo, lead, lag, 'e')
Which prints:
NaN
NaN
NaN
NaN
NaN
NaN
NaN
3.39851
1.24966
0.45742
2.06175
3.28350
4.37315
5.40325
6.41432
7.42128
8.42441
I am a new user of MATLAB. I want to find the value that makes f(x) = 0, using the Newton-Raphson method. I have tried to write a code, but it seems that it's difficult to implement Newton-Raphson method. This is what I have so far:
function x = newton(x0, tolerance)
tolerance = 1.e-10;
format short e;
Params = load('saved_data.mat');
theta = pi/2;
zeta = cos(theta);
I = eye(Params.n,Params.n);
Q = zeta*I-Params.p*Params.p';
% T is a matrix(5,5)
Mroot = Params.M.^(1/2); %optimization
T = Mroot*Q*Mroot;
% Find the eigenvalues
E = real(eig(T));
% Find the negative eigenvalues
% Find the smallest negative eigenvalue
gamma = min(E);
% Now solve for lambda
M_inv = inv(Params.M); %optimization
zm = Params.zm;
x = x0;
err = (x - xPrev)/x;
while abs(err) > tolerance
xPrev = x;
x = xPrev - f(xPrev)./dfdx(xPrev);
% stop criterion: (f(x) - 0) < tolerance
err = f(x);
end
% stop criterion: change of x < tolerance % err = x - xPrev;
end
The above function is used like so:
% Calculate the functions
Winv = inv(M_inv+x.*Q);
f = #(x)( zm'*M_inv*Winv*M_inv*zm);
dfdx = #(x)(-zm'*M_inv*Winv*Q*M_inv*zm);
x0 = (-1/gamma)/2;
xRoot = newton(x0,1e-10);
The question isn't particularly clear. However, do you need to implement the root finding yourself? If not then just use Matlab's built in function fzero (not based on Newton-Raphson).
If you do need your own implementation of the Newton-Raphson method then I suggest using one of the answers to Newton Raphsons method in Matlab? as your starting point.
Edit: The following isn't answering your question, but is just a note on coding style.
It is useful to split your program up into reusable chunks. In this case your root finding should be separated from your function construction. I recommend writing your Newton-Raphson method in a separate file and call this from the script where you define your function and its derivative. Your source would then look some thing like:
% Define the function (and its derivative) to perform root finding on:
Params = load('saved_data.mat');
theta = pi/2;
zeta = cos(theta);
I = eye(Params.n,Params.n);
Q = zeta*I-Params.p*Params.p';
Mroot = Params.M.^(1/2);
T = Mroot*Q*Mroot; %T is a matrix(5,5)
E = real(eig(T)); % Find the eigen-values
gamma = min(E); % Find the smallest negative eigen value
% Now solve for lambda (what is lambda?)
M_inv = inv(Params.M);
zm = Params.zm;
Winv = inv(M_inv+x.*Q);
f = #(x)( zm'*M_inv*Winv*M_inv*zm);
dfdx = #(x)(-zm'*M_inv*Winv*Q*M_inv*zm);
x0 = (-1./gamma)/2.;
xRoot = newton(f, dfdx, x0, 1e-10);
In newton.m you would have your implementation of the Newton-Raphson method, which takes as arguments the function handles you define (f and dfdx). Using your code given in the question, this would look something like
function root = newton(f, df, x0, tol)
root = x0; % Initial guess for the root
MAXIT = 20; % Maximum number of iterations
for j = 1:MAXIT;
dx = f(root) / df(root);
root = root - dx
% Stop criterion:
if abs(dx) < tolerance
return
end
end
% Raise error if maximum number of iterations reached.
error('newton: maximum number of allowed iterations exceeded.')
end
Notice that I avoided using an infinite loop.