import numpy as np 
import pandas as pd 
import sys
np.set_printoptions(threshold=sys.maxsize)

def calculate_loss(x, y, w):
    y_pred = np.sign(np.matmul(x, w))
    zeros = np.zeros(shape = (len(y_pred), 1))
    pred_hadamard_label = np.multiply(-y,y_pred)
    loss = (np.sum(np.maximum(zeros, pred_hadamard_label)))/len(y)
    return loss

def online_perceptron(x_train, y_train, x_val, y_val, n_iters):
    y_train = y_train.reshape(len(y_training),1)
    weight_array = []
    training_loss_array = []
    val_loss_array = []

    w = np.zeros(shape = (x_train.shape[1], 1))

    for i in range(n_iters + 1):
        for x, y in zip(x_train, y_train):
            x = x.reshape(1, x_training.shape[1])
            y = y.reshape(1,1)
            y_pred = np.matmul(x,w)
            # print(y_pred.shape)
            if -(y_pred * y) <= 0:
                w = w + np.matmul(y,x).T
                # print(w)
        training_loss = calculate_loss(x_train, y_train, w)
        training_loss_array.append(training_loss)
        print("Iterations " + str(i)+ " training loss " + str(training_loss))

        val_loss = calculate_loss(x_val, y_val, w)
        val_loss_array.append(val_loss)
        print("Iterations " + str(i)+ " validation loss " + str(val_loss))

        weight_array.append(w)

    return weight_array, training_loss_array, val_loss_array         

x_training = np.load('/nfs/stak/users/lehoang/Downloads/CS534_I2/data/interim/x_training.npy')
y_training = np.load('/nfs/stak/users/lehoang/Downloads/CS534_I2/data/interim/y_training.npy')
x_val = np.load('/nfs/stak/users/lehoang/Downloads/CS534_I2/data/interim/x_val.npy')
y_val = np.load('/nfs/stak/users/lehoang/Downloads/CS534_I2/data/interim/y_val.npy')

n_iters = 15

# w, training_loss, val_loss = online_perceptron(x_training, y_training, x_val, y_val, n_iters)
# x_training = np.load('/nfs/stak/users/lehoang/Downloads/CS534_I2/data/interim/x_training.npy')
x_training[1]

def predict(x, w):
    y = np.sign(np.matmul(x,w))
    return y