##### LINEAR REGRESSION - MODIFIED (NON-LINEAR) PSEUDOINVERSION ####

import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model                    # for verification
from sklearn.svm import SVR                         # for verification
from sklearn.neural_network import MLPRegressor     # for verification
from sklearn.metrics import r2_score

data = np.loadtxt('data.txt')       # shape (50, 2)

x = data[:, 0]      # shape (50,)
y = data[:, 1]      # shape (50,)

plt.figure(1, figsize=(10, 8), dpi=100, facecolor='w', edgecolor='k')
plt.scatter(x, y, color='orange', label='original data')

### Modified (Non-Linear) Pseudoinversion method

print("Modified (Non-Linear) Pseudoinversion method")

# We'll add some "features", synthetically
x_sin = np.sin(x)
x_squared = (x**2)
features = np.concatenate((x[:, np.newaxis], x_sin[:, np.newaxis], x_squared[:, np.newaxis]), axis=1)

X = np.ones((data.shape[0], 1))
X = np.concatenate((X, features), axis=1)

theta_optimal = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), y)       # shape (4,)

y_hat = theta_optimal[0] + theta_optimal[1] * x + theta_optimal[2] * x_sin + theta_optimal[3] * x_squared

plt.plot(x, y_hat, color='green', linestyle='', marker='*', label = 'pseudoinv fitted line')

print("theta_optimal:", theta_optimal)      # [2.693 2.406 0.092 0.230]
print("R-squared:", r2_score(y, y_hat))     # 0.99

### Verification

# scikit-learn Linear Regression
print("\nscikit-learn Linear Regression")
reg = linear_model.LinearRegression()
reg.fit(x.reshape(-1, 1), y)
y_pred = reg.predict(x.reshape(-1, 1))
plt.plot(x, y_pred, color='black', linestyle='-', linewidth=3.0, label = 'scikit LR fitted line')
print("intercept, slope:", reg.intercept_, reg.coef_)
print("R-squared:", r2_score(y, y_pred))    # 0.96

# Support Vector Regression (SVR) using linear and non-linear kernels
print("\nSupport Vector Regression (SVR) using linear and non-linear kernels:")

# Linear model
print("\nLinear model")
clf = SVR(kernel='linear', C=1e3)
y_pred = clf.fit(x.reshape(-1, 1), y).predict(x.reshape(-1, 1))
plt.plot(x, y_pred, color='red', linewidth=1.0, label = 'Linear model')
print("intercept, slope:", clf.intercept_, clf.coef_)
print("R-squared:", r2_score(y, y_pred))    # 0.96

# Polynomial model
print("\nPolynomial model")
clf = SVR(kernel='poly', C=10, degree=2)
y_pred = clf.fit(x.reshape(-1, 1), y).predict(x.reshape(-1, 1))
plt.plot(x, y_pred, color='cyan', linestyle='', marker='2', label = 'Polynomial model')
print("R-squared:", r2_score(y, y_pred))    # 0.98

plt.xlabel('data')
plt.ylabel('target')
plt.title('Support Vector Regression vs My Non-Linear Pseudoinversion')
plt.legend()

plt.figure(2, figsize=(10, 8), dpi=100, facecolor='w', edgecolor='k')
plt.scatter(x, y, color='darkorange', label='original data')
plt.scatter(x, y_hat, color='green', marker='*', label='pseudoinv fitted line')

# RBF model
print("\nRBF model")
clf = SVR(kernel='rbf', C=1e3, gamma=0.1)
y_pred = clf.fit(x.reshape(-1, 1), y).predict(x.reshape(-1, 1))
plt.plot(x, y_pred, color='navy', linestyle='', marker='.', label = 'RBF model')
print("R-squared:", r2_score(y, y_pred))    # 0.99

plt.xlabel('data')
plt.ylabel('target')
plt.title('Support Vector Regression vs My Non-Linear Pseudoinversion')
plt.legend()

plt.figure(3, figsize=(10, 8), dpi=100, facecolor='w', edgecolor='k')
plt.scatter(x, y, color='darkorange', label='original data')
plt.scatter(x, y_hat, color='green', marker='*', label='pseudoinv fitted line')

# Multi-layer Perceptron regressor works better with features centered around zero, with standard deviation of 1.
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
x_scaled = x.copy().reshape(-1, 1)
scaler.fit(x_scaled)
x_scaled = scaler.transform(x_scaled)

# Multi-layer Perceptron regressor
print("\nMulti-layer Perceptron regressor")
clf = MLPRegressor(hidden_layer_sizes=(5, 2), max_iter=1000, solver='lbfgs')
y_pred = clf.fit(x_scaled, y).predict(x_scaled)
plt.plot(x, y_pred, color='navy', linestyle='', marker='.', label = 'Multi-layer Perceptron regressor')
print("R-squared:", r2_score(y, y_pred))    # 0.99

plt.xlabel('data')
plt.ylabel('target')
plt.title('Multi-layer Perceptron regressor vs My Non-Linear Pseudoinversion')
plt.legend()

plt.show()


# -------------------------------------------------------------------------------------- #
# -------------------------------------------------------------------------------------- #
# Vignette #XX
# APPM 4720/5720 Randomized Algorithms, Spring 2019
#
# Demo to show how to approximate a matrix-matrix product using randomization based on
# the approach of P. Drineas and M. Mahoney. See section four of "Lectures on Randomized
# Linear Algebra" by Drineas and Mahoney for additional details and analysis.
#
# This script focuses on the case where U \in \reals^{n \times d} with n >> d is an
# orthogonal matrix (specifically its columns are orthogonal). We choose c so that the
# deviation between our randomized matrix and the one we're approximating is bounded with
# high probability. The details for can be found in the Drineas and Mahoney paper.
#
# Algorithm randomized matrix multiplication.
# given U \in \reals^{n \times d} with n >> d, an integer c (1 \le c \le n),
#   and a probability distribution p of length n.
# repeat for k = 1,\dots, c:
#       1. pick i_k \in {1,\dots,n} with P(i = k) = p_k iid with replacement.
#       2. set R(k,:) = 1/sqrt(c * p_{i_k}) * U(i_k,:).
# return R^T R = sum_{k=1}^c 1/(c * p_{i_k}) * U(:,i_k) U(i_k,:).
# -------------------------------------------------------------------------------------- #
import numpy as np                      # import numpy package
import time as time                     # import time package
import matplotlib.pyplot as plt         # import matplotlib package
np.set_printoptions(precision = 2)      # display only four digits
# -------------------------------------------------------------------------------------- #
def vignette_rand_mat_mult_ortho(n_sims = 100, n = 1000, d = 6):
    # n_sims = 100; n = 1000; d = 6         # choose d ~ log n
    np.random.seed(seed = 2)                # set seed for reproducibility
    # ensure parameters are integers
    n_sims = np.int(n_sims);  n = np.int(n);  d = np.int(d);
    beta = 1; epsilon = 0.9; delta = 0.1;
    c_big_n = np.int(np.ceil(96*d/(beta*epsilon**2) *
                np.log(96*d/(beta*epsilon**2*np.sqrt(delta)))))
    c_sm_n = np.int(np.ceil(10*d**2 / (beta*epsilon**2)))
    c = np.amin([c_big_n, c_sm_n])
    # storage for simulations
    fro_norms = np.zeros(n_sims)
    # generate "data" matrices
    U = np.random.normal(scale = 1 / np.sqrt(n), size = (n,d))  # isotropic columns
    U, R_qr = np.linalg.qr(U)
    # ell_2 norms: columns of U and rows of U
    col_norm_U = np.linalg.norm(U, axis = 0); row_norm_U = np.linalg.norm(U, axis = 1)
    # probabilities for sampling
    probs = beta * row_norm_U**2 / d    # nearly optimal probs
    probs = probs / sum(probs)          # undo roundoff---ensure they sum to 1
    # compute theoretical upper bounds on expected squared Frobenius norms
    upper_bound = d**2 / (c*beta)          # optimal probabilities
    # simulation
    for t in range(n_sims):
        # initialize / re-zero matrices
        RTR = np.zeros((d,d))
        for k in range(c):
            # step 1
            i = np.random.choice(a = np.arange(n), replace = True, p = probs)
            # calculate rescaling coefficients
            rescale = 1 / np.sqrt(c*probs[i])
            # step 2
            R = rescale * U[i,:]
            # compute random matrix product via outerproduct
            RTR = np.outer(R, R) + RTR
        # calculate Frobenius norms of actual vs. randomized
        fro_norms[t] = np.linalg.norm(np.eye(d) - RTR, ord = 'fro')
    # print comparisons averaged across the number of simulations
    print('||U^T U - R^T R||_F^2 =', np.round(np.mean(fro_norms**2), 4),
          'vs', np.round(upper_bound, 4))

vignette_rand_mat_mult_ortho()

# Question: If you see that the estimated squared Frobenius norm for the naive
#           probabilities is smaller than that for the optimal probabilities, what should
#           you do?


import math

import matplotlib.pyplot as plt
import numpy as np

limit = {
    "x_sx": -math.pi,
    "x_dx": math.pi,
    "y_down": -2.0,
    "y_up": 2.0,
}

arccos_limit = {
    "x_sx": -math.pi,
    "x_dx": math.pi,
    "y_down": -1,
    "y_up": 3,
}

arccosh_limit = {
    "x_sx": 1,
    "x_dx": (math.pi * 2) - 1,
    "y_down": -1,
    "y_up": 3,
}

def multiple_plotting():
    x_limit = math.pi * 2
    rows = 4
    cols = 3

    limits = [
        limit, limit, limit,
        limit, arccos_limit, limit,
        limit, arccos_limit, limit,
        limit, arccosh_limit, limit
    ]

    x = np.linspace(-x_limit, x_limit, 100)

    # functions
    ys = [
        np.sin(x), np.cos(x), np.tan(x),
        np.arcsin(x), np.arccos(x), np.arctan(x),
        np.sinh(x), np.cosh(x), np.tanh(x),
        np.arcsinh(x), np.arccosh(x), np.arctanh(x)
    ]
    fig, axs = plt.subplots(nrows=rows, ncols=cols, figsize=(16, 9))

    fig.suptitle('Trigonometric functions')

    counter = 0
    for i in range(rows):
        for j in range(cols):
            # get/set the x limits of the current axes
            axs[i, j].set_xlim(limits[counter].get('x_sx'), limits[counter].get('x_dx'))
            # get/set the y limits of the current axes
            axs[i, j].set_ylim(limits[counter].get('y_down'), limits[counter].get('y_up'))
            axs[i, j].plot(x, ys[counter])
            # add a horizontal line across the axis
            axs[i, j].axhline(y=0, color='k')
            # add a vertical line across the axes
            axs[i, j].axvline(x=0, color='k')

            counter = counter + 1

    # display all open figures
    plt.show()

if __name__ == '__main__':
    multiple_plotting()

    # x = np.linspace(0, 2, 100)
    #
    # ax = plt.figure().gca()  # ``gca`` - get current axes
    #
    # ax.plot(x, x, label='linear')
    # ax.plot(x, x ** 2, label='quadratic')
    # ax.plot(x, x ** 3, label='cubic')
    #
    # ax.xaxis.set_major_locator(MaxNLocator(integer=True))
    # plt.show()

    # plotting
    # plotter = UFuncFunctionPlotter(np.cos, -math.pi, math.pi, 100)
    # plotter.plotting(-math.pi, math.pi, -1.5, 1.5)
    #
    # plotter = UFuncFunctionPlotter(np.cos, -math.pi, math.pi, 100)
    # plotter.fill_y_axis()
    # plotter.plotting(-math.pi, math.pi, -1.5, 1.5)

# https://python.astrotech.io/matplotlib/multiple-figures.html#multiple-figures-with-single-plots
# https://matplotlib.org/devdocs/gallery/subplots_axes_and_figures/subplots_demo.html


# -*- coding: utf-8 -*-
"""
Created on Mon Jul 12 16:50:51 2021

@author: Korkut Emre Arslantürk/ 250206039
"""

# Note: I did this program using spyder from anaconda navigator.
#Please make sure you have installed python library for symbolic mathematics "sympy".

#Importing libraries

#%%
import sympy as sym
import math
import numpy as np
from sympy.utilities.lambdify import lambdify

# create a "symbol" called x
x = sym.Symbol('x')

#define values
a = np.pi / 6; b = np.pi / 2; error = 0.00001;
dt=np.pi/3000;
t=np.linspace(a, b, num=1001)

#Define function
f=(sym.cos(x) * (sym.exp(x) + x)) / ((x * x) - sym.log(x))

# I found Exact Result using python integral function. In last part
#I make error calculation using that.
from scipy.integrate import quad

def integrand(x):
    return (np.cos(x) * (np.exp(x) + x)) / ((x * x) - np.log(x))

ans, err = quad(integrand, a, b)
exact=ans

#Evaulating 2nd and 4th order Derivatives for using to find subinterval number
#according to error bound formulas.
derivative_f = f.diff(x,2) ; derivative_4f = f.diff(x,4)

#transform the function to available passing x values
f2order = lambdify(x,derivative_f); f4order = lambdify(x,derivative_4f)
forder=lambdify(x,f)
#Let me find K2 and K4 values which values give us max value for second and
#4th order derivates. I need this according to Error bound formulas to find
#compound midpoint, trapezoidal and Simpson's Method

dev2=np.zeros(1001)
j=1

while j<(len(t)-1):

        dev2[j]= f2order(j*dt)

        j=j+1

K2=max(abs(dev2))

dev4=np.zeros(1001)
j=1
while j<(len(t)-1):

        dev4[j]= f4order(j*dt)

        j=j+1

K4=max(abs(dev4))

#After find K2 and K4 values, I determine the number of subintervals required
#for the compound midpoint, compound trapezoidal and Simpson’s to assure
#this accuracy.

n_midpoint=pow(((K2*(pow((b - a),3)))/((abs(error) * 24))),1 / 2)
n_midpoint=math.ceil(n_midpoint)

n_trapezoidal=pow(((K2*(pow((b - a),3)))/(abs(error)*12)),1 / 2)
n_trapezoidal=math.ceil(n_trapezoidal)

n_simpson=pow(((K4*(pow((b - a),5)))/(abs(error)*180)),1 / 4);
n_simpson=math.ceil(n_simpson)

#I printed the number of subintervals required for the compound
# midpoint, compound trapezoidal and Simpson’s to assure this accuracy.
print("Number of subintervals required for the compound midpoint ",n_midpoint)
print("Number of subintervals required for the compound trapezoidal ",n_trapezoidal)
print("Number of subintervals required for the Simpson's ",n_simpson)

#After that I found the results by using this subintervals and methods
#to prove that I was at the specified error

#Firstly, I found needed H values.
h_n=(b - a)/n_midpoint
h_t=(b - a)/n_trapezoidal
h_s=(b - a)/n_simpson

#Approximation according to compound midpoint
k = a + (h_n) / 2
res_1 = 0; i = 1
while i < (n_midpoint):

       d=(np.cos(k) * (np.exp(k) + (k)))/(((k) * (k)) - np.log(k))
       res_1 = d + res_1
       i = i + 1
       k = k + (h_n)

midpoint=h_n*res_1;
midpoint_error= ((abs(midpoint-exact))/exact)

#Approximation according to compound trapezoidal

i=1
res_2=0
while i<(n_trapezoidal):

       d=(np.cos(a+i*h_t)*(np.exp(a+i*h_t)+(a+i*h_t)))/(((a+i*h_t)*(a+i*h_t))-np.log(a+i*h_t))
       res_2=d+res_2
       i=i+1

fa=(np.cos(a)*(np.exp(a)+a))/((a*a)-np.log(a)); fb=(np.cos(b)*(np.exp(b)+b))/((b*b)-np.log(b))
res_2=res_2+(0.5*(fa + fb))
Trapezoidal=h_t*res_2
Trapezoidal_error= ((abs(Trapezoidal-exact))/exact)

#Approximation according to Simpson's Rule

m= np.linspace(a, b, n_simpson)

f_simp=(np.cos(m)*(np.exp(m)+m))/((m*m)-np.log(m))

firstpart=0; secondpart=0
i=1
while(i<=n_simpson-1):
    firstpart=firstpart+forder(a+i*h_s)
    i=i+2

i=2
while(i<=n_simpson-2):
    secondpart=secondpart+forder(a+i*h_s)
    i=i+2

result_simpson= (h_s/3)*(forder(a)+forder(b)+4*firstpart+2*secondpart)

simpson_error= ((abs(result_simpson-exact))/exact)

print("Exact Result",exact)
print("Midpooint Result: ",midpoint)
print("Trapezoidal Result",Trapezoidal)
print("Simpson Result: ",result_simpson)
print("Error of Midpoint: ",midpoint_error)
print("Error of Trapezoidal", Trapezoidal_error)
print("Error of Simpson Method:", simpson_error)

Determination of required subintervals.py

import numpy,from scipy,import sympy,from sympy


#### BT: f(x) = x^2 + 5sin(x)

import math
import numpy as np
import matplotlib.pyplot as plt

def grad(x):
    """ Ham tinh dao ham cua f(x) = 2x + 5cos(x) """
    return 2*x + 5*np.cos(x)

def cost(x):
    """ Ham tinh gia tri cua f(x) """
    return x**2 + 5*np.sin(x)

def GD1(x0, eta = 0.1, epxilon = 1e-3):
    """ Ham thuc hien thuat toan GD
     eta: learning rate
     x0: thoi diem bat dau
     epxilon: Gia tri du nho de khi dao ham du nho
     """
    x = [x0]
    temp = 0
    for it in range(100):
        x_new = x[-1] - eta * grad(x[-1])
        temp += 1
        if abs( grad(x_new) ) < epxilon:
            break
        x.append(x_new)
    return (x, temp)

(x1, it1) = GD1(-5, 0.1)
(x2, it2) = GD1(5, 0.1)
print('Solution x1 = %f, cost = %f, obtained after %d iterations'%(x1[-1], cost(x1[-1]), it1))
print('Solution x2 = %f, cost = %f, obtained after %d iterations'%(x2[-1], cost(x2[-1]), it2))


from math import pi

import matplotlib.pyplot as py
import sympy as sp
import numpy as np
import time

x = sp.Symbol('x')
y = sp.Symbol('y')
n = sp.Symbol('n')

#No 1
#a
#X for tools and equipment
#Y for materials for EACH cloth
revenueEq = (1.5*x + 2*x)*(n/2)
totalCostEq = y + x*n
profitEq = revenueEq - totalCostEq
#I will be assuming Y has the value of 1000X and X has the value of 200000
xVal = 200000
yVal = 50*xVal
print("a. Total cost:", totalCostEq)
print("   Revenue:", revenueEq)
temp = 1
while (revenueEq.evalf(subs={x : xVal, y: yVal, n  : temp}) <= totalCostEq.evalf(subs={x : xVal, y: yVal, n: temp})):
    temp+=1
print("The solution means that once", temp, "clothes is sold, we will have broken even between cost and revenue. So any amount of clothes after this will produce a profit.")
#b
nVal = temp+1
print("b. For", nVal, "amount of clothes, he will get a profit of Rp", profitEq.evalf(subs={x: xVal, y: yVal, n:nVal}))
#c
nVals = [i for i in range(500, 500*10, 100)]
profits = []
for nval in nVals:
    profits.append(profitEq.evalf(subs={x: xVal, y: yVal, n:nval}))
py.plot(nVals, profits)
py.xlabel("Number of clothes")
py.ylabel("Profits")
py.show()
#d
#LU Decomposition
matrix = [[1, 2, 3, 10],
          [4, 7, 5, 4],
          [7, 1, 9, 11]]
intervals = []
start = time.time()
sp.solve_linear_system_LU(sp.Matrix(matrix), [x, y, n])
end = time.time()
intervals.append(end - start)
#Gauss Elimination
#According to SymPy, Gauss Elimination is more efficient than Gauss-Jordan elimination
start = time.time()
sp.solve_linear_system(sp.Matrix(matrix), x, y, n)
end = time.time()
intervals.append(end - start)
print("d.")
print("LU Decomposition (time taken):", intervals[0])
print("Gauss Elimination (time taken):", intervals[1])
print()

#No 2
#a
functionOri = (x-1)
function = functionOri
def no_2_eq(function, n, xVal):
    answer = 0
    for i in range(1, n+1):
        if (i == 1):
            answer = function.evalf(subs={x: xVal})
        elif (i % 2 == 1): #Odd
            answer = answer + (functionOri**i/i).evalf(subs={x: xVal})
        else:
            answer = answer - (functionOri**i/i).evalf(subs={x: xVal})
    return answer
print("No 2:")
actualFunc = sp.ln(x)
xVal = 2
trueError = actualFunc.evalf(subs={x: 2}) - no_2_eq(function, 5, xVal)
print("a. True Error:", trueError)
#b
absError = abs(trueError)
target = 0.0001
actualVal = actualFunc.evalf(subs={x: 2})
answer = -500
temp = 1
while (abs(actualVal - answer) >= target):
    if (temp == 1):
        answer = function.evalf(subs={x: xVal})
    elif (temp % 2 == 1): #Odd
        answer = answer + (functionOri**temp/temp).evalf(subs={x: xVal})
    else:
        answer = answer - (functionOri**temp/temp).evalf(subs={x: xVal})
    temp += 1
print("b.", temp-1)
#c
target = 0.1/100
answer = -99999999999999999
temp = 1
while ((abs(actualVal - answer)/actualVal) >= target):
    if (temp == 1):
        answer = function.evalf(subs={x: xVal})
    elif (temp % 2 == 1): #Odd
        answer = answer + (functionOri**temp/temp).evalf(subs={x: xVal})
    else:
        answer = answer - (functionOri**temp/temp).evalf(subs={x: xVal})
    temp += 1
print("c.", temp-1)
#d
answers = []
for n in range(1, 11):
    answers.append(abs(actualVal - no_2_eq(function, n, xVal)))
xValues = [x for x in range(1, 11)]
py.plot(np.array(xValues), np.array(answers))
py.xlabel("Terms number")
py.ylabel("Approximate error")
py.show()
print()

#No 3
def simpson_rule(equation, a, b, n):
    """
    Method to get the integration approximation of a function using simpson rule

    Parameters:
    equation: The equation f(x)
    a: lower bound of the integral
    b: upper bound of the integral
    n: no of segments
    """

    h = (b-a)/n
    x = sp.Symbol('x')
    xVal = a

    result = 0
    #First segment
    result += equation.evalf(subs={x:xVal})
    xVal += h
    #Other segments
    for i in range(1, n+1):
        if (i == n):  #If last segment
            result += equation.evalf(subs={x:xVal})
        else:
            if (i % 2 != 0):
                result += equation.evalf(subs={x:xVal}) * 4
            else:
                result += equation.evalf(subs={x:xVal}) * 2
        xVal += h

    result *= h/3

    return result

function = sp.sin(x)

answers = []
for n in range(4, 11, 2):
    answers.append(simpson_rule(function, 0, pi, n))

print("No 3:")
n = 4
for i in range(len(answers)):
    print("N is", n, ":", answers[i])
    n+=2    #Simpson only accepts even segments


'''
@author: hakuri
'''
from numpy import *
import matplotlib.pyplot as plt
def loadDataSet(fileName):      #general function to parse tab -delimited floats
    dataMat = []                #assume last column is target value
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = map(float,curLine) #map all elements to float()
        dataMat.append(fltLine)
    return dataMat

def distEclud(vecA, vecB):
    return sqrt(sum(power(vecA - vecB, 2))) #la.norm(vecA-vecB)

def randCent(dataSet, k):
    n = shape(dataSet)[1]
    centroids = mat(zeros((k,n)))#create centroid mat
    for j in range(n):#create random cluster centers, within bounds of each dimension
        minJ = min(array(dataSet)[:,j])

        rangeJ = float(max(array(dataSet)[:,j]) - minJ)
        centroids[:,j] = mat(minJ + rangeJ * random.rand(k,1))

    return centroids

def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m = shape(dataSet)[0]
    clusterAssment = mat(zeros((m,2)))#create mat to assign data points                                       #to a centroid, also holds SE of each point
    centroids = createCent(dataSet, k)
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):#for each data point assign it to the closest centroid
            minDist = inf; minIndex = -1
            for j in range(k):
                distJI = distMeas(array(centroids)[j,:],array(dataSet)[i,:])
                if distJI < minDist:
                    minDist = distJI; minIndex = j
            if clusterAssment[i,0] != minIndex: clusterChanged = True
            clusterAssment[i,:] = minIndex,minDist**2
        print centroids
#         print nonzero(array(clusterAssment)[:,0]
        for cent in range(k):#recalculate centroids
                ptsInClust = dataSet[nonzero(array(clusterAssment)[:,0]==cent)[0][0]]#get all the point in this cluster

                centroids[cent,:] = mean(ptsInClust, axis=0) #assign centroid to mean
    id=nonzero(array(clusterAssment)[:,0]==cent)[0]
    return centroids, clusterAssment,id

def plotBestFit(dataSet,id,centroids):

    dataArr = array(dataSet)
    cent=array(centroids)
    n = shape(dataArr)[0]
    n1=shape(cent)[0]
    xcord1 = []; ycord1 = []
    xcord2 = []; ycord2 = []
    xcord3=[];ycord3=[]
    j=0
    for i in range(n):
        if j in id:
            xcord1.append(dataArr[i,0]); ycord1.append(dataArr[i,1])
        else:
            xcord2.append(dataArr[i,0]); ycord2.append(dataArr[i,1])
        j=j+1
    for k in range(n1):
          xcord3.append(cent[k,0]);ycord3.append(cent[k,1])

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    ax.scatter(xcord3, ycord3, s=50, c='black')

    plt.xlabel('X1'); plt.ylabel('X2');
    plt.show()

if __name__=='__main__':
    dataSet=loadDataSet('/Users/hakuri/Desktop/testSet.txt')
# #     print randCent(dataSet,2)
#      print dataSet
#
#      print  kMeans(dataSet,2)
    a=[]
    b=[]
    a, b,id=kMeans(dataSet,2)
    plotBestFit(dataSet,id,a)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint

# Euler
def Euler(T_l,y_0):
    U = np.zeros_like(T_l)
    for k in range(Nt):
        tk = T_l[k]
        U[k] = y_0
        yk = y_0 + h*f(y_0,tk)
        y_0 = yk
    return U
#######

# Henn
def Heun(T_l,y_0):
    U = np.zeros_like(T_l)
    yk1 = y_0
    for k in range(Nt):
        tk = T_l[k]
        U[k] = yk1
        yk = y_0 + h*f(y_0,tk)
        yk_e = yk + h*f(tk,yk)
        yk1 = yk + h/2*(f(tk,yk)+f(tk+h, yk_e))
        y_0 = yk
    return U
########

# RK4
def rk4(T_l, y_0):
    U = np.zeros_like(T_l)
    U[0] = y_0
    for k in range(Nt):
        yk = y_0
        tk = T_l[k]
        Ak = f(yk,tk)
        Bk = f(yk + h*Ak/2, tk + h/2 )
        Ck = f(yk + h*Bk/2, tk + h/2 )
        Dk = f(yk + h*Ck, tk + h )
        U[k] = yk
        y_0 = yk + h*(Ak + 2*Bk + 2*Ck + Dk)/6
    return U
#######

fig = plt.figure(frameon=True, facecolor='w')
ax = fig.gca()
trs = 30*'-'
igs = 30*'='

e = 2.220446

def f(y, t):
    return y*np.sin(t)

t0 = 0

tf = 2*np.pi

y0 = 1

Nt = 11
T,h = np.linspace(t0,tf,Nt, retstep=True)
print 2*trs, '\nO passo temporal é h = ',h
fg_h = (tf - t0)*0.05

W = Euler(T, y0)

X = Heun(T, y0)

Y = rk4(T, y0)

# odeint
Z = odeint(f, y0, T)
#######

print 2*igs,'''\nTabela comparativa:
    T[k] --> tempo
    W[k] --> Euler
    X[k] --> Heun
    Y[k] --> Runge-Kutta
    Z[k] --> odeint( ) \n''', igs
print 'T[k] --> W[k] -- X[k] -- Y[k] -- Z[k]\n',2*trs
for k in range(Nt):
    print '%4.2f --> %6.4f -- %6.4f -- %6.4f -- %6.4f'%(T[k], W[k], X[k], Y[k], Z[k])
print 2*igs,'\nGráfico para 11 valores igualmente espaçados.'

Ym = min(np.amin(Y),0.)
YM = np.amax(Y)
fg_v = (YM  - Ym)*0.05
plt.plot(T,W,'y-',linewidth=2,label=' Euler')
plt.plot(T,X,'g--',linewidth=2,label=' Hens')
plt.plot(T,Y,'b.',label=' RK4')
plt.plot(T,Z,'r-',linewidth=2,label='odeint( )')
plt.xlim(t0-fg_h,tf+fg_h)
plt.ylim(Ym-fg_v,YM+fg_h)
plt.title('Graficos comparativos')
ax.grid(True)
ax.axhline(y=0., color='k')
ax.axvline(x=0., color='k')
ax.grid(True)
plt.legend(loc='best')
ax.axis([t0-fg_h,tf+fg_h, Ym-fg_v, YM+fg_v])
plt.show()

Nt = 101
T,h = np.linspace(t0,tf,Nt, retstep=True)
print '\nGráfico para 101 valores igualmente espaçados.'
fg_h = (tf - t0)*0.05

W = Euler(T, y0)

X = Heun(T, y0)

Y = rk4(T, y0)

# odeint
Z = odeint(f, y0, T)
#######

Ym = min(np.amin(Y),0.)
YM = np.amax(Y)
fg_v = (YM  - Ym)*0.05
plt.plot(T,W,'y-',linewidth=2,label=' Euler')
plt.plot(T,X,'g--',linewidth=2,label=' Hens')
plt.plot(T,Y,'b.',label=' RK4')
plt.plot(T,Z,'r-',linewidth=2,label='odeint( )')
plt.xlim(t0-fg_h,tf+fg_h)
plt.ylim(Ym-fg_v,YM+fg_h)
plt.title('Graficos comparativos')
ax.grid(True)
ax.axhline(y=0., color='k')
ax.axvline(x=0., color='k')
ax.grid(True)
plt.legend(loc='best')
ax.axis([t0-fg_h,tf+fg_h, Ym-fg_v, YM+fg_v])
plt.show()


from factory import *
import numpy as np

import sys
from pathlib import Path

#############################################
root_path = Path(__file__).parents
sorting_  = str( root_path[1] ) + '/sorting/'

sys.path.append( sorting_ )
from quick_sort import *
#############################################

class Correlations(object):

	def __init__(self):
		super().__init__()

	def PearsonCorrelation(self, x:list, y:list):

		'''
		This correlation index is a linear correlation index. It goes from -1 till 1. This coefficient is ideal
		when the two variables are linearly related.
		A correlation equal to -1 stands for perfect inverse correlation. A correlation index equal to 1 stands for
		a perfect positive correlation. Basically, Pearson correlation index is the ratio between covariance between
		X and Y variables and multiplication between their standard deviation.

		param x: first list to analyze to see how much correlation is in place against y variable
		param y: second list to analyze to see how much correlation is in place against x variable
		'''

		SI         = StatisticalIndexes()

		covariance = SI.Covariance(x, y)
		dev_std_x  = SI.StandardDeviationSample(x)
		dev_std_y  = SI.StandardDeviationSample(y)

		return round(covariance / (dev_std_x * dev_std_y), 9)

	def SpearmanCorrelation(self, x:list, y:list):

		'''
		Spearman correlation index is a non-parametric index for correlations.
		This correlation index wants the variables to be sortable since it performs correlation measuring
		the rank of the variables.
		Differently from Pearson correlation index, Spearman correlation index measures how well
		the relationship between two variables could be described by a monotonic function.
		Practically, this index is nothing more than a sub-case of the Pearson correlation index
		performed over ranks.

		param x: first list to analyze to see how much correlation is in place against y variable
		param y: second list to analyze to see how much correlation is in place against x variable
		'''

		SI         = StatisticalIndexes()

		x_rank     = SI.Ranker(x) # Rank x array...
		y_rank     = SI.Ranker(y) # Rank y array...

		covariance = SI.Covariance(x_rank, y_rank)
		dev_std_x  = SI.StandardDeviationSample(x_rank)
		dev_std_y  = SI.StandardDeviationSample(y_rank)

		return round(covariance / (dev_std_x * dev_std_y), 9)

	def KendallCorrelation(self, x:list, y:list):

		'''
		'''

		pass

x = [12,14,19,16]
y = [13,15,16,17]

from scipy.stats import spearmanr

s  = StatisticalIndexes()
si = Correlations()

print('Spearman mine',  si.SpearmanCorrelation(x, y))
print('Spearman scipy', spearmanr(x, y))


import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scipy.optimize as opt

from cost import log_cost
from map_feature import map_feature
from predict import predict

# Logistic Regression using scipy.optimize.minimize and regularization

# Load Data

filename = 'microchip_tests.txt'
df = pd.read_csv(filename, header=None, names=['Test 1', 'Test 2', 'Accepted'])

# Plot Data

positive = df[df['Accepted'].isin([1])]
negative = df[df['Accepted'].isin([0])]

plt.scatter(positive['Test 1'], positive['Test 2'], s=15, c='b', marker='o', label='Accepted')
plt.scatter(negative['Test 1'], negative['Test 2'], s=15, c='r', marker='x', label='Not Accepted')

plt.legend()
plt.xlabel("Microchip Test 1")
plt.ylabel("Microchip Test 2")
plt.show()

# Convert DataFrames to ndarrays

df.insert(0, 'Ones', 1)

cols = df.shape[1]
x = df.iloc[:, 0:cols-1]
y = df.iloc[:, cols-1:cols]

x = x.values
y = y.values

# Map Features (for microchip test)
x = map_feature(x[:, 1], x[:, 2], degree=6)

# Create Theta
theta = np.array([[0 for _ in range(x.shape[1])]])

# Set Hyperparameter
hyper_p = 0.01

# Minimize Function

options = {'maxiter': 400}
res = opt.minimize(log_cost, theta, (x, y, hyper_p), jac=True, method='TNC', options=options)

cost = res.fun
print(f"The current cost is: {cost}")
new_theta = res.x

# Determine Accuracy

accuracy = predict(new_theta, x, y)
print(f"Accuracy = {accuracy}%")


#!/usr/bin/env python
# coding: utf-8
# In[ ]:
import numpy as np
import pandas as pd
from pandas_datareader import data as web
from scipy.stats import norm
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
# In[ ]:
ticker = 'PG'
data = pd.DataFrame()
data[ticker] = web.DataReader(ticker, data_source='iex', start='2015-1-1', end='2017-3-21')['close']
# In[ ]:
log_returns = np.log(1 + data.pct_change())
#

# $$
# {\LARGE S_t = S_{t-1} \mathbin{\cdot} e^{((r - \frac{1}{2} \cdot stdev^2) \mathbin{\cdot} \delta_t + stdev \mathbin{\cdot} \sqrt{\delta_t} \mathbin{\cdot} Z_t)}  }
# $$
#

# In[ ]:
r = 0.025
# In[ ]:
stdev = log_returns.std() * 250 ** 0.5
stdev
# In[ ]:
type(stdev)
# In[ ]:
stdev = stdev.values
stdev
# In[ ]:
T = 1.0
t_intervals = 250
delta_t = T / t_intervals
iterations = 10000
# In[ ]:
Z = np.random.standard_normal((t_intervals + 1, iterations))
S = np.zeros_like(Z)
S0 = data.iloc[-1]
S[0] = S0
#

# $$
# {\LARGE S_t = S_{t-1} \mathbin{\cdot} e^{((r - \frac{1}{2} \cdot stdev^2) \mathbin{\cdot} \delta_t + stdev \mathbin{\cdot} \sqrt{\delta_t} \mathbin{\cdot} Z_t)}  }
# $$
#

# In[ ]:
for t in range(1, t_intervals + 1):
    S[t] = S[t-1] * np.exp((r - 0.5 * stdev ** 2) * delta_t + stdev * delta_t ** 0.5 * Z[t])
# In[ ]:
S
# In[ ]:
S.shape
# In[ ]:
plt.figure(figsize=(10, 6))
plt.plot(S[:, :10]);


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Nov  4 16:19:48 2020

@author: ggruszczynski

"""

import os
import numpy as np
import matplotlib
import matplotlib.pyplot as plt

def fun(x):
    return np.sin(x)

def f_prim_analytical(x):
    return np.cos(x)

def central_fd(f,x,h):
    f_prim = (f(x+h) - f(x-h))/(2*h)
    return f_prim

def forward_fd(f,x,h):
    f_prim = (f(x+h) - f(x))/h
    return f_prim

def backward_fd(f,x,h):
    f_prim = (f(x) - f(x-h))/h
    return f_prim

def calc_L2_per_element(anal, num):
    return np.sqrt((anal - num) * (anal - num) / (anal * anal))
    #return  np.max(np.abs(anal - num))

x0 = np.pi/4.

dh = np.logspace(-10, -1, 11)
# dh2 = np.linspace(1e-6, 1e-2, 100)
f_prim_exact = f_prim_analytical(x0)
f_prim_exact = np.full(len(dh), f_prim_exact)

f_prim_central_fd = central_fd(fun, x0, dh)
rel_error_central_fd = calc_L2_per_element(f_prim_central_fd, f_prim_exact)

f_prim_forward_fd = forward_fd(fun, x0, dh)
rel_error_forward_fd = calc_L2_per_element(f_prim_forward_fd, f_prim_exact)

f_prim_backward_fd = backward_fd(fun, x0, dh)
rel_error_backard_fd = calc_L2_per_element(f_prim_backward_fd, f_prim_exact)

##########################
plot_dir = f'moje_wykresy'
if not os.path.exists(plot_dir):
    os.makedirs(plot_dir)

fig_name = os.path.join(plot_dir, f"calc_derivative_with_fd.png")
# # plt.rcParams.update({'font.size': 14})

fig, ax = plt.subplots()

y = dh**1
y = y / y[-1] * rel_error_central_fd[-1]
ax.loglog(dh,y, label=r'${h}$')

y = dh**2
y = y / y[-1] * rel_error_central_fd[-1]
ax.loglog(dh,y, label=r'${h^2}$')

ax.loglog(dh, rel_error_central_fd, linestyle="", color='black', marker='x', label=r'central FD')
ax.loglog(dh, rel_error_forward_fd, linestyle="", color='black', marker='o', label=r'forward FD')
# ax.loglog(dh, rel_error_backard_fd, linestyle="", color='black', marker='v', label=r'backward FD')

ax.set(xlabel=r'$\delta_h$', ylabel=r'$L_2(f^{\prime}(x_0, \delta h))$')
ax.set(title='FD - Convergence study')
ax.legend()
ax.grid()

fig.tight_layout()
plt.pause(1e-9)  # there is a race condition somewhere in the matplotlib code.
fig.savefig(fig_name, bbox_inches='tight', dpi=200)
plt.show()
plt.close(fig)  # close the figure


"""Scatterplots."""

import pandas as pd
import matplotlib.pyplot as plt
from util import get_data, plot_data, compute_daily_returns
import numpy as np

def test_run():
    # Read data
    dates = pd.date_range('2009-01-01', '2012-12-31')  # date range as index
    symbols = ['SPY','XOM','GLD']
    df = get_data(symbols, dates)  # get data for each symbol
    plot_data(df)

    # Compute daily returns
    daily_returns = compute_daily_returns(df)
    plot_data(daily_returns, title = "Daily returns", ylabel = "Daily returns")

    # Scatterplots SPY versus XOM
    daily_returns.plot(kind = 'scatter', x = 'SPY', y = 'XOM')
    beta_XOM, alpha_XOM = np.polyfit(daily_returns['SPY'], daily_returns['XOM'], 1)
    print "beta_XOM=", beta_XOM
    print "alpha_XOM=", alpha_XOM
    plt.plot(daily_returns['SPY'], beta_XOM * daily_returns['SPY'] + alpha_XOM, '-', color = 'r')
    plt.show()

    # Scatterplots SPY versus GLD
    daily_returns.plot(kind = 'scatter', x = 'SPY', y = 'GLD')
    beta_GLD, alpha_GLD = np.polyfit(daily_returns['SPY'], daily_returns['GLD'], 1)
    print "beta_GLD=", beta_GLD
    print "alpha_GLD=", alpha_GLD
    plt.plot(daily_returns['SPY'], beta_GLD * daily_returns['SPY'] + alpha_GLD, '-', color = 'r')
    plt.show()

    # Comment: beta_XOM is fairly high than beta_GLD, so XOM is more reactive
    # to the market than GLD.

    # On the other hand, alpha values denote how well the products performs well
    # with respect to SPY. In this case, alpha_XOM is negative, and alpha_GLD is
    # positive. This means that GLD performs better.

    # Calculate correlation coefficient
    print daily_returns.corr(method = 'pearson')

    # As you have seen in this lesson, the distribution of daily returns for
    # stocks and the market look very similar to a Gaussian.
    # This property persists when we look at weekly, monthly, and annual returns
    # as well.
    # If they were really Gaussian we'd say the returns were normally distributed.
    # In many cases in financial research we assume the returns are normally distributed.
    # But this can be dangerous because it ignores kurtosis or the probability
    # in the tails.
    # In the early 2000s investment banks built bonds based on mortgages.
    # They assumed that the distribution of returns for these mortgages was
    # normally distributed.
    # On thet basis they were able to show that these bonds had a very low probability of default.
    # But they made two mistakes. First, they assumed that the return of each
    # of these mortgages was independent; and two that this return would be
    # normally distributed.
    # Both of these assumptions proved to be wrong, as massive number of omeowners
    # defaulted on their mortgages.
    # It was these defaults that precipitated the great recession of 2008.
    #

if __name__ == "__main__":
    test_run()


""" taylor_expansion.py
Taylor Series Approximation for given function using sympy notation.

"""

import matplotlib.pyplot as plt
import numpy as np
from sympy.functions import sin,cos,exp
import sympy as sy
plt.rcParams["figure.figsize"] = (12,8) # w, h

def factorial(k):
    if k == 0:
        return 1
    acc = k
    while k >1 :
        k -= 1
        acc = acc * k
    return acc

def taylor(func, x_0, n):
    """
    func: function to be expanded
    x_0: about x_0
    n: order
    """
    x = sy.Symbol('x')
    p = 0;
    # n denotes upper index
    for i in range(n+1):
        p += (func.diff(x,i).subs(x,x_0)) * ((x-x_0)**i) / factorial(i)
    return p

# approximation of first 'n' terms
def plot(function, x_upper_bound=None, appr_order=None, no_approx=False):
    """
    function: simpy function to be passed
    appr_order: degree of approximation polynom
    x_upper_bound: Boundaries of x during the visualization
    no_approx: Only plot the original function, mutually exclusive with above arguments
    """
    x = sy.Symbol('x')
    if not no_approx:
        # approximation function,
        appr_function = taylor(function, 0, appr_order)
        x1 = np.linspace(-1 * x_upper_bound, x_upper_bound)
        y1 = []
        for k in x1:
            y1.append(appr_function.subs(x,k))
        plt.plot(x1,y1, label="approximation value")
        plt.suptitle('Taylor Series Expansion for '+ str(function) +' \n order: ' + str(appr_order))

    x_2 = np.linspace(-1*x_upper_bound,x_upper_bound)
    y_2 = []
    for k in x_2:
        y_2.append(function.subs(x,k))

    plt.plot(x_2, y_2, label="real value")
    plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
    return plt.show()

def demo():
    x = sy.Symbol('x')
    plot(appr_order=3, x_upper_bound=4, function=sin(x))
    plot(appr_order=3, x_upper_bound=4, function=exp(x))
    plot(appr_order=5, x_upper_bound=4, function=x**2+x**3-3)
    plot(appr_order=7, x_upper_bound=10, function=sin(x))

if __name__ == '__main__':
    demo()


from __future__ import print_function
import numpy as np

# Exact solution for q
def q(t):
    return 50 - 2*np.exp(-0.196*t)

# Exact qdot (from differential equation)
def qd(t):
    return 9.8 - 0.196*q(t)

def residual(qdot, q):
    """
    Residual of the ODE
    """
    return qdot - 9.8 + 0.196*q

# BDF coefficients
alpha1 = np.array([1.0, -1.0])
alpha2 = np.array([3.0/2.0, -4.0/2.0, 1.0/2.0])
alpha3 = np.array([11.0/6.0, -18.0/6.0, 9.0/6.0, -2.0/6.0])
alpha4 = np.array([25.0/12.0, -48.0/12.0, 36.0/12.0, -16.0/12.0, 3.0/12.0])
alpha5 = np.array([137.0/60.0, -300.0/60.0, 300.0/60.0, -200.0/60.0, 75.0/60.0, -12.0/60.0])
alpha6 = np.array([147.0/60.0, -360.0/60.0, 450.0/60.0, -400.0/60.0, 225.0/60.0, -72.0/60.0, 10.0/60.0])

# Make a list
alpha  = [alpha1, alpha2, alpha3, alpha4, alpha5, alpha6]

# Sanity check coeffs
for alp in alpha:
    print(np.sum(alp))

# Supported order of accuracy
orders = [1 ,2, 3, 4, 5, 6]

print("original step size")
t = 0.0; h = 1.0; e1 = []
for order in orders:
    # An O(h^p) approximation of qdot using BDF formula
    qdot = 0.0
    for i in xrange(order+1):
        qdot += alpha[order-1][i]*q(t-i*h)
    qdot = qdot/h
    e1.append(np.abs(qdot -  qd(t)))

print("reducing step size")
t = 0.0; h = h/2.0; e2 = []
for order in orders:
    # An O(h^p) approximation of qdot using BDF formula
    qdot = 0.0
    for i in xrange(order+1):
        qdot += alpha[order-1][i]*q(t-i*h)
    qdot = qdot/h
    e2.append(np.abs(qdot -  qd(t)))
    print(residual(qdot,q(t)), e2[order-1])

# Compare theoretical and numerical accuracies
for order in orders:
    pexp = np.log(e2[order-1]/e1[order-1])/np.log(2)
    print(order, pexp)

# Compute residual
print (residual(qdot, q(t)))


import pandas as pd
import plotly.express
from IMLearn.learners import UnivariateGaussian, MultivariateGaussian
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio
import plotly

pio.templates.default = "simple_white"
Q1_FORMAT = "({E}, {Var})"

def test_univariate_gaussian():
    # Question 1 - Draw samples and print fitted model

    x = np.random.normal(10, 1, 1000)
    estimator = UnivariateGaussian()
    estimator = estimator.fit(x)
    print(Q1_FORMAT.format(E=estimator.mu_, Var=estimator.var_))

    # Question 2 - Empirically showing sample mean is consistent
    diffs_list = []
    sample_sizes = []

    # take i first samples from 10 to 1000
    for i in range(10, 1001, 10):
        # calculate the diffs
        diffs_list.append(abs(10 - estimator.fit(x[:i]).mu_))
        sample_sizes.append(i)

    # plot the diffs
    df = pd.DataFrame({'sample size': sample_sizes, 'diffs': diffs_list})
    plotly.express.bar(df, x='sample size', y='diffs',
                       title='Distance Between True Value and Estimated Values of Expectations').show()

    # Question 3 - Plotting Empirical PDF of fitted model
    pdf = estimator.pdf(x)
    plotly.express.scatter(pdf, x=x, y=pdf, title='Probability Density Function',
                           labels={'x': 'samples', 'y': 'Density'}).show()

def test_multivariate_gaussian():
    # Question 4 - Draw samples and print fitted model
    mu = np.array([0, 0, 4, 0])
    sigma = np.array([[1, 0.2, 0, 0.5],
                      [0.2, 2, 0, 0],
                      [0, 0, 1, 0],
                      [0.5, 0, 0, 1]])
    x = np.random.multivariate_normal(mu, sigma, 1000)
    estimator = MultivariateGaussian()
    estimator = estimator.fit(x)
    print(estimator.mu_, '\n', estimator.cov_)

    # Question 5 - Likelihood evaluation
    func = np.linspace(-10, 10, 200)
    heatmap_list = []
    max_val = np.NINF
    for f1 in func:
        inner_list = []
        for f3 in func:
            value = MultivariateGaussian.log_likelihood(np.array([f1, 0, f3, 0]), sigma, x)
            # find the maximum log-likelihood for Q6
            if value > max_val:
                max_val, best_x, best_y = value, f1, f3
            heatmap_list.append((f1, f3, value))

    df = pd.DataFrame(heatmap_list, columns=['f1', 'f3', 'log-likelihood'])
    plotly.express.density_heatmap(df, x='f3', y='f1', z='log-likelihood',
                                   title='Heatmap of log-likelihoods Between -10 to 10', histfunc='avg').show()

    # Question 6 - Maximum likelihood
    print("The Max log-likelihood is mu: [{},0,{},0], and the value is {}".format(best_x, best_y, max_val))

if __name__ == '__main__':
    np.random.seed(0)
    test_univariate_gaussian()
    test_multivariate_gaussian()


#!/usr/bin/env python3
"""
Clustering Module
"""
import numpy as np

def kmeans(X, k, iterations=1000):
    """
    Performs K-means on a dataset:

    X is a numpy.ndarray of shape (n, d) containing the dataset
        n is the number of data points
        d is the number of dimensions for each data point
    k is a positive integer containing the number of clusters
    iterations is a positive integer containing the maximum number of
    iterations that should be performed
    If no change in the cluster centroids occurs between iterations, your
    function should return
    Initialize the cluster centroids using a multivariate uniform distribution
    (based on0-initialize.py)
    If a cluster contains no data points during the update step, reinitialize
    its centroid
    You should use numpy.random.uniform exactly twice
    You may use at most 2 loops
    Returns: C, clss, or None, None on failure
        C is a numpy.ndarray of shape (k, d) containing the centroid means for
        each cluster
        clss is a numpy.ndarray of shape (n,) containing the index of the
        cluster in C that each data point belongs to

    """
    if not isinstance(X, np.ndarray) or len(X.shape) != 2:
        return None, None
    if type(k) != int or k <= 0 or k >= X.shape[0]:
        return None, None
    if type(iterations) != int or iterations <= 0:
        return None, None

    n, d = X.shape
    xmax = np.max(X, axis=0).astype(np.float)
    xmin = np.min(X, axis=0).astype(np.float)
    C = np.random.uniform(xmin, xmax, size=(k, d))

    for i in range(iterations):
        dtcs = np.linalg.norm(X[:, None] - C, axis=-1)
        klss = np.argmin(dtcs, axis=-1)

        Cc = np.copy(C)
        for j in range(k):
            idxs = np.argwhere(klss == j)
            if not len(idxs):
                C[j] = np.random.uniform(xmin, xmax, size=(1, d))
            else:
                C[j] = np.mean(X[idxs], axis=0)
        if (Cc == C).all():
            return (C, klss)

    dtcs = np.linalg.norm(X[:, None] - C, axis=-1)
    klss = np.argmin(dtcs, axis=-1)

    return (C, klss)


'''
------------------------------------
Assignment 8 - EE2703 (Jan-May 2020)
Done by Akilesh Kannan (EE18B122)
Created on 15/03/20
Last Modified on 15/03/20
------------------------------------
'''

# Imports
import numpy as np
import scipy.fftpack as fft
import matplotlib.pyplot as plt

# Global Variables
plotsDir = 'plots/'
PI = np.pi

## Random Sequence FFT and IFFT
xOriginal = np.random.rand(128)
X = fft.fft(xOriginal)
xComputed = fft.ifft(X)
plt.figure(0)
t = np.linspace(-40, 40, 129)
t = t[:-1]
plt.plot(t, xOriginal, 'b', label='Original $x(t)$', lw=2)
plt.plot(t, np.abs(xComputed), 'g', label='Computed $x(t)$', lw=2)
plt.xlabel(r'$t\ \to$')
plt.grid()
plt.legend()
plt.title('Comparison of actual and computed $x(t)$')
plt.savefig(plotsDir+'Fig0.png')
maxError = max(np.abs(xComputed-xOriginal))
print(r'Magnitude of maximum error between actual and computed values of the random sequence: ', maxError)     # order of 1e-15

## Spectrum of sin(5t)
x = np.linspace(0, 2*PI, 129)
x = x[:-1]
y = np.sin(5*x)
Y = fft.fftshift(fft.fft(y))/128.0
fig1 = plt.figure(1)
fig1.suptitle(r'FFT of $sin(5t)$')
YMag = np.abs(Y)
YPhase = np.angle(Y)
presentFreqs = np.where(YMag > 1e-3)
w = np.linspace(-40, 40, 129)
w = w[:-1]
plt.subplot(211)
plt.plot(w, YMag, lw=2)
plt.xlim([-10, 10])
plt.ylabel(r'$\|Y\|$')
plt.grid()
plt.subplot(212)
plt.xlim([-10, 10])
plt.ylim([-np.pi, np.pi])
plt.ylabel(r'$\angle Y$')
plt.xlabel(r'$k\ \to$')
plt.plot(w[presentFreqs], YPhase[presentFreqs], 'go', lw=2)
plt.grid()
plt.savefig(plotsDir+'Fig1.png')

## AM Modulation with (1 + 0.1cos(t))cos(10t)
x = np.linspace(-4*PI, 4*PI, 513)
x = x[:-1]
y = (1+0.1*np.cos(x))*np.cos(10*x)
Y = fft.fftshift(fft.fft(y))/512.0
fig2 = plt.figure(2)
fig2.suptitle(r'AM Modulation with $(1+0.1cos(t))cos(10t)$')
YMag = np.abs(Y)
YPhase = np.angle(Y)
presentFreqs = np.where(YMag > 1e-3)
w = np.linspace(-40, 40, 513)
w = w[:-1]
plt.subplot(211)
plt.plot(w, YMag, lw=2)
plt.xlim([-15, 15])
plt.ylabel(r'$\|Y\|$')
plt.grid()
plt.subplot(212)
plt.xlim([-15, 15])
plt.ylim([-np.pi, np.pi])
plt.ylabel(r'$\angle Y$')
plt.xlabel(r'$k\ \to$')
plt.plot(w[presentFreqs], YPhase[presentFreqs], 'go', lw=2)
plt.grid()
plt.savefig(plotsDir+'Fig2.png')

## Spectrum of sin^3(t)
x = np.linspace(-4*PI, 4*PI, 513)
x = x[:-1]
y = (np.sin(x))**3
Y = fft.fftshift(fft.fft(y))/512.0
fig3 = plt.figure(3)
fig3.suptitle(r'Spectrum of $sin^3(t)$')
YMag = np.abs(Y)
YPhase = np.angle(Y)
presentFreqs = np.where(YMag > 1e-3)
w = np.linspace(-40, 40, 513)
w = w[:-1]
plt.subplot(211)
plt.plot(w, YMag, lw=2)
plt.xlim([-5, 5])
plt.ylabel(r'$\|Y\|$')
plt.grid()
plt.subplot(212)
plt.plot(w[presentFreqs], YPhase[presentFreqs], 'go', lw=2)
plt.xlim([-5, 5])
plt.ylim([-np.pi, np.pi])
plt.ylabel(r'$\angle Y$')
plt.xlabel(r'$k\ \to$')
plt.grid()
plt.savefig(plotsDir+'Fig3.png')

## Spectrum of cos^3(t)
x = np.linspace(-4*PI, 4*PI, 513)
x = x[:-1]
y = (np.cos(x))**3
Y = fft.fftshift(fft.fft(y))/512.0
fig4 = plt.figure(4)
fig4.suptitle(r'Spectrum of $cos^3(t)$')
YMag = np.abs(Y)
YPhase = np.angle(Y)
presentFreqs = np.where(YMag > 1e-3)
w = np.linspace(-40, 40, 513)
w = w[:-1]
plt.subplot(211)
plt.plot(w, YMag, lw=2)
plt.xlim([-5, 5])
plt.ylabel(r'$\|Y\|$')
plt.grid()
plt.subplot(212)
plt.plot(w[presentFreqs], YPhase[presentFreqs], 'go', lw=2)
plt.xlim([-5, 5])
plt.ylim([-np.pi, np.pi])
plt.ylabel(r'$\angle Y$')
plt.xlabel(r'$k\ \to$')
plt.grid()
plt.savefig(plotsDir+'Fig4.png')

## Spectrum of cos(20t + 5cos(t))
x = np.linspace(-4*PI, 4*PI, 513)
x = x[:-1]
y = np.cos(20*x + 5*np.cos(x))
Y = fft.fftshift(fft.fft(y))/512.0
fig5 = plt.figure(5)
fig5.suptitle(r'Spectrum of $cos(20t + 5cos(t))$')
YMag = np.abs(Y)
YPhase = np.angle(Y)
presentFreqs = np.where(YMag > 1e-3)
w = np.linspace(-40, 40, 513)
w = w[:-1]
plt.subplot(211)
plt.plot(w, YMag, lw=2)
plt.xlim([-50, 50])
plt.ylabel(r'$\|Y\|$')
plt.grid()
plt.subplot(212)
plt.plot(w[presentFreqs], YPhase[presentFreqs], 'go', lw=2)
plt.xlim([-50, 50])
plt.ylim([-np.pi, np.pi])
plt.ylabel(r'$\angle Y$')
plt.xlabel(r'$k\ \to$')
plt.grid()
plt.savefig(plotsDir+'Fig5.png')

## Spectrum of Gaussian

### Phase and Magnitude of estimated Gaussian Spectrum
# I have chosen a window from [-8pi, 8pi] and took 512 points in that interval

t =  np.linspace(-8*PI, 8*PI, 513)
t = t[:-1]
xTrueGaussian = np.exp(-(t**2)/2)
Y = fft.fftshift(fft.fft(fft.ifftshift(xTrueGaussian)))*8/512.0
fig6 = plt.figure(6)
fig6.suptitle(r'Comparison of spectrum of $e^{-\frac{t^2}{2}}$')
YMag = np.abs(Y)
YPhase = np.angle(Y)
absentFreqs = np.where(YMag < 1e-3)
YPhase[absentFreqs] = 0
w = np.linspace(-40, 40, 513)
w = w[:-1]
plt.subplot(221)
plt.plot(w, YMag, lw=2)
plt.xlim([-10, 10])
plt.ylabel(r'$\|Y\|$')
plt.title("Estimated Spectrum")
plt.grid()
plt.subplot(223)
plt.plot(w, YPhase, 'ro', lw=2)
plt.xlim([-10, 10])
plt.ylim([-np.pi, np.pi])
plt.ylabel(r'$\angle Y$')
plt.xlabel(r'$k\ \to$')
plt.grid()

### Phase and Magnitude of true Gaussian spectrum
trueY = np.exp(-(w**2)/2)/np.sqrt(2*PI)
trueYMag = np.abs(trueY)
trueYPhase = np.angle(trueY)
plt.subplot(222)
plt.plot(w, trueYMag)
plt.xlim([-10, 10])
plt.title("True Spectrum")
plt.grid()
plt.subplot(224)
plt.plot(w, trueYPhase, 'ro')
plt.xlim([-10, 10])
plt.ylim([-np.pi, np.pi])
plt.xlabel(r'$k\ \to$')
plt.grid()
plt.savefig(plotsDir+'Fig6.png')

meanError = np.mean(np.abs(trueY - Y))
print(r'Magnitude of mean error between actual and computed values of the Gaussian: ', meanError)     #

plt.show()


#! /usr/bin/env python3
"""
Demonstrate that for a gaussian beam, we get 50% transmission when pinhole size
is equal to beam FWHM

It is also a nice little example of sympy

TODO: repeat calculation when beam is offcenter
"""
import sympy

answers = {True: "Yes", False: "No"}

def find_half(function):
    return sympy.solve(sympy.Eq(function, sympy.Rational(1, 2)))[0]

# Gaussian sigma of intensity distribution
sig = sympy.Symbol("sig", positive=True)

# variable to integrate over
r = sympy.Symbol("r", positive=True)

# pinhole opening
D = sympy.Symbol("D", positive=True)

beam = sympy.exp(-r ** 2 / 2 / sig ** 2)

# calculate beam FWHM
HWHM = find_half(beam)[r]
FWHM = 2 * HWHM

# transmitted power through pinhole
transmitted = sympy.integrate(2 * sympy.pi * r * beam, (r, 0, D / 2))

# calculate full beam for R → infinity
full_beam = sympy.limit(transmitted, D, sympy.oo)

transmitted_normalized = transmitted / full_beam
transmitted_normalized = sympy.simplify(transmitted_normalized)

solution = find_half(transmitted_normalized)[D]

print("Pinhole diameter to have 50% intensity transmission", solution)
print("Beam FWHM", FWHM)
print(
    "Do you get 50% transmission when pinhole is open to beam FWHM ? ",
    answers[sympy.Eq(solution, FWHM)],
)


import numpy as np
from scipy.stats import kendalltau, spearmanr

def tr(X, Y):
    """
    Computes the absolute TR (Tau(Kendal) Rho(spearman)) between X and Y as
    defined by *Some newmeasures of dependence for random variables based
    on spearman’s rho and kendall tau* by  Lu et al.(2018).
    Parameters
    ----------
    X : numpy array like object where the rows correspond to the samples
        and the columns to features.

    Y : numpy array like, of same size as X and one single output.

    Returns
    -------
    numpy array of size the number of input features of X
    which holds the absolute TR between each feature and Y.
    """
    n, d = X.shape
    ny, nd = Y.shape

    assert n == ny
    assert nd == 1

    tr_stats = np.zeros((d, 1))

    for i in range(d):
        tau = kendalltau(X[:, i], Y[:, 0]).correlation
        rho = spearmanr(X[:, i], b=Y[:, 0]).correlation
        tr_stats[i] = abs(3 * tau - 2 * rho)

    return tr_stats

if __name__ == "__main__":
    x, y = [1, 2, 3, 4, 5], [5, 6, 7, 8, 7]
    print("rho: ", spearmanr(x, y).correlation)
    print("tau: ", kendalltau(x, y).correlation)
    print(f"{tr(x,y)=}")


# -*- coding: utf-8 -*-
"""
Author: Paschalis Giakoumoglou
Date: Thu Jun 17 21:15:07 2021
"""
import numpy as np
import pandas as pd
import sympy as symb

def least_squares(f, x, degree):
    """ 5.3 Least Squares (p.100) """
    a = pd.Series(data=[[i for i in range(len(x))],x,f], index=['i','x','f(x)'])
    print(a)
    print()

    n = len(x)

    y = np.transpose(f)
    A = np.zeros((n,degree+1))
    A[:,0] = 1
    for i in range(1, degree+1):
        A[:, i] = np.transpose(x)**i
    A[:,1] = np.transpose(x)

    print(A)

    AT = np.transpose(A)
    ATxA = np.matmul(AT, A)
    INV = np.linalg.inv(ATxA)
    a = np.matmul(np.matmul(INV, AT), y)
    print("A transpose * A = ")
    print(ATxA)
    print()
    print("(A transpose * A) ** -1 = ")
    print(INV)
    print()
    print("solution a = ")
    print(a)
    print()
    X = symb.Symbol('x')
    fun = a[0]
    for i in range(1, degree+1):
        fun += (X**i)*a[i]
    print(fun)

if __name__ == "__main__":

    # Example Least Squares First Grade
    x = np.array([0,3,6])
    f = np.array([1,4,5])
    least_squares(f,x,1)

    #Example Least Squares Second Grade
    x = np.array([0,1,2,3])
    f = np.array([3,2,4,4])
    least_squares(f,x,2)

    #Example 2020
    x = np.array([-0.5,0.3,0.7,1.5])
    f = np.array([1.2,2,1,-1])
    least_squares(f,x,2)


import numpy as np

def isControllable(A, B, computeSVD=False):
    """
    check if system is controllable

    NOTE(jwd) - the singular value decomposition gives insight to the most controllable directions of a system.

    Inputs:
        A (numpy matrix/array) - system state matrix
        B (numpy matrix/array) - system control matrix
        computeSVD (bool) - (default=False) compute singular value decomposition and return it

    Returns:
        controllable (bool) - True if the system meets controllability criteria, otherwise False
        singular value decomposition tuple (U, Sigma, V.T) if computeSVD=True, otherwise `None`
    """
    A = A.astype('float')
    B = B.astype('float')
    rows = A.shape[0]
    nRows = rows
    nCols = rows * B.shape[1]
    # could also use control.ctrb()
    Q = np.empty([nRows, nCols])
    Q[:,:B.shape[1]] = B
    k = 1
    for i in range(B.shape[1], Q.shape[1], B.shape[1]):
        Ak = np.linalg.matrix_power(A, k)
        Q[:,i:i+B.shape[1]] = Ak@B
        k += 1
    rank = np.linalg.matrix_rank(Q)
    controllable = (rank == k)
    if computeSVD:
        U, Sigma, VT = np.linalg.svd(Q)
        return controllable, (U, Sigma, VT)
    return controllable, None

def isObservable(A, C, computeSVD=False):
    """
    check if system is observable.  This is dual to the controllability problem, so a call to this method is really
    the call `isControllable(A.T, C.T, one of {True, False})`

    NOTE(jwd) - the singular value decomposition gives insight to the most observable directions of a system.

    Inputs:
        A (numpy matrix/array) - system state matrix
        C (numpy matrix/array) - system measurement matrix
        computeSVD (bool) - (default=False) compute singular value decomposition and return it

    Returns:
        observable (bool) - True if the system meets observability criteria, otherwise False
        singular value decomposition tuple (U, Sigma, V.T) if computeSVD=True, otherwise `None`
    """
    return isControllable(A.T, C.T, computeSVD=computeSVD)


import numpy as np

def solve_l(L, b):
    """
    Risoluzione di un sistema lineare triangolare inferiore con procedura di sostituzioni in avanti.

    :param L: la matrice triangolare inferiore
    :param b: il vettore dei termini noti
    :return: il vettore x delle incognite e il flag di successo
    """
    m, n = L.shape

    if m != n:
        print("Matrice non quadrata")
        return [], False
    if not np.all(np.diag(L)):
        print("Elemento diagonale nullo")
        return [], False

    x = np.zeros((n, 1))
    for i in range(n):
        s = np.dot(L[i, :i], x[:i])
        x[i] = (b[i] - s) / L[i, i]

    return x, True

def solve_u(U, b):
    """
    Risoluzione di un sistema lineare triangolare superiore con procedura di sostituzioni all'indietro.

    :param U: la matrice triangolare superiore
    :param b: il vettore dei termini noti
    :return: il vettore x delle incognite e il flag di successo
    """
    m, n = U.shape

    if m != n:
        print("Matrice non quadrata")
        return [], False
    if not np.all(np.diag(U)):
        print("Elemento diagonale nullo")
        return [], False

    x = np.zeros((n, 1))
    for i in range(n - 1, -1, -1):
        s = np.dot(U[i, i + 1:], x[i + 1:])
        x[i] = (b[i] - s) / U[i, i]

    return x, True

def fattorizzazione_lu_no_pivot(A):
    """
    Fattorizzazione LU di una matrice senza l'utilizzo del pivoting parziale

    :param A: la matrice da fattorizzare (quadrata)
    :return: le matrici L, U ed il flag di successo
    """
    m, n = A.shape
    if m != n:
        print("Matrice non quadrata")
        return [], [], False

    U = A.copy()
    for k in range(n - 1):
        if U[k, k] == 0:
            print("Elemento diagonale nullo")
            return [], [], False
        for i in range(k + 1, n):
            U[i, k] /= U[k, k]
            for j in range(k + 1, n):
                U[i, j] -= U[i, k] * U[k, j]

    L = np.tril(U, -1) + np.eye(n)
    U = np.triu(U)
    return L, U, True

def fattorizzazione_lu_pivot(A):
    """
    Fattorizzazione LU di una matrice con l'utilizzo del pivoting parziale

    :param A: la matrice da fattorizzare (quadrata)
    :return: le matrici L, U, P ed il flag di successo
    """

    def swap_rows(M, r1, r2):
        M[[r1, r2], :] = M[[r2, r1], :]

    m, n = A.shape
    if m != n:
        print("Matrice non quadrata")
        return [], [], [], False

    U = A.copy()
    P = np.eye(n)
    for k in range(n - 1):
        if U[k, k] == 0:
            print("Elemento diagonale nullo")
            return [], [], [], False
        for i in range(k + 1, n):
            pivot = k + np.argmax(abs(U[k:, k]))
            if k != pivot:
                swap_rows(U, k, pivot)
                swap_rows(P, k, pivot)
            U[i, k] /= U[k, k]
            for j in range(k + 1, n):
                U[i, j] -= U[i, k] * U[k, j]

    L = np.tril(U, -1) + np.eye(n)
    U = np.triu(U)
    return L, U, P, True

def solve_lu(L, U, P, b):
    """
    Risoluzione di un sistema lineare che è stato fattorizzato con le matrici L, U e P.

    :param L: la matrice L
    :param U: la matrice U
    :param P: la matrice P (nel caso di fattorizzazione senza pivot sarà una matrice identità)
    :param b: il vettore dei termini noti
    :return: il vettore x delle incognite e il flag di successo
    """
    y, flag = solve_l(L, np.dot(P, b))
    return solve_u(U, y)

def solve(A, B, pivot):
    """
    Solve generico di un sistema lineare anche a più dimensioni.

    :param A: la matrice A
    :param B: la matrice contente i vettori dei termini noti nelle colonne
    :param pivot: flag indicante se si vuole utilizzare il pivoting parziale o meno
    :return: la matrice risultante X con i vettori delle incognite nelle colonne
    """
    L, U, P, flag = fattorizzazione_lu_pivot(A) if pivot else fattorizzazione_lu_no_pivot(A)
    if min(B.shape) == 1:
        return solve_lu(L, U, P, B)
    m, n = A.shape
    X = np.zeros((n, n))
    B = B.transpose()
    for i in range(B.shape[0]):
        X[i] = solve_lu(L, U, P, B[i]).squeeze(1)
    return X.transpose(), True


from __future__ import print_function

import numpy as np
import matplotlib.pyplot as plt

from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

# ========== HW11 SOLUTION [Python2/3] ========== #

np.random.seed(1)
x = np.random.random(20) * 2.0
noise = np.random.normal(size=20)
y = 2.0 * x - 3.2 + noise
plt.figure()
plt.plot(x, y, 'o')
plt.show()

X = x.reshape(-1, 1)

# ========== 1 ========== #

linreg_fit = LinearRegression(fit_intercept=True)
linreg_fit.fit(X, y)
print(linreg_fit.score(X, y))

# ========== 2 ========== #

X = x.reshape(-1, 1)

poly2 = PolynomialFeatures(degree=2)
X = poly2.fit_transform(X)
quad_fit = LinearRegression(fit_intercept=False)
quad_fit.fit(X, y)
print(quad_fit.score(X, y))

# ========== 3 ========== #

X = x.reshape(-1, 1)

poly10 = PolynomialFeatures(degree=10)
X = poly10.fit_transform(X)
poly10_fit = LinearRegression(fit_intercept=False)
poly10_fit.fit(X, y)
print(poly10_fit.score(X, y))

# ========== 4 ========== #

# flank the x values
xs = np.linspace(np.min(x) - .5,
                 np.max(x) + .5, 100)
xs = xs.reshape(-1, 1)
xs_quad = poly2.transform(xs)
xs_poly10 = poly10.transform(xs)
lin_yhat = linreg_fit.predict(xs)
quad_yhat = quad_fit.predict(xs_quad)
poly10_yhat = poly10_fit.predict(xs_poly10)

plt.figure()
plt.plot(x, y, 'o')
plt.plot(xs, lin_yhat, '-')
plt.plot(xs, quad_yhat, '-')
plt.plot(xs, poly10_yhat, '-')
plt.show()

# the 10-degree model had the highest r^2,
# but it is clearly overfitting!

# zoom in:

plt.figure()
plt.plot(x, y, 'o')
plt.plot(xs, lin_yhat, '-')
plt.plot(xs, quad_yhat, '-')
plt.plot(xs, poly10_yhat, '-')
plt.xlim(np.min(x), np.max(x))
plt.ylim(np.min(y), np.max(y))
plt.show()


#!/usr/bin/python

#################################################
# Basic Classifier #
# Constructing a simple data set #
# Linear classifier #
# Nearest neighbors classification #
# Sk. Mashfiqur Rahman #
#################################################

import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import cKDTree
# from prob_1 import KDTree

# Global data set for problem 2, 3, 4
N = 5000
mean_0 = [3, 2]
covariance_0 = [[5, 1], [1, 1]]
mean_1 = [8, 5]
covariance_1 = [[5, 0], [0, 2]]

X = np.concatenate((np.random.multivariate_normal(mean_0, covariance_0, N),
                    np.random.multivariate_normal(mean_1, covariance_1, N)), axis=0)
y = np.concatenate((np.zeros((N, 1), 'int64'),
                    np.ones((N, 1), 'int64')), axis=0)

mask = np.random.random(2*N) < 0.8
X_training = X[mask]
y_training = y[mask]
mask = np.logical_not(mask)
X_test = X[mask]
y_test = y[mask]

def prob_2():

    plt.figure(figsize=(16, 12))
    plt.plot(X[:N, 0], X[:N, 1], 'o', markerfacecolor='none', color='#75bbfd', label="class 0")
    plt.plot(X[N:, 0], X[N:, 1], 'o', markerfacecolor='none', color='#f97306', label="class 1")
    plt.xlabel('x1', fontsize=22)
    plt.ylabel('x2', fontsize=22)
    plt.suptitle("10000 random data points from a multivariate normal/Gaussian distributions.", fontsize=24)
    plt.legend(fontsize='22')
    plt.savefig('10000 random data points from a multivariate Gaussian distributions.png')
    plt.show()

def prob_3():

    beta = np.linalg.inv(X_training.T.dot(X_training)).dot(X_training.T).dot(y_training)
    y_hat = X_test.dot(beta)
    mask = X_test.dot(beta) < 0.5
    y_hat[mask] = 0
    mask = np.logical_not(mask)
    y_hat[mask] = 1

    c = np.count_nonzero(y_hat == y_test)  # count the number of true elements in Boolean array
    print('The classification accuracy of the algorithm is:', float(c / len(y_test))*100., '%')

    y_training_new = y_training.reshape(-1) # To form an 1D array
    y_test_new = y_test.reshape(-1)
    y_hat_new = y_hat.reshape(-1)

    training0 = X_training[y_training_new == 0]
    training1 = X_training[y_training_new == 1]
    correct0 = X_test[np.logical_and(y_test_new == 0, y_hat_new == 0)]
    correct1 = X_test[np.logical_and(y_test_new == 1, y_hat_new == 1)]
    incorrect0 = X_test[np.logical_and(y_test_new == 0, y_hat_new == 1)]
    incorrect1 = X_test[np.logical_and(y_test_new == 1, y_hat_new == 0)]

    plt.figure(figsize=(16, 12))
    plt.plot(training0[:, 0], training0[:, 1], 's', markerfacecolor='none', color='#75bbfd', label='Training set elements from class 0')
    plt.plot(training1[:, 0], training1[:, 1], 'x', color='#f97306', label='Training set elements from class 1')
    plt.plot(correct0[:, 0], correct0[:, 1], 'o', markerfacecolor='none', color='#00FF00', label='Correctly classified test set elements from class 0')
    plt.plot(correct1[:, 0], correct1[:, 1], '.', color='#800080', label='Correctly classified test set elements from class 1')
    plt.plot(incorrect0[:, 0], incorrect0[:, 1], '*', color='#EE82EE', label='Incorrectly classified test set elements from class 0')
    plt.plot(incorrect1[:, 0], incorrect1[:, 1], '+', color='k', label='Incorrectly classified test set elements from class 1')
    plt.xlabel('x1', fontsize=22)
    plt.ylabel('x2', fontsize=22)
    plt.suptitle("Linear Classifier performance map", fontsize=24)
    plt.legend()
    plt.savefig('Linear Classifier performance map.png')
    plt.show()

def prob_4():

    KDT = cKDTree(X_training).query(X_test, k=1)
    # KDT1 = KDTree(X_training).find_nearest(X_test)
    y_hat = y_training[KDT [1]]  # Ignoring the location of the neighbors (the second output array)
    # y_hat1 = y_training[KDT1 [1]]
    c = np.count_nonzero(y_hat == y_test)  # count the number of true elements in Boolean array
    # c1 = np.count_nonzero(y_hat1 == y_test)
    print('The classification accuracy of the KD tree classifier is:', float(c / len(y_test))*100., '%')
    # print('The classification accuracy of my own KD tree classifier is:', float(c1 / len(y_test))*100., '%')

    y_training_new = y_training.reshape(-1)
    y_test_new = y_test.reshape(-1)
    y_hat_new = y_hat.reshape(-1)

    training0 = X_training[y_training_new == 0]
    training1 = X_training[y_training_new == 1]
    correct0 = X_test[np.logical_and(y_test_new == 0, y_hat_new == 0)]
    correct1 = X_test[np.logical_and(y_test_new == 1, y_hat_new == 1)]
    incorrect0 = X_test[np.logical_and(y_test_new == 0, y_hat_new == 1)]
    incorrect1 = X_test[np.logical_and(y_test_new == 1, y_hat_new == 0)]

    plt.figure(figsize=(16, 12))
    plt.plot(training0[:, 0], training0[:, 1], 's', markerfacecolor='none', color='#75bbfd', label='Training set elements from class 0')
    plt.plot(training1[:, 0], training1[:, 1], 'x', color='#f97306', label='Training set elements from class 1')
    plt.plot(correct0[:, 0], correct0[:, 1], 'o', markerfacecolor='none', color='#00FF00', label='Correctly classified test set elements from class 0')
    plt.plot(correct1[:, 0], correct1[:, 1], '.', color='#800080', label='Correctly classified test set elements from class 1')
    plt.plot(incorrect0[:, 0], incorrect0[:, 1], '*', color='#EE82EE', label='Incorrectly classified test set elements from class 0')
    plt.plot(incorrect1[:, 0], incorrect1[:, 1], '+', color='k', label='Incorrectly classified test set elements from class 1')
    plt.xlabel('x1', fontsize=22)
    plt.ylabel('x2', fontsize=22)
    plt.suptitle("KD tree Classifier performance map", fontsize=24)
    plt.legend()
    plt.savefig('KD tree Classifier performance map.png')
    plt.show()

# Main Function
prob_2()   # Simple Data Set
prob_3()   # Linear Classifier
prob_4()   # KD tree Classifier


from IMLearn.learners import UnivariateGaussian, MultivariateGaussian
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio
import plotly.express as px
pio.templates.default = "simple_white"

MEAN = 10
VAR = 1
SAMPLE_SIZE = 1000

def test_univariate_gaussian():
    # Question 1 - Draw samples and print fitted model
    samples = np.random.normal(loc=MEAN, scale=VAR, size=SAMPLE_SIZE)
    estimator = UnivariateGaussian().fit(samples)
    print("({0}, {1})".format(estimator.mu_, estimator.var_))

    # Question 2 - Empirically showing sample mean is consistent
    estimated_mean = []
    ms = np.linspace(10, 1000, 100).astype(int)
    for m in ms:
        sample_group = samples[:m]
        estimator = UnivariateGaussian().fit(sample_group)
        diff = abs(MEAN - estimator.mu_)
        estimated_mean.append(diff)
    go.Figure([go.Scatter(x=ms, y=estimated_mean, mode='markers+lines')],
              layout=go.Layout(title=r"$\text{Absolute Distance Between The Estimated And True Value Of The "
                                     r"Expectation As A Function Of The Sample Size}$",
                               xaxis_title="$m\\text{ - number of samples}$",
                               yaxis_title="r$|\hat\mu - \mu|$")).show()

    # Question 3 - Plotting Empirical PDF of fitted model
    samples_pdf = estimator.pdf(samples)
    go.Figure([go.Scatter(x=samples, y=samples_pdf, mode='markers')],
              layout=go.Layout(title=r"$\text{PDF of 1000 N(10,1) samples}$",
                               xaxis_title=r"$\text{sample value}$",
                               yaxis_title=r"$\text{Density}$")).show()

def test_multivariate_gaussian():
    # Question 4 - Draw samples and print fitted model
    mu = np.array([0, 0, 4, 0])
    cov = np.array([[1, 0.2, 0, 0.5], [0.2, 2, 0, 0], [0, 0, 1, 0], [0.5, 0, 0, 1]])
    samples = np.random.multivariate_normal(mean=mu, cov=cov, size=SAMPLE_SIZE)
    estimator = MultivariateGaussian().fit(samples)
    print(estimator.mu_)
    print(estimator.cov_)

    # Question 5 - Likelihood evaluation
    results = {}
    matrix = []
    ms = np.linspace(-10, 10, 200)
    for f1 in ms:
        row = []
        for f3 in ms:
            mu = np.array([f1, 0, f3, 0])
            lh = MultivariateGaussian.log_likelihood(mu, cov, samples)
            results[(f1, f3)] = lh
            row.append(lh)
        matrix.append(row)
    px.imshow(matrix, x=ms, y=ms, labels={"x": "f3", "y": "f1"},
              title="Heatmap of log likelihood").show()

    # Question 6 - Maximum likelihood
    print("%.3f, %.3f" % max(results, key=results.get))

if __name__ == '__main__':
    np.random.seed(0)
    test_univariate_gaussian()
    test_multivariate_gaussian()


# Exercise_1
# Import plotting class from matplotlib library
from matplotlib import pyplot as plt

# Create a scatter plot
plt.scatter(x, y)

# Display the scatter plot
plt.show()

--------------------------------------------------
# Exercise_2
# Import linkage and fcluster functions
from scipy.cluster.hierarchy import linkage, fcluster

# Use the linkage() function to compute distance
Z = linkage(df, 'ward')

# Generate cluster labels
df['cluster_labels'] = fcluster(Z, 2, criterion='maxclust')

# Plot the points with seaborn
sns.scatterplot(x='x', y="y", hue="cluster_labels", data=df)
plt.show()

--------------------------------------------------
# Exercise_3
# Import kmeans and vq functions
from scipy.cluster.vq import kmeans, vq

# Compute cluster centers
centroids,_ = kmeans(df, 2)

# Assign cluster labels
df['cluster_labels'], _ = vq(df , centroids)

# Plot the points with seaborn
sns.scatterplot(x='x', y='y' , hue= 'cluster_labels', data=df)
plt.show()

--------------------------------------------------
# Exercise_4
# Import the whiten function
from scipy.cluster.vq import whiten

goals_for = [4,3,2,3,1,1,2,0,1,4]

# Use the whiten() function to standardize the data
scaled_data = whiten(goals_for)
print(scaled_data)

--------------------------------------------------
# Exercise_5
# Plot original data
plt.plot(goals_for, label='original')

# Plot scaled data
plt.plot(scaled_data, label='scaled')

# Show the legend in the plot
plt.legend()

# Display the plot
plt.show()

--------------------------------------------------
# Exercise_6
# Prepare data
rate_cuts = [0.0025, 0.001, -0.0005, -0.001, -0.0005, 0.0025, -0.001, -0.0015, -0.001, 0.0005]

# Use the whiten() function to standardize the data
scaled_data = whiten(rate_cuts)

# Plot original data
plt.plot(rate_cuts, label='original')

# Plot scaled data
plt.plot(scaled_data, label='scaled')

plt.legend()
plt.show()

--------------------------------------------------
# Exercise_7
#1
# Scale wage and value
fifa['scaled_wage'] = whiten(fifa["eur_wage"])
fifa['scaled_value'] = whiten(fifa["eur_value"])
#2
# Scale wage and value
fifa['scaled_wage'] = whiten(fifa['eur_wage'])
fifa['scaled_value'] = whiten(fifa['eur_value'])

# Plot the two columns in a scatter plot
fifa.plot(x='scaled_wage', y='scaled_value', kind='scatter')
plt.show()
#3
# Scale wage and value
fifa['scaled_wage'] = whiten(fifa['eur_wage'])
fifa['scaled_value'] = whiten(fifa['eur_value'])

# Plot the two columns in a scatter plot
fifa.plot(x='scaled_wage', y='scaled_value', kind = 'scatter')
plt.show()

# Check mean and standard deviation of scaled values
print(fifa[['scaled_wage', 'scaled_value']].describe())

--------------------------------------------------

Machine Learning Scientist with Python Track/6. Cluster Analysis in Python/ch1_exercises.py


import os
import sys
import inspect
import math

current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parent_dir = os.path.dirname(current_dir)
sys.path.insert(0, parent_dir)

import numpy as np
import auxiliary as aux
from typing import Callable

def gramian_angular_field(
    timeseries: np.ndarray, upper_bound: float = 1.0, lower_bound: float = -1.0
) -> tuple:
    """
        **Compute the Gramian Angular Field of a time series.**

        The Gramian Angular Field is a bijective transformation of time series data into an image of dimension `n+1`.
        Inserting an `n`-dimensional time series gives an `(n x n)`-dimensional array with the corresponding encoded
        time series data.

        + param **timeseries**: time series data, type `np.ndarray`.
        + param **upper_bound**: upper bound for scaling, type `float`.
        + param **lower_bound**: lower bound for scaling, type `float`.
        + return **tuple**: (GAF, phi, r, scaled-series), type `tuple`.
    """

    # Min-Max scaling
    min_ = np.amin(serie)
    max_ = np.amax(serie)
    scaled_serie = (2 * serie - max_ - min_) / (max_ - min_)

    # Floating point inaccuracy!
    scaled_serie = np.where(scaled_serie >= 1.0, 1.0, scaled_serie)
    scaled_serie = np.where(scaled_serie <= -1.0, -1.0, scaled_serie)

    # Polar encoding
    phi = np.arccos(scaled_serie)

    # Note! The computation of r is not necessary
    r = np.linspace(0, 1, len(scaled_serie))

    # GAF Computation (every term of the matrix)
    gaf = tabulate(phi, phi, cos_sum)

    return (gaf, phi, r, scaled_serie)


# example of grid search for function optimization
from numpy import arange
from numpy.random import rand

# objective function
def objective(x, y):
	return x**2.0 + y**2.0

# define range for input
r_min, r_max = -5.0, 5.0
# generate a grid sample from the domain
sample = list()
step = 0.1
for x in arange(r_min, r_max+step, step):
	for y in arange(r_min, r_max+step, step):
		sample.append([x,y])
# evaluate the sample
sample_eval = [objective(x,y) for x,y in sample]
# locate the best solution
best_ix = 0
for i in range(len(sample)):
	if sample_eval[i] < sample_eval[best_ix]:
		best_ix = i
# summarize best solution
print('Best: f(%.5f,%.5f) = %.5f' % (sample[best_ix][0], sample[best_ix][1], sample_eval[best_ix]))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Dec  2 15:23:46 2020

Copyright 2020 by Hadrien Montanelli.
"""
# %% Imports.

# Standard library import:
from math import pi
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from scipy.sparse import eye, kron
from scipy.sparse.linalg import spsolve
import time

# Chebpy imports:
from chebpy.trig import multmat, trigpts
from chebpy.sph import bmc, coeffs2vals, feval, laplacian, vals2coeffs, pcond

# %% Solve Laplacian(u) = f on the sphere.

# RHS:
l = 10
f1 = lambda lam, tt: l*(l+1) * np.sin(tt)**l * np.cos(l*lam)
f2 = lambda lam, tt: (l+1)*(l+2) * np.cos(tt) * np.sin(tt)**l * np.cos(l*lam)
f = lambda lam, tt: f1(lam, tt) + f2(lam, tt)

# Exact solution:
uex1 = lambda lam, tt: -np.sin(tt)**l * np.cos(l*lam)
uex2 = lambda lam, tt: -np.cos(tt) * np.sin(tt)**l * np.cos(l*lam)
uex = lambda lam, tt: uex1(lam, tt) + uex2(lam, tt)

# Grid points:
n = 64
dom = [-pi, pi]
lam = trigpts(n, dom)
tt = trigpts(n, dom)
LAM, TT = np.meshgrid(lam, tt)

# Assemble RHS:
F = vals2coeffs(feval(f, LAM, TT))
F = np.reshape(F.T, (n*n, 1))

# Zero-mean condition:
F[n*int(n/2) + int(n/2)] = 0

# Assemble Laplacian (with mean condition):
start = time.time()
L = laplacian(n, 1)
end = time.time()
print(f'Time   (setup): {end-start:.5f}s')
plt.figure()
plt.spy(L)

# Sparse solve:
start = time.time()
I = eye(n)
Tsin2 = multmat(n, lambda x: np.sin(x)**2, dom)
U = spsolve(L, kron(I, Tsin2) @ F)
end = time.time()
print(f'Time   (solve): {end-start:.5f}s')

# Plot solution:
U = np.reshape(U, (n, n)).T
u = coeffs2vals(U)
plt.figure()
plt.contourf(LAM, TT, u, 40, cmap=cm.coolwarm)
plt.colorbar()

# Plot exact solution:
plt.figure()
plt.contourf(LAM, TT, feval(uex, LAM, TT), 40, cmap=cm.coolwarm)
plt.colorbar()

# Error:
error = feval(uex, LAM, TT) - u
error = np.max(np.abs(error))/np.max(np.abs(feval(uex, LAM, TT)))
print(f'Error  (L-inf): {error:.2e}')

# BMC symmetry:
S = bmc(U)
print(f'BMC-I symmetry: {S:.2e}')

# Pole condition:
P = pcond(U)
print(f'Pole condition: {P:.2e}')


import numpy as np
import scipy.stats
from sklearn import preprocessing

a = np.array([0, 1, 2, 3, 4])
print(a)
# [0 1 2 3 4]

print((a - a.min()) / (a.max() - a.min()))
# [0.   0.25 0.5  0.75 1.  ]

print((a - a.mean()) / a.std())
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print((a - a.mean()) / a.std(ddof=1))
# [-1.26491106 -0.63245553  0.          0.63245553  1.26491106]

a_2d = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
print(a_2d)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

def min_max(x, axis=None):
    x_min = x.min(axis=axis, keepdims=True)
    x_max = x.max(axis=axis, keepdims=True)
    return (x - x_min) / (x_max - x_min)

print(min_max(a_2d))
# [[0.    0.125 0.25 ]
#  [0.375 0.5   0.625]
#  [0.75  0.875 1.   ]]

print(min_max(a_2d, axis=0))
# [[0.  0.  0. ]
#  [0.5 0.5 0.5]
#  [1.  1.  1. ]]

print(min_max(a_2d, axis=1))
# [[0.  0.5 1. ]
#  [0.  0.5 1. ]
#  [0.  0.5 1. ]]

print(min_max(a))
# [0.   0.25 0.5  0.75 1.  ]

def standardization(x, axis=None, ddof=0):
    x_mean = x.mean(axis=axis, keepdims=True)
    x_std = x.std(axis=axis, keepdims=True, ddof=ddof)
    return (x - x_mean) / x_std

print(standardization(a_2d))
# [[-1.54919334 -1.161895   -0.77459667]
#  [-0.38729833  0.          0.38729833]
#  [ 0.77459667  1.161895    1.54919334]]

print(standardization(a_2d, ddof=1))
# [[-1.46059349 -1.09544512 -0.73029674]
#  [-0.36514837  0.          0.36514837]
#  [ 0.73029674  1.09544512  1.46059349]]

print(standardization(a_2d, axis=0))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(standardization(a_2d, axis=0, ddof=1))
# [[-1. -1. -1.]
#  [ 0.  0.  0.]
#  [ 1.  1.  1.]]

print(standardization(a_2d, axis=1))
# [[-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]]

print(standardization(a_2d, axis=1, ddof=1))
# [[-1.  0.  1.]
#  [-1.  0.  1.]
#  [-1.  0.  1.]]

print(standardization(a))
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print(standardization(a, ddof=1))
# [-1.26491106 -0.63245553  0.          0.63245553  1.26491106]

print(scipy.stats.zscore(a))
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print(scipy.stats.zscore(a_2d))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(scipy.stats.zscore(a_2d, axis=None, ddof=1))
# [[-1.46059349 -1.09544512 -0.73029674]
#  [-0.36514837  0.          0.36514837]
#  [ 0.73029674  1.09544512  1.46059349]]

mm = preprocessing.MinMaxScaler()

print(mm.fit_transform(a_2d.astype(float)))
# [[0.  0.  0. ]
#  [0.5 0.5 0.5]
#  [1.  1.  1. ]]

print(preprocessing.minmax_scale(a.astype(float)))
# [0.   0.25 0.5  0.75 1.  ]

print(preprocessing.minmax_scale(a_2d.astype(float), axis=1))
# [[0.  0.5 1. ]
#  [0.  0.5 1. ]
#  [0.  0.5 1. ]]

ss = preprocessing.StandardScaler()

print(ss.fit_transform(a_2d.astype(float)))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(preprocessing.scale(a.astype(float)))
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print(preprocessing.scale(a_2d.astype(float), axis=1))
# [[-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]]


'''
Laboratorio de Metodos Computacionales
Solucion Ejercicio 2
'''

import numpy as np

#Funcion que retorna el alcance maximo
def alcance_maximo(theta, v0, g):
	return v0**2 * np.sin(2*theta)/g

#Funcion que retorna la derivada del alcance maximo
def derivada_alcance_maximo(theta, v0, g, h):
	return (alcance_maximo(theta + h, v0, g) - alcance_maximo(theta, v0, g) )/h

#Funcion que retorna la segunda derivada del alcance maximo
def derivada2_alcance_maximo(theta, v0, g, h):
	return (alcance_maximo(theta + h, v0, g) - 2.0*alcance_maximo(theta, v0, g) + alcance_maximo(theta-h, v0, g))/h**2.0

#Funcion que utiliza el metodo de Newton para buscar el cero de la funcion derivada, correspondiente al alcance maxim
def newton(init_guess, delta, v0, g, h):

    guess = init_guess
    while np.abs(derivada_alcance_maximo(guess, v0, g, h)) > delta:
        guess = guess - derivada_alcance_maximo(guess, v0, g, h)/derivada2_alcance_maximo(guess, v0, g, h)

    return guess

#Corre la funcion Newton para varios guess iniciales
for i in range(2,9):
	guess = np.pi/2.0 / 10.0 * i

	print(180.0/np.pi*guess, 180.0/np.pi * newton(guess, 0.001, 20, -10, 0.01))


"""
=====================================
Cross-Correlation (Phase Correlation)
=====================================

In this example, we use phase correlation to identify the relative shift
between two similar-sized images.

The ``register_translation`` function uses cross-correlation in Fourier space,
optionally employing an upsampled matrix-multiplication DFT to achieve
arbitrary subpixel precision [1]_.

.. [1] Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup,
       "Efficient subpixel image registration algorithms," Optics Letters 33,
       156-158 (2008). :DOI:`10.1364/OL.33.000156`

"""
import numpy as np
import matplotlib.pyplot as plt

from skimage import data
from skimage.feature import register_translation
from skimage.feature.register_translation import _upsampled_dft
from scipy.ndimage import fourier_shift

image = data.camera()
shift = (25, 25)
# The shift corresponds to the pixel offset relative to the reference image
offset_image = fourier_shift(np.fft.fftn(image), shift)
offset_image = np.fft.ifftn(offset_image)
print("Known offset (y, x): {}".format(shift))

# pixel precision first
shift, error, diffphase = register_translation(image, offset_image)

fig = plt.figure(figsize=(8, 3))
ax1 = plt.subplot(1, 3, 1)
ax2 = plt.subplot(1, 3, 2, sharex=ax1, sharey=ax1)
ax3 = plt.subplot(1, 3, 3)

ax1.imshow(image, cmap='gray')
ax1.set_axis_off()
ax1.set_title('Reference image')

ax2.imshow(offset_image.real, cmap='gray')
ax2.set_axis_off()
ax2.set_title('Offset image')

# Show the output of a cross-correlation to show what the algorithm is
# doing behind the scenes
image_product = np.fft.fft2(image) * np.fft.fft2(offset_image).conj()
cc_image = np.fft.fftshift(np.fft.ifft2(image_product))
ax3.imshow(cc_image.real)
ax3.set_axis_off()
ax3.set_title("Cross-correlation")

plt.show()

print("Detected pixel offset (y, x): {}".format(shift))

# subpixel precision
shift, error, diffphase = register_translation(image, offset_image, 100)

fig = plt.figure(figsize=(8, 3))
ax1 = plt.subplot(1, 3, 1)
ax2 = plt.subplot(1, 3, 2, sharex=ax1, sharey=ax1)
ax3 = plt.subplot(1, 3, 3)

ax1.imshow(image, cmap='gray')
ax1.set_axis_off()
ax1.set_title('Reference image')

ax2.imshow(offset_image.real, cmap='gray')
ax2.set_axis_off()
ax2.set_title('Offset image')

# Calculate the upsampled DFT, again to show what the algorithm is doing
# behind the scenes.  Constants correspond to calculated values in routine.
# See source code for details.
cc_image = _upsampled_dft(image_product, 150, 100, (shift*100)+75).conj()
ax3.imshow(cc_image.real)
ax3.set_axis_off()
ax3.set_title("Supersampled XC sub-area")

plt.show()

print("Detected subpixel offset (y, x): {}".format(shift))


import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

matplotlib.rcParams['xtick.direction'] = 'out'
matplotlib.rcParams['ytick.direction'] = 'out'

delta = 0.025
x = np.arange(-8.0, 8.0, delta)
y = np.arange(-8.0, 8.0, delta)
X, Y = np.meshgrid(x, y)

Z0 = mlab.bivariate_normal(X, Y, 1.**0.5, 2.**0.5, 1, 1,0)

plt.figure()
levels = np.arange(-8, 8, 0.01)
CS = plt.contour(X, Y, Z0, levels)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Problem 3a')

Z1 = mlab.bivariate_normal(X, Y, 2.**0.5,3.**0.5,-1,2,1)
plt.figure()
levels = np.arange(-8, 8, 0.01)
CS = plt.contour(X, Y, Z1, levels)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Problem 3b')

Z2 = mlab.bivariate_normal(X, Y, 2.**0.5, 1.**0.5, 0, 2,1)
Z3 = mlab.bivariate_normal(X, Y, 2.**0.5, 1.**0.5, 2,0, 1)
Z4 = Z2 - Z3
plt.figure()
levels = np.arange(-8, 8, 0.015)
CS = plt.contour(X, Y, Z4, levels)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Problem 3c')

Z5 = mlab.bivariate_normal(X, Y, 2.**0.5, 1.**0.5, 0, 2,1)
Z6 = mlab.bivariate_normal(X, Y, 2.**0.5, 3.**0.5, 2,0, 1)
Z7 = Z5 - Z6
plt.figure()
levels = np.arange(-8, 8, 0.015)
CS = plt.contour(X, Y, Z7, levels)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Problem 3d')

Z8 = mlab.bivariate_normal(X, Y, 2.**0.5, 1.**0.5, 1,1,0)
Z9 = mlab.bivariate_normal(X, Y, 2.**0.5, 2.**0.5, -1,-1, 1)
Z10 = Z8 - Z9
plt.figure()
levels = np.arange(-8, 8, 0.015)
CS = plt.contour(X, Y, Z10, levels)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Problem 3e')

plt.show()


#Python Assignments

#1. Division of the array inputs, element-wise:
import numpy as np
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print("Original array:")
print(x)
print("Division of the array inputs, element-wise:")
print(np.true_divide(x, 3))

#2. Largest integer smaller or equal to the division of the inputs
x = [1.0, 2.0, 3.0, 4.0]
print("Original array:")
print(x)
print("Largest integer smaller or equal to the division of the inputs:")
print(np.floor_divide(x, 1.5))

#3. print("First array elements raised to powers from second array, element-wise
x = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
print("Original array")
print(x)
print("First array elements raised to powers from second array, element-wise:")
print(np.power(x, 3))

#4. Element-wise remainder of division
x = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
print("Original array:")
print(x)
print("Element-wise remainder of division:", np.remainder(x, 5))

#5.Element-wise absolute value
x = np.array([-10.2, 122.2, .20])
print("Original array:")
print(x)
print("Element-wise absolute value:", np.absolute(x))

#6. A NumPy program to get the element-wise remainder of an array of division.
x = np.round([1.23, 1.90, 2.40])
print(x)
x = np.round([0.32, .49, .62], decimals=1)
print(x)
x = np.round([.2, 1.8, 2.4, 4.1, 4.0])
print(x)

#7.Round elements of the array to the nearest integer
x = np.array([-.7, -1.5, -1.7, 0.3, 1.5, 1.8, 2.0])
print("Original array:")
print(x)
x = np.rint(x)
print("Round elements of the array to the nearest integer:")
print(x)

#8. A NumPy program to get the floor, ceiling and truncated values of the elements of a numpy array.
x = np.array([-1.6, -1.5, -0.3, 0.1, 1.4, 1.8, 2.0])
print("Original array:")
print(x)
print("Floor values of the above array elements:")
print(np.floor(x))
print("Ceil values of the above array elements:")
print(np.ceil(x))
print("Truncated values of the above array elements:")
print(np.trunc(x))

#9. A NumPy program to add, subtract, multiply, divide arguments element-wise.
print("Add:")
print(np.add(2.0, 3.0))
print("Subtract:")
print(np.subtract(10.0, 13.0))
print("Multiply:")
print(np.multiply(2.0, 2.0))
print("Divide:")
print(np.divide(1.0, 4.0))

#10. a NumPy program to compute logarithm of the sum of exponentiations of the inputs, sum of exponentiations of the inputs in base-2.
log1 = np.log(1e-50)
log2 = np.log(2.5e-50)
print("Logarithm of the sum of exponentiations:")
print(np.logaddexp(log1, log2))
print("Logarithm of the sum of exponentiations of the inputs in base-2:")
print(np.logaddexp2(log1, log2))


from .compartment import CompartmentModel
import pandas as pd
import numpy as np

class SIR(CompartmentModel):
    """SIR modelA simple mathematical description of the spread of a disease in a population is the so-called SIR model, which divides the (fixed) population of N individuals into three "compartments" which may vary as a function of time, t:

        S(t) are those susceptible but not yet infected with the disease;
        I(t) is the number of infectious individuals;
        R(t) are those individuals who have recovered from the disease and now have immunity to it.

        The SIR model describes the change in the population of each of these compartments in terms of two parameters, β and γ.
        β - describes the effective contact rate of the disease: an infected individual comes into contact with βN other individuals per unit time (of which the fraction that are susceptible to contracting the disease is S/N).
        γ -  is the mean recovery rate: that is, 1/γ is the mean period of time during which an infected individual can pass it on.

        Reference: https://scipython.com/book/chapter-8-scipy/additional-examples/the-sir-epidemic-model/
    """

    def fit(
        self,
        pop_size: int,
        n_infected: int,
        n_recovered: int,
        contact_rate: float,
        mean_recovery_rate: float,
    ):
        """Fits the SIR Model

            Args:
                pop_size (int): Population size of the region being projected
                n_infected (int): Current number of infected in the region being projected
                n_recovered (int): Current number of recovered in the region being projected
                contact_rate (float) (β): β, contact rate of the disease: an infected individual
                                        comes into contact with βN other individuals per unit time (of which the fraction that are susceptible to contracting the disease is S/N).
                mean_recovery_rate (float): γ, Passed in the form of 1/γ, where:
                                                γ is the mean recovery rate: that is
                                                1/γ is the mean period of time during which an infected individual can pass it on.
        """
        self.pop = pop_size
        self.s0 = pop_size - n_infected - n_recovered
        self.i0 = n_infected
        self.r0 = n_recovered
        self.beta = contact_rate
        self.gamma = mean_recovery_rate

    def predict(self, days: int = 10, plot=False):
        self.initialize_variables(days)
        self.S, self.I, self.R = self.integrate_diff_equations(
            self.y0, self.t, self.pop, self.beta, self.gamma
        )
        self.results = pd.DataFrame(
            {"S": self.S, "I": self.I, "R": self.R}, index=self.t
        )
        return self.results.S, self.results.I, self.results.R

    def initialize_variables(self, days):
        self.days = days
        self.t = np.linspace(0, self.days, self.days)
        self.y0 = self.s0, self.i0, self.r0

    def derivate(self, y, days, pop, beta, gamma):
        S, I, R = y
        dSdt = self.get_Sdt(S, I, pop, beta)
        dIdt = self.get_Idt(S, I, pop, beta, gamma)
        dRdt = self.get_Rdt(I, gamma)
        return dSdt, dIdt, dRdt

    @staticmethod
    def get_Sdt(S, I, pop, beta):
        return -beta * S * I / pop

    @staticmethod
    def get_Idt(S, I, pop, beta, gamma):
        return beta * S * I / pop - gamma * I

    @staticmethod
    def get_Rdt(I, gamma):
        return gamma * I

    def plot(self, save=False):
        super().plot(
            "Time / days", "Number (1000s)", save=save,
        )

    def plot_model(self, ax):
        ax.plot(self.t, self.S / 1000, "b", alpha=0.5, lw=2, label="Susceptible")
        ax.plot(self.t, self.I / 1000, "r", alpha=0.5, lw=2, label="Infected")
        ax.plot(
            self.t, self.R / 1000, "g", alpha=0.5, lw=2, label="Recovered with immunity"
        )
        return ax


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Feb 10 17:02:36 2019

@author: alankar
"""

import numpy as np
from scipy.special.orthogonal import p_roots #Legendre Polynomial roots
import matplotlib.pyplot as plt
#import time

def Hermite_pol(n,x,Outside=True):   #memo is refreshed whenever called from outside, Always keep outside True
    if (Outside):
        global memo #remembers the child recursion loops for speedup
        memo = {}
        try:#So that it may also work with scalar value of x
           memo = {0:np.ones(len(x)),1:2*x}
        except:
           memo = {0:1.,1:2*x}
    if n not in memo:
        N = n-1
        memo[n] = 2*x*Hermite_pol(N,x,False)-2*N*Hermite_pol(N-1,x,False)
    return memo[n]

x = np.linspace(-4,4,100)
plt.figure(figsize=(13,10))
for n in range(4):
    y = Hermite_pol(n,x)
    plt.plot(x,y,label=r'$H_{%d}(x)$'%n)

plt.legend(loc='best',prop={'size': 18})
plt.ylim(-15.0,20.0)
plt.grid()
plt.xlabel(r'$x$',size=22)
plt.ylabel(r'$H_n(x)$',size=22)
plt.title('Hermite Polynomials',size=25,y=1.02)
plt.tick_params(axis='both', which='major', labelsize=15)
plt.tick_params(axis='both', which='minor', labelsize=12)
plt.savefig('13_1.png')
plt.show()

plt.figure(figsize=(13,10))
for n in range(4):
    psi = Hermite_pol(n,x)
    psi *= np.exp(-x**2/2)/np.sqrt((2**n)*np.math.factorial(n)*np.pi**0.5)
    plt.plot(x,psi,label=r'$\psi_{%d}(x)$'%n)

plt.legend(loc='best',prop={'size': 18})
plt.grid()
plt.xlabel(r'$x$',size=22)
plt.ylabel(r'$\psi_n(x)$',size=22)
plt.title('Harmonic Oscillator Wavefunctions',size=25,y=1.02)
plt.tick_params(axis='both', which='major', labelsize=15)
plt.tick_params(axis='both', which='minor', labelsize=12)
plt.savefig('13_2.png')
plt.show()

#t = time.time()
x = np.linspace(-10,10,800)
n = 30
psi = Hermite_pol(n,x)
psi *= (1/np.sqrt(2**n*np.math.factorial(n)*np.sqrt(np.pi)))*np.exp(-x**2/2)
plt.figure(figsize=(13,10))
plt.plot(x,psi,label=r'$\psi_{%d}(x)$'%n)
plt.legend(loc='best',prop={'size': 18})
plt.grid()
plt.xlabel(r'$x$',size=22)
plt.ylabel(r'$\psi_n(x)$',size=22)
plt.title('Harmonic Oscillator Wavefunction',size=25,y=1.02)
plt.tick_params(axis='both', which='major', labelsize=15)
plt.tick_params(axis='both', which='minor', labelsize=12)
plt.savefig('13_3.png')
plt.show()
#print("Took %.2f secs"%(time.time()-t))

def gauss_quad(func,a,b,n,*args):#Legendre
    [x,w] = p_roots(n+1)
    I_G = 0.5*(b-a)*np.sum(w*func(0.5*(b-a)*x+0.5*(b+a),*args))
    return I_G

N = 50
psi = lambda x,n:Hermite_pol(n,x)*(1/np.sqrt(2**n*np.math.factorial(n)*np.sqrt(np.pi)))*np.exp(-x**2/2)
integ = lambda theta,n:np.tan(theta)**2*np.abs(psi(np.tan(theta),n))**2/np.cos(theta)**2

n = 0
uncer = np.sqrt(gauss_quad(integ,-np.pi/2,np.pi/2,N,n))
print('Ground state uncertainty: %.4f'%uncer)

n = 5
uncer = np.sqrt(gauss_quad(integ,-np.pi/2,np.pi/2,N,n))
print('%dth Eigenstate uncertainty: %.4f'%(n,uncer))

"""
Output:

Ground state uncertainty: 0.7071
5th Eigenstate uncertainty: 2.3451
"""


# -*- coding: utf-8 -*-

import numpy as np
from sympy import *
from math import *

def regra_3_8_Simpson(fx,a,h,x):

    return ((3*h)*(fx.subs(x,a) + 3*fx.subs(x,a+h) + 3*fx.subs(x,a+2*h) + fx.subs(x,a+3*h)))/8

x = symbols('x')

fx = sympify(str(input("\n\n   Digite a função f(x): ")))
a = float(input("   Digite o começo do intervalo de integração: "))
b = float(input("   Digite o fim do intervalo de integração: "))
t = float(input("   Digite o modo de integração: (0 - sem repetição, 1 - com repetição): "))

if(t == 0):

    Ir = integrate(fx,(x,a,b))
    Ia = regra_3_8_Simpson(fx,a,abs(b-a)/4,x)
    print("   Integral aproximada: "+str(Ia)+"\n\n")

elif(t == 1):

   m = int(input("   Digite a quantidade m de intervalos: "))

   h = float(abs(b-a)/m)

   if(m*h == (b-a) and (m-4)%3 == 0):
        Ia = 0
        for i in range(0,m,3):
            Ia += regra_3_8_Simpson(fx,a,h,x)
            a += 3*h

        print("   Integral aproximada: "+str(Ia)+"\n\n")
   else:
        print("   Erro: m não está no formato 4 + 3(n-1), onde n é um número inteiro maior do que zero.\n\n")