% Name: Audrey Le
% Course: EE8993-01
% Assignment: #2
% Purpose: the purpose of this assignment is to classify 2-dimensional 
% data using principle component analysis
%

% load in the two training sets
%
load set1.data;
load set2.data;

% calculate the means of the training sets
%
u1 = mean(set1);
u2 = mean(set2);

% data points to be classified
%
a = [-1, -1];
b = [0, 0];
c = [0.5, 0.5];
d = [0.5, -0.5];

% find the Euclidean distance between a, b, c, d and u1, u2
%
eu_a_to_u1 = dist(u1, a');
eu_a_to_u2 = dist(u1, a');

eu_b_to_u1 = dist(u1, b');
eu_b_to_u2 = dist(u2, b');

eu_c_to_u1 = dist(u1, c');
eu_c_to_u2 = dist(u2, c');

eu_d_to_u1 = dist(u1, d');
eu_d_to_u2 = dist(u2, d');

% determine to what training set do the data points belong
%
fprintf ('\nclassify data using original space:\n');

if (eu_a_to_u1 < eu_a_to_u2) 
   fprintf ('a[%.2f, %.2f] belongs to set1\n', a(1,1), a(1,2));
else
   fprintf ('a[%.2f, %.2f] belongs to set2\n', a(1,1), a(1,2));
end;

if (eu_b_to_u1 < eu_b_to_u2) 
   fprintf ('b[%.2f, %.2f] belongs to set1\n', b(1,1), b(1,2));
else
   fprintf ('b[%.2f, %.2f] belongs to set2\n', b(1,1), b(1,2));
end;

if (eu_c_to_u1 < eu_c_to_u2) 
   fprintf ('c[%.2f, %.2f] belongs to set1\n', c(1,1), c(1,2));
else
   fprintf ('c[%.2f, %.2f] belongs to set2\n', c(1,1), c(1,2));
end;

if (eu_d_to_u1 < eu_d_to_u2) 
   fprintf ('d[%.2f, %.2f] belongs to set1\n', d(1,1), d(1,2));
else
   fprintf ('d[%.2f, %.2f] belongs to set2\n', d(1,1), d(1,2));
end;

% find the eigen values and eigen vectors from the covariance matrices
% of the training sets
%
cov1 = cov(set1);
cov2 = cov(set2);

[evector1, evalues1] = eig(cov1);
[evector2, evalues2] = eig(cov2);
lambda1 = inv(sqrtm(evalues1));
lambda2 = inv(sqrtm(evalues2));

% calculate the transformation matrices
%
t1 = lambda1 * evector1';
t2 = lambda2 * evector2';

% compute the new set1 and set2 using the transformation matrices
%
t1_set1 = t1 * set1';
t2_set2 = t2 * set2';

% calculate the new means
%
t1_u1 = mean(t1_set1');
t2_u2 = mean(t2_set2');

% transform the data points and recompute the distance 
%
t1_a = t1 * a';
t2_a = t2 * a';
t1_b = t1 * b';
t2_b = t2 * b';
t1_c = t1 * c';
t2_c = t2 * c';
t1_d = t1 * d';
t2_d = t2 * d';

t1_a_to_u1 = dist(t1_u1, t1_a);
t2_a_to_u2 = dist(t2_u2, t2_a);
t1_b_to_u1 = dist(t1_u1, t1_b);
t2_b_to_u2 = dist(t2_u2, t2_b);
t1_c_to_u1 = dist(t1_u1, t1_c);
t2_c_to_u2 = dist(t2_u2, t2_c);
t1_d_to_u1 = dist(t1_u1, t1_d);
t2_d_to_u2 = dist(t2_u2, t2_d);

% reclassify the data points in transformed space using minimum distance
%
fprintf ('\nclassify data using transformed space:\n');

if (t1_a_to_u1 < t2_a_to_u2) 
   fprintf ('a[%.2f, %.2f] to x1\n', a(1,1), a(1,2));
else
   fprintf ('a[%.2f, %.2f] to x2\n', a(1,1), a(1,2));
end;

if (t1_b_to_u1 < t2_b_to_u2) 
   fprintf ('b[%.2f, %.2f] belongs to x1\n', b(1,1), b(1,2));
else
   fprintf ('b[%.2f, %.2f] belongs to x2\n', b(1,1), b(1,2));
end;

if (t1_c_to_u1 <  t2_c_to_u2) 
   fprintf ('c[%.2f, %.2f] belongs to x1\n', c(1,1), c(1,2));
else
   fprintf ('c[%.2f, %.2f] belongs to x2\n', c(1,1), c(1,2));
end;

if (t1_d_to_u1 <  t2_d_to_u2) 
   fprintf ('d[%.2f, %.2f] belongs to x1\n', d(1,1), d(1,2));
else
   fprintf ('d[%.2f, %.2f] belongs to x2\n', d(1,1), d(1,2));
end;

% find the covariance matrices of the tranformed training sets
%
t1_cov1 = cov(t1_set1');
t2_cov2 = cov(t2_set2');

% shift the training sets to the origin and find the transformed sets
%
[x1_size, y1_size] = size(set1);
[x2_size, y2_size] = size(set2);

for i = 1:x1_size
   shifted_set1(i,:) = set1(i,:) - u1;
end;

for i = 1:x2_size
   shifted_set2(i,:) = set2(i,:) - u2;
end;

t1_shifted_set1 = t1 * shifted_set1';
t2_shifted_set2 = t2 * shifted_set2';

t1_set1t = t1_set1';
t2_set2t = t2_set2';
t1_shifted_set1t = t1_shifted_set1';
t2_shifted_set2t = t2_shifted_set2';

% find the decision region
%
index = 1;
for i = -5:0.1:5,
   for j = -5:0.1:5,
      d1 = dist(u1, [i, j]');
      d2 = dist(u2, [i, j]');
      if (d1 >= d2-0.1) 
         if (d1 <= d2+0.1)
	    decision_pts(index, 1) = i;
	    decision_pts(index, 2) = j;
	    index = index + 1;
	 end;
      end;
   end;
end;

index = 1;
for i = -5:0.1:5,
   for j = -5:0.1:5,
      d1 = dist(t1_u1, t1*[i, j]');
      d2 = dist(t2_u2, t2*[i, j]');
      if (d1 >= d2-0.1) 
         if (d1 <= d2+0.1)
	    t_decision_pts(index, 1) = i;
	    t_decision_pts(index, 2) = j;
	    index = index + 1;
	 end;
      end;
   end;
end;

% plot the data sets
%
figure;
hold;
grid on;
title('Data Sets and Data Points in Original Space');
plot (set1(:,1), set1(:,2), 'ko');
plot (set2(:,1), set2(:,2), 'k+'); 
plot (a(:,1), a(:,2), 'k*'); 
plot (b(:,1), b(:,2), 'k*'); 
plot (c(:,1), c(:,2), 'k*'); 
plot (d(:,1), d(:,2), 'k*'); 

% plot transformed data sets and data points
%
figure;
hold;
grid on;
title('Data Sets and Test Points in Transformed Space');
plot (t1_set1t(:,1), t1_set1t(:,2), 'ko');
plot (t1_a(1,1), t1_a(2,1), 'k*'); 
plot (t1_b(1,1), t1_b(2,1), 'k*'); 
plot (t1_c(1,1), t1_c(2,1), 'k*'); 
plot (t1_d(1,1), t1_d(2,1), 'k*'); 

plot (t2_set2t(:,1), t2_set2t(:,2), 'k+');
plot (t2_a(1,1), t2_a(2,1), 'kd'); 
plot (t2_b(1,1), t2_b(2,1), 'kd'); 
plot (t2_c(1,1), t2_c(2,1), 'kd'); 
plot (t2_d(1,1), t2_d(2,1), 'kd'); 

% plot the shifted and transformed data sets
%
figure;
hold;
grid on;
title('Shifted Data Set 1 in Transformed Space 1');
plot (t1_shifted_set1t(:,1), t1_shifted_set1t(:,2), 'ko');

figure;
hold;
grid on;
title('Shifted Training Data Set 2 in Transformed Space 2');
plot (t2_shifted_set2t(:,1), t2_shifted_set2t(:,2), 'k+'); 

% plot original data sets and decision regions
figure;
hold;
grid on;
title('Data Sets and Decision Regions in Original Space');
plot (set1(:,1), set1(:,2), 'ko');
plot (set2(:,1), set2(:,2), 'k+'); 
plot (decision_pts(:,1), decision_pts(:,2)); 
plot (a(:,1), a(:,2), 'k*'); 
plot (b(:,1), b(:,2), 'k*'); 
plot (c(:,1), c(:,2), 'k*'); 
plot (d(:,1), d(:,2), 'k*'); 

figure;
hold;
grid on;
title('Data Sets and Decision Regions in Tranformed Space');
plot (set1(:,1), set1(:,2), 'ko');
plot (set2(:,1), set2(:,2), 'k+'); 
plot (t_decision_pts(:,1), t_decision_pts(:,2)); 
plot (a(:,1), a(:,2), 'k*'); 
plot (b(:,1), b(:,2), 'k*'); 
plot (c(:,1), c(:,2), 'k*'); 
plot (d(:,1), d(:,2), 'k*'); 

