# -*- coding: utf-8 -*-
"""HW6_Q1.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1rZxaSXzf_A38opZjtiGZefmBgPYCOGfv
"""

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd

"""Assume that you have 4 samples each with dimension 3, described in the data matrix X,

a. Find the sample mean.

b. Zero-center the samples, and find the eigenvalues and eigenvectors of the data covariance matrix Q.
"""

x = [[3,2,1],[2,4,5],[1,2,3],[0,2,5]]
mean = []
sum = 0
for col in range(len(x[0])):
  for row in range(len(x)):
    sum += x[row][col]
  mean.append(sum / len(x))
  sum = 0
# print(mean)
zero_center_mat = x[:]
# print(zero_center_mat)
for col in range(len(x[0])):
  for row in range(len(x)):
    zero_center_mat[row][col] = x[row][col] - mean[col]

Q = np.cov(np.array(zero_center_mat).T)
e, v = np.linalg.eig(Q)
print(f'the covariance matrix is: \n{Q}\n')
print(f'the eigenvalues is \n{e}\n')
print(f'the eigenvectors are \n{v}\n')

"""c. Find the PCA coefficients corresponding to each of the samples in X."""

zero_center_mat = np.array(zero_center_mat)
eig_value = e[0]
eig_vec = v[0]

coef_mat = zero_center_mat.dot(eig_vec.T)
print(f'the PCA coefficients is: \n{coef_mat}')
# print(zero_center_mat)

"""d. Reconstruct the original samples from the top two principal components, and report the reconstruction error for each of the samples."""

vec_mat = v[0:2]
new_sample_mat = zero_center_mat.dot(vec_mat.T)

dis_zero = []
dis_new_zero = []
temp_dis = 0
temp_new_dis = 0
for row in range(len(zero_center_mat)):
  for col in range(len(zero_center_mat[0])):
    temp_dis += zero_center_mat[row][col] ** 2
  dis_zero.append(temp_dis)
  temp_dis = 0

for row in range(len(new_sample_mat)):
  for col in range(len(new_sample_mat[0])):
    temp_new_dis += new_sample_mat[row][col] ** 2
  dis_new_zero.append(temp_new_dis)
  temp_new_dis = 0

err_per_sample = []
for _ in range(len(dis_zero)):
  err_per_sample.append(np.sqrt(abs(dis_zero[_] - dis_new_zero[_])))
print(f'the error are {err_per_sample}')