clear all;
close all;
clc;

% initialize Rosenbrock function and his gradient
f     = @(x) (1-x(1)).^2 + 100*(x(2)-x(1).^2).^2;
gradf = @(x) [2*x(1)-2-400*x(1)*(x(2)-x(1).^2); 200*(x(2)-x(1).^2)];
hessf = @(x) [-400*x(2)+1200*x(1).^2+2, -400*x(1);
              -400*x(1), 200];

%set initial values
x0 = [0; 2];
tol = 1e-11;
sigma = 0.1;
beta = 0.5;

%calculate mininium of f via newtonMethod
tic
[x_nm,fx,nit_nm] = newtonMethod(f,gradf,hessf,x0,tol,sigma,beta);
time_n = toc

%calculate mininium of f via quasiNewtonMethod
tic
[x_qnm,fx,nit_qnm] = quasiNewtonMethod(f,gradf,x0,tol,sigma,beta);
time_qn = toc

%calculate mininium of f via gradientMethod
tic
[x_gm,fx,nit_gm] = gradientMethod(f,gradf,x0,sigma,beta,tol);
time_g = toc

nit = [nit_nm, nit_qnm, nit_gm]

%plot rosenbrock function and paths 
figure(1)
sx = linspace(-2,2,256);
sy = linspace(-2,4,256);
[X,Y] = meshgrid(sx,sy);
surf(X,Y,(1-X).^2 + 100*(Y-X.^2).^2-10000)
view(2)
hold on;
shading flat
plot(x_nm(1,:),x_nm(2,:),'*g-');
plot(x_qnm(1,:),x_qnm(2,:),'*r-');
plot(x_gm(1,:),x_gm(2,:),'*m-');
legend('Rosenbrock function','newtonMethod','quasiNewtonMethod','gradientMethod')

%plot error
figure(2)
loglog(1:length(x_nm),sum(abs(x_nm-1)),'g')
hold on;
loglog(1:length(x_qnm),sum(abs(x_qnm-1)),'r')
loglog(1:length(x_gm),sum(abs(x_gm-1)),'m')
legend('newtonMethod','quasiNewtonMethod','gradientMethod')
