%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%          MECA0027 Structural and Multidisciplinary Optimization         %
%                     Unconstrained Optimization                          %
%                    University Of Liège, Belgium                         %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Solve the minimization problem
%
%             min f(x,y)
%
% using the following optimization methods
%
% 1) Steepest descent
% 2) Conjugate gradient (Fletcher and Reeves)
% 3) Basic Newton
% 4) Newton-like
% 5) Quasi-Newton (BFGS)


%% Parameters --------------------------------------------------------------------------
functionID = func;          % = 1 if min f(x,y) = 2*x.^2 + 2*y.^2 + 3*x.*y - 2*x + 10*y - 1;
                            % = 2 if min f(x,y) = 0.4*x.^2 + 0.4*y.^2 + 6*cos((pi/2)*x) + x - 3*cos((pi/2)*y) - y;
xinit   = [A B];            % initial point
MaxIter = itermax;          % Maximum number of iterations
Epsilon = tolerance;        % Tolerance


%% Initialization

disp('Which optimization method do you want to use? Press:')
disp('     1 for Steepest descent method')
disp('     2 for Conjugate gradient method using method of Fletcher and Reeves')
disp('     3 for Basic Newton method')
disp('     4 for Newton-like method')
disp('     5 for Quasi-Newton method - Boyden-Fletcher-Goldfard-Shanno (BFGS)')
prompt = '';
method = input(prompt);

n=2;                        % Dimension of the problem
xinit=reshape(xinit,2,1);   % To be sure that it's a column vector
x=zeros(n,MaxIter);         % Initialization of vector x
x(:,1)=xinit;               % Put xinit in vector x.

%% Methods -----------------------------------------------------------------------------

switch method
    case 1
        disp('You chose the steepest descent method.')
        
        for i=1:MaxIter
            %%%% ---------------------------------------------------------------------------
            %%%% ADD YOUR CODE
            %%%%
        end
        
        x=x(:,1:i); %Remove the zero elements due to the initialization step
        
    case 2
        disp('You chose the conjugate gradient method using method of Fletcher and Reeves.')
        
        for i=1:MaxIter
            %%%% ---------------------------------------------------------------------------
            %%%% ADD YOUR CODE
            %%%%
        end
        
        x=x(:,1:i); %Remove the zero elements due to the initialization step
        
    case 3
        disp('You chose the basic Newton method.')
        
        for i=1:MaxIter
            %%%% ---------------------------------------------------------------------------
            %%%% ADD YOUR CODE
            %%%%
        end
        
        x=x(:,1:i); %Remove the zero elements due to the initialization step
        
    case 4
        disp('You chose the Newton-like method.')
        
        for i=1:MaxIter
            %%%% ---------------------------------------------------------------------------
            %%%% ADD YOUR CODE
            %%%%
        end
        
        x=x(:,1:i); %Remove the zero elements due to the initialization step
        
    case 5
        disp('You chose the Quasi-Newton method - Boyden-Fletcher-Goldfard-Shanno (BFGS).')
        
        for i=1:MaxIter
            %%%% ---------------------------------------------------------------------------
            %%%% ADD YOUR CODE
            %%%%
        end
        
        x=x(:,1:i); %Remove the zero elements due to the initialization step
        
end

%% Plot the function with the optimization path and the results

disp(['The optimal point is: x = ' num2str(x(1,end)) ', y = ' num2str(x(2,end)) '.'])
disp(['The objective function value is: ' num2str(getObjFVal(x(:,end),functionID)) '.'])
plotOptimizationPath(x,functionID)

