# Implement Bayes Classifier here!
import numpy as np
def sep_class(X,y):
    train={}
    for i in range(len(y)):
        x=X[i]
        label=y[i]
        if(label not in train):
            train[label]=[]
        train[label].append(x)
    return train
def class_estimates(train):
    mean={}
    var={}
    for label in train:
        #calculate sample mean
        mean[label]=np.mean(np.asarray(train[label]),axis=0)
        #calculate sample variance. ddof set(unless only one example is there for label)
        #because we have to divide by n-1 to get sample variance
        dof=1
        if(len(train[label])==1):
            dof=0
        var[label]=np.var(np.asarray(train[label]),axis=0,ddof=dof)
    return mean,var
def prior_prob(train):
    p_class={}
    n=sum([len(v) for v in train.values()])
    for label in train:
        p_class[label]=len(train[label])/n
    return p_class
def likelihood(x,mean,var):
    p=0.0
    for i in range(len(x)):
        if(var[i]==0):
            if(x[i]==mean[i]):
                return 1.0
            else:
                return 0.0
        else:
            p=p-0.5*np.log(2*np.pi*var[i])-((x[i]-mean[i])**2)/(2*var[i])
    return (p)
def posterior(x,train):
    post={}
    mean,var=class_estimates(train)
    p_class=prior_prob(train)
    for label in train:
        post[label]=likelihood(x,mean[label],var[label])+np.log(p_class[label])
    return post
def predict(X_test,X_train,y_train):
    n_test=X_test.shape[0]
    train=sep_class(X_train,y_train)
    pred_label=np.zeros(n_test)
    for i in range(n_test):
        post=posterior(X_test[i,:],train)
        pred_label[i]=max(post,key=lambda k:post[k])
    return pred_label


from sympy.core.sympify import _sympify
from sympy.matrices.expressions import MatrixExpr
from sympy.core.numbers import I
from sympy.core.singleton import S
from sympy.functions.elementary.exponential import exp
from sympy.functions.elementary.miscellaneous import sqrt

class DFT(MatrixExpr):
    r"""
    Returns a discrete Fourier transform matrix. The matrix is scaled
    with :math:`\frac{1}{\sqrt{n}}` so that it is unitary.

    Parameters
    ==========

    n : integer or Symbol
        Size of the transform.

    Examples
    ========

    >>> from sympy.abc import n
    >>> from sympy.matrices.expressions.fourier import DFT
    >>> DFT(3)
    DFT(3)
    >>> DFT(3).as_explicit()
    Matrix([
    [sqrt(3)/3,                sqrt(3)/3,                sqrt(3)/3],
    [sqrt(3)/3, sqrt(3)*exp(-2*I*pi/3)/3,  sqrt(3)*exp(2*I*pi/3)/3],
    [sqrt(3)/3,  sqrt(3)*exp(2*I*pi/3)/3, sqrt(3)*exp(-2*I*pi/3)/3]])
    >>> DFT(n).shape
    (n, n)

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/DFT_matrix

    """

    def __new__(cls, n):
        n = _sympify(n)
        cls._check_dim(n)

        obj = super().__new__(cls, n)
        return obj

    n = property(lambda self: self.args[0])  # type: ignore
    shape = property(lambda self: (self.n, self.n))  # type: ignore

    def _entry(self, i, j, **kwargs):
        w = exp(-2*S.Pi*I/self.n)
        return w**(i*j) / sqrt(self.n)

    def _eval_inverse(self):
        return IDFT(self.n)

class IDFT(DFT):
    r"""
    Returns an inverse discrete Fourier transform matrix. The matrix is scaled
    with :math:`\frac{1}{\sqrt{n}}` so that it is unitary.

    Parameters
    ==========

    n : integer or Symbol
        Size of the transform

    Examples
    ========

    >>> from sympy.matrices.expressions.fourier import DFT, IDFT
    >>> IDFT(3)
    IDFT(3)
    >>> IDFT(4)*DFT(4)
    I

    See Also
    ========

    DFT

    """
    def _entry(self, i, j, **kwargs):
        w = exp(-2*S.Pi*I/self.n)
        return w**(-i*j) / sqrt(self.n)

    def _eval_inverse(self):
        return DFT(self.n)


import bisect
import random
import sys

import numpy as np

HAYSTACK = np.arange(1, 30, 2)
NEEDLES = np.arange(1, 30, 3)
ROW_FMT = '{0:2d} @ {1:2d}     {2}{0:<2d}'

def demo(bisect_fn):
    for needle in reversed(NEEDLES):
        position = bisect_fn(HAYSTACK, needle)
        # graphical offset showing where the item is to be inserted
        offset = position * '  |'
        print(ROW_FMT.format(needle, position, offset))

def grade(score, bisect_fn, breakpoints=None, grades='FDCBA'):
    """
    Use case of bisect: table lookups by numeric values, such as converting scores to grades.
    """
    if breakpoints is None:
        breakpoints = [60, 70, 80, 90]
    i = bisect_fn(breakpoints, score)
    return grades[i]

def demo_insort(list_size):
    random.seed(1917)
    my_list = []
    for i in range(list_size):
        new_item = random.randrange(list_size * 2)
        bisect.insort(my_list, new_item)
        print('%2d ->' % new_item, my_list)

if __name__ == "__main__":
    # When the items are equal in comparison, bisect_right returns an insertion point after the existing item,
    # and bisect_left returns the position of the existing item
    if sys.argv[-1] == 'left':
        bisect_fn = bisect.bisect_left
    else:
        bisect_fn = bisect.bisect_right

    print('DEMO:', bisect_fn.__name__)
    print('haystack ->', ' '.join('%2d' % n for n in HAYSTACK))
    demo(bisect_fn)

    # Faster than using the index method for very large lists.
    print('GRADES:')
    [print(f'{round(score)} -> {grade(round(score), bisect_fn)}') for score in np.linspace(30, 100, 7)]

    # Inserting an item into an ordered list
    demo_insort(list_size=7)


import numpy as np
from matplotlib import pyplot as plt

def rk4(f, y0, T, N):
    # f(t_n, y_n) -> y'_n
    # y0 = Initial value
    # T = Final value of t, t varies from 0 to T inclusive
    # N = number of steps
    y = np.array(y0, dtype=float)
    h = float(T)/N
    ts = np.linspace(0, T, N+1)

    out = np.empty(shape=(N+1,y.shape[0]), dtype=float)

    for i, t in enumerate(ts[:-1]):
        out[i] = y
        k1 = f(t, y)
        k2 = f(t+0.5*h, y + 0.5*h*k1)
        k3 = f(t+0.5*h, y + 0.5*h*k2)
        k4 = f(t+h, y + h*k3)
        y += h* 1/6.0 * (k1 + k2+k2 + k3+k3 + k4)

    out[N] = y

    return out

def p3a():
    f = lambda t,y: y
    y0 = [1]
    T = 1

    return (np.e - rk4(f,y0,T,10)[10,0])/(np.e - rk4(f,y0,T,20)[20,0])

def p3b():
    f = lambda t,y: y
    y0 = [1]
    T = 1

    for n in range(1,100):
        approx = rk4(f, y0, T, n)[n,0]
        if str(approx)[:7] == '2.71828':
            return f'Step size N = {n} returns y_N = {approx}'

beta = 0.5 # S->I growth
gamma = 0.25 # I->R growth
rho1 = 0.01 # Group 1->2 growth
rho2 = 0.01 # Group 2->1 growth

y0 = np.array([.95,.05,0,1,0,0])
T = 60

def f(t,Phi): # f(t,y) = y'
    S1, I1, R1, S2, I2, R2 = Phi # Extract pre-step values
    f = np.zeros(6) # Output array
    f[0] = -beta*S1*I1-rho1*S1+rho2*S2          # New S1
    f[1] = beta*S1*I1-gamma*I1-rho1*I1+rho2*I2  # New I1
    f[2] = gamma*I1-rho1*R1+rho2*R2             # New R1
    f[3] = -beta*S2*I2-rho2*S2+rho1*S1          # New S2
    f[4] = beta*S2*I2-gamma*I2-rho2*I2+rho1*I1  # New I2
    f[5] = gamma*I2-rho2*R2+rho1*R1             # New R2
    return f   # Return new values

def p5d():
    N25 = rk4(f, y0, T, 25)[25,:]
    N50 = rk4(f, y0, T, 50)[50,:]
    N100 = rk4(f, y0, T, 100)[100,:]

    for i, label in enumerate(['S_1','I_1','R_1','S_2','I_2','R_2']):
        print(f'Ratio for {label} = {(N50[i] - N25[i])/(N100[i] - N50[i])}')

def p5efgh(r1, r2):
    global rho1, rho2

    rho1 = r1
    rho2 = r2

    arr = rk4(f, y0, T, 100)
    ts = np.linspace(0,T,101) # All t values

    plt.figure()  # Start a plot
    plt.plot(ts,arr[:,0],'-',linewidth=1)   # Plot S1
    plt.plot(ts,arr[:,1],'-',linewidth=1)   # Plot I1
    plt.plot(ts,arr[:,2],'-',linewidth=1)   # Plot R1
    plt.plot(ts,arr[:,3],'--',linewidth=1)   # Plot S2
    plt.plot(ts,arr[:,4],'--',linewidth=1)   # Plot I2
    plt.plot(ts,arr[:,5],'--',linewidth=1)   # Plot R2
    plt.legend(['S_1','I_1','R_1','S_2','I_2','R_2'])  # Label each plot accordingly
    plt.xlabel('t') # Label x axis
    plt.show() # Finish and show the plot

def ab2(f, y0, y1, T, N):
    # f(t_n, y_n) -> y'_n
    # y0,y1 = Initial values
    # T = Final value of t, t varies from 0 to T inclusive
    # N = number of steps
    h = float(T)/N
    ts = np.linspace(0, T, N+1)

    out = np.empty(shape=(N+1,y0.shape[0]), dtype=float)
    out[0] = np.array(y0, dtype=float)
    out[1] = np.array(y1, dtype=float)

    for i in range(2,N+1):
        tm1 = ts[i-1]
        tm2 = ts[i-2]
        ym1 = out[i-1]
        ym2 = out[i-2]

        out[i] = ym1 + h*(1.5*f(tm1,ym1) - 0.5*f(tm2, ym2))

    return out

def p5i():
    y1 = y0
    N25 = ab2(f, y0, y1, T, 25)[25,:]
    N50 = ab2(f, y0, y1, T, 50)[50,:]
    N100 = ab2(f, y0, y1, T, 100)[100,:]

    for i, label in enumerate(['S_1','I_1','R_1','S_2','I_2','R_2']):
        print(f'Ratio for {label} = {(N50[i] - N25[i])/(N100[i] - N50[i])}')


"""
    2D trapezoidal rule to integrate Gauss's law for a dipole

    Solution to Problem Set 2, Problem 3
    To run:
        python trap_rule_2_3.py

"""

import matplotlib.pyplot as plt
import numpy as np

def trap_2D(f, x_min, x_max, y_min, y_max, n, m,*P):
    hx = (x_max-x_min)/n
    hy = (y_max-y_min)/m

# contributions from rectangle corners
    I = (f(x_min,y_min,*P)+f(x_min,y_max,*P)+f(x_max,y_min,*P)+f(x_max,y_max,*P))/4

# contributions from rectangle sides
    I_x = 0

    for i in range(1,n):
        xi = x_min+i*hx
        I_x += (f(xi,y_min,*P)+f(xi,y_max,*P))/2;

    I_y = 0

    for j in range(1,m):
        yj = y_min+j*hy
        I_y += (f(x_min,yj,*P)+f(x_max,yj,*P))/2

# contributions from inside of rectangle
    I_xy = 0

    for i in range(1,n):
        for j in range(1,m):
            xi = x_min+i*hx
            yj = y_min+j*hy

            I_xy += f(xi,yj,*P)

    return (I+I_x+I_y+I_xy)*hx*hy

#function to be integrated, divided by q
def Er_R2_overQ(theta,phi, d,R):
    return 1/(4.*np.pi) * (2+d/R*np.sin(theta)*np.cos(phi))*np.sin(theta)

int_analytic = 2.0
#integration boundaries
theta_min = 0
theta_max = np.pi
phi_min = 0
phi_max = 2.*np.pi
#choose some values for (d,R) such that d/R = 0.1
d = 0.1
R = 1
P =(0.1,1)
N = np.array([50, 100, 200, 400])
rel_err = np.zeros(4)
for i in range(N.shape[0]):
    int_trap = trap_2D(Er_R2_overQ, theta_min,theta_max,phi_min,phi_max, N[i], N[i],*P)
    rel_err[i] = np.abs(int_trap - int_analytic) / int_analytic

#fit a line to log(N), log(rel_err) to get slope/convergence rate
m, b = np.polyfit(np.log(N), np.log(rel_err), 1)
print("convergence rate 2D trapezoidal rule %.3f" % m)
plt.xlabel("log(number of steps)")
plt.ylabel("log(relative Error)")
plt.yscale('log')
plt.xscale('log')
#plot relative error
plt.plot(N, rel_err, marker ='o',label='2D Trapezoidal Rule',color ='b')
# and best fit
plt.plot(N,np.exp(np.log(N)*m+b),linestyle = "--",color ='b')
plt.legend()
plt.show()

Problem Sets/Problem Set 2/Solutions/trap2D_ps2_3.py


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
print(tf.__version__)

"""## We want to try some non linear curvy datasets"""

n = 10000
std = 6
X = np.random.random((n,2)) * (2*std) - (std)
y = np.cos(X[:,0]) + np.sin(X[:,1])

# TRAIN TEST SPLIT
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)

print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)

# Visualising the dataset
plt.scatter(X_train[:,0], y_train, color = 'red')
plt.title('X1 Plot')
plt.xlabel('X1')
plt.ylabel('y')
plt.show()

# Visualising the dataset
plt.scatter(X_train[:,1], y_train, color = 'red')
plt.title('X2 Plot')
plt.xlabel('X2')
plt.ylabel('y')
plt.show()

# Visualising the dataset with the target variable
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.scatter(X_train[:,0], X_train[:,1], y_train)
plt.title('Scatter Plot')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()

N, D = X_train.shape

model = tf.keras.models.Sequential([
                                    tf.keras.layers.Flatten(input_shape = (D,)),
                                    tf.keras.layers.Dense(40, activation='relu'),
                                    tf.keras.layers.Dense(1)
])

#custom_opt = tf.keras.optimizers.Adam(0.01)
model.compile(
    optimizer='adam',
    loss='mse')

report = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs = 100)

plt.plot(report.history['loss'], label="loss")
plt.plot(report.history['val_loss'], label="validation_loss")
plt.legend()

print("Train eval: ", model.evaluate(X_train, y_train))
print("Test eval: ", model.evaluate(X_test, y_test))

y_pred = model.predict(X_test)[:,0]

print(y_test.shape)
print(y_pred.shape)

plt.scatter(y_test, y_pred, color = 'b')
plt.title('y_test vs y_pred')
plt.xlabel('y_test')
plt.ylabel('y_pred')
plt.show()

# Visualising the dataset
plt.scatter(X_test[:,0], y_test, color = 'red')
plt.scatter(X_test[:,0], y_pred, color = 'b')
plt.title('Scatter Plot PCA')
plt.xlabel('PCA 1')
plt.ylabel('y')
plt.show()

# Visualising the dataset
plt.scatter(X_test[:,1], y_test, color = 'red')
plt.scatter(X_test[:,1], y_pred, color = 'b')
plt.title('Scatter Plot PCA')
plt.xlabel('PCA 2')
plt.ylabel('y')
plt.show()

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[:,0], X[:,1], y)

y_pred = model.predict(X).flatten()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[:,0], X[:,1], y_pred)
plt.show()


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

#This version of ImageBlur was designed to run from the command line
#It takes a single command line parameter which is the image to blur

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import sys

# First we're going to load in an image, convert it into a single colour (greyscale), and resize it for convenience.
#

#Report if you don't supply the right number of command line arguments
if(len(sys.argv) != 2 ):
    print("Usage:")
    print("    ImageBlur.py <filename>")
    exit()

#This line opens the command line parameter as an image file
#and bombs out if it fails
try:
    img = Image.open(sys.argv[1]).convert('L')
except Exception as e:
    print("Unable to open image file. Error was : " + str(e))
    exit()

# We'll work with a resized version of this image
dim = 2000
img_resized = img.resize((dim,dim))

# ... and convert it into a numpy array of floats
img_data = np.asarray(img_resized,dtype=float)

# Show the image
plt.figure(figsize = [6, 6])
plt.imshow(img_data,cmap='gray');

# A simple image blur is done by convolving the image with a Gaussian, so we need to create one of the right size. Convolution is most-easily done by converting to Fourier space and multiplying, then converting back into real space.

# In[9]:

#CHANGE this line to adjust blur amount. Higher is more blurred
width =  0.2

# Define a Gaussian in 1D on a grid with the same number of points as the image
domain = np.linspace(-5,5,dim)
gauss = np.exp(-0.5*domain**2/(width*width))

# Roll this around the 1D boundary so that the Gaussian is centered on grid 0,0
shift = int(dim/2)
gauss = np.roll(gauss,shift)

# Turn into a 2D Gaussian
gauss2D = gauss[:,np.newaxis] * gauss[np.newaxis,:]

# In[7]:

# Fourier transform the image and the Gaussian using standard numpy functions
img_fft   = np.fft.fft2(img_data)
gauss_fft = np.fft.fft2(gauss2D)

# In[8]:

# Multiplication in Fourier space
img_conv = img_fft*gauss_fft
# Transform the result back into real space using the inverse transform
img_ifft = np.fft.ifft2(img_conv)

# Display the result of blurring the picture
plt.figure(figsize = [6, 6])
plt.imshow(img_ifft.real,cmap='gray');

plt.show()
# In a real program we'd probably want to save this image somehow, or do some more processing here.


import numpy as np

def normalize_data(n_covid, n_people, scale):
    # TODO: Calculate the number of cases per its population

    norm_cases = [i/j*1000000 for i,j in zip(n_covid,n_people)]
    for idx, n in enumerate(n_covid):
        norm_cases.append(idx)
    return norm_cases

regions  = ['Seoul', 'Gyeongi', 'Busan', 'Gyeongnam', 'Incheon', 'Gyeongbuk', 'Daegu', 'Chungnam', 'Jeonnam', 'Jeonbuk', 'Chungbuk', 'Gangwon', 'Daejeon', 'Gwangju', 'Ulsan', 'Jeju', 'Sejong']
n_people = [9550227.,  13530519., 3359527.,     3322373.,   2938429.,     2630254., 2393626.,    2118183.,   1838353.,   1792476.,    1597179.,   1536270.,   1454679.,   1441970., 1124459., 675883.,   365309.] # 2021-08
n_covid  = [    644,       529,      38,          29,       148,          28,      41,         62,        23,        27,         27,        33,        16,        40,      20,      5,        4] # 2021-09-21

sum_people = sum(n_people) # TODO: The total number of people
sum_covid  = sum(n_covid) # TODO: The total number of new cases
norm_covid = normalize_data(n_covid, n_people, 1000000) # The new cases per 1 million people

# Print population by region
print('### Korean Population by Region')
print('* Total population:', sum_people)
print("---------------------------------")
print('| Region | Population | Ratio (%) |')
print('| ------ | ---------- | --------- |')
ratio = [x/sum_people*100. for x in n_people]
for idx, pop in enumerate(n_people):
    print('| %s | %d | %.1f |' % (regions[idx], pop, ratio[idx]))
print('')

# TODO: Print COVID-19 new cases by region
print("### Korean COVID-19 New Cases by Region")
print("* Total sum:", sum_covid)
print('| Region | New Cases | Ratio (%) | New Cases/1m |')
print('| ------ | ---------- | --------- | --------- |')
ratio = [i/100 for i in n_covid]
for idx, covid in enumerate(n_covid):
    # TODO: The ratio of new cases to the total
    print('| %s | %d | %.1f | %.1f |' % (regions[idx], covid, ratio[idx], norm_covid[idx]))
print('')


import random
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets.samples_generator import make_blobs

np.random.seed(0)

X, y = make_blobs(n_samples=5000, centers=[[4,4], [-2, -1], [2, -3], [1, 1]], cluster_std=0.9)

plt.scatter(X[:, 0], X[:, 1], marker='.')

k_means = KMeans(init = "k-means++", n_clusters = 4, n_init = 12)

k_means.fit(X)

k_means_labels = k_means.labels_
k_means_labels

k_means_cluster_centers = k_means.cluster_centers_
k_means_cluster_centers

# Initialize the plot with the specified dimensions.
fig = plt.figure(figsize=(6, 4))

# Colors uses a color map, which will produce an array of colors based on
# the number of labels there are. We use set(k_means_labels) to get the
# unique labels.
colors = plt.cm.Spectral(np.linspace(0, 1, len(set(k_means_labels))))

# Create a plot
ax = fig.add_subplot(1, 1, 1)

# For loop that plots the data points and centroids.
# k will range from 0-3, which will match the possible clusters that each
# data point is in.
for k, col in zip(range(len([[4, 4], [-2, -1], [2, -3], [1, 1]])), colors):
    # Create a list of all data points, where the data poitns that are
    # in the cluster (ex. cluster 0) are labeled as true, else they are
    # labeled as false.
    my_members = (k_means_labels == k)

    # Define the centroid, or cluster center.
    cluster_center = k_means_cluster_centers[k]

    # Plots the datapoints with color col.
    ax.plot(X[my_members, 0], X[my_members, 1], 'w', markerfacecolor=col, marker='.')

    # Plots the centroids with specified color, but with a darker outline
    ax.plot(cluster_center[0], cluster_center[1], 'o', markerfacecolor=col, markeredgecolor='k', markersize=6)

# Title of the plot
ax.set_title('KMeans')

# Remove x-axis ticks
ax.set_xticks(())

# Remove y-axis ticks
ax.set_yticks(())

# Show the plot
plt.show()

#wget -O Cust_Segmentation.csv https://cf-courses-data.s3.us.cloud-object-storage.appdomain.cloud/IBMDeveloperSkillsNetwork-ML0101EN-SkillsNetwork/labs/Module%204/data/Cust_Segmentation.csv

import pandas as pd
cust_df = pd.read_csv("Cust_Segmentation.csv")
cust_df.head()

df = cust_df.drop('Address', axis=1)
df.head()

from sklearn.preprocessing import StandardScaler
X = df.values[:,1:]
X = np.nan_to_num(X)
Clus_dataSet = StandardScaler().fit_transform(X)
Clus_dataSet

clusterNum = 3
k_means = KMeans(init = "k-means++", n_clusters = clusterNum, n_init = 12)
k_means.fit(X)
labels = k_means.labels_
print(labels)

df["Clus_km"] = labels
df.head(5)

df.groupby('Clus_km').mean()

area = np.pi * ( X[:, 1])**2
plt.scatter(X[:, 0], X[:, 3], s=area, c=labels.astype(np.float), alpha=0.5)
plt.xlabel('Age', fontsize=18)
plt.ylabel('Income', fontsize=16)

plt.show()

from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(1, figsize=(8, 6))
plt.clf()
ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=48, azim=134)

plt.cla()
# plt.ylabel('Age', fontsize=18)
# plt.xlabel('Income', fontsize=16)
# plt.zlabel('Education', fontsize=16)
ax.set_xlabel('Education')
ax.set_ylabel('Age')
ax.set_zlabel('Income')

ax.scatter(X[:, 1], X[:, 0], X[:, 3], c= labels.astype(np.float))


# Problem: https://projecteuler.net/problem=201

"""
    . Let state encode the size of subset and the curr_sum of a subset as follows,
        state = curr_sum * (MAX_SUBSET_SIZE + 1) + subset_size
    . This way of encoding states allow us to easily generate the next states.
      For example, if we want to add a new element of value V to the state, we have
      new_state = (curr_sum + V) * (MAX_SUBSET_SIZE + 1) + subset_size + 1
                = curr_sum * (MAX_SUBSET_SIZE + 1) + subset_size + V * (MAX_SUBSET_SIZE+1) + 1
                = state + V * (MAX_SUBSET_SIZE+1) + 1
    . Let DP[i][state] keep the number of combinations of subsets of size j and of sum k where state = k * (MAX_SUBSET_SIZE + 1) + j and the subset consists of elements from the first i elements from the superset.
        . DP[i][state] = 0 if there are no such a combination
        . DP[i][state] = 1 if there's one such a combination
        . DP[i][state] = 2 if there are more than one such a combination
    . We have that,
        DP[i+1][state] = DP[i][state] + DP[i][prev_state]
            where prev_state = (curr_sum - element[i+1]) * (MAX_SUBSET_SIZE + 1) + subset_size - 1
                for each corresponding state where state = curr_sum * (MAX_SUBSET_SIZE + 1) + subset_size
        This is correct as += DP[i][state] means that we decide to not to add the elements[i+1]
                    and    += DP[i][prev_state] means that we decide to add the elements[i+1].
"""

import numpy as np
from scipy.ndimage.interpolation import shift

N = 100
M = 50

elements = [k*k for k in range(1, N+1)]
max_sum = sum(sorted(elements)[-M:])

def encode(subset_size, curr_sum):
    return curr_sum * (M+1) + subset_size
def decode(h):
    return h % (M+1), h // (M+1)

n_states = (M+1) * (max_sum+1)

if __name__ == "__main__":
    ans = 0

    prev_DP = None
    curr_DP = np.zeros(n_states+1, dtype = np.int16)

    curr_DP[encode(0, 0)] = 1

    for i, element in enumerate(elements):
        prev_DP, curr_DP = curr_DP, prev_DP
        curr_DP = prev_DP + shift(prev_DP, element*(M+1) + 1, cval=0)
        #                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        #                   generate the next states from the previous states
        curr_DP[np.where(curr_DP > 1)] = 2

    size_M_index = np.arange(max_sum+1) * (M+1) + M
    result_index = curr_DP[size_M_index]
    ans = np.sum(np.where(result_index == 1))
    print(ans)


import numpy as np

def radius_of_curvature(p0, p1, p2):
    """
    Calculates the radius of curvurature between three points. Based on https://stackoverflow.com/questions/1211212/how-to-calculate-an-angle-from-three-points and https://en.wikipedia.org/wiki/Degree_of_curvature.
    """
    a = np.array([p1[0] - p2[0], p1[1] - p2[1]])
    b = np.array([p1[0] - p0[0], p1[1] - p0[1]])
    c = np.array([p0[0] - p2[0], p0[1] - p2[1]])
    Dc = np.arccos(a.dot(b) / (np.linalg.norm(a) * np.linalg.norm(b)))
    radius_of_curvature = np.linalg.norm(c) / (2 * np.sin(Dc / 2))
    return radius_of_curvature


import numpy as np
from scipy import stats
from scipy.stats import levene, f_oneway

def gaussian_test(col, values):
    stat1, p1 = stats.shapiro(values)
    stat2, p2 = stats.normaltest(values)

    print(f"Gaussian: {col}\n\t{p1:5f} (Shapiro-Wilk)\n\t{p2:5f} (D'Agostino's)")

def correlation_test(df):
    pearson_stat = df.corr(method=lambda x, y: stats.pearsonr(x, y)[0])
    pearson_p = df.corr(method=lambda x, y: stats.pearsonr(x, y)[1])
    spearman_stat = df.corr(method=lambda x, y: stats.spearmanr(x, y)[0])
    spearman_p = df.corr(method=lambda x, y: stats.spearmanr(x, y)[1])

    pearson_p = (pearson_p - np.eye(df.shape[1])).round(4)
    spearman_p = (spearman_p - np.eye(df.shape[1])).round(4)

    return pearson_stat, pearson_p, spearman_stat, spearman_p

def boldness_test(bold1, bold2, bold3):
    rng = np.random.RandomState(42)
    a_ton_of_text_boldness = rng.uniform(low=0.7, high=bold2 + 0.5, size=200)

    variance_check = [[bold1, bold2], [bold2, bold3]]

    for check in variance_check:
        stat1, p1 = levene(a_ton_of_text_boldness, check, center='mean')
        stat2, p2 = f_oneway(a_ton_of_text_boldness, check)

        print(f'{p1:5f}')
        print(f'{p2:5f}')


import numpy as np

'''
Compute cost function
@param x matrix of size (set_len, input_len)
@param y vector of size (set_len) - expected values
@param w vector of size (input_len) - weights
@param b vector of size (1) - bias
@return cost value
'''
def cost_function(X, y, w, b):
    y_hat = np.dot(X, w) + b
    res = 0.5 * np.sum((y - y_hat) ** 2)
    return res

def evaluate(X, y, w, b):
    print('Cost: ' + str(cost_function(X, y, w, b)))

'''
Apply stochastic gradient descent on the whole training set of size set_len
@param x matrix of size (set_len, input_len)
@param y vector of size (set_len) - expected values
@param w vector of size (input_len) - weights
@param b vector of size (1) - bias
@param lr - learning rate
@return vector (input_len) updated weights, updated biais
'''
def sgd(X, y, w, b, lr):
    y_hat = np.dot(X, w) + b
    dW = np.dot(X.T, y_hat - y)
    dB = sum(y_hat - y)
    w = w - lr * dW
    b = b - lr * dB
    return w, b

'''
@param x matrix of size (set_len, input_len)
@param y vector of size (set_len) - expected values
@param epochs - number of epochs of learning
@param lr - learning rate

Run the training for several epochs.
After each epochs, the wieghts are tested on the training set
'''
def train(X, y, epochs, lr):

    w = np.random.randn(X.shape[1])
    b = np.random.randn(1)

    #Training
    for i in range(1, epochs + 1):
        print('Epoch :' + str(i))
        w, b = sgd(X, y, w, b, lr)
        evaluate(X, y, w, b)

    return w, b


# Credits to @Micah on StackOverflow
# got this function from https://stackoverflow.com/questions/22239691/code-for-line-of-best-fit-of-a-scatter-plot-in-python
# Added some of my own code to increase redability and made it work with NaN's in the data

# Function to plot a Line of best Fit (Trendline)
import numpy as np
import matplotlib.pyplot as plt

def trendline(xd, yd, order=1, c='r', alpha=1, Rval=True):
    """Make a line of best fit,
       Set Rval=False to print the R^2 value on the plot"""

    #Only be sure you are using valid input (not NaN)
    idx = np.isfinite(xd) & np.isfinite(yd)

	#Calculate trendline
    coeffs = np.polyfit(xd[idx], yd[idx], order)

    intercept = coeffs[-1]
    slope = coeffs[-2]
    power = coeffs[0] if order == 2 else 0

    minxd = np.min(xd)
    maxxd = np.max(xd)

    xl = np.array([minxd, maxxd])
    yl = power * xl ** 2 + slope * xl + intercept

    #Plot trendline
    plt.plot(xl, yl, c, alpha=alpha)

    #Calculate R Squared
    p = np.poly1d(coeffs)

    ybar = np.sum(yd) / len(yd)
    ssreg = np.sum((p(xd) - ybar) ** 2)
    sstot = np.sum((yd - ybar) ** 2)
    Rsqr = ssreg / sstot

    if not Rval:
        #Plot R^2 value
        plt.text(0.8 * maxxd + 0.2 * minxd, 0.8 * np.max(yd) + 0.2 * np.min(yd),
                 '$R^2 = %0.2f$' % Rsqr)
    else:
        #Return the R^2 value:
        return Rsqr


'''
the basic implementation of rotation matrix, Axis-angle, Euler angle and Quaternion.
'''
import numpy as np

def cross_product():
    # study cross product and skew-symmetric
    a = np.random.rand(3)
    b = np.random.rand(3)
    print('a cross product b:', np.cross(a, b))
    print('using skew-symmetric:')

    def skew_symmetric(a):
        return np.array([
            [0, -a[2], a[1]],
            [a[2], 0, -a[0]],
            [-a[1], a[0], 0]
        ])

    print('cross by using skew_symmetric:', skew_symmetric(a) @ b)

def rotation_matrix():
    # create two coordinate which rotate by z axis: angle: 45 degree.
    e_1 = np.array([[1], [0], [0]])
    e_2 = np.array([[0], [1], [0]])
    e_3 = np.array([[0], [0], [1]])
    E = np.hstack((e_1, e_2, e_3))
    e_1p = np.array([[1.], [1.], [0.]]) / np.sqrt(2)
    e_2p = np.array([[-1.], [1.], [0.]]) / np.sqrt(2)
    e_3p = np.array([[0], [0], [1]])
    Ep = np.hstack((e_1p, e_2p, e_3p))
    R = E.T @ Ep
    print('rotation matrix:R=\n', R)
    print('R inv:\n', np.linalg.inv(R))
    print('R.T:\n', R.T)
    print('we can find R.T == inv(R)')
    print('check orthogonal property:', np.linalg.norm(R @ R.T - np.eye(3)))

    # using homogeneous representation
    # create two translation vector.
    t1 = np.array([[1], [2], [3]])
    t2 = np.array([[3], [2], [1]])
    R1 = R
    R2 = R1 @ R1 @ R1
    p = np.array([[2], [3], [5]])
    print('after transformation:')
    res1 = R2 @ (R1 @ p + t1) + t2
    print('res=', res1.ravel())
    print('using Homogeneous coordinates:')
    p1 = np.vstack((p, 1))
    T1 = np.hstack((R1, t1))
    tmp = np.array([[0, 0, 0, 1]])
    T1 = np.vstack((T1, tmp))
    print('Transform matrix:T1=\n', T1)

    T2 = np.hstack((R2, t2))
    tmp = np.array([[0, 0, 0, 1]])
    T2 = np.vstack((T2, tmp))
    print('Transform matrix:T2=\n', T2)
    res2 = T2 @ T1 @ p1
    print('res=', res2.ravel()[:3])

if __name__ == '__main__':
    rotation_matrix()


# Copyright 2021 Neuron-AI GitHub Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
from numpy import array, sqrt
from warnings import warn

def euclidean_distance(x, y, **kwargs):
	x = array(x).reshape(1, -1)
	y = array(y).reshape(1, -1)

	if x.shape != y.shape and kwargs.get("suppress_warnings") != True:
		warn(UserWarning("using sequences which do not contain equivalent numbers of items can result in unexpected results."))

	return sqrt(sum((x - y)**2 for x, y in zip(x[0], y[0])))

def manhattan_distance(x, y, **kwargs):
	x = array(x).reshape(1, -1)
	y = array(y).reshape(1, -1)

	if x.shape != y.shape and kwargs.get("suppress_warnings") != True:
		warn(UserWarning("using sequences which do not contain equivalent numbers of items can result in unexpected results."))

	return sum(abs((x - y)) for x, y in zip(x[0], y[0]))

distance_functions = {
    "euclidean": euclidean_distance,
    "manhattan": manhattan_distance
}


"""Measures of dispersion of datasets"""

import numpy as np

__all__ = [
    'interquartile_range', 'maximum_absolute_value', 'standard_deviation', 'total_range',
]

def interquartile_range(X):
    """
    Distance between the first and the third quartile; range of the central half of the data.

    Parameters
    ----------
    X : np.array
        Dataset. Should be a two-dimensional array.

    Returns
    -------
    a: np.array
        One-dimensional array that contains the interquartile range for each feature.
    """
    quartiles = np.nanpercentile(X, [25, 75], axis=0)
    return quartiles[1, :] - quartiles[0, :]

def maximum_absolute_value(X):
    """
    Maximum distance from 0.

    Parameters
    ----------
    X : np.array
        Dataset. Should be a two-dimensional array.

    Returns
    -------
    a: np.array
        One-dimensional array that contains the maximum absolute value for each feature.
    """
    return np.nanmax(np.abs(X), axis=0)

def standard_deviation(X):
    """
    Square root of the sum of the squared distances to the mean.

    Parameters
    ----------
    X : np.array
        Dataset. Should be a two-dimensional array.

    Returns
    -------
    a: np.array
        One-dimensional array that contains the standard deviation for each feature.
    """
    return np.nanstd(X, axis=0)

def total_range(X):
    """
    Distance between the smallest and largest value.

    Parameters
    ----------
    X : np.array
        Dataset. Should be a two-dimensional array.

    Returns
    -------
    a: np.array
        One-dimensional array that contains the ranges for each feature.

    Notes
    -----
    This function is not called `range` so as not to overwrite the built-in function `range`.
    """
    return np.nanmax(X, axis=0) - np.nanmin(X, axis=0)


"""Fourier matrix."""
import numpy as np

def fourier(dim: int) -> np.ndarray:
    r"""
    Generate the Fourier transform matrix [WikDFT]_.

    Generates the `dim`-by-`dim` unitary matrix that implements the quantum
    Fourier transform.

    The Fourier matrix is defined as:

    .. math::
        W_N = \frac{1}{N}
        \begin{pmatrix}
            1 & 1 & 1 & 1 & \ldots & 1 \\
            1 & \omega & \omega^2 & \omega^3 & \ldots & \omega^{N-1} \\
            1 & \omega^2 & \omega^4 & \omega^6 & \ldots & \omega^{2(N-1)} \\
            1 & \omega^3 & \omega^6 & \omega^9 & \ldots & \omega^{3(N-1)} \\
            \vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\
            1 & \omega^{N-1} & \omega^{2(N-1)} & \omega^{3(N-1)} &
            \ldots & \omega^{3(N-1)}
        \end{pmatrix}

    Examples
    ==========

    The Fourier matrix generated from :math:`d = 3` yields the following
    matrix:

    .. math::
        W_3 = \frac{1}{3}
        \begin{pmatrix}
            1 & 1 & 1 \\
            0 & \omega & \omega^2 \\
            1 & \omega^2 & \omega^4
        \end{pmatrix}

    >>> from toqito.matrices import fourier
    >>> fourier(3)
    [[ 0.57735027+0.j ,  0.57735027+0.j ,  0.57735027+0.j ],
     [ 0.57735027+0.j , -0.28867513+0.5j, -0.28867513-0.5j],
     [ 0.57735027+0.j , -0.28867513-0.5j, -0.28867513+0.5j]]

    References
    ==========
    .. [WikDFT] Wikipedia: DFT matrix,
        https://en.wikipedia.org/wiki/DFT_matrix

    :param dim: The size of the Fourier matrix.
    :return: The Fourier matrix of dimension `dim`.
    """
    # Primitive root of unity.
    root_unity = np.exp(2 * 1j * np.pi / dim)
    entry_1 = np.arange(0, dim)[:, None]
    entry_2 = np.arange(0, dim)
    return np.power(root_unity, entry_1 * entry_2) / np.sqrt(dim)


from __future__ import annotations
import numpy as np
from numpy.linalg import inv, det, slogdet
from collections.abc import Callable

class UnivariateGaussian:
    """
    Class for univariate Gaussian Distribution Estimator
    """
    def __init__(self, biased_var: bool = False) -> UnivariateGaussian:
        """
        Estimator for univariate Gaussian mean and variance parameters

        Parameters
        ----------
        biased_var : bool, default=False
            Should fitted estimator of variance be a biased or unbiased estimator

        Attributes
        ----------
        fitted_ : bool
            Initialized as false indicating current estimator instance has not been fitted.
            To be set as True in `UnivariateGaussian.fit` function.

        mu_: float
            Estimated expectation initialized as None. To be set in `UnivariateGaussian.fit`
            function.

        var_: float
            Estimated variance initialized as None. To be set in `UnivariateGaussian.fit`
            function.
        """
        self.biased_ = biased_var
        self.fitted_, self.mu_, self.var_ = False, None, None

    def fit(self, X: np.ndarray) -> UnivariateGaussian:
        """
        Estimate Gaussian expectation and variance from given samples

        Parameters
        ----------
        X: ndarray of shape (n_samples, )
            Training data

        Returns
        -------
        self : returns an instance of self.

        Notes
        -----
        Sets `self.mu_`, `self.var_` attributes according to calculated estimation (where
        estimator is either biased or unbiased). Then sets `self.fitted_` attribute to `True`
        """
        m = X.shape[0]
        self.mu_ = np.sum(X) / m
        var_denom = np.sum((X - self.mu_)**2)
        if self.biased_:
            self.var_ = var_denom / m
        else:
            self.var_ = var_denom / (m - 1)

        self.fitted_ = True
        return self

    def pdf(self, X: np.ndarray) -> np.ndarray:
        """
        Calculate PDF of observations under Gaussian model with fitted estimators

        Parameters
        ----------
        X: ndarray of shape (n_samples, )
            Samples to calculate PDF for

        Returns
        -------
        pdfs: ndarray of shape (n_samples, )
            Calculated values of given samples for PDF function of N(mu_, var_)

        Raises
        ------
        ValueError: In case function was called prior fitting the model
        """
        if not self.fitted_:
            raise ValueError("Estimator must first be fitted before calling `pdf` function")
        normalization_factor = 1/np.sqrt(2*np.pi*self.var_)
        exponential_factor = -((X-self.mu_)**2)/(2*self.var_)
        return normalization_factor * np.exp(exponential_factor)

    @staticmethod
    def log_likelihood(mu: float, sigma: float, X: np.ndarray) -> float:
        """
        Calculate the log-likelihood of the data under a specified Gaussian model

        Parameters
        ----------
        mu : float
            Expectation of Gaussian
        sigma : float
            Variance of Gaussian
        X : ndarray of shape (n_samples, )
            Samples to calculate log-likelihood with

        Returns
        -------
        log_likelihood: float
            log-likelihood calculated
        """
        m = X.shape[0]
        return (-0.5)*(m*np.log(2*np.pi) + \
                       m*np.log(sigma) + \
                       (1/sigma)*np.sum((X-mu)**2))

class MultivariateGaussian:
    """
    Class for multivariate Gaussian Distribution Estimator
    """
    def __init__(self):
        """
        Initialize an instance of multivariate Gaussian estimator

        Attributes
        ----------
        fitted_ : bool
            Initialized as false indicating current estimator instance has not been fitted.
            To be set as True in `MultivariateGaussian.fit` function.

        mu_: ndarray of shape (n_features,)
            Estimated expectation initialized as None. To be set in `MultivariateGaussian.fit`
            function.

        cov_: ndarray of shape (n_features, n_features)
            Estimated covariance initialized as None. To be set in `MultivariateGaussian.fit`
            function.
        """
        self.mu_, self.cov_ = None, None
        self.fitted_ = False

    def fit(self, X: np.ndarray) -> MultivariateGaussian:
        """
        Estimate Gaussian expectation and covariance from given samples

        Parameters
        ----------
        X: ndarray of shape (n_samples, n_features)
            Training data

        Returns
        -------
        self : returns an instance of self

        Notes
        -----
        Sets `self.mu_`, `self.cov_` attributes according to calculated estimation.
        Then sets `self.fitted_` attribute to `True`
        """
        self.fitted_ = True
        m = X.shape[0]
        self.mu_ = np.sum(X,axis=0) / m
        centered_X = X - self.mu_.T
        self.cov_ = (centered_X.T @ centered_X) / (m - 1)
        return self

    def pdf(self, X: np.ndarray):
        """
        Calculate PDF of observations under Gaussian model with fitted estimators

        Parameters
        ----------
        X: ndarray of shape (n_samples, n_features)
            Samples to calculate PDF for

        Returns
        -------
        pdfs: ndarray of shape (n_samples, )
            Calculated values of given samples for PDF function of N(mu_, cov_)

        Raises
        ------
        ValueError: In case function was called prior fitting the model
        """
        if not self.fitted_:
            raise ValueError("Estimator must first be fitted before calling `pdf` function")
        d = self.mu_.shape[0]
        normalization_factor = 1/np.sqrt(((2*np.pi)**d)*det(self.cov_))
        centered_X = X - self.mu_.T
        Ax = np.einsum('ij,nj->ni',inv(self.cov_),centered_X)
        xAx = np.einsum('ni,ni->n', centered_X, Ax)
        exponential_factor = (-0.5)*xAx
        return normalization_factor * np.exp(exponential_factor)

    @staticmethod
    def log_likelihood(mu: np.ndarray, cov: np.ndarray, X: np.ndarray) -> float:
        """
        Calculate the log-likelihood of the data under a specified Gaussian model

        Parameters
        ----------
        mu : ndarray of shape (n_features,)
            Expectation of Gaussian
        cov : ndarray of shape (n_features, n_features)
            covariance matrix of Gaussian
        X : ndarray of shape (n_samples, n_features)
            Samples to calculate log-likelihood with

        Returns
        -------
        log_likelihood: float
            log-likelihood calculated over all input data and under given parameters of Gaussian
        """
        m,d = X.shape
        centered_X = X - mu.T
        Ax = np.einsum('ij,nj->ni',inv(cov),centered_X)
        sum_xAx = np.einsum('ni,ni->', centered_X, Ax)
        return (-0.5)*(m*d*np.log(2*np.pi) + m*slogdet(cov)[1] + np.sum(sum_xAx))


"""
  Name     : c14_10_correlated_random_numbers.py
  Book     : Python for Finance (2nd ed.)
  Publisher: Packt Publishing Ltd.
  Author   : Yuxing Yan
  Date     : 6/6/2017
  email    : yany@canisius.edu
             paulyxy@hotmail.com
"""

import scipy as sp
sp.random.seed(123)
n=1000
rho=0.3
x1=sp.random.normal(size=n)
x2=sp.random.normal(size=n)
y1=x1
y2=rho*x1+sp.sqrt(1-rho**2)*x2
print(sp.corrcoef(y1,y2))


#
#	root-secant.py
#	Finding root using secant method
#
#	Sparisoma Viridi | https://butiran.github.io/
#
#	Execute: py root-secant.js
#
#	20210103
#	1042 Start this program from root-newton-raphton.py.
# 1351 Remove unecessary semicolons.
#	20210210
#	0527 Typo node --> py.
#

# Import necessary libraries
import numpy as np

# Define a test function
def test_function(x):
	y3 = 0.01 * x * x * x
	y2 = -0.2192 * x * x
	y1 = 0.3056 * x
	y0 = 1.568
	y = y3 + y2 + y1 + y0
	return y

# Define input
f = test_function
xinit1 = 2
xinit2 = 3
eps = 1E-10
n = 0
maxstep = 40

# Define default message and parameter
xroot = "not found"
SHOW_PROGRESS = False

# Do iteration
Nstep = 0
x = []
x.append(xinit1)
x.append(xinit2)
froot = np.abs(f(x[n+1]))

while froot > eps and n < maxstep - 1:
	x.append(x[n+1] - f(x[n+1]) * (x[n+1] - x[n])  / (f(x[n+1]) - f(x[n])))

	froot = np.abs(f(x[n+2]))
	if froot < eps:
		xroot = x[n+2]

	if SHOW_PROGRESS:
		if n == 0:
			fn = f(x[n])
			print("n\tx\tf(x)")
			print(n, x[n], f(x[n]), sep="\t")
			print(n+1, x[n+1], f(x[n+1]), sep="\t")
		print(n+2, x[n+2], f(x[n+2]), sep="\t")

	n += 1

Nstep = n+2

if SHOW_PROGRESS:
	print()

# Display result
print("f(x)  0.01x^3 - 0.2192x^2 + 0.3056x + 1.568");
print("x1    ", xinit1, sep="")
print("x2    ", xinit2, sep="")
print("ε     ", eps, sep="")
print("Nstep ", Nstep, sep="")
print("xroot ", xroot, sep="")


#!/usr/bin/env python3

from datetime import date
import math
import numpy as np
import sys
from math import *

#Binomial Tree model
def tree(stock_price, strike_price, rf, volatility, div_yield, steps, c_or_p):
	#Inputs
    Dt = 1 / steps #set time to expiration equal to 1
    r_Dt = rf * Dt
    exp_r_Dt = math.exp(r_Dt)
    exp_neg_r_Dt = math.exp(-r_Dt)
    exp_div_Dt = math.exp(div_yield * Dt)
    exp_neg_div_Dt = math.exp(-div_yield * Dt)
    sig_sqrt_Dt = volatility * math.sqrt(Dt)
    exp_sig_sqrt_Dt = math.exp(sig_sqrt_Dt)

	#probability of step up & down
    u = exp_sig_sqrt_Dt
    d = 1/u
    q = (exp_r_Dt * exp_neg_div_Dt - d) / (u -d)
    p = 1 - q

	#Step by step matrix calculation with estimated price of the underlying
    sv = np.zeros((steps + 1,steps +1), dtype = np.float64)
    sv[0,0] = stock_price
    z1 = 0
    for i in range(1,steps + 1, 1):
        z1 = z1 + 1
        for n in range(z1 + 1):
            sv[n,i] = sv[0,0] * (u ** (i - n)) * (d ** n)

	#Matrix with the final payoff depending on put or call
    iv = np.zeros((steps + 1,steps +1), dtype = np.float64)
    z2 = 0
    for i in range(1,steps + 1, 1):
        find = False
        for n in range(z2 + 2):
            if c_or_p == "C":
                iv[n,i] = max(sv[n,i] - strike_price, 0)
            elif c_or_p == "P":
                iv[n,i] = max(-1 * (sv[n,i] - strike_price), 0)
            else:
                print("fravor has to be 'C' for call and 'P' for put")
                find = True
                break
        if find:
            break
        z2 = z2 + 1

    pv = np.zeros((steps + 1,steps +1), dtype = np.float64)
    pv[:, steps] = iv[:, steps]
    z3 = steps + 1
    for i in range(steps -1, -1, -1):
        z3 = z3 - 1
        for n in range(z3):
            pv[n,i] = (q * pv[n, i + 1] + p * pv[n + 1, i + 1]) * exp_neg_r_Dt
    return(pv[0,0])

#Black-Scholes model
def phi(x):
    #Cumulative distribution function for the standard normal distribution
    return (1.0 + erf(x / sqrt(2.0))) / 2.0

def black_scholes_call(stock_price, strike_price, rf, volatility, div_yield, c_or_p):
	#Black Scholes formula for call and put options
	d1 = (math.log(stock_price/strike_price) + rf - div_yield + volatility**2/2)/volatility
	d2 = d1 - volatility
	#Call price
	call_bs = stock_price * phi(d1) - exp(-rf) * strike_price * phi(d2)
	#Put price
	put_bs = exp(-rf) * strike_price * phi(-d2) - stock_price * phi(-d1)
	if c_or_p == 'C':
		return(call_bs)
	elif c_or_p == 'P':
		return(put_bs)
	else:
		print("You have to select your option to be either a call('C') or a put('P')")

if __name__ == "__main__":
	#inputs for Black Scholes model
	stock_price = float(sys.argv[1])
	strike_price = float(sys.argv[2])
	rf = float(sys.argv[3])
	volatility = float(sys.argv[4])
	div_yield = float(sys.argv[5])
	c_or_p = sys.argv[6]

	#inputs for Binomial Tree model
	steps = int(sys.argv[7])

	#calculate the difference between two methods
	diff = tree(stock_price, strike_price, rf, volatility, div_yield, steps, c_or_p) - black_scholes_call(stock_price, strike_price, rf, volatility, div_yield, c_or_p)
	print('Price of this option using Binomial Tree model is ', tree(stock_price, strike_price, rf, volatility, div_yield, steps, c_or_p))
	print('Price of this option using Black-Scholes model is ', black_scholes_call(stock_price, strike_price, rf, volatility, div_yield, c_or_p))
	print('Price difference between these two methods is', diff)


# Undergraduate Student: Arturo Burgos
# Professor: João Rodrigo Andrade
# Federal University of Uberlândia - UFU, Fluid Mechanics Laboratory - MFLab, Block 5P, Uberlândia, MG, Brazil

# Third exercise: Fibonacci sequence - by a common loop

import numpy as np
import time
from numba import jit

n = int(input("Enter the n indices: "))
Fbn=0 # Value of the first box
A = 0 # Values of the second
B = 1 # Value of the third box

##############################
# Variable iterative fibonacci  --> Better performance, why?
##############################

@jit(nopython=True)
def varloop_fibonacci(k,F1,F2,S):

    for i in range(0,k):
        F1=S
        S = F1+F2
        F2 = F1

    return S

t_initial1 = time.time()
Fbn = varloop_fibonacci(n,A,B,Fbn)

print('\n')
print("--- %s seconds ---\n" % (time.time() - t_initial1))
print("The correspond indices number is: ",Fbn)
print('\n')
Fbn=0
t_initial = time.time()  # I set here the initial time.
Fbn = varloop_fibonacci(n,A,B,Fbn)
print("--- %s seconds after compilation---\n" % (time.time() - t_initial1))
print("The correspond indices number is: ",Fbn)


import numpy as np
import sklearn
from sklearn import model_selection
import logistic_regressor as lr
from sklearn import linear_model
import scipy.io
from sklearn.model_selection import KFold

######################################################################################
#   The sigmoid function                                                             #
#     Input: z: can be a scalar, vector or a matrix                                  #
#     Output: sigz: sigmoid of scalar, vector or a matrix                            #
#     TODO: 1 line of code expected                                                  #
######################################################################################

def sigmoid (z):

    # sig = np.zeros(z.shape)
    # Your code here
    sig = 1 / (1 + np.exp(-z))
    # End your code

    return sig

######################################################################################
#   The log_features transform                                                       #
#     Input: X: a data matrix                                                        #
#     Output: a matrix with every element x replaced by  log(x+1 )                   #
#     TODO: 1 line of code expected                                                  #
######################################################################################

def log_features(X):
    #logf = np.zeros(X.shape)
    # Your code here
    logf = np.log(1 + X)

    # End your code
    return logf

######################################################################################
#   The std_features transform                                                       #
#     Input: X: a data matrix                                                        #
#     Output: a matrix with every column with zero mean, unit variance               #
######################################################################################

def std_features(X):
    mu = np.mean(X,axis=0)
    sigma = np.std(X,axis=0)
    X_norm = (X - mu) / sigma
    return X_norm, mu, sigma

######################################################################################
#   The bin_features transform                                                       #
#     Input: X: a data matrix                                                        #
#     Output: a matrix with every element x replaced by 1 if x > 0 else 0            #
#     TODO: 1 line of code expected                                                  #
######################################################################################

def bin_features(X):
    tX = np.zeros(X.shape)
    # your code here
    tX = (X > 0) * 1
    # end your code
    return tX

######################################################################################
#   The select_lambda_crossval function                                              #
#     Inputs: X: a data matrix                                                       #
#             y: a vector of labels                                                  #
#             lambda_low, lambda_high,lambda_step: range of lambdas to sweep         #
#             penalty: 'l1' or 'l2'                                                  #
#     Output: best lambda selected by crossvalidation for input parameters           #
######################################################################################

# Select the best lambda for training set (X,y) by sweeping a range of
# lambda values from lambda_low to lambda_high in steps of lambda_step
# pick sklearn's LogisticRegression with the appropriate penalty (and solver)

# about 20 lines of code expected

# For each lambda value, divide the data into 10 equal folds
# using sklearn's model_selection KFold function.
# Then, repeat i = 1:10:
#  1. Retain fold i for testing, and train logistic model on the other 9 folds
#  with that lambda
#  2. Evaluate accuracy of model on left out fold i
# Accuracy associated with that lambda is the averaged accuracy over all 10
# folds.
# Do this for each lambda in the range and pick the best one
#
def select_lambda_crossval(X,y,lambda_low,lambda_high,lambda_step,penalty):

    best_lambda = lambda_low
    # Your code here
    # Implement the algorithm above.
    n = 10
    lambda_record = {}
    for l in np.linspace(lambda_low, lambda_high, int(np.abs(lambda_high - lambda_low) / lambda_step) + 1):
        try:
            if penalty == 'l2':
                clf = linear_model.LogisticRegression(C=1.0/l, penalty='l2', solver='lbfgs', fit_intercept=True)
            elif penalty == 'l1':
                clf = linear_model.LogisticRegression(C=1.0 / l, penalty='l1', solver='liblinear', fit_intercept=True)
        except:
            raise AttributeError
        kfold = model_selection.KFold(n)
        accuracies = list()
        for train_index, val_index in kfold.split(X):
            Xtrain, Xval = X[train_index], X[val_index]
            ytrain, yval = y[train_index], y[val_index]
            clf.fit(Xtrain, ytrain)
            predy = clf.predict(Xval)
            accuracy = np.mean(predy == yval)
            accuracies.append(accuracy)
        lambda_record[l] = np.mean(accuracies)
    best_lambda = sorted(lambda_record, key=lambda x : lambda_record[x])[-1]

    # end your code

    return best_lambda

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

def load_mat(fname):
  d = scipy.io.loadmat(fname)
  Xtrain = d['Xtrain']
  ytrain = d['ytrain']
  Xtest = d['Xtest']
  ytest = d['ytest']

  return Xtrain, ytrain, Xtest, ytest

def load_spam_data():
    data = scipy.io.loadmat('spamData.mat')
    Xtrain = data['Xtrain']
    ytrain1 = data['ytrain']
    Xtest = data['Xtest']
    ytest1 = data['ytest']

    # need to flatten the ytrain and ytest
    ytrain = np.array([x[0] for x in ytrain1])
    ytest = np.array([x[0] for x in ytest1])
    return Xtrain,Xtest,ytrain,ytest


# Supplementary classes and functions for ENGSCI233 notebook performance.ipynb
# author: David Dempsey
import numpy as np
from matplotlib import pyplot as plt

def compare_scaling():
    ''' plots two different algorithm scalings
    '''
    N = np.linspace(1,1e5, 101)
    k = 0.4e4
    heapN = k*N*np.log2(N)
    insertionN = N**2

    # plot the comparison
    f,ax = plt.subplots(1,1, figsize=(8,4))
    ax.plot(N, insertionN, 'b-', label='algorithm 1')
    ax.plot(N, heapN, 'r-', label = 'algorithm 2')
    ax.legend()
    ax.set_xlabel('size of problem, $N$')
    ax.set_ylabel('execution time, $\mathcal{O}(N)$')
    plt.show()

def scaling_loglog():
    ''' plots two different algorithm scalings
    '''
    N = 2**np.arange(1,10)
    fN = N**2
    # plot the comparison
    f,(ax1,ax2,ax3) = plt.subplots(1,3, figsize=(16,4))
    ax1.plot(N, fN, 'bx',mew=1.5)
    ax2.plot(np.log10(N), np.log10(fN), 'bx',mew=1.5)
    ax3.plot(N, fN, 'bx',mew=1.5)
    for ax in [ax1,ax3]:
        ax.set_xlabel('size of problem, $N$')
        ax.set_ylabel('execution time, $\mathcal{O}(N)$')
    ax2.set_xlabel('logged size of problem, $log(N)$')
    ax2.set_ylabel('logged execution time, $log(\mathcal{O}(N))$')
    ax3.set_xscale('log')
    ax3.set_yscale('log')
    plt.show()

def parallel_analysis():
    ''' plots parallel speed up and efficiency
    '''
    Ts = np.array([6.4, 4.7, 3.9, 3.9, 3.5, 3.8, 4.9, 4.9])
    n = np.arange(1,len(Ts)+1)
    f,(ax1,ax2) = plt.subplots(1,2, figsize=(16,4))
    ax1.plot(n, Ts[0]/Ts, 'bx',mew=1.5)
    ax2.plot(n, Ts[0]/Ts/n, 'bx',mew=1.5)
    ax1.set_xlabel('cpus'); ax2.set_xlabel('cpus')
    ax1.set_ylabel('speed up'); ax2.set_ylabel('efficiency')
    plt.show()


import numpy as np
import pandas as pd

size = 15
basearray = np.linspace(0,1,size) # linear scale
basearray = basearray.astype('float')
# print(basearray)
np.random.shuffle(basearray)
# print(basearray)

index = 0
while index < len(basearray):
    if basearray[index] < 0.3:
        basearray[index] = 0.0
    else:
        basearray[index] = basearray[index] + index * 0.1
    index = index + 1
##print(basearray)

def replacezeroeswith(array, newvalue):
    array[ array == 0 ] = newvalue

test1 = basearray.copy()
replacezeroeswith(test1, np.nan)
##print(test1)

df=pd.DataFrame({'X':basearray})
replacezeroeswith(df.X, np.nan)
##print(df)

# Option 1 Now drop NaN values
df1 = pd.DataFrame({'X':basearray})
df1 = df1.dropna()
##print("df1")
##print(df1)

# Option 2 Replace with
mean = df1.X.mean()
df2 = pd.DataFrame({'X':basearray})
replacezeroeswith(df2.X, mean)
##print("df2")
##print(df2)

# Option 3 select random item from existing (Hot Deck)
hotdeck = np.random.choice(df1.X)
df3 = pd.DataFrame({'X':basearray})
replacezeroeswith(df3.X,hotdeck)
##print("df3")
##print(df3)

# Option 4 select item with given rule (Cold Deck)
colddeck = df1.X[0] # first item
df4 = pd.DataFrame({'X':basearray})
replacezeroeswith(df4.X, colddeck)
##print("df4")
##print(df4)

# Option 5 regression imputation / replace with estimator

def replace_with_estimator(given, index):
    untilme = given[0: index - 1]
    # moving average
    wsize = 5
    size = len(untilme)
    if wsize > size:
        wsize = size
    estimate = given.rolling(wsize).mean().iloc[-1]
    given[index] = estimate

df5 = pd.DataFrame({'X':basearray})
index = 0
while index < len(df5.X):
    if df5.X[index] == 0 :
        replace_with_estimator(df5.X,index)
    index = index + 1
##print("df5")
##print(df5)

# Option 6 - Stochastic regression - estimate with some random residue
# not implemented here

df_final = pd.DataFrame({'X':df.X, 'M1': df1.X, 'M2': df2.X, 'M3': df3.X, 'M4': df4.X, 'M5': df5.X})
print(df_final)

# Homework is about Option 7 - Interpolation

Numpy and Pandas Samples/Data Imputation Examples.py


#!/usr/bin/env python
# coding: utf-8

# In[41]:

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt

from scipy.stats import chi2_contingency

# https://www.kaggle.com/nicapotato/womens-ecommerce-clothing-reviews#Womens%20Clothing%20E-Commerce%20Reviews.csv

# In[42]:

e_comm_data = pd.read_csv('datasets/E-commerce.csv', index_col=0)

e_comm_data.sample(10)

# In[43]:

e_comm_data.shape

# In[44]:

e_comm_data = e_comm_data[['Recommended IND', 'Rating']]

e_comm_data.head()

# In[45]:

e_comm_data[['Rating']].hist(figsize=(10, 8))

# ### Make a dataframe which having columns `Rating` and contain sum of `frequency` of rating.
#
# https://towardsdatascience.com/running-chi-square-tests-in-python-with-die-roll-data-b9903817c51b

# In[46]:

df_for_obs = pd.crosstab(e_comm_data['Recommended IND'], e_comm_data['Rating'])

df_for_obs

# ### Returns values `Chi2-test`, `p-value`, `degree of freedom`, and `expected value`
#
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.chi2_contingency.html
#
# https://en.wikipedia.org/wiki/Contingency_table

# In[47]:

chi2, p_value, degrees_of_freedom, expected_values = chi2_contingency(df_for_obs.values)

# ### `Chi2-test`

# In[48]:

print('Chi2 stats: {}'. format(round(chi2, 3)))

# ### `p-value`

# In[49]:

print('The p-values: {}'.format(p_value))

# ### `Degree of freedom`

# In[50]:

print('The degree of freedom: {}'.format(degrees_of_freedom))

# ### `Expected` occurance of `Rating`

# In[51]:

expected_values

# In[52]:

expected_df = pd.DataFrame({
    '0': expected_values[0],
    '1': expected_values[1],
})

# In[53]:

expected_df

# In[54]:

plt.figure(figsize=(10, 8))

plt.bar(expected_df.index, expected_df['1'], label="Recommended")
plt.bar(expected_df.index, expected_df['0'], label="Not recommended")

plt.legend()

# In[55]:

ratings_recommended = e_comm_data[e_comm_data['Recommended IND'] == 1]

ratings_not_recommended = e_comm_data[e_comm_data['Recommended IND'] == 0]

# In[56]:

ratings_recommended.shape, ratings_not_recommended.shape

# In[62]:

ratings_recommended.sample(10)

# In[63]:

ratings_not_recommended.sample(10)

# In[64]:

ratings_recommended[['Rating']].hist(figsize=(10, 8))

# In[65]:

ratings_not_recommended[['Rating']].hist(figsize=(10, 8))

# In[66]:

plt.figure(figsize=(10, 8))

plt.hist(ratings_recommended['Rating'], label="Recommended")
plt.hist(ratings_not_recommended['Rating'], label="Not recommended")

plt.legend()

# In[ ]:


import numpy as np

def entropy(distribution, unit=2):
    """Finds the entropy of a distribution.
        Its default unit is 'bit'.

    Args:
        distribution ([FrequencyTable]): A FrequencyTable or any of
                                         its sub-classes
        unit (int, optional): Unit of the entropy. Defaults to 2 (bits).

    Returns:
        [float]: Entropy of the distribution
    """
    frequencies = distribution.frequencies(normalised=True)
    # check to see if it is a deterministic case (all but one are zero)
    zeros_size = frequencies[frequencies == 0].size
    if zeros_size + 1 == frequencies.size:
        return 0
    else:
        return np.sum(-frequencies * np.log2(frequencies) / np.log2(unit))


import numpy as np
import math  as m

def getAlpha(k, N):
    if k == 0:
        a = N
    else:
        a = N/2
    return a

# dct1D
def dct1(v):
    N = len(v)
    c = np.zeros(N)
    for k in range(0, N):
        ck = 0
        for i in range(0, N):
            ck = ck + m.cos(m.pi * k * (2*(i+1) - 1) / (2*N)) * v[i]
        ck = ck / m.sqrt(getAlpha(k, N))
        c[k] = ck
    return c

# dct2D with 2 x dct1D
def dct2V1(Mat):
    N,M = np.shape(Mat)

    C = np.zeros((N, M))

    for h in range(0, N):
        v = Mat[h,:]
        C[h] = dct1(v)

    Mat = np.copy(C)

    for h in range(0, M):
        v = Mat[:, h]
        C[:,h] = dct1(v)
    return C

# dct2D
def dct2V2(Mat):
    N,M = np.shape(Mat)

    C = np.zeros((N, M))

    for k in range(0, N):
        for l in range(0, M):
            ckl = 0
            for i in range(0, N):
                for j in range(0, M):
                    ckl = ckl + m.cos(m.pi * k * (2*(i+1) - 1) / (2 * N)) * m.cos(m.pi * l * (2*(j+1) - 1) / (2 * M)) * Mat[i, j]
            C[k, l] = ckl / m.sqrt(getAlpha(k,N) * getAlpha(l,M));
    return C


from sympy import *
x, y, z = symbols('x y z')
init_printing(use_unicode=True)

#print simplify(sin(x)**2 + cos(x)**2)

#print simplify((x**3 + x**2 - x - 1)/(x**2 + 2*x + 1))

#print simplify(gamma(x)/gamma(x - 2))

print simplify((x + 1)**2)
print expand((x + 1)**2)


"""TensorFlow-related utilities."""
from __future__ import absolute_import
from __future__ import division
from __future__ import generator_stop
from __future__ import print_function

import numpy as np
import tensorflow as tf

def tf_log(tensor, base=np.exp(1.)):
    r"""TensorFlow logarithmic operation.

    Parameters
    ----------
    tensor : tensorflow.Tensor
        Tensor for logarithmic operation.
    base : int or float, default np.exp(1.)
        Base of logarithmic operation.

    Returns
    -------
    new_tensor : tensorflow.Tensor
        Tensor after logarithmic operation.

    Notes
    -----
    Logarithmic identity
    .. math:: \log_a{b}=\frac{\log_c{b}}{\log_c{a}}

    References
    ----------
    .. [1] https://github.com/tensorflow/tensorflow/issues/1666#issuecomment-202453841
    .. [2] https://en.wikipedia.org/wiki/List_of_logarithmic_identities
    """
    numerator = tf.math.log(tensor)
    denominator = tf.math.log(tf.constant(base, dtype=numerator.dtype))
    new_tensor = numerator / denominator
    return new_tensor


import numpy as np

def cov(arr : np.ndarray):
    """Compute the sample covariance matrix for
    a matrix arr, assumed to be given in (samples x features)
    form for data fitting applications.

    Parameters
    ----------
    arr : np.ndarray
        matrix in (samples x features) form
    """
    n, _ = arr.shape
    return arr.T@arr / (n - 1)

def center(arr: np.ndarray):
    """Center a data matrix, assumedly given in (samples x features)
    form for data fitting applications.

    Parameters
    ----------
    arr : np.ndarray
        matrix in (samples x features) form
    """
    return arr - np.mean(arr, axis=0)


import numpy as np

from utils import _array_almost_equal, _correct_format

class Polynomial_fit:

    def polynomial_fit(self, seq):
        """ Un = a * Un-1 + b * n + c
        """
        B = np.array(seq[1:4])
        A = np.array([[seq[k], k + 1, 1] for k in range(3)])
        return np.around(np.linalg.solve(A,B), decimals=2)

    def recursion(self, u, n, coef):
        a, b, c = coef
        return a * u + b * n + c

    def __call__(self, seq):
        try:
            coef = self.polynomial_fit(seq)
            Attempt = seq[:4]
            for n in range(4, len(seq)):
                Attempt = np.append(Attempt, self.recursion(Attempt[-1], n, coef))
            if _array_almost_equal(Attempt, seq):
                print('Polynomial fit succeeded.\nUn = {} * Un-1 + {} * n + {}.\nThe following term is {}.\n'.format(_correct_format(coef[0]), _correct_format(coef[1]), _correct_format(coef[2]), _correct_format(self.recursion(seq[-1], (n+1), coef))))
            else:
                print("No polynomial fit\n")
        except:
            print("No polynomial fit\n")


"""
Created by Joseph Edradan
Github: https://github.com/josephedradan

Date created: 2/15/2021

Purpose:

Details:

Description:

Notes:

IMPORTANT NOTES:

Explanation:

Reference:
    Minimum Edit Distance Algorithm in Python in 2020 (EXPLAINED)
        Notes:
            Using Rylan Fowers' minimum edit distance algo

        Reference:
            https://www.youtube.com/watch?v=AY2DZ4a9gyk
"""

import numpy as np
import pandas as pd

def min_edit_distance_fowers(source, target):
    list_source_char = [c for c in source]
    list_target_char = [c for c in target]

    # Make np_array
    np_array = np.zeros((len(source), len(target)))

    # Target is 0th row
    np_array[0] = [c for c in range(len(target))]

    # Source is the 0th col ([index_row_all, index_column])
    np_array[:, 0] = [c for c in range(len(source))]

    """
    Solve the [1,1] location if necessary

    If the char at index 1 of both target and source are different the amount of edits needed to achieve the target
    string is the min of the top and left indices values around the [1,1]

    """

    try:
        # if target[1] != source[1]:
        #     np_array[1, 1] = 2

        # For item index in row, start on index 1 (Target is the row)
        for i in range(1, len(target)):

            # for item index in col, start on index 1 (Source is the column)
            for j in range(1, len(source)):

                # If the respective chars from i and j for the source and target are NOT the same
                if target[i] != source[j]:

                    """
                    Change the value at the given position given i and j

                    Note that i and j are switched

                    """
                    np_array[j, i] = min(np_array[j - 1, i], np_array[j, i - 1]) + 1

                # If the respective chars from i and j for the source and target are the same
                else:
                    np_array[j, i] = np_array[j - 1, i - 1]

    except Exception as e:
        print(e)
        print("S:{:<20} T:{:<20} j{:<5} i:{:<5} ".format(source, target, j, i))

    # Make pandas DF of the np array
    data_frame = pd.DataFrame(np_array, columns=list_target_char, index=list_source_char)

    return np_array, data_frame, np_array[-1, -1]

if __name__ == '__main__':
    print(min_edit_distance_fowers("joseph", "edradan")[0])
    print(min_edit_distance_fowers("joseph", "edradan")[1])
    print(min_edit_distance_fowers("joseph", "edradan")[2])
    print()

    print(min_edit_distance_fowers("#joseph", "#joe")[0])
    print(min_edit_distance_fowers("#joseph", "#joe")[1])
    print(min_edit_distance_fowers("#joseph", "#joe")[2])
    print()

    print(min_edit_distance_fowers("$BCDE", "#DE")[0])
    print(min_edit_distance_fowers("$BCDE", "#DE")[1])
    print(min_edit_distance_fowers("$BCDE", "#DE")[2])
    print()


from numpy import *
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib import rc
from numpy.linalg import eigh
from numpy.linalg import norm

# Load the "gatlin" image data
X = loadtxt('gatlin.csv', delimiter=',')

#================= ADD YOUR CODE HERE ====================================
# Perform SVD decomposition
## TODO: Perform SVD on the X matrix
# Instructions: Perform SVD decomposition of matrix X. Save the
#               three factors in variables U, S and V
#

w, U = eigh(dot(X, transpose(X)))
index_w = max(argsort(w)) - argsort(w)
w = w[index_w]
U = U[:, index_w]

w2, V = eigh(dot(transpose(X),X))
index_w2 = max(argsort(w2)) - argsort(w2)
w2 = w2[index_w2]
V = V[:, index_w2]

Sdiag = diag(sqrt(absolute(w)))
S = zeros(X.shape)
min_size = min(X.shape)
S[:min_size,:min_size] = Sdiag

#=========================================================================

# Plot the original image
plt.figure(1)
plt.imshow(X,cmap = cm.Greys_r)
plt.title('Original image (rank 480)')
plt.axis('off')
plt.draw()

#================= ADD YOUR CODE HERE ====================================
# Matrix reconstruction using the top k = [10, 20, 50, 100, 200] singular values
## TODO: Create four matrices X10, X20, X50, X100, X200 for each low rank approximation
## using the top k = [10, 20, 50, 100, 200] singlular values
#

Ks = [10, 20, 50, 100, 200]
Xs = []

for k in Ks:
	Sk = S[:k, :k]
	Uk = U[:, :k]
	Vk = V[:, :k]
	Xs.append(dot(dot(Uk,Sk),transpose(Vk)))

#=========================================================================

#================= ADD YOUR CODE HERE ====================================
# Error of approximation
## TODO: Compute and print the error of each low rank approximation of the matrix
# The Frobenius error can be computed as |X - X_k| / |X|
#

error = []
for x in Xs:
	error.append((norm(X-x)/norm(X)))

plt.figure(3)
plt.plot(Ks, error)
plt.show()

#=========================================================================

Xgen = (x for x in Xs)

# Plot the optimal rank-k approximation for various values of k)
# Create a figure with 6 subfigures
plt.figure(2)

# Rank 10 approximation
plt.subplot(321)
plt.imshow(Xgen.next(),cmap = cm.Greys_r)
plt.title('Best rank' + str(5) + ' approximation')
plt.axis('off')

# Rank 20 approximation
plt.subplot(322)
plt.imshow(Xgen.next(),cmap = cm.Greys_r)
plt.title('Best rank' + str(20) + ' approximation')
plt.axis('off')

# Rank 50 approximation
plt.subplot(323)
plt.imshow(Xgen.next(),cmap = cm.Greys_r)
plt.title('Best rank' + str(50) + ' approximation')
plt.axis('off')

# Rank 100 approximation
plt.subplot(324)
plt.imshow(Xgen.next(),cmap = cm.Greys_r)
plt.title('Best rank' + str(100) + ' approximation')
plt.axis('off')

# Rank 200 approximation
plt.subplot(325)
plt.imshow(Xgen.next(),cmap = cm.Greys_r)
plt.title('Best rank' + str(200) + ' approximation')
plt.axis('off')

# Original
plt.subplot(326)
plt.imshow(X,cmap = cm.Greys_r)
plt.title('Original image (Rank 480)')
plt.axis('off')

plt.draw()

#================= ADD YOUR CODE HERE ====================================
# Plot the singular values of the original matrix
## TODO: Plot the singular values of X versus their rank k

#=========================================================================

plt.show()


import numpy as np
import numpy.random as rd
import scipy.stats as st
import matplotlib.pyplot as plt
import pickle as pk
import sys

#Definir les funcions per a fer test
def f_norm(x):
    return st.norm.pdf(x,0,1)

def f_skew(x):
    return st.skewnorm.pdf(x,7,loc=-1.32,scale=1.65)

def f_bimodal_asym(x):
    std1 = 0.41
    std2 = 0.71
    sample = 0.4*st.norm.pdf(x,-0.82-0.16,std1)+0.6*st.norm.pdf(x,0.82-0.16,std2)
    return sample

def f_bimodal_sym(x):
    std1 = 0.5
    std2 = 0.5
    sample = 0.5*st.norm.pdf(x,-0.9,std1)+0.5*st.norm.pdf(x,0.9,std2)
    return sample

def f_trimodal_asym(x):
    std1 = 0.65
    std2 = 0.35
    std3 = 0.35
    mu1 = -1.7
    mu2 = 0
    mu3 = 1.3
    sample = 0.2*st.norm.pdf(x,mu1+0.08,std1)+0.6*st.norm.pdf(x,mu2+0.08,std2)+0.2*st.norm.pdf(x,mu3+0.08,std3)
    return sample

def f_trimodal_sym(x):
    std1 = 0.65
    std2 = 0.15
    std3 = std1
    mu1 = -1.3
    mu2 = 0
    mu3 = -mu1
    sample = 0.25*st.norm.pdf(x,mu1,std1)+0.5*st.norm.pdf(x,mu2,std2)+0.25*st.norm.pdf(x,mu3,std3)
    return sample

def f_student(x):
    return st.t.pdf(x,3,scale=0.585)

def f_laplace(x):
    return st.laplace.pdf(x,loc=0,scale=0.72)

def f_laplace_sharp(x):
    std1 = 0.2
    std2 = 1
    sample = 0.5*st.laplace.pdf(x,0,std1)+0.5*st.laplace.pdf(x,0,std2)
    return sample

def f_test1(x):
    std1 = 0.5
    std2 = 0.5
    sample = 0.5*st.norm.pdf(x,-0.9,std1)+0.5*st.norm.pdf(x,0.9,std2)
    return sample

def f_test2(x):
    std1 = 0.6
    std2 = 0.6
    sample = 0.8*st.norm.pdf(x,-1.05+0.62,std1)+ 0.2*st.norm.pdf(x,1.05+0.62,std2)
    return sample


import numpy as np

# Q3
f = np.matrix([[25,50,1,4],[255,52,2,5],[255,100,0,3],[255,100,3,120]])
w1 = np.matrix([[1,1,1],[1,-8,1],[1,1,1]])
w2 = np.matrix([[0,1/10,0],[1/10,6/10,1/10],[0,1/10,0]])

def conv_point(f, w, x, y):
  n,m = w.shape
  a = int((n - 1) / 2)
  b = int((m - 1) / 2)
  sub_f = f[x-a : x+a+1, y-b : y+b+1]
  w = np.flip(np.flip(w, 0), 1)
  value = np.sum(np.multiply(sub_f, w))
  return int(value)

print('w1 of g(1, 1) =', conv_point(f, w1, 1, 1))
print('w1 of g(2, 2) =', conv_point(f, w1, 2, 2))
print('w2 of g(1, 2) =', conv_point(f, w2, 1, 2))
print()

# Q4
wm = np.matrix([[1,1,1],[1,1,1],[1,1,1]])

def conv_point_median(f, w, x, y):
  n,m = w.shape
  a = int((n - 1) / 2)
  b = int((m - 1) / 2)
  sub_f = f[x-a : x+a+1, y-b : y+b+1]
  sub_f = np.delete(sub_f, [1,1])
  r = np.sort(np.asarray(sub_f).reshape(-1))
  return int(np.median(r))

def conv_point_max(f, w, x, y):
  n,m = w.shape
  a = int((n - 1) / 2)
  b = int((m - 1) / 2)
  sub_f = f[x-a : x+a+1, y-b : y+b+1]
  return int(np.max(sub_f))

def conv_point_midpoint(f, w, x, y):
  n,m = w.shape
  a = int((n - 1) / 2)
  b = int((m - 1) / 2)
  sub_f = f[x-a : x+a+1, y-b : y+b+1]
  max = np.max(sub_f)
  min = np.min(sub_f)
  return int((max + min) / 2)

print('median of g(1, 2) =', conv_point_median(f, wm, 1, 2))
print('max of g(2, 2) =', conv_point_max(f, wm, 2, 2))
print('midpoint of g(2, 1) =', conv_point_midpoint(f, wm, 2, 1))


import math
from numba import jit, prange
import time
import numpy as np

@jit('i8(i8,i8)', nopython=True)
def gcd(a, b):
    """
    Reference:
    https://qiita.com/wrist/items/889696a507fbc8b392e4
    http://swdrsker.hatenablog.com/entry/2017/12/20/235201
    https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.remainder.html
    """
    while b != 0:
        #a, b = b, a % b
        a, b = b, np.remainder(a, b)
    return a

@jit('f8(i8)', nopython=True)
def calc_pi_by_gcd(N):
    s = 0
    for a in range(1, N+1):
        for b in range(1, N+1):
            if gcd(a, b) == 1:
                s += 1
    pi = math.sqrt(6*N**2/s)
    return pi

@jit('f8(i8)', nopython=True, parallel=True)
def calc_pi_by_gcd_parallel(N):
    s = 0
    for a in prange(1, N+1):
        for b in range(1, N+1):
            if gcd(a, b) == 1:
                s += 1
    pi = math.sqrt(6*N**2/s)
    return pi

def main():
    start = time.time()
    pi = calc_pi_by_gcd(10000)
    end = time.time()
    print(pi)
    print("Elapsed time=", end-start)

    start = time.time()
    pi = calc_pi_by_gcd_parallel(10000)
    end = time.time()
    print(pi)
    print("Elapsed time=", end-start)

if __name__ == '__main__':
    main()


import numpy as np
import innerproduct

def l2distance(X,Z=None):

    """
    function D=l2distance(X,Z)

    Computes the Euclidean distance matrix.
    Syntax:
    D=l2distance(X,Z)
    Input:
    X: nxd data matrix with n vectors (rows) of dimensionality d
    Z: mxd data matrix with m vectors (rows) of dimensionality d

    Output:
    Matrix D of size nxm
    D(i,j) is the Euclidean distance of X(i,:) and Z(j,:)

    call with only one input:
    l2distance(X)=l2distance(X,X)

    """

    if Z is None:
        Z = X

    n, d = X.shape
    m = Z.shape[0]

    G = innerproduct(X, Z)
    S = np.broadcast_to(innerproduct(X).diagonal().reshape(n, 1), (n,m))
    R = np.broadcast_to(innerproduct(Z).diagonal().reshape(m, 1).T, (n,m))

    D = np.sqrt(S - (2 * G) + R)

    assert(D.shape == (n, m))

    return D


import numpy as np

def sphere(x_positions):
    return np.array([x ** 2 for x in x_positions]).sum()

def f2(x_positions):
    return ((x_positions - np.arange(len(x_positions)))**2).sum()

def rosenbrock(x_positions):
    return (100 * (x_positions[1::] - x_positions[:-1] ** 2)**2 + (x_positions[:-1] - 1)**2).sum()

def rastrigin(x_positions):
    return (x_positions ** 2 - 10 * np.cos(2*np.pi*x_positions) + 10).sum()

def griewank(x_positions):
    return ((x_positions ** 2).sum()) / 4000 - np.prod(np.cos(x_positions / np.sqrt(np.arange(1, len(x_positions)+1)))) + 1

def ackley(x_positions):
    result = -20 * np.exp(-0.2 * np.sqrt((x_positions ** 2).sum()) / len(x_positions)) - \
             np.exp((np.cos(2 * np.pi * x_positions)).sum() / len(x_positions)) + 20 + np.e
    return result

def easom(x_positions):
    return -np.cos(x_positions[0]) * np.cos(x_positions[1]) * np.exp(-((x_positions[0] - np.pi)**2) - ((x_positions[1] - np.pi)**2))

def brown(x_positions):
    return (((x_positions[:-1] ** 2) ** (x_positions[1::] ** 2 + 1)) + ((x_positions[1::] ** 2) ** (x_positions[:-1] ** 2 + 1))).sum()

def schwefel(x_positions):
    return ((np.absolute(x_positions))**2).sum() + np.prod(np.absolute(x_positions))

def zakharov(x_positions):
    return -np.sum(x_positions) + (x_positions * np.arange(len(x_positions)) / 2).sum() ** 2 + (x_positions * np.arange(len(x_positions)) / 2).sum() ** 4

def schaffersf6(x_positions):
    return 0.5 + ((np.sin(np.sqrt(x_positions[0] ** 2 + x_positions[1] ** 2))) ** 2 - 0.5) / ((1 + 0.001 * (x_positions[0] ** 2 + x_positions[1] ** 2)) ** 2)

def leeyao_2004(x):
    result = np.pi / len(x) * (10 * ((np.sin(np.pi * x[0])) ** 2)
                               + (((x[:-1] - 1)**2) * (1 + 10 * ((np.sin(np.pi * x[1::]))**2))).sum()
                               + (x - 1)**2) + _leeyao_u(x)
    print(result)
    return result

def _leeyao_u(x_positions):
    a, k, m = 10, 100, 4
    result = []
    for z in x_positions:
        if z > a:
            result.append(k * ((z - a) ** m))
        elif -a <= z <= a:
            result.append(0)
        elif z < -a:
            result.append(k * ((-z-a) ** m))
    return np.array(result).sum()


import numpy as np

class Activate:
    @staticmethod
    def sigmoid(x):
        return 1/(1 + np.exp(-x))

    @staticmethod
    def dsigmoid(x):
        s = Activate.sigmoid(x)
        return s*(1-s)

    @staticmethod
    def tanh(x):
        return 2/(1 + np.exp(-2*x)) - 1

    @staticmethod
    def dtanh(x):
        return 1 - Activate.tanh(x)**2


#!/usr/bin/env python3

# FILE CONTENTS: special functions used in other files

import numpy as np

import scipy
from scipy import linalg

from sympy.functions.combinatorial.numbers import stirling as sympy_stirling

# factorial and its logarithm
def factorial(nn, vals = {}):
    if vals.get(nn) == None:
        vals[nn] = scipy.special.factorial(nn, exact = (type(nn) == int))
    return vals[nn]
def ln_factorial(nn, vals = {}):
    if vals.get(nn) == None:
        vals[nn] = scipy.special.gammaln(nn+1)
    return vals[nn]

# falling factorial and its logarithm
def poch(nn, kk, vals = {}):
    if vals.get((nn,kk)) == None:
        vals[nn,kk] = np.prod([ nn-cc for cc in range(kk) ], dtype = int)
    return vals[nn,kk]
def ln_poch(nn, kk, vals = {}):
    if vals.get((nn,kk)) == None:
        vals[nn,kk] = np.sum([ np.log(nn-cc) for cc in range(kk) ])
    return vals[nn,kk]

# binomial coefficient and its logarithm
def binom(nn, kk, vals = {}):
    if vals.get((nn,kk)) == None:
        integer_inputs = ( type(nn) is int ) and ( type(kk) is int )
        vals[nn,kk] = scipy.special.comb(nn, kk, exact = integer_inputs)
    return vals[nn,kk]

# unsigned stirling number of the first kind
def stirling(nn, kk, vals = {}):
    if vals.get((nn,kk)) == None:
        vals[nn,kk] = int(sympy_stirling(nn, kk, kind = 1, signed = False))
    return vals[nn,kk]

# coefficient for computing a product of spin operators
def zeta(mm, nn, pp, qq, vals = {}):
    if vals.get((mm,nn,pp,qq)) == None:
        val = (-1)**pp * 2**qq * np.sum([ stirling(pp,ss) * binom(ss,qq)
                                          * (mm+nn-2*pp)**(ss-qq)
                                          for ss in range(qq,pp+1) ], dtype = int)
        vals[mm,nn,pp,qq] = val
        vals[nn,mm,pp,qq] = val
    return vals[mm,nn,pp,qq]

# return vector in (z,x,y) format along an axis specified by text
def axis_str(text):
    sign, axis = text
    axis = axis.lower()
    assert(sign in [ "+", "-" ])
    assert(axis in [ "z", "x", "y" ])
    if axis == "z": vec = np.array([ 1, 0, 0 ])
    if axis == "x": vec = np.array([ 0, 1, 0 ])
    if axis == "y": vec = np.array([ 0, 0, 1 ])
    if sign == "-": vec = -vec
    return vec

# get polar and azimulthal angles of a vector (v_z, v_x, v_y)
def vec_theta_phi(vec):
    return np.array([ np.arccos(vec[0]/scipy.linalg.norm(vec)),
                      np.arctan2(vec[2],vec[1]) ])

# trig functions that check for "special" values
def my_cos(phi):
    if phi == 0 or abs(phi) == 2*np.pi: return 1
    if abs(phi) in [ np.pi/2, 3*np.pi/2 ]: return 0
    if abs(phi) == np.pi: return -1
    return np.cos(phi)
def my_sin(phi):
    if phi == 0 or abs(phi) in [ np.pi, 2*np.pi ]: return 0
    if abs(phi) == np.pi/2: return np.sign(phi)
    if abs(phi) == 3*np.pi/2: return -np.sign(phi)
    return np.sin(phi)
def my_expi(phi):
    return my_cos(phi) + 1j*my_sin(phi)

import numpy,import scipy,from scipy,from sympy


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

# Diferenças finitas:

# Exemplo:
def sen(x):
    return np.sin(x)

'Problema calcular o valor de Df para x in [0, pi] aproximar. '

def d_sen(x, n):
    h = np.pi / n
    return (sen(x + h) - sen(x)) / h

# -----------------------------------------------------------------------
# Método de Euler:

# Solução para o problema y' = y, com y'(t) = x.

# Condições de valor inicial:
# Ponto incial:
to = 0
# Valor incial:
yo = 1

b = 10
n = 1000

h = int(abs(b - to)) / n

x = np.linspace(to, b, n + 1)

F = np.zeros(n + 1)
F[0] = yo

for i in range(1, n + 1):
    F[i] = (h + 1) * F[i - 1]
# Plot solução real:

plt.plot(x, np.exp(x))
# Plot solução aprox.
plt.plot(x, F)

plt.show()

# ---------------------------------------------------------------------------
# Método de Monte Carlo.

# Pontos sorteados:
m = 10000
# Verificação dos pontos

Circulo = 0.0
to = time.time()
for k in range(m):
    x = np.random.rand() * 2
    y = np.random.rand() * 2
    if (x - 1) ** 2 + (y - 1) ** 2 <= 1:
        Circulo += 1
t = time.time() - to
pi = 4 * (Circulo / m)
Erro = abs(np.pi - pi)
# print('Valor aprox. : {}, Valor de Erro: {} e tempo de execução: {}'.format(pi, Erro, t))

def f(x, y):
    return x ** 2 + y ** 2


import numpy as np
import sys

from collections import deque

class PacLinearRegression():
    """
    A class used to fit a linear regression to a dataset, given features X and
    label y provided that both are in the form of numpy arrays.

    ...

    Attributes
    ----------
    learning_rate : float
        learning rate of the linear regression for gradient descent
    cost_function : str
        type of cost function to be used (mae or mse)
    max_iter : int
        number of gradient descent iteration (10x higher for mae)
    X : array of float/int
        the feature array of the dataset
    y : array of float/int
        the label array of the dataset
    theta0 : arrray of float
        slope parameter(s) of linear regression
    theta1 : float
        intercept/bias parameter of linear regression
    m : int
        number of data points
    cost_hist: list of float
        the historical cost function values
    coeff_: list of float
        the list representation of theta0 and theta1, respectively

    Methods
    -------
    fit(X, y):
        Fit a linear regression to a data by calling gradientDescent method.
    computeCostFunction(y_pred):
        Return cost value per specified cost function.
    gradientCalculation(y_pred):
        Calculate gradients for theta0 and theta1 provided the type of cost
        function.
    gradientDescent():
        Create a loop of gradient descent method, appending cost_hist per iter.
    predict(X):
        Predict the label given feature X.
    score(y_val, y_pred):
        Return the R-squared metric of the model.
    """

    def __init__(self, max_iter=1e4, learning_rate=1e-4,
                cost_function='mse', early_stop=False):
        """
        Constructs necessary attributes for the PacLinearRegression object.
        Attributes are introduced within fit method for a more concise
        structure.

        Parameters
        ----------
            learning_rate : float
                learning rate of the linear regression for gradient descent
            cost_function : str
                type of cost function to be used (mae or mse)
            max_iter : int
                number of gradient descent iteration (10x higher for mae)
        """

        self.learning_rate = learning_rate
        self.cost_function = cost_function
        if cost_function == 'mae':
            self.max_iter = int(max_iter * 10)
        else:
            self.max_iter = int(max_iter)
        self.early_stop = early_stop

    def fit(self, X, y):
        """
        Fit a linear regression to a data by calling gradientDescent method.

        Parameters
        ----------
            X : array of float/int
                the feature array of the dataset
            y : array of float/int
                the label array of the dataset
            theta0 : arrray of float
                slope parameter(s) of linear regression
            theta1 : float
                intercept/bias parameter of linear regression
            m : int
                number of data points
            cost_hist: list of float
                the historical cost function values
            coeff_: list of float
                the list representation of theta0 and theta1, respectively

        Returns
        -------
            self : fitted PacLinearRegression class
        """

        try:
            self.X = X.reshape(len(X), X.shape[1])
            self.theta0 = np.zeros(X.shape[1]).reshape(X.shape[1], -1)
        except:
            self.X = X.reshape(len(X), 1)
            self.theta0 = 0
        self.y = y.reshape(len(y), 1)
        self.theta1 = 0
        self.m = len(X)
        self.cost_hist = self.gradientDescent()
        self.coeff_ = [i[0] for i in self.theta0] + [self.theta1]
        return self

    def computeCostFunction(self, y_pred):
        """Return cost value per specified cost function."""
        if self.cost_function == 'mse':
            return (1/self.m) * sum((self.y - y_pred)**2)
        elif self.cost_function == 'mae':
            return (1/self.m) * sum(abs((self.y - y_pred)))
        else:
            print('Error: cost_function is not valid.')
            sys.exit()

    def gradientCalculation(self, y_pred):
        """
        Calculate gradients for theta0 and theta1 provided the type of cost
        function.

        Parameters
        ----------
            y_pred : array of float/int
                the predicted label of current iteration.

        Returns
        -------
            None
        """

        if self.cost_function == 'mse':
            dtheta0 = (-1/self.m) * self.X.T.dot(self.y - y_pred)
            dtheta1 = (-1/self.m) * np.sum(self.y - y_pred)
        elif self.cost_function == 'mae':
            y_adj = self.y - y_pred
            y_adj[y_adj==0] = 0
            y_adj[y_adj<0] = -1
            y_adj[y_adj>0] = 1
            dtheta0 = (-1/self.m) * np.sum(y_adj)
            dtheta1 = (-1/self.m) * np.sum(y_adj)
        self.theta0 -= self.learning_rate * dtheta0
        self.theta1 -= self.learning_rate * dtheta1

    def gradientDescent(self):
        """
        Create a loop of gradient descent method, appending cost_hist per iter.
        An early stopping criterion is also implemented using relative error of
        average cost function per 100 appended values. The value set is 0.005%.

        Parameters
        ----------
            None

        Returns
        -------
            cost_hist: list of float
                the historical cost function values
        """

        cost_hist, cost_threshold = [], []
        cost_mean = deque(maxlen=100)
        threshold = 100
        for i in range(self.max_iter):
            y_pred = self.predict(self.X)
            cost_hist.append(self.computeCostFunction(y_pred))
            cost_mean.append(self.computeCostFunction(y_pred))
            if (i+1 >= threshold) and self.early_stop:
                cost_threshold.append(np.mean(cost_mean))
                try:
                    cut_off = abs((cost_threshold[-1] - cost_threshold[-2]) \
                                * 100 / cost_threshold[-2])
                    if cut_off < 0.001:
                        self.max_iter = len(cost_hist)
                        return cost_hist
                except:
                    continue
            self.gradientCalculation(y_pred)
        return cost_hist

    def predict(self, X):
        """Predict the label given feature X."""
        return X.dot(self.theta0) + self.theta1

    def score(self, y_val, y_pred):
        """Return the R-squared metric of the model."""
        y_pred = [i[0] for i in y_pred]
        y_bar = np.mean(y_val)
        denom = np.sum((y_bar - y_val)**2)
        numer = (denom - np.sum((y_pred - y_val)**2))
        R_squared = numer / denom
        return R_squared


def golden_section(f, a, b, tol=1e-5, **kwargs):
    """
    Golden section search.

    Stolen from https://en.wikipedia.org/wiki/Golden-section_search

    Given a function f with a single local minimum in
    the interval [a,b], gss returns a subset interval
    [c,d] that contains the minimum with d-c <= tol.

    example:
    >>> f = lambda x: (x-2)**2
    >>> a = 1
    >>> b = 5
    >>> tol = 1e-5
    >>> (c,d) = golden_section(f, a, b, tol)
    >>> print (c,d)
    (1.9999959837979107, 2.0000050911830893)
    """
    import numpy as np

    # 1/phi
    invphi = (np.sqrt(5) - 1) / 2
    # 1/phi^2
    invphi2 = (3 - np.sqrt(5)) / 2

    (a, b) = (min(a, b), max(a, b))
    h = b - a
    if h <= tol:
        return (a, b)

    # required steps to achieve tolerance
    n = int(np.ceil(np.log(tol / h) / np.log(invphi)))

    c = a + invphi2 * h
    d = a + invphi * h
    yc = f(c, **kwargs)
    yd = f(d, **kwargs)

    for k in range(n - 1):
        if yc < yd:
            b = d
            d = c
            yd = yc
            h = invphi * h
            c = a + invphi2 * h
            yc = f(c, **kwargs)
        else:
            a = c
            c = d
            yc = yd
            h = invphi * h
            d = a + invphi * h
            yd = f(d, **kwargs)

    if yc < yd:
        return (a, d)
    else:
        return (c, b)


import math as mt
def velocity(t,g=9.8,m=78.5,c=12.5):
    return (g*m*(1-mt.exp(-(c/m)*t)))/c
ti=[]
t0=0 # Waktu Awal
t1=12 # Waktu Akhir
n=12000
h=(t1-t0)/n
fa=velocity(t0)
fn=velocity(t1)
## pengisian matriks
while t0<t1+h:
    ti.append(t0)
    t0=t0+h
print('nilai t=',ti)
panjang=len(ti)
####
velo=[]
for i in range (0, panjang):
    v=velocity(ti[i])
    velo.append(v)
print('Nilai hasil fungsi =',velo)
###
length=len(velo)
sigma=0
for i in range(1,length-1):
    sigma=sigma+velo[i]
print("sigma =",sigma)
## METODE TRAPEZOID
hasil=(fa+2*sigma+fn)*h/2
print("Hasil Trapezoid =", hasil)
####
sigmaGanjil=0
sigmaGenap=0
#METODE SIMPSON
for i in range(1,length-1):
    if i%2!=0 :
        sigmaGanjil=sigmaGanjil+velo[i]
    else:
        sigmaGenap=sigmaGenap+velo[i]
print("hasil sigma ganjil = ",sigmaGanjil,", hasil sigma genap =",sigmaGenap)
simpson=(fa+4*sigmaGanjil+2*sigmaGenap+fn)*h/3
print("Nilai Hasil Simpson =",simpson)

from sympy import *
t=Symbol('t')
g=9.8
m=78.5
c=12.5
fd=(g*m*(1-exp(-(c/m)*t)))/c
integral=fd.integrate(t)
print("Hasil Integral=",integral)

from scipy import integrate
hasilIntegral=integrate.quad(velocity,0,12)
print("Hasil Integral Eksak",hasilIntegral)

er_simson=abs(simpson-hasilIntegral[0])
er_trape=abs(hasil-hasilIntegral[0])
print("Hasil Eror Sympson = ", er_simson)
print("Hasil Eror Trapezoid = ", er_trape)

Chapter 9/Tugas Nomor 1 Integrasi Numerik.py


__author__ = "Nadimozzaman Pappo"
__github__ = "http://github.com/mnpappo"

"""
This scripts simulates(by 2d ploting) various activation functions used in ANN.
"""

import theano
import theano.tensor as T
import matplotlib.pyplot as plt
import numpy as np

# sigmoid/logistic function
def sigmoid(a):
    x = T.dmatrix('x')
    s = 1/(1+T.exp(-x))
    logistic = theano.function([x], s)  # performs elementwise operations
    result = logistic([a])  # we got the logistic value for every element in i
    return result

# sample input
a = np.arange(-10, 10, .2)
result = sigmoid(a)
# A plot of the logistic function, with a on the x-axis and sigmoid(a) on
# the y-axis
# our logistic theano func retuns a 2d array/matrix thats why we neeed to
# flatten it to plot
plt.plot(a, np.array(result).flatten())
plt.title('logistic/sigmoid function')
plt.grid(True)
plt.xlabel("input", color='red')
plt.ylabel("logistic output", color='red')
plt.show()

# tanh function
def tanh(a):
    x = T.dmatrix('x')
    p, q = T.exp(x)-T.exp(-x), T.exp(x)+T.exp(-x)
    t = p/q
    tanhfunc = theano.function([x], t)
    result = tanhfunc([a])
    return result

# sample input
a = np.arange(-10, 10, .2)
result = tanh(a)

plt.plot(a, np.array(result).flatten())
plt.title('tanh function')
plt.grid(True)
plt.xlabel("input", color='red')
plt.ylabel("tanh output", color='red')
plt.show()