So I have the following function, which finds the root of a function using Newton-raphson method. I think my issue is relatively simple: I want the function to find the square root of a given positive number, using the newton raphson medthod. Help?
# FUNCTION:
newton <- function(f, delta = 0.0000001, x_0 = 2, n=1000){
h = 0.0000001
i = 1; x1 = x_0
p = numeric(n)
while (i <= n) { #while i is less than or equal to n(1000), continue iterations
df.dx = (f(x_0 + h) - f(x_0)) / h #
x1 = (x_0 - (f(x_0) / df.dx)) # output of original guess minus (f(x)/f´(x)) (formula for root finding)
p[i] = x1 # counts iteration so we don't exceed 1000
i = i+1 # same as ^
if (abs(x1 - x_0) < delta) break # if output is less than delta: end iteration. Otherwise continue. (x1-x_0=if new value is below our threshold, stop)
x_0 = x1
}
return(p[1: (i-1)]) #
}
############## TEST ###############
func1 <- function(x){
x^5 - 7
}
newton(func1)
#VARIABLES are
#f = the function we input
#delta = the accuracy threashold we are willing to accept
#x_0 = our initial guess
#n = the number of iterations
#h = the distance from X1 to X0,this value much little ,the root much #closed.
#abs is a sys
A possible solution :
newton <- function(f, delta = 0.0000001, x_0 = 2, n=1000){
h = 0.0000001
i = 1; x1 = x_0
p = numeric(n)
while (i <= n) { #while i is less than or equal to n(1000), continue iterations
df.dx = (f(x_0 + h) - f(x_0)) / h #
x1 = (x_0 - (f(x_0) / df.dx)) # output of original guess minus (f(x)/f´(x)) (formula for root finding)
p[i] = x1 # counts iteration so we don't exceed 1000
i = i+1 # same as ^
if (abs(x1 - x_0) < delta) break # if output is less than delta: end iteration. Otherwise continue. (x1-x_0=if new value is below our threshold, stop)
x_0 = x1
}
return(list(result = x1, iterations = p[1:i-1]))
}
nthrootsub <- function(input, nth, x){ x^nth - input}
nthroot <- function(input, nth) {newton(function(x) nthrootsub(input, nth, x))}
############## TEST ###############
10^(1/5)
#[1] 1.584893
nthroot(10,5)
#$result
#[1] 1.584893
#$iterations
#[1] 1.725000 1.605878 1.585435 1.584894 1.584893 1.584893
Related
I've tried to find roots of nonlinear equation by using a Newton-Raphson method.
The problem I stuck in is that I don't get the right first derivative of following equation:
y is the target variable for my prediction, X is a matrix of the predictor variables, Theta is a smoothing parameter.
I need to get the arg min of Q.
For that I want to use this approach of Newton-Raphson:
newton.raphson <- function(f, a, b, tol = 1e-5, n = 1000) {
require(numDeriv) # Package for computing f'(x)
x0 <- a # Set start value to supplied lower bound
k <- n # Initialize for iteration results
# Check the upper and lower bounds to see if approximations result in 0
fa <- f(a)
if (fa == 0.0) {
return(a)
}
fb <- f(b)
if (fb == 0.0) {
return(b)
}
for (i in 1:n) {
dx <- genD(func = f, x = x0)$D[1] # First-order derivative f'(x0)
x1 <- x0 - (f(x0) / dx) # Calculate next value x1
k[i] <- x1 # Store x1
if (abs(x1 - x0) < tol) {
root.approx <- tail(k, n=1)
res <- list('root approximation' = root.approx, 'iterations' = k)
return(res)
}
# If Newton-Raphson has not yet reached convergence set x1 as x0 and continue
x0 <- x1
}
print('Too many iterations in method')
Thanks in advance for your help!
I am reading Section 4.2 in Simulation (2006, 4ed., Elsevier) by Sheldon M. Ross, which introducing generating a Poisson random variable by the inverse transform method.
Denote pi =P(X=xi)=e^{-λ} λ^i/i!, i=0,1,... and F(i)=P(X<=i)=Σ_{k=0}^i pi to be the PDF and CDF for Poisson, respectively, which can be computed via dpois(x,lambda) and ppois(x,lambda) in R.
There are two inverse transform algorithms for Poisson: the regular version and the improved one.
The steps for the regular version are as follows:
Simulate an observation U from U(0,1).
Set i=0 and F=F(0)=p0=e^{-λ}.
If U<F, select X=i and terminate.
If U >= F, obtain i=i+1, F=F+pi and return to the previous step.
I write and test the above steps as follows:
### write the regular R code
pois_inv_trans_regular = function(n, lambda){
X = rep(0, n) # generate n samples
for(m in 1:n){
U = runif(1)
i = 0; F = exp(-lambda) # initialize
while(U >= F){
i = i+1; F = F + dpois(i,lambda) # F=F+pi
}
X[m] = i
}
X
}
### test the code (for small λ, e.g. λ=3)
set.seed(0); X = pois_inv_trans_regular(n=10000,lambda=3); c(mean(X),var(X))
# [1] 3.005000 3.044079
Note that the mean and variance for Poisson(λ) are both λ, so the writing and testing for the regular code are making sense!
Next I tried the improved one, which is designed for large λ and described according to the book as follows:
The regular algorithm will need to make 1+λ searches, i.e. O(λ) computing complexity, which is fine when λ is small, while it can be greatly improved upon when λ is large.
Indeed, since a Poisson random variable with mean λ is most likely to take on one of the two integral values closest to λ , a more efficient algorithm would first check one of these values, rather than starting at 0 and working upward. For instance, let I=Int(λ) and recursively determine F(I).
Now generate a Poisson random variable X with mean λ by generating a random number U, noting whether or not X <= I by seeing whether or not U <= F(I). Then search downward starting from I in the case where X <= I and upward starting from I+1 otherwise.
It is said that the improved algorithm only need 1+0.798√λ searches, i.e., having O(√λ) complexity.
I tried to wirte the R code for the improved one as follows:
### write the improved R code
pois_inv_trans_improved = function(n, lambda){
X = rep(0, n) # generate n samples
p = function(x) {dpois(x,lambda)} # PDF: p(x) = P(X=x) = λ^x exp(-λ)/x!
F = function(x) {ppois(x,lambda)} # CDF: F(x) = P(X ≤ x)
I = floor(lambda) # I=Int(λ)
F1 = F(I); F2 = F(I+1) # two close values
for(k in 1:n){
U = runif(1)
i = I
if ( F1 < U & U <= F2 ) {
i = I+1
}
while (U <= F1){ # search downward
i = i-1; F1 = F1 - p(i)
}
while (U > F2){ # search upward
i = i+1; F2 = F2 + p(i)
}
X[k] = i
}
X
}
### test the code (for large λ, e.g. λ=100)
set.seed(0); X = pois_inv_trans_improved(n=10000,lambda=100); c(mean(X),var(X))
# [1] 100.99900000 0.02180118
From the simulation results [1] 100.99900000 0.02180118 for c(mean(X),var(X)), which shows nonsense for the variance part. What should I remedy this issue?
The main problem was that F1 and F2 were modified within the loop and not reset, so eventually a very wide range of U's are considered to be in the middle.
The second problem was on the search downward the p(i) used should be the original i, because F(x) = P(X <= x). Without this, the code hangs for low U.
The easiest fix for this is to start i = I + 1. Then "in the middle" if statement isn't needed.
pois_inv_trans_improved = function(n, lambda){
X = rep(0, n) # generate n samples
p = function(x) {dpois(x,lambda)} # PDF: p(x) = P(X=x) = λ^x exp(-λ)/x!
`F` = function(x) {ppois(x,lambda)} # CDF: F(x) = P(X ≤ x)
I = floor(lambda) # I=Int(λ)
F1 = F(I); F2 = F(I+1) # two close values
for(k in 1:n){
U = runif(1)
i = I + 1
# if ( F1 < U & U <= F2 ) {
# i = I + 1
# }
F1tmp = F1
while (U <= F1tmp){ # search downward
i = i-1; F1tmp = F1tmp - p(i);
}
F2tmp = F2
while (U > F2tmp){ # search upward
i = i+1; F2tmp = F2tmp + p(i)
}
X[k] = i
}
X
}
This gives:
[1] 100.0056 102.2380
I'm trying to write a loop in R that should do the following:
Calculate the square root of a given positive number using Newtons method. My idea is something like this:
delta <- 0.0000001
x <- input_value
#DO:
x.new = 0.5*(x + mu/x)
x = x.new
#UNTIL:
abs(xˆ2 - mu) < delta
It's meant as a quick way to find the root(s) of a given number.
Does anyone has any ideas as to how to make a loop that does this in R?
This is how I ended up solving my issue:
# PROGRAM
find_roots <- function(f, a, b, delta = 0.00005, n = 1000) {
require(numDeriv) # Package for calculating f'(x)
x_0 <- a # Set start value to supplied lower bound
k <- n # Initialize for iteration results
for (i in 1:n) {
dx <- genD(func = f, x = x_0)$D[1] # First-order derivative f'(x0)
x_1 <- x_0 - (f(x_0) / dx) # Calculate next value x_1
k[i] <- x_1 # Store x_1
# Once the difference between x0 and x1 becomes sufficiently small, output the results.
if (abs(x_1 - x_0) < delta) {
root.approx <- tail(k, n=1)
res <- list('root approximation' = root.approx, 'iterations' = k)
return(res)
}
# If Newton-Raphson has not yet reached convergence set x1 as x0 and continue
x_0 <- x_1
}
print('Too many iterations in method')
}
#Example of it working:
func1 <- function(x) {
x^2 + 3*x + 1
}
# Check out the magic
newton.raphson(func1, 2,3)
There is a function like:
y = (e^x - 2)^n
The x is an unknown, for n = 2,3,4,...,8
Now I want to use NR method to find the root of this function(initial x is 0).
I know how to write an NR method if the n is a fixed value, here's my origin NR code:
NR <- function(f, x0, tol = 1e-5, ite = 1000){
require(numDeriv) #call the package for computing dx
k <- ite
for (i in 1:ite){
#calculate dx
dx <- genD(func = f, x = x0)$D[1]
#get the x1
x1 <- x0 - (f(x0) / dx)
k[i] <- x1
if(abs(x1 - x0) < tol){
root <- x1
re <- list('root approximation' = root, 'iteration' = length(k))
return(re)
}
x0 <- x1
}
print('Outside the upper iteration')
}
Now I rewrite my function:
f <- function(x, n){
(exp(x) - 2) ^ n
}
If I want to output every root for different n, I think I should add another loop before the loop "for (i in 1:ite)"
So I rewrite my NR function code:
NR <- function(f, x0, tol = 1e-5, ite = 1000){
require(numDeriv) #call the package for computing dx
k <- ite
for(n in 2:8){
for (i in 1:ite){
#calculate dx
dx <- genD(func = f, x = x0)$D[1]
#get the x1
x1 <- x0 - (f(x0, n) / dx)
k[i] <- x1
if(abs(x1 - x0) < tol){
root <- x1
re <- list('root approximation' = root, 'iteration' = length(k))
return(re)
}
x0 <- x1
}
print('Outside the upper iteration')
}
}
But when I run NR(f,0), R showed me the error is :
Error in func(x, ...) : argument "n" is missing, with no default
How can I figure this out?
Thank you for your help!
I hope you find my answer helpful:
If you try ?genD you will read this:
Usage
genD(func, x, method="Richardson",
method.args=list(), ...)
## Default S3 method: genD(func, x, method="Richardson",
method.args=list(), ...) Arguments
func a function for which the first (vector) argument is used as a
parameter vector. x The parameter vector first argument to func.
And in the bottom of the R Documentation this example:
Examples
func <- function(x){c(x[1], x[1], x[2]^2)}
z <- genD(func, c(2,2,5))
Therefore, the issue with your code is that you need to use a vector as an argument for f:
f <- function(c){ (exp(c[1]) - 2) ^ c[2] }
NR <- function(f, x0, tol = 1e-5, ite = 1000){ require(numDeriv)
#call the package for computing dx k <- ite for(n in 2:8){
for (i in 1:ite){
#calculate dx
dx <- genD(func = f, x = c(x0,n))$D[1]
#get the x1
x1 <- x0 - (f(c(x0,n)) / dx)
k[i] <- x1
if(abs(x1 - x0) < tol){
root <- x1
re <- list('root approximation' = root, 'iteration' = length(k))
return(re)
}
x0 <- x1
}
print('Outside the upper iteration') } }
NR(f,0)
If I run that my output is:
$`root approximation` [1] 0.6931375
$iteration [1] 15
Best!
Alright, so I'm working on a small R program in order to do approximation using Halley's method. Basically I need to be able to approximate to 9 decimal places the value of 59^(1/7) using Halley's method.
What I have for the first order recurrence relation of Halley's method is this:
Xn+1 = Xn - [ f(Xn) / ( f'(Xn) - (f(Xn)f''(Xn)/2f'(Xn)) ) ]
So far this is the code I have.
halleysMethodApprox = function(ftnH, x0, m0, k0, tol = 1e-8, max.iter=2) {
x <- x0
m <- m0
k <- k0
fx <- ftnH(x, m, k)
iter <- 0
b <- fx[1]/(fx[2] - (fx[1]*fx[3])/(2*fx[2]) )
while( (abs(fx[1] - x) > tol) && (iter < max.iter) ) {
# calculate X(n+1)
b <- ( fx[1]/(fx[2] - ( (fx[1]*fx[3])/(2*fx[2]) ) ))
x <- x - b
fx <- ftnH(x, m-1, 0)
iter <- iter + 1
cat("At iteration", iter, "value of x is: ", x, "\n")
}
if( abs(x) > tol ) {
cat("Algorithm failed to converge\n")
return(NULL)
} else {
cat("Algorithm converged\n")
return(x)
}
}
and this function for generating a vector containing the function of x, and its derivatives.
ftnH = function (x, m, k) {
fx <- x^m - k
dfx <- (m*x^(m-1))
ddfx <- ((m-1)*m)*x^(m-2)
return (c(fx, dfx, ddfx))
}
print(halleysMethodApprox(ftnH, 59, (1/7), 0))
I'm not quite sure how I am supposed to numerically approximate 59^(1/7) using the above definition for Halley's method.
If you want to calculate x=59^(1/7), your function for using Halley's method is f(x) = x^7-59 = 0. And there were a few typos and minor errors in your code. Here's a corrected version:
halleysMethodApprox = function(ftnH, x0, m0, k0, tol = 1e-8, max.iter=100) {
# x0: starting estimate, eqn: x = k0^(1/m0)
x <- x0
m <- m0
k <- k0
fx <- ftnH(x0, m0, k0)
iter <- 0
b <- fx[1]/(fx[2] - (fx[1]*fx[3])/(2*fx[2]) )
while( (abs(fx[1]) > tol) && (iter < max.iter) ) {
# calculate X(n+1)
b <- ( fx[1]/(fx[2] - ( (fx[1]*fx[3])/(2*fx[2]) ) ))
x <- x - b
fx <- ftnH(x, m0, k0)
iter <- iter + 1
cat("At iteration", iter, "value of x is: ", x, "\n")
}
if(abs(fx[1]) > tol) {
cat("Algorithm failed to converge\n")
return(NULL)
} else {
cat("Algorithm converged\n")
return(x)
}
}
ftnH = function (x, m, k) {
fx <- x^m - k
dfx <- (m*x^(m-1))
ddfx <- ((m-1)*m)*x^(m-2)
return (c(fx, dfx, ddfx))
}
halleysMethodApprox(ftnH, 1, 7, 59)
# At iteration 1 value of x is: 1.320442
# At iteration 2 value of x is: 1.655396
# At iteration 3 value of x is: 1.78716
# At iteration 4 value of x is: 1.790519
# At iteration 5 value of x is: 1.790519
# Algorithm converged
# [1] 1.790519