Last active
March 4, 2019 20:29
-
-
Save estebanz01/85e4a5f2548921d2de342a1daf51dc0c to your computer and use it in GitHub Desktop.
Ruby snippet that tries to compute and find the root for a function using the Newton-Raphson method.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/env ruby | |
def derivative_of(f:, x:) | |
h = 1e-14 # 1 * 10^-14 this is the smallest number ruby can handle in calculations before defaulting result to zero. | |
(f.call(x + h) - f.call(x)) / h # This is a naive approach to calculate limit of f(x) in x. | |
end | |
# Newton's Method, where we calculate f(x), f'(x) and calculate error. | |
def find_root(f:, seed:, iterations: nil, error_level: nil) | |
if iterations.nil? && error_level.nil? | |
throw 'Iterations and error level not defined. Please specify at least one' | |
end | |
x = nil # Root | |
x0 = seed # Initial value | |
i = 0 # Number of iterations made | |
loop do | |
break if !iterations.nil? && i >= iterations # Leave if we have reached the number of iterations. | |
x = x0 - (f.call(x0) / derivative_of(f: f, x: x0)) | |
if x.nan? | |
x = nil | |
break | |
end | |
break if x == 0 || (x - x0).abs <= error_level | |
i = i+1 # Iteration finished | |
x0 = x # Swap the x0 value | |
end | |
x # Result | |
rescue Math::DomainError | |
x = nil | |
end | |
# Example # 1 | |
# F(x) = (e ^ x) * ln(x) | |
# Exact root is defined at 1 | |
f = lambda { |x| Math.exp(x) * Math.log(x) } # f(x) = (e^x) * ln(x) defined in R | |
root = find_root(f: f, seed: 2, error_level: 0.00000001) | |
if root.nil? | |
puts 'Computed root of F(x) cannot be found or do not exist.' | |
else | |
puts "Computed root of F(x) = (e^x)ln(x) is #{root}. Exact root is 1.0." | |
end | |
# Example # 2 | |
# F(x) = (x ^ 5) * tanh(x^3) | |
# Exact root is defined at 0 | |
f = lambda { |x| (x ** 5) * Math.tanh(x ** 3) } # f(x) = (x^5) * tanh(x^3) defined in R | |
root = find_root(f: f, seed: 2, error_level: 0.00000001) | |
if root.nil? | |
puts 'Computed root of F(x) cannot be found or do not exist.' | |
else | |
puts "Computed root of F(x) = (x^5)tanh(x^3) is #{root}. Exact root is 0.0." | |
end | |
# Example # 3 | |
# F(x) = (x ^ 2) + 2 | |
# Exact root is not defined | |
f = lambda { |x| (x ** 2) + 2 } # f(x) = x^2 + 2 defined in R | |
root = find_root(f: f, seed: 2, error_level: 0.00000001) | |
if root.nil? | |
puts 'Computed root of F(x) = x^2 + 2 cannot be found or do not exist.' | |
else | |
puts "Root of F(x) is #{root}." | |
end | |
# Example # 4 | |
# F(x) = ln^x(x) + 1 | |
# Exact root is not defined | |
f = lambda { |x| (Math.log(x) ** x) + 1 } # f(x) = ln^x(x) + 1 defined in R | |
root = find_root(f: f, seed: 2, error_level: 0.00000001) | |
if root.nil? | |
puts 'Computed root of F(x) = ln^x(x) + 1 cannot be found or do not exist.' | |
else | |
puts "Computed root of F(x) is #{root}." | |
end | |
# Example # 5 | |
# F(x) = (x - 1) / (x + 1) | |
# Exact root is defined at 1 | |
f = lambda { |x| (x - 1) * (x + 1) } # f(x) = (x - 1) * (x + 1) defined in R | |
root = find_root(f: f, seed: 2, error_level: 0.00000001) | |
if root.nil? | |
puts 'Computed root of F(x) cannot be found or do not exist.' | |
else | |
puts "Computed root of F(x) = (x - 1)(x + 1) is #{root}. Exact root is 1.0" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment