#Python3 Steven
#simualtion distrubutions for people's income
#https://en.wikipedia.org/wiki/Gini_coefficient
import numpy as np
import matplotlib.pyplot as plt
from genDistributions import *
from distributions import *
#from plotCommon import scatterSub

def calLineSlopAndBias(startPt,stopPt):
    slop = (stopPt[1]-startPt[1])/(stopPt[0]-startPt[0])
    b = stopPt[1]-slop*stopPt[0]
    return slop,b

def calDistribution(dis):
    dis = np.abs(dis)
    disOrdered = sorted(dis)
    #plot(range(len(dis)), dis)
    cumDis = np.cumsum(disOrdered)

    l = len(cumDis)
    slop,b = calLineSlopAndBias([0,cumDis[0]],[len(cumDis)-1,cumDis[len(cumDis)-1]])
    equalDis = [ slop*i+b for i in range(l)]

    # print('dis=',dis)
    # print('disOrdered=',disOrdered)
    # print('cumDis=',cumDis)
    # print('equalDis=',equalDis)

    gini = (np.sum(equalDis)-np.sum(cumDis))/np.sum(equalDis)
    return dis,disOrdered,cumDis,equalDis,gini

def plotAll(dis,name=''):
    dis,disOrdered,cumDis,equalDis,gini = calDistribution(dis)

    fmt = '{:24} | {:18}'
    print( fmt.format('Distribution:'+name,'Gini coefficient:' + str(round(gini,4))))

    #plotIncomeDistribution(name,dis,disOrdered)
    # plotLorenzCurve(cumDis,equalDis,gini)
    plotWhole(name,dis,disOrdered,cumDis,equalDis,gini)

gSaveBasePath=r'.\images\\'
def plotWhole(name,dis,disOrdered,cumDis,equalDis,gini):
    plt.figure(figsize=(9,4.2))

    ax = plt.subplot(1, 2, 1)
    ax.plot(dis,label='Income ' + name + ' distribution')
    ax.plot(disOrdered,label='Income ordered')
    ax.set_title("Income")
    ax.legend()

    ax = plt.subplot(1, 2, 2)
    z0 = np.zeros(len(cumDis))
    x = range(len(cumDis))
    c1 = tuple(ti/255 for ti in (176,196,214))
    c2 = tuple(ti/255 for ti in (128,179,255))
    ax.fill_between(x,equalDis,cumDis, color=c1)# where=x<=1, facecolor='green'
    ax.fill_between(x,z0,cumDis, color=c2)
    ax.plot(cumDis,label='Cumlative Income')
    ax.plot(equalDis,linestyle='dashed',label='Equal Income')
    ax.set_title('Income Lorenz Curve,Gini='+str(round(gini,4)))
    ax.legend()

    plt.subplots_adjust(left=0.07, bottom=0.07, right=0.97, top=0.90, wspace=None, hspace=None)
    plt.savefig(gSaveBasePath + name + '_simulationGini' + '.png')
    plt.show()

def plotIncomeDistribution(name,dis,disOrdered):
    ax = plt.subplot(1, 1, 1)
    #ax.plot(dis,label='Income distribution')
    #ax.plot(disOrdered,label='Income ordered')
    ax.hist(dis,bins=60, rwidth=0.72, label='Income',alpha=0.75)
    #plt.hist(x, 50, density=True, facecolor='g', alpha=0.75)

    ax.set_title("Income " + name + ' Distribution')
    ax.legend()
    plt.savefig(gSaveBasePath + name + '_simulationIncome' + '.png')
    plt.show()

def plotLorenzCurve(cumDis,equalDis,gini): #https://en.wikipedia.org/wiki/Lorenz_curve
    ax = plt.subplot(1, 1, 1)

    z0 = np.zeros(len(cumDis))
    x = range(len(cumDis))
    c1 = tuple(ti/255 for ti in (176,196,214))
    c2 = tuple(ti/255 for ti in (128,179,255))
    plt.fill_between(x,equalDis,cumDis, color=c1)# where=x<=1, facecolor='green'
    plt.fill_between(x,z0,cumDis, color=c2)
    ax.plot(cumDis,label='Cumlative Income')
    ax.plot(equalDis,linestyle='dashed',label='Equal Income')
    ax.set_title('Income Lorenz Curve,Gini='+str(round(gini,4)))
    ax.legend()
    plt.show()

def simulateDistribution():
    N=500
    start=0
    width=1
    dis = genUniform_distribution(N,start,width)
    #dis = Uniform_distribution(N,0,1)
    #print(dis,'sum=',np.sum(dis))
    #plot(np.linspace(0,1,N), dis)
    #plot(range(N), dis)
    plotAll(dis,name='Uniform')

    dis = genNormal_distribution(N,1)
    #print(dis,'sum=',np.sum(dis))
    plotAll(dis,name='Normal')

    dis = genGamma_distribution(N)
    plotAll(dis,name='Gamma')

    dis = genExp_distribution(N)
    plotAll(dis,name='Exponential')

    dis = genPoisson_distribution(N)
    plotAll(dis,name='Poisson')

    dis = genBinomial_distribution(N)
    plotAll(dis,name='Binomial')

    dis = genBernoulli_distribution(N)
    plotAll(dis,name='Bernoulli')

def standardDistribution():
    N=500
    plotAll(Uniform_distribution(N,0,1), name='S_Uniform')
    plotAll(Binomial_distribution(N, 0.8), name='S_Binomial')
    plotAll(Poisson_distribution(N,0.2), name='S_Poisson')
    plotAll(ZipfsLaw(N), name='S_ZipfsLaw')
    plotAll(NormalDistribution(np.linspace(0, N, N), u=N//2,delta=10), name='S_Normal')
    plotAll(Cauchy_pdf(np.linspace(0, N, N), x0=N//2, scaler=10), name='S_Cauchy')
    plotAll(Gumbel_distribution(np.linspace(0, N, N), u=N//2, belta=10), name='S_Gumbel')
    plotAll(Weibull_distribution(np.linspace(0, N, N),lamda=N//2,k=1.5), name='S_Weibull')
    plotAll(Pareto_distribution(np.linspace(0, N, N),alpha=.5,Xm=2), name='S_Pareto')
    plotAll(Logit_normal_distribution(np.linspace(0.001, 0.999, N), u=0,deta=1.5), name='S_Logit_normal')

def main():
    #simulateDistribution()
    standardDistribution()

if __name__=='__main__':
    main()


from typing import Any, Union, List
import numpy as np
from causaldag.utils.ci_tests import kernels
from scipy.stats import gamma
from causaldag.utils.ci_tests._utils import residuals
from causaldag.utils.core_utils import to_list

def hsic_test_vector(x: np.ndarray, y: np.ndarray, sig: float=1/np.sqrt(2), alpha=0.05):
    if x.ndim == 1:
        x = x.reshape((len(x), 1))
    if y.ndim == 1:
        y = y.reshape((len(y), 1))
    n = x.shape[0]
    if y.shape[0] != n:
        raise ValueError("Y should have the same number of samples as X")

    n = x.shape[0]
    H = np.eye(n) - np.ones([n, n])/n
    kernel_precision = 1/(sig**2)

    # === COMPUTE CENTRALIZED KERNEL MATRICES
    kx = kernels.rbf_kernel(x, kernel_precision)
    ky = kernels.rbf_kernel(y, kernel_precision)
    kx_centered = kernels.center(kx)
    ky_centered = kernels.center(ky)

    # === COMPUTE STATISTIC
    statistic = 1/n**2 * np.sum(kx_centered * ky_centered.T)  # SAME AS trace(kx_centered @ ky_centered)

    mu_x = 1/(n*(n-1)) * np.sum(kx - np.diag(np.diag(kx)))  # SUM OFF-DIAGONALS
    mu_y = 1/(n*(n-1)) * np.sum(ky - np.diag(np.diag(ky)))
    mean_approx = 1/n * (1 + mu_x*mu_y - mu_x - mu_y)
    var_approx = 2*(n-4)*(n-5)/(n*(n-1)*(n-2)*(n-3)) * np.sum(kx_centered * kx_centered.T) * np.sum(ky_centered * ky_centered.T) / n**4

    k_approx = mean_approx ** 2 / var_approx
    prec_approx = var_approx / mean_approx

    critval = gamma.ppf(1-alpha, k_approx, scale=prec_approx)
    p_value = 1 - gamma.cdf(statistic, k_approx, scale=prec_approx)

    return dict(
        statistic=statistic,
        critval=critval,
        p_value=p_value,
        reject=statistic > critval,
        mean_approx=mean_approx,
        var_approx=var_approx
    )

def hsic_test(
        suffstat: Any,
        i: int,
        j: int,
        cond_set: Union[List[int], int]=None,
        alpha: float=0.05
):
    cond_set = to_list(cond_set)
    if len(cond_set) == 0:
        return hsic_test_vector(suffstat[:, i], suffstat[:, j], alpha=alpha)
    else:
        residuals_i, residuals_j = residuals(suffstat, i, j, cond_set)
        return hsic_test_vector(residuals_i, residuals_j, alpha=alpha)


import numpy as np
import torch
import torch.nn as nn

"""
The modules/function here implement custom versions of batch normalization in PyTorch.
In contrast to more advanced implementations no use of a running mean/variance is made.
You should fill in code into indicated sections.
"""

######################################################################################
# Code for Question 3.1
######################################################################################

class CustomBatchNormAutograd(nn.Module):
  """
  This nn.module implements a custom version of the batch norm operation for MLPs.
  The operations called in self.forward track the history if the input tensors have the
  flag requires_grad set to True. The backward pass does not need to be implemented, it
  is dealt with by the automatic differentiation provided by PyTorch.
  """

  def __init__(self, n_neurons, eps=1e-5):
    """
    Initializes CustomBatchNormAutograd object.

    Args:
      n_neurons: int specifying the number of neurons
      eps: small float to be added to the variance for stability

    TODO:
      Save parameters for the number of neurons and eps.
      Initialize parameters gamma and beta via nn.Parameter
    """
    super(CustomBatchNormAutograd, self).__init__()

    ########################
    # PUT YOUR CODE HERE  #
    #######################
    self.gamma = nn.Parameter(torch.ones(n_neurons))
    self.beta = nn.Parameter(torch.zeros(n_neurons))
    self.eps = eps
    ########################
    # END OF YOUR CODE    #
    #######################

  def forward(self, input):
    """
    Compute the batch normalization

    Args:
      input: input tensor of shape (n_batch, n_neurons)
    Returns:
      out: batch-normalized tensor

    TODO:
      Check for the correctness of the shape of the input tensor.
      Implement batch normalization forward pass as given in the assignment.
      For the case that you make use of torch.var be aware that the flag unbiased=False should be set.
    """

    ########################
    # PUT YOUR CODE HERE  #
    #######################
    shape = input.shape

    if len(shape) == 1:
        input = input.unsqueeze(0)
        shape = input.shape
    elif len(shape) > 2:
        raise ValueError(f"Expected 2D input. Instead, got {len(shape)}D input with shape of {shape}.")
    elif shape[1] != self.gamma.shape[0]:
        raise ValueError(f"Expected input of shape batch_size x {self.gamma.shape[0]}. Instead, got input with"
                         f"shape of {shape}.")

    mean = input.mean(0)
    var = input.var(0)

    x_hat = (input - mean)/torch.sqrt(var + self.eps)
    out = self.gamma * x_hat + self.beta
    ########################
    # END OF YOUR CODE    #
    #######################

    return out

######################################################################################
# Code for Question 3.2 b)
######################################################################################

class CustomBatchNormManualFunction(torch.autograd.Function):
  """
  This torch.autograd.Function implements a functional custom version of the batch norm operation for MLPs.
  Using torch.autograd.Function allows you to write a custom backward function.
  The function will be called from the nn.Module CustomBatchNormManualModule
  Inside forward the tensors are (automatically) not recorded for automatic differentiation since the backward
  pass is done via the backward method.
  The forward pass is not called directly but via the apply() method. This makes sure that the context objects
  are dealt with correctly. Example:
    my_bn_fct = CustomBatchNormManualFunction()
    normalized = fct.apply(input, gamma, beta, eps)
  """

  @staticmethod
  def forward(ctx, input, gamma, beta, eps=1e-5):
    """
    Compute the batch normalization

    Args:
      ctx: context object handling storing and retrival of tensors and constants and specifying
           whether tensors need gradients in backward pass
      input: input tensor of shape (n_batch, n_neurons)
      gamma: variance scaling tensor, applied per neuron, shpae (n_neurons)
      beta: mean bias tensor, applied per neuron, shpae (n_neurons)
      eps: small float added to the variance for stability
    Returns:
      out: batch-normalized tensor

    TODO:
      Implement the forward pass of batch normalization
      Store constant non-tensor objects via ctx.constant=myconstant
      Store tensors which you need in the backward pass via ctx.save_for_backward(tensor1, tensor2, ...)
      Intermediate results can be decided to be either recomputed in the backward pass or to be stored
      for the backward pass. Do not store tensors which are unnecessary for the backward pass to save memory!
      For the case that you make use of torch.var be aware that the flag unbiased=False should be set.
    """

    ########################
    # PUT YOUR CODE HERE  #
    #######################
    shape = input.shape

    if len(shape) == 1:
        input = input.unsqueeze(0)
        shape = input.shape
    elif len(shape) > 2:
        raise ValueError(
            f"Expected 2D input. Instead, got {len(shape)}D input with shape of {shape}.")
    elif shape[1] != gamma.shape[0]:
        raise ValueError(f"Expected input of shape batch_size x {gamma.shape[0]}. Instead, got input with"
                         f"shape of {shape}.")

    mean = input.mean(0)
    var = input.var(0, unbiased = False)
    inv_var = 1/torch.sqrt(var + eps)
    x_hat = (input - mean) * inv_var
    out = gamma * x_hat + beta

    ctx.save_for_backward(input, gamma, beta, mean, inv_var)
    ctx.eps = eps

    ########################
    # END OF YOUR CODE    #
    #######################

    return out

  @staticmethod
  def backward(ctx, grad_output):
    """
    Compute backward pass of the batch normalization.

    Args:
      ctx: context object handling storing and retrival of tensors and constants and specifying
           whether tensors need gradients in backward pass
    Returns:
      out: tuple containing gradients for all input arguments

    TODO:
      Retrieve saved tensors and constants via ctx.saved_tensors and ctx.constant
      Compute gradients for inputs where ctx.needs_input_grad[idx] is True. Set gradients for other
      inputs to None. This should be decided dynamically.
    """

    ########################
    # PUT YOUR CODE HERE  #
    #######################
    input, gamma, beta, mean, inv_var = ctx.saved_tensors
    input_needs_grad, gamma_needs_grad, beta_needs_grad = ctx.needs_input_grad
    batch_dim = input.shape[0]

    x_hat = (input - mean) * inv_var
    dx_hat = grad_output * gamma
    grad_gamma = (grad_output * x_hat).sum(0) if gamma_needs_grad else None
    grad_beta = grad_output.sum(0) if beta_needs_grad else None
    grad_input = 1./batch_dim * inv_var * \
                (batch_dim * dx_hat - dx_hat.sum(0) - \
                x_hat * (dx_hat * x_hat).sum(0)) if input_needs_grad else None
    ########################
    # END OF YOUR CODE    #
    #######################

    # return gradients of the three tensor inputs and None for the constant eps
    return grad_input, grad_gamma, grad_beta, None

######################################################################################
# Code for Question 3.2 c)
######################################################################################

class CustomBatchNormManualModule(nn.Module):
  """
  This nn.module implements a custom version of the batch norm operation for MLPs.
  In self.forward the functional version CustomBatchNormManualFunction.forward is called.
  The automatic differentiation of PyTorch calls the backward method of this function in the backward pass.
  """

  def __init__(self, n_neurons, eps=1e-5):
    """
    Initializes CustomBatchNormManualModule object.

    Args:
      n_neurons: int specifying the number of neurons
      eps: small float to be added to the variance for stability

    TODO:
      Save parameters for the number of neurons and eps.
      Initialize parameters gamma and beta via nn.Parameter
    """
    super(CustomBatchNormManualModule, self).__init__()

    ########################
    # PUT YOUR CODE HERE  #
    #######################
    self.gamma = nn.Parameter(torch.ones(n_neurons))
    self.beta = nn.Parameter(torch.zeros(n_neurons))
    self.eps = eps
    ########################
    # END OF YOUR CODE    #
    #######################

  def forward(self, input):
    """
    Compute the batch normalization via CustomBatchNormManualFunction

    Args:
      input: input tensor of shape (n_batch, n_neurons)
    Returns:
      out: batch-normalized tensor

    TODO:
      Check for the correctness of the shape of the input tensor.
      Instantiate a CustomBatchNormManualFunction.
      Call it via its .apply() method.
    """

    ########################
    # PUT YOUR CODE HERE  #
    #######################
    shape = input.shape

    if len(shape) == 1:
        input = input.unsqueeze(0)
        shape = input.shape
    elif len(shape) > 2:
        raise ValueError(
            f"Expected 2D input. Instead, got {len(shape)}D input with shape of {shape}.")
    elif shape[1] != self.gamma.shape[0]:
        raise ValueError(f"Expected input of shape batch_size x {self.gamma.shape[0]}. Instead, got input with"
                         f"shape of {shape}.")

    batchNormFunc = CustomBatchNormManualFunction()
    out = batchNormFunc.apply(input, self.gamma, self.beta, self.eps)
    ########################
    # END OF YOUR CODE    #
    #######################

    return out


""" Module for analytic expressions of option prices
"""

from scipy.stats import norm
import numpy as np

def black_scholes_call_price(spot,strike,expiry,interest_rate,volatility):
      """ Analytic Black schole price for a European call

      Args:
        - spot: current spot
        - strike: call option's strike
        - expiry: expiry/maturity of the option (in years)
        - interest_rate: annualized interest rate
        - volatility: annualized volatility

      Returns:
        - price: the price of the European call
      """
      k = strike
      factor_plus  = (interest_rate+0.5*volatility**2)
      factor_minus = (interest_rate-0.5*volatility**2)
      d1 = (np.log(spot/k) + factor_plus*expiry) \
           /volatility/np.sqrt(expiry)
      d2 = (np.log(spot/k) + factor_minus*expiry) \
           /volatility/np.sqrt(expiry)
      price  = spot*norm.cdf(d1) - \
               k*np.exp(-interest_rate*expiry)*norm.cdf(d2)
      return price

def margrabe_option_price(spots,expiry,covariance_matrix):
    """ Analytic Magrabe price for an exchange option

    """
    sigma = np.sqrt(np.trace(covariance_matrix) \
                    - np.trace(np.fliplr(covariance_matrix)))
    if len(np.shape(spots))>1:
        s_plus  = spots[:,0]
        s_minus = spots[:,1]
        d1 = (np.log(s_plus/s_minus)+sigma**2*expiry*0.5)/sigma/np.sqrt(expiry)
        d2 = d1 - sigma*np.sqrt(expiry)
        price  = s_plus*norm.cdf(d1) - s_minus*norm.cdf(d2)
    else:
        s_plus  = spots[0]
        s_minus = spots[1]
        d1 = (np.log(s_plus/s_minus)+sigma**2*expiry)*0.5/sigma/np.sqrt(expiry)
        d2 = d1 - sigma*np.sqrt(expiry)
        price  = s_plus*norm.cdf(d1) - s_minus*norm.cdf(d2)
    return price


import numpy as np

#Función que calcula la matriz resultante C después de aplicar la operación convolución de A*B
def convolucion(A,B):
	for row in range(len(A)-2):
		for column in range(len(A[0])-2):
			suma = 0
			for i_row in range(len(B)):
				for j_column in range(len(B[0])):
					suma = suma + A[row+i_row][column+j_column]*B[i_row][j_column]
			C[row][column] = suma
	return C

#Matriz del ejemplo de la página
Matriz1 = [[1,2,3,4,5,6],[7,8,9,10,11,12],[0,0,1,16,17,18],[0,1,0,7,23,24],[1,7,6,5,4,3]]
Filtro = [[1,1,1],[0,0,0],[2,10,3]]

#Matriz del ejercicio.
#Matriz1 =[[6,9,0,3],[8,4,9,1],[4,1,3,12],[3,2,1,100]]
#Filtro = [[1,0,2],[5,0,9],[6,2,1]]

A = np.array(Matriz1) #Me da una mejor representación al hacer el print.
B = np.array(Filtro)

C = np.zeros((len(A)-2,len(A[0])-2)) #Genera una matriz de ceros que me sirve para inicializar la matriz directamente.

print(np.array(C))
print(convolucion(A,B))


##### Графики на плоскости

### --- 1 Задание пункт:

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-2*np.pi, 3*np.pi, 201)
plt.plot(x,  5*np.cos(x + 1) + 5)
plt.plot(x, -0.5*np.cos(x + 6))
plt.plot(x, 4*np.cos(x - 2)-5)
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True)
plt.show()

### --- 3 Задание ---

## Напишите код, который будет переводить полярные координаты в декартовы.
a = np.linspace(0, 2*np.pi, 100)
r = 2
x = r*np.cos(a)
y = r*np.sin(a)
plt.plot(x, y)

## Напишите код, который будет рисовать график окружности в полярных координатах.
x = np.linspace(0, 2*np.pi, 100)
y = 4+0*np.cos(x)
plt.polar(x, y)

## Напишите код, который будет рисовать график отрезка прямой линии в полярных координатах.
#--- не сделано

### --- 4 Задание ---
## 1

from scipy.optimize import fsolve

def equations(p):
    x, y = p
    return (y - x**2 + 1, np.exp(x) + x - x*y - 1)

x1, y1 =  fsolve(equations, (-2, 3))

print (x1, y1)
x2, y2 =  fsolve(equations, (2, 3))

print (x2, y2)

## 2
#--- не сделано


"""
This file uses fourier transform from numpy module on data filemsl_rems.csv
which recorded surface air pressure measurements from the Mars over 2
Mars years. We will explore the how to extract information through
Fourier transfrom
"""
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import find_peaks

#importing data from csv
marsData = np.genfromtxt('msl_rems.csv', delimiter=',',skip_header=1)
Time,L_S,A,B,C,D,E = marsData.T

def cosine_wave(time, amplitude, period, phase):
    """Generate a cosine wave with known amplitude, period, and phase"""
    return amplitude*np.cos((time/period + phase) *2*np.pi)

def fourierAnalysis(data,dt):
    """
    Perform Fourier Transform and return the fft coeffiecients,
    frequency, amplitude, and phase
    """
    fftData = np.fft.fft(data)
    fftData = fftData[1::]
    freqs = np.fft.fftfreq(len(data),dt)
    freqs = freqs[1::]
    amplitude = 2 * np.abs(fftData)/len(data)
    phase = np.arctan2(fftData.imag, fftData.real)

    ln = len(data)//2
    amplitude = amplitude[:ln]
    phase = phase[:ln]
    freqs = freqs[:ln]

    return fftData, freqs, amplitude, phase

def printAnswers(peaksIndices, amplitude, freqs, phase):
    """
    This function takes the indices of peaks and prints out the
    amplitude, period, and phase of the peaks.
    """
    for i in peaksIndices:
        print("Peak {}:".format(np.where(peaksIndices == i)[0]+1))
        print("amplitudes:", amplitude[i])
        print("period:", 1/freqs[i], "sol")
        print("phase:", phase[i], "rad")
        print()

def filterbyMinPeriod(peakIndices, freqs, amplitude, minimum, num):
    """
    This function takes the indices of peaks and filter out for peaks with
    periods over a minimum threshold. Then, it will print out the
    amplitude, period, and phase of the peaks.
    """
    temp = []
    for i in peakIndices:
        if 1/freqs[i] >= minimum:
            temp.append(i)
    result = sorted(temp, key=lambda x: amplitude[x], reverse=True)
    return result[:num]

def filterbyMaxPeriod(peakIndices, freqs, amplitude, maximum, num):
    """
    This function takes the indices of peaks and filter out for peaks with
    periods under a maximum threshold. Then, it will print out the
    amplitude, period, and phase of the peaks.
    """
    temp = []
    for i in peakIndices:
        if 1/freqs[i] <= maximum:
            temp.append(i)
    result = sorted(temp, key=lambda x: amplitude[x], reverse=True)
    return result[:num]

## PART A
#set arbituary time from 0s to 100s for testing
dt = 0.1
timeRange = np.arange(0,100,dt)
#construction of our test case with amplitude of 3, period of 20, and phase of 0.25
y = cosine_wave(timeRange, 3, 20, 0.25)
#fourier transformed data
fy, freqs, amplitude, phase = fourierAnalysis(y, dt)
#calculating amplitude, period, phase from fft data
print("fft amplitude:", np.max(amplitude), "original amplitude:",3)
print("fft period:", 1/freqs[np.argmax(amplitude)], "original period:",20)
print("fft phase:", phase[np.argmax(amplitude)]/(2*np.pi), "original phase:",np.pi/2)
#plotting the results
fig, graph = plt.subplots()
graph.plot(timeRange, y)
graph.set(xlabel='Time', ylabel='Amplitude',
      title='Frequency and amplitude')
graph.grid()
plt.show()

fig, graph = plt.subplots()
graph.plot(1/freqs, amplitude)
graph.set(xlabel='Frequency', ylabel='Amplitude',
      title='Frequency and amplitude')
graph.grid()
fig.savefig("q2a.png")
plt.show()

## PART B
#fourier transform data set A
fy, freqs, amplitude, phase = fourierAnalysis(A, 1/24)
#find the peaks in amplitude and printing respective informations:
peaksIndices = find_peaks(amplitude)[0][::-1]
printAnswers(peaksIndices, amplitude, freqs, phase)

#plotting amplitude and phase over period in log scale
fig, graph = plt.subplots()
graph.plot(1/freqs, amplitude)
graph.set(xlabel='Period in log scale (sols)', ylabel='Pressure Amplitude (Pa?)',
       title='Period and amplitude',xscale="log")
graph.grid()
fig.savefig("q2b_amplitude.png")
plt.show()

fig, graph = plt.subplots()
graph.plot(1/freqs, phase)
graph.set(xlabel='Period in log scale (sols)', ylabel='Phase (rad)',
       title='Period and phase',xscale="log")
graph.grid()
fig.savefig("q2b_phase.png")
plt.show()

## PART C
#fourier transform data set B
fy, freqs, amplitude, phase = fourierAnalysis(B, 1/24)
#find the peaks in amplitude and printing respective informations:
peaksIndices = find_peaks(amplitude)[0][::-1]
printAnswers(peaksIndices, amplitude, freqs, phase)

#plotting amplitude and phase over period in log scale
fig, graph = plt.subplots()
graph.plot(1/freqs, amplitude)
graph.set(xlabel='Period in log scale (sols)', ylabel='Pressure Amplitude',
       title='Period and amplitude', xscale="log")
graph.grid()
fig.savefig("q2c_amplitude.png")
plt.show()

fig, graph = plt.subplots()
graph.plot(1/freqs, phase)
graph.set(xlabel='Period in log scale (sols)', ylabel='Phase (rad)',
       title='Period and phase',xscale="log")
graph.grid()
fig.savefig("q2c_phase.png")
plt.show()

## PART D
#fourier transform data set C
fy, freqs, amplitude_C, phase = fourierAnalysis(C, 1/24)
#find the peaks in amplitude and printing respective informations:
peaksIndices_C = find_peaks(amplitude_C)[0][::-1]
printAnswers(peaksIndices_C, amplitude_C, freqs, phase)

#plotting amplitude and phase over period in log scale
fig, graph = plt.subplots()
graph.plot(1/freqs, amplitude_C)
graph.set(xlabel='Period in log scale (sols)', ylabel='Pressure Amplitude',
       title='Period and amplitude', xscale="log")
graph.grid()
fig.savefig("q2d_amplitude.png")
plt.show()

fig, graph = plt.subplots()
graph.plot(1/freqs, phase)
graph.set(xlabel='Period in log scale (sols)', ylabel='Phase (rad)',
       title='Period and phase',xscale="log")
graph.grid()
fig.savefig("q2d_phase.png")
plt.show()

## PART E
#fourier transform data set D
fy, freqs, amplitude_D, phase = fourierAnalysis(D, 1/24)
#find the peaks in amplitude and printing respective informations:
#using information from part d to kinda cheat
mask = []
for peak in peaksIndices_C:
    mask.append(np.where(np.logical_and(amplitude_D <= amplitude_C[peak]*1.1,
                               amplitude_D >= amplitude_C[peak]*0.9))[0])
mask = [item for sublist in mask for item in sublist]
peaksIndices = find_peaks(amplitude_D, distance=16047)[0][::-1]
printAnswers(mask, amplitude_D, freqs, phase)

#plotting amplitude and phase over period in log scale
fig, graph = plt.subplots()
graph.plot(1/freqs, amplitude_D)
graph.set(xlabel='Period in log scale (sols)', ylabel='Pressure Amplitude (Pa?)',
       title='Period and amplitude', xscale="log")
graph.grid()
fig.savefig("q2e_amplitude.png")
plt.show()

fig, graph = plt.subplots()
graph.plot(1/freqs, phase)
graph.set(xlabel='Period in log scale (sols)', ylabel='Phase (rad)',
       title='Period and phase',xscale="log")
graph.grid()
fig.savefig("q2e_phase.png")
plt.show()

fig, graph = plt.subplots()
graph.plot(Time, D)
graph.set(xlabel='time (s)', ylabel='Pressure (Pa)',
       title='Time series of D')
graph.grid()
fig.savefig("q2e_timeseries.png")
plt.show()

## PART F
#fourier transform data set E
fy, freqs, amplitude, phase = fourierAnalysis(E, 1/24)
#find the peaks in amplitude and printing respective informations:
peaksIndices = find_peaks(amplitude)[0][::-1]
#finding peaks over 100 sols and under 1 sol
filtered100 = filterbyMinPeriod(peaksIndices, freqs, amplitude, 100, 4)
filtered1 = filterbyMaxPeriod(peaksIndices, freqs, amplitude, 1.1, 4)
print("largest  waves  with periods longer than 100 sols:")
printAnswers(filtered100, amplitude, freqs, phase)
print("largest  waves  with periods shorted than 1 sols:")
printAnswers(filtered1, amplitude, freqs, phase)

#plotting amplitude and phase over period in log scale
fig, graph = plt.subplots()
graph.plot(1/freqs, amplitude)
graph.set(xlabel='Period in log scale (sols)', ylabel='Pressure Amplitude (Pa?)',
       title='Period and amplitude', xscale="log")
graph.grid()
fig.savefig("q2f_amplitude.png")
plt.show()

fig, graph = plt.subplots()
graph.plot(1/freqs, phase)
graph.set(xlabel='Period in log scale (sols)', ylabel='Phase (rad)',
       title='Period and phase',xscale="log")
graph.grid()
fig.savefig("q2f_phase.png")
plt.show()


'''
Is Temperature a Random Walk (with Drift)?

An ARMA model is a simplistic approach to forecasting climate changes, but it illustrates many of the topics covered in this class.

The DataFrame temp_NY contains the average annual temperature in Central Park, NY from 1870-2016 (the data was downloaded from the NOAA here). Plot the data and test whether it follows a random walk (with drift).

INSTRUCTIONS
100XP
Convert the index of years into a datetime object using pd.to_datetime(), and since the data is annual, pass the argument format='%Y'.
Plot the data using .plot()
Compute the p-value the Augmented Dickey Fuller test using the adfuller function.
Save the results of the ADF test in result, and print out the p-value in result[1].
'''
# Import the adfuller function from the statsmodels module
from statsmodels.tsa.stattools import adfuller

# Convert the index to a datetime object
temp_NY.index = pd.to_datetime(temp_NY.index, format='%Y')

# Plot average temperatures
temp_NY.plot()
plt.show()

# Compute and print ADF p-value
result = adfuller(temp_NY['TAVG'])
print("The p-value for the ADF test is ", result[1])


# Eric Robbins
# A quick test of scipy's solution to the assignment (cost-matrix) problem

import random
import numpy as np
from scipy.optimize import linear_sum_assignment
import math

X_RANGE = 100
Y_RANGE = 100

# randomize stations and centroids (workers and jobs, respectively, in the classic assignment problem)
# format is (index, x_coord, y_coord)
stations = [(i, random.randint(-X_RANGE, X_RANGE), random.randint(-Y_RANGE, Y_RANGE)) for i in range(15)]
centroids = [(i, random.randint(-X_RANGE, X_RANGE), random.randint(-Y_RANGE, Y_RANGE)) for i in range(15)]

# calculate pythagorean distance between two xy coords
def pyth_dist(pt1, pt2):

    return math.sqrt(math.pow((pt2[1] - pt1[1]), 2) + math.pow((pt2[2] - pt1[2]), 2))

# create empty numpy array
m = len(stations)
n = len(centroids)
cost_mat = np.empty(shape=(m,n))

newRow = []
temp_arr = []

# make matrix out of station->centroid distances
for j in range(n):
    for i in range(m):
        newRow.append(pyth_dist(stations[i], centroids[j]))
    temp_arr.append(newRow)
    newRow = []

# fill numpy array
cost_mat = np.array(temp_arr)

# find optimized pairings (hungarian method)
opt_row, opt_col = linear_sum_assignment(cost_mat)

# output ordered pairs
print_list = []
for i in range(len(opt_row)):
    print_list.append((stations[opt_row[i]], centroids[opt_col[i]]))

print(print_list)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Jul  9 11:57:54 2019

@author: fietekrutein

A script for solving an unconstrained single variable function using
the Golden Section method
"""
import numpy as np

# function as per example problem

def gsNext(a0, b0, p):
    return(a0 + p*(b0 - a0))

# method

def GoldenSection(a,b,fx,tol=0.001):
    aCurrent = a
    bCurrent = b

    N = int(np.ceil((np.log(2*tol) - np.log(np.abs(b-a)))/np.log(0.618)))

    aNext = gsNext(aCurrent, bCurrent, 0.382)
    bNext = gsNext(aCurrent, bCurrent, 0.618)
    fxa = fx(aNext)
    fxb = fx(bNext)

    for i in range(N):
        if fxa < fxb:
            bCurrent = bNext
            bNext = aNext
            fxb = fxa
            aNext = gsNext(aCurrent, bCurrent, 0.382)
            fxa = fx(aNext)
        else:
            aCurrent = aNext
            aNext = bNext
            fxa = fxb
            bNext = gsNext(aCurrent, bCurrent, 0.618)
            fxb = fx(bNext)

    return((aCurrent+bCurrent)/2)

# execute

GoldenSection(0,2,lambda x: 2*x**6 + 3*x**4 -12*x, 0.01)


from numpy import mat

'''
测试A的转置的逆与A的逆的转置是否相等
'''
m = mat([[2, 3, 1],
         [4, 5, 6],
         [7, 8, 9],
         ])

print(m.T.I)
print(m.I.T)


import numpy as np
import matplotlib.pyplot as plt

# mass, spring constant, initial position and velocity
m = 1
k = 1
x = 0
v = 1

# Creating first two data using Euler's method
t_max = 0.2
dt = 0.1
t_array = np.arange(0, t_max, dt)
x_list = []
v_list = []
for t in t_array:
    x_list.append(x)
    v_list.append(v)
    a = -k * x / m
    x = x + dt * v
    v = v + dt * a

# Verlet method
t_max = 10
dt = 0.1
t_array = np.arange(0.2, t_max, dt)

# initialise empty lists to record trajectories
counter = 1
# Euler integration
for t in t_array:
    # append current state to trajectories
    # calculate new position and velocity
    a = -k * x / m
    x = 2*x_list[counter]-x_list[counter-1]+(dt**2)*a
    v = (1/dt)*(x-x_list[counter])
    x_list.append(x)
    v_list.append(v)
    counter +=1
# convert trajectory lists into arrays, so they can be sliced (useful for Assignment 2)
x_array = np.array(x_list)
v_array = np.array(v_list)

t_array_plot = np.arange(0, t_max, dt)
# plot the position-time graph
plt.figure(1)
plt.clf()
plt.xlabel('time (s)')
plt.grid()
plt.plot(t_array_plot, x_array, label='x (m)')
plt.plot(t_array_plot, v_array, label='v (m/s)')
plt.legend()
plt.show()


import numpy as np
import matplotlib.pyplot as plt

def identity(x):
    return x

def d_identity(x):
    return np.ones(shape=x.shape)

def relu(x):
    y = np.copy(x)
    threshold = x < np.zeros(shape=x.shape)
    y[threshold] = 0
    return y

def d_relu(x):
    y = np.ones(shape=x.shape)
    threshold = x < np.zeros(shape=x.shape)
    y[threshold] = 0
    return y

def sigmoid(x):
    return 1/(1+np.exp(-x))

def d_sigmoid(x):
    return sigmoid(x)*(1-sigmoid(x))

if __name__ == '__main__':
    x = np.arange(-6, 6, 0.1)
    y = identity(x)
    plt.plot(x, y)
    y = d_identity(x)
    plt.plot(x, y)
    plt.show()

    y = relu(x)
    plt.plot(x, y)
    y = d_relu(x)
    plt.plot(x, y)
    plt.show()

    y = sigmoid(x)
    plt.plot(x, y)
    y = d_sigmoid(x)
    plt.plot(x, y)
    plt.show()


import numpy as np
from matplotlib import cm
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize

def surface_curvature_3d(X, Y, Z):
  # Shape
  (lr,lb) = X.shape

  # First Derivatives
  Xv,Xu = np.gradient(X)
  Yv,Yu = np.gradient(Y)
  Zv,Zu = np.gradient(Z)

  # Second Derivatives
  Xuv,Xuu = np.gradient(Xu)
  Yuv,Yuu = np.gradient(Yu)
  Zuv,Zuu = np.gradient(Zu)

  Xvv,Xuv = np.gradient(Xv)
  Yvv,Yuv = np.gradient(Yv)
  Zvv,Zuv = np.gradient(Zv)

  # 2D to 1D conversion
  # Reshape to 1D vectors
  Xu = np.reshape(Xu,lr*lb)
  Yu = np.reshape(Yu,lr*lb)
  Zu = np.reshape(Zu,lr*lb)
  Xv = np.reshape(Xv,lr*lb)
  Yv = np.reshape(Yv,lr*lb)
  Zv = np.reshape(Zv,lr*lb)
  Xuu = np.reshape(Xuu,lr*lb)
  Yuu = np.reshape(Yuu,lr*lb)
  Zuu = np.reshape(Zuu,lr*lb)
  Xuv = np.reshape(Xuv,lr*lb)
  Yuv = np.reshape(Yuv,lr*lb)
  Zuv = np.reshape(Zuv,lr*lb)
  Xvv = np.reshape(Xvv,lr*lb)
  Yvv = np.reshape(Yvv,lr*lb)
  Zvv = np.reshape(Zvv,lr*lb)

  Xu = np.c_[Xu, Yu, Zu]
  Xv = np.c_[Xv, Yv, Zv]
  Xuu = np.c_[Xuu, Yuu, Zuu]
  Xuv = np.c_[Xuv, Yuv, Zuv]
  Xvv = np.c_[Xvv, Yvv, Zvv]

  # First fundamental Coeffecients of the surface (E,F,G)
  E = np.einsum('ij,ij->i', Xu, Xu)
  F = np.einsum('ij,ij->i', Xu, Xv)
  G = np.einsum('ij,ij->i', Xv, Xv)

  m = np.cross(Xu, Xv, axisa=1, axisb=1)
  p = np.sqrt(np.einsum('ij,ij->i', m, m))
  n = m / np.c_[p,p,p] # n is the normal

  # Second fundamental Coeffecients of the surface (L,M,N), (e,f,g)
  L = np.einsum('ij,ij->i', Xuu, n) #e
  M = np.einsum('ij,ij->i', Xuv, n) #f
  N = np.einsum('ij,ij->i', Xvv, n) #g

  # Gaussian Curvature
  # Alternative formula for gaussian curvature in wiki
  # K = det(second fundamental) / det(first fundamental)
  K = (L*N-M**2) / (E*G-F**2)
  K = np.reshape(K, lr*lb)
  # wiki trace of (second fundamental)(first fundamental inverse)

  # Mean Curvature
  H = ((E*N + G*L - 2*F*M) / ((E*G - F**2))) / 2
  H = np.reshape(H,lr*lb)

  # Principle Curvatures
  Pmax = H + np.sqrt(H**2 - K)
  Pmin = H - np.sqrt(H**2 - K)

  # Curvedness
  # 3D Shape Modeling for Cell Nuclear Morphological Analysis and Classification
  CV = np.sqrt((Pmin**2 + Pmax**2) / 2)

  # Shape Index
  # 3D Shape Modeling for Cell Nuclear Morphological Analysis and Classification
  SI = np.zeros(Pmax.shape)
  idx = (Pmax - Pmin) != 0
  SI[idx] = (2 / np.pi) * np.arctan((Pmin[idx] + Pmax[idx])/(Pmax[idx] - Pmin[idx]))

  # Reshape
  K = np.reshape(K,(lr,lb))
  H = np.reshape(H,(lr,lb))
  Pmax = np.reshape(Pmax,(lr,lb))
  Pmin = np.reshape(Pmin,(lr,lb))
  CV = np.reshape(CV,(lr,lb))
  SI = np.reshape(SI,(lr,lb))

  return K, H, Pmax, Pmin, CV, SI

if __name__ == '__main__':

  # Generate surface data
  X = np.arange(-5, 5, 0.25)
  Y = np.arange(-5, 5, 0.25)
  X, Y = np.meshgrid(X, Y)
  Z = np.exp(-0.1*X**2-0.1*Y**2)

  # Curvature 3D
  K, H, Pmax, Pmin, CV, SI = surface_curvature_3d(X, Y, Z)

  # Plot
  fig = plt.figure()
  ax = fig.gca(projection='3d')

  # Auto-adjust true radius into [0,1] for color mapping
  norm = Normalize()
  colors = norm(CV)
  cmap = cm.get_cmap("jet")

  # Surface
  ax.plot_surface(X, Y, Z, facecolors=cmap(colors),
                  linewidth=0, antialiased=False)

  # Add a color bar which maps values to colors
  # the surface is not mappable, we need to handle the colorbar manually
  mappable = cm.ScalarMappable(cmap=cmap)
  mappable.set_array(colors)
  fig.colorbar(mappable, shrink=0.9, aspect=5)

  # Save
  plt.savefig('./im/surface_curvature3d.png', bbox_inches = 'tight',
    pad_inches = 0)

  # Show
  plt.show()


import numpy as np

def centroide(k,data,cent):
    n = np.array(data.shape)[0]
    dataF = np.zeros(shape=(n,k),dtype=float)
    for counter in range(0,k):
        diff = cent[counter,:] - data
        diff2 = diff**2
        diffm = diff2[:,0] + diff2[:,1]
        distance = [ x**0.5 for x in diffm]
        dataF[:,counter] = distance
    dataC = np.zeros(shape=(k,2),dtype=float)
    indice = np.argmin(dataF,1)
    for counter in range(0,k):
        x = data[indice == counter][:,0].mean()
        y = data[indice == counter][:,1].mean()
        new_center = [x,y]
        dataC[counter,:] = new_center
    return(dataC)

def kmeans(data,k):
    center = np.random.rand(k,2)
    while True:
        new_center = centroide(k,data,center)
        comp = center - new_center
        if np.all(comp == 0):
            center = new_center
            break
        else:
            center = new_center
            new_center = centroide(k,data,center)
    return center


import numpy as np

d1 = np.array([1,2,3,4])
d2 = np.array([5,6,7,8])

result =np.add( d1, d2)

print("add\n",result)
result =np.subtract( d1, d2)

print("subtract\n",result)
result =np.multiply( d1, d2)

print("multiply\n",result)
result =np.divide( d2, d1)

print("divide\n",result)

result =np.floor_divide( d2, d1)

print("floor divide\n",result)

result =np.power( d1, d2)

print("power\n",result)

result =np.remainder( d1, d2)

print("remainder\n",result)

result =np.divmod( d2, d1)

print("divmod\n",result)

result =np.absolute( d1)*-1

print("-abs\n",result)

result =np.trunc(  d2/d1)

print("trunc\n",result)
result =np.around(  d2/d1,2)

print("around\n",result)
result =np.floor(  d2/d1)

print("floor\n",result)
result =np.ceil(  d2/d1)

print("ceil\n",result)
result =np.ceil(  d1/d2)
print("Original\n",d1/d2)
print("ceil\n",result)
result =np.log(  d1)

print("log\n",result)
result =np.log10(  d2/d1)

print("log10\n",result)


import numpy as np
import scipy.linalg as sl

def gaussian_loglikelihood(z, th, sigsq):
  z = np.atleast_2d(z)
  x = z[:, :-1]
  y = z[:, -1]
  th = np.atleast_2d(th)
  XST = x.dot(th.T)
  return -1./2.*np.log(2.*np.pi*sigsq) - 1./(2.*sigsq)*(y[:,np.newaxis]**2 - 2*XST*y[:,np.newaxis] + XST**2)

def gaussian_grad_x_loglikelihood(z, th, sigsq):
  z = np.atleast_2d(z)
  x = z[:, :-1]
  y = z[:, -1]
  th = np.atleast_2d(th)
  return 1./sigsq*(y[:, np.newaxis] - x.dot(th.T))[:,:,np.newaxis]*np.hstack((th, np.ones(th.shape[0])[:,np.newaxis]))[np.newaxis, :, :]

def gaussian_KL(mu0, Sig0, mu1, Sig1inv):
  t1 = np.dot(Sig1inv, Sig0).trace()
  t2 = np.dot((mu1-mu0),np.dot(Sig1inv, mu1-mu0))
  t3 = -np.linalg.slogdet(Sig1inv)[1] - np.linalg.slogdet(Sig0)[1]
  return 0.5*(t1+t2+t3-mu0.shape[0])

def weighted_post(th0, Sig0inv, sigsq, z, w):
  z = np.atleast_2d(z)
  X = z[:, :-1]
  Y = z[:, -1]
  LSigpInv = np.linalg.cholesky(Sig0inv + (w[:, np.newaxis]*X).T.dot(X)/sigsq)
  LSigp = sl.solve_triangular(LSigpInv, np.eye(LSigpInv.shape[0]), lower=True, overwrite_b = True, check_finite = False)
  mup = np.dot(LSigp.dot(LSigp.T),  np.dot(Sig0inv,th0) + (w[:, np.newaxis]*Y[:,np.newaxis]*X).sum(axis=0)/sigsq )
  #Sigp = np.linalg.inv(Sig0inv + (w[:, np.newaxis]*X).T.dot(X)/sigsq)
  #mup = np.dot(Sigp,  np.dot(Sig0inv,th0) + (w[:, np.newaxis]*Y[:,np.newaxis]*X).sum(axis=0)/sigsq )
  return mup, LSigp, LSigpInv


import sympy as sp

x = sp.Symbol('x')
function = x**2 - 2

def bisection(f, xl, xr):
    fxl = f.evalf(subs={x : xl})
    xm = 0

    while True:
        xm = (xl + xr)/2
        fxl = f.evalf(subs={x : xl})
        fxm = f.evalf(subs={x : xm})
        if fxl * fxm < 0:
            xr = xm
        else:
            xl = xm

        if abs(fxm) < 10**(-4):
            break

    return xm

def newton(f, df, xVal):
    while True:
        fx = f.evalf(subs={x : xVal})
        xVal = xVal -  fx/ df.evalf(subs={x : xVal})

        if abs(fx) < 10**(-4):
            break

    return xVal

def secant(f, x1, x2):
    xNew = 0

    while True:
        fx1 = f.evalf(subs={x : x1})
        fx2 = f.evalf(subs={x : x2})
        denominator = fx2 - fx1
        if denominator != 0:
            xNew = x2 - ((x2-x1)/denominator) * fx2
            if abs(xNew - x2) < 10*(-4):
                break
            else:
                x1 = x2
                x2 = xNew
        else:
            break

    return xNew

print("Bisection:", bisection(function, 0, 4))
print("Newton:", newton(function, sp.diff(function), 4))
print("Secant:", secant(function, 0, 4))


import numpy as np

print("VEKTORAUFGABEN")
print()
print("a) Betrag des Vektors [[-6]")
print("                       [7]]")
print()
print('=', np.linalg.norm(np.array([[-6], [7]])))
print()
print("b) [[2]    [[-4]")
print("    [3]  +  [5]")
print("    [4]]    [-7]]")
print()
print('=', np.array([[2], [3], [4]]) + np.array([[-4], [5], [-7]]))
print()
print("c)     [[6]")
print("   5 *  [-7]")
print("        [8]]")
print()
print('=', 5 * np.array([[6], [-7], [8]]))
print()
print("d) [[2]    [[8]")
print("    [3]  *  [-1]")
print("    [4]]    [4]]")
print()
print('=', np.array([[2], [3], [4]]) * np.array([[8], [-1], [4]]))
print()
print("MATRIXAUFGABEN")
print()
print("                      [[2    1.5]")
print("A = [[3  -4  5] , B =  [-1.5   2]  , C = [[-3  1]")
print("     [-5  4  3]]       [0     -1]]        [2  -4]]")
print()
a = np.array([[3, -4, 5], [-5, 4, 3]])
b = np.array([[2, 1.5], [-1.5, 2], [0, -1]])
c = np.array([[-3, 1], [2, -4]])
print("a) A + B[T]")
print('=', a + b.transpose())
print()
print("b) A * B")
print('=', np.dot(a, b))
print()
print("c) B * A")
print('=', np.dot(b, a))
print()
print("d) det(C)")
print('=', np.linalg.det(c))
print()
print("e) C ** -1")
print('=', np.linalg.inv(c))
print()
print("f) Gleichungssysteme mit inverser Matrix lösen:")
print("f1) -3x + y = 0, 2x - 4y = -20")
print('=', np.linalg.solve(c, np.array([0, -20])))
print()
print("f2) -3x + y = -2, 2x - 4y = 16")
print('=', np.linalg.solve(c, np.array([-2, 16])))


import numpy as np
import matplotlib.pyplot as plt
from scipy.special import assoc_laguerre
import seaborn as sns

sns.set_theme()

def radial_wavefunction(x, n, l, z):
    prefac = (2.0 * z / n) ** 3 / 2.0 / n / np.prod(range(n - l, n + l + 1))
    return (
        -np.sqrt(prefac)
        * np.exp(-z * x / n)
        * (2.0 * z * x / n) ** l
        * assoc_laguerre(2.0 * z * x / n, n - l - 1, k=2.0 * l + 1.0)
    )

def integrate(x, y):
    return np.sum((y[1:] + y[:-1]) * (x[1:] - x[:-1])) / 2

def normalize(x, y):
    mask = x > 0
    prop_density = y[mask] ** 2
    N = integrate(x[mask], prop_density)
    if y[1] < 0:
        return y / x / np.sqrt(N)
    return -y / x / np.sqrt(N)

def plot_eigenfunction(
    basefilename, indices, savename, xmax=10, l=0, z=1, fakenorm=False, legend=True
):
    data = np.genfromtxt(f"build/output/{basefilename}_plot_points.npy").T
    eigvalues = np.genfromtxt(f"build/output/{basefilename}_eigenvalues.npy").T

    x, ys = data[0], data[1:]
    mask = x <= xmax

    iter = list(zip(ys, eigvalues))
    for idx in indices:
        y, eigvalue = iter[idx]
        y_ = normalize(x, y)

        ana = radial_wavefunction(x[mask], idx + 1 + l, l, z)

        if fakenorm:
            y_ = y_ / y_[mask][-10] * ana[-10]

        p = plt.plot(x[mask], y_[mask], label=f"$E_{{ {idx+1} }}={eigvalue}$")[0]

        if not legend:
            plt.text(x[mask][1] - 0.1, y_[mask][1] - 0.1, f"$E_{{ {idx+1} }}$")

        plt.plot(
            x[mask],
            ana,
            ".",
            alpha=0.5,
            color=p.get_color(),
        )

    plt.xlabel("$r/a_0$")
    plt.ylabel(r"$\psi_n(r) / a_0^{-3/2}$")

    if legend:
        plt.legend()

    plt.tight_layout()
    plt.savefig(f"build/plots/{savename}.pdf")
    plt.cla()

plot_eigenfunction("good_wideplot", [0, 1, 2], "eigenfunctions", legend=False)
plot_eigenfunction("good_wideplot", [10, 11, 12], "eigenfunctions_high", fakenorm=True)
plot_eigenfunction("good_wideplot_l1", [1, 2, 3], "eigenfunctions_l1", l=1)
plot_eigenfunction("good_wideplot_l2", [2, 3, 4], "eigenfunctions_l2", l=2)
plot_eigenfunction(
    "good_wideplot_l6", [6, 7, 8], "eigenfunctions_l6", fakenorm=True, l=6
)


#!/usr/bin/python

'''
mjtsai1974@20180606, v1.1, scipy.norm for Gaussian normal distribution illustration

http://www.astroml.org/book_figures/chapter3/fig_gaussian_distribution.html

dist = scipy.stats.norm(...)

Where ... should be filled in with the desired distribution parameters Once we have defined the distribution parameters in this way, these distribution objects have many useful methods; for example:

    dist.pmf(x) computes the Probability Mass Function at values x in the case of discrete distributions
    dist.pdf(x) computes the Probability Density Function at values x in the case of continuous distributions
    dist.rvs(N) computes N random variables distributed according to the given distribution
'''

import numpy as np
from scipy.stats import norm
from matplotlib import pyplot as plt

#----------------------------------------------------------------------
# This function adjusts matplotlib settings for a uniform feel in the textbook.
# Note that with usetex=True, fonts are rendered with LaTeX.  This may
# result in an error if LaTeX is not installed on your system.  In that case,
# you can set usetex to False.
from astroML.plotting import setup_text_plots
setup_text_plots(fontsize=8, usetex=False)

# Define the distributions to be plotted
sigma_values = [0.5, 1.0, 2.0]
linestyles = ['-', '--', ':']
mu = 0
x = np.linspace(-10, 10, 1000)

# plot the distributions
fig, ax = plt.subplots(figsize=(5, 3.75))

for sigma, ls in zip(sigma_values, linestyles):
    # create a gaussian / normal distribution
    dist = norm(mu, sigma)

    plt.plot(x, dist.pdf(x), ls=ls, c='black',
             label=r'$\mu=%i,\ \sigma=%.1f$' % (mu, sigma))

plt.xlim(-5, 5)
plt.ylim(0, 0.85)

plt.xlabel('$x$')
plt.ylabel(r'$p(x|\mu,\sigma)$')
plt.title('Gaussian Distribution')

plt.legend()
plt.show()


import numpy as np

def intersect_lines(p0, q0, p1, q1):
    """
    Intersect two lines in 3d: (p0, q0) and (p1, q1). Each should be a 3D
    point.

    See also:
        https://math.stackexchange.com/a/271366/640314
    """
    e = p0 - q0  # direction of line 0
    f = p1 - q1  # direction of line 1

    # Check for special case where we're given the intersection
    # Note that we must check for these, because if p0 == p1 then
    # g would be zero length and we can't continue
    if np.all(p0 == p1) or np.all(p0 == q1):
        return p0
    if np.all(q0 == p1) or np.all(p0 == q1):
        return q0

    g = p0 - p1  # line between to complete a triangle
    h = np.cross(f, g)
    k = np.cross(f, e)
    h_ = np.linalg.norm(h)
    k_ = np.linalg.norm(k)
    if h_ == 0 or k_ == 0:
        # There is no intesection; either parallel (k=0) or collinear (both=0) lines.
        return None

    # Check for the special case of lines in parallel planes.
    # https://math.stackexchange.com/a/697278/640314
    if np.dot(g, k) != 0:
        return None

    l = h_ / k_ * e  # noqa: E741
    sign = -1 if np.all(h / h_ == k / k_) else +1
    return p0 + sign * l

def intersect_2d_lines(p0, q0, p1, q1):
    """
    Intersect two lines: (p0, q0) and (p1, q1). Each should be a 2D
    point.
    """
    # Adapted from http://stackoverflow.com/a/26416320/893113
    dy = q0[1] - p0[1]
    dx = q0[0] - p0[0]
    lhs0 = [-dy, dx]
    rhs0 = p0[1] * dx - dy * p0[0]

    dy = q1[1] - p1[1]
    dx = q1[0] - p1[0]
    lhs1 = [-dy, dx]
    rhs1 = p1[1] * dx - dy * p1[0]

    a = np.array([lhs0, lhs1])
    b = np.array([rhs0, rhs1])

    try:
        return np.linalg.solve(a, b)
    except np.linalg.LinAlgError:
        return None


"""
Numerical integration of the SIR disease model
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint

# right hand side of the equation
def compute_SIR_rhs(y, t, N, beta, gamma):
    S, I, R = y
    dSdt = - beta * I * S / N # number of uninfected people
    dIdt = beta * I * S / N - gamma * I # number of infected people
    dRdt = gamma * I # number of recovert people
    return dSdt, dIdt, dRdt

# parameters
beta = 1 / 1.0 # = 1 / time between contacts between people
N = 100 # = number of people
gamma = 1 / 14.0 # = 1 / time until recovery
args = (N, beta, gamma)
initial_infected_ratio = 1e-4
num_infected = initial_infected_ratio * N
y0 = (N - num_infected, num_infected, 0)

if __name__ == "__main__":
    # integrate the system
    t_s = np.linspace(0, 8 / gamma, 400)
    S, I, R = odeint(compute_SIR_rhs, y0, t_s, args).T

    # plot the result
    plt.plot(t_s, S, label="S")
    plt.plot(t_s, I, label="I")
    plt.plot(t_s, R, label="R")
    plt.xlabel("t")
    plt.ylabel("number of people")
    plt.title(r"SIR disease model with $N = %i, \beta = %.2f, \gamma = %.2f$" % args)
    plt.text(t_s[len(t_s) // 2], N / 2,
            r"$\frac{\mathrm{d} S}{\mathrm{d} t} = - \beta I S / N$" + "\n" +
            r"$\frac{\mathrm{d}I}{\mathrm{d}t} = \beta I S / N - \gamma I$" + "\n" +
            r"$\frac{\mathrm{d}R}{\mathrm{d}t} = \gamma I$")
    plt.legend()
    plt.show()


# the functions used in the application are here
import numpy as np
import matplotlib.pyplot as plt
import h5py

def sigmoid(Z):
    A = 1/(1+np.exp(-Z))
    cache = Z
    return A, cache

def relu(Z):
    A = np.maximum(0,Z)
    assert(A.shape == Z.shape)
    cache = Z
    return A, cache

def relu_backward(dA, cache):
    Z = cache
    dZ = np.array(dA, copy=True)
    dZ[Z <= 0] = 0
    assert (dZ.shape == Z.shape)
    return dZ

def sigmoid_backward(dA, cache):
    Z = cache
    s = 1/(1+np.exp(-Z))
    dZ = dA * s * (1-s)
    return dZ

def load_data():

    train_dataset = h5py.File('datasets/<your .h5 file>', "r")
    train_set_x_orig = np.array(train_dataset["train_set_x"][:])
    train_set_y_orig = np.array(train_dataset["train_set_y"][:])

    test_dataset = h5py.File('datasets/<your .h5 file>', "r")
    test_set_x_orig = np.array(test_dataset["test_set_x"][:])
    test_set_y_orig = np.array(test_dataset["test_set_y"][:])

    classes = np.array(test_dataset["list_classes"][:])
    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))

    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

def initialize_parameters_deep(layer_dims):

    np.random.seed(1)
    parameters = {}
    L = len(layer_dims)

    for l in range(1, L):
        parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1]) / np.sqrt(layer_dims[l-1])
        parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))

        assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l-1]))
        assert(parameters['b' + str(l)].shape == (layer_dims[l], 1))

    return parameters

#Forward Propagation
def linear_forward(A, W, b):

    Z = W.dot(A) + b

    assert(Z.shape == (W.shape[0], A.shape[1]))
    cache = (A, W, b)

    return Z, cache

def linear_activation_forward(A_prev, W, b, activation):

    if activation == "sigmoid":

        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = sigmoid(Z)

    elif activation == "relu":

        Z, linear_cache = linear_forward(A_prev, W, b)
        A, activation_cache = relu(Z)

    assert (A.shape == (W.shape[0], A_prev.shape[1]))
    cache = (linear_cache, activation_cache)

    return A, cache

def L_model_forward(X, parameters):

    caches = []
    A = X
    L = len(parameters) // 2
    for l in range(1, L):
        A_prev = A
        A, cache = linear_activation_forward(A_prev, parameters['W' + str(l)], parameters['b' + str(l)], activation = "relu")
        caches.append(cache)

    AL, cache = linear_activation_forward(A, parameters['W' + str(L)], parameters['b' + str(L)], activation = "sigmoid")
    caches.append(cache)

    assert(AL.shape == (1,X.shape[1]))

    return AL, caches

#Computing Cost
def compute_cost(AL, Y):
    m = Y.shape[1]
    cost = (1./m) * (-np.dot(Y,np.log(AL).T) - np.dot(1-Y, np.log(1-AL).T))

    cost = np.squeeze(cost)
    assert(cost.shape == ())

    return cost

#Backward Propagation
def linear_backward(dZ, cache):

    A_prev, W, b = cache
    m = A_prev.shape[1]

    dW = 1./m * np.dot(dZ,A_prev.T)
    db = 1./m * np.sum(dZ, axis = 1, keepdims = True)
    dA_prev = np.dot(W.T,dZ)

    assert (dA_prev.shape == A_prev.shape)
    assert (dW.shape == W.shape)
    assert (db.shape == b.shape)

    return dA_prev, dW, db

def linear_activation_backward(dA, cache, activation):

    linear_cache, activation_cache = cache

    if activation == "relu":
        dZ = relu_backward(dA, activation_cache)
        dA_prev, dW, db = linear_backward(dZ, linear_cache)

    elif activation == "sigmoid":
        dZ = sigmoid_backward(dA, activation_cache)
        dA_prev, dW, db = linear_backward(dZ, linear_cache)

    return dA_prev, dW, db

def L_model_backward(AL, Y, caches):

    grads = {}
    L = len(caches)
    m = AL.shape[1]
    Y = Y.reshape(AL.shape)

    dAL = - (np.divide(Y, AL) - np.divide(1 - Y, 1 - AL))

    current_cache = caches[L-1]
    grads["dA" + str(L-1)], grads["dW" + str(L)], grads["db" + str(L)] = linear_activation_backward(dAL, current_cache, activation = "sigmoid")

    for l in reversed(range(L-1)):

        current_cache = caches[l]
        dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads["dA" + str(l + 1)], current_cache, activation = "relu")
        grads["dA" + str(l)] = dA_prev_temp
        grads["dW" + str(l + 1)] = dW_temp
        grads["db" + str(l + 1)] = db_temp

    return grads

#Updating and predicting
def update_parameters(parameters, grads, learning_rate):

    L = len(parameters) //2

    for l in range(L):
        parameters["W" + str(l+1)] = parameters["W" + str(l+1)] - learning_rate * grads["dW" + str(l+1)]
        parameters["b" + str(l+1)] = parameters["b" + str(l+1)] - learning_rate * grads["db" + str(l+1)]

    return parameters

def predict(X, y, parameters):

    m = X.shape[1]
    n = len(parameters)
    p = np.zeros((1,m))

    probas, caches = L_model_forward(X, parameters)

    for i in range(0, probas.shape[1]):
        if probas[0,i] > 0.5:
            p[0,i] = 1
        else:
            p[0,i] = 0

    print("Accuracy: "  + str( np.sum( (p == y) / m )*100 ) )

    return p

train_x_orig, train_y, test_x_orig, test_y, classes = load_data()

train_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T
test_x_flatten = test_x_orig.reshape(test_x_orig.shape[0], -1).T

train_x = train_x_flatten/255.
test_x = test_x_flatten/255.

#Integrating all the functions to a model
def L_layer_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False):

    np.random.seed(1)
    costs = []

    parameters = initialize_parameters_deep(layers_dims)

    for i in range(0, num_iterations):

        AL, caches = L_model_forward(X, parameters)

        cost = compute_cost(AL, Y)

        grads = L_model_backward(AL, Y, caches)

        parameters = update_parameters(parameters, grads, learning_rate)

        if print_cost and i % 100 == 0:
            print ("Cost after iteration %i: %f" % (i, cost))
        if print_cost and i % 100 == 0:
            costs.append(cost)

    plt.plot(np.squeeze(costs))
    plt.ylabel('cost')
    plt.xlabel('iterations (per tens)')
    plt.title("Learning rate =" + str(learning_rate))
    plt.show()

    return parameters

layers_dims = #These values are custom example:[12288, 20, 7, 5, 1]
parameters = L_layer_model(train_x, train_y, layers_dims, num_iterations=2500, print_cost=True)

print("Train Accuracy:")
pred_train = predict(train_x, train_y, parameters)

print("Test Accuracy:")
pred_test = predict(test_x, test_y, parameters)

#Running on unseen image
import cv2
image = cv2.imread("/content/test.jpeg")

image=cv2.resize(image, (64,64))
image=np.reshape(image,(12288,1))
image=image/255

my_label_y = [0]

my_predicted_image = predict(image, my_label_y, parameters)

print ("y = " + str(np.squeeze(my_predicted_image)) + ", your L-layer model predicts a \"" + classes[int(np.squeeze(my_predicted_image)),].decode("utf-8") +  "\" picture.")
from IPython.display import Image
Image(filename='/content/test.jpeg')


import numpy as np
from numpy.linalg import norm
from util.merge_Tucker import merge_Tucker
from util.t2m import t2m
from util.m2t import m2t

def hosvd(X, rank, max_iter=1, err_tol=1, track_fval=False):
    ''' Higher Order Singular Value Decomposition.
    Takes the HOSVD of tensor input.

    Parameters:
    ---
        X: Data tensor

        rank: Aimed ranks for the resulting tensor.

        max_iter: Number of iterations. If 1, HOSVD will be applied, otherwise
            HOOI will be run.

        err_tol: Error tolerance. Not relevant for HOSVD.

    Returns:
    ---
        Y: Tensor with ranks `rank`at each mode unfolding.
        U_list: List of factor matrices of HOSVD.
    '''
    sizes = X.shape
    sizes_core = list(sizes)
    n = len(sizes)
    U_list = [np.eye(sizes[i]) for i in range(n)]
    Y = X.copy()

    iter = 0
    change = np.inf
    err_tot = []
    val_change = []
    while iter < max_iter and change > err_tol:
        Y_old = Y.copy()
        for i in range(n):
            ind = np.setdiff1d(np.arange(n), i)
            U_other = [U_list[j] for j in ind]
            C = merge_Tucker(X, U_other, ind, transpose=True)
            U, S, _ = np.linalg.svd(t2m(C, i), full_matrices=False)
            ind = np.argsort(S)[::-1]
            ind = ind[:rank[i]]
            U_list[i] = U[:, ind]
            sizes_core[i] = rank[i]

        C = m2t(U_list[-1].transpose()@t2m(C, n-1), sizes_core, n-1)
        Y = merge_Tucker(C, U_list, np.arange(n))

        change = norm(Y-Y_old)**2
        if track_fval:
            val_change.append(change)
            err_tot.append(norm(Y-X)**2)

        iter += 1

    return Y, U_list, err_tot, val_change


# Optimization Course - Lecture 1 Exercise 1 using PYOMO
# Author: Íngrid Munné-Collado
# Date: 07/01/2021
# code based on https://www.youtube.com/watch?v=hTKa7Qc38b4&t=184s

# Requirements: Install pyomo, glpk and gurobi. You should apply for an academic license in gurobi
from pyomo.environ import *
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
import pandas as pd
import numpy as np

# Read import data

# Creating the model
model = AbstractModel()
""" This is useful because everything we define as a model will be the equations.
All data used to solve the model will come in a different file"""

# Defining Sets
model.plantas = Set()
model.mercados = Set()

# Defining Parameters for each set
model.produccion = Param(model.plantas)
model.demanda = Param(model.mercados)
model.costes = Param(model.plantas, model.mercados)

# Defining variables
model.unidades = Var(model.plantas, model.mercados, within = NonNegativeReals)

# Defining ObjectiveFunction in an abstract way
def CosteTotal(model):
    return sum(model.costes[n,i] * model.unidades[n,i]
               for n in model.plantas
               for i in model.mercados)

model.costefinal = Objective(rule=CosteTotal)
# here we are saying that we will save the value of the OF defined previously in
# this variable of the model.

# Defining constraints
def MinDemanda(model, mercado): #it depends on model and each of the markets
    return sum(model.unidades[i,mercado] for i in model.plantas) >= model.demanda[mercado]

model.DemandaConstraint = Constraint(model.mercados, rule=MinDemanda)

def MaxProduccion(model, planta):
        return sum(model.unidades[planta, j] for j in model.mercados) <= model.produccion[planta]
model.ProdConstraint = Constraint(model.plantas, rule=MaxProduccion)

## in order to solve the problem we have to run this command in a terminal prompt
## pyomo solve --solver=glpk Transport_problem_example_pyomo.py datos.dat


import numpy as np

class KMeans:
    def __init__(self, k: int, max_iterations=100):
        self.k = k
        self.max_iterations = max_iterations
        self.centroids = None

    def fit(self, dataset):
        x = dataset.X
        self._min = np.min(x, axis=0)
        self._max = np.max(x, axis=0)

    def init_centroids(self):
        self.centroids = np.array([np.random.uniform(low=self._min, high=self._max) for i in range(self.k)])

    def init_centroids_random_points(self, X):
        rng = np.random.default_rng()
        self.centroids = rng.choice(X, self.k)
        return self.centroids

    def distance(self, x, centroids):
        return np.sqrt(((centroids-x)**2).sum(axis=1))

    def get_closest_centroids(self, x):
        dist = self.distance(x, self.centroids)
        closest_centroid_index = np.argmin(dist, axis=0)
        return closest_centroid_index

    def transform(self, dataset):
        X = dataset.X
        changed = True
        count = 0
        old_idxs = np.zeros(X.shape[0])
        self.init_centroids_random_points(X)
        while changed and count < self.max_iterations:
            # array of indexes of nearest centroid
            idxs = np.apply_along_axis(self.get_closest_centroids, axis=1, arr=X)
            cent = [np.mean(X[idxs == i], axis=0) for i in range(self.k)]
            self.centroids = np.array(cent)
            changed = np.all(old_idxs == idxs)
            old_idxs = idxs
            count += 1
        return self.centroids, idxs

    def fit_transform(self, dataset):
        self.fit(dataset)
        return self.transform(dataset)


from ast import AST
from arboles import *
from genetic_algorithm import Individual, Population
import matplotlib.pyplot as plt
import math
import random
import numpy as np

random.seed(16)
ITERATIONS = 1000

# gene function and fitness function to evaluate and evolve a finder of the number 10
tree10 = AST([AddNode, SubNode, MultNode], [2, 3, 5])
def fitness_10(ind):
    score = ind.genes.eval()
    return math.exp(-((score - 10) ** 2) / 100)

# gene function and fitness function to evaluate and evolve a finder of the number 65346
tree65346 = AST([AddNode, SubNode, MultNode, MaxNode], [25, 7, 8, 100, 4, 2])
def fitness_65346(ind):
    score = ind.genes.eval()
    return math.exp(-((score - 65346) ** 2) / 1000000)

# gene function and fitness function to evaluate and evolve a finder of the number 65346
# that limits the number of nodes on the tree and gives better score to trees with less nodes
def fitness_65346_short(ind):
    score = ind.genes.eval()
    score_fitness = math.exp(-((score - 65346) ** 2) / 1000000)
    tree_number_of_nodes = len(ind.genes.serialize())
    number_of_nodes_fitness = (50 - tree_number_of_nodes) / 50 if tree_number_of_nodes <= 50 else 0
    return (score_fitness * 9  + number_of_nodes_fitness) / 10  if score_fitness != 1 else 1

# gene function and fitness function to evaluate and evolve a finder of the number 65346
# with no repetition on the terminal nodes
tree_no_repetition = AST([AddNode, SubNode, MultNode], [25, 7, 8, 100, 4, 2])
def fitness_no_repetition(ind):
    score = ind.genes.eval()
    nodes = ind.genes.serialize()
    # making a list with only terminal nodes
    terminal_nodes = [x.eval() for x in nodes if isinstance(x, TerminalNode)]
    # checking if there are no repeated nodes
    if len(terminal_nodes) == len(set(terminal_nodes)):
        score_fitness = math.exp(-((score - 65346) ** 2) / 100000000)
        return score_fitness
    else: return 0

# gene function and fitness function to evaluate and evolve an equation finder of
# x² + x - 6
number_list = list(range(-10, 11))
number_list.extend(['x'] * 20)
tree_symbolic = AST([AddNode, SubNode, MultNode], number_list)
def fitness_symbolic(ind):
    def func(x):
        return x ** 2 + x - 6
    fitness_func = np.zeros(201)
    fitness_eval = np.zeros(201)
    # calculates the function directly and with the evaluation function of the tree
    for i in range(-100, 101):
        fitness_func[i + 100] = func(i)
        fitness_eval[i + 100] = ind.genes.eval({'x': i})
    # calculating the mean square error and converting it to an appropiate fitness function
    fitness_error = ((fitness_func - fitness_eval) ** 2).mean()
    return 1 / (1 + fitness_error)

# gene function and fitness function to evaluate and evolve an equation finder of
# (x + 3) / 3
tree_division = AST([AddNode, SubNode, MultNode, DivNode], number_list)
def fitness_division(ind):
    def func(x):
        return (x + 3) / 3
    fitness_func = np.zeros(201)
    fitness_eval = np.zeros(201)
    # catching divisions by zero
    try:
        for i in range(-100, 101):
            fitness_func[i + 100] = func(i)
            fitness_eval[i + 100] = ind.genes.eval({'x': i})
        fitness_error = ((fitness_func - fitness_eval) ** 2).mean()
        return 1 / (1 + fitness_error)
    except ZeroDivisionError:
        return 0

# method to run each example
def run_exercise(fitness_func, gen_func, pop_size, mut_rate, title):
    pop = Population(pop_size, mut_rate, fitness_func, print)
    pop.generate_individuals(gen_func)
    y1, y2, y3 = pop.evolve(iterations=ITERATIONS, fitness_limit=1)
    plt.plot(range(pop.generation - 1), y1)
    plt.plot(range(pop.generation - 1), y2)
    plt.plot(range(pop.generation - 1), y3)
    plt.title(title)
    plt.legend(["minimum fitness", "average fitness", "maximum fitness"], loc=2)
    plt.ylabel("fitness")
    plt.xlabel("generation")
    plt.show()

if __name__ == "__main__":
    # To select which example to run
    option = input("Select example tu run:\n(1) Find number 10\n(2) Find number 65346\n(3) Find number 65346 (short trees version) \
        \n(4) Find number 65346 with no repetition in terminal nodes\n(5) Find equation x²+x-6\n(6) Find equation (x+3)/3\n")
    if option == '1':
        run_exercise(fitness_10, tree10, 10, 0.3, "Finding number 10")
    elif option == '2':
        run_exercise(fitness_65346, tree65346, 150, 0.3, "Finding number 65346")
    elif option == '3':
        run_exercise(fitness_65346_short, tree10, 150, 0.4, "Finding number 65346 (short trees)")
    elif option == '4':
        run_exercise(fitness_no_repetition, tree_no_repetition, 100, 0.5, "Finding number 65346 (no repetition)")
    elif option == '5':
        run_exercise(fitness_symbolic, tree_symbolic, 50, 0.1, "Finding x²+x-6")
    elif option == '6':
        run_exercise(fitness_division, tree_division, 50, 0.1, "Finding (x+3)/3")


import numpy as np
import ista
import utils

X = np.array([[2, 0, 0], [0, 1, 0]]).T
y = np.array([3, 2, 2])

lambd = 6

def f(w):
    return 0.5*np.sum((X@w - y)**2) + lambd * np.linalg.norm(w, ord=1)

w0 = 0.5 * np.ones(2)
stepsize = 0.1

w_traces = ista.ista(X, y, lambd, w0, stepsize=stepsize, tol=1e-9)

f_value = f(w_traces[-1])

print()
print('lambda =', lambd)
print('number of iterations:', len(w_traces)-1)
print('solution:', w_traces[-1])
print('value:', f_value)
print()

# visualization
Q = X.T@X
b = X.T@y
c = y@y

def f_2d(w1, w2):
    return 0.5 * Q[0, 0] * w1**2 + 0.5 * Q[1, 1] * w2**2 + Q[0, 1] * w1 * w2 \
        - b[0] * w1 - b[1] * w2 - 0.5 * c + lambd * (np.abs(w1) + np.abs(w2))

def gap(w):
    return f(w) - f_value

path = 'figures/4/'
utils.plot_traces_2d(f_2d, w_traces, path+f'ista_traces_lambda{lambd}.png')
utils.plot(gap, w_traces, path+f'ista_gap_lambda{lambd}.png')


import numpy as np

def vec_mse(y, y_hat):
    if type(y) != np.ndarray or type(y_hat) != np.ndarray:
        return None
    if y.shape != y_hat.shape or len(y.shape) != 1:
        return None
    return np.dot(y_hat - y, y_hat - y) / y.size

if __name__ == "__main__":
    X = np.array([0, 15, -9, 7, 12, 3, -21])
    Y = np.array([2, 14, -13, 5, 12, 4, -19])

    print(vec_mse(X, Y))
    print(vec_mse(X, X))


import numpy as np

"""
Version 1.0
Last Updated 12/09/2014

"""

def rsl_get_groundr_and_h(slant_r, elev):

    """
Author: Timothy Lang (timothy.j.lang@nasa.gov)
Given slant range and elevation, return ground range and height.

Inputs
  slant_r  slant range (km)
  elev     elevation (deg)

Outputs
  gr    ground range (km)
  h     height above radar (km)

This Python function is adapted from the Radar Software Library routine
RSL_get_groundr_and_h, written by John Merritt and Dennis Flanigan

    """

    Re = 4.0/3.0 * 6371.1  # Effective earth radius in km.
    h = np.sqrt(Re**2 + slant_r**2 - 2.0 * Re * slant_r *
                np.cos((elev + 90.0) * np.pi / 180.0))
    gr = Re * np.arccos((Re**2 + h**2 - slant_r**2) / (2.0 * Re * h))
    h = h - Re
    return gr, h

###################################################

def rsl_get_slantr_and_elev(gr, h):

    """
Author: Timothy Lang (timothy.j.lang@nasa.gov)
Given ground range and height, return slant range and elevation.

Inputs
  gr  ground range (km)
  h   height (km)

Outputs
  slantr    slant range
  elev      elevation in degrees

This Python function is adapted from the Radar Software Library routine
RSL_get_slantr_and_elev, written by John Merritt and Dennis Flanigan

    """

    Re = 4.0/3.0 * 6371.1  # Effective earth radius in km.
    rh = h + Re
    slantrsq = Re**2 + rh**2 - (2 * Re * rh * np.cos(gr/Re))
    slantr = np.sqrt(slantrsq)
    elev = np.arccos((Re**2 + slantrsq - rh**2)/(2 * Re * slantr))
    elev = elev * 180.0/np.pi
    elev = elev - 90.0
    return slantr, elev


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
import gym
from gym import wrappers
from time import sleep

class ValueIteration:
    def __init__(self, env, gamma=0.8):
        self.env = env
        self.pi = np.random.choice(env.nA, env.nS)
        self.v = np.zeros(env.nS)
        self.gamma = gamma

    def value_iteration(self):
        v = self.v.copy()
        for s in range(self.env.nS):
            q_sa = np.zeros(self.env.nA)
            for a in range(self.env.nA):
                q_sa[a] = sum([p * (r + self.gamma * self.v[s_]) for p, s_, r, _ in self.env.P[s][a]])

            v[s] = np.max(q_sa)

        return v

    def get_optimal_policy(self):
        for s in range(self.env.nS):
            q_sa = np.zeros(self.env.nA)
            for a in range(self.env.nA):
                q_sa[a] = sum([p * (r + self.gamma * self.v[s_]) for p, s_, r, _ in self.env.P[s][a]])

            self.pi[s] = np.argmax(q_sa)

        return self.pi

    def iterate(self):
        n = 200000
        eps = 1e-20
        for i in range(n):
            v_new = self.value_iteration()

            if (np.all(self.v == v_new)):
                print('Value-Iteration converged at step %d.' %(i+1))
                break

            self.v = v_new

        return self.get_optimal_policy()

    def run_episode(self, render = False, key = False, wait = 0.0):
        obs = self.env.reset()
        total_reward = 0
        step_idx = 0
        while True:
            if render:
                self.env.render()
                if key:
                    temp_key = input('')
                elif wait > 0.0:
                    sleep(wait)

            obs, reward, done , _ = self.env.step(int(self.pi[obs]))
            total_reward += (self.gamma ** step_idx * reward)
            step_idx += 1
            if done:
                break
        return total_reward

if __name__ == '__main__':
    env = gym.make("FrozenLake8x8-v0")
    env = env.unwrapped
    gamma = 0.8
    value_iteration = ValueIteration(env, gamma)

    # random policy
    k = input('run 1 episode with ramdom policy?')
    score = value_iteration.run_episode(True, False, 0.1)
    print('score(random policy) = ', score)

    # policy iteration
    value_iteration.iterate()

    # 1 episode
    k = input('run 1 episode with value iteration?')
    score = value_iteration.run_episode(True, False, 0.1)
    print('score(value iteration, 1 episode) = ', score)

    # multiple episodes
    k = input('run 100 episodes with policy iteration?')
    scores = [value_iteration.run_episode(False) for _ in range(100)]
    score = np.mean(scores)
    print('Average score(value iteration, 100 episodes) = ', score)


import os as _os
on_rtd = _os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd:
    import numpy as _np

def chisquare(observe, expect, error, ddof, verbose=True):
    """
    Finds the reduced chi square difference of *observe* and *expect* with a given *error* and *ddof* degrees of freedom.

    *verbose* flag determines if the reduced chi square is printed to the terminal.
    """
    chisq = 0
    error   = error.flatten()
    observe = observe.flatten()
    expect  = expect.flatten()
    for i, el in enumerate(observe):
        chisq = chisq + _np.power((el - expect[i]) / error[i], 2)

    red_chisq = chisq / (len(observe) - ddof)
    if verbose:
        # print 'Chi-Squared is {}.'.format(chisq)
        print('Reduced Chi-Squared is {}.'.format(red_chisq))

    return red_chisq


"""活性化関数
"""

import numpy as np

def step(x):
    """
    ステップ関数

    Args:
        x(np.array): 入力値

    Returns: 活性化関数によって変換した出力値

    """
    # xの要素が0より大ならTrue/そうでなければFalseに変換
    y = x > 0

    # Trueを1, Falseを0のフラグに変換
    return y.astype(np.int)

def sigmoid(x):
    """
    シグモイド関数

    Args:
        x(np.array): 入力値

    Returns: 活性化関数によって変換した出力値

    """
    return 1 / (1 + np.exp(-x))

def relu(x):
    """
    ReLU関数

    Args:
        x(np.array): 入力値

    Returns: 活性化関数によって変換した出力値

    """
    return np.maximum(0, x)  # xと0の大きい方を返す

def identity(x):
    """
    恒等関数

    Args:
        x(np.array): 入力値

    Returns: 入力値と同じ配列

    """
    return x

def softmax(x):
    """

    Args:
        x(np.array): 入力値

    Returns: 入力信号をSoftmaxで変換した配列

    """
    c = np.max(x)

    exp_x = np.exp(x - c)  # オーバーフロー対策
    sum_exp_x = np.sum(exp_x)

    y = exp_x / sum_exp_x

    return y


from __future__ import division
import sys
import operator as op
#import scipy.misc as sm

#def binomialCoeff(n, r):
#    r = min(r, n-r)
#    if r == 0: return 1
#    numer = reduce(op.mul, xrange(n, n-r, -1))
#    denom = reduce(op.mul, xrange(1, r+1))
#    return numer//denom

#def k_permute(n, k):
#    """
#    Compute nPk, i.e., n!/(n-k)!
#    """
#    res = 1
#    for i in xrange(n-k+1, n+1):
#        res *= i
#    return res

def binomialCoeff(n , k):
    """
    Python program for Optimized Dynamic Programming solution to
    Binomail Coefficient. This one uses the concept of pascal
    Triangle and less memory
    """
    # Declaring an empty array
    C = [0 for i in xrange(k+1)]
    C[0] = 1 #since nC0 is 1

    for i in range(1,n+1):

        # Compute next row of pascal triangle using
        # the previous row
        j = min(i ,k)
        while (j>0):
            C[j] = C[j] + C[j-1]
            j -= 1

    return C[k]

def distribute_over_bins_no_empty(k, b):
    """
    This function returns the number of ways that k elements can be distributed
    over b bins such that no bin is empty.
    """
    if k < b: return 0
    if b == 1: return 1
    tot = b ** k
    for i in xrange(1,b):
        tot -= binomialCoeff(b, i) * distribute_over_bins_no_empty(k, i)
    return tot

def probability_page_num_exactly(i, n, k):
    """
    This function computes the probability that distributing k elements
    uniformly at random over n pages exactly i pages are used.
    """
    if i > n: return 0
    return (binomialCoeff(n, i) * distribute_over_bins_no_empty(k, i)) / (n ** k)

def expected_page_num(n, k):
    """
    This function computes the expected number of pages (out of n) unto which
    k records would be distributed, with the records being distributed
    according to a uniform distribution (i.i.d.)
    """
    tot = 0
    for i in xrange(1,k+1):
        tot += i * probability_page_num_exactly(i, n, k)
    return tot

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: " + sys.argv[0] + " n k")
        sys.exit(1)
    else:
        n = int(sys.argv[1])
        k = int(sys.argv[2])
        res = expected_page_num(n,k)
        print(res)


# from mpl_toolkits.mplot3d import Axes3D i do not see that it is needed
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np

fig = plt.figure() # return matplotlib.figure.Figure instance
ax = fig.gca(projection='3d') #Get current axes, creating one if necessary.

# Make data.
X = np.arange(-5, 5, 0.25) # shape (40,0)
Y = np.arange(-5, 5, 0.25) # shape (40,0)
X, Y = np.meshgrid(X, Y) # following the mesh X.shape is (40,40) and Y.shape is (40,40)
R = np.sqrt(X**2 + Y**2) # R.shape is 40,40
Z = np.sin(R) # R.shape is 40,40

# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)

# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()


import numpy as np

from . import modulus
from .types import Fp

def inverse_el(el: Fp, p: int) -> Fp:
    """Compute the inverse of an element over Fp

    Args:
        el (Fp): An element in Fp
        p (int): A prime number

    Returns:
        Fp: The inverse of the element over Fp
    """
    return pow(int(el), p-2, p)

def inverse_poly(poly: np.poly1d, p: int, mod_poly: np.poly1d) -> np.poly1d:
    """Compute the inverse of an element over Fpn.

    Args:
        poly (np.poly1d): An element in Fpn
        p (int): A prime number.
        mod_poly (np.poly1d): An monic irreducible polynomial.

    Returns:
        np.poly1d: The inverse of the element over Fpn.
    """
    if len(poly.coeffs) == 1:
        inverse_of_el = inverse_el(poly.coeffs[0], p)
        return np.poly1d(np.array([inverse_of_el]))

    return modulus.modulus_pow_poly(poly,
                                    p**(len(mod_poly.coeffs)-1)-2, p, mod_poly)


from sympy.utilities.lambdify import lambdify
import sympy.parsing.sympy_parser as symp
import sympy.abc
import numpy as np

class ScalarTransferFunction(object):
    def __init__(self, transfer_function_string, symbol=sympy.abc.s):
        self.symbol = symbol
        self.transfer_function_string = transfer_function_string
        self.closure = lambdify(self.symbol, symp.parse_expr(self.transfer_function_string), modules=['sympy'])

    def __call__(self, s):
        return self.closure(s)

    def to_dict(self):
        return {'class': (__name__, self.__class__.__name__), 'function': self.transfer_function_string}

    def imshow(self, rates, times=None, show=True):
        import matplotlib.pyplot as plt

        vals = [self(rate) for rate in rates]
        times = np.linspace(0.0, 1.0, len(rates)) if times is None else times

        fig, ax1 = plt.subplots()
        ax1.set_xlabel('time (seconds)')
        ax1.set_ylabel(str(self.symbol), color='b')
        ax1.plot(times, rates, '--b')
        ax1.tick_params(axis='y', labelcolor='b')

        ax2 = ax1.twinx()
        ax2.set_ylabel('transform', color='r')
        ax2.plot(times, vals, 'r')
        ax2.tick_params(axis='y', labelcolor='r')

        plt.title(self.transfer_function_string)
        if show:
            plt.show()

class MultiTransferFunction(object):
    def __init__(self, symbol_tuple, transfer_function_string):
        self.symbol_tuple = symbol_tuple
        self.transfer_function_string = transfer_function_string
        self.closure = lambdify(self.symbol_tuple, symp.parse_expr(self.transfer_function_string), modules=['sympy'])

    def __call__(self, *s):
        if isinstance(s[0], (float,)):
            return self.closure(*s)
        else:
            return np.array(list(map(lambda x: self.closure(*x), zip(*s))))

    def to_dict(self):
        return {'class': (__name__, self.__class__.__name__), 'function': self.transfer_function_string}


# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

# Curve-fit y around the peak to find subpixel peak x
def quadraticpeak(y, x=None, npts=7, plotTitle=None):
    if x is None:
        x = np.arange(len(y))
    xmax = np.argmax(y)
    W = int((npts + 1) / 2)
    window = np.arange(xmax - W + 1, xmax + W)
    window = np.clip(window, 0, len(x) - 1)
    coeff = np.polyfit(x[window], y[window], 2)

    if plotTitle:
        plt.figure()
        plt.plot(x[window], y[window], label="fit")
        sx = np.linspace(x[xmax - W], x[xmax + W], 100)
        plt.plot(sx, np.polyval(coeff, sx), label="fit")
        plt.legend()
        plt.title(plotTitle)

    return -coeff[1] / (2 * coeff[0])

if __name__ == "__main__":

    x = np.arange(100)
    max = 50
    y = -(x - max) ** 2 + np.random.uniform(-5, 5, size=len(x))

    plt.figure()
    plt.plot(x, y)
    print(quadraticpeak(y, x, npts=12, plotTitle="Fit"))


from scipy.spatial.distance import pdist, squareform
from scipy import exp
from scipy.linalg import eigh
import numpy as np
from sklearn.datasets import make_moons

'''
Author: Ankur Wasnik
Date 	: Jan 24 0632
Kernel RBF(radial basis function) custom implementation
'''

def rbf_kernel_pca(X , gamma , n_components):
	#1.Calculate pairwise squared euclidean distance
	sq_dist = pdist(X,'sqeuclidean')
	#2.Convert pairwise distance into square matrix
	sq_mat = squareform(sq_dist)
	#3.Compute the kernel square matrix
	K =np.exp(-gamma*sq_mat)
	#4.Center the kernel matrix
	#Most important step
	N = K.shape[0]
	one_n = np.ones((N,N))/N
	K = K -one_n.dot(K) -K.dot(one_n) + one_n.dot(K).dot(one_n)
	#5.Obtaining the eigenvalues and eigenvectors
	eigvals, eigvecs = eigh(K)
	eigvals , eigvecs = eigvals[:,:,-1] , eigvecs[:,:,-1]
	#6.Collect top K eigenvectors
	k_eigv = np.column_stack([eigvals[:,i] for i in range(n_components)])

	return k_eigv

'''
Implementing the kernel rbf to solve half-moon shapes
'''
if __name__=='__main__' :
	X,y = make_moons(n_samples=100 , random_state=69)
	#1.visualizing data
	import matplotlib.pyplot as plt
	plt.scatter(X[y==0,0] , X[y==0,1])
	plt.scatter(X[y==1,0] , X[y==1,1])
	plt.tight_layout()
	plt.show()
	#2.Apply kernel rbf to data
	X_krbf = rbf_kernel_pca(X=X , gamma=15 , n_components=2)
	#3.Visualize reduced data
	fig,ax = plt.subplots(nrows=1,ncols=2)
	ax[0] = plt.scatter(X_krbf[y==0,0],[X_krbf[y==0,1]])
	ax[0] = plt.scatter(X_krbf[y==1,0],[X_krbf[y==1,1]])
	ax[1] = plt.scatter(X_krbf[y==0,0],np.zeros((50,1))+0.02)
	ax[1] = plt.scatter(X_krbf[y==1,0],np.zeros((50,1))-0.02)
	ax[0].set_xlabel('PC1')
	ax[0].set_ylabel('PC2')
	ax[1].set_xlabel('PC1')
	ax[1].set_ylabel('PC2')
	plt.tight_layout()
	plt.show()


import numpy as np
from sklearn import metrics
from sklearn.preprocessing import StandardScaler

class LinearRegression:

    def __init__(self, fit_intercept=True, normalize=False):
        self.coefs_ = None
        self.intercept_ = None
        self.fit_intercept = fit_intercept
        self.normalize = normalize
        self.scaler = StandardScaler()

    def add_constant(self, X):
        return np.c_[X, np.ones(X.shape[0])]

    def fit(self, X, y):
        """
        Returns coefficients b1, b0 of an equation of the form y = b1.x + b0
        which is the least squares solution providing the line of best fit
        :param x: numpy array, representing independent features
        :param y: numpy array, representing dependent feature
        :return:
        """
        if self.fit_intercept:
            X = self.add_constant(X)
        if self.normalize:
            X = self.scaler.fit_transform(X)
        b = (np.linalg.inv(X.T.dot(X)).dot(X.T)).dot(y)
        self.coefs_ = b[:-1]
        self.intercept_ = b[-1]
        return self

    def predict(self, test):
        """
        Return predictions for fitted model
        :param test: numpy array of set of test features
        :return: numpy array of predictions
        """
        if not all(self.coefs_):
            raise ValueError("Fit the model before predicting")
        if self.normalize:
            test = self.scaler.transform()
        predictions = test.dot(self.coefs_) + self.intercept_
        return predictions

    def score(self, actuals, predictions):
        """
        Returns R-squared score for the fitted model
        :param actuals: Matrix of dependent feature
        :param predictions: Matrix of predictions
        :return: R-squared score
        """
        rss = np.square(predictions-actuals).sum()
        tss = np.square(actuals - actuals.mean()).sum()
        r2 = 1 - rss/tss
        return r2

if __name__ == '__main__':
    x = np.random.rand(100, 5)
    actual_coeffs = np.array([4.5, 5.2, 3.7, 9.1, 6.8])
    y = np.array((x * actual_coeffs).sum(axis=1) + 5).reshape(-1, 1)
    print(y.shape, x.shape)
    linear_reg = LinearRegression()
    linear_reg.fit(x, y)
    x_test = np.random.rand(10, 5)
    y_test = np.array((x_test * actual_coeffs).sum(axis=1) + 5).reshape(-1, 1)
    print(linear_reg.coefs_)
    y_pred = linear_reg.predict(x_test)
    err = (abs(y_test - y_pred)/y_test).mean()
    print(err)
    actual_r2 = metrics.r2_score(y_test, y_pred)
    our_r2 = linear_reg.score(y_test, y_pred)
    print(actual_r2, our_r2)


import numpy as np

matriz = np.array(([10, 3, -2],
                   [2, 8, -1],
                   [1, 1, 5]))

vetorb = np.array(([57, 20, -4]))

# 1x + 1y = 3
# 1x - 3y = -3

# Decompor a Matriz, Identidade(D), Triangular_inferior(E), Triangular_superior(F)
dim = len(matriz)
D = np.zeros((dim, dim)) # Diagonal
F = np.zeros((dim, dim)) # Triangular_superior
E = np.zeros((dim, dim)) # Triangular_inferior
for i in range(0, len(matriz)):
    D[i][i] = matriz[i][i]

for i in range(0, len(matriz)):
    for j in range(i+1, len(matriz)):
        F[i][j] = matriz[i][j]

for i in range(0, len(matriz)):
    for j in range(0, i):
        E[i][j] = matriz[i][j]

E *= -1  # (-E) pois A = D (-E) -F
F *= -1  # (-F) pois A = D -E (-F)

E_F = E+F
matriz_j = np.linalg.inv(D)   # D^(-1)
matriz_j = matriz_j.dot(E_F)  # matriz_j = np.linalg.inv(D).dot(E_F)

# Temos a matriz de jacob

# calcula o c(e uma constante), c = D^(-1)*b -> c = D^(-1)*vetorb
c = np.linalg.inv(D).dot(vetorb)

# iniciando o x Na origem [0,..,0]
x = np.zeros((dim))

#  primeira interacao
x = matriz_j.dot(x)+c
x_anterior = x
# print(x)

#  segunda interacao
x = matriz_j.dot(x) + c
# print(x)

vetor = np.zeros((dim))

for i in range(0, dim):
    vetor[i] = x[i] - x_anterior[i]

# print(vetor)

modulo = 0

for i in range(0, dim):
   modulo += np.absolute(vetor[i])

modulo = modulo ** (1 / 2)
# print(modulo)
ki = 1
#print(f"primeira interacao {x}")
while modulo > 0.00001:
    modulo = 0
    x_anterior = x
    x = matriz_j.dot(x) + c
    ki+=1
    vetor = np.zeros((dim))
    for i in range(0, dim):
        vetor[i] = x[i] - x_anterior[i]
    for i in range(0, dim):
        modulo += np.absolute(vetor[i])
    modulo = modulo ** (1 / 2)
print(f"Interacoes {ki}")
print(np.round(x, 4))


import numpy as np
from scipy.sparse import issparse

from ya_pca.linalg_utils import svd_wrapper

def select_rank_variance_explained(X, q=0.95, svals=None):
    """
    Selects the PCA rank by finding the components which explains the desired amount of variance.

    Parameters
    ----------
    X: array-like, (n_samples, n_features)

    q: float
        The desired percent of variance to be explained

    svals: array-like, None
        (Optional) Precomputed singular values.

    Output
    ------
    rank_est, out

    rank_est: int
        Estimated rank

    out: dict
        All output from rank selection algorithm.
    """

    if svals is None:
        svals = svd_wrapper(X)[1]

    tot_variance = safe_frob_norm(X) ** 2
    var_expl_prop = svals ** 2 / tot_variance

    assert np.allclose(var_expl_prop.sum(), 1)

    var_expl_cum = np.cumsum(var_expl_prop)
    rank_est = np.where(var_expl_cum > q)[0].min()

    return rank_est, {'tot_variance': tot_variance,
                      'var_expl_prop': var_expl_prop,
                      'var_expl_cum': var_expl_cum}

def safe_frob_norm(X):
    """
    Calculates the Frobenius norm of X whether X is dense or sparse.

    Currently, neither scipy.linalg.norm nor numpy.linalg.norm work for
    sparse matrices.
    """
    if issparse(X):
        return np.sqrt(sum(X.data ** 2))
    else:
        return np.linalg.norm(np.array(X), ord='fro')


#!/usr/bin/python

# Project Euler Problem 7
# Which starting number, under one million, produces the longest Collatz chain?
# Holly Becker

# The following iterative sequence is defined for the set of positive integers:

# n -> n/2 (n is even)
# n -> 3n + 1 (n is odd)

# Using the rule above and starting with 13, we generate the following sequence:
# 13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

# It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

# Which starting number, under one million, produces the longest chain?

# NOTE: Once the chain starts the terms are allowed to go above one million.

#import networkx as nx
# Add numbers in a sequence to a graph, pointing to it's next neighbour

def collatz(n):
    if n % 2 == 0: # even
        return n/2
    else:
        return 3*n+1

# ~5 sec
def first_try(maximum):
    # Make graph of collatz chains
    collatz_graph = {} # number: next in chain
    for current in range(2, maximum):
        next = collatz(current)
        # Generate chain
        while current > 1:
            if current not in collatz_graph:
                collatz_graph[current] = next
            else: # We've already calculated the rest of the chain
                break
            current, next = next, collatz(next)

    def get_length(start):
        length = 1
        while collatz_graph[start] > 1:
            # Memoize!
            if start not in collatz_length:
                length += 1
                start = collatz_graph[start]
            else: # We already know the length of the rest
                return length + collatz_length[start]
        return length

    # Find all the lengths
    collatz_length = {1: 1} # start number: length
    for start in range(2, maximum):
        if start not in collatz_length:
            collatz_length[start] = get_length(start)

    longest = max(collatz_length, key=collatz_length.get)
    print(("Chain starting at %d is length %d." % (longest, collatz_length[longest])))

if __name__ == '__main__':
    first_try(1000000)


#!/bin/env python
import numpy as np
import matplotlib.pyplot as plt
import sys, os
import argparse

def uqi(x,y):
    """A Universal Image Quality Index, named Q."""
    x = np.array([float(i) for i in x])
    y = np.array([float(i) for i in y])
    cov = np.cov(x,y)
    a_var = cov[0][0]
    b_var = cov[1][1]
    ab_cov = cov[0][1]
    uqi = (       (4 * ab_cov * x.mean() * y.mean() )
        / ((a_var + b_var) * (x.mean() ** 2 + y.mean() ** 2))
        )
    return uqi

def rmse(x,y):
    x = np.array([float(i) for i in x])
    y = np.array([float(i) for i in y])
    return np.sqrt(((x - y) ** 2).mean())

def nrmse(x,y):
    """normalized root-mean-square deviation or error"""
    x = np.array([float(i) for i in x])
    y = np.array([float(i) for i in y])
    nrmse = np.sqrt(((x - y) ** 2).mean())/y.mean()
    return nrmse

def vs_fig(x,y,filename=None,title=None,xlabel=None,ylabel=None,M=None,m=None):
#    font = {'family': 'serif',
#            'color':  'darkred',
#            'weight': 'normal',
#            'size': 16,
#            }
    x = np.array([float(i) for i in x])
    y = np.array([float(i) for i in y])
    fig, ax = plt.subplots()
    ax.scatter(x, y, s=2,color='red',zorder=10)
    lims = [np.min([ax.get_xlim(), ax.get_ylim()]),
            np.max([ax.get_xlim(), ax.get_ylim()]),]
    if M:lims[1]= M
    if m:lims[0]= m
    ax.plot(lims, lims, 'k-', alpha=0.75, zorder=0)
    ax.set_aspect('equal')
    ax.set_xlim(lims)
    ax.set_ylim(lims)
    xynrmse = nrmse(x,y)
    xyrmse = rmse(x,y)
    xyuqi = uqi(x,y)
    #text = "NRMSE:%f\nRMSE:%f\nUQI:%f\n"%(xynrmse,xyrmse,xyuqi)
    text = "RMSE:%f\nUQI:%f\n"%(xyrmse,xyuqi)
    ax.text(.9, .25, text,
            horizontalalignment='right',
            verticalalignment='top',
            transform=ax.transAxes)
    if title:
        ax.set_title(title)
    if xlabel:
        ax.set_xlabel(xlabel)
    if ylabel:
        ax.set_ylabel(ylabel)
    if filename:
        fig.savefig(filename,dpi=300)
        with open(filename+'.log',"w") as f:
            f.write("fig:%s\n"%(title))
            f.write("NRMSE:%f  normalized root-mean-square deviation or error.\n"%(xynrmse))
            f.write(" RMSE:%f  root-mean-square deviation or error.\n"%(xyrmse))
            f.write("  UQI:%f  A Universal Image Quality Index.\n"%(xyuqi))
    else:
        return fig, ax

def getdata(input_filename):
    MAX_COLS = 20
    data = [ [] for i in range(MAX_COLS)]
    with open(input_filename) as f:
        for i in f:
            if i[0] == '#':continue
            dat = i.split()
            for idx, num in enumerate(dat):
                data[idx].append(num)
    return data

def argparser():
    usage = ("To draw a fig vs 2 cols.")
    parser = argparse.ArgumentParser(description=usage)
    parser.add_argument('-f', help="input file.")
    import tempfile
    tf = tempfile.NamedTemporaryFile(prefix="fig.", suffix='.png',dir='.')
    tf = tf.name
    parser.add_argument('-o', default=tf, help="output fig name.")
    parser.add_argument('-x', type=int, help="col number of x, start for 1.")
    parser.add_argument('-y', type=int, help="col number of y, start for 1.")
    parser.add_argument('-t', "--title", help="title of fig.")
    parser.add_argument('-xl', "--xlabel", help="xlabel of fig.")
    parser.add_argument('-yl', "--ylabel", help="ylabel of fig.")
    parser.add_argument("-M", type=float, help="max of x&y")
    parser.add_argument("-m", type=float, help="min of x&y")

    return parser

if __name__=='__main__':
    parser = argparser()
    args = parser.parse_args()
    if len(sys.argv) < 4:
        parser.print_help()
        sys.exit()
    data = getdata(args.f)
    x = data[args.x-1]
    y = data[args.y-1]
    vs_fig(x, y,
           filename=args.o,
           title=args.title,
           xlabel=args.xlabel,
           ylabel=args.ylabel,
           M=args.M,
           m=args.m
           )


"""
Example: scikis.statsmodels.GLS
"""

import scikits.statsmodels.api as sm
import numpy as np
data = sm.datasets.longley.load()
data.exog = sm.add_constant(data.exog)

# The Longley dataset is a time series dataset
# Let's assume that the data is heteroskedastic and that we know
# the nature of the heteroskedasticity.  We can then define
# `sigma` and use it to give us a GLS model

# First we will obtain the residuals from an OLS fit

ols_resid = sm.OLS(data.endog, data.exog).fit().resid

# Assume that the error terms follow an AR(1) process with a trend
# resid[i] = beta_0 + rho*resid[i-1] + e[i]
# where e ~ N(0,some_sigma**2)
# and that rho is simply the correlation of the residuals
# a consistent estimator for rho is to regress the residuals
# on the lagged residuals

resid_fit = sm.OLS(ols_resid[1:], sm.add_constant(ols_resid[:-1])).fit()
print resid_fit.tvalues[0]
print resid_fit.pvalues[0]
# While we don't have strong evidence that the errors follow an AR(1)
# process we continue

rho = resid_fit.params[0]

# As we know, an AR(1) process means that near-neighbors have a stronger
# relation so we can give this structure by using a toeplitz matrix

from scipy.linalg import toeplitz

# # for example
# >>> toeplitz(range(5))
# array([[0, 1, 2, 3, 4],
#       [1, 0, 1, 2, 3],
#       [2, 1, 0, 1, 2],
#       [3, 2, 1, 0, 1],
#       [4, 3, 2, 1, 0]])

order = toeplitz(range(len(ols_resid)))

# so that our error covariance structure is actually rho**order
# which defines an autocorrelation structure

sigma = rho**order

gls_model = sm.GLS(data.endog, data.exog, sigma=sigma)
gls_results = gls_model.fit()

# of course, the exact rho in this instance is not known so it
# it might make more sense to use feasible gls, which currently only
# has experimental support

# We can use the GLSAR model with one lag, to get to a similar result

glsar_model = sm.GLSAR(data.endog, data.exog, 1)
glsar_results = glsar_model.iterative_fit(1)

# comparing gls and glsar results, we see that there are some small
# differences in the parameter estimates and the resulting standard
# errors of the parameter estimate. This might be do to the numerical
# differences in the algorithm, e.g. the treatment of initial conditions,
# because of the small number of observations in the longley dataset.
print gls_results.params
print glsar_results.params
print gls_results.bse
print glsar_results.bse