Hey @GuyFromBosnia, welcome!
To make it easier for others to help you, it is a good idea to post a reproducible code example that is cleanly formatted (see here for more advice).
I took the liberty of adjusting formatting and making some simplifications, here’s what I arrive at:
using LinearAlgebra
function f(v)
n = length(v)
h = 1 / (n + 1)
y = zeros(n)
y[1] = -2v[1] + v[2] + (1 / 4) * exp(v[1])
y[n] = -2v[n] + v[n-1] + (h^2) * exp(v[n])
for i in 2:n-1
h = 1 / (i + 1)
y[i] = ((v[i+1] - 2v[i] + v[i-1]) / h^2) + exp(v[i])
y[i] *= h^2
end
return y
end
function jacobian_exact(f, x)
n = length(x)
J = zeros(n, n)
for i = 1:n
for j = 1:n
h = 1 / (i + 1)
if i == j
J[i, j] = 2 / h^2 + exp(x[i])
elseif i == j + 1 || i == j - 1
J[i, j] = -1 / h^2
end
end
end
return J
end
function jacobian_approx(f, x, epsilon)
n = length(x)
J = zeros(n, n)
for j in 1:n
ej = zeros(n)
ej[j] = 1
J[:, j] = (f(x + epsilon * ej) - f(x)) / epsilon
end
return J
end
function newton_method(f, x0, epsilon, max_iter, method::Symbol=:exact)
x = copy(x0)
iter = 0
while norm(f(x)) > epsilon && iter < max_iter
if method == :exact
J = jacobian_exact(f, x)
elseif method == :approximate
J = jacobian_approx(f, x, epsilon)
else
error("Invalid method specified. Must be :exact or :approximate.")
end
x -= J \ f(x)
iter += 1
end
return x
end
epsilon = 1e-6
xr = collect(1:4)
jacobian_exact(f, xr)
jacobian_approx(f, xr, epsilon)
x0 = zeros(4)
exact_root_newton = newton_method(f, x0, epsilon, 100, :exact)
approx_root_newton = newton_method(f, x0, epsilon, 100, :approximate)
From what I can tell, the jacobian_approx
function seems to be correct, so I would say there is either an error in jacobian_exact
or in the function f
itself. What is the function you’re trying to implement?
If you’re new to Julia, you may not be aware of it, but there are plenty of packages that will compute exact derivatives for you much more reliably: see the JuliaDiff webpage for a list