import numpy as np
from PIL import Image
from matplotlib import pyplot as plt
from numpy.fft import fft2, fftshift, ifft2

# %% read images
img_raw = np.asarray(Image.open('Q5_1.tif'))
row, col = img_raw.shape

# %% spatial filtering
sobel_filter = np.array([[-1, 0, 1],
                         [-2, 0, 2],
                         [-1, 0, 1]])

img_pad = np.pad(img_raw, 1)
img_spatial = np.asarray([(img_pad[i:i + 3, j:j + 3] * sobel_filter).sum()
                          for i in range(row)
                          for j in range(col)]).reshape(row, col)

plt.subplot(121)
plt.imshow(img_raw, cmap='gray')
plt.title('Raw Q5_1.tif')

plt.subplot(122)
plt.imshow(img_spatial, cmap='gray')
plt.title('Sobel filtered Q5_1.tif\n(in spatial domain)')
# plt.savefig('Q5_1_1.png')
plt.show()

# %% freq domain filtering
img_fourier = fftshift(fft2(np.pad(img_raw, ((0, row), (0, col)))))
filter_fourier = fftshift(fft2(np.pad(sobel_filter, ((0, 2 * row - 3), (0, 2 * col - 3)))))

img_view = np.log10(np.abs(img_fourier) + 1).astype(np.uint8)
filter_view = np.abs(filter_fourier).astype(np.uint8)

plt.subplot(121)
plt.imshow(img_view, cmap='gray')
plt.title('Fourier transform of Q5_1.tif\n(Shifted and log transformed)')

plt.subplot(122)
plt.imshow(filter_view, cmap='gray')
plt.title('Fourier transform of Sobel Filter\n(Shifted and log transformed)')
plt.savefig('Q5_1_2.png')
plt.show()

img_freq = np.real(ifft2(fftshift(img_fourier * filter_fourier)))[0:row, 0:col]

plt.subplot(121)
plt.imshow(img_raw, cmap='gray')
plt.title('Raw Q5_1.tif')

plt.subplot(122)
plt.imshow(img_freq, cmap='gray')
plt.title('Sobel Filtered Q5_1.tif\n(in frequency domain)')
plt.savefig('Q5_1_3.png')
plt.show()

# %% no fft shift
img_fourier_no_shift = fft2(np.pad(img_raw, ((0, row), (0, col))))
img_view_no_shift = np.log10(np.abs(img_fourier_no_shift) + 1).astype(np.uint8)
img_freq_no_shift = np.real(ifft2(img_fourier * filter_fourier))[0:row, 0:col]

plt.subplot(121)
plt.imshow(img_view_no_shift, cmap='gray')
plt.title('Fourier transform of Q5_1.tif\n(Not shifted, log transformed)')

plt.subplot(122)
plt.imshow(img_freq_no_shift, cmap='gray')
plt.title('Sobel Filtered Q5_1.tif\n(in frequency domain, not shifted)')
plt.savefig('Q5_1_4.png')
plt.show()


import pandas as pd

import matplotlib.pyplot as plt

import numpy as np

#https://datahub.io/core/s-and-p-500
dat = pd.read_csv("c:/users/jliv/downloads/data_csv.csv")

dat['year']=dat['Date'].apply(lambda x: x[:4])
dat['year']=dat['year'].astype(int)

i = dat.index.values/max(dat.index)

print("Has the SP500 grown strictly exponentially? It can be shown that an exponential model a second exponential model on the exponent can well describe the historical growth of the sp500.")
plt.plot(dat['SP500'])
plt.title("monthly s&p 500: big exponential growth")
plt.xlabel("month since 1871")
plt.show()

print("If growth is exponential, evaluating log(sp500) can render growth linear. It is observable that the log-trend still grows more in recent history than in early history.")
plt.plot(np.log(dat['SP500']))
plt.title("monthly log s&p 500: growing faster and faster, but linear in part")
plt.xlabel("month since 1871")
plt.show()

print("Using a homomorphism on i (normalized month since 1871), functionally a**i for some a, 'a' can be chosen to map the normalized month to a new value in space a**i, such that small i are mapped to a closer proximity to each other than large i.")
a=6
plt.scatter(i,a**i)
plt.title("i (month since 1871, normalized), maps to a**i \n stretching high i and compressing low i")
plt.xlabel("i = month since 1871 normalized")
plt.ylabel("a**i")
plt.show()

print("Initial guess of a is "+str(a)+", such that plot log_a(sp500) against a**i is as linear as possible.")
plt.plot(a**i,np.log(dat['SP500'])/np.log(a))
plt.title("warping x axis: a**x; a="+str(a)+", compressing low x \n stretching high x, even more linear")
plt.xlabel("a**i")
plt.ylabel("log_a(sp500)")
plt.show()

print("With initial a = "+str(a)+", fitting linear model X=[a**i,1] to log_a(sp500) for inital guess of beta.  log_a(sp500)=b1*i'+b0 where i'=a**i")
X = np.column_stack([a**i,np.ones(len(i))])
Y=np.log(dat['SP500'])/np.log(a)
beta = np.linalg.inv(X.T@X)@(X.T@Y)

Yhat=X@beta

plt.plot(a**i,Y)
plt.plot(a**i,Yhat)
plt.title("Fitting a linear model this can be abstracted into an exponential curve \n with respect to a power-warped axis")
plt.xlabel("a**i")
plt.ylabel("log_a(sp500)")
plt.show()

print("Plotting log_a(Y) over unmorphed i scale, exponential growth is observable. Here log_5(sp500)=b1*a**i+b0")
plt.plot(i,Y)
plt.plot(i,Yhat)
plt.ylabel("i")
plt.title("This growth is well behaved with respect to a**i, and thus, i")
plt.show()

print("Plotting Y over unmorphed i scale, growth is exponential, and the exponent grows exponentially. Here sp500=a**(b1*a**i+b0). The shape is largely correct, but parameters a, b1 and b0 can be tuned with gradient descent.")
plt.plot(i,a**Y)
plt.plot(i,a**Yhat)
plt.ylabel("i")
plt.title("This growth is well behaved with respect to a**i, and thus, i")
plt.show()

print("Setting Y to be sp500, x is i (normalized month since 1870).")
print("Model is Y=a**(b1*a**i+b0), from visual analysis above, initial a guessed "+str(a)+", and model fit given a="+str(a)+" yielded beta vector "+ str(beta)+".")

print("Derivative of SSE cost function is evaluated using each of a, b1 and b0.")
print("In terms of a: (a**(b1*a**X+b0)-Y)@(a**(b1*a**X+b0-1)*(b1*a**X+b0+b1*X*np.log(a)*a**X))")
print("In terms of b1: (a**(b1*a**X+b0)-Y)@(np.log(a)*a**(b1*a**X+b0+X))")
print("In terms of b0: (a**(b1*a**X+b0)-Y)@(np.log(a)*a**(b1*a**X+b0))\n")

Y=dat['SP500']
X = i

l=.00000000001
tol=1e-8
a,b1,b0=a,beta[0],beta[1]
e1=1e5
for c in range(15000):
    err = (a**(b1*a**X+b0)-Y)

    e2=np.mean(abs(err))

    if e1-e2<tol:
        break
    else:
        e1=e2
    grad_mod_a = a**(b1*a**X+b0-1)*(b1*a**X+b0+b1*X*np.log(a)*a**X)
    grad_mod_b1=np.log(a)*a**(b1*a**X+b0+X)
    grad_mod_b0 = np.log(a)*a**(b1*a**X+b0)

    grad_a=err@grad_mod_a
    grad_b1=err@grad_mod_b1
    grad_b0=err@grad_mod_b0

    a,b1,b0=a-l*grad_a,b1-l*grad_b1,b0-l*grad_b0

print(np.mean(abs(err)))
print("After gradient descent, new a, b1 and b0 are:",a,b1,b0)
yhat=a**(b1*a**X+b0)

print("With learned a, b1 and b0, model well-defines historical growth of the market.")
plt.plot(Y)
plt.plot(yhat)
plt.show()


import numpy as np
import matplotlib.pyplot as plt

"""
A2-Part-1: Generate a sinusoid

Write a function to generate a real sinusoid (use np.cos()) given its amplitude A, frequency f (Hz), initial phase phi (radians),
sampling rate fs (Hz) and duration t (seconds).

All the input arguments to this function (A, f, phi, fs and t) are real numbers such that A, t and fs are
positive, and fs > 2*f to avoid aliasing. The function should return a numpy array x of the generated
sinusoid.

EXAMPLE: If you run your code using A=1.0, f = 10.0, phi = 1.0, fs = 50.0 and t = 0.1, the output numpy
array should be: array([ 0.54030231, -0.63332387, -0.93171798,  0.05749049,  0.96724906])
"""
def genSine(A, f, phi, fs, t):
    """
    Inputs:
        A (float) =  amplitude of the sinusoid
        f (float) = frequency of the sinusoid in Hz
        phi (float) = initial phase of the sinusoid in radians
        fs (float) = sampling frequency of the sinusoid in Hz
        t (float) =  duration of the sinusoid (is second)
    Output:
        The function should return a numpy array
        x (numpy array) = The generated sinusoid (use np.cos())
    """
    Xs = []
    Tn = np.arange(0.0, t, 1.0/fs)
    lenTn = int(t*fs)
    for i in range(lenTn):
        Xs.append(A*np.cos(2*np.pi*f*Tn[i] + phi))
    x = np.array(Xs)
    return(x)

sinA = genSine(0.5, 2.0, 0.0, 1000.0, 2.0)
sinB = genSine(0.5, 2.0, 0.0, 1000.0, 2.0)
sinSum = sinA + sinB
plt.plot(sinA)
plt.plot(sinB)
plt.plot(sinSum)


import random
import time
import numpy as np

# Check if a number is a power of 2 using bit manipulations
def pow_of_2_check(n: int) -> bool:
    assert n > 0, f"The number for power-of-2-check should be a POSITIVE integer. Here n = {n}."
    return n & (n - 1) == 0  # &: bit-wise and

# O(n**log_2^7) sub-cubic time complexity
def strassen_mat_mult(m1: np.ndarray, m2: np.ndarray) -> np.ndarray:
    assert pow_of_2_check(m1.shape[0]) and m1.shape[0] == m1.shape[1] == m2.shape[0] == m2.shape[1], \
        f"Both mat should be of shape 2^n*2^n with the same n. Here the shapes are {m1.shape}, {m2.shape}."

    n = m1.shape[0]
    if n <= 2:  # Base case
        return m1 @ m2
    else:
        # Split m1 and m2 evenly into 4 sub-matrices each
        half_n = n//2
        a, b, c, d = m1[:half_n, :half_n], m1[:half_n, half_n:], m1[half_n:, :half_n], m1[half_n:, half_n:]
        e, f, g, h = m2[:half_n, :half_n], m2[:half_n, half_n:], m2[half_n:, :half_n], m2[half_n:, half_n:]
        # Compute the 7 products
        p1 = strassen_mat_mult(a, f-h)
        p2 = strassen_mat_mult(a+b, h)
        p3 = strassen_mat_mult(c+d, e)
        p4 = strassen_mat_mult(d, g-e)
        p5 = strassen_mat_mult(a+d, e+h)
        p6 = strassen_mat_mult(b-d, g+h)
        p7 = strassen_mat_mult(a-c, e+f)
        # Combine the results
        output_1 = p5 + p4 - p2 + p6
        output_2 = p1 + p2
        output_3 = p3 + p4
        output_4 = p1 + p5 - p3 - p7
    return np.concatenate((np.concatenate((output_1, output_2), axis=1), np.concatenate((output_3, output_4), axis=1)),
                          axis=0)

if __name__ == '__main__':
    # Test function "pow_of_2_check"
    test = 1483948
    print(f"The number is a power of 2: {pow_of_2_check(test)}")
    test = 2 ** 10
    print(f"The number is a power of 2: {pow_of_2_check(test)}")

    # Test Strassen matrix multiplication algorithm
    mat_size = 2**6
    mat_1 = random.randint(1, 100)*np.random.rand(mat_size, mat_size)
    mat_2 = random.randint(1, 100)*np.random.rand(mat_size, mat_size)
    ans = strassen_mat_mult(mat_1, mat_2)
    # print(f"Product = {ans}")
    print(f"Normalized Fresenius norm of (ans - np mat mult result): {np.linalg.norm(ans - mat_1@mat_2)/mat_size}")

    repetition = int(1e2)
    start = time.time()
    for _ in range(repetition):
        strassen_mat_mult(mat_1, mat_2)
    print(f"Strassen matrix multiplication average time = {(time.time() - start)/repetition}s")


from math import sqrt, pi, exp
import numpy as np

def distance(x1, y1, x2, y2):
    """
    Distance between two points (x1, y1), (x2, y2).
    """
    return sqrt((x1-x2)**2 + (y1-y2)**2)

def array_dist(p1, p2):
    """
    Distance between two points represented by arrays.
    """
    return distance(p1[0], p1[1], p2[0], p2[1])

def direction(p1, p2):
    """
    Direction between two points p1 and p2.
    """
    return (p2-p1)/distance(p1[0], p1[1], p2[0], p2[1])

def theta(v1, v2):
    """
    Computes angle between two vectors
    """
    val = v1.dot(v2)/(np.linalg.norm(v1)*np.linalg.norm(v2))
    if val > 1:
        print(val, v1, v2)
        return np.arccos(1)
    elif val < -1:
        print(val, v1, v2)
        return np.arccos(-1)
    return np.arccos(val)

def proj(v1, v2):
    """
    Computes projection of v1 onto v2
    """
    return np.dot(v1, v2)/np.linalg.norm(v2)

def t1_force(t):
    M = 0.01
    N = 15
    s1 = 2
    s2 = 0.3
    sig_square = s1**2 + s2**2

    s = s1**2 + s2**2
    A = -(M * N) / sqrt(2*pi*s)
    return A * exp(-(t**2) / (2*s)) * (-t/s)
    #return (M*N*t/(ss*sqrt(2*pi*ss))) * exp(-(t**2)/(2*ss))
    #return ((M*N)/(sqrt(2*pi*sig_square))) * ((2*t*exp((-t**2)/(2*sig_square)))/(2*sig_square))

def t2_force(p, orig):
    return 0.005*array_dist(p, orig)

def ccw(A, B, C):
    """
    Check if a point C is counter-clockwise to AB.
    """
    return (C[1] - A[1])*(B[0]-A[0]) > (B[1]-A[1])*(C[0]-A[0])

def is_intersect(A, B, C, D):
    """
    Check if two line segments AB and CD intersect.
    """
    return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D)

def line_line_segment_intersect(p, d, p1, p2):
    """
    Check if a line defined by point p and direction d intersects
    a segment p1p2.
    """

    extend1 = [p[0] + 500000*d[0], p[1] + 500000*d[1]]
    extend2 = [p[0] - 500000*d[0], p[1] - 500000*d[1]]

    return is_intersect(p, extend1, p1, p2) or is_intersect(p, extend2, p1, p2)

def minDistance(A, B, E) :
    """
    Minimum distance from a point E to line segment AB. Adapted from GeeksforGeeks.
    """

    # vector AB
    AB = [None, None]
    AB[0] = B[0] - A[0]
    AB[1] = B[1] - A[1]

    # vector BP
    BE = [None, None]
    BE[0] = E[0] - B[0]
    BE[1] = E[1] - B[1]

    # vector AP
    AE = [None, None]
    AE[0] = E[0] - A[0]
    AE[1] = E[1] - A[1]

    # Variables to store dot product

    # Calculating the dot product
    AB_BE = AB[0] * BE[0] + AB[1] * BE[1]
    AB_AE = AB[0] * AE[0] + AB[1] * AE[1]

    # Minimum distance from
    # point E to the line segment
    reqAns = 0

    # Case 1
    if (AB_BE > 0) :

        # Finding the magnitude
        y = E[1] - B[1]
        x = E[0] - B[0]
        reqAns = sqrt(x * x + y * y)

    # Case 2
    elif (AB_AE < 0) :
        y = E[1] - A[1]
        x = E[0] - A[0]
        reqAns = sqrt(x * x + y * y)

    # Case 3
    else:

        # Finding the perpendicular distance
        x1 = AB[0]
        y1 = AB[1]
        x2 = AE[0]
        y2 = AE[1]
        mod = sqrt(x1 * x1 + y1 * y1)
        reqAns = abs(x1 * y2 - y1 * x2) / mod

    return reqAns


#!/usr/bin/env python
# coding: utf-8
# ## Monte Carlo - Euler Discretization - Part II
# *Suggested Answers follow (usually there are multiple ways to solve a problem in Python).*
# *Euler Discretization – continued.*
# In[1]:
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')
ticker = 'MSFT'
data = pd.DataFrame()
data[ticker] = web.DataReader(ticker, data_source='yahoo', start='2000-1-1')['Adj Close']
log_returns = np.log(1 + data.pct_change())
stdev = log_returns.std() * 250 ** 0.5
stdev = stdev.values
r = 0.025
T = 1.0
t_intervals = 250
delta_t = T / t_intervals
iterations = 10000
Z = np.random.standard_normal((t_intervals + 1, iterations))
S = np.zeros_like(Z)
S0 = data.iloc[-1]
S[0] = S0
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])
plt.figure(figsize=(10, 6))
plt.plot(S[:, :10]);
# ******
# Use numpy.maximum to create a vector with as many elements as there are columns in the S matrix.
# In[2]:
p = np.maximum(S[-1] - 110, 0)
# In[3]:
p
# In[4]:
p.shape
# Use the following formula to forecast the price of a stock option.
# $$
# C = \frac{exp(-r \cdot T) \cdot \sum{p_i}}{iterations}
# $$
# In[5]:
np.sum(p)
# In[6]:
C = np.exp(-r * T) * np.sum(p) / iterations
C
# Because this pricing model is based on random iterations, you will obtain a different result every time you re-run the code in this document. Expand the “Kernel” list from the Jupyter menu and click on “Restart and run all”/”Restart & run all cells” to verify this is true.


#!usr/bin/python
"""
author  : Bhekimpilo Ndhlela
author  : 18998712
module  : Applied Mathematics(Numerical Methods) TW324
task    : computer assignment 04 question 4
since   : Friday-23-03-2018
"""
def trapezium(exact_I, H, x0=0., debug=True):
    apprx_I = array([h/2. * (exp(x0) + exp(h)) for h in H])
    return array([abs(apI - exI) for apI, exI in zip(apprx_I, exact_I)])

def midpoint(exact_I, H, x0=0., debug=True):
    W = array([x0 + (h / 2.0) for h in H])
    apprx_I = array([h * exp(w) for h, w in zip(H, W)])
    return array([abs(apI - exI) for apI, exI in zip(apprx_I, exact_I)])

def simpson(exact_I, H, x0=0., debug=True):
    apprx_I = array([h/6.*(exp(x0)+(4.*exp(h/2.))+exp(h)) for h in H])
    return array([abs(apI - exI) for apI, exI in zip(apprx_I, exact_I)])

def debug(abs_err_s, abs_err_m, abs_err_t, debug=True):
    if debug is True:
        print "DEBUG MODE: [ON] [Question 4 Simpson's method]"
        print "SIMPSONS METHOD\t\tMIDPOINT METHOD\t\tTRAPEZIUM METHOD"
        for s, m, t in zip(abs_err_s, abs_err_m, abs_err_t):
            print "{:.20f}".format(s),"{:.20f}".format(m),"{:.20f}".format(t)
    else:
        print "DEBUG MODE: [OFF] [Question 4 Simpson's method]"

def plot_abs_errs(abs_err_t, abs_err_m, abs_err_s):
    #loglog plot to display the error as function of the step size
    plt.title("|xc-x| of: The Midpoint, Simpson & Trapezium Methods against h")
    plt.ylabel("Midpoint vs Simpson vs Trapezium")
    plt.xlabel("h")
    plt.yscale('log'); plt.xscale('log')
    plt.plot([1., .1, .01], abs_err_t, "k-", label="Trapezium")
    plt.plot([1., .1, .01], abs_err_m, "r-", label="Midpoint")
    plt.plot([1., .1, .01], abs_err_s, "g-", label="Simpson")
    plt.legend(bbox_to_anchor=(.65, .9))
    plt.show()

if __name__ == "__main__":
    from numpy import (exp, abs, array)
    import matplotlib.pyplot as plt

    H         = array([1., .1, .01])
    exact_I   = array([exp(h) - 1 for h in H])

    abs_err_t = trapezium(exact_I, H)
    abs_err_m = midpoint(exact_I, H)
    abs_err_s = simpson(exact_I, H)

    debug(abs_err_s, abs_err_m, abs_err_t)
    plot_abs_errs(abs_err_t, abs_err_m, abs_err_s)
else:
    from sys import exit
    exit("USAGE: python q5.py")


import numpy as np
import matplotlib.pyplot as plt

# Give the parameters.
H0 = 7.16e-11 # [yr^-1]
omega_0 = 1

# Define a and time-derivative of a.
a = lambda t: ((3/2)*H0*t)**(2/3)
a_dot = lambda t: H0*((3/2)*H0*t)**(-1/3)

# Define the function to be solved.
def ode(t, y):

    """
    y ... A vector function containing D and dD/dt
    t ... time to integrate over

    """

    # Define the initial conditions. Will assign values later.
    D , dD_dt = y[0], y[1]

    d2D_dt2 = -2*(a_dot(t)/a(t))*dD_dt + (3/2)*omega_0*(H0**2)*(D/(a(t)**3))

    return np.array([dD_dt, d2D_dt2])

# define the solver method.
def rk4(ode,y,t,h):

    """
    ode ... ordinary differential equation to solve
    y   ... A vector fucntion containing D and dD/dt
    t   ... time to integrate over
    h   ... integration step

    Method using here is the classic Runge-Kutta (4-th order), acquired L10.

    """

    k1 = h * ode(t, y)
    k2 = h * ode(t+h/2., y+k1/2.)
    k3 = h * ode(t+h/2., y+k2/2.)
    k4 = h * ode(t+h, y+k3)

    return k1/6. + k2/3. + k3/3. + k4/6.

# Define the ode solver.
def ode_solver(init, lower, upper, N):

    # Define the integration step.
    h = (upper-lower)/N

    # Define initial conditions and assign values.
    y, t_values, D_values = init, [], []

    # Solve the ode using rk4.
    for i in np.arange(lower, upper, h):
        t_values.append(i)
        D_values.append(y[0])
        y += rk4(ode,y,i,h)

    return t_values, D_values

# Define the time range and number of data points.
t_init, t_final, t_step = 1., 1000., 10
N = (t_final-t_init)*t_step

# Plot given the initial conditions.
plt.figure()

case1, case2, case3 = [3,2], [10,-10], [5,0]
all_cases = [[case1,'case1'], [case2,'case2'], [case3,'case3']]

for i in range(len(all_cases)):
    t_values, D_values = ode_solver(all_cases[i][0], t_init, t_final, N)
    plt.loglog(t_values, D_values, label=all_cases[i][1])

plt.xlabel('t', fontsize=14)
plt.ylabel('D(t)', fontsize=14)
plt.legend()

plt.savefig('./plots/handin2_p3.png')
plt.close()


import math
import numpy as np

def evenParity(n):
	"""Determines if n is an even parity.

	Calculates the number of 1 bits in the binary representation of the given
	integer, n. An even parity is true if the number of 1 bits in the
	representation is even.

	Args:
		n: integer to check for even parity.

	Returns:
		A 0 if n is an even parity, else a 1.
	"""
	binary =  "{0:b}".format(n)
	return binary.count('1') % 2

def oddParity(n):
	"""Determines if n is an odd parity.

	Calculates the number of 1 bits in the binary representation of the given
	integer, n. If the number is odd,  outputs a 0. If the number is even,
	outputs a 1.

	Args:
		n: integer to check for odd parity.

	Returns:
		A 0 if n is an odd parity, else a 1.
	"""
	binary = "{0:b}".format(n)
	return (binary.count('1') + 1) % 2

def adder(n):
	"""Adds 42 to a given number.

	Args:
		n: integer to add to.

	Returns:
		The value of n added by 42.
	"""
	return n + 42

def addThem(n, m):
	"""Calculates the sum of n and m.

	Args:
		n: an integer to add.
		m: an integer to add.
	Returns:
		The sum of n and m.
	"""
	return n + m

def multiply(n, m):
	"""Returns n multiplied by m.

	Args:
		n: integer to be multiplied by
		m: integer to be multiplied by

	Returns:
		The product of n and m.
	"""
	return n * m

def multiplyAndAdd(n, m):
	"""Adds 5 to n, adds 7 to m, and returns the product of the two.

	f(n, m) = (n + 5) * (m + 7)

	Args:
		n: integer as an input to the function
		m: integer as an input to the function

	Returns:
		The output of the function given n and m.
	"""
	return (n + 5) * (m + 7)

def makePalindrome(s):
	"""Makes a palindrome from a given string.

	Reverses and appends s to the end of s. This guarantees the return
	statement is a palindrome.

	Args:
		s: a string

	Returns:
		A palindrome formed by appending s reversed to the end of s.
	"""
	return s + s[::-1]

def isPalindrome(s):
	"""Validates whether the input is a palindrome.

	Args:
		s: a string

	Returns:
		True if the input is a valid palindrome, else False.
	"""
	return all(s[i] == s[-i - 1] for i in range(len(s) >> 1))

def sine(x):
	"""Returns the sin of x radians.

	Args:
		x: number of radians

	Returns:
		The sine of x radians.
	"""
	return math.sin(x)

def expansionTerms(x):
	output = np.zeros(9, dtype='float32')
	n = 1
	for i in range(9):
		if i % 2 == 0:
			output[i] = float((x ** n) / math.factorial(n))
		else:
			output[i] = float(-(x ** n) / math.factorial(n))
		n += 2
	return output

def fib(n):
	"""Approximates the nth Fibonacci number.

	Since this uses Binet's formula, it is only exactly accurate from 1 to 70.
	Past n values of 70, it is only an approximation.

	Binet's formula is defined as:
	F(n) = ((Phi ^ n) - ((- Phi) ^ -n)) / sqrt(5)
			 = (((1 + sqrt(5)) / 2) ^ n) - ((1 - sqrt(5)) / 2) ^ n)) / sqrt(5))

	Args:
		n: integer for the nth number in the Fibonacci sequence

	Returns:
		The output of Binet's forumula with input n, an approximation of the nth
		number in the Fibonacci sequence.
	"""
	return round(((((1 + math.sqrt(5)) / 2) ** n)
				- (((1 - math.sqrt(5)) / 2) ** n))
				/ math.sqrt(5))

def testFibAccuracy():
	"""Calculates when the function fib(n) becomes inaccurate.

	Exactly up to 70.
	71 - 72 are off by 1.
	73 and on are off by more than 1.

	Returns:
		fn: the last Fibonacci number found by using the recursive function.
		count: the number of Fibonacci numbers calculated.
		fib(count): an approximation for the last Fibonacci number.
	"""
	fn = f1 = f2 = 1
	count = 2
	while (fn == fib(count)) | (fn == fib(count) + 1) | (fn == fib(count) - 1):
		fn = f1 + f2
		f2, f1 = f1, fn
		count+=1
	return fn, count, fib(count)

def determinant(m):
	"""Calculates the determinant of a matrix.

	Args:
		m: array of arrays that represents a matrix.

	Returns:
		The determinant of a matrix.
	"""
	return np.linalg.det(m)

def main():
	print("evenParity(2) ->", evenParity(2))
	print("evenParity(3) ->", evenParity(3))
	print("evenParity(10) ->", evenParity(10))
	print("oddParity(2) ->", oddParity(2))
	print("oddParity(3) ->", oddParity(3))
	print("oddParity(10) ->", oddParity(10))
	print("oddParity(1243) + evenParity(1243) == 1 ->",
		   oddParity(1243) + evenParity(1243) == 1)
	print("adder(1) ->", adder(1))
	print("adder(5) ->", adder(5))
	print("multiply(3, 7) ->", multiply(3, 7))
	print("multiplyAndAdd(3, 7) ->", multiplyAndAdd(3, 7))
	print("isPalindrome('abc') ->", isPalindrome('abc'))
	print("isPalindrome('yootnooy') ->", isPalindrome('yootnooy'))
	print("makePalindrome('This is the final countdown!') ->",
		makePalindrome('This is the final countdown!'))
	print("isPalindrome(makePalindrome('This is the final countdown!')) ->",
		isPalindrome(makePalindrome('This is the final countdown!')))
	print("sine(math.pi) ->", sine(math.pi))
	print("sine(math.pi / 2) ->", sine(math.pi / 2))
	print("fib(2) ->", fib(2))
	print("fib(3) ->", fib(3))
	print("fib(4) ->", fib(4))
	print("fib(5) ->", fib(5))
	print("fib(6) ->", fib(6))
	fn, count, approx = testFibAccuracy()
	print("Actual", count, "number in fib sequence =", fn,
		"Approximation =", approx)

if __name__ == "__main__":
    main()


"""
This script plots the analytic solution to the differential equation in
exercise 2.2.3 of the book `Nonlinear Dynamics and Chaos` by Steven H. Strogatz.
"""
import matplotlib.pyplot as plt
import numpy as np

def get_velocities(times, x0: float):
    # Fix the integration constant using the initial condition
    c = 1.0 / (x0 ** 2) - 1.0
    if x0 < 0.0:
        return -1.0 / np.sqrt(1.0 + c * np.exp(-2.0 * times))
    else:
        return +1.0 / np.sqrt(1.0 + c * np.exp(-2.0 * times))

if __name__ == "__main__":
    # The set of initial conditions that we use.
    initial_conditions = [2.0, 0.7, 0.5, 0.3, -0.3, -0.5, -0.7, -2.0]

    # The time steps we use
    time_steps = np.linspace(0, 3, 100)

    fig, ax = plt.subplots()

    plt.title(r"$\dot{x}=x-x^3$")
    plt.xlabel("t")
    plt.ylabel("x")
    for counter, ic in enumerate(initial_conditions):
        velocities = get_velocities(time_steps, ic)
        ax.plot(time_steps, velocities, color=f"C{counter}")

    # Add the fixed points
    plt.plot(time_steps, np.zeros(len(time_steps)), color="gray", linestyle="-.")
    plt.plot(time_steps, np.ones(len(time_steps)), color="gray", linestyle="--")
    plt.plot(time_steps, -np.ones(len(time_steps)), color="gray", linestyle="--")

    # Draw the plot
    # plt.savefig('ex_2_2_3.pdf')
    plt.show()


import numpy as np
import skimage
import utils
import pathlib
import matplotlib.pyplot as plt
import functools as ft

'''
[1.0 points] Implement a function in task2a.py/task2a.ipynb that implements Otsu’s algorithm for thresholding, and returns a single threshold value.
Segment the images thumbprint.png and polymercell.png, and include the results in your report.
'''
def sum_to_threshhold(arr: np.ndarray, threshold: int):
    sum = 0
    for i, el in enumerate(arr):
        if(i < threshold):
            sum+=el

    return sum

def mean_to_threshhold(arr: np.ndarray, threshold: int, less_than: bool):
    numerator_sum = 0
    divisor_sum = 0

    if(less_than):
        for i, el in enumerate(arr):
            if(i < threshold):
                numerator_sum += i * el
                divisor_sum += el
    else:
        for i, el in enumerate(arr):
            if(i >= threshold):
                numerator_sum += i * el
                divisor_sum += el

    return numerator_sum/divisor_sum

def otsu_thresholding(im: np.ndarray) -> int:
    """
        Otsu's thresholding algorithm that segments an image into 1 or 0 (True or False)
        The function takes in a grayscale image and outputs a boolean image

        args:
            im: np.ndarray of shape (H, W) in the range [0, 255] (dtype=np.uint8)
        return:
            (int) the computed thresholding value
    """
    assert im.dtype == np.uint8
    # START YOUR CODE HERE ### (You can change anything inside this block)
    # You can also define other helper functions

    # Compute normalized histogram
    intensity_count = np.zeros(256)
    for i in range(len(im)):
        for j in range(len(im[i])):
            intensity_count[im[i][j]] += 1

    #test = [9,6,4,5,8,4]
    num_pixels = im.shape[0]*im.shape[1]
    best_between_class_variance = -100
    best_threshold = -1
    # Check for each threshold if it produces a better between class variance
    for threshold in range(1,256):
        background_percentage = sum_to_threshhold(intensity_count, threshold)/num_pixels
        foreground_percentage = 1-background_percentage

        background_mean = mean_to_threshhold(intensity_count, threshold, True)
        foreground_mean = mean_to_threshhold(intensity_count, threshold, False)

        between_class_variance = background_percentage*foreground_percentage*(background_mean-foreground_mean)**2
        if(best_between_class_variance < between_class_variance):
            best_between_class_variance = between_class_variance
            best_threshold = threshold

    threshold = best_threshold
    '''
    plt.imshow(im, cmap="gray")
    plt.show()
    '''
    # Plot intensity distribution
    intensity_levels = list(range(0,256))
    plt.bar(intensity_levels, intensity_count)
    plt.show()

    return threshold
    ### END YOUR CODE HERE ###

if __name__ == "__main__":
    # DO NOT CHANGE
    impaths_to_segment = [
        pathlib.Path("thumbprint.png"),
        pathlib.Path("polymercell.png"),
        pathlib.Path("defective-weld.png")
    ]
    for impath in impaths_to_segment:
        im = utils.read_image(impath)
        threshold = otsu_thresholding(im)
        print("Found optimal threshold:", threshold)

        # Segment the image by threshold
        segmented_image = (im >= threshold)
        assert im.shape == segmented_image.shape, "Expected image shape ({}) to be same as thresholded image shape ({})".format(
            im.shape, segmented_image.shape)
        assert segmented_image.dtype == np.bool, "Expected thresholded image dtype to be np.bool. Was: {}".format(
            segmented_image.dtype)

        segmented_image = utils.to_uint8(segmented_image)

        save_path = "{}-segmented.png".format(impath.stem)
        utils.save_im(save_path, segmented_image)


# -*- coding: utf-8 -*-
"""
Created on Sat Mar 23 22:36:14 2019

INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA DO PÁRA - IFPA ANANINDEUA

@author:
        Prof. Dr. Denis C. L. Costa

        Discentes:
            Heictor Alves de Oliveira Costa
            Lucas Pompeu Neves

Grupo de Pesquisa:
                 Gradiente de Modelagem Matemática e
                 Simulação Computacional - GM²SC

Assunto:
        Derivadas Parciais

Nome do sript: derivadas_parciais

Disponível em:
    https://github.com/GM2SC/DEVELOPMENT-OF-MATHEMATICAL-METHODS-IN-
    COMPUTATIONAL-ENVIRONMENT/blob/master/SINEPEM_2019/derivadas_parciais.py

"""

# Bibliotecas

# Cálculo Diferencial e Integral: sympy
import sympy as sy

# Variáveis simbólicas
x,y = sy.symbols('x,y')

print('')

# Função de várias Variáveis: f(x,y)
def f(x,y):
    return 3*x**2*y**3

# (f(x,y), x, 1) --> (Função, variável, ordem da derivada)
# Derivada em função de x: dfx(x,y)
def dfx(x,y):
    return sy.diff(f(x,y), x, 1)
# Derivada em função de y: dfy(x,y)
def dfy(x,y):
    return sy.diff(f(x,y), y, 1)
print('')
print('=======================================================')
print('Função Analisada: f(x,y) =', f(x,y))

print('Derivada Parcial em função de x: dfx(x,y) =', dfx(x,y))

print('Derivada Parcial em função de y: dfy(x,y) =', dfy(x,y))

print('=======================================================')
print('')
# Valor Numérico das Derivadas Parciais
print('Valor Numérico da Derivada Parcial dfx')
x1 = 2; y1 = -1
print('nos pontos x1 e y1 -->', (x1,y1))

VN_dfx= dfx(x,y).subs(x,x1).subs(y,y1)
print('VN_dfx =', VN_dfx)

print('')
print('Valor Numérico da Derivada Parcial dfy')
x2 = 1; y2 = 3
print('nos pontos x2 e y2 -->', (x2,y2))
VN_dfy= dfy(x,y).subs(x,x2).subs(y,y2)
print('VN_dfy =', VN_dfy)

print('')
print('---> Fim do Programa derivadas_parciais <---')


import numpy
from matplotlib import pyplot

def forward_difference(f, x0, h):
    return (f(x0+h) - f(x0)) / h
def backward_difference(f, x0, h):
    return (f(x0) - f(x0-h)) / h
def central_difference(f, x0, h):
    return (f(x0+h) - f(x0-h)) / (2*h)

def euler(f, x_end, y0, N):
    x, dx = numpy.linspace(0, x_end, N+1, retstep=True)
    y = numpy.zeros((len(y0),N+1))
    y[:,0] = y0
    for n in range(N):
        y[:,n+1] = y[:,n] + dx * f(x[n], y[:,n])
    return x, dx, y

if __name__=="__main__":
    h = 0.5
    print("Forward difference, h=",h, "y'=",
          forward_difference(numpy.exp, 0, h))
    print("Backward difference, h=",h, "y'=",
          backward_difference(numpy.exp, 0, h))
    print("Central difference, h=",h, "y'=",
          central_difference(numpy.exp, 0, h))
    h = 0.05
    print("Forward difference, h=",h, "y'=",
          forward_difference(numpy.exp, 0, h))
    print("Backward difference, h=",h, "y'=",
          backward_difference(numpy.exp, 0, h))
    print("Central difference, h=",h, "y'=",
          central_difference(numpy.exp, 0, h))
    h_all = 0.5/2**numpy.arange(1,10)
    errors_forward = numpy.zeros_like(h_all)
    errors_backward = numpy.zeros_like(h_all)
    errors_central = numpy.zeros_like(h_all)
    for i, h in enumerate(h_all):
        errors_forward[i] = abs(1 - forward_difference(numpy.exp, 0, h))
        errors_backward[i] = abs(1 - backward_difference(numpy.exp, 0, h))
        errors_central[i] = abs(1 - central_difference(numpy.exp, 0, h))
    pyplot.figure(figsize=(12,6))
    pyplot.loglog(h_all, errors_forward, 'kx', label="Forward")
    pyplot.loglog(h_all, errors_backward, 'bo', label="Backward")
    pyplot.loglog(h_all, errors_central, 'r^', label="Central")
    pyplot.loglog(h_all, h_all/h_all[0]*errors_forward[0], 'b-',
                  label=r"$\propto h$")
    pyplot.loglog(h_all, (h_all/h_all[0])**2*errors_central[0], 'g-',
                  label=r"$\propto h^2$")
    pyplot.xlabel(r"$h$")
    pyplot.ylabel("Error")
    pyplot.legend(loc="upper left")
    pyplot.show()

    def f_sin(x, y):
        return -numpy.sin(x)
    print("Euler's Method")
    x, dx, y = euler(f_sin, 0.5, [1], 5)
    print("dx=", dx, "y(0.5)=", y[0,-1])
    x, dx, y = euler(f_sin, 0.5, [1], 50)
    print("dx=", dx, "y(0.5)=", y[0,-1])
    Npoints = 5*2**numpy.arange(1,10)
    dx_all = 0.5/Npoints
    errors = numpy.zeros_like(dx_all)
    for i, N in enumerate(Npoints):
        x, dx, y = euler(f_sin, 0.5, [1], N)
        errors[i] = abs(y[0,-1] - numpy.cos(0.5))
        dx_all[i] = dx
    pyplot.figure(figsize=(12,6))
    pyplot.loglog(dx_all, errors, 'kx')
    pyplot.loglog(dx_all, errors[0]*(dx_all/dx_all[0])**1, 'b-',
                  label=r"$\propto \Delta x$")
    pyplot.legend(loc='upper left')
    pyplot.xlabel(r"$\Delta x$")
    pyplot.ylabel("Error")
    pyplot.show()

    def f_circle(x, y):
        dydx = numpy.zeros_like(y)
        dydx[0] = -y[1]
        dydx[1] = y[0]
        return dydx
    y0 = numpy.array([1, 0])
    x, dx, y = euler(f_circle, 50, y0, 500)
    pyplot.figure(figsize=(8,8))
    pyplot.plot(y[0,:], y[1,:])
    pyplot.show()
    x, dx, y = euler(f_circle, 50, y0, 5000)
    pyplot.figure(figsize=(8,8))
    pyplot.plot(y[0,:], y[1,:])
    pyplot.show()


import os
import time
import json
import math
import pandas as pd
from scipy import stats
from prettytable import PrettyTable

os.chdir('..')
path = os.getcwd()

def simpleLinear(filename):

    with open(filename, newline='') as csvFile:
        start = time.time()
        df = pd.read_csv(csvFile)
        elapsed = time.time() - start
        print("Read Time ->", round(elapsed, 4), "seconds.")
        start = time.time()
        x = df['X']
        y = df['Y']
        avg_x = x.mean()
        avg_y = y.mean()
        diff_x = []
        diff_y = []
        for index, row in df.iterrows():
            diff_x.append(row['X'] - avg_x)
            diff_y.append(row['Y'] - avg_y)
        b1_numerator = sum([i * j for i, j in zip(diff_x, diff_y)])
        b1_denominator = sum([i ** 2 for i in diff_x])
        b1 = b1_numerator/b1_denominator
        b0 = avg_y - (b1 * avg_x)
        yhat = []
        residuals = []
        for index, row in df.iterrows():
            yhat.append(b0 + b1*row['X'])
            residuals.append(row['Y'] - (b0 + b1*row['X']))
        tss = sum([i ** 2 for i in diff_y])
        rss = sum([i ** 2 for i in residuals])
        rse = math.sqrt(rss/(df.shape[0] - 2))
        stdErrB0 = math.sqrt((rse ** 2) * (1/df.shape[0] + (avg_x ** 2)/b1_denominator))
        stdErrB1 = math.sqrt((rse ** 2)/b1_denominator)
        b0CI = [round(b0 - 2*stdErrB0, 4), round(b0 + 2*stdErrB0, 4)]
        b1CI = [round(b1 - 2*stdErrB1, 4), round(b1 + 2*stdErrB1, 4)]
        b0Tstat = b0/stdErrB0
        b1Tstat = b1/stdErrB1
        b0pval = stats.t.sf(abs(b0Tstat), df.shape[0] - 2)*2
        b1pval = stats.t.sf(abs(b1Tstat), df.shape[0] - 2)*2
        Rsquared = 1 - rss/tss
        adjRsquared = 1 - ((1 - Rsquared) * (df.shape[0] - 1))/(df.shape[0] - 2)
        fStat = (tss - rss)/(rss/(df.shape[0] - 2))
        elapsed = time.time() - start
        results = {
            "intercept" : {
                "b0" : round(b0, 4),
                "std_error" : round(stdErrB0, 4),
                "confidence_interval" : b0CI,
                "t_value" : round(b0Tstat, 4),
                "p_value" : round(b0pval, 6)
                },
            "slope" : {
                "b1" : round(b1, 4),
                "std_error" : round(stdErrB1, 4),
                "confidence_interval" : b1CI,
                "t_value" : round(b1Tstat, 4),
                "p_value" : round(b1pval, 6)
                },
            "equation" : "y = " + str(round(b0, 4)) + " + " + str(round(b1, 4)) + " * x",
            "rss" : round(rss, 4),
            "tss" : round(tss, 4),
            "rse" : round(rse, 4),
            "R_squared" : round(Rsquared, 4),
            "adjRsquared" : round(adjRsquared, 4),
            "f_statistic": round(fStat, 2),
            "degrees_of_freedom" : df.shape[0] - 2,
            "predicted_y" : yhat,
            "residuals" : residuals
            }
        print("Computation Time ->", round(elapsed, 4), "seconds.")
        df['yhat'] = pd.Series(yhat).values
        df['residuals'] = pd.Series(residuals).values
        t = PrettyTable(['X', 'Y', 'Yhat', 'residuals'])
        for index, row in df.iterrows():
            t.add_row(row)
        print(t)
        return results

def main():
    filename = path + '\\data\\autoInsur.csv'
    print("+----------+")
    print("Model Output")
    print("+----------+")
    results = simpleLinear(filename)
    with open(path + '\\src\\simpleLinearModel.json', 'w') as outfile:
        json.dump(results, outfile)
    print("+-----------------+")
    print("Model File Written.")
    print("+-----------------+")

if __name__ == "__main__":
    main()


import numpy as np
import matplotlib.pyplot as plt

class InterpolatingFunction(object):
    def __init__(self):
        print('initializing interpolating function class')
        plt.rcParams["figure.figsize"] = [20, 7]

    def calculateNodes(self,nNodes,plot=False):
        """Calculates Chebyshev points of the second kind (aka Gauss-Lobatto grid points)

        Parameters:
        nNodes (int): number of grid points

        Returns:
        ndarray: array containing all grind points
        """
        j = np.arange(nNodes)
        nodes = -np.cos(j*np.pi/(nNodes-1))

        if plot:
            plt.grid(True)
            plt.plot(nodes,np.zeros(nNodes),'x')
            plt.show()

        return(nodes)

    def calculateWeights(self,nodes,plot=False):
        """Calculates according weights for barycentric interpolation if provided
        nodes are Chebyshev points of second kind

        Parameters:
        nodes (ndarray): nodes

        Returns:
        ndarray: weights
        """

        weights = np.ones(len(nodes))*np.power((-1),np.arange(len(nodes)))
        weights[0]/=2
        weights[-1]/=2

        if plot:
            plt.grid(True)
            plt.plot(nodes,weights,'x')
            plt.show()

        return(weights)

    def calculateBasisFunctions(self,nodes,weights,n,plot=False):
        """Calculates the basis functions l_j(s) for n equidistant points s

        Parameters:
        nodes (ndarray[nNodes]): Gaus-Lobatto nodes
        weights (ndarray[nNodes]): barycentric weights for Gaus-Lobatto nodes

        Returns:
        ndarray[nNodes,n] : values of basis functions on n equidistant points s
        """
        l = np.empty((len(nodes),n))
        s = np.linspace(-1,1,n)

        # [sum_{k=0}^{n} w_k/(s-s_k)]^-1
        temp2 = 1/np.sum(np.repeat(np.reshape(weights,[len(weights),1]),len(s),axis=1)/
                         (np.repeat(np.reshape(s,[1,len(s)]),len(nodes),axis=0)-
                          np.repeat(np.reshape(nodes,[len(nodes),1]),len(s),axis=1)),axis=0)
        for j in range(len(nodes)):
            # w_j/(s-s_j):
            temp1 = weights[j]/(s-nodes[j])
            l[j,:]=temp1*temp2
            if plot:
                plt.plot(s,l[j,:])
        if plot:
            plt.plot(nodes,np.zeros(len(nodes))+1,'x')
            plt.grid(True)
            #plt.yscale("Log")
            plt.show()
        return l

    def interpolateFunction(self,values,basis,plot=False,nodes=None):
        """Calculates a Lagrange interpolation function for given values at the nodes
        with the given basis functions

        Parameters:
        values (ndarray[nNodes]): values at sampling points
        basis (ndarray[nNodes,n]): the basis functions as calculatet with
        corresponding functiong

        Returns:
        ndarray[n] : the interpolation function at n equidistant points
        """
        nNodes = len(values)
        nPoints = len(basis[0])
        p = np.sum(np.repeat(np.reshape(values,(nNodes,1)),nPoints,axis=1)*basis,axis=0)
        if plot:
            plt.plot(np.linspace(-1,1,1000),p)
            plt.plot(nodes,values,'x')
            plt.grid(True)
            plt.show()
        return(p)

    def derivative(self,values,matrix):
        """Calculates the m-th derivateive of a function at barycentric nodes
        given by parameter values at barycentric nodes by means of a differentiation matrix

        Parameters:
        values (ndarray[nNodes]): values at sampling points
        matrix (ndarray[nNodes,nNodes]): m-th differentiation matrix

        Returns:
        ndarray[nNoes] : values of the derivative function at the sampling points
        """

        #p'(s_i)=Sum_{j=0}^n l'_j(s_i)f_j
        p = np.dot(matrix,values)
        return p

    def differentiationMatrix(self,m,nodes,weights,plot=False):
        """Calculates the m-th differentiation matrix for a function given at barycentric nodes

        Parameters:
        m (int): m-th derivative of the given function
        nodes (ndarray[nNodes]): Gaus-Lobatto nodes
        weights (ndarray[nNodes]): barycentric weights for Gaus-Lobatto nodes

        Returns:
        ndarray[nNoes,nNodes] : m-th differentiation matrix
        """

        nNodes=len(nodes)
        #calculate some matrices frequenty used in the following calculation
        temp1=np.repeat(np.reshape(weights,(nNodes,1)),nNodes,axis=1)
        temp2=np.transpose(temp1)
        tempW = temp2/temp1 #w_j / w_i
        temp3=np.repeat(np.reshape(nodes,(nNodes,1)),nNodes,axis=1)
        temp4=np.transpose(temp3)
        tempS = temp3-temp4 #s_i - s_j

        #calculate matrix of first derivative
        temp5=tempW/tempS
        temp5[temp5==np.inf]=0
        temp6=-np.sum(temp5,axis=1)
        row,col = np.diag_indices(temp5.shape[0])
        temp5[row,col] = temp6

        if m==1:
            D = temp5
        elif m>1:
            for i in range(2,m+1):
                temp7 = np.repeat(np.reshape(np.diag(temp5),(nNodes,1)),nNodes,axis=1)
                temp5 = np.nan_to_num(i/tempS*(tempW*temp7-temp5))
                temp6=-np.sum(temp5,axis=1)
                row,col = np.diag_indices(temp5.shape[0])
                temp5[row,col] = temp6
            D = temp5
        else:
            raise Exception('degree of derivative not supported')

        if plot:
            plt.matshow(D)
            plt.colorbar()
            plt.show()

        return D


# Decorrelating your data and dimension reduction
# Dimension reduction summarizes a dataset using its common occuring patterns. In this chapter, you'll learn about the most fundamental of dimension reduction techniques, "Principal Component Analysis" ("PCA"). PCA is often used before supervised learning to improve model performance and generalization. It can also be useful for unsupervised learning. For example, you'll employ a variant of PCA will allow you to cluster Wikipedia articles by their content!

# Correlated data in nature
# You are given an array grains giving the width and length of samples of grain. You suspect that width and length will be correlated. To confirm this, make a scatter plot of width vs length and measure their Pearson correlation.

# Perform the necessary imports
import matplotlib.pyplot as plt
from scipy.stats import pearsonr

# Assign the 0th column of grains: width
width = grains[:,0]

# Assign the 1st column of grains: length
length = grains[:,1]

# Scatter plot width vs length
plt.scatter(width, length)
plt.axis('equal')
plt.show()

# Calculate the Pearson correlation
correlation, pvalue = pearsonr(width,length)

# Display the correlation
print(correlation)

# Decorrelating the grain measurements with PCA
# You observed in the previous exercise that the width and length measurements of the grain are correlated. Now, you'll use PCA to decorrelate these measurements, then plot the decorrelated points and measure their Pearson correlation.

# Import PCA
from sklearn.decomposition import PCA

# Create PCA instance: model
model = PCA()

# Apply the fit_transform method of model to grains: pca_features
pca_features = model.fit_transform(grains)

# Assign 0th column of pca_features: xs
xs = pca_features[:,0]

# Assign 1st column of pca_features: ys
ys = pca_features[:,1]

# Scatter plot xs vs ys
plt.scatter(xs, ys)
plt.axis('equal')
plt.show()

# Calculate the Pearson correlation of xs and ys
correlation, pvalue = pearsonr(xs, ys)

# Display the correlation
print(correlation)

# The first principal component
# The first principal component of the data is the direction in which the data varies the most. In this exercise, your job is to use PCA to find the first principal component of the length and width measurements of the grain samples, and represent it as an arrow on the scatter plot.

# The array grains gives the length and width of the grain samples. PyPlot (plt) and PCA have already been imported for you.

# Make a scatter plot of the untransformed points
plt.scatter(grains[:,0], grains[:,1])

# Create a PCA instance: model
model = PCA()

# Fit model to points
model.fit(grains)

# Get the mean of the grain samples: mean
mean = model.mean_

# Get the first principal component: first_pc
first_pc = model.components_[0,:]

# Plot first_pc as an arrow, starting at mean
plt.arrow(mean[0], mean[1], first_pc[0], first_pc[1], color='red', width=0.01)

# Keep axes on same scale
plt.axis('equal')
plt.show()

# Variance of the PCA features
# The fish dataset is 6-dimensional. But what is its intrinsic dimension? Make a plot of the variances of the PCA features to find out. As before, samples is a 2D array, where each row represents a fish. You'll need to standardize the features first.

# Perform the necessary imports
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
import matplotlib.pyplot as plt

# Create scaler: scaler
scaler = StandardScaler()

# Create a PCA instance: pca
pca = PCA()

# Create pipeline: pipeline
pipeline = make_pipeline(scaler,pca)

# Fit the pipeline to 'samples'
pipeline.fit(samples)

# Plot the explained variances
features = range(pca.n_components_)
plt.bar(features, pca.explained_variance_)
plt.xlabel('PCA feature')
plt.ylabel('variance')
plt.xticks(features)
plt.show()

# Dimension reduction of the fish measurements
# In a previous exercise, you saw that 2 was a reasonable choice for the "intrinsic dimension" of the fish measurements. Now use PCA for dimensionality reduction of the fish measurements, retaining only the 2 most important components.

# The fish measurements have already been scaled for you, and are available as scaled_samples.

# Import PCA
from sklearn.decomposition import PCA

# Create a PCA model with 2 components: pca
pca = PCA(n_components =2)

# Fit the PCA instance to the scaled samples
pca.fit(scaled_samples)

# Transform the scaled samples: pca_features
pca_features = pca.transform(scaled_samples)

# Print the shape of pca_features
print(pca_features.shape)

# A tf-idf word-frequency array
# In this exercise, you'll create a tf-idf word frequency array for a toy collection of documents. For this, use the TfidfVectorizer from sklearn. It transforms a list of documents into a word frequency array, which it outputs as a csr_matrix. It has fit() and transform() methods like other sklearn objects.

# You are given a list documents of toy documents about pets. Its contents have been printed in the IPython Shell.

# Import TfidfVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer

# Create a TfidfVectorizer: tfidf
tfidf = TfidfVectorizer()

# Apply fit_transform to document: csr_mat
csr_mat = tfidf.fit_transform(documents)

# Print result of toarray() method
print(csr_mat.toarray())

# Get the words: words
words = tfidf.get_feature_names()

# Print words
print(words)

# Clustering Wikipedia part I
# You saw in the video that TruncatedSVD is able to perform PCA on sparse arrays in csr_matrix format, such as word-frequency arrays. Combine your knowledge of TruncatedSVD and k-means to cluster some popular pages from Wikipedia. In this exercise, build the pipeline. In the next exercise, you'll apply it to the word-frequency array of some Wikipedia articles.

# Create a Pipeline object consisting of a TruncatedSVD followed by KMeans. (This time, we've precomputed the word-frequency matrix for you, so there's no need for a TfidfVectorizer).

# The Wikipedia dataset you will be working with was obtained from here.

# Perform the necessary imports
from sklearn.decomposition import TruncatedSVD
from sklearn.cluster import KMeans
from sklearn.pipeline import make_pipeline

# Create a TruncatedSVD instance: svd
svd = TruncatedSVD(n_components= 50)

# Create a KMeans instance: kmeans
kmeans = KMeans(n_clusters=6)

# Create a pipeline: pipeline
pipeline = make_pipeline(svd,kmeans)

# Clustering Wikipedia part II
# It is now time to put your pipeline from the previous exercise to work! You are given an array articles of tf-idf word-frequencies of some popular Wikipedia articles, and a list titles of their titles. Use your pipeline to cluster the Wikipedia articles.

# A solution to the previous exercise has been pre-loaded for you, so a Pipeline pipeline chaining TruncatedSVD with KMeans is available.

# Import pandas
import pandas as pd

# Fit the pipeline to articles
pipeline.fit(articles)

# Calculate the cluster labels: labels
labels = pipeline.predict(articles)

# Create a DataFrame aligning labels and titles: df
df = pd.DataFrame({'label': labels, 'article': titles})

# Display df sorted by cluster label
print(df.sort_values('label'))

Unsupervised Learning in Python/Decorrelating_your_data_and_dimension_reduction.py


import numpy as np

def sigmoid(x: np.ndarray) -> np.ndarray: # x:input / return output of sigmoid func
  """
  ref:
    http://www.kamishima.net/mlmpyja/lr/sigmoid.html
  """
  sigmoid_range = 34.538776394910684
  x = np.clip(x, -sigmoid_range, sigmoid_range)

  return 1.0 / (1.0 + np.exp(-x))

def softmax(x: np.ndarray) -> np.ndarray: # x:input / return output of softmax func
  """
  ref:
    https://qiita.com/shohei-ojs/items/d66783bcead3eb7efd82
    "axis = -1, keepdims = True" is 2dim and 1dim to share process
  """
  c = np.max(x, axis=-1, keepdims=True)
  exp_x = np.exp(x - c) # for overflow
  sum_exp_x = np.sum(exp_x, axis=-1, keepdims=True)
  y = exp_x / sum_exp_x

  return y

def cross_entropy_error(y: np.ndarray, t: np.ndarray) -> float: # y:output of NN, t:correct label / return value of cross entropy error
  if y.ndim == 1:
    t = t.reshape(1, t.size)
    y = y.reshape(1, y.size)

  delta = 1e-7 # to prevent log(0)
  err = -np.sum(t * np.log(y + delta))
  batch_size = y.shape[0] # to normalize
  return err / batch_size

def sigmoid_grad(x: np.ndarray) -> np.ndarray: # fast ver / x:input / return output of sigmoid func
  return (1.0 - sigmoid(x)) * sigmoid(x)


import numpy as np

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

def tanh(z):
    return np.tanh(z)

def sin(z):
    return np.sin(z)

def relu(z):
    return np.maximum(0.001, z)

def softmax(Z):
    return np.exp(Z) / np.sum(np.exp(Z))

def der_sigmoid(z):
    #return sigmoid(z)*(1 - sigmoid(z))
    return  (1.0 / (1 + np.exp(-(z))))*(1 -  1.0 / (1 + np.exp(-(z))))

def der_tanh(z):
    return 1 - np.tanh(z) ** 2

def der_relu(z):
    return (z>0)*1 + (z<0)*0.001


import numpy as np
from scipy.stats import chi2, multivariate_normal
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse

def get_error_ellipse_parameters(cov, confidence=None, sigma=None):
    """Returns parameters of an ellipse which contains a specified
    amount of normally-distributed 2D data, where the data is
    characterised by its covariance matrix.

    Parameters
    ----------
    cov : array_like
        Input covariance matrix of shape (2,2)
    confidence : float
        Fraction of data points within ellipse. 0 < confidence < 1.
        If confidence is not given, it is calculated according to sigma.
    sigma : float
        Length of axes of the ellipse in standard deviations. If
        confidence is also given, sigma is ignored.

    Returns
    -------
    semi_major : float
        Length of major semiaxis of ellipse.
    semi_minor : float
        Length of minor semiaxis of ellipse.
    angle : float
        Rotation angle of ellipse in radian.
    confidence : float
        Fraction of data expected to lie within the ellipse.
    sigma : float
        Length of major and minor semiaxes in standard deviations.
    """
    cov = np.array(cov)
    if(cov.shape != (2,2)):
        raise ValueError("The covariance matrix needs to be of shape (2,2)")
    if(confidence == None and sigma == None):
        raise RuntimeError("One of confidence and sigma is needed as input argument")
    if(confidence and sigma):
        print("Argument sigma is ignored as confidence is also provided!")

    if(confidence == None):
        if(sigma < 0):
            raise ValueError("Sigma needs to be positive")
        scaling = np.square(sigma)
        confidence = chi2.cdf(scaling, 2)
    if(sigma == None):
        if(confidence > 1 or confidence < 0):
            raise ValueError("Ensure that confidence lies between 0 and 1")
        scaling = chi2.ppf(confidence, 2)
        sigma = np.sqrt(scaling)
    eigenvalues, eigenvectors = np.linalg.eig(cov)

    maxindex = np.argmax(eigenvalues)
    vx, vy = eigenvectors[:, maxindex]
    angle = np.arctan2(vy, vx)
    semi_minor, semi_major = np.sqrt(np.sort(eigenvalues) * scaling)
    print("With sigma = {:.2f}, {:.1f}% of data points lie within ellipse.".format(sigma, confidence * 100))

    return semi_major, semi_minor, angle, confidence, sigma

##################
## Example usage
##################
if(__name__ == "__main__"):
    mean_x, mean_y = 5, -2
    covariance = [[1, -2.04], [-2.04, 5.16]]

    rv = multivariate_normal([mean_x, mean_y], covariance)
    data_points = rv.rvs(size = 500)

    fig = plt.figure()
    ax = fig.gca()
    plt.scatter(data_points[:,0], data_points[:,1], alpha = .5)

    confidence = 0.95
    semi_major, semi_minor, angle, confidence, sigma\
        = get_error_ellipse_parameters(covariance, confidence = confidence)
    ax.add_patch(Ellipse((mean_x, mean_y), 2*semi_major, 2*semi_minor, 180*angle/np.pi,\
            facecolor = 'none', edgecolor = 'red',\
            label = 'Confidence = {:.0f}% (sigma = {:.2f})'.format(confidence * 100, sigma)))

    sigma = 1
    semi_major, semi_minor, angle, confidence, sigma,\
        = get_error_ellipse_parameters(covariance, sigma = sigma)
    ax.add_patch(Ellipse((mean_x, mean_y), 2*semi_major, 2*semi_minor, 180*angle/np.pi,\
            facecolor = 'none', edgecolor = 'yellow',\
            label = 'Sigma = {:.0f} (confidence = {:.1f}%)'.format(sigma, confidence * 100)))
    ax.legend()
    fig.savefig('plot.png')
    plt.show()


#usr/bin/env/python
'''
Author  : Bhekimpilo Ndhlela
Author  : 18998712
module  : TW244 Applied Mathematics
task    : Assignment 01 problem2
since   : Saturday-28-07-2018
'''

from numpy import (exp, linspace, array, abs, zeros, shape)
import matplotlib.pyplot as plt
from sys import exit

def eulers_method(f, I, y0=1.0,(a,b)=(0.0,4.0), h=1.0):
    X = array([0.0, 1.0, 2.0, 3.0, 4.0])
    W = array([y0, 0.0, 0.0, 0.0, 0.0])

    for i in xrange(int(a), int(b)):
        W[i+1] = W[i] + h * f(X[i], W[i])
    absolute_error(W, X, 'Euler\'s Method')

def modified_eulers_method(f, I, y0=1.0,(a,b)=(0.0,4.0), h=1.0):
    X = array([0.0, 1.0, 2.0, 3.0, 4.0])
    W = array([y0, 0.0, 0.0, 0.0, 0.0])

    for i in xrange(int(a), int(b)):
        temp = W[i] + h*f(X[i], W[i])
        W[i+1] = W[i] + (h/2.0)*(f(X[i], W[i]) + f(X[i+1], temp))
    absolute_error(W, X, 'Improved Euler\'s Method')

def absolute_error(W, X, label, debug=True):
    Y = array([ I(n) for n in xrange(len(W))])
    abs_err = array([abs(ya - yc) for ya, yc in zip(Y, W)])
    if debug is True:
        print(label)
        for i , (err, w) in enumerate(zip(abs_err, W)):
            print 'x = ', i, '\t\tw = {:.10f} \ty = {:.10f}\terr = {:.10f}'.format(w, Y[i], abs_err[i])
    plot_comparison_func(Y, W, X, label)

def plot_comparison_func(Y, W, x, lbl):
    plt.title('Analytical vs. ' + lbl)
    plt.xlabel('x')
    plt.ylabel('y = f(x)')
    plt.plot(x, Y, '-k', linewidth=2, label='Analytical Solution')
    plt.plot(x, W, '--r', linewidth=2, label='Numerical Solution')
    plt.legend(bbox_to_anchor=(.4, .4))
    plt.show()

def plot_analytical_solution():
    X = linspace(0, 4, 1000)
    y = array([ exp(1 - exp(-x)) for x in X])
    plt.title('Plot of function f(x) = exp(1 - exp(-x))')
    plt.xlabel('x = linspace(0, 4, 1000)')
    plt.ylabel('f(x) = exp(1 - exp(-x))')
    plt.plot(X, y, '-k', linewidth=4)
    plt.show()

if __name__ == '__main__':
    f = lambda x, y: exp(-x) * y    # f(x, y) = y DE
    I = lambda x: exp(1 - exp(-x))  # Exact Solution
    plot_analytical_solution()
    eulers_method(f, I)
    modified_eulers_method(f, I)
else:
    exit('USAGE: python problem2.py')


import math
import numpy as np

#define data
data = [6.224, 6.665, 6.241, 5.302, 5.073, 5.127, 4.994, 5.012, 5.108, 5.377, 5.510, 6.372]
m = len(data)
b = np.reshape(data,(m,1))
time = [0.0, 1/12, 2/12, 3/12, 4/12, 5/12, 6/12, 7/12, 8/12, 9/12, 10/12, 11/12]

#Create the A matrix from the time
Amatrix = []
n = 0
while n < m:
    Amatrix.append([1.0, round(math.cos(2*math.pi*time[n]), 12), round(math.sin(2*math.pi*time[n]), 12),])
    n = n + 1
    pass
Amatrix = np.array(Amatrix)
print(Amatrix)

#Create and use Transpose
TransposeMatrix = Amatrix.transpose()
print(TransposeMatrix)
Cmatrix = np.matmul(TransposeMatrix, Amatrix)
print(Cmatrix)

#Fix error when ATranspose times A has a 0 on the diagonal, may cause problems if not careful
f = 0
while f < 3:
    if Cmatrix[f,f] == 0:
        Cmatrix[f,f] = .0000000000000001
        pass
    f = f + 1
    pass

TransposeTimesb = np.matmul(TransposeMatrix, b)
print(TransposeTimesb)
C = np.linalg.solve(Cmatrix,TransposeTimesb)
print(C)

#Calculate Error
r = np.subtract(b, np.matmul(Amatrix, C))
k = 0
SE = 0
while k < m:
    SE = SE + (r.item(k))**2

    k = k + 1
    pass
RMSE = math.sqrt(SE/m)

print("F3(t) = ", C.item(0), " + ", C.item(1), "* cos(2(pi)t) + ", C.item(2), "* sin(2(pi)t)")
print("RMSE = ", RMSE)


import numpy as np
from typing import Tuple

def R(theta: float) -> np.ndarray:
    """
        Returns the rotation matrix for rotating an object
        centered around the origin with a given angle

        Arguments:
            theta: angle in degrees

        Returns:
            R: 2x2 np.ndarray with rotation matrix
    """
    theta = np.radians(theta)
    return np.array(
        [[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]
    )

def cart2pol(x: float, y: float) -> Tuple[float, float]:
    """
        Cartesian to polar coordinates

        angles in degrees
    """
    rho = np.hypot(x, y)
    phi = np.degrees(np.arctan2(y, x))
    return rho, phi

def pol2cart(rho: float, phi: float) -> Tuple[float, float]:
    """
        Polar to cartesian coordinates

        angles in degrees
    """
    x = rho * np.cos(np.radians(phi))
    y = rho * np.sin(np.radians(phi))
    return x, y


import numpy as np
import matplotlib.pyplot as mpl
from scipy import interpolate
import time

# -------------------------------------|Declaração de funções|-------------------------------------#
def f0(x):
    return np.e ** np.cos(np.pi * x)

def d2f0(x):
    return np.pi ** 2 * (np.sin(np.pi * x) ** 2 - np.cos(np.pi * x)) * np.e ** (np.cos(np.pi * x))

def d4f0(x):
    return (
        np.pi ** 4
        * (
            np.sin(np.pi * x) ** 4
            - 6 * np.sin(np.pi * x) ** 2 * np.cos(np.pi * x)
            - 4 * np.sin(np.pi * x) ** 2
            + 3 * np.cos(np.pi * x) ** 2
            + np.cos(np.pi * x)
        )
        * np.e ** (np.cos(np.pi * x))
    )

def f1(x):
    return np.sin(np.pi * x ** 2)

def d2f1(x):
    return 2 * np.pi * (-2 * np.pi * x ** 2 * np.sin(np.pi * x ** 2) + np.cos(np.pi * x ** 2))

def d4f1(x):
    return (
        4
        * np.pi ** 2
        * (
            4 * np.pi ** 2 * x ** 4 * np.sin(np.pi * x ** 2)
            - 12 * np.pi * x ** 2 * np.cos(np.pi * x ** 2)
            - 3 * np.sin(np.pi * x ** 2)
        )
    )

def f2(x):
    return 1 / (1 + x ** 5)

def d2f2(x):
    return 10 * x ** 3 * (5 * x ** 5 / (x ** 5 + 1) - 2) / (x ** 5 + 1) ** 2

def d4f2(x):
    return (
        120
        * x
        * (125 * x ** 15 / (x ** 5 + 1) ** 3 - 150 * x ** 10 / (x ** 5 + 1) ** 2 + 40 * x ** 5 / (x ** 5 + 1) - 1)
        / (x ** 5 + 1) ** 2
    )

def f2_g(x):
    if x != -1:
        return 1 / (1 + x ** 5)

def f3(x):
    return np.cos(np.e ** np.cos(np.pi * x))

def d2f3(x):
    return (
        np.pi ** 2
        * (
            -np.e ** (np.cos(np.pi * x)) * np.sin(np.pi * x) ** 2 * np.cos(np.e ** (np.cos(np.pi * x)))
            - np.sin(np.pi * x) ** 2 * np.sin(np.e ** (np.cos(np.pi * x)))
            + np.sin(np.e ** (np.cos(np.pi * x))) * np.cos(np.pi * x)
        )
        * np.e ** (np.cos(np.pi * x))
    )

def d4f3(x):
    return (
        np.pi ** 4
        * (
            np.e ** (3 * np.cos(np.pi * x)) * np.sin(np.pi * x) ** 4 * np.cos(np.e ** (np.cos(np.pi * x)))
            + 6 * np.e ** (2 * np.cos(np.pi * x)) * np.sin(np.pi * x) ** 4 * np.sin(np.e ** (np.cos(np.pi * x)))
            - 6
            * np.e ** (2 * np.cos(np.pi * x))
            * np.sin(np.pi * x) ** 2
            * np.sin(np.e ** (np.cos(np.pi * x)))
            * np.cos(np.pi * x)
            - 7 * np.e ** (np.cos(np.pi * x)) * np.sin(np.pi * x) ** 4 * np.cos(np.e ** (np.cos(np.pi * x)))
            + 18
            * np.e ** (np.cos(np.pi * x))
            * np.sin(np.pi * x) ** 2
            * np.cos(np.pi * x)
            * np.cos(np.e ** (np.cos(np.pi * x)))
            + 4 * np.e ** (np.cos(np.pi * x)) * np.sin(np.pi * x) ** 2 * np.cos(np.e ** (np.cos(np.pi * x)))
            - 3 * np.e ** (np.cos(np.pi * x)) * np.cos(np.pi * x) ** 2 * np.cos(np.e ** (np.cos(np.pi * x)))
            - np.sin(np.pi * x) ** 4 * np.sin(np.e ** (np.cos(np.pi * x)))
            + 6 * np.sin(np.pi * x) ** 2 * np.sin(np.e ** (np.cos(np.pi * x))) * np.cos(np.pi * x)
            + 4 * np.sin(np.pi * x) ** 2 * np.sin(np.e ** (np.cos(np.pi * x)))
            - 3 * np.sin(np.e ** (np.cos(np.pi * x))) * np.cos(np.pi * x) ** 2
            - np.sin(np.e ** (np.cos(np.pi * x))) * np.cos(np.pi * x)
        )
        * np.e ** (np.cos(np.pi * x))
    )

def trapezio(f, df, x, fx, n, a, b):

    inicio = time.time()

    v = np.linspace(a, b, num=n)
    h = abs(v[1] - v[0])

    x.append(v[0])
    fx.append(f(v[0]))

    res = np.zeros((3))

    for i in range(1, n):

        x.append(v[i])
        fx.append(f(v[i]))

        res[0] += (h / 2) * (fx[i - 1] + fx[i])

    res[1] = erro(df, n, a, b, h, "T")

    fim = time.time()

    res[2] = fim - inicio

    print("Regra dos Trapezios:")
    print("\t-> Resultado:", res[0])
    print("\t-> Erro:", res[1])
    print("\t-> Tempo:", res[2], end="\n\n")

    return res

def simpson(f, df, x, fx, n, a, b):

    inicio = time.time()

    v = np.linspace(a, b, num=n)
    h = abs(v[1] - v[0])

    x.append(v[0])
    fx.append(f(v[0]))

    res = np.zeros((3))

    for i in range(2, n, 2):

        x.append(v[i - 1])
        x.append(v[i])
        fx.append(f(v[i - 1]))
        fx.append(f(v[i]))

        res[0] += (h / 3) * (fx[i - 2] + 4 * fx[i - 1] + fx[i])

    res[1] = erro(df, n, a, b, h, "S")

    fim = time.time()

    res[2] = fim - inicio

    print("Regra de Simpson:")
    print("\t-> Resultado:", res[0])
    print("\t-> Erro:", res[1])
    print("\t-> Tempo:", res[2], end="\n\n")

    return res

def erro(df, n, a, b, h, tipo):

    x0 = np.linspace(a, b, num=1000)

    if tipo == "t" or tipo == "T":
        return (n * (h ** 3) / 12) * np.max(np.abs(df(x0)))

    elif tipo == "s" or tipo == "S":
        return (n * (h ** 5) / 180) * np.max(np.abs(df(x0)))

def f_de_x(f, fx, x, a, b):

    for i in range(int(a * 50), int(b * 50 + 1)):
        i /= 50

        x.append(i)
        fx.append(f(i))

def grafico_trapezio(f, xf, t, xt, funcao):

    mpl.figure()
    mpl.plot(xf, f, label=funcao, color="k")
    mpl.stem(
        xt,
        t,
        basefmt="b",
        use_line_collection=True,
        linefmt="blue",
        markerfmt="blue",
        label="integração numérica pela Regra dos Trapézios",
    )
    mpl.fill_between(xt, t, 0, facecolor="#8112ff", alpha=0.3)
    mpl.xlabel("x")
    mpl.ylabel("f(x)")
    mpl.legend()
    mpl.grid(True)

def grafico_simpson(f, xf, fxs, xs, funcao):

    mpl.figure()
    mpl.plot(xf, f, label=funcao, color="k")
    mpl.stem(
        xs,
        fxs,
        basefmt="r",
        use_line_collection=True,
        linefmt="red",
        markerfmt=" ",
        label="integração numérica pela Regra de Simpson",
    )

    for i in range(2, n, 2):
        fxp = []
        xp = []
        fx = interpolate.interp1d(xs[i - 2 : i + 1], fxs[i - 2 : i + 1], kind="quadratic")
        xp = np.linspace(xs[i - 2], xs[i], 50)
        fxp = fx(xp)

        mpl.plot(xp, fxp, color="r")
        mpl.fill_between(xp, fxp, 0, facecolor="#f2600c", alpha=0.3)

    mpl.xlabel("x")
    mpl.ylabel("f(x)")
    mpl.legend()
    mpl.grid(True)

# -------------------------------------------------------------------------------------------------#

# -------------------------------------|Variáveis de controle|-------------------------------------#

# Número de pontos (impar)
n = 1000001

a = 0  # Intervalo inicial
b = 1  # Intervalo final

funcao0 = False
funcao1 = False
funcao2 = False
funcao3 = True

graficos = False
# -------------------------------------------------------------------------------------------------#

# ------------------------------------|Declaração de variáveis|------------------------------------#
f = [f0, f1, [f2, f2_g], f3]
df = [[d2f0, d4f0], [d2f1, d4f1], [d2f2, d4f2], [d2f3, d4f3]]
xt = [[], [], [], []]
fxt = [[], [], [], []]
xs = [[], [], [], []]
fxs = [[], [], [], []]
x = [[], [], [], []]
fx = [[], [], [], []]
# -------------------------------------------------------------------------------------------------#

# Caso n seja par, incrementa-se 1, pois n precisa de ser ímpar
if n % 2 == 0:
    n += 1

# --|Calculando e printando as integrais numéricas com seus respectivos erros e tempo de execução|--#
if funcao0 == True:
    print("\nÁrea de e^cos(pi*x) entre", a, "e", b, "com", n, "pontos", end="\n\n")
    trapezio(f[0], df[0][0], xt[0], fxt[0], n, a, b)
    simpson(f[0], df[0][1], xs[0], fxs[0], n, a, b)

if funcao1 == True:
    print("\nÁrea de sen(pi*x^2) entre", a, "e", b, "com", n, "pontos", end="\n\n")
    trapezio(f[1], df[1][0], xt[1], fxt[1], n, a, b)
    simpson(f[1], df[1][1], xs[1], fxs[1], n, a, b)

if funcao2 == True:
    print("\nÁrea de 1/(1 + x^5) entre", a, "e", b, "com", n, "pontos", end="\n\n")
    trapezio(f[2][0], df[2][0], xt[2], fxt[2], n, a, b)
    simpson(f[2][1], df[2][1], xs[2], fxs[2], n, a, b)

if funcao3 == True:
    print("\nÁrea de cos(e^cos(pi*x)) entre", a, "e", b, "com", n, "pontos", end="\n\n")
    trapezio(f[3], df[3][0], xt[3], fxt[3], n, a, b)
    simpson(f[3], df[3][1], xs[3], fxs[3], n, a, b)
# -------------------------------------------------------------------------------------------------#

# --------------------------------------|Plotando os gráficos|-------------------------------------#
if graficos == True:

    if funcao0 == True:
        f_de_x(f[0], fx[0], x[0], -2, 2)
        grafico_trapezio(fx[0], x[0], fxt[0], xt[0], "e^cos(pi*x)")
        grafico_simpson(fx[0], x[0], fxs[0], xs[0], "e^cos(pi*x)")

    if funcao1 == True:
        f_de_x(f[1], fx[1], x[1], -2, 2)
        grafico_trapezio(fx[1], x[1], fxt[1], xt[1], "sen(pi*x^2)")
        grafico_simpson(fx[1], x[1], fxs[1], xs[1], "sen(pi*x^2)")

    if funcao2 == True:
        f_de_x(f[2][1], fx[2], x[2], -2, 2)
        grafico_trapezio(fx[2], x[2], fxt[2], xt[2], "1/(1 + x^5)")
        grafico_simpson(fx[2], x[2], fxs[2], xs[2], "1/(1 + x^5)")

    if funcao3 == True:
        f_de_x(f[3], fx[3], x[3], -2, 2)
        grafico_trapezio(fx[3], x[3], fxt[3], xt[3], "cos(e^cos(pi*x))")
        grafico_simpson(fx[3], x[3], fxs[3], xs[3], "cos(e^cos(pi*x))")

    mpl.show()
# -------------------------------------------------------------------------------------------------#

Lista-implementacao-3/2 - Integracao Numerica/integracao numerica.py


# The Fibonacci numbers, commonly denoted F(n) form a sequence,
# called the Fibonacci sequence, such that each number is the sum of the two preceding ones,
# starting from 0 and 1. That is,
# F(0) = 0,   F(1) = 1
# F(N) = F(N - 1) + F(N - 2), for N > 1.
# Given N, calculate F(N).

# Example 1:
# Input: 2
# Output: 1
# Explanation: F(2) = F(1) + F(0) = 1 + 0 = 1.

# Example 2:
# Input: 3
# Output: 2
# Explanation: F(3) = F(2) + F(1) = 1 + 1 = 2.

# Example 3:
# Input: 4
# Output: 3
# Explanation: F(4) = F(3) + F(2) = 2 + 1 = 3.

# Note:
# 0 ≤ N ≤ 30.

class Solution(object):
    def fib(self, N):
        """
        :type N: int
        :rtype: int
        """
        # M1. 原始递归
        # 时间复杂度: O(2^n) 递归树分析
        # 空间复杂度: O(n) 栈帧分析

        # if N == 0:
        #     return 0
        # if N < 3:
        #     return 1
        # return self.fib(N-2) + self.fib(N-1)

        # M2. 尾递归
        # 时间复杂度: O(n) 尾递归过程分析
        # 空间复杂度: O(n) 栈帧分析

        # def helper(first, second, N):
        #     if N == 0:
        #         return 0
        #     if N < 3:
        #         return 1
        #     if N == 3:
        #         return first + second
        #     return helper(second, first+second, N-1)
        # return helper(1, 1, N)

        # M3. DP循环
        # 时间复杂度: O(n)
        # 空间复杂度: O(n)

        # import numpy as np
        # if N == 0:
        #     return 0
        # tmp = np.zeros(N+1, dtype=int)
        # tmp[0] = 0
        # tmp[1] = 1
        # for i in range(2, N+1):
        #     tmp[i] = tmp[i-1] + tmp[i-2]
        # return tmp[N]

        # M4. DP循环 空间优化
        # 时间复杂度: O(n)
        # 空间复杂度: O(1)

        if N == 0:
            return 0
        if N < 3:
            return 1
        first, second = 0, 1
        res = 0
        for i in range(2, N+1):
            res = first + second
            first = second
            second = res
        return res


import numpy as np

def householder(_A):
	A = _A.copy()
	n = A.shape[1]
	v = np.zeros_like(A)
	for k in range(n):
		sigma = np.sign(A[k, k]) * np.sqrt((A[k:, k] ** 2).sum())
		if (A[k:, k] ** 2).sum() < 1e-10:
			continue
		v[k, k] += sigma
		v[k:, k] += A[k:, k]
		beta = v[:, k].dot(v[:, k])
		for j in range(k, n):
			A[:, j] -= 2 * (v[:, k].dot(A[:, j]) / beta) * v[:, k]
	return A, v

def QR(A):
	r, _ = householder(A)
	# A=QR, Q=AR^{-1}
	q = A.dot(np.linalg.inv(r))
	# q, r = np.linalg.qr(A)
	return q, r

def check(A):
	for i in range(1, A.shape[0]):
		if abs(A[i, :i-1]).sum() > 1e-3:
			return False
	return True

def solve(A):
	cnt = 0
	while check(A) == False and cnt <= 1000:
		q, r = QR(A)
		A = r.dot(q)
		cnt += 1
	if cnt >= 1000:
		print('Cannot solve A!')
		return None
	return A.diagonal()

def gen53():
	print('t53 result'.center(30, '-'))
	# A = np.array([[4,0,0],[4,5,5],[2,5,5.]])
	# A = np.array([[1,0,0], [0,1,0], [0,0,1], [-1,1,0],[-1,0,1], [0,-1,1.]])
	# print(QR(A))
	# exit()
	# A = np.array([
	# 	[2.9766, 0.3945, 0.4198, 1.1159],
	# 	[0.3945, 2.7328, -0.3097, 0.1129],
	# 	[0.4198, -0.3097, 2.5675, 0.6079],
	# 	[1.1159, 0.1129, 0.6079, 1.7231],
	# 	])
	A = np.array([
		[.5, .5, .5, .5],
		[.5, .5, -.5, -.5],
		[.5, -.5, .5, -.5],
		[.5, -.5, -.5, .5]
		])
	print(solve(A))
	print('end t53'.center(30, '-')+'\n')

if __name__ == '__main__':
	gen53()


import numpy as np

"""
meshgrid的结果，
第一个是横坐标轴的数据的集合
第二个是纵坐标轴数据的集合
两者合起来构成一个网格点的集合

x[0]与y[0] 逐个元素组合，是四个点的坐标，这些点构成一条横线。纵坐标是y[i], 横坐标是x[i]
"""
grid_x, grid_y = np.meshgrid(np.linspace(-3, 3, 4), np.linspace(-3, 3, 4))
print(grid_x)
print("-----------------")
print(grid_y)


import numpy as np

#solve (x_1)+4*(x_2)=2,-2*(x_1)+x_2=14
A=np.array([[1,4]
           ,[-2,1]])

print("det(A)=",np.linalg.det(A))
#det(A)= 9.000000000000002
#the reason that 2 appear here:
#the decimal calcuation error
#det(A)!=0 -> not singular matrix
# -> has unique solution

b=np.array([2,14])
x=np.linalg.solve(A,b)
print(x)
#[-6.  2.]

class Uniqueness_of_solution:
    def __init__(self):
        pass
    def judge_solution(self,A,b):
        #to avoid the decimal error
        #determine by the value of the det(A)by a small float number
        if abs(np.linalg.det(A))<0.0000001:
            print("doesn't have a unique solution")
        else:
            print("has a unique solution:")
            print(np.linalg.solve(A,b))
            return np.linalg.solve(A,b)

#solve:
#x-4y+6z=3
#-2x+8y-12z=-6
#2x-y+3z=1

C=np.array([[1,-4,6]
           ,[-2,8,-12]
           ,[2,-1,3]])

D=np.array([3,-6,1])

sol=Uniqueness_of_solution()
sol.judge_solution(A,b)
#[-6.  2.]
sol.judge_solution(C,D)
#doesn't have a unique solution

#What if doesn't have a unique solution and using linalg.solve?
# ans=np.linalg.solve(C,D)
# print(ans)
#terminal:
#numpy.linalg.LinAlgError: Singular matrix

#solve for the traffic flows
# (x_1)-(x_2)=160
# (x_2)-(x_3)=-40
# (x_3)-(x_4)=210
# (x_4)-(x_1)=-330

E=np.array([[1,-1,0,0]
           ,[0,1,-1,0]
           ,[0,0,1,-1]
           ,[-1,0,0,1]])

F=np.array([160,-40,210,-330])

print("det(E)=",np.linalg.det(E))
if np.linalg.det(E)!=0:
    print("non-singular matrix")
else:
    print("singular matrix")
# det(E)= 0.0
# singular matrix

#solve for the traffic flows (if (x_4)=100)

G=np.array([[1,0,0]
           ,[1,-1,0]
           ,[0,0,1]])

H=np.array([430,160,310])

print("det(G)=",np.linalg.det(G))
if np.linalg.det(G)!=0:
    print("non-singular matrix")
    print("the solution is:")
    print(np.linalg.solve(G,H))
else:
    print("singular matrix")

# det(G)= -1.0
# non-singular matrix
# the solution is:
# [430. 270. 310.]


"""Test functions. Functions to be minimized."""
import numpy as np

def function_sphere(vector):
    """Return the value of the sphere function for the given vector.
    :param vector: n-dimensional array.
    :return value: value of the function at this point in the n-dimensional space.
    """
    return sum([x*x for x in vector])

def function_ackley(vector):
    """Implementations of the Ackley function.
    :param vector: n-dimensional array of floats.
    :return value: value of the Ackley function for the given point in the space.
    """
    n = len(vector)               # dimension of the vector
    sv = function_sphere(vector)  # value of the sphere function

    a = -0.2 * np.sqrt( 1/n * sv)
    b = 1/n * sum([np.cos( 2 * np.pi * x) for x in vector])
    value = -20 * np.exp(a) - np.exp(b) + 20 + np.e

    return value

def function_himmelblau(vector):
    """Compute the value of the Himmelblau's function for a given 2d point in R^2.
    :param vector: 2D array of floats.
    :return value: value of the function at the given point.
    """
    value = np.power(np.power(vector[0], 2) + vector[1] - 11, 2)
    value += np.power(vector[0] + np.power(vector[1], 2) - 7, 2)

    return value

def function_rastrigin(vector):
    """Computes the rastrigin function.
    :param vector: n-dimensional array of floats, vector of dimension n.
    :return value: value of the function at that point.
    """
    A = 10
    An = A * len(vector) # A * n, where n is the dimension of the space
    v = sum([np.power(x, 2) - A * np.cos(2 * np.pi * x) for x in vector])

    value = An + v
    return value


'''
Y is the dependant variable and X is the independant variable
We are going to fit a line
        Y = a0 + a1*x
using Gradient Descent minimizing the SSE.
This code will work for any variable with single attribute, i.e.
it is Linear Regression in 1 variable.
'''
import random
import matplotlib.pyplot as plt
import numpy as np

#Sum of Squares Error
def sse(n,a0,a1,x,y):
    """
    Compute the sse sse sse.

    Args:
        n: (array): write your description
        a0: (array): write your description
        a1: (array): write your description
        x: (array): write your description
        y: (array): write your description
    """
    s=0
    mean=np.mean(y)
    for i in range(n):
        s+=(a0+a1*x[i]-mean)**2
    return s/(2*n)

#Calculate the cost function
def cost(n,a0,a1,x,y,ch,p=2):
    """
    Calculate the cost between two points.

    Args:
        n: (todo): write your description
        a0: (todo): write your description
        a1: (todo): write your description
        x: (todo): write your description
        y: (todo): write your description
        ch: (todo): write your description
        p: (todo): write your description
    """
    s=0;
    if ch=='sum-of-squares':
        for i in range(n):
            s+=(a0+a1*x[i]-y[i])**2
        return s/(2*n)
    if ch=='l-p norm':
        for i in range(n):
            s+=abs(a0+a1*x[i]-y[i])**p
        return s**(1/p)

#Partial Differential with respect to a0
def dela0(n,a0,a1,x,y):
    """
    Dela0 dela0.

    Args:
        n: (array): write your description
        a0: (array): write your description
        a1: (array): write your description
        x: (array): write your description
        y: (array): write your description
    """
    s=0;
    for i in range(n):
        s+=(a0+a1*x[i]-y[i])
    return s/n

#Partial Differential with respect to a1
def dela1(n,a0,a1,x,y):
    """
    Dela1 dela1 dela1 dela

    Args:
        n: (array): write your description
        a0: (array): write your description
        a1: (array): write your description
        x: (array): write your description
        y: (array): write your description
    """
    s=0;
    for i in range(n):
        s+=(a0+a1*x[i]-y[i])*x[i]
    return s/n

def predict(x, y, alphas=np.linspace(0.001,1,10), it=1000):
    """
    Predict the predicted )

    Args:
        x: (array): write your description
        y: (array): write your description
        alphas: (array): write your description
        np: (array): write your description
        linspace: (array): write your description
        it: (array): write your description
    """
    mx=max(x)
    my=max(y)

    # Normalize values in the range 0-1
    for i in range(len(x)):
        x[i]/=mx
        y[i]/=my
    coeff, r2, cos = grad_desc(x, y, alphas, it)
    coeff, x, y = rescale(x, y, coeff, mx, my)
    r2_alpha(r2, alphas)
    plot_predict(x, y, coeff, r2, cos, it)
    # Store all predictions for which R^2 is maximum in an array
    a0=coeff[r2.index(max(r2))][0]
    a1=coeff[r2.index(max(r2))][1]
    pred=a0+x*a1
    return pred

def grad_desc(x, y, alphas, it):
    """
    Describe the objective function.

    Args:
        x: (todo): write your description
        y: (todo): write your description
        alphas: (todo): write your description
        it: (todo): write your description
    """
    r2=[]# Array to store calculated R^2 values
    coeff=[] #Array to store Predicted Coefficients for Linear Regression

    for alpha in alphas:
        cos=[]
        #Initialize random weights
        a0=random.random()
        a1=random.random()
        for i in range(it):
            # Reduce the coefficient by alpha times partial differential
            temp0=a0-alpha*dela0(len(x),a0,a1,x,y)
            temp1=a1-alpha*dela1(len(x),a0,a1,x,y)
            a0=temp0
            a1=temp1
            #Add the cost for each iteration
            cos.append(cost(len(x),a0,a1,x,y,ch='sum-of-squares'))
        # Calculate and store the R^2 value for a particular learning rate alpha
        r2.append(1-(cos[-1]/(cos[-1]+sse(len(x),a0,a1,x,y))))
        #Store the predicted coefficients for regression
        coeff.append([a0,a1])
    return coeff, r2, cos

def r2_alpha(r2, alphas):
    """
    Plot r2 alpha

    Args:
        r2: (todo): write your description
        alphas: (array): write your description
    """
    #Plot for R^2 vs alpha
    plt.plot(alphas, r2)
    plt.title('R^2 vs. Learning Rate')

    #Max. value of R^2 over all values of alpha
    print(max(r2))
    #Value of alpha for maximum R^2
    print(np.linspace(0.001,1,10)[r2.index(max(r2))])

def rescale(x, y, coeff, mx, my):
    """
    Rescale x y - axis.

    Args:
        x: (todo): write your description
        y: (todo): write your description
        coeff: (todo): write your description
        mx: (todo): write your description
        my: (todo): write your description
    """
    # Bring the data back to scale
    for i in range(len(coeff)):
        coeff[i][0]*=my
        coeff[i][1]*=my/mx
    for i in range(len(x)):
        x[i]*=mx
        y[i]*=my
    return coeff, x, y

def plot_predict(x, y, coeff, r2, cos, it):
    """
    Plots the r2d plot

    Args:
        x: (array): write your description
        y: (array): write your description
        coeff: (array): write your description
        r2: (array): write your description
        cos: (array): write your description
        it: (array): write your description
    """
    # Plot the training data, cost function and Predicted vs Actual values
    fig1,ax=plt.subplots(1,2,figsize=(14,4))
    ax[0].plot([x for x in range(it)],cos)
    ax[0].set_title('Cost Function')
    ax[0].set_xlabel('No. of Iterations')
    ax[1].scatter(x,y,marker='x',color='r',label="Training Data")
    ax[1].plot(np.arange(1,12),[coeff[r2.index(max(r2))][0]+coeff[r2.index(max(r2))][1]*x for x in np.arange(1,12)],label="Linear Regression")
    plt.legend()
    ax[1].set_title('Predicted vs Actual')
    plt.xlabel("Experience in Years")
    plt.ylabel("Salary")
    plt.show()

Machine Learning & AI/Linear_Regression_with_Gradient_Descent.py


from scipy.fftpack import fft
import numpy as np

def get_fft(t,x):

    """
    This function returns fast-fourier transform. fftpack in scipy is used for this purpose, however,
    numpy.fft.fft can also be used in similar manner.

    t:       time
    x:       signal

    fr:      frequency axis
    X_fr:    amplitude complex number
    amp:     amplitude
    angle:   phase angle
    """

    # Sampling Frequency
    Fs = 1 / (t[1] - t[0])

    # Generate Frequency Axis
    n = np.size(t)
    n_half = int(n / 2)
    fr = (Fs / 2) * np.linspace(0, 1, n_half)

    # Compute FFT
    X     = fft(x)
    X_fr  = (1 / n_half) * X[0:n_half]
    amp   = np.absolute(X_fr)
    angle = np.angle(X_fr)

    return fr, X_fr, amp, angle

def get_ifft(X):

    """
    X:            amplitude complex number
    """
    return np.fft.ifft(X).real * np.size(X) / 2

def fft_comps_cutoff(t, x, cutoff = 0.01):

    fr, X_fr, amp, angle = get_fft(t, x)

    # filter
    amp_norm = amp / amp.max()
    mask = amp_norm > cutoff

    return fr[mask], X_fr[mask], amp[mask], angle[mask]

def construct_time_signal_from_comps(t_vec, freq, amplitude, angle):

    y_vec = np.zeros_like(t_vec)
    for fr, amp, a in zip(freq, amplitude, angle):
        # y_vec += amp * np.sin(2 * np.pi * fr * t_vec + a)
        y_vec += amp * np.sin(2 * np.pi * fr * t_vec) # + a)

    return y_vec


import numpy as np

import matplotlib.pyplot as plt
#%matplotlib inline

#import matplotlib.image as img
#import PIL.Image as Image
from PIL import Image
import math
import cmath

import time

import csv

from numpy import binary_repr

from fractions import gcd

class Haar(object):
    """
    This class Haar implements all the procedures for transforming a given 2D digital image
    into its corresponding frequency-domain image (Haar Transform)
    """

    def __init__():
        pass

    #Compute the Haar kernel.
    @classmethod
    def computeKernel(self, N):
        """
        Computes/generates the haar kernel function.

        Parameters
        ----------
        N : int
            Size of the kernel to be generated.

        Returns
        -------
        kernel : ndarray
            The generated kernel as a matrix.
        """

        i = 0
        kernel = np.zeros([N, N])
        n = int(math.log(N, 2))

        #Fill for the first row of the kernel
        for j in xrange(N):
            kernel[i, j] = 1.0/math.sqrt(N)

        # For the other rows of the kernel....
        i += 1
        for r in xrange(n):
             for m in xrange(1, (2**r)+1):
                j=0
                for x in np.arange(0, 1, 1.0/N):
                    if (x >= (m-1.0)/(2**r)) and (x < (m-0.5)/(2**r)):
                        kernel[i, j] = (2.0**(r/2.0))/math.sqrt(N)
                    elif (x >= (m-0.5)/(2**r)) and (x < m/(2.0**r)):
                        kernel[i, j] = -(2.0**(r/2.0))/math.sqrt(N)
                    else:
                        kernel[i, j] = 0
                    j += 1
                i += 1
        return kernel

    @classmethod
    def computeForwardHaar(self, imge):
        """
        Computes/generates the 2D Haar transform.

        Parameters
        ----------
        imge : ndarray
            The input image to be transformed.

        Returns
        -------
        final2DHaar : ndarray
            The transformed image.
        """

        N = imge.shape[0]
        kernel = Haar.computeKernel(N)

        imge1DHaar = np.dot(kernel, imge)

        #Transpose the kernel as it is not symmetric
        final2DHaar = np.dot(imge1DHaar, kernel.T)

        return final2DHaar/N

    @classmethod
    def computeInverseHaar(self, imgeHaar):
        """
        Computes/generates the inverse of 2D Haar transform.

        Parameters
        ----------
        imgeHaar : ndarray
            The Haar transformed image.

        Returns
        -------
        imgeInverse : ndarray
            The inverse of the transformed image.
        """

        N = imgeHaar.shape[0]
        kernel = Haar.computeKernel(N)

        imge1DInverse = np.dot(kernel.T, imgeHaar)
        imgeInverse = np.dot(imge1DInverse, kernel)

        return imgeInverse/N


#!/usr/bin/env python
# GET TRANSFORMATION MATRIX FROM FIXED-ANGLES ROTATIONS AND A TRANSLATION
# SANTIAGO GARCIA AND ELKIN GUERRA

import numpy as np
import math

class Transformation:
    """
    Get transformation matrix from fixed-angles rotations and a translation.

    :returns: transformation matrix size(4, 4)
    :param angle_x: rotation of {B} with respect of {A} in "x" axis.
    :param angle_y: rotation of {B} with respect of {A} in "y" axis.
    :param angle_z: rotation of {B} with respect of {A} in "z" axis.
    :param vector_AB: vector from origin of {A} to origin of {B}.
    """

    def __init__(self, angle_x, angle_y, angle_z, vector_AB):
        # Add extra "1" to vector_AB
        vector_AB.append(1)
        self.vector_AB = np.transpose([vector_AB])

        # Initialize rotation matrices in zero
        self.RX = np.eye(3)
        self.RY = np.eye(3)
        self.RZ = np.eye(3)

        # Change the rotation matrices based on inputs
        self.create_rotation_matrix("x", angle_x)
        self.create_rotation_matrix("y", angle_y)
        self.create_rotation_matrix("z", angle_z)

        # Create homogeneous transformation matrix
        self.create_transformation_matriz()

    def create_rotation_matrix(self, axis, angle):

        if axis == "x":
            self.RX = np.array([
                [1, 0, 0],
                [0, math.cos(angle), -math.sin(angle)],
                [0, math.sin(angle), math.cos(angle)]
            ])

        if axis == "y":
            self.RY = np.array([
                [math.cos(angle), 0, math.sin(angle)],
                [0, 1, 0],
                [-math.sin(angle), 0, math.cos(angle)]
            ])

        if axis == "z":
            self.RZ = np.array([
                [math.cos(angle), -math.sin(angle), 0],
                [math.sin(angle), math.cos(angle), 0],
                [0, 0, 1]
            ])

    def create_transformation_matriz(self):
        # Get rotation matrix with fixed angles approach (Rxyz = Rz.Ry.Rx)
        R_ZYX = np.dot(np.dot(self.RZ, self.RY), self.RX)

        extra_zeros_perspective = np.array([[0, 0, 0]])
        self.TM = np.concatenate((R_ZYX, extra_zeros_perspective))
        self.TM = np.concatenate((self.TM, self.vector_AB), axis=1)

# TESTS
if __name__ == "__main__":
    test = Transformation(0, 0, math.radians(30), [10, 5, 0])
    print("\nRX:\n", test.RX)
    print("\nRY:\n", test.RY)
    print("\nRZ:\n", test.RZ)
    print("\nTM:\n", test.TM)

    test = Transformation(0, 0, math.radians(90), [1, 2, 3])
    print("\nRX:\n", test.RX)
    print("\nRY:\n", test.RY)
    print("\nRZ:\n", test.RZ)
    print("\nTM:\n", test.TM)


"""
    A/B split test calculator
    ----------

    This module implements the statistical calculation of the A/B test split significance. The
    implementation was taken from https://www.periscopedata.com/blog/ab-testing-in-redshift.html
    which contains the code to do the statistical analysis using the normal approximation method
    in redshift with scipy. This was translated to python using scipy too.
"""

from scipy.stats import norm

def standard_error(sample_size, successes):
    """
    Calculates the standard error of a sample proportion.

    Formula: σp = sqrt [ p(1 - p) / n ].
    with:
    p = proportion of successes in sample (successes / sample size)

    :param sample_size: the size of the sample
    :param successes: the number of successes on the given sample.
    :return: the standard error on the sample proportion -> σp
    """
    p = successes / sample_size
    return (p * (1 - p) / sample_size) ** 0.5

def significance(size_a, successes_a, size_b, successes_b):
    """
    Calculates the significance for an A/B test.

    :param size_a: Sample size of the experiment A
    :param successes_a: Successes of the experiment A
    :param size_b: Sample size fo the experiment B
    :param successes_b: Successes of the experiment b
    :return: The significance of the test.
    """
    # Raising an error if the condition of size_sample > successes is not met.
    if size_a < successes_a or size_b < successes_b:
        raise ValueError('The size numbers must be greater than the number of successes for an '
                         'experiment')

    p_a = successes_a / size_a
    p_b = successes_b / size_b
    se_a = standard_error(size_a, successes_a)
    se_b = standard_error(size_b, successes_b)

    numerator = (p_b - p_a)
    denominator = (se_a ** 2 + se_b ** 2) ** 0.5

    return norm.sf(abs(numerator / denominator))


import numpy as np

# We create a 5 x 5 ndarray that contains integers from 0 to 24
X = np.arange(25).reshape(5, 5)

# We print X
print()
print('Original X = \n', X)
print()

# We use Boolean indexing to select elements in X:
print('The elements in X that are greater than 10:', X[X > 10])
print('The elements in X that less than or equal to 7:', X[X <= 7])
print('The elements in X that are between 10 and 17:', X[(X > 10) & (X < 17)])

# We use Boolean indexing to assign the elements that are between 10 and 17 the value of -1
X[(X > 10) & (X < 17)] = -1

# We print X
print()
print('X = \n', X)
print()

## Set Operations

# We create a rank 1 ndarray
x = np.array([1,2,3,4,5])

# We create a rank 1 ndarray
y = np.array([6,7,2,8,4])

# We print x
print()
print('x = ', x)

# We print y
print()
print('y = ', y)

# We use set operations to compare x and y:
print()
print('The elements that are both in x and y:', np.intersect1d(x,y))
print('The elements that are in x that are not in y:', np.setdiff1d(x,y))
print('All the elements of x and y:',np.union1d(x,y))

## Sorting

# We create an unsorted rank 1 ndarray
x = np.random.randint(1,11,size=(10,))

# We print x
print()
print('Original x = ', x)

# We sort x and print the sorted array using sort as a function.
print()
print('Sorted x (out of place):', np.sort(x))

# When we sort out of place the original array remains intact. To see this we print x again
print()
print('x after sorting:', x)

# We sort x but only keep the unique elements in x
print(np.sort(np.unique(x)))

## Sorting in place

# We create an unsorted rank 1 ndarray
x = np.random.randint(1,11,size=(10,))

# We print x
print()
print('Original x = ', x)

# We sort x and print the sorted array using sort as a method.
x.sort()

# When we sort in place the original array is changed to the sorted array. To see this we print x again
print()
print('x after sorting:', x)

# When sorting rank 2 ndarrays, we need to specify to the np.sort() function whether we are sorting by rows or columns.
# This is done by using the axis keyword.

# We create an unsorted rank 2 ndarray
X = np.random.randint(1,11,size=(5,5))

# We print X
print()
print('Original X = \n', X)
print()

# We sort the columns of X and print the sorted array
print()
print('X with sorted columns :\n', np.sort(X, axis = 0))

# We sort the rows of X and print the sorted array
print()
print('X with sorted rows :\n', np.sort(X, axis = 1))

## Quiz question
X = np.arange(1, 26).reshape(5, 5)
print(X)
print(X[X%2 == 1])


import numpy as np
import matplotlib.pyplot as pyplot

def step_func(x) :
    '''
    안쓴다.
    '''
    return np.array(x>0, dtype=np.int)

def sigmoid_func(x) :
    '''
    안쓴다.
    '''
    return 1/(1+np.exp(-x))

def ReLU_func(x):
    '''
    쓴다.
    '''
    return np.maximum(0, x)

def parametric_ReLU_func(x):
    '''
    쓴다
    '''
    a=0.2
    return np.where(x>0, x, a*x)

def identity_func(x):
    '''
    출력층의 활성함수
     항등함수. 출력=입력
     회귀문제에서 사용
    '''
    return x

def softmax_func_overflow(x):
    '''
    출력층 활성함수
     신경망의 출력값으로 확률벡터를 얻는다. (해석 용이)
     분류문제에서 사용
     신경망의 출력값을 0~1 로 제한. 모든 출력값의 합은 1.
    '''
    expX=np.exp(x)
    sumX=np.sum(expX)
    return expX/sumX

def softmax_func(x):
    '''
    출력층 활성함수
     신경망의 출력값으로 확률벡터를 얻는다. (해석 용이)
     분류문제에서 사용
     신경망의 출력값을 0~1 로 제한. 모든 출력값의 합은 1.
     이전 버전에서 오버플로우가 발생하므로 x 에서 x 의 최대값을 빼서 오버플로우를 막는다.
    '''
    maxX=np.max(x)
    expX=np.exp(x-maxX)
    sumX=np.sum(expX)
    return expX/sumX

if __name__ == '__main__' :
    print('activation function')
    x=np.arange(-5, 5, 0.1)
    y_step=step_func(x)
    y_sig=sigmoid_func(x)
    y_ReLU=ReLU_func(x)
    y_para_ReLU=parametric_ReLU_func(x)

    pyplot.plot(x,y_step, '--')
    pyplot.plot(x,y_sig, '-.')
    pyplot.plot(x,y_ReLU,':')
    pyplot.plot(x,y_para_ReLU, ',')
    pyplot.show()

    print('\nsoftmax function')
    x=np.array([2.3, -0.9, 3.6])
    y=softmax_func_overflow(x)
    print(y, np.sum(y))

    # x1 = np.array([900, 1000, -1000]) # 입력이 너무 큰 경우 overflow
    # y1 = softmax_func_overflow(x1)
    # print(y1, np.sum(y1))

    print('\n개선된 softmax function') # overflow 가 해결됨
    x2=np.array([900, 1000, 1000])
    y2=softmax_func(x2)
    print(y2, np.sum(y2))