
% Example where the Rosenbrock function is approximated
close all, clear variables
clc

% Definition of the current path folder
FileName = mfilename('fullpath');
[directory,~,~] = fileparts(FileName);
[dirmain,~,~] = fileparts(fileparts(directory));
addpath(genpath(dirmain)) 
setup

% Defintion of the Dimension of Splinter
Sdim = 3;

Case = ['n' 'n' 'y'];

% Auxiliary function for the 1-dimensional case
G = 5;
k = .5;
f0 = .01;
funct_1 = @(x) G*1./(1+exp(-k*G*x)*(G/f0-1));

% 6-hump camelback function for the 2-dimensional case
funct_2 = @(x,y) (4 - 2.1*x.^2 + 1/3.*x.^4).*x.^2 + x.*y + (-4 + 4*y.^2).*y.^2; 

% Auxiliary function for the N-dimensional case
funct_3 = @(x) sum(x,2);

% Definition of the ranges for the parameter
range_1 = [100:50:1000 2.^(10:17)];
range_2 = [10:10:250 270:20:350];
range_N = [4:9];

n_range_1 = numel(range_1);
n_range_2 = numel(range_2);
n_range_N = numel(range_N);

%T Predefinition of the arrays
time_approx_1 = zeros(numel(range_1),1);
time_approx_2 = zeros(numel(range_2),1);
time_approx_N = zeros(numel(range_N),1);
n_var_1       = time_approx_1;
n_var_2       = time_approx_2;
n_var_N       = time_approx_N;

% Preparation of the print text
PrintText = ['-D model - It took %8.2f s to solve the problem with %6.0i elements ' ...
             'and a %1.0i-D Spline. \n'];


for k = 1:max([n_range_1 n_range_2 n_range_N])
    
    if k <= n_range_1 && Case(1) == 'y'
        
        % Definition of the grid for the evaluation of the points
        N_1  = range_1(k);
        xs_1 = linspace(-1,5,N_1)';

        % Definition of a Spline of Dimension Sdim
        zs_1 = funct_1(xs_1);
        time.in.approx_1 = tic;
        a_1              = BSplineBuilder(xs_1, zs_1, Sdim).build();
        time_approx_1(k) = toc(time.in.approx_1);

        % Definition of the number of variables
        n_var_1(k) = N_1;

        % Printing of the results
        fprintf(['1',PrintText],time_approx_1(k),n_var_1(k),Sdim)
    end
    
    if k <= n_range_2 && Case(2) == 'y'
        
        % Definition of the grid for the evaluation of the points
        N_2 = range_2(k);
        x_2 = linspace(-2,2,N_2);
        y_2 = linspace(-1,1,N_2);
        [X_2,Y_2] = meshgrid(x_2,y_2);
        Z_2 = funct_2(X_2,Y_2);

        % Definition of the vectors for BSplinebuilder
        xs_2 = [X_2(:) Y_2(:)];
        zs_2 = Z_2(:);

        % Definition of a Quartic bspline
        time.in.approx_2 = tic;
        a_2              = BSplineBuilder(xs_2, zs_2, Sdim).build();
        time_approx_2(k) = toc(time.in.approx_2);

        % Definition of the number of variables
        n_var_2(k) = N_2^2;

        % Printing of the results
        fprintf(['2',PrintText],time_approx_2(k),n_var_2(k),Sdim)
    end

    if k <= n_range_N && Case(3) == 'y'
        
        % Definition of the grid for the evaluation of the points
        N_N = range_N(k);
        Xn_N = linspace(1,5,N_N)';   
        [X_N{1}, X_N{2}, X_N{3}, X_N{4}, X_N{5}] = ndgrid(Xn_N);   % , X_N{6}, X_N{7}, X_N{8}

        for l = 1:numel(X_N)
            X_N{l} = X_N{l}(:);
        end

        % Definition of the vectors for BSplinebuilder
        xs_N = cell2mat(X_N);
        zs_N = funct_3(xs_N);

        % Definition of a Cubic bspline
        time.in.approx_N = tic;
        a_N              = BSplineBuilder(xs_N, zs_N, min(N_N-1,Sdim)).build();
        time_approx_N(k) = toc(time.in.approx_N);

        % Definition of the number of variables
        n_var_N(k) = numel(zs_N);

        % Printing of the results
        fprintf(['%1.0i',PrintText,'\n'],numel(X_N),time_approx_N(k),n_var_N(k),min(N_N-1,Sdim))
    end
    fprintf('\n')
end