%% Exercise 1
%% Part a
clear all; clc; close all;
input = [0 0.5 1 1.5 2 2.5 3 3.5];
target_output = [2.5 1.5 1.5 1 1 0.5 -0.5 -2]';
Fi=[ones(1,length(input)); input];
Weight_matrix = eye(8);
Weight_matrix=Weight_matrix/8;
Wml1=inv(Fi*Weight_matrix*Fi')*(Fi*Weight_matrix*target_output);

prediction1 = Wml1'*Fi;

% Weighted Squared Error
weighted_square_error1=0;
for m=1:length(input)
    weighted_square_error1 = weighted_square_error1 + ((target_output(m)-prediction1(m))^2)/8;
end
weighted_square_error1=weighted_square_error1/2;
fprintf('\n Weighted Square Error (w=1/8): %.5f \n',weighted_square_error1);
%% Part b
Weight_matrix = 0.1*eye(8);
Weight_matrix(8,8)=0.3;
Wml2=inv(Fi*Weight_matrix*Fi')*(Fi*Weight_matrix*target_output);

prediction2 = Wml2'*Fi;

% Weighted Squared Error
weighted_square_error2=0;
for m=1:length(input)
    weighted_square_error2 = weighted_square_error2 + ((target_output(m)-prediction2(m))^2)/8;
end
weighted_square_error2=weighted_square_error2/2;
fprintf('\n Weighted Square Error (w1-7=0.1 , w8=0.3): %.5f \n',weighted_square_error2);

figure(1)
plot(input, target_output, 'r*',input, prediction1,'k-',input, prediction2,'m-')
legend('Target','Prediction 1', 'Prediction 2')
xlabel('x');
ylabel('y');
grid on
title('Input Vs Output-Predictions')
saveas(gcf,'ex1b.png')

%% Part c
clear all; clc; close all;
input = [0 0.5 1 1.5 2 2.5 3 3.5];
target_output = [2.5 1.5 1.5 1 1 0.5 -0.5 -2]';
F=[input; input.^2; input.^3; input.^4; input.^5; input.^6; input.^7];
Fi1=[ones(1,length(input)); F(1,:)];
Fi2=[ones(1,length(input)); F(1:2,:)];
Fi3=[ones(1,length(input)); F(1:3,:)];
Fi4=[ones(1,length(input)); F(1:4,:)];
Fi5=[ones(1,length(input)); F(1:5,:)];
Fi6=[ones(1,length(input)); F(1:6,:)];
Fi7=[ones(1,length(input)); F(1:7,:)];

Weight_matrix = eye(8)/8;

% For M=1:7 we have to take the over-constrained solution, 
Wml1=inv(Fi1*Weight_matrix*Fi1')*(Fi1*Weight_matrix*target_output);
Wml2=inv(Fi2*Weight_matrix*Fi2')*(Fi2*Weight_matrix*target_output);
Wml3=inv(Fi3*Weight_matrix*Fi3')*(Fi3*Weight_matrix*target_output);
Wml4=inv(Fi4*Weight_matrix*Fi4')*(Fi4*Weight_matrix*target_output);
Wml5=inv(Fi5*Weight_matrix*Fi5')*(Fi5*Weight_matrix*target_output);
Wml6=inv(Fi6*Weight_matrix*Fi6')*(Fi6*Weight_matrix*target_output);
Wml7=inv(Fi7*Weight_matrix*Fi7')*(Fi7*Weight_matrix*target_output);

pred1 = Wml1'*Fi1;
pred2 = Wml2'*Fi2;
pred3 = Wml3'*Fi3;
pred4 = Wml4'*Fi4;
pred5 = Wml5'*Fi5;
pred6 = Wml6'*Fi6;
pred7 = Wml7'*Fi7;

% For visualization purposes
variable=0:0.05:3.5;
Var_table=[ones(1,length(variable)); variable; variable.^2; variable.^3; variable.^4; variable.^5; variable.^6; variable.^7];
prediction1 = Wml1'*Var_table(1:2,:);
prediction2 = Wml2'*Var_table(1:3,:);
prediction3 = Wml3'*Var_table(1:4,:);
prediction5 = Wml5'*Var_table(1:6,:);
prediction7 = Wml7'*Var_table(1:8,:);

% Plot the functions
figure(2)
plot(input, target_output, 'r*');
hold on
grid on
plot(variable, prediction1, 'g-',variable, prediction2,'b-',variable, prediction3,'k-',variable, prediction5,'m-',variable, prediction7,'c-');
legend('Target','Prediction - Polynomial 1', 'Prediction - Polynomial 2', 'Prediction - Polynomial 3', 'Prediction - Polynomial 5', 'Prediction - Polynomial 7');
xlabel('x');
ylabel('y');
axis([0 3.5 -2.5 2.5])
title('Input Vs Output-Predictions')
saveas(gcf,'ex1c.png')

%% Part d
K=length(input);
M=1:1:7;
clear m a;
weight_square_error(1:7)=0;
for a=1:length(M)
    for m=1:K
        string=strcat('pred',num2str(a));
        prediction=eval(string);
        weight_square_error(a)=weight_square_error(a)+((target_output(m)-prediction(m))^2)/8;
    end
    weight_square_error(a)=weight_square_error(a)/2;
end

figure(3)
plot(M, weight_square_error,'mo-');
xlabel('Polynomial order (M)');
ylabel('Weighted Squared Error');
grid on
title('Polynomial Order (M) Vs. Weighted Squared Error')
xlabel('Polynomial order (M)');
ylabel('Weighted Squared Error');
saveas(gcf,'ex1d.png')

