# -*- coding: utf-8 -*-
"""
Created on Sat Apr 20 15:18:27 2019

@author: Miguel Ángel Vélez

"""

import numpy as np

#------------------------------------------------------------------------------------------------#
#------------------------------------- Multiple Regression --------------------------------------#
#------------------------------------------------------------------------------------------------#

#y1 = [15, 17, 13, 23, 16, 21, 14, 20, 24, 17, 16, 18, 23, 15, 16]
##
#x1 = [10, 12, 8, 17, 10, 15, 10, 14, 19, 10, 11, 13, 16, 10, 12]
#x2 = [2.4, 2.72, 2.08, 3.68, 2.56, 3.36, 2.24, 3.2, 3.84, 2.72, 2.07, 2.33, 2.98, 1.94, 2.17]

def beta_hat(y, *args):
    """
    """
    x = list(args)

    ones = [1] * (len(y))
    X = np.matrix([ones] + x).transpose()

    #print(np.dot(transpose_X, X))
    # print(xs * transpose_x)

    #print(
            #np.dot(np.linalg.inv(np.dot(X.transpose(), X)), np.dot(y, X.transpose()))
            #np.dot(y, np.dot(np.linalg.inv(np.dot(X.transpose(), X)), X.transpose()))
            #np.dot(np.dot(np.linalg.inv(np.dot(X.transpose(), X)), X.transpose()), y).tolist()[0]
            #)

    beta_hat = np.dot(np.dot(np.linalg.inv(np.dot(X.transpose(), X)), X.transpose()), y).tolist()[0]

    return beta_hat

def regression(y, *args):
    """
    """
    betas = beta_hat(y, *args)
    model = lambda *xs : betas[0] + sum([(betas[i] * xs[i - 1]) for i in range(1, len(betas))])
    model.shape = "ÿ = {}".format(round(betas[0], 2))
    for i in range(1, len(betas)):
        model.shape += (" + {}X{}".format(round(betas[i], 2), i))
    return model

def y_hat(y, *args):
    """
    """
    model = regression(y, *args)

    length_args = len(args[0])
    length_parent = len(args)

    y_hat = []

    for i in range(0, length_args):
        aux = []
        #print("aux: ", aux)
        for j in range(0, length_parent):
            #print("args: ", args[j][i])
            aux.append(args[j][i])

        #print("*aux: ", *aux)
        y_hat.append(model(*aux))
        #print("yhat: ", y_hat)

    return y_hat

#print(y_hat(y1, x1, x2))

def get_se(y, *args):
    """
    """
    y_hats = y_hat(y, *args)

    n = len(y)
    k = len(args)

    se = (sum([(y[i] - y_hats[i])**2 for i in range(n)]) / (n - k - 1))**0.5
    return se

#print(get_se(y1, x1, x2))

def get_scr(y, *args):
    """
    """
    y_hats = y_hat(y, *args)
    n = len(y)
    mean_y = np.mean(y)

    scr = sum([(y_hats[i] - mean_y)**2 for i in range(n)])
    return scr

def get_sct(y, *args):
    """
    """
    mean_y = np.mean(y)
    n = len(y)
    sct = sum([(y[i] - mean_y)**2 for i in range(n)])
    return sct

def get_sce(y, *args):
    """
    """
    y_hats = y_hat(y, *args)
    n = len(y)

    sce = sum([(y[i] - y_hats[i])**2 for i in range(n)])
    return sce

def get_r2(y, *args):
    """
    """
    r2 = get_scr(y, *args) / get_sct(y, *args)
    return r2

def get_r2_(y, *args):
    """
    """
    n = len(y)
    k = len(args)

    r2_ = 1 - (1 - get_r2(y, *args)) * ((n - 1) / (n - k -1))
    return r2_

def get_cmr(y, *args):
    """
    """
    k = len(args)
    cmr = get_scr(y, *args) / k
    return cmr

def get_cme(y, *args):
    """
    """
    n = len(y)
    k = len(args)
    cme = get_sce(y, *args) / (n - k - 1)
    return cme

def get_fratio(y, *args):
    """
    """
    fratio = get_cmr(y, *args) / get_cme(y, *args)
    return fratio

def matrix_corr(y, *args):
    """
    """
    matrix = np.corrcoef(y, args)
    return matrix

def get_sr(rij, n):
    """
    """
    sr = ((1 - (rij)**2) / (n - 2))**0.5
    return sr

def t_multicollinearity(rij, sr):
    """
    """
    t = rij / sr
    return t

def t_regression(b, beta, sb):
    """
    """
    t = (b - beta) / sb
    return t

def get_sbs(y, *x):
    """
    """
    xs = list(x)
    ones = [1] * len(y)
    X = np.matrix([ones] + xs).transpose()

    X_matrix = np.linalg.inv(np.dot(X.transpose(), X))

    cme = get_cme(y, *x)

    C = cme * X_matrix

    sbs = [(C[i, i]**0.5) for i in range(len(x) + 1)]

    return sbs

#print(get_sbs(y1, x1, x2))

#print(matrix_corr(y1, x1, x2))
#print(get_sr(matrix_corr(y1, x1, x2)[1, 2], len(y1)))

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


import os
import time
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

# %matplotlib inline
fig = plt.figure()
ax = plt.axes(projection='3d')
ax = plt.axes(projection='3d')

# Data for a three-dimensional line
zline = np.linspace(0, 15, 1000)
xline = np.sin(zline)
yline = np.cos(zline)
ax.plot3D(xline, yline, zline, 'gray')

# Data for three-dimensional scattered points
zdata = 15 * np.random.random(100)
xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap='Greens');

def f(x, y):
    return np.sin(np.sqrt(x ** 2 + y ** 2))

x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)

X, Y = np.meshgrid(x, y)
Z = f(X, Y)

fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 50, cmap='binary')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z');

ax.view_init(60, 35)
fig

plt.style.use('_mpl-gallery')

# make data
x = np.linspace(-10, 10, 200)
y = 4 + 2 * np.sin(2*x)/x

# plot
fig, ax = plt.subplots()

ax.plot(x, y, linewidth=2.0)

ax.set(xlim=(-8, 8), xticks=np.arange(-8, 8),
       ylim=(4, 10), yticks=np.arange(0, 10))

np.random.seed(1)
x = np.random.uniform(-3, 3, 256)
y = np.random.uniform(-3, 3, 256)
z = (1 - x/2 + x**5 + y**3) * np.exp(-x**2 - y**2)

# plot:
fig, ax = plt.subplots()

ax.plot(x, y, 'o', markersize=2, color='grey')
ax.tripcolor(x, y, z)

ax.set(xlim=(-3, 3), ylim=(-3, 3))

plt.show()

st = [[1,5,"malakia"], True, "lol", 15, 1.5, 35]
st2 = ["kappa", [1,5,6,7], 1.55]

st.append(st[0])
for i in range (0,len(st)):
	print(st[i])
a=0.5
b=-1.55

if abs(a-b)<0:
	print("true")
else:
	print("false")

for i in range (0, np.random.randint(2, 100)):
	print(np.random.randint(2,100))


import numpy as np
import pandas as pd

def normalize(X: np.ndarray) -> np.ndarray:
    """
    Normalizes a 1D matrix to have 0 mean and 1 std.

    :param X: Matrix to be normalized.
    :return: Normalized matrix.
    """

    return (X - X.mean()) / X.std()

def normalize_df(df: pd.DataFrame) -> pd.DataFrame:
    """
    Normalizes all dataframe columns to have 0 mean and 1 std.

    :param df: Dataframe to be normalized.
    :return: Normalized dataframe.
    """

    for col in df.columns:
        df[col] = normalize(df[col])
    return df


import numpy as np

### Pareto Class ###
class Pareto(object):

    @staticmethod
    def cull(pts, dominates):
        dominated, cleared = [], []
        remaining = pts

        while remaining:
            candidate = remaining[0]
            new_remaining = []
            for other in remaining[1:]:
                [new_remaining, dominated][Pareto.dominates(candidate, other)].append(other)
            if not any(Pareto.dominates(other, candidate) for other in new_remaining):
                cleared.append(candidate)   # PARETO POINT
            else:
                dominated.append(candidate)
            remaining = new_remaining
        return cleared, dominated

    @staticmethod
    def dominates(row, rowCandidate):
        return all(r <= rc for r, rc in zip(row, rowCandidate))

    @staticmethod
    def computeParetoOptimalMember(Y, index=None):
        index = np.arange(0,Y.shape[0]) if index is None else np.asarray(index)

        Ypareto, Ydominated = Pareto.cull(Y.tolist(), Pareto.dominates)
        paretoIndex = [index[np.all(Y == ypareto, axis=1)][0]    for i, ypareto    in enumerate(Ypareto)]
        dominatedIndex = [i for i in index if not i in paretoIndex]

        return paretoIndex, dominatedIndex

    @staticmethod
    def computeParetoRanks(Y):
        indexunranked = np.arange(0,Y.shape[0])
        ranks = 99*np.ones(Y.shape[0])
        paretoRank = 0
        while len(indexunranked) > 0:
            paretoIndex, indexunranked = Pareto.computeParetoOptimalMember(Y[indexunranked,:], index=indexunranked)
            ranks[paretoIndex] = paretoRank
            paretoRank += 1

        return ranks


import numpy as np

a = np.array([[0, 1, 2, 3],
             [4, 5, 6, 7],
             [8, 9, 10, 11]])
print(a)

'''
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
'''

print(a.reshape(2, 6)) # 形状変換

'''
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]]
'''

b = np.arange(24).reshape(2, 3, 4)
# np.arange(24) は 0 以上 24 未満の整数を 1 次元 array として生成
print(b) # 3 次元 array

'''
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
'''

print(b.reshape(2, 3, 2, -1)) # 形状変換

'''
[[[[ 0  1]
   [ 2  3]]

  [[ 4  5]
   [ 6  7]]

  [[ 8  9]
   [10 11]]]

 [[[12 13]
   [14 15]]

  [[16 17]
   [18 19]]

  [[20 21]
   [22 23]]]]
'''

print(b.reshape(-1)) # 1 次元 array への変換

'''
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
'''


import numpy as np

def poly_fit(n,xx,yy,sym=False):
	x = np.copy(xx)
	y = np.copy(yy)
	start = 0
	if not sym:
		# initialize variables
		A = np.zeros((n,n))
		b = np.zeros(n)
		step = 1
	else:
		step = 2
		if n % 2 == 0:
			if n > 2:
				size = int(n / 2)
				start = 1
			else:
				size = n
				step = 1
		else:
			size = int(n / 2) + 1
		A = np.zeros( (size,size) )
		b = np.zeros( size )
	for i,e in enumerate(range(start,n,step)):
		for j,f in enumerate(range(start,n,step)):
			A[i,j] = sum( x ** float(e + f) )
		b[i] = sum( y * x ** float(e) )
	a = np.linalg.solve(A,b)
	if sym:
		start = 1
		if n % 2 == 0:
			start = 0
		a = np.insert(a,range(start,a.size),0.)
	r = r2(a,x,y)
	return a, r

def poly_func(a,x):
	f = 0.
	n = len(a)
	for i in range(n):
		f += a[i] * x ** float(i)
	return f

def r2(aa,xx,yy):
	a = np.copy(aa)
	x = np.copy(xx)
	y = np.copy(yy)
	n = len(y)
	y_ = sum(y) / float(n)
	SSt = sum((y-y_)**2.)
	f = np.zeros(n)
	for i in range(n):
		f[i] = poly_func(a,x[i])
	SSr = sum((y-f)**2.)
	return 1. - SSr / SSt

def force_good_poly_fit(n,xx,yy,tol,sym=False):
	x = np.copy(xx)
	y = np.copy(yy)

	a, r = poly_fit(n,x,y,sym=sym)
	x_bad = []
	y_bad = []
	print('R2 is {:7.5f}'.format(r))
	while r < tol:

		e_loc = 0
		l = y.size
		e_max = 0.
		for i in range(l):
			e = abs(poly_func(n,a,x[i]) - y[i])
			if e > e_max:
				e_max = e
				e_loc = i
		x_bad.append(x[e_loc])
		y_bad.append(y[e_loc])
		x = np.delete(x,e_loc)
		y = np.delete(y,e_loc)

		a, r = poly_fit(n,x,y)
		print('R2 is {:7.5f}'.format(r))

	mx = max(y)

	return a, x, y, x_bad, y_bad, r, mx

def rms(raw_x, raw_y, a):
	x = np.copy( raw_x )
	y = np.copy( raw_y )
	avg = np.mean(abs(y))
	l = len(x)
	func = np.zeros(l)
	e = np.zeros(l)
	e_per = np.zeros(l)
	for i in range(l):
		func[i] = poly_func(a, x[i])
		e[i] = (y[i] - func[i]) ** 2.
		e_per[i] = ((y[i] - func[i])/avg) ** 2.
	return np.sqrt(np.mean(e)), np.sqrt(np.mean(e_per))


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

from utils.utility import euclidean_dist

class KMeans:
    def __init__(self, n_clusters=1, centroid_plot=True):
        self.centroid_plot = centroid_plot
        # self.elbow_plot = True
        self.n_clusters = n_clusters

        return

    def _cost_function(self, X, c, mu):
        J = 0
        for i in range(X.shape[0]):
            J += np.square(
                        euclidean_dist(X[i, :],
                        mu[int(c[i]), :].reshape(1, X.shape[1])))
        J /= X.shape[0]

        return J

    def _assign_cluster(self, X, c, mu):
        for i in range(len(X)):
            dist = euclidean_dist(X[i], mu)
            idx = np.argmin(dist)
            c[i] = idx

        return c

    def _cluster_centroid(self, X, c, mu):
        mu = np.zeros((self.n_clusters, X.shape[1]))
        for c_ in set(c.ravel()):
            counter = 0
            for i in range(X.shape[0]):
                if c[i] == c_:
                    mu[int(c[i]), :] += X[i, :]
                    counter += 1
            mu[int(c_)] /= counter
        return mu

    def _plot_scatter(self, X, cluster_arr, optimal):
        X_1 = X[:, 0]
        X_2 = X[:, 1]
        c = cluster_arr.ravel()

        plt.scatter(X_1[c==0], X_2[c==0])
        plt.scatter(X_1[c==1], X_2[c==1])
        plt.scatter(X_1[c==2], X_2[c==2])
        plt.scatter(optimal[:, 0], optimal[:, 1], color='k')
        plt.show()

    def fit(self, X):
        m, n = X.shape
        prev_J = float('inf')
        optimal = None
        cluster_arr = np.zeros((m , 1))
        random.seed(1)
        for i in range(10):
            cluster_mean = []
            for j in range(self.n_clusters):
                mean = random.choice(X)
                cluster_mean.append(mean)

            cluster_mean = np.array(cluster_mean)

            for iter in range(100):
                cluster_arr = self._assign_cluster(X, cluster_arr, cluster_mean)
                cluster_mean = self._cluster_centroid(X, cluster_arr, cluster_mean)
                J = self._cost_function(X, cluster_arr, cluster_mean)
                print("Job : {} | Iteration : {} | "
                      "Cost : {}" .format(i+1, iter+1,
                                                round(float(J), 4)), end='\r')
            J = self._cost_function(X, cluster_arr, cluster_mean)
            if J  <= prev_J:
                optimal = cluster_mean
                prev_J = J

        if self.centroid_plot:
            self._plot_scatter(X, cluster_arr, optimal)

        self._optimal = optimal

        return self

    def predict(self, X):
        c = np.zeros((X.shape[0], 1))
        for i in range(len(X)):
            dist = euclidean_dist(X[i], self._optimal)
            idx = np.argmin(dist)
            c[i] = idx

        return c


import numpy as np
import conv

print('\n======================== Test 1')
image = np.array(
    [[[
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ]]], dtype='float32')  # N=1, Ci=1, H=4, W=4
kernel = np.ones((3, 1, 3, 3), dtype='float32') # Co, Ci, K, K
output = np.zeros((1, 3, 4, 4), dtype='float32') # N, Co, H, W
conv.conv2d(image, kernel, output)
print(image)
print('------')
print(kernel)
print('------')
print(output)

print('\n======================== Test 2')
image = np.array(
    [[[
        [1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]
    ]]], dtype='float32')  # N=1, Ci=1, H=4, W=4
kernel = np.ones((1, 1, 1, 1), dtype='float32') # Co, Ci, K, K
output = np.zeros((1, 1, 4, 4), dtype='float32') # N, Co, H, W
conv.conv2d(image, kernel, output)
print(image)
print('------')
print(kernel)
print('------')
print(output)

print('\n======================== Test 3')
kernel = np.ones((1, 1, 1, 1), dtype='float32') # Co, Ci, K, K
output = np.zeros((1, 1, 4, 4), dtype='float32') # N, Co, H, W
conv.conv2d(image, kernel, output)
print(image)
print('------')
print(kernel)
print('------')
print(output)

print('\n======================== Test 4')
image = np.array(
    [[[
        [0, 1, 2, 3],
        [4, 5, 6, 7],
        [8, 9, 10, 11],
        [12, 13, 14, 15]
    ]]], dtype='float32')  # N=1, Ci=1, H=4, W=4
kernel = np.ones((3, 1, 3, 3), dtype='float32') # Co, Ci, K, K
output = np.zeros((1, 3, 4, 4), dtype='float32') # N, Co, H, W
conv.conv2d(image, kernel, output, (0., 0.01))
print(image)
print('------')
print(kernel)
print('------')
print(output)
print('------')
print('bias', (0., 0.01))


"""
KNN means K-Nearest-Neighbors.
First, we choose k nearest neighbors, and see what class they belong to because
they are LABELED at that time.
Seconnd, count the most common class. If there are two or more classes have the
same number, take some action and retry (such as discard the farthest point)
Finally we are sure to get the class of the input points.

KNN is a lazy algorithms because it waits for input and then compute.
"""

import numpy as np
from collections import Counter

def distance(v, w):
    "compute the distance between two vectors"
    vn = np.array(v)
    wn = np.array(w)
    return np.sqrt(sum(np.square(vn-wn)))

def majority_vote(labels):
    "assumes that labels are ordered from nearest to farthest"
    vote_counts = Counter(labels)
    winner, winner_count = vote_counts.most_common(1)[0]
    num_winners = len([count
                       for count in vote_counts.values()
                       if count == winner_count])
    if num_winners == 1:
        return winner
    else:
        return majority_vote(labels[:-1]) # try again without the farthest

# user interface
def knn_classify(k, labeled_points, new_point):
    "each labeled point should be a pair (point, label)"

    # order the points from nearest to farthest
    by_distance = sorted(labeled_points,
                         key=lambda (point, _): distance(point, new_point))

    # find the labels for the k closest
    k_nearest_labels = [label for _, label in by_distance[:k]]

    # and let them vote
    return majority_vote(k_nearest_labels)

# drawback
# 1. compute costly!
# 2. curse of dimensionality -- when it comes to high dimensionality, points are
# tend not to be close to one another at all

# Special thanks to Joel Grus


import numpy as np

def mean_datasets(files):
    datasets = []

    for file in files:
        datasets.append(np.loadtxt(file, delimiter=','))

    result = np.mean(datasets, axis=0)
    return np.round(result, decimals=1)

if __name__ == '__main__':
    # Test Case 1
    print(mean_datasets(['data1.csv', 'data2.csv', 'data3.csv']))

    # Test Case 2
    print(mean_datasets(['data4.csv', 'data5.csv', 'data6.csv']))


import numpy as np
import time

def create_tridiag(a, b, c, n):
    A = np.zeros((n, n))
    for i in range(n):
        A[i][i] = b
        if i < n - 1:
            A[i + 1][i] = a
            A[i][i + 1] = c
    return A

def solve_gauss(A, B):
    n = len(A)
    det = 1
    for i in range(n):
        # Find Maximum Row
        maxRow = i
        for j in range(i + 1, n):
            if abs(A[j][i]) > abs(A[maxRow][i]):
                maxRow = j
            # Swap Rows
        if maxRow != i:
            det *= -1
            for k in range(0, n):
                temp = A[i][k]
                A[i][k] = A[maxRow][k]
                A[maxRow][k] = temp
            temp = B[maxRow]
            B[maxRow] = B[i]
            B[i] = temp

        # Make upper diagonal
        for k in range(i + 1, n):
            t = -A[k][i] / A[i][i]
            for c in range(i, n):
                A[k][c] += t * A[i][c]
            B[k] += t * B[i]

    # Solve equation Ax=b for an upper triangular matrix A
    X = [0 for i in range(n)]
    for i in range(n - 1, -1, -1):
        X[i] = B[i] / A[i][i]
        for k in range(i - 1, -1, -1):
            B[k] -= A[k][i] * X[i]
        det *= A[i][i]
    return det, X

'''___Main___'''

n = 50
a = create_tridiag(1, 4, -1, n)
b = [1 for i in range(n)]
start = time.time()
d, result = solve_gauss(a, b)
end = time.time()
print("Determinant: ", d)
print("Result: ", result)
print("NumPy Result: ", np.linalg.solve(a, b))
print("Time: ", end - start)


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

pio.renderers.default = 'browser'
pio.templates.default = "simple_white"

def test_univariate_gaussian():
    # Question 1 - Draw samples and print fitted model
    question_1_samples = np.random.normal(10, 1, size=1000)
    question_1_model = UnivariateGaussian()
    question_1_model.fit(question_1_samples)
    print(question_1_model.mu_, question_1_model.var_)

    # Question 2 - Empirically showing sample mean is consistent
    question_2_x_values = []
    mean_values = []

    ug = UnivariateGaussian()
    for i in range(10, 1001, 10):
        question_2_x_values.append(i)
        ug.fit(question_1_samples[1:i])
        mean_values.append(np.abs(10-ug.mu_))

    question_2_fig = go.Figure()
    question_2_fig.update_layout(
        title="Samples from ~N(10,1) and their difference from the true mean",
        xaxis_title="Sample size",
        yaxis_title="Difference from mean"
    )

    question_2_fig.add_scatter(
        x=question_2_x_values,
        y=mean_values,
    )
    question_2_fig.show()

    # Question 3 - Plotting Empirical PDF of fitted model
    question_3_fig = go.Figure()
    question_3_fig.update_layout(
        title="Samples from ~N(10,1) and their PDFs",
        xaxis_title="Sample value",
        yaxis_title="PDF of sample"
    )

    qs_3_samples = np.sort(question_1_samples)
    question_3_fig.add_scatter(
        x=qs_3_samples,
        y=question_1_model.pdf(qs_3_samples),
    )

    """The expected result is a graph that looks like a bell,
    as the samples were taken from normal distribution.
    """
    question_3_fig.show()

def test_multivariate_gaussian():
    # Question 4 - Draw samples and print fitted model
    mean = np.array([0, 0, 4, 0])
    cov = np.array(
        [
            [1, 0.2, 0, 0.5],
            [0.2, 2, 0, 0],
            [0, 0, 1, 0],
            [0.5, 0, 0, 1]
        ])

    question_1_samples = \
        np.random.multivariate_normal(mean, cov, size=1000)

    question_1_model = MultivariateGaussian()
    question_1_model.fit(question_1_samples)
    print("Mean:\n", question_1_model.mu_)
    print("\n")
    print("Cov:\n", question_1_model.cov_)

    # Question 5 - Likelihood evaluation
    space = np.linspace(-10, 10, 200)
    heat = np.zeros((space.size, space.size))

    for i, f1 in enumerate(space):
        for j, f3 in enumerate(space):
            heat[i, j] = MultivariateGaussian.log_likelihood(np.array([f1, 0, f3, 0]), cov, question_1_samples)

    fig = go.Figure(go.Heatmap(x=space, y=space, z=heat), layout=go.Layout(title="Log-likelihood for [f1,0,f3,0]"))
    fig.show()
    # Question 6 - Maximum likelihood]
    indices = np.unravel_index(heat.argmax(),heat.shape)
    max_log_likelihood = np.round(heat[indices[0],indices[1]],3)

    max_f1 = np.round(space[indices[0]],3)
    max_f3 = np.round(space[indices[1]],3)
    print("The (f1,f3) values with the max log-likelihood of", max_log_likelihood)
    print("are: ",max_f1, "and", max_f3)

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


#---------------------------------------------------------------------------------------------------#
Chapter 1 - Graphical exploratory data analysis

#---------------------------------------------------------------------------------------------------#
#Axis labels!

# Plot histogram of versicolor petal lengths
_ = plt.hist(versicolor_petal_length)

# Label axes
plt.xlabel('petal length (cm)')
plt.ylabel('count')

# Show histogram

plt.show()

#---------------------------------------------------------------------------------------------------#
#Adjusting the number of bins in a histogram

# Import numpy
import numpy as np

# Compute number of data points: n_data
n_data = len(versicolor_petal_length)

# Number of bins is the square root of number of data points: n_bins
n_bins = np.sqrt(n_data)

# Convert number of bins to integer: n_bins
n_bins = int(n_bins)

# Plot the histogram
_ = plt.hist(versicolor_petal_length, bins=n_bins)

# Label axes
_ = plt.xlabel('petal length (cm)')
_ = plt.ylabel('count')

# Show histogram
plt.show()

#---------------------------------------------------------------------------------------------------#
#Plotting the ECDF

# Compute ECDF for versicolor data: x_vers, y_vers
x_vers, y_vers = ecdf(versicolor_petal_length)

# Generate plot
_ = plt.plot(x_vers, y_vers, marker='.', linestyle='none')

# Make the margins nice
plt.margins(0.02)

# Label the axes
_ = plt.xlabel('petal length (cm)')
_ = plt.ylabel('ECDF')

# Display the plot
plt.show()

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

#Computing the ECDF
def ecdf(data):
    """Compute ECDF for a one-dimensional array of measurements."""

    # Number of data points: n
    n = len(data)

    # x-data for the ECDF: x
    x = np.sort(data)

    # y-data for the ECDF: y
    y = np.arange(1, n+1) / n

    return x, y

#---------------------------------------------------------------------------------------------------#
#Comparison of ECDFs

# Compute ECDF for versicolor data: x_vers, y_vers
x_vers, y_vers = ecdf(versicolor_petal_length)
x_set, y_set = ecdf(setosa_petal_length)
x_virg, y_virg = ecdf(virginica_petal_length)
# Generate plot
_ = plt.plot(x_vers, y_vers, marker='.', linestyle='none')
_ = plt.plot(x_set, y_set, marker='.', linestyle='none')
_ = plt.plot(x_virg, y_virg, marker='.', linestyle='none')
# Make the margins nice
plt.margins(0.02)

# Annotate the plot
plt.legend(('setosa', 'versicolor', 'virginica'), loc='lower right')
_ = plt.xlabel('petal length (cm)')
_ = plt.ylabel('ECDF')

# Display the plot
plt.show()

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

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

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

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

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

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

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

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

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

Statistical Thinking in Python (Part 1)/Chapter 1 - Graphical exploratory data analysis.py


# coding: utf-8

# # What to Input
#
# Graph: Your implementation can expect your graph to be submitted in adjacency matrix format, through a text file (call it graph.txt). Here is an example text filePreview the document to show you can provide adjacency matrix as input. This document will contain graph structure in matrix format, with three columns (I,j,k). Each row will denote information for a cell. e.g. a row of the form "i j k" denotes that the matrix contains a value k at the row i column j.  The value k=1 denotes that there is a link from document (node) i to document (node) j, else the value of k =0.
#
# Parameters: In your implementations use beta=0.85 as the dampening factor.
#
#
# # What to output:
#
#  Your code should give out the Rank Vector (after convergence),
#     and number of iterations it took to converge.
#     The rank scores should be rounded to 4 decimal places.

# In[29]:

get_ipython().run_line_magic('pylab', 'inline')
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
img=mpimg.imread('graph.png')
imgplot = plt.imshow(img)
plt.show()

# In[30]:

# import library
import numpy as np, pandas as pd
import warnings
warnings.filterwarnings("ignore")

# In[31]:

# Read graph text file form disk
graph = open('./graph.txt', 'r')
data = graph.read() # process graph.txt
graph.close()# closing file
data = data.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ').split() # split data and put in one row
# data

# In[32]:

def split(theList):
    for i in range(0, len(theList), 3):
        yield theList[i:i+3]
data = split(data)
data = list(data)
data

# In[33]:

dic = {} #a dictionary object
dicdup = {} #duplicates
for i in data:
    node = i[0]
    if node not in dic:
        dic[node] = 0
    if i[1] not in dic: # for the graph.txt files where only 1 is shown
        dic[i[1]] = 0
    if i[2] == "1": #is there an dic edge?

        if node + "---->" + i[1] not in dicdup: #k=1 dictionary
            dic[node] += 1
            dicdup[node+"---->"+i[1]] = 1
dicdup

# # Matrix M

# In[34]:

m_matrix = pd.DataFrame(columns=dic.keys(), index=dic.keys(), dtype="double").fillna(0)
for i in data:
    if i[2] == "1":
        m_matrix.at[i[1],i[0]] = 1 / dic[i[0]]
print("What is the output for Matrix M? Give (print) the matrix:","\n\n", m_matrix,"\n")
m_matrix = m_matrix.as_matrix() #create a numpy matrix

# # Matrix A

# In[35]:

# A = beta * M + (1-beta)*T
beta = 0.85 #BETA

T = np.matrix([[1/6,1/6,1/6,1/6,1/6,1/6],
               [1/6,1/6,1/6,1/6,1/6,1/6],
               [1/6,1/6,1/6,1/6,1/6,1/6],
               [1/6,1/6,1/6,1/6,1/6,1/6],
               [1/6,1/6,1/6,1/6,1/6,1/6],
               [1/6,1/6,1/6,1/6,1/6,1/6]])
reuslt1= beta * m_matrix
reuslt2=(1-beta)*T
print("What is the output of Matrix A? After applying teleportation. Give (print) the matrix.")
# Matrix_A= reuslt1+reuslt2
Matrix_A=np.add(reuslt1,reuslt2)
print(Matrix_A)

# # Original Rank Vector R

# In[36]:

rj = []
for i in range(0, len(dic)):
    rj.append(1 / len(dic))
original_rank_vector_R = np.matrix(rj).T
print("What is the original rank vector (R)?:","\n\n", original_rank_vector_R, "\n")

# # Converged Rank Vector R

# In[37]:

iterations = 0; #iterations
lastrvec = original_rank_vector_R
currentrvec = np.empty(shape=(len(dic),1))  #(n,1) format for r vectors: n rows, one col
currentrvec.fill(-1) #start while loop with currentrvec values of -1
while(np.allclose(lastrvec, currentrvec, rtol=1e-06, atol=1e-06) == 0):
    lastrvec = original_rank_vector_R
    iterations += 1
#     print(iterations)
    currentrvec =  m_matrix * original_rank_vector_R  # Formula for M :         rank_vector_t_plus_1 = m_matrix * rank_vector_t
    original_rank_vector_R = currentrvec
print(" When you use Matrix M")
print(currentrvec)
print("\n iterations is", iterations)

# In[38]:

iterations = 0; #exponent for iterations
lastrvec = original_rank_vector_R
currentrvec = np.empty(shape=(len(dic),1))
currentrvec.fill(0)
teleport_factor = (1- beta) / len(dic)  #probability that the user will jump
# teleport_factor= round(teleport_factor)
# print("teleport_factor:" ,teleport_factor)
# Formula for A:  rank_vector_t_plus_1 = damp_factor * m_matrix * rank_vector_t + teleport_factor
while(np.allclose(lastrvec, currentrvec, rtol=1e-06, atol=1e-06) == 0):
#     to 6 decimal places
    lastrvec = original_rank_vector_R
    iterations += 1
#     print(iterations , "\t", lastrvec)
    currentrvec = beta * m_matrix * original_rank_vector_R +  teleport_factor
    original_rank_vector_R = currentrvec
print(" When you use Matrix A")
print(currentrvec )
print("\n iterations is", iterations)


import numpy as np

def calculate_probability(values):
    probabilities={}
    unique_values=list(set(values))
    for unique_value in unique_values:
        probabilities[str(unique_value)]=len(values[values==unique_value])/len(values)
    return probabilities

def calculate_entropy(values):
    probabilities=calculate_probability(values)
    entropy=0
    for probability_key in probabilities.keys():
        probability_value=probabilities[probability_key]
        entropy=entropy-1*probability_value*np.log(probability_value)
        entropy=entropy/np.log(np.exp(1))
    return entropy

def calculate_information_gain(x,y):
    information_gain=0
    unique_x_values=set(x)
    for unique_x_value in unique_x_values:
        sub_y=y[x==unique_x_value]
        sub_ratio=len(sub_y)/len(y)
        information_gain=information_gain+sub_ratio*calculate_entropy(sub_y)
    return information_gain

def create_decision_tree(x,y,dimension_level):
    unique_rows=np.unique(x,axis=0)
    #print(x,y)
    if np.shape(unique_rows)[0]<2 or dimension_level==0:
        return y[0]
    entropy=calculate_entropy(y)
    base_information_gain=-1
    selected_dimension=-1
    for i in range(np.shape(x)[1]):
        current_information_gain=entropy-calculate_information_gain(x[:,i],y)
        if base_information_gain<current_information_gain:
            base_information_gain=current_information_gain
            selected_dimension=i
    #print('entropy:',entropy,'information gain:',base_information_gain)
    #print('splitting based on dimension',selected_dimension)
    unique_x_values=set(x[:,selected_dimension])
    #sub-tree routine
    decision_tree={}
    for unique_x_value in unique_x_values:
        #print('unique_x_value:',unique_x_value,'out of',unique_x_values)
        decision_tree['dimension']=selected_dimension
        sub_mask=x[:,selected_dimension]==unique_x_value
        sub_x=x[sub_mask]
        sub_y=y[sub_mask]
        decision_sub_tree=create_decision_tree(sub_x,sub_y,dimension_level-1)
        decision_tree[str(unique_x_value)]=decision_sub_tree
    return decision_tree

def check_fit(x,y,decision_tree):
    matches=0
    for i in range(np.shape(x)[0]):
        current_x=x[i,:]
        decision_sub_tree=decision_tree
        for j in range(0,np.shape(x)[1]):
            if type(decision_sub_tree) is dict:
                current_dimension=int(decision_sub_tree['dimension'])
                decision_sub_tree=decision_sub_tree[str(x[i,current_dimension])]
            else:
                break
        prediction=decision_sub_tree
        if prediction==y[i]:
            matches=matches+1
    accuracy=matches/len(y)
    return accuracy

if __name__=='__main__':
    for i in range(10):
        #generate random dataset
        x=np.floor(np.random.rand(100,32)/0.2)
        y=np.floor(np.random.rand(100)/0.2)

        print(x,y)

        decision_tree=create_decision_tree(x,y,np.shape(x)[1])
        print('decision tree:',decision_tree)

        print('training accuracy:',check_fit(x,y,decision_tree))


import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([2, 3, 4, 5])
c = np.vstack((a, b))

print(c)
print(c.shape)

d = np.hstack((a, b))
print(d)
print(d.shape)

e = np.array([
    [0, 1],
    [1, 0],
])
print("Rows %d" % e.shape[0])
print("Columns %d" % e.shape[1])


'''
This performs some statistical manipulations on distributions given in series
It has no state
'''

from scipy import stats

def compareDistributionsMannWhitney(distA, distB, sig_level, htmlise=False):
    distA.sort()
    distB.sort()
    u_statistic, p_value = stats.mannwhitneyu(distA,distB)

    diver = "\n"
    if htmlise:
        diver = "
\n"

    test_string = "-- Mann-Whitney U Test --" + diver
    test_string +=  "Hypothesis:The distributions are identical" + diver
    test_string += "Method: If the p-value < " + str(round(sig_level,2)) + " we will reject" + diver
    test_string += "Evidence: The p-value is " + str(round(p_value,4)) + diver
    test_string += "(U Statistic=" + str(round(u_statistic,2)) + ")" + diver
    if p_value < sig_level:
        test_string += "Conclusion: We reject the hypothesis, they are not the same."
    else:
        test_string += "Conclusion: We have no evidence to reject the hypothesis."

    return p_value, test_string

def normalityShapiroWilk(distA, sig_level, htmlise=False):
    distA.sort()
    statistic,pvalue = stats.shapiro(distA)

    diver = "\n"
    if htmlise:
        diver = "
\n"

    test_string = "-- Shapiro-Wilk Normality Test --" + diver
    test_string +=  "Hypothesis:The distribution is normal" + diver
    test_string += "Method: If the p-value < " + str(round(sig_level,2)) + " we will reject" + diver
    test_string += "Evidence: The p-value is " + str(round(pvalue,4)) + diver
    test_string += "(Statistic=" + str(round(statistic,2)) + ")" + diver
    if pvalue < sig_level:
        test_string += "Conclusion: Not normal, we reject the hypothesis."
    else:
        test_string += "Conclusion: Normal, we have no evidence to reject the hypothesis."

    return pvalue, test_string


import numpy as np
import matplotlib.pyplot as plt
import skfuzzy as fuzz

x_qual = np.arange(0,11,1)
x_serv = np.arange(0,11,1)
x_tip = np.arange(0,26,1)

qual_lo = fuzz.trimf(x_qual, [0, 0, 5])
qual_md = fuzz.trimf(x_qual, [0, 5, 10])
qual_hi = fuzz.trimf(x_qual, [5, 10, 10])
serv_lo = fuzz.trimf(x_serv, [0, 0, 5])
serv_md = fuzz.trimf(x_serv, [0, 5, 10])
serv_hi = fuzz.trimf(x_serv, [5, 10, 10])
tip_lo = fuzz.trimf(x_tip, [0, 0, 13])
tip_md = fuzz.trimf(x_tip, [0, 13, 25])
tip_hi = fuzz.trimf(x_tip, [13, 25, 25])

fig, (ax0, ax1, ax2) = plt.subplots(nrows=3, figsize=(8, 9))
ax0.plot(x_qual, qual_lo, 'b', linewidth=1.5, label='Bad')
ax0.plot(x_qual, qual_md, 'g', linewidth=1.5, label='Decent')
ax0.plot(x_qual, qual_hi, 'r', linewidth=1.5, label='Great')
ax0.set_title('Food quality')
ax0.legend()

ax1.plot(x_serv, serv_lo, 'b', linewidth=1.5, label='Poor')
ax1.plot(x_serv, serv_md, 'g', linewidth=1.5, label='Acceptable')
ax1.plot(x_serv, serv_hi, 'r', linewidth=1.5, label='Amazing')
ax1.set_title('Service quality')
ax1.legend()

ax2.plot(x_tip, tip_lo, 'b', linewidth=1.5, label='Low')
ax2.plot(x_tip, tip_md, 'g', linewidth=1.5, label='Medium')
ax2.plot(x_tip, tip_hi, 'r', linewidth=1.5, label='High')
ax2.set_title('Tip amount')
ax2.legend()

# Turn off top/right axes
for ax in (ax0, ax1, ax2):
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.get_xaxis().tick_bottom()
    ax.get_yaxis().tick_left()

plt.tight_layout()
plt.show()

qual_level_lo = fuzz.interp_membership(x_qual, qual_lo, 6.5)
qual_level_md = fuzz.interp_membership(x_qual, qual_md, 6.5)
qual_level_hi = fuzz.interp_membership(x_qual, qual_hi, 6.5)

serv_level_lo = fuzz.interp_membership(x_serv, serv_lo, 9.8)
serv_level_md = fuzz.interp_membership(x_serv, serv_md, 9.8)
serv_level_hi = fuzz.interp_membership(x_serv, serv_hi, 9.8)

active_rule1 = np.fmax(qual_level_lo, serv_level_lo)
tip_activation_lo = np.fmin(active_rule1, tip_lo)

tip_activation_md = np.fmin(serv_level_md, tip_md)

active_rule3 = np.fmax(qual_level_hi, serv_level_hi)
tip_activation_hi = np.fmin(active_rule3, tip_hi)

#tip0 = np.zeros_like(x_tip)
# fig, ax0 = plt.subplots(figsize=(8, 3))
# ax0.fill_between(x_tip, tip0, tip_activation_lo, facecolor='b', alpha=0.7)
# ax0.plot(x_tip, tip_lo, 'b', linewidth=0.5, linestyle='--', )
# ax0.fill_between(x_tip, tip0, tip_activation_md, facecolor='g', alpha=0.7)
# ax0.plot(x_tip, tip_md, 'g', linewidth=0.5, linestyle='--')
# ax0.fill_between(x_tip, tip0, tip_activation_hi, facecolor='r', alpha=0.7)
# ax0.plot(x_tip, tip_hi, 'r', linewidth=0.5, linestyle='--')
# ax0.set_title('Output membership activity')
# # Turn off top/right axes
# for ax in (ax0,):
#     ax.spines['top'].set_visible(False)
#     ax.spines['right'].set_visible(False)
#     ax.get_xaxis().tick_bottom()
#     ax.get_yaxis().tick_left()
#     plt.tight_layout()
#
# plt.show()

aggregated = np.fmax(tip_activation_lo, np.fmax(tip_activation_md, tip_activation_hi))
tip = fuzz.defuzz(x_tip, aggregated, 'centroid')

#
# tip_activation = fuzz.interp_membership(x_tip, aggregated, tip)
# fig, ax0 = plt.subplots(figsize=(8, 3))
# ax0.plot(x_tip, tip_lo, 'b', linewidth=0.5, linestyle='--', )
# ax0.plot(x_tip, tip_md, 'g', linewidth=0.5, linestyle='--')
# ax0.plot(x_tip, tip_hi, 'r', linewidth=0.5, linestyle='--')
# ax0.fill_between(x_tip, tip0, aggregated, facecolor='Orange', alpha=0.7)
# ax0.plot([tip, tip], [0, tip_activation], 'k', linewidth=1.5, alpha=0.9)
# ax0.set_title('Aggregated membership and result (line)')
# for ax in (ax0,):
#     ax.spines['top'].set_visible(False)
#     ax.spines['right'].set_visible(False)
#     ax.get_xaxis().tick_bottom()
#     ax.get_yaxis().tick_left()
#     plt.tight_layout()
# plt.show()


import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

# making life easier
def l2hnorm(x, h):
    return np.linalg.norm(x)*np.sqrt(h)

# Colelctors for convergence analysis
err = []
hs = []

#Choose here if you want to see the plots for h = 0.2
plot = False

#Choose here if you want to use the asymetrical domain
asym = True

# Creating a matrix for the symetrical case
def make_A(n):
    L = np.diag((n-1)*[2],0)
    L += np.diag((n-2)*[-1],1)
    L += np.diag((n-2)*[-1],-1)
    return L

# Creating a similar matrix for the asymetrical case
def make_A_asym(n):
    L = np.diag((n-1)*[2.0],0)
    L += np.diag((n-2)*[-1.0],1)
    L += np.diag((n-2)*[-1.0],-1)
    L[0,0] = 1
    L[0,1] = -(2/3)
    return L

for k in range(0,4):
    # k refinement
    h = 0.2/(2**k)
    hs.append(h)
    n = int(1/h)

    # creating the domain and a finer domain for the exactg solution
    omega = np.linspace(0,1, n+1)
    omega2 = np.linspace(0,1, 100)
    if asym:
        omega = np.delete(omega, 1)

    # Calling the proper matrix creation
    A = make_A(n) if not asym else make_A_asym(n-1)

    L = A/(h**2)

    # exact solutions
    fn1 = lambda x: -1/2*np.power(x,2)+3/2*x+1
    fn2 = lambda x: -1*np.exp(x)+np.e*x+2

    # inner points of the computational domain
    wh = np.linspace(0+h, 1-h, n-1)
    if asym:
        wh = wh[1:]

    # creating the boundary conditions
    f1 = np.ones(wh.shape[0])
    f1[0] += 1/h/h if not asym else 1/3/h/h
    f1[-1] += 2/h/h

    f2 = np.exp(wh)
    f2[0] += 1/h/h if not asym else 1/3/h/h
    f2[-1] += 2/h/h

    # Solving the system
    u1 = np.linalg.solve(L.copy(),f1)
    u2 = np.linalg.solve(L.copy(),f2)

    # inserting boundary conditions
    u1 = np.insert(u1, 0, 1)
    u1 = np.append(u1, 2)

    u2 = np.insert(u2, 0, 1)
    u2 = np.append(u2, 2)

    # Plotting of the solution
    if k==0 and plot:

        print(L)
        print(f1)
        print(f2)
        plt.plot(omega, u1, '-x', label="numerical")
        plt.plot(omega2, fn1(omega2), label="analytical")
        plt.legend()
        plt.show()

        plt.plot(omega, u2, '-x', label="numerical")
        plt.plot(omega2, fn2(omega2), label="analytical")
        plt.legend()
        plt.show()
        print(u1)
        print(fn1(omega))
        print(u2)
        print(fn2(omega))

    #Convergence analysis of u2
    print(l2hnorm(u1-fn1(omega), h))
    err.append(l2hnorm(u2-fn2(omega),h))
    print(err[-1])

#FInding alphha and C
to_fit = lambda x,a,c: c*np.power(x,a)

fitted = curve_fit(to_fit, hs, err)[0]
print(fitted)

# Plotting Convergence analysis
plt.loglog(hs,err,'-x', label="Global Error")
plt.loglog(hs, to_fit(hs, *fitted), label="Fitted logarithmic function")
plt.legend()
plt.axis('equal')
plt.show()


# -*- coding: utf-8 -*-
"""
Created on Wed Jun 26 09:11:43 2019

@author: Lenovo
"""
"""
ARTIFICIAL NEURAL NETWORK
cross entropy=-summation[yln(p)+(1-y)(ln(1-p))]
feed forward
back propagation
"""
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam

np.random.seed(0)
n_pts=500
x=np.linspace(-3,3,n_pts)
y=(5*x+3)+np.random.uniform(-5,5,n_pts)
plt.scatter(x,y)
plt.show()

model=Sequential()
model.add(Dense(50,input_dim=1,activation='relu'))

model.add(Dense(1))
model.compile(Adam(lr=0.01),loss='mse')

h=model.fit(x,y,verbose=1,epochs=50,validation_split=0.1)

plt.plot(h.history["loss"])
plt.show()

pred=model.predict(x)
plt.scatter(x,y,color="red")
plt.plot(x,pred,color='yellow')
plt.show()

"""
non-linear
"""
np.random.seed(0)
n_pts=500
x=np.linspace(-3,3,n_pts)
y=np.sin(x)+np.random.uniform(-0.5,0.5,n_pts)
plt.scatter(x,y,color='b')
plt.show()

model=Sequential()
model.add(Dense(50,input_dim=1,activation='sigmoid'))
model.add(Dense(30,activation='sigmoid'))
model.add(Dense(1))
model.compile(Adam(lr=0.01),loss='mse')
h=model.fit(x,y,verbose=1,epochs=50)

plt.plot(h.history["loss"])
plt.show()

pred=model.predict(x)
plt.scatter(x,y,color="red")
plt.plot(x,pred,color='black')
plt.show()

"""
classification problem using keras
"""
import matplotlib.pyplot as plt
n_pts=500
np.random.seed(0)

Xa=np.array([np.random.normal(13,2,n_pts),np.random.normal(13,2,n_pts)]).T
Xb=np.array([np.random.normal(8,2,n_pts),np.random.normal(8,2,n_pts)]).T

X=np.vstack((Xa,Xb))
Y=np.matrix(np.append(np.zeros(n_pts),np.ones(n_pts))).T
plt.scatter(X[:n_pts,0],X[:n_pts,1],color="r")
plt.scatter(X[n_pts:,0],X[n_pts:,1],color="b")
plt.show()

#importing keras functions

from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
model=Sequential()
model.add(Dense(units=1,input_shape=(2,),activation="sigmoid"))
adam=Adam(lr=0.1)
model.compile(adam,loss="binary_crossentropy",metrics=["accuracy"])
history=model.fit(x=X,y=Y,verbose=1,batch_size=50,validation_split=0.1,epochs=10)
plt.plot(history.history["loss"],color="c")
plt.plot(history.history["val_loss"])
plt.legend(["training","validation"])
plt.title("Loss")
plt.xlabel("epoch")

plt.plot(history.history["acc"])
plt.plot(history.history["val_acc"])
plt.legend(["training","validation"])
plt.title("Accuracy")
plt.xlabel("epoch")

def plot_decision_boundary(X,y,model):
    x_span = np.linspace(min(X[:,0])-1,max(X[:,0])+1)
    y_span =  np.linspace(min(X[:,1])-1,max(X[:,1])+1)

    xx,yy=np.meshgrid(x_span,y_span)

    xx_,yy_=xx.ravel(),yy.ravel()
    grid = np.c_[xx_,yy_]
    pred_func = model.predict(grid)
    z = pred_func.reshape(xx.shape)
    plt.contourf(xx,yy,z)
plot_decision_boundary(X,Y,model)
plt.scatter(X[:n_pts,0],X[:n_pts,1])
plt.scatter(X[n_pts:,0],X[n_pts:,1])

x=7.5
y=10

point=np.array([[x,y]])
prediction = model.predict(point)
plt.plot([x],[y],marker='o',markersize=10,color="black")
print(prediction)

"""
classification using keras problem 2
"""

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam

np.random.seed(0)
n=500
X,Y = datasets.make_circles(n_samples=n, random_state=0,noise=0.1,factor=0.2)
print(X)
print(Y)

plt.scatter(X[Y==0,0],X[Y==0,1])
plt.scatter(X[Y==1,0],X[Y==1,1])

model=Sequential()
model.add(Dense(4,input_shape=(2,),activation='sigmoid'))
model.add(Dense(1,activation='sigmoid'))
model.compile(Adam(lr=0.01),"binary_crossentropy",metrics=["accuracy"])
history=model.fit(x=X,y=Y,verbose=1,batch_size=20,validation_split=0.1,epochs=75,shuffle=True)
plt.plot(history.history["acc"])
plt.legend(["Accuracy"])
plt.title("Accuracy")
plt.xlabel("epoch")

plt.plot(history.history["loss"])
plt.legend(["loss"])
plt.title("loss")
plt.xlabel("epoch")

def plot_decision_boundary(X,Y,model):
     x_span = np.linspace(min(X[:,0])-0.25,max(X[:,0])+0.25)
     y_span =  np.linspace(min(X[:,1])-0.25,max(X[:,1])+0.25)

     xx,yy=np.meshgrid(x_span,y_span)
     grid=np.c_[xx.ravel(),yy.ravel()]
     pred_func = model.predict(grid)
     z = pred_func.reshape(xx.shape)
     plt.contourf(xx,yy,z)
plot_decision_boundary(X,Y,model)
plt.scatter(X[Y==0,0],X[Y==0,1])
plt.scatter(X[Y==1,0],X[Y==1,1])

a=0
b=0.75

point=np.array([[a,b]])
prediction = model.predict(point)
plt.plot([a],[b],marker='o',markersize=10,color="black")
print(prediction)

"""
churn modelling dataset claasificatiion using keras
"""
import pandas as pd
data=pd.read_csv(r"C:\Users\Lenovo\Desktop\ai and ml dec\data\Churn_Modelling.csv")
data.drop(['RowNumber','CustomerId','Surname'],axis=1,inplace=True)
data.dtypes

from sklearn.preprocessing import LabelEncoder
le=LabelEncoder()

data.Geography=le.fit_transform(data.Geography)
data.Gender=le.fit_transform(data.Gender)
ip=data.drop(["Exited"],axis=1)
op=data["Exited"]

from sklearn.preprocessing import OneHotEncoder

ohe=OneHotEncoder(categorical_features=[1])
ip=ohe.fit_transform(ip).toarray()

from sklearn.model_selection import train_test_split
xtr,xts,ytr,yts=train_test_split(ip,op,test_size=0.2)

from sklearn.preprocessing import StandardScaler

sc=StandardScaler()
sc.fit(xtr)
xtr=sc.transform(xtr)
xts=sc.transform(xts)

model=Sequential()
model.add(Dense(10,input_shape=(12,),activation='sigmoid'))
model.add(Dense(1,activation='sigmoid'))
model.compile(Adam(lr=0.01),"binary_crossentropy",metrics=["accuracy"])
history=model.fit(x=xtr,y=ytr,verbose=1,batch_size=50,validation_split=0.1,epochs=10)
plt.plot(history.history["acc"])
plt.legend(["Accuracy"])
plt.title("Accuracy")
plt.xlabel("epoch")

plt.plot(history.history["loss"])
plt.legend(["loss"])
plt.title("loss")
plt.xlabel("epoch")


import numpy as np
from loss import CategoricalCrossEntropy

class ActivationReLU:
    def forward(self, inputs):
        self.output = np.maximum(0, inputs)
        # store the inputs for the backwars pass
        self.inputs = inputs

    def backward(self, dvalues):
        self.dinputs = dvalues.copy()
        # zero gradient where input values are negative
        self.dinputs[self.inputs <= 0] = 0

class ActivationSoftmax:
    def forward(self, inputs):
        # get non-normalized probabilities
        # subtract the map value of the inputs to prevent exploding values
        # when dealing with really large numbers. it does not take much for
        # exponential values to get very large (ie. e^1000 will overflow)
        # since e^-inf == 0 and e^0 = 1, we subtract the largest value to put
        # the input values in the range of -inf to 0 (since largest itself == 0)
        exp_values = np.exp(inputs - np.max(inputs, axis=1, keepdims=True))

        # normalize
        # axis=1 means sum the rows, keepdims=True will keep it in the same dims
        # as the exp_values (ie. wont flatten to a list)
        probabilities = exp_values / np.sum(exp_values, axis=1, keepdims=True)

        self.output = probabilities

    def backward(self, dvalues):
        self.dinputs = np.empty_like(dvalues)

        for index, (single_output, single_dvalues) in enumerate(zip(self.output, dvalues)):
            # flatten out array
            single_output = single_output.reshape(-1, 1)

            # compute jacobian matrix of the output
            jacobian_matrix = np.diagflat(single_output) - np.dot(single_output, single_output.T)

            # calculate the samplewise gradient and add it to the array of sample gradients
            self.dinputs[index] = np.dot(jacobian_matrix, single_dvalues)

# Softmax Classifier - combined Softmax activation and cross-entropy loss
#                      for faster backwards step
class ActivationSoftmaxLossCategoricalCrossentropy:
    def __init__(self):
        self.activation = ActivationSoftmax()
        self.loss = CategoricalCrossEntropy()

    def forward(self, inputs, y_true):
        # compute output
        self.activation.forward(inputs)
        self.output = self.activation.output

        # compute loss
        return self.loss.calculate(self.output, y_true)

    def backward(self, dvalues, y_true):
        # number of samples
        samples = len(dvalues)

        # if labels are one-hot encoded, turn them
        # into discrete values
        if len(y_true.shape) == 2:
            y_true = np.argmax(y_true, axis=1)

        # compute gradient
        self.dinputs = dvalues.copy()
        self.dinputs[range(samples), y_true] -= 1

        # normalize
        self.dinputs = self.dinputs / samples

class ActivationSigmoid:
    def forward(self, inputs):
        self.inputs = inputs
        self.output = 1 / (1 + np.exp(-inputs))

    def backward(self, dvalues):
        self.dinputs = dvalues * (1 - self.output) * self.output


import numpy as np

def halfcos(N: int) -> np.ndarray:
    """
    Create a half-cosine function of length N samples.

    Parameters:
        N: Usually odd.
    Returns:
        h: discrete samples of the half-cosine
    """
    # The amplitude gives unit gain at zero frequency.
    h = np.cos((np.array(range(1, N+1))/(N+1) - 0.5) * np.pi)
    h = h / sum(h)
    return h

'''
Use the np.convolve function in a for loop to convolve a 15-sample half-cosine
with each row of the test image, Lighthouse.
https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.convolve.html

Observe the resulting image Xf and note the increased width and the gradual
fade to black at the edges, caused by conv assuming the signal is zero
outside the range of the input vectors.
'''

def convse(X: np.ndarray, h: np.ndarray) -> np.ndarray:
    """
    Filter rows of image X using filter h with symmetric extension of X.

    Parameters:
        X: Image matrix (Usually 256x256)
        h: Filter coefficients
    Returns:
        Y: Row - Filtered image

    PS: Need to apply `convse` twice to filter rows and columns.
    """
    r, c = X.shape
    m = len(h)
    m2 = m // 2
    if m % 2:
        X = np.pad(X, [(0, 0), (m2, m2)], mode='reflect')
    else:
        X = np.pad(X, [(0, 0), (m2, m2)], mode='symmetric')

    Y = np.zeros((r, c))
    # Loop for each term in h. This loop is the convolution.
    for i in range(m):
        Y = Y + h[i] * X[:, i:i+c]
    return Y


import os
import sys
import numpy
import matplotlib.animation
import matplotlib.pyplot as plt
import scipy.integrate

def E_0(n):
    return n + 0.5

def phi(N, x):
    coef = tuple(0 if i < N else 1 for i in range(N+1))
    return numpy.polynomial.hermite.hermval(x, c=coef) * numpy.exp(-(x**2) / 2) / (numpy.power(numpy.pi, 0.25) * numpy.sqrt(2**N * numpy.math.factorial(N)))

def calculate_H(size, lam, x):
    H = numpy.diag([E_0(n) for n in range(size)])

    Phi = [None for _ in range(size)]
    for i in range(size):
        Phi[i] = phi(i, x)

    for i in range(size):
        for j in range(size):
            H[i,j] += lam * numpy.trapz(Phi[i]*x*x*x*x*Phi[j], x)

    return H, numpy.array(Phi)

def psi(c, x):
    psi = numpy.zeros(len(x), dtype=complex)
    for i in range(len(c)):
        coef = tuple(0 if j < i else 1 for j in range(i+1))
        psi += c[i] / (numpy.power(numpy.pi, 0.25) * numpy.sqrt(2**i * numpy.math.factorial(i))) * \
            numpy.polynomial.hermite.hermval(x, c=coef) * numpy.exp(-(x**2) / 2)
    return psi

def calculate_psi(ncalc, nret, lam, x):
    H, Phi = calculate_H(ncalc, lam, x)
    eigval, eigvec = numpy.linalg.eigh(H)
    psis = []
    for i in range(nret):
        psis.append(psi(eigvec[:,i], x))
    return eigval[:nret], psis

def plot_energies(x, Es, psis, lam):
    fig = plt.figure(figsize=(16,9))
    plt.title("Excited eigenstates of anharmonic oscillator $V(x) = \\frac{{1}}{{2}}x^2 + \\lambda x^4$ for $\\lambda = {}$".format(numpy.round(lam, 2)), fontsize=18)

    plots = []
    for psi in psis:
        plots += plt.plot(x, numpy.abs(psi)**2, linewidth=2)

    plt.legend(plots, Es, title="$E$", loc="upper right")
    plt.grid(linestyle="dotted", alpha=0.5)
    plt.xlabel("$x$", fontsize=16)
    plt.ylabel("$||\\psi(x)||^2$", fontsize=16)

    fig.savefig("task1_lam={}.pdf".format(int(lam*10)), bbox_inches="tight")
    # plt.show()

def plot_per_lam(x, lam_to_Epsi):
    fig, axes = plt.subplots(2, 3, figsize=(16,9))
    fig.suptitle("Excited eigenstates of anharmonic oscillator $V(x) = \\frac{{1}}{{2}}x^2 + \\lambda x^4$")

    n = 0
    axes_to_plots = [[] for _ in range(6)]
    axes_to_energies = [[] for _ in range(6)]
    for lam in lam_to_Epsi:
        n = len(lam_to_Epsi[lam][1])
        for i in range(len(lam_to_Epsi[lam][0])):
            axes_to_plots[i] += axes[int(i/3), i%3].plot(x, numpy.abs(lam_to_Epsi[lam][1][i])**2, linewidth=0.5)
            axes_to_energies[i].append(lam_to_Epsi[lam][0][i])
            print(lam_to_Epsi[lam][0][i])

    print(n)
    for i in range(n):
        axes[int(i/3), i%3].set_title("$n$-th excited eigenstate for $n={}$".format(i))
        axes[int(i/3), i%3].set_xlabel("$x$")
        axes[int(i/3), i%3].set_ylabel("$||\\psi(x)||^2$")
        axes[int(i/3), i%3].grid(linestyle="dotted", alpha=0.5)
        axes[int(i/3), i%3].legend(axes_to_plots[i], numpy.round(axes_to_energies[i], 2), title="$E_{}$".format(i))

    fig.legend(axes_to_plots[0], numpy.round(sorted(lam_to_Epsi.keys()), 2), title="$\\lambda$", loc="right")
    fig.savefig("task1_states_per_n.pdf", bbox_inches="tight")

def task1():
    L = 5
    lams = [0.2*i for i in range(6)]
    ncalc = 16
    nret = 6
    h = 0.01
    x = numpy.linspace(-L, L, int(2*L/h) + 1)

    lam_to_Epsi = {}

    for lam in lams:
        print(lam)
        Es, psis = calculate_psi(ncalc, nret, lam, x)
        lam_to_Epsi[lam] = [Es, psis]
        plot_energies(x, Es, psis, lam)

    plot_per_lam(x, lam_to_Epsi)

def animate(x, states, filename, lam, h, interval_base=10):
    print("Rendering animation ...")
    fig, ax = plt.subplots()
    plt.suptitle("($\\lambda = {0}$)".format(lam))
    plt.xlabel(r"$x$")
    plt.ylabel(r"$|\psi|^2$")

    def animate_func(frame):
        print("{0} | {1}".format(len(states), frame))
        ax.clear()
        ax.set_ylim(bottom=0, top=1)
        ax.plot(x, numpy.abs(states[frame])**2/(h**2))

    animation = matplotlib.animation.FuncAnimation(fig, animate_func, frames=len(states), interval=interval_base)
    animation.save(filename+".mp4")

def plot_animation(x, lam_psits, lams, tau, h):
    axes_to_plots = [[] for _ in range(6)]
    ts = numpy.array([20*i for i in range(6)])
    alphas = numpy.linspace(0.1, 1, len(ts))

    fig, axes = plt.subplots(2,3, figsize=(16,9))
    fig.suptitle("Time evolution of anharmonic oscillator $V(x) = \\frac{{1}}{{2}} x^2 + \\lambda x^4$", fontsize=16)

    for i in range(len(lams)):
        for ti, t in enumerate(ts):
            axes_to_plots[i] += axes[int(i/3), i%3].plot(x, numpy.abs(lam_psits[i][t])**2 *(h**2), 'b-', alpha=alphas[ti])

        axes[int(i/3), i%3].set_title("$\\lambda={}$".format(numpy.round(lams[i], 2)))
        axes[int(i/3), i%3].set_xlabel("$x$")
        axes[int(i/3), i%3].set_ylabel("$||\\psi(x)||^2$")
        axes[int(i/3), i%3].set_ylim(bottom=0, top=1.4)
        axes[int(i/3), i%3].grid(linestyle="dotted", alpha=0.5)

    fig.legend(axes_to_plots[0], ts*tau, title="$t = n\\tau$", loc="right")
    fig.savefig("task2_timeevolution.pdf", bbox_inches="tight")

def task2():
    L = 5
    lams = [0.2*i for i in range(6)]
    ncalc = 15
    nret = 6
    h = 0.01
    x = numpy.linspace(-L, L, int(2*L/h) + 1)
    tau = 0.01
    t1 = 10
    ts = numpy.linspace(0, t1, int(t1/tau) + 1)

    psi0 = phi(0, x)
    lam_psits = []

    for lam in lams:
        print(lam)
        lam_psits.append([])
        Es, psis = calculate_psi(ncalc, nret, lam, x)

        for t in ts:
            lam_psits[-1].append(numpy.zeros(len(x), dtype=complex))
            for n in range(nret):
                lam_psits[-1][-1] += numpy.dot(psis[n], psi0) * numpy.exp(-1j * Es[n] * t) * psis[n]

        lam_psits[-1] = numpy.array(lam_psits[-1])
    # plt.plot(x, numpy.abs(lam_psits[0][0])**2)
    # plt.show()

    # animate(x, lam_psits[-1], "animacija", lams[-1], h)
    plot_animation(x, lam_psits, lams, tau, h)

if __name__ == "__main__":
    os.chdir("hw2_stationary-problem-and-spectral-methods/images/")

    # task1()
    task2()


import copy
import numpy as np

def rowmul(matrix, index, k):
    """
    Multiplies index row with k
    """
    matrix[index, :] = k * matrix[index, :]
    return matrix

def rowadd(matrix, index1, index2, k):
    """
    Adds the index1 row with index2 row which in turn is multiplied by k
    """
    matrix[index1, :] += k * matrix[index2, :]
    return matrix

def update_mat(mat, row):
    '''
    Put the pivots to the first line
    '''
    mat_this = abs(mat)
    max_index = np.argmax(mat_this[row:, row]) + row
    if max_index == row:
        return mat
    else:
        change = copy.deepcopy(mat[max_index, :])
        mat[max_index, :] = mat[row, :]
        mat[row, :] = change
    return mat

def rref(matrix):
    """
    Returns the reduced row echelon form of a Matrix.

    Examples
    ========

    >>>from factorization.matrixtools import rref
    >>>import numpy as np
    >>> a = np.array([[3,7,4],[2,4,5],[6,2,3]])
    >>> rref(a)

    array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

    """
    result_matrix = copy.deepcopy(matrix)
    result_matrix = result_matrix.astype(np.float)
    nrow, ncol = result_matrix.shape
    for i in range(min(nrow, ncol)):
        result_matrix = update_mat(result_matrix, i)
        if np.all(np.round(result_matrix[i, :], decimals=4) == 0):
            continue
        frist_nzero = np.where(np.round(result_matrix[i, :], decimals=4) != 0)[0][0]
        if result_matrix[i, frist_nzero] != 1:
            rowmul(result_matrix, i, 1 / result_matrix[i, frist_nzero])
        rows = [k for k in range(nrow)]
        rows.remove(i)
        for j in rows:
            if (np.round(result_matrix[j, frist_nzero], decimals=4) != 0):
                rowadd(result_matrix, j, i, -result_matrix[j, frist_nzero])
    return result_matrix

def rank(matrix):
    '''
    Return the rank of the matrix

    Examples
    ========

    >>>from factorization.matrixtools import rank
    >>>import numpy as np
    >>> a = np.array([[3,7,4],[2,4,5],[6,2,3]])
    >>> rank(a)

    3
    '''
    result_matrix = copy.deepcopy(matrix)
    rref_state = rref(result_matrix)
    rank_num = 0
    for i in range(rref_state.shape[0]):
        if np.any(np.round(rref_state[i, :], decimals=4) != 0):
            rank_num += 1
    return rank_num

class Mattools():
    '''
    Some basic tools of matrix , contain " rref , rank , columnspace and nullspace"
    '''

    def __init__(self, mat):
        self.mat = copy.deepcopy(mat)
        self.nrow, self.ncol = self.mat.shape
        self.stables = []
        self.pivots = []

    def rref(self):
        '''
        Returns the reduced row echelon form of a Matrix.

        Example
        ========

        >>>from factorization import Matrix
        >>>import numpy as np
        >>>a = np.array([[0,0,0],[3,0,-4],[4,11,-2]])
        >>>test_object = Matrix(a)
        >>>test_object.rank()

        array([[ 1.        ,  0.        , -1.33333333],
       [-0.        ,  1.        ,  0.3030303 ],
       [ 0.        ,  0.        ,  0.        ]])

        See also
        ========

        def rref(matrix)
        '''
        return rref(self.mat)

    def rank(self):
        '''
        Return the rank of the matrix

        Example
        ========

        >>>from factorization import Matrix
        >>>import numpy as np
        >>>a = np.array([[0,0,0],[3,0,-4],[4,11,-2]])
        >>>test_object = Matrix(a)
        >>>test_object.rank()

        2

        See also
        ========

        def rank(matrix)
        '''
        return rank(self.mat)

    def columnspace(self):
        '''
        columnspace is also 值空间

        Example
        ========

        >>>from factorization import Matrix
        >>>import numpy as np
        >>>a = np.array([[0,0,0],[3,0,-4],[4,11,-2]])
        >>>test_object = Matrix(a)
        >>>test_object.columnspace()

        array([[ 0.,  0.],
       [ 3.,  0.],
       [ 4., 11.]])
        '''
        if self.rank() == self.ncol:
            return self.mat
        pivots = []
        result_matrix = copy.deepcopy(self.mat)
        rref_state = rref(result_matrix)
        for i in range(rref_state.shape[0]):
            if np.any(np.round(rref_state[i, :], decimals=4) != 0):
                pivots.append(i)
        columspace_mat = np.zeros([self.nrow, len(pivots)])
        for i in range(len(pivots)):
            pivots_row = rref_state[pivots[i], :]
            for j in range(pivots_row.size):
                if pivots_row[j] == 1:
                    columspace_mat[:, i] = result_matrix[:, j]
                    continue
        return columspace_mat

    def nullspace(self):
        '''
        For nullspace of matrix

        Example
        ========

        >>>from factorization import Matrix
        >>>import numpy as np
        >>>a = np.array([[0,0,0],[3,0,-4],[4,11,-2]])
        >>>test_object = Matrix(a)
        >>>test_object.nullspace()

        array([[ 1.33333333],
       [-0.3030303 ],
       [ 1.        ]])
        '''
        if self.rank() == self.ncol:
            return np.zeros([self.ncol, 1])
        vars = [i for i in range(self.ncol)]
        result_matrix = copy.deepcopy(self.mat)
        rref_state = rref(result_matrix)
        for i in range(rref_state.shape[0]):
            if np.any(np.round(rref_state[i, :], decimals=4) != 0):
                self.pivots.append(i)
        for i in range(len(self.pivots)):
            pivots_row = rref_state[self.pivots[i], :]
            for j in range(pivots_row.size):
                if pivots_row[j] == 1:
                    self.stables.append(j)
                    vars.remove(j)
                    break
        nullspace_mat = np.zeros([self.ncol, self.ncol - len(self.pivots)])
        for i in range(len(self.pivots)):
            pivots_row = rref_state[self.pivots[i], :]
            for k in range(len(vars)):
                nullspace_mat[self.stables[i], k] = -pivots_row[vars[k]]
        for i in range(len(vars)):
            nullspace_mat[vars[i], i] = 1
        return nullspace_mat

if __name__ == "__main__":
    pass


import numpy as np
import scipy.sparse as sps
import scipy.sparse.linalg as spla
from scipy.special import *

def make_matrix_square_root_applier(A, check_error=True):
    A = A.tocsr()
    weights, poles, _ = matrix_inverse_square_root_rational_weights_and_poles(A)
    N = len(weights)

    AA = [A - poles[k]*sps.eye(A.shape[0]) for k in range(N)]
    AA_solvers = [spla.factorized(A) for A in AA]

    def apply_isqrtA(v):
        u = np.zeros(v.shape)
        for k in range(N):
            u = u + weights[k] * AA_solvers[k](v)
        return u

    def apply_sqrtA(v):
        return A * apply_isqrtA(v)

    if check_error:
        v = np.random.randn(A.shape[1])
        u1 = apply_sqrtA(apply_sqrtA(v))
        u2 = A * v
        sqrt_err = np.linalg.norm(u1-u2)/np.linalg.norm(u2)
        print('sqrt_err=', sqrt_err)

    return apply_sqrtA

def matrix_inverse_square_root_rational_weights_and_poles(A, tol=1e-8, N_max=30, verbose=False):
    # Computes the weights and poles for a rational approximation to the inverse square root of a
    # symmetric positive definite matrix.
    max_lambda = spla.eigsh(A, 1, return_eigenvectors=False, which='LM')[0]
    min_lambda = spla.eigsh(A, 1, return_eigenvectors=False, which='SM')[0]
    if verbose:
        print('min_lambda=', min_lambda, ', max_lambda=', max_lambda)

    xx = np.logspace(np.log10(min_lambda), np.log10(max_lambda), 1000)
    for N in range(1,N_max+1):
        weights, poles, rational_function = inverse_square_root_rational_weights_and_poles(min_lambda, max_lambda, N)
        yy = rational_function(xx)
        yy_true = 1./np.sqrt(xx)
        err = np.linalg.norm(yy_true - yy)/np.linalg.norm(yy_true)
        if verbose:
            print('N=', N, ', err=', err)
        if err < tol:
            break
    return weights, poles, rational_function

def inverse_square_root_rational_weights_and_poles(lower_limit_m, upper_limit_M, number_of_rational_terms_N):
    # Computes weights and poles for the rational approximation
    #   1/sqrt(z) = weights[0]/(z - poles[0]) + weights[1]/(z - poles[1]) + ... + weights[N]/(z - poles[N])
    # designed to be accurate on the positive interval [m,M].
    #
    # Adapted version of method 3 from:
    #   Hale, Nicholas, Nicholas J. Higham, and Lloyd N. Trefethen.
    #   "Computing A^α,\log(A), and related matrix functions by contour integrals."
    #   SIAM Journal on Numerical Analysis 46.5 (2008): 2505-2523.
    m = lower_limit_m
    M = upper_limit_M
    N = number_of_rational_terms_N
    k2 = m/M
    Kp = ellipk(1-k2)
    t = 1j * np.arange(0.5, N) * Kp/N
    sn, cn, dn, ph = ellipj(t.imag,1-k2)
    cn = 1./cn
    dn = dn * cn
    sn = 1j * sn * cn
    w = np.sqrt(m) * sn
    dzdt = cn * dn

    poles = (w**2).real
    weights = (2 * Kp * np.sqrt(m) / (np.pi*N)) * dzdt
    rational_function = lambda zz: np.dot(1. / (zz.reshape((-1,1)) - poles), weights)
    return weights, poles, rational_function


"""
Harris Corner Detection
functions:
cv2.
    cornerHarris()
    cornerSubPix()

corners - regions in image with large variation in intensity in all directions
detect by:
    find difference in intensity for a displacement of (u, v) in all directions
    E(u, v) = sum(wrt x,y) w(x, y) [I(x+u, y+v) - I(x, y)]^2
        w is window function, , I(x+u, y+v) shifted intensity, I(x, y) intensity
        window function either rect window or gaussian window (gives weights to underneath pixels)
have to maximize E(u, v) for corner detection
    -> have to maximize 2nd term
        apply taylor expansion, get

        E(u, v) ~= [u v] M [u v]'
        M = sum(wrt x, y) w(x, y) [I_x I_y] x [I_x; I_y]
        I_x and I_y are image derivs in x and y dirs, respectively
            can be found with cv2.Sobel()
After, they created a score (an eq'n) that determines if window contains corner or not
    R = det(M) - k(trace(M))^2
    det(M) = \lambda_1 * \lambda_2
    trace(M) = \lambda_1 + \lambda_2
    \lambda_1 & \lambda_2 are eigenvals of M
        values of eigenvals determine whether region is corner, edge, or flat
            when |R| small, when \lambda_1 & \lambda_2 small, region flat
            when R < 0, when \lambda_1 >> \lambda_2 or vv, region is edge
            when R large, when \lambda_1 & \lambda_2 large and \lambda_1 ~ \lambda_2, region is a corner
            see: http://docs.opencv.org/3.1.0/harris_region.jpg
Result of Harris corner detection: grayscale image with these scores
    thresholding for suitable gives corners of image
"""

# Harris Corner Detector in OpenCV
# function: cv2.cornerHarris()
# arguments:
    # img - input image; grayscale and float32 type
    # blockSize - size of nbhd considered for corner detection
    # ksize - aperture parameter of Sobel deriv used
    # k - Harris detector free parameter in eq'n

# ex.
import cv2
import numpy as np

filename = 'chessboard.png'
img = cv2.imread(filename)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2, 3, 0.04)

# result is dilated for marking the corners, not important
dst = cv2.dilate(dst, None)

# Threshold for an optimal value, it may vary depending on the image
img[dst>0.01*dst.max()] = [0, 0, 255]

cv2.imshow('dst', img)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows


import numpy as np
import sys, os

sys.path.append(os.pardir)
from dataset.mnist import load_mnist

# 损失函数 loss function 是表示神经网络性能的'恶劣程度'的指标
# 最有名的损失函数 均方误差 mean squared error

# 均方误差的实现
def mean_squared_error(y, t):
    return 0.5 * np.sum((y - t) ** 2)

t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
# 设 2 为正确解
y = np.array([0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0])
print(np.ndim(y))
print(y)
y = y.reshape(1, y.size)
print(y)
M = mean_squared_error(np.array(y), np.array(t))
print(M)

# 交叉熵误差 cross entropy error
def cross_entropy_error(y, t):
    delta = 1e-7  # .0000001
    return -np.sum(t * np.log(y + delta))

# mini-batch
# (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
# train_size = x_train.shape[0]
# batch_size = 10
# batch_mask = np.random.choice(train_size, batch_size)
# x_batch = x_train[batch_mask]
# t_batch = t_train[batch_mask]
#
# print(np.random.choice(6000, 10))

# mini-batch版交叉熵误差的实现
def batch_cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
    batch_size = y.shape[0]
    return -np.sum(t * np.log(y + 1e-7)) / batch_size

#
def batch_cross_entropy_error_normalize(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size

# 导数的实现
# 不好的实现 数值微分

def numerical_diff(f, x):
    h = 10e-50
    return (f(x + h) - f(x - h)) / (2 * h)

# 梯度的实现
def numerical_gradient(f, x):
    h = 1e-4  # 0.0001
    grad = np.zeros_like(x)  # 生成和x形状相同的数组

    for idx in range(x.size):
        tmp_val = x[idx]
        # f(x+h)的计算
        x[idx] = tmp_val + h
        fxh1 = f(x)

        # f(x-h)的计算
        x[idx] = tmp_val - h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2) / (2 * h)
        x[idx] = tmp_val  # 还原值
    return grad

def function_2(x):
    return x[0] ** 2 + x[1] ** 2

n1 = numerical_gradient(function_2, np.array([3.0, 4.0]))
n2 = numerical_gradient(function_2, np.array([0.0, 2.0]))
n3 = numerical_gradient(function_2, np.array([3.0, 0.0]))
print(n1, n2, n3)

# 梯度下降法
def gradient_descent(f, init_x, lr=0.01, step_num=100):
    x = init_x
    for i in range(step_num):
        grad = numerical_gradient(f, x)
        x -= lr * grad
    return x

init_x = np.array([-3.0, 4.0])
G = gradient_descent(function_2, init_x=init_x, lr=0.1, step_num=100)
print(G)

# 神经网络的梯度


import numpy as np

def unitStep(v):
	if v >= 0:
		return 1
	else:
		return 0

def perceptronModel(x, w, b):
	v = np.dot(w, x) + b
	y = unitStep(v)
	return y

# w1 = 1, w2 = 1, b = -1.5
def AND(x):
	w = np.array([1, 1])
	b = -1.5
	return perceptronModel(x, w, b)

test1 = np.array([0, 1])
test2 = np.array([1, 1])
test3 = np.array([0, 0])
test4 = np.array([1, 0])

print("AND({}, {}) = {}".format(0, 1, AND(test1)))
print("AND({}, {}) = {}".format(1, 1, AND(test2)))
print("AND({}, {}) = {}".format(0, 0, AND(test3)))
print("AND({}, {}) = {}".format(1, 0, AND(test4)))


"""
This python code demonstrates an edge-based active contour model as an application of the
Distance Regularized Level Set Evolution (DRLSE) formulation in the following paper:

  C. Li, C. Xu, C. Gui, M. D. Fox, "Distance Regularized Level Set Evolution and Its Application to Image Segmentation",
     IEEE Trans. Image Processing, vol. 19 (12), pp. 3243-3254, 2010.

Author: Ramesh Pramuditha Rathnayake
E-mail: rsoft.ramesh@gmail.com

Released Under MIT License
"""

import numpy as np
from scipy.ndimage import laplace

from lv_set.potential_func import SINGLE_WELL, DOUBLE_WELL

def drlse_edge(phi_0, g, lmda, mu, alfa, epsilon, timestep, iters, potential_function):  # Updated Level Set Function
    """

    :param phi_0: level set function to be updated by level set evolution
    :param g: edge indicator function
    :param lmda: weight of the weighted length term
    :param mu: weight of distance regularization term
    :param alfa: weight of the weighted area term
    :param epsilon: width of Dirac Delta function
    :param timestep: time step
    :param iters: number of iterations
    :param potential_function: choice of potential function in distance regularization term.
%              As mentioned in the above paper, two choices are provided: potentialFunction='single-well' or
%              potentialFunction='double-well', which correspond to the potential functions p1 (single-well)
%              and p2 (double-well), respectively.
    """
    phi = phi_0.copy()
    [vy, vx] = np.gradient(g)
    for k in range(iters):
        phi = neumann_bound_cond(phi)
        [phi_y, phi_x] = np.gradient(phi)
        s = np.sqrt(np.square(phi_x) + np.square(phi_y))
        delta = 1e-10
        n_x = phi_x / (s + delta)  # add a small positive number to avoid division by zero
        n_y = phi_y / (s + delta)
        curvature = div(n_x, n_y)

        if potential_function == SINGLE_WELL:
            dist_reg_term = laplace(phi, mode='nearest') - curvature  # compute distance regularization term in equation (13) with the single-well potential p1.
        elif potential_function == DOUBLE_WELL:
            dist_reg_term = dist_reg_p2(phi)  # compute the distance regularization term in eqaution (13) with the double-well potential p2.
        else:
            raise Exception('Error: Wrong choice of potential function. Please input the string "single-well" or "double-well" in the drlse_edge function.')
        dirac_phi = dirac(phi, epsilon)
        area_term = dirac_phi * g  # balloon/pressure force
        edge_term = dirac_phi * (vx * n_x + vy * n_y) + dirac_phi * g * curvature
        phi += timestep * (mu * dist_reg_term + lmda * edge_term + alfa * area_term)
    return phi

def dist_reg_p2(phi):
    """
        compute the distance regularization term with the double-well potential p2 in equation (16)
    """
    [phi_y, phi_x] = np.gradient(phi)
    s = np.sqrt(np.square(phi_x) + np.square(phi_y))
    a = (s >= 0) & (s <= 1)
    b = (s > 1)
    ps = a * np.sin(2 * np.pi * s) / (2 * np.pi) + b * (s - 1)  # compute first order derivative of the double-well potential p2 in equation (16)
    dps = ((ps != 0) * ps + (ps == 0)) / ((s != 0) * s + (s == 0))  # compute d_p(s)=p'(s)/s in equation (10). As s-->0, we have d_p(s)-->1 according to equation (18)
    return div(dps * phi_x - phi_x, dps * phi_y - phi_y) + laplace(phi, mode='nearest')

def div(nx: np.ndarray, ny: np.ndarray) -> np.ndarray:
    [_, nxx] = np.gradient(nx)
    [nyy, _] = np.gradient(ny)
    return nxx + nyy

def dirac(x: np.ndarray, sigma: np.ndarray) -> np.ndarray:
    f = (1 / 2 / sigma) * (1 + np.cos(np.pi * x / sigma))
    b = (x <= sigma) & (x >= -sigma)
    return f * b

def neumann_bound_cond(f):
    """
        Make a function satisfy Neumann boundary condition
    """
    g = f.copy()

    g[np.ix_([0, -1], [0, -1])] = g[np.ix_([2, -3], [2, -3])]
    g[np.ix_([0, -1]), 1:-1] = g[np.ix_([2, -3]), 1:-1]
    g[1:-1, np.ix_([0, -1])] = g[1:-1, np.ix_([2, -3])]
    return g


__all__ = ['mvee']
import math
import numpy as np
try:
    from scipy.spatial import ConvexHull
except ImportError:
    def _getConvexHull(points):
        return points
else:
    def _getConvexHull(points):
        hull = ConvexHull(points)
        return points[np.unique(hull.simplices)]

def mvee(points, tol=1.e-4, limits=10000):
    """
    Finds the minimum volume enclosing ellipsoid (MVEE) of a set of data points
    in the M-dimentional space.

    Parameters
    ----------
    points : (N, M) array_like
        A array of N points in the M-dimentional space. N must be larger than M.
    tol : float, optional
        Error in the solution with respect to the optimal value.
    limits : int, optional
        Maximal number of iteration.

    Returns
    -------
    A : (M,M) ndarray
        The matrix of the ellipse equation in the 'center form':
        (x-c)^{T} A^{-1} (x-c) = 1,
        where the eigenvalues of A are the squares of the semiaxes.
    c : (M,) ndarray
        The center of the ellipse.

    Notes
    -----
    This function is ported from the MATLAB routine
    ``Minimum Volume Enclosing Ellipsoid'' (see [1]_ and [2]_)
    by Nima Moshtagh (nima@seas.upenn.edu) at University of Pennsylvania.
    Note that the output matrix A here is different from the original MATLAB
    routine, where it returns A^{-1} instead.

    References
    ----------
    .. [1] http://www.mathworks.com/matlabcentral/fileexchange/9542-minimum-volume-enclosing-ellipsoid/content/MinVolEllipse.m
    .. [2] http://stackoverflow.com/questions/14016898/port-matlab-bounding-ellipsoid-code-to-python

"""
    P = _getConvexHull(points)
    N, d = P.shape
    if N <= d:
        raise ValueError("The number of points must be larger than the number of dimensions.")
    dp1_inv = 1./float(d+1)
    Q = np.vstack((P.T, np.ones(N)))
    err = tol + 1.
    u = np.ones(N)/float(N)
    while err > tol and limits > 0:
        X_inv = np.linalg.inv(np.einsum('ij,j,kj', Q, u, Q))
        M = np.einsum('ji,jk,ki->i', Q, X_inv, Q)
        j = np.argmax(M)
        step_size = (1.-d/(M[j]-1.))*dp1_inv
        u[j] -= 1.
        err = math.sqrt((u*u).sum())*math.fabs(step_size)
        u *= (1.-step_size)
        u[j] += 1.
        u /= u.sum()
        limits -= 1
    c = np.dot(u, P)
    A = (np.einsum('ji,j,jk', P, u, P) - np.outer(c,c)) * float(d)
    return A, c


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
A Port of some of the functionality of the "chebpade" function in the "chebfun" library.

Copyright 2017 by The University of Oxford and The Chebfun Developers.
All rights reserved. See http://www.chebfun.org/ for Chebfun information.

This file is part of Fieldosophy, a toolkit for random fields.

"""

import numpy as np
from scipy import linalg
from scipy import signal

# %% Define functions

def ClenshawLord( f, N, domain, m, n ):
    """
    Function for computing Clenshaw-Lord approximation of chebychev polynomial on -1,1

    A port of the function "chabpade" from the Matlab-library "chebfun".
    """

    # Acquire Chebyshev approximation of f
    chebPoly = np.polynomial.chebyshev.Chebyshev.interpolate(f, deg = N, domain = domain )

    # Get chebyshev coefficients
    c = chebPoly.coef

    # Zero pad if needed
    if c.size < m + 2*n:
        c = np.concatenate( (c, np.zeros(m+2*n-c.size)) )

    # Setup system of linear equations to solve for beta
    c[0] = 2*c[0]
    top = c[ np.abs( np.arange(m-n+1,m+1) ) ]
    bottom = c[ np.abs( np.arange(m,m+n) ) ]
    rhs = c[ np.arange(m+1,m+n+1) ]

    beta = np.array([1])
    if n > 0:
        beta = linalg.hankel(top, bottom)
        beta = linalg.solve( beta, rhs )
        beta = np.flipud( np.concatenate( (-beta , np.array([1])) ) )

    # Compute alpha
    l = np.max((m,n))
    c[0] = c[0]/2
    alpha = signal.convolve(c[:l+1], beta)
    alpha = alpha[:l+2]

    # Compute numerator polynomial
    pk = np.zeros( (m+1) )
    D = np.outer( alpha, beta )
    pk[0] = np.sum(D.diagonal())
    for k in range(m):
        pk[k+1] = np.sum( np.concatenate( ( D.diagonal(k+1), D.diagonal(-k-1) ) ) )

    # Compute denominator
    qk = np.zeros( (n+1) )
    qk[0] = np.dot(beta, beta)
    for k in range(n):
        u = beta[:-(k+1)]
        v = beta[(k+1):]
        qk[k+1] = np.dot(u,v)

    # # Normalize the coefficients
    pk = pk/qk[0]
    qk = 2*qk/qk[0]
    qk[0] = 1

    # Get coefficients of corresponding power series
    pk = np.polynomial.chebyshev.cheb2poly(pk)
    qk = np.polynomial.chebyshev.cheb2poly(qk)

    # Return polynomial objects
    pk = np.polynomial.polynomial.Polynomial( pk, domain = domain )
    qk = np.polynomial.polynomial.Polynomial( qk, domain = domain )

    return (pk, qk)


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

'''
This is a collection of functions implemented in python that replicate
their implementation in GrADS.
Content:
1. Centered Differences (cdifof)
2. Horizontal Divergence (hdivg)
3. Vertical component of the relative vorticity (hcurl)
4. Horizontal Advection (hadv)

Only requires Numpy.
'''

import numpy as np

def cdiff(scalar,axis=0):
    '''
    Performs the same as GrADS function cdiff()
    http://cola.gmu.edu/grads/gadoc/gradfunccdiff.html
    The scalar quantity must by 2D.
    The finite differences calculation ignores the borders, where np.nan is returned.
    '''
    # Check if 2D
    dimScalar=np.size(np.shape(scalar))
    if dimScalar != 2:
        print("Pystuff Error: scalar must have only 2 dimensions, but it has %d." %dimScalar)
        return

    # Length of each dimension
    lendim0=np.shape(scalar)[0]
    lendim1=np.shape(scalar)[1]

    # Initialize output var
    out=np.zeros(np.shape(scalar))
    out.fill(np.nan)

    # Centered finite differences
    for x in np.arange(1,lendim0-1):
        for y in np.arange(1,lendim1-1):
            if axis==0:
                out[x,y]=scalar[x+1,y]-scalar[x-1,y]
            elif axis==1:
                out[x,y]=scalar[x,y+1]-scalar[x,y-1]
            else:
                print("Pystuff Error: Invalid axis option. Must be either 0 or 1.")
                return
    return out

def hdivg(u,v,lat,lon):
    '''
    Calculates the horizontal divergence (du/dx+dv/dy) exactly like GrADS.
    lat and lon are 1D arrays.
    http://cola.gmu.edu/grads/gadoc/gradfunccdiff.html
    '''
    latv, lonv = np.meshgrid(lat, lon, indexing='ij')
    r  = 6.371*(10**6)
    dtr = np.pi/180
    dudx = cdiff(u, axis=1)/cdiff(lonv*dtr, axis=1)
    dvdy = cdiff(v*np.cos(latv*dtr), axis=0)/cdiff(latv*dtr, axis=0)
    out  = (dudx + dvdy)/(r*np.cos(latv*dtr))
    return out

def hcurl(u,v,lat,lon):
    '''
    Calculates the vertical component of the relative vorticity (dv/dx-du/dy) exactly like GrADS.
    lat and lon are 1D arrays.
    http://cola.gmu.edu/grads/gadoc/gradfunccdiff.html
    '''
    latv, lonv = np.meshgrid(lat, lon, indexing='ij')
    r  = 6.371*(10**6)
    dtr = np.pi/180
    dvdx = cdiff(v, axis=1)/cdiff(lonv*dtr, axis=1)
    dudy = cdiff(u*np.cos(latv*dtr), axis=0)/cdiff(latv*dtr, axis=0)
    out  = (dvdx - dudy)/(r*np.cos(latv*dtr))
    return out

def hadv(u,v,t,lat,lon):
    '''
    Calculates the advection of a scalar variable.
    lat and lon are 1D arrays.
    http://cola.gmu.edu/grads/gadoc/gradfunccdiff.html
    '''
    latv, lonv = np.meshgrid(lat, lon, indexing='ij')
    dtr = np.pi/180
    r   = 6.371*(10**6)
    dtx = cdiff (t, axis=1)
    dty = cdiff (t, axis=0)
    dx  = cdiff(lonv, axis=1)*dtr
    dy  = cdiff(latv, axis=0)*dtr
    out = -( (u*dtx)/(np.cos(latv*dtr)*dx) + v*dty/dy )/r
    return out


import numpy as np
import matplotlib.pyplot as plt

N = 100
D = 2

X = np.random.randn(N, D)
# center first 50 points at (-2, -2)
X[:50, :] = X[:50, :] - 2 * np.ones((50, D))
# center last 50 points at (2, 2)
X[50:, :] = X[50:, :] + 2 * np.ones((50, D))
# labels: first 50 = 0, last 50 = 1
T = np.array([0] * 50 + [1] * 50)

ones = np.array([[1] * N]).T
Xb = np.concatenate((ones, X), axis=1)

W = np.random.random(D + 1)
z = Xb.dot(W)

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

Y = sigmoid(z)

def cross_entropy(T, Y):
    E = 0
    for i in range(N):
        if T[i] == 1:
            E -= np.log(Y[i])
        else:
            E -= np.log(1 - Y[i])
    return E

print(cross_entropy(T, Y))

# Closed form
W = np.array([0, 4, 4])
z = Xb.dot(W)
Y = sigmoid(z)
print(cross_entropy(T, Y))

# y = -x
plt.scatter(X[:, 0], X[:, 1], c=T, s=100, alpha=0.5)
x_axis = np.linspace(-6, 6, 100)
y_axis = -x_axis
plt.plot(x_axis, y_axis)
plt.show()


import numpy as np
import editdistance

from numba import jit

#TODO add more

def makeLn(n):
    return lambda a, b: np.linalg.norm(a - b, ord=n)

def editDistance(a, b):
    return editdistance.eval(a, b)

@jit(nopython=True)
def earthMoverDistance(u, v):
    """
    Compute the first Wasserstein distance between two 1D distributions.
    :param u, v: (Array-like) Values observed in the (empirical) distribution.
    :return: (float) The computed distance between the distributions.
    """
    # Calculate the CDFs of u and v
    u_cumweights = np.concatenate((np.array([0.0]), np.cumsum(u)))
    u_cdf = u_cumweights / u_cumweights[-1]

    v_cumweights = np.concatenate((np.array([0.0]), np.cumsum(v)))
    v_cdf = v_cumweights / v_cumweights[-1]

    return np.sum(np.abs(u_cdf - v_cdf))


import numpy as np

# Piratiado: https://kaushikghose.wordpress.com/2013/10/24/computing-mutual-information-and-other-scary-things/

def calc_MI(X, Y, bins=100, sparse=False):
    if sparse:
        X = X.toarray()[0]
        Y = Y.toarray()[0]

    c_XY = np.histogram2d(X,Y,bins)[0]
    c_X = np.histogram(X,bins)[0]
    c_Y = np.histogram(Y,bins)[0]

    H_X = shan_entropy(c_X)
    H_Y = shan_entropy(c_Y)
    H_XY = shan_entropy(c_XY)

    MI = H_X + H_Y - H_XY
    return MI

def shan_entropy(c):
    c_normalized = c / float(np.sum(c))
    c_normalized = c_normalized[np.nonzero(c_normalized)]
    H = -sum(c_normalized* np.log2(c_normalized))
    return H


import numpy as np

# Cria um Vetor com a função array do NumPy.
v = np.array([2, 1])

# Tira a Magnitude do Vetor.
vMag = np.linalg.norm(v)
print("Magnitude (distância) do meu vetor {0} é {1}".format(v, vMag))


from numpy import array, cos
from benchmarks.benchmark import Benchmark

class Shubert(Benchmark):
    """dim: 2"""
    def __init__(self, lower=-10, upper=10, dimension=2):
        super(Shubert, self).__init__(lower, upper, dimension)

    def get_optimum(self):
        return array([[]]), -186.7309  # has 18 global minima. May be restricted to the square xi /in [-5.12, 5.12]

    @staticmethod
    def eval(sol):
        sum1 = 0
        sum2 = 0
        for i in range(1, 6):
            new1 = i * cos((i + 1) * sol[0] + i)
            new2 = i * cos((i + 1) * sol[1] + i)
            sum1 += new1
            sum2 += new2

        return sum1 * sum2


import numpy as np
from scipy.optimize import linprog

def wasserstein_distance(p, q, D):
    """Wasserstein-distance
    p.shape=[m], q.shape=[n], D.shape=[m, n]
    p.sum()=1, q.sum()=1, p∈[0,1], q∈[0,1]
    """
    A_eq = []
    for i in range(len(p)):
        A = np.zeros_like(D)
        A[i, :] = 1
        A_eq.append(A.reshape(-1))
    for i in range(len(q)):
        A = np.zeros_like(D)
        A[:, i] = 1
        A_eq.append(A.reshape(-1))
    A_eq = np.array(A_eq)
    b_eq = np.concatenate([p, q])
    D = D.reshape(-1)
    result = linprog(D, A_eq=A_eq[:-1], b_eq=b_eq[:-1])
    return result.fun

def word_mover_distance(x, y):
    """WMD（Word Mover's Distance）
    x.shape=[m,d], y.shape=[n,d]
    """
    p = np.ones(x.shape[0]) / x.shape[0]
    q = np.ones(y.shape[0]) / y.shape[0]
    D = np.sqrt(np.square(x[:, None] - y[None, :]).mean(axis=2))
    return wasserstein_distance(p, q, D)

def word_rotator_distance(x, y):
    """WRD（Word Rotator's Distance
    x.shape=[m,d], y.shape=[n,d]
    """
    x_norm = (x**2).sum(axis=1, keepdims=True)**0.5
    y_norm = (y**2).sum(axis=1, keepdims=True)**0.5
    p = x_norm[:, 0] / x_norm.sum()
    q = y_norm[:, 0] / y_norm.sum()
    D = 1 - np.dot(x / x_norm, (y / y_norm).T)
    return wasserstein_distance(p, q, D)

def word_rotator_similarity(x, y):
    """1 - WRD
    x.shape=[m,d], y.shape=[n,d]
    """
    return 1 - word_rotator_distance(x, y)


import numpy as np
import scipy

def truncNorm( a=0, b=1, mu=0, sigma=1, size=1 ):
    return scipy.stats.truncnorm.rvs( (a-mu)/sigma, (b-mu)/sigma, loc=mu, scale=sigma, size=size )

def truncNormCdf( x, a=0, b=1, mu=0, sigma=1 ):
    return scipy.stats.truncnorm.cdf( x, (a-mu)/sigma, (b-mu)/sigma, loc=mu, scale=sigma )

def truncNormPdf( x, a=0, b=1, mu=0, sigma=1 ):
    return scipy.stats.truncnorm.pdf( x, (a-mu)/sigma, (b-mu)/sigma, loc=mu, scale=sigma )

def truncPowerLawRVs( k, minX, maxX, size=1, skew='negative', algorithm='custom' ):
    if algorithm == 'custom':
        u = np.random.random( size )
        if skew == 'negative':
            vals = maxX - (maxX - minX)*np.power(1-u,1/(1-k))
        elif skew == 'positive':
            k = -k
            vals = np.power( (np.power(maxX,k+1) - np.power(minX,k+1))*u + np.power(minX,k+1), 1/(k+1) )
    elif algorithm == 'scipy':
        vals = scipy.stats.powerlaw.rvs( k+1, loc=minX, scale=(maxX-minX), size=size )

    return vals

def truncPowerLawPdf( x, k, minX, maxX ):
    if not isinstance(x,np.ndarray):
        x = np.array( x )

    pdf = np.zeros_like( x )
    pdf[x < minX] = 0
    pdf[x > maxX] = 0
    remaining = (x > minX ) & ( x < maxX )
    pdf[remaining] = np.power(1/(maxX-x[remaining]),k)

    return pdf

def truncPowerLawMean( k, minX, maxX ):
    m = maxX - ((1-k)/(2-k))*(maxX - minX)
    return m

def truncPowerLawVar( k, minX, maxX ):
    eDiff = maxX - minX
    secondmoment = (1 - k) * ( eDiff*eDiff/(3-k) + maxX*maxX/(1-k) - 2*maxX*eDiff/(2-k) )
    #eDiff = maxX
    #print( (1- k) * ( eDiff*eDiff/(3-k) + maxX*maxX/(1-k) - 2*maxX*eDiff/(2-k) )- truncPowerLawMean( k, 0, maxX )**2  )
    #print( maxX * maxX * (1 + (k-4)*(1-k)/((3-k)*(2-k))) - truncPowerLawMean( k, 0, maxX )**2 )
    return secondmoment - truncPowerLawMean( k, minX, maxX )**2


import numpy as np

def Normalization(raw_data):
    MAX = np.max(raw_data.ravel()).astype('float32')
    MIN = np.min(raw_data.ravel())
    new_data = (raw_data - MIN)/(MAX - MIN)- 0.5
    return new_data


import numpy
import scipy.io.wavfile
import matplotlib.pyplot as plot
from scipy.fftpack import dct

sample_rate, signal = scipy.io.wavfile.read('./1234.wav')  # File assumed to be in the same directory
#signal = signal[0:int(3.5 * sample_rate)]  # Keep the only first 3.5 seconds
Time = numpy.linspace(0, len(signal) / sample_rate, len(signal)) #Time axis

#--Pre-Emphasis--
pre_emphasis = 0.97 #typical values for the filter coefficient (α) are 0.95 or 0.97,
emphasized_signal = numpy.append(signal[0], signal[1:] - pre_emphasis * signal[:-1])

#--Framing--
#Typical frame sizes in speech processing range from 20 ms to 40 ms with 50% (+/-10%) overlap between consecutive frames.
frame_size = 0.025 #Popular setting 25 ms for the frame size
frame_stride = 0.01 #10 ms stride (15 ms overlap)

frame_length, frame_step = frame_size * sample_rate, frame_stride * sample_rate  # Convert from seconds to samples
signal_length = len(emphasized_signal)
frame_length = int(round(frame_length))
frame_step = int(round(frame_step))
num_frames = int(numpy.ceil(float(numpy.abs(signal_length - frame_length)) / frame_step))  # Make sure that we have at least 1 frame

pad_signal_length = num_frames * frame_step + frame_length
z = numpy.zeros((pad_signal_length - signal_length))
pad_signal = numpy.append(emphasized_signal, z) # Pad Signal to make sure that all frames have equal number of samples without truncating any samples from the original signal

indices = numpy.tile(numpy.arange(0, frame_length), (num_frames, 1)) + numpy.tile(numpy.arange(0, num_frames * frame_step, frame_step), (frame_length, 1)).T #construct array
frames = pad_signal[indices.astype(numpy.int32, copy=False)] #just for plotting
ham_frames = pad_signal[indices.astype(numpy.int32, copy=False)]

#--Apply Hamming Window--
ham_frames *= numpy.hamming(frame_length)
# frames *= 0.54 - 0.46 * numpy.cos((2 * numpy.pi * n) / (frame_length - 1))  # Explicit Implementation **

#Fourier-Transform and Power Spectrum
#We can now do an N-point FFT on each frame to calculate the frequency spectrum. aka Short-Time Fourier-Transform (STFT)
#NFFT = 256 #N is typically 256 or 512
NFFT = frame_length
mag_frames = numpy.absolute(numpy.fft.rfft(ham_frames, NFFT))  # Magnitude of the FFT
freq_scale = numpy.fft.rfftfreq(frame_length, 1./sample_rate)  # Frequency scale
pow_frames = ((1.0 / NFFT) * ((mag_frames) ** 2))  # Power Spectrum

#--Filter Banks--
nfilt = 40 #number of filter banks

low_freq_mel = 0
high_freq_mel = (2595 * numpy.log10(1 + (sample_rate / 2) / 700))  # Convert Hz to Mel
mel_points = numpy.linspace(low_freq_mel, high_freq_mel, nfilt + 2)  # Equally spaced in Mel scale
hz_points = (700 * (10**(mel_points / 2595) - 1))  # Convert Mel to Hz
bin = numpy.floor((NFFT + 1) * hz_points / sample_rate)

fbank = numpy.zeros((nfilt, int(numpy.floor(NFFT / 2 + 1))))
for m in range(1, nfilt + 1):
    f_m_minus = int(bin[m - 1])   # left
    f_m = int(bin[m])             # center
    f_m_plus = int(bin[m + 1])    # right

    for k in range(f_m_minus, f_m):
        fbank[m - 1, k] = (k - bin[m - 1]) / (bin[m] - bin[m - 1])
    for k in range(f_m, f_m_plus):
        fbank[m - 1, k] = (bin[m + 1] - k) / (bin[m + 1] - bin[m])
filter_banks = numpy.dot(pow_frames, fbank.T)
filter_banks = numpy.where(filter_banks == 0, numpy.finfo(float).eps, filter_banks)  # Numerical Stability
filter_banks = 20 * numpy.log10(filter_banks)  # dB

# -- Mel-frequency Cepstral Coefficients (MFCCs) --
num_ceps = 12 #Typically, for Automatic Speech Recognition (ASR), the resulting cepstral coefficients 2-13 are retained and the rest are discarded

mfcc = dct(filter_banks, type=2, axis=1, norm='ortho')[:, 1 : (num_ceps + 1)] # Keep 2-13 (num_ceps+1)

#One may apply sinusoidal liftering1 to the MFCCs to de-emphasize higher MFCCs
#(nframes, ncoeff) = mfcc.shape
#n = numpy.arange(ncoeff)
#lift = 1 + (cep_lifter / 2) * numpy.sin(numpy.pi * n / cep_lifter)
#mfcc *= lift  #*

#-- Print some details
print("Sound file duration " + str(len(signal) / sample_rate) + "(secs), " + str(len(signal)) + " samples")
print("Sampling rate " + str(sample_rate) + "Hz ("+ str(sample_rate) +" samples per sec)" )
print("-Framing-")
print("Frame length: " +str(frame_length) + " samples, " + str(round(frame_size*1000)) + 'ms')
print("Frame overlapp: " +str(round((frame_size-frame_stride)*1000)) + "ms")
print("No. of frames: " +str(num_frames))
print("-Filter Banks-")
print("No. of filter banks: " + str(nfilt) + " (spectogram array size)")
print("-MCC's-")
print("No. of coeffecients: " + str(num_ceps))

#-- Plots
plot.figure(1,[12, 6]) #plot 1st frame

plot.subplot(321)
plot.title("(1) Frame #1")
plot.xlabel("Time ")
plot.tight_layout(2)
plot.plot(frames[0])

plot.subplot(322)
plot.title("(2) Hamming applied")
plot.plot(ham_frames[0])

plot.subplot(323)
plot.title("(3) FFT spectrum")
plot.xlabel("Freq (Hz)")
plot.bar(freq_scale,mag_frames[0],freq_scale[1])

plot.subplot(324)
plot.title("(4) Power spectrum")
plot.xlabel("Freq (Hz)")
plot.bar(freq_scale,pow_frames[0],freq_scale[1])

plot.subplot(325)
plot.title("(5) Mel Filters applied ")
plot.xlabel("Freq (Hz)")
plot.bar(numpy.arange(freq_scale[-1]/nfilt,freq_scale[-1]+(freq_scale[-1]/nfilt),freq_scale[-1]/nfilt), filter_banks[0], (freq_scale[-1]/nfilt))

plot.subplot(326)
plot.title("(6) MFCC's ")
plot.xlabel(" Coefficient # ")
plot.bar(numpy.arange(1,num_ceps+1,1), mfcc[0], 1)

plot.figure(2, [12, 6])#plot full signal

plot.subplot(321)
plot.title("(1) Raw .wav signal")
plot.tight_layout(2)
plot.plot(Time,signal)

plot.subplot(322)
plot.title("(2) Pre-emphasised signal")
plot.plot(emphasized_signal)

plot.subplot(323)
plot.title("(3) FFT")
plot.imshow(mag_frames.T,plot.cm.jet, aspect='auto')
plot.yticks([0,50,100],[int(freq_scale[0]),int(freq_scale[50]),int(freq_scale[100])])
plot.gca().invert_yaxis()
plot.ylabel("Freq (Hz)")

plot.subplot(324)
plot.title("(4) Power Spectrum (periodogram) ")
plot.imshow(pow_frames.T,plot.cm.jet, aspect='auto')
plot.yticks([0,50,100],[int(freq_scale[0]),int(freq_scale[50]),int(freq_scale[100])])
plot.gca().invert_yaxis()
plot.ylabel("Freq (Hz)")

plot.subplot(325)
plot.title("(5) Mel Filter banks applied (spectogram)")
plot.imshow(filter_banks.T,plot.cm.jet, aspect='auto')
plot.yticks([0,int(nfilt/2),int(nfilt)],[int(freq_scale[0]),int(freq_scale[50]),int(freq_scale[100])])
plot.gca().invert_yaxis()
plot.ylabel("Freq (Hz)")
plot.xlabel("Time")

plot.subplot(326)
plot.title("(6) MFCC's")
plot.imshow(mfcc.T,plot.cm.jet, aspect='auto')
#plot.yticks([0,int(nfilt/2),int(nfilt)],[int(freq_scale[0]),int(freq_scale[50]),int(freq_scale[100])])
plot.gca().invert_yaxis()
plot.ylabel("MFCC Coeffecients")
plot.xlabel("Time")

plot.show()


from sklearn.metrics import mean_absolute_error as mae
import numpy as np

def smape(y_true, y_pred):
    return 200 * np.mean(np.abs((y_true - y_pred)) / (np.abs(y_true + y_pred)))

def mase(y_true, y_pred, y_pred_naive):
    naive_mae = mae(y_true, y_pred_naive)
    y_pred_mae = mae(y_true, y_pred)

    return y_pred_mae / naive_mae

def mues(y_true, y_pred):
    return np.mean(np.maximum(np.sign(y_true - y_pred), 0))

def moes(y_true, y_pred):
    return np.mean(np.maximum(np.sign(y_pred - y_true), 0))

def muas(y_true, y_pred):
    m = mues(y_true, y_pred)
    if m == 0:
        return 0
    else:
        return (1 / m) * np.mean(np.maximum(y_true - y_pred, 0) / np.abs(y_true))

def moas(y_true, y_pred):
    m = moes(y_true, y_pred)
    if m == 0:
        return 0
    else:
        return (1 / m) * np.mean(np.maximum(y_pred - y_true, 0) / np.abs(y_true))