# -----------------------------------------------------------
#  Códigos para a primeira lista de exercícios
#  Processamento Adapatativo de Sinais
#  2019.2
#  COPPE/UFRJ
# -----------------------------------------------------------

import numpy as np
import sympy as sp

from utils.arminha import arma
from utils.eigen import eigenstuff, symbolic_diagonalize
from utils.mse_plot import mse_plt
from utils.newton_method import newton
from utils.steepest_descent import sd
from utils.wiener import wiener_solution


def questao_3():
    # -----------------------------------------------------------
    # Exercício 3
    # -----------------------------------------------------------

    # Letra (a)
    print('\n \n 3 - Letra (a) \n')
    R = (1 / 4) * np.matrix([[4, 3, 2, 1], [3, 4, 3, 2], [2, 3, 4, 3], [1, 2, 3, 4]])
    eigenstuff(R)

    # Letra (b)
    print('\n 3 - Letra (b) \n')
    R = np.matrix([[1, 0.95, 0.9025, 0.857374], [0.95, 1, 0.95, 0.9025], [0.9025, 0.95, 1, 0.95],
                   [0.857375, 0.9025, 0.94, 1]])
    eigenstuff(R)

    # Letra (c)
    print('\n 3 - Letra (c) \n')

    sigma_squared = 1
    R = 50 * sigma_squared * np.matrix([[1, 0.9899, 0.98, 0.970], [0.9899, 1, 0.9899, 0.98],
                                        [0.98, 0.9899, 1, 0.9899], [0.970, 0.98, 0.9899, 1]])
    eigenstuff(R)

    # Letra (d)
    print('\n 3 - Letra (d) \n')
    R = np.matrix([[1, 0.5, 0.25, 0.125], [0.5, 1, 0.5, 0.25], [0.25, 0.5, 1, 0.5],
                   [0.125, 0.25, 0.5, 1]])
    eigenstuff(R)


def questao_4():
    # -----------------------------------------------------------
    # Exercício 4
    # -----------------------------------------------------------

    print('\n Exercício 4')

    a_1 = sp.symbols('a_1')
    a_2 = sp.symbols('a_2')

    R = (1 / 4) * sp.Matrix([[a_1, a_2], [a_2, a_1]])
    symbolic_diagonalize(R)


def questao_9():
    # -----------------------------------------------------------
    # Exercício 9
    # -----------------------------------------------------------
    x, _, R = arma(num_pts=1000000, mean=0, sigma=0.1)
    print(np.mean(x), np.var(x))
    print(R)


def questao_15(R, p):
    # -----------------------------------------------------------
    # Exercício 15
    # -----------------------------------------------------------

    # Letra (a)

    print('\n \n  15 - Letra (a) \n')

    w_0 = wiener_solution(R, p)
    print(f'The Wiener solution:')
    print(f'{w_0}')
    return w_0


def questao_16(R, p, num_iteracoes):
    # -----------------------------------------------------------
    # Exercício 16
    # -----------------------------------------------------------
    w_list = sd(R=R, p=p, num_iteracoes=num_iteracoes)
    # for n, w in enumerate(w_list):
    #     print('\n')
    #     print(n, w)

    # print(f'último w do sd: {w_list[-1]}')
    mse_plt(np.array(wiener_solution(R, p)), w_list)


def questao_17(R, p, num_iteracoes):
    # -----------------------------------------------------------
    # Exercício 17
    # -----------------------------------------------------------
    w_list = newton(R=R, p=p, num_iteracoes=num_iteracoes)
    # for n, w in enumerate(w_list):
    #     print('\n')
    #     print(n, w)

    # print(f'último w do newton: {w_list[-1]}')
    mse_plt(np.array(wiener_solution(R, p)), w_list)


if __name__ == "__main__":

    # questao_3()
    # questao_4()

    # questao_9()

    # ----- Para a questão 15, 16 e 17)
    R = (1 / 4) * np.matrix([[4, 3, 2, 1], [3, 4, 3, 2], [2, 3, 4, 3], [1, 2, 3, 4]])
    p = np.matrix([[1 / 2], [3 / 8], [2 / 8], [1 / 8]])
    # questao_15(R, p)
    questao_16(R, p, num_iteracoes=1000)
    #questao_17(R, p, num_iteracoes=1000)
