import numpy as np

def flat_ind_so3(l, m, n):
    """
    The SO3 spectrum consists of matrices f_hat^l of size (2l+1, 2l+1) for l=0, ..., L_max.
    If we flatten these matrices and stack them, we get a big vector where the element f_hat^l_mn has a certain
     flat index. This function computes that index.

    The number of elements up to and including order L is
    N_L = sum_{l=0}^L (2l+1)^2 = 1/3 (2 L + 1) (2 L + 3) (L + 1)

    Element (l, m, n) has N_l elements before it from previous blocks, and in addition several elements in the current
    block. The number of elements in the current block, before (m, n) is determined as follows.
    First we associate with indices m and n (running from -l to l) with their zero-based index:
    m' = m + l
    n' = n + l
    The linear index of this pair (m', n') is
    i = m' * w + n'
    where w is the width of the matrix, i.e. w = 2l + 1

    The final index of (l, m, n) is N_L + i

    :param l, m, n: spectral indices
    :return: index of (l, m, n) in flat vector
    """
    assert np.abs(m) <= l
    assert np.abs(n) <= l

    if l == 0:
        return 0  # The N_L formula only works for l > 0, so we special case this

    L = l - 1
    N_L = ((2 * L + 1) * (2 * L + 3) * (L + 1)) // 3
    i = (m + l) * (2 * l + 1) + (n + l)
    return N_L + i

def flat_ind_zp_so3(l, m, n, b):
    """
    The SO3 spectrum consists of matrices f_hat^l of size (2l+1, 2l+1) for l=0, ..., L_max = b - 1.
    These can be stored in a zero-padded array A of shape (b, 2b, 2b) with axes l, m, n with zero padding around
     the center of the last two axes. If we flatten this array A we get a vector v of size 4b^3.
    This function gives the flat index in this array v corresponding to element (l, m, n)

    The zero-based 3D index of (l, m, n) in A is (l, b + m, b + n).
    The corresponding flat index is i = l * 4b^2 + (b + m) * 2b + b + n

    :param l, m, n: spectral indices
    :return: index of (l, m, n) in flat zero-padded vector
    """
    return l * 4 * (b ** 2) + (b + m) * 2 * b + b + n

def list_to_flat(f_hat_list):
    """
    A function on the SO(3) spectrum can be represented as:
     1. a list f_hat of matrices f_hat[l] of size (2l+1, 2l+1)
     2. a flat vector which is the concatenation of the flattened matrices
     3. a zero-padded tensor with axes l, m, n.

    This function converts 1 to 2.

    :param f_hat: a list of matrices
    :return: a flat vector
    """
    return np.hstack([a.flat for a in f_hat_list])

def num_spectral_coeffs_up_to_order(b):
    """
    The SO(3) spectrum consists of matrices of size (2l+1, 2l+1) for l=0, ..., b - 1.
    This function computes the number of elements in a spectrum up to (but excluding) b - 1.

    The number of elements up to and including order L is
    N_L = sum_{l=0}^L (2l+1)^2 = 1/3 (2 L + 1) (2 L + 3) (L + 1)

    :param b: bandwidth
    :return: the number of spectral coefficients
    """
    L_max = b - 1
    assert L_max >= 0
    return ((2 * L_max + 1) * (2 * L_max + 3) * (L_max + 1)) // 3

def flat_to_list(f_hat_flat, b):
    """
    A function on the SO(3) spectrum can be represented as:
     1. a list f_hat of matrices f_hat[l] of size (2l+1, 2l+1)
     2. a flat vector which is the concatenation of the flattened matrices
     3. a zero-padded tensor with axes l, m, n.

    This function converts 2 to 1.

    :param f_hat: a flat vector
    :return: a list of matrices
    """
    f_hat_list = []
    start = 0
    for l in range(b):
        f_hat_list.append(f_hat_flat[start:start + (2 * l + 1) ** 2].reshape(2 * l + 1, 2 * l + 1))
        start += (2 * l + 1) ** 2
    return f_hat_list


# coding:utf-8
#

import numpy as np
from scipy import stats

def calc_statistics(x):
    n = x.shape[0]  # 样本个数

    # 手动计算
    m = 0
    m2 = 0
    m3 = 0
    m4 = 0
    for t in x:
        m += t
        m2 += t*t
        m3 += t**3
        m4 += t**4
    m /= n
    m2 /= n
    m3 /= n
    m4 /= n

    mu = m
    sigma = np.sqrt(m2 - mu*mu)
    skew = (m3 - 3*mu*m2 + 2*mu**3) / sigma**3
    kurtosis = (m4 - 4*mu*m3 + 6*mu*mu*m2 - 4*mu**3*mu + mu**4) / sigma**4 - 3
    print('手动计算均值、标准差、偏度、峰度：', mu, sigma, skew, kurtosis)

def calc_statistics2(x):
    # 使用系统函数验证
    mu = np.mean(x, axis=0)
    sigma = np.std(x, axis=0)
    skew = stats.skew(x)
    kurtosis = stats.kurtosis(x)
    print('函数库计算均值、标准差、偏度、峰度：', mu, sigma, skew, kurtosis)

if __name__ == '__main__':
    d = np.random.randn(5)
    print(d)
    print(d.shape)
    calc_statistics(d)
    calc_statistics2(d)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function, division

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# https://en.wikipedia.org/wiki/B%C3%A9zier_curve
# https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-837-computer-graphics-fall-2012/lecture-notes/MIT6_837F12_Lec01.pdf
# https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-837-computer-graphics-fall-2012/lecture-notes/MIT6_837F12_Lec02.pdf

def linear_bezier(p0, p1, ts):

    tsm = 1-ts

    pts = p0[None,:]*tsm[:,None] \
            + p1[None,:]*ts[:,None]

    return pts

def quadratic_bezier(p0, p1, p2, ts):

    pts = p0[None,:]*((1-ts)*(1-ts))[:,None] \
            + p1[None,:]*2*((1-ts)*ts)[:,None] \
            + p2[None,:]*(ts*ts)[:,None]

    return pts

def cubic_bezier(p0, p1, p2, p3, ts):

    pts = p0[None,:]*((1-ts)**3)[:,None] \
            + p1[None,:]*3*(((1-ts)**2)*ts)[:,None] \
            + p2[None,:]*3*((1-ts)*(ts**2))[:,None] \
            + p3[None,:]*(ts**3)[:,None]

    return pts

def cubic_bezier_in_matrix_form(ptc, ts):

    '''
    pt - n x dim
    ts - 1d - [0 ... 1]
    '''

    G = ptc.T                                               # Geometry (control points)
    B = np.array([
        [ 1,-3, 3,-1],
        [ 0, 3,-6, 3],
        [ 0, 0, 3,-3],
        [ 0, 0, 0, 1]])                                     # Spline Basis - Bernstein
    T = np.vstack( (np.ones_like(ts), ts, ts**2, ts**3) )   # Power basis

    Q = np.dot(G,np.dot(B,T))                               # Q = GBT

    return Q.T

def cubic_bspline(ptc, ts):

    '''
    pt - 4 x dim
    ts - 1d - [0 ... 1]
    '''

    G = ptc.T                                               # Geometry (control points)
    B = np.array([
        [ 1,-3, 3,-1],
        [ 4, 0,-6, 3],
        [ 1, 3, 3,-3],
        [ 0, 0, 0, 1]])/6.0                                 # Spline Basis - Bernstein
    T = np.vstack( (np.ones_like(ts), ts, ts**2, ts**3) )   # Power basis

    Q = np.dot(G,np.dot(B,T))                               # Q = GBT

    return Q.T

def cubic_bsplines(ptc, ts):

    '''
    pt - n x dim
    ts - 1d - [0 ... 1]
    '''

    n_dim = ptc.shape[1]
    n_ts  = len(ts)

    B = np.array([
        [ 1,-3, 3,-1],
        [ 4, 0,-6, 3],
        [ 1, 3, 3,-3],
        [ 0, 0, 0, 1]])/6.0                                 # Spline Basis - Bernstein
    T = np.vstack( (np.ones_like(ts), ts, ts**2, ts**3) )   # Power basis

    nw = len(ptc)-3
    # print(nw)
    ps = []
    for i in range(nw):
        Gi = ptc[i:i+4].T                  # Geometry (control points)
        # print(Gi)
        Qi = np.dot(Gi,np.dot(B,T))      # Q = GBT  [ dim x 4]x[4x4]x[4xlen(ts)] ==> [dim x len(ts)]
        ps.append(Qi.T)

    return np.vstack(ps)

if __name__=='__main__':

    ts = np.linspace(0,1,100)

    ps = np.array([[0,1], [1,0]])
    #
    ptbz = linear_bezier(ps[0], ps[1], ts)

    plt.figure()
    ax = plt.subplot(1,1,1)
    ax.plot(ps[:,0], ps[:,1], 's-', label='control points')
    ax.plot(ptbz[:,0], ptbz[:,1], label='bezier curve')
    ax.axis('equal')
    ax.grid()
    ax.legend()

    ps = np.array([[0,1], [0.2,0], [1,0]])
    #
    ptbz = quadratic_bezier(ps[0], ps[1], ps[2], ts)

    plt.figure()
    ax = plt.subplot(1,1,1)
    ax.plot(ps[:,0], ps[:,1], 's-', label='control points')
    ax.plot(ptbz[:,0], ptbz[:,1], label='bezier curve')
    ax.axis('equal')
    ax.grid()
    ax.legend()

    ps = np.array([[0,1], [0.5,1], [0.5,0], [1,0]])
    #
    ptbz = cubic_bezier(ps[0], ps[1], ps[2], ps[3], ts)

    plt.figure()
    ax = plt.subplot(1,1,1)
    ax.plot(ps[:,0], ps[:,1], 's-', label='control points')
    ax.plot(ptbz[:,0], ptbz[:,1], label='bezier curve')
    ax.axis('equal')
    ax.grid()
    ax.legend()

    ps = np.array([[0,1], [0.5,1], [0.5,0], [1,0]])
    #
    ptbz = cubic_bezier_in_matrix_form(ps, ts)
    ptbs = cubic_bspline(ps, ts)

    plt.figure()
    ax = plt.subplot(1,1,1)
    ax.plot(ps[:,0], ps[:,1], 's-', label='control points')
    ax.plot(ptbz[:,0], ptbz[:,1], label='bezier curve')
    ax.plot(ptbs[:,0], ptbs[:,1], label='b-spline curve')
    ax.axis('equal')
    ax.grid()
    ax.legend()

    ps = np.array([
        [0,1],
        [0,1],
        [0.5,1],
        [0.5,0],
        [1,0],
        [1,0],
        # [2,1],
        # [3,0],
        # [4,1],
        # [4,1],
        ])
    #
    ptbs = cubic_bsplines(ps, ts)
    # print(ptbs)

    plt.figure()
    ax = plt.subplot(1,1,1)
    ax.plot(ps[:,0], ps[:,1], 's-', label='control points')
    # ax.plot(ptbz[:,0], ptbz[:,1], label='bezier curve')
    ax.plot(ptbs[:,0], ptbs[:,1], label='b-spline curve')
    ax.axis('equal')
    ax.grid()
    ax.legend()

    ''' show and close all together '''
    for i in plt.get_fignums():
        plt.figure(i).canvas.mpl_connect('close_event', lambda event: plt.close('all') )
    plt.show()


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

show_charts = False
save_path = '/Users/gustavoamarante/Dropbox/Aulas/QuantFin/figures/'

X, y = make_blobs(n_samples=1500, random_state=170)

y_pred2 = KMeans(n_clusters=2).fit_predict(X)
y_pred3 = KMeans(n_clusters=3).fit_predict(X)
y_pred4 = KMeans(n_clusters=4).fit_predict(X)
y_pred5 = KMeans(n_clusters=5).fit_predict(X)

fig, ax = plt.subplots(2, 2)
ax[0, 0].scatter(X[:, 0], X[:, 1], c=y_pred2)
ax[0, 0].set_title('$K=2$')

ax[0, 1].scatter(X[:, 0], X[:, 1], c=y_pred3)
ax[0, 1].set_title('$K=3$')

ax[1, 0].scatter(X[:, 0], X[:, 1], c=y_pred4)
ax[1, 0].set_title('$K=4$')

ax[1, 1].scatter(X[:, 0], X[:, 1], c=y_pred5)
ax[1, 1].set_title('$K=5$')

plt.suptitle('K-Means Clustering for Different Sizes')
plt.tight_layout()
plt.savefig(save_path + 'KMeans - Blobs - different sizes of K.pdf')

if show_charts:
    plt.show()

plt.close()

# Distorted Blobs
transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]
X_aniso = np.dot(X, transformation)

y_pred2 = KMeans(n_clusters=2).fit_predict(X_aniso)
y_pred3 = KMeans(n_clusters=3).fit_predict(X_aniso)
y_pred4 = KMeans(n_clusters=4).fit_predict(X_aniso)
y_pred5 = KMeans(n_clusters=5).fit_predict(X_aniso)

fig, ax = plt.subplots(2, 2)
ax[0, 0].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred2)
ax[0, 0].set_title('$K=2$')

ax[0, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred3)
ax[0, 1].set_title('$K=3$')

ax[1, 0].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred4)
ax[1, 0].set_title('$K=4$')

ax[1, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred5)
ax[1, 1].set_title('$K=5$')

plt.suptitle('K-Means Clustering for Different Sizes')
plt.tight_layout()
plt.savefig(save_path + 'KMeans - distorted Blobs - different sizes of K.pdf')

if True:
    plt.show()

plt.close()


import superimport

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
import os

np.random.seed(42)

# Generate Data
n = 9
var = 3
corr = .5

cov_mat = [[var, corr * var], [corr * var, var]]
X = np.random.multivariate_normal([0, 0], cov_mat, n)

# Project Data onto PCA line
subspace_dim = 1
pca = PCA(subspace_dim)
X_reconstr = pca.inverse_transform(pca.fit_transform(X))

# Create figure and save.
fig, ax = plt.subplots(figsize=(5, 5))

# Plot raw data
ax.scatter(X[:, 0], X[:, 1], marker='o', facecolor='none', edgecolor='red')
X_mean = np.mean(X, axis=0)
ax.scatter(X_mean[0], X_mean[1], facecolor='red')

# Plot PCA line
low_point = X_mean - 10 * pca.components_.reshape(-1)
high_point = X_mean + 10 * pca.components_.reshape(-1)
ax.plot([low_point[0], high_point[0]], [low_point[1], high_point[1]], color='magenta')
ax.set_ylim(-5, 5)
ax.set_xlim(-5, 5)

# Plot projected points
ax.scatter(X_reconstr[:, 0], X_reconstr[:, 1], marker='o', facecolor='none', edgecolor='teal')

# Plot projection lines
for (xi1, xi2), (xi1_rec, xi2_rec) in zip(X, X_reconstr):
    ax.plot([xi1, xi1_rec], [xi2, xi2_rec], color='blue')

# Save figure
figdir = "../figures"
#
def save_fig(fname):
    plt.savefig(os.path.join(figdir, fname))

save_fig("pcaDemo2dProjection.pdf")

plt.draw()


# -*- coding: utf-8 -*-#
'''
# Name:         CrossEntropy
# Description:  CrossEntropy 交叉熵
# Author:       super
# Date:         2020/5/7
'''

import numpy as np
import matplotlib.pyplot as plt

def target_function2(a,y):
    p1 = y * np.log(a)
    p2 = (1-y) * np.log(1-a)
    y = -p1 - p2
    return y

if __name__ == '__main__':
    err = 1e-2  # avoid invalid math caculation
    a = np.linspace(0+err,1-err)
    y = 0
    z1 = target_function2(a,y)
    y = 1
    z2 = target_function2(a,y)
    p1, = plt.plot(a,z1)
    p2, = plt.plot(a,z2)
    plt.grid()
    plt.legend([p1,p2],["y=0","y=1"])
    plt.xlabel("a")
    plt.ylabel("Loss")
    plt.show()


import numpy as np
import sys

sys.setrecursionlimit(10**6)

def knapsack1():
   f = open("knapsack1.txt","r")
   params = [line.rstrip('\n')  for line in f]
   f.close()

   Capacity = int(params[0].split()[0])
   Items = int(params[0].split()[1])
   #print(Capacity, Items)

   v = np.zeros(Items+1)
   w = np.zeros(Items+1)
   for i in range(1,len(params)):
    v[i] = int(params[i].split()[0])
    w[i] = int(params[i].split()[1])
   #print(v,w)

   A = np.zeros((Items+1,Capacity))
   #print(A[0][0])
   for i in range(1,Items+1):
    for x in range(0,Capacity):
      if w[i] > x:
        A[i][x] = A[i-1][x]
      else:
        A[i][x] = A[i-1][x]  if (A[i-1][x] > A[i-1][x-int(w[i])]+v[i]) else A[i-1][x-int(w[i])]+v[i]
    #print(A[i][x])

   return A[Items][Capacity-1]

def knapsack(N, W):
   global v
   global w

   if N == 1:
    return 0.0

   if table.get((N,W)) == None:
    max_val_1 = knapsack(N-1, W)
    if int(w[N]) > W:
     table[(N-1,W)] = max_val_1
     return max_val_1
    else:
     max_val_2 = knapsack(N-1, W-int(w[N])) + int(v[N])
     if max_val_1 > max_val_2:
      table[(N-1,W)] = max_val_1
      return max_val_1
     else:
      table[(N-1,W-int(w[N]))] = max_val_2 - int(v[N])
      return max_val_2
   else:
    return table[(N,W)]

def knapsack2():
   global v
   global w
   global table

   table = {}

   f = open("knapsack_big.txt","r")
   params = [line.rstrip('\n')  for line in f]
   f.close()

   Capacity = int(params[0].split()[0])
   Items = int(params[0].split()[1])

   v = np.zeros(Items+1)
   w = np.zeros(Items+1)
   for i in range(1,len(params)):
    v[i] = int(params[i].split()[0])
    w[i] = int(params[i].split()[1])

   max_val = knapsack(Items, Capacity)
   return max_val

print(knapsack1())
print (knapsack2())

#1 Hint: There is a counterexample with 4 items
   Hint: How do you know it's possible to group the chosen items into subsets S1,S2 into groups of sizes W1, W2
   Neither Algorithm is guaranteed to produce an optimal solution to the problem

#2 Hint: Are all the necessary subproblem solutions available for constant time look-up?
   Both algorithms are well-defined and correct after reversing the order of loops.

#3 2.18
#4 All options are correct

#5 Hint: How do you avoid keeping track of \Theta(n^2) subproblem solutions when computing an optimal binary search tree?
   Hint: By throwing away old subproblems that you won't ever need again, you can save space.
   Theta(1), Theta(n), Theta(n^2)


import numpy as np
import matplotlib.pyplot as plt

def f_x(x):
    return np.power(x + 2, 2) - 16 * np.exp(-np.power((x - 2), 2))

#Vejamos a sua forma no intervalo [-8, 8]
def main_plot():
    x = np.arange(-8, 8, 0.001)
    y = map(lambda u: f_x(u), x)
    plt.plot(x, list(y))
    plt.title('Cost function f(x)')

plt.grid(True)
main_plot()
plt.show()

def grad_f_x(x):
    return (2 * x - 4) - 16 * (-2 * x + 4) * np.exp(-np.power(x - 2, 2))

def gradient_descent(x0, func, grad):
    #
    precision = 0.001
    #Learning rate
    learning_rate = 0.0001
    #
    max_iter = 10000
    x_new = x0
    res = []
    for i in range(max_iter):
        x_old = x_new
        #Vamos usar B = 1
        x_new = x_old - learning_rate * grad(x_old)
        f_x_new = func(x_new)
        f_x_old = func(x_old)
        res.append([x_new, f_x_new])
        #print(f_x_new - f_x_old)
        if(abs (f_x_new - f_x_old) < precision):
            print("Precisao %f alcancada:" % (f_x_new - f_x_old))
            return np.array(res)
    print("Iteraccao maxima alcancada")
    return np.array(res)

x0 = -8
res = gradient_descent(x0, f_x, grad_f_x)
plt.plot(res[:,0], res[:, 1], '+')
main_plot()
plt.show()

X = np.arange(-10, 10, 1)
Y = np.arange(-10, 10, 1)
U, V = np.meshgrid(X, Y)

fig, ax = plt.subplots()
q = ax.quiver(X, Y, U, V)
ax.quiverkey(q, X=0.3, Y=1.1, U=20,label='Quiver key, length = 10', labelpos='E')

plt.show()

img = np.array([[88, 93, 42, 25, 36, 14, 59, 46, 77, 13, 52, 58],
       [43, 47, 40, 48, 23, 74, 12, 33, 58, 93, 87, 87],
       [54, 75, 79, 21, 15, 44, 51, 68, 28, 94, 78, 48],
       [57, 46, 14, 98, 43, 76, 86, 56, 86, 88, 96, 49],
       [52, 83, 13, 18, 40, 33, 11, 87, 38, 74, 23, 88],
       [81, 28, 86, 89, 16, 28, 66, 67, 80, 23, 95, 98],
       [46, 30, 18, 31, 73, 15, 90, 77, 71, 57, 61, 78],
       [33, 58, 20, 11, 80, 25, 96, 80, 27, 40, 66, 92],
       [13, 59, 77, 53, 91, 16, 47, 79, 33, 78, 25, 66],
       [22, 80, 40, 24, 17, 85, 20, 70, 81, 68, 50, 80]])


#import library we need
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')

#read our dataset
train = pd.read_csv('Data-Train.csv')
test = pd.read_csv('Data-Test.csv')

#change our dataset to matrix and transpose them
x_train = np.transpose(np.asmatrix(train['x']))
y_train = np.transpose(np.asmatrix(train['y']))

x_test = np.transpose(np.asmatrix(test['x']))
y_test = np.transpose(np.asmatrix(test['y']))

#add x0 to our data
ones = np.ones((x_train.shape[0],1))
x_new = np.append(ones, x_train, 1)

#creat our m , n  and theta fill with 1 (2*1)
m, n = np.shape(x_new)
theta = np.ones((1,n))
theta = np.transpose(theta)
theta_new = theta

#choose our iteration & Learning Rate

itr= 200
alpha = 0.00004

#calculate our Gradient Descent (Stochastic)
LSM = np.zeros((itr,2))
d = 0

while d < itr:
    for i in range(0, m):
        for j in range(0, n):
            theta_new[j] = theta[j] - (alpha * ((x_new[i]*theta - y_train[i])*x_new[i, j]))

        theta = theta_new

    y_pred = theta[0] + theta[1]*x_train.T

    Loop_LSM = 0
    for i in range(0, m):
        Loop_LSM += (y_train.A1[i] - y_pred.A1[i])**2
    Loop_LSM = Loop_LSM/(2*m)
    LSM[d,0] = d
    LSM[d,1] = Loop_LSM

    d += 1

print('Number of iteration : ',itr)
print('Learning Rate : ',alpha)
print('Theta[0] = ', theta[0])
print('Theta[1] = ', theta[1])

#calculate our h(theta) or y_predection for both data
y_pred_train = theta[0] + theta[1]*x_train.T

y_pred_test = theta[0] + theta[1]*x_test.T

#calculate our test data cost function
train_LSM = 0
m = y_train.shape[0]

for i in range(m):
    train_LSM += ((y_train.A1[i] - y_pred_train.A1[i])**2)
train_LSM = train_LSM/(2*m)

print("Train Least Squared Error : ", train_LSM)

#calculate our test data cost function
test_LSM = 0
m = y_test.shape[0]

for i in range(m):
    test_LSM += ((y_test.A1[i] - y_pred_test.A1[i])**2)
test_LSM = test_LSM/(2*m)

print("Test Least Squared Error : ", test_LSM)

#plot our data and Gradient
fig, plots = plt.subplots(2,2)
fig.suptitle(' Stochastic Gradient Descent')

plots[0,0].scatter(train['x'],train['y'],color = "green", s = 0.1, label = 'Train data')
plots[0,0].plot(x_train.T.A1, y_pred_train.A1, color = "black")
plots[0,0].set(xlabel='X', ylabel='Y')
plots[0,0].legend(loc = 'upper left')

plots[0,1].scatter(test['x'],test['y'],color = "red", s = 0.1, label = 'Test data')
plots[0,1].plot(x_train.T.A1, y_pred_train.A1, color = "black")
plots[0,1].set(xlabel='X')
plots[0,1].legend(loc = 'upper left')

plots[1,0].plot(LSM.T[0], LSM.T[1], color = "black")
plots[1,0].set(xlabel='Iteration', ylabel='LSM')
plots[1,0].legend(loc = 'upper left')

plt.show()

Linear Regression with Stochastic Gradient Descent/GD Stochastic.py


"""Symbolic Curvature Utilities

This module provides functions for computing components of various curvature-related
tensors, such as Christoffel symbols, Riemann Tensor, and Ricci Tensor. While the
sympy module does offer analogous functions in the sympy.diffgeom subpackage, there is
an obnoxious bug in that derivatives must be take with respect to coordinate functions
as opposed to the identical symbol. We remediate that shortcoming here, allowing for
maximal interoperability with the other sympy utilies for solving differential equations
and computing derivatives.
"""
import itertools

import sympy
from sympy import Derivative as D, Rational, Expr

from pystein import utilities
from pystein.metric import Metric

def christoffel_symbol_component(lam: int, mu: int, nu: int, metric: Metric) -> Expr:
	"""Compute a component of the Chrisoffel symbol for a particular metric corresponding to

		G_mn^l = 1/2 g^ms (p_m g_ns + p_n g_sm - p_s g_mn)

	Args:
		lam:
			int, Upper index of Christoffel symbol
		mu:
			int, lower left index of Christoffel symbol
		nu:
			int, lower right index of Christoffel symbol
		metric:
			Metric

	Returns:
		Expression of the G_mn^l
	"""
	M = metric.matrix
	I = metric.inverse.matrix
	coord_symbols = metric.coord_system.base_symbols()
	dim = len(coord_symbols)
	return Rational(1, 2) * sum([I[lam, sig] * (D(M[nu, sig], coord_symbols[mu]) +
												D(M[sig, mu], coord_symbols[nu]) -
												D(M[mu, nu], coord_symbols[sig])) for sig in range(dim)])

def riemann_tensor_component(rho: int, sig: int, mu: int, nu: int, metric: Metric, simplify_intermediate: bool = False) -> Expr:
	"""Compute a component of the Riemann Tensor for a particular metric corresponding to

		R^r_smn = p_m G_ns^r - p_n G_ms^r + G_ml^r G_ns^l - G_nl^r G_ms^l

	Args:
		rho:
			int, Upper index of the Riemann Tensor
		sig:
			int, lower left index of Riemann Tensor
		mu:
			int, lower middle index of Riemann Tensor
		nu:
			int, lower right index of Riemann Tensor
		metric:
			Metric

	Returns:
		Expression of the R^r_smn
	"""

	def G(l, m, n):
		"""Shorthand"""
		c = christoffel_symbol_component(l, m, n, metric)
		return sympy.simplify(c) if simplify_intermediate else c

	coord_symbols = metric.coord_system.base_symbols()
	dim = len(coord_symbols)
	return D(G(rho, nu, sig), coord_symbols[mu]) - \
		   D(G(rho, mu, sig), coord_symbols[nu]) + \
		   sum([G(rho, mu, lam) * G(lam, nu, sig) for lam in range(dim)]) - \
		   sum([G(rho, nu, lam) * G(lam, mu, sig) for lam in range(dim)])

def ricci_tensor_component(mu: int, nu: int, metric: Metric, simplify_intermediate: bool = False):
	"""Compute a component of the Ricci Tensor for a particular metric corresponding to

		R_mn = R_m^l_ln

	Args:
		mu:
			int, lower left index of Ricci Tensor
		nu:
			int, lower right index of Ricci Tensor
		metric:
			Metric

	Returns:
		Expression of the R_mn
	"""

	def R(r, s, m, n):
		"""Shorthand"""
		r = riemann_tensor_component(r, s, m, n, metric=metric, simplify_intermediate=simplify_intermediate)
		return sympy.simplify(r) if simplify_intermediate else r

	return sum([R(lam, mu, lam, nu) for lam in range(metric.coord_system.dim)])

def ricci_scalar(metric: Metric, simplify_intermediate: bool = False) -> Expr:
	"""Compute the Ricci Scalar for a particular metric corresponding to

		R = R^l_l = g^mn R_mn

	Args:
		metric:
			Metric

	Returns:
		Expression of R
	"""
	I = metric.inverse.matrix
	return sum(sum(I[lam, rho] * ricci_tensor_component(rho, lam, metric=metric, simplify_intermediate=simplify_intermediate) for rho in range(metric.coord_system.dim)) for lam in range(metric.coord_system.dim))

def einstein_tensor_component(mu: int, nu: int, metric: Metric):
	"""Compute a component of the Einstein Tensor for a particular metric corresponding to

		G_mn = R_mn - (1/2) R g_mn

	Args:
		mu:
			int, lower left index of Einstein Tensor
		nu:
			int, lower right index of Einstein Tensor
		metric:
			Metric

	Returns:
		Expression of the G_mn
	"""
	return ricci_tensor_component(mu, nu, metric) - Rational(1, 2) * ricci_scalar(metric) * metric.matrix[mu, nu]

def compute_components(metric: Metric, non_trivial: bool = True):
	N = len(metric.coord_system.base_symbols())
	christoffels = [((m, n, l), utilities.full_simplify(christoffel_symbol_component(l, m, n, metric=metric))) for l, m, n in itertools.product(range(N), range(N), range(N))]
	riemanns = [((m, n, r, s), utilities.full_simplify(riemann_tensor_component(r, s, m, n, metric=metric))) for m, n, r, s in
				itertools.product(range(N), range(N), range(N), range(N))]
	riccis = [((m, n), utilities.full_simplify(ricci_tensor_component(m, n, metric=metric))) for m, n in itertools.product(range(N), range(N))]

	if non_trivial:
		christoffels = [x for x in christoffels if x[1]]
		riemanns = [x for x in riemanns if x[1]]
		riccis = [x for x in riccis if x[1]]

	return christoffels, riemanns, riccis

def display_components(cps):
	label_names = ['\\mu', '\\nu', '\\rho', '\\sigma'][:len(cps)]
	exprs = [c[1] for c in cps]
	labels = [c[0] for c in cps]
	utilities.concat_latex(exprs, labels, label_names, display=True)


import sympy
import time

## From Bent: 2008_2 Computer Bonus
## Computer Bonus
##
## Find the smallest integer greater than 7 which has the property that
## the sum of all the integral divisors of its cube equals a perfect
## square. One and N are both divisors of N.
##
## -- Pierre de Fermat (circa 1650)
##
##

max_n = 1_000_000
solutions = []

t1=time.time()
for n in range(8,max_n+1):
    x=sympy.factorint(n*n*n)
    s=1
    for k in x:
        t=1
        for m in range(x[k]):
            t=k*t+1
        s=s*t
    # s = sum of the factors of the cube of n
    # Check to see if it is a perfect square
    c=round(s**(1/2))
    if c*c == s:
        print("Solution = ",n,"   Time = ",time.time()-t1)
        solutions.append(n)
t2=time.time()
print("Total elapsed time = ",t2-t1)
print("Largest value tested = ",max_n)
print("Number of solutions = ",len(solutions))
print("Solution set:")
print(solutions)


# numpy provide trigonometric ufunc sin(), cos(), tan()
# that takes values in radians and produce corresponding sin, cos, tan values
import numpy as np
x = np.sin(np.pi/2)            # np.sin function does operation sin() on values in array
print(x)

y = np.array([np.pi/2, np.pi/3, np.pi/4, np.pi/5])
z = np.sin(y)                  # putting whole array in sin() function
print(z)

a = np.array([360, 540, 720, 900])
b = np.deg2rad(a)                      # converting degree values to radian
print(b)

c = np.array([1, 2, 3, 4])
d = np.rad2deg(c)                      # converting radian values to degree
print(d)

e = np.array([1.0, 0.1, 1, -1])                     # converting sin, cos, tan values into radian values
f = np.arcsin(e)
print(f)

base = 3
perp = 4
h = np.hypot(base, perp)                     # finding hypotenuse length of pythagoras triangle
print(h)

Python/Numpy/numpy 41 - ufunc trigonometric function.py


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

''' The problem is: dy/dt = f(t,y).'''

def f(t, y):
    return 0.5*y

# a,b: edges of the interval, w0:ititial value, h:step
def PredictorCorrector(a, b, w0, h):
    n = ceil((b - a) / h)

    w, t = np.zeros(n+1), np.zeros(n+1)
    w[0], t[0] = w0, a

    for i in range(3):
        k1 = h * f(t[i], w[i])
        k2 = h * f(t[i] + h / 2, w[i] + k1 / 2)
        k3 = h * f(t[i] + h / 2, w[i] + k2 / 2)
        k4 = h * f(t[i] + h, w[i] + k3)
        w[i+1] = w[i] + 1 / 6 * (k1 + 2 * k2 + 2 * k3 + k4)
        t[i+1] = t[i] + h

    for i in range(3, n):
        #Predictor
        w[i+1] = w[i] + h/24*(55*f(t[i], w[i]) - 59*f(t[i-1], w[i-1]) + 37*f(t[i-2], w[i-2]) - 9*f(t[i-3], w[i-3]))
        #Corrector
        w[i+1] = w[i] + (h/24)*(9*f(t[i+1], w[i+1]) + 19*f(t[i], w[i]) - 5*f(t[i-1], w[i-1]) + f(t[i-2], w[i-2]))

        t[i+1] = t[i] + h

    return w, t

if __name__ == '__main__':

    a, b, w0, h = 0, 2, 1, 0.2

    print("\n", PredictorCorrector(a, b, w0, h)[0])

    # Visualization
    x = np.linspace(0, 2, 100)

    y = np.zeros(len(x))

    for j in range(len(x)):
        y[j] = exp(0.5*x[j])

    plt.plot(x, y, color="black", label="Solution")
    plt.plot(PredictorCorrector(a, b, w0, h)[1], PredictorCorrector(a, b, w0, h)[0], label="Predictor-Corrector")
    plt.xlabel("t")
    plt.ylabel("y")
    plt.legend()
    plt.show()


# requirements.txt:
# pyro 1.6.0
# torch 1.8.0

import numpy as np
import matplotlib.pyplot as plt

def rosenbrock(x,y):
    return (1-x)**2 + 100* (y-x*x)**2

def viz(xspace=(-30, 30, 100), yspace=(-300, 800, 100), trajectory=None):
    x = np.linspace(*xspace)
    y = np.linspace(*yspace)
    X, Y = np.meshgrid(x, y)
    Z = rosenbrock(X,Y)

    fig = plt.figure()
    ax = plt.axes(projection='3d')

    ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
                    cmap='viridis', edgecolor='none')
    if trajectory is not None:
        ax.scatter(*trajectory)
    plt.show()
viz()

# sanity check for the analytical solution.
epsilon = 1e-8
minimum = rosenbrock(np.array([1-epsilon,1,1+epsilon]),np.array([1-epsilon,1,1+epsilon]))
assert minimum[0] > minimum[1] and minimum[2] > minimum[1]

# SGD
def gradient_descent(x0=0, y0=0, lr=1e-3, n_step=int(1e4), momentum=0.0):
    import torch
    import torch.optim as optim
    x = torch.zeros([1]) + x0
    y = torch.zeros([1]) + y0
    x.requires_grad_(True)
    y.requires_grad_(True)

    optimizer = optim.SGD([x,y], lr=lr, momentum=momentum)
    ts = ([],[],[])
    for i in range(n_step):
        optimizer.zero_grad()
        z = rosenbrock(x,y)
        if i % 200==0:
            if i%1000==0:
                print(f"z = {z.detach().numpy()[0]}")
            ts[0].append(x.detach().numpy()[0])
            ts[1].append(y.detach().numpy()[0])
            ts[2].append(z.detach().numpy()[0])
        z.backward()
        # print(f"x = {x[0]} - {optimizer.param_groups[0]['lr']} * {x.grad[0]}")
        optimizer.step()
        # print(f" = {x[0]}")
        # print("")
    return x[0],y[0],ts

# routine gradient descent
x,y,ts = gradient_descent()
print(f"final result x={x:.3f}, y={y:.3f}")
viz( (0,1,100), (0,1,100), trajectory=ts)

# gradient descent with harder initialization, smaller learning rate, and momentum.
x,y,ts = gradient_descent(x0=3, y0=-2, lr=1e-5, momentum=0.99)
print(f"final result x={x:.3f}, y={y:.3f}")
viz( (0,3,100), (-2,5,100), trajectory=ts)


# -*- coding: utf-8 -*-
"""L04_Welliton.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1Z4mLm2egCuODcKhluqWbwYHbnOIjB_y7

**Welliton Leal - Aula de Exercícios 01**

***N-dimensional Arrays***
"""

import numpy as np #importa biblioteca e define atalho pra chama-la
lst = [[1, 2, 3], [4, 5, 6]] #cria lista com duas linhas
ary2d = np.array(lst)  #armazena em um vetor de 2 dimensões
ary2d

ary2d.dtype #exibe o tipo

"""***Array Construction Routines***"""

float32_ary = ary2d.astype(np.float32) #muda o tipo
float32_ary

float32_ary.dtype

ary2d.size #mostra tamanho

ary2d.ndim #mostra dimensão

ary2d.shape #mostra formato

np.array([1, 2, 3]).shape

np.ones((3, 3)) #matriz de 1's

np.zeros((3, 3)) #matriz de 0's

np.eye(3) #matriz ID

np.diag((3, 3, 3)) #matriz IDxEscalar

np.arange(4., 10.) #cria array com valores dentro do intervalo

np.arange(5) #cria array com valores de 0 até o valor

np.linspace(0., 1., num=5) #cria array no intervalo de 0 a 1 dividido em 5 partes = 1/5

"""***Array Indexing***"""

ary = np.array([1, 2, 3]) #exibe valor da pos 0
ary[0]

ary[:2] # equivalent to ary[0:2]

ary = np.array([[1, 2, 3],
... [4, 5, 6]])
ary[0, 0] #exibe valor na pos superior esquerda

ary[-1, -1] # exibe valor na pos inferior da direita

ary[0, 1] #exibe primeira linha segunda coluna

ary[0] # exibe primeira linha inteira

ary[:, 0] # exibe a primeira coluna inteira

ary[:, :2] #exibe as primeiras duas colunas

ary[0,0]

"""***Array Math and Universal Functions***"""

lst = [[1, 2, 3], [4, 5, 6]] #cria lista
for row_idx, row_val in enumerate(lst):
  for col_idx, col_val in enumerate(row_val):
    lst[row_idx][col_idx] += 1
lst

lst = [[1, 2, 3], [4, 5, 6]]
[[cell + 1 for cell in row] for row in lst]

ary = np.array([[1, 2, 3], [4, 5, 6]])
ary = np.add(ary, 1)
ary

ary + 1 #soma 1 em tudo

ary**2 #multiplica tudo por 2

ary = np.array([[1, 2, 3],
... [4, 5, 6]])
np.add.reduce(ary) #soma as colunas

np.add.reduce(ary, axis=1) #soma as linha

ary.sum(axis=0) #soma as colunas

ary.sum() #some todos os valores

"""***Broadcasting***"""

ary1 = np.array([1, 2, 3])
ary2 = np.array([4, 5, 6])
ary1 + ary2 #soma os 2 vetores valor a valor

ary3 = np.array([[4, 5, 6],
... [7, 8, 9]]) #definindo nova lista

ary3 + ary1 #soma ary1 + ary3

"""***Advanced Indexing – Memory Views and Copies***"""

ary = np.array([[1, 2, 3],
... [4, 5, 6]])
first_row = ary[0] #cria variável e armazena toda a primeira linha
first_row += 99 #soma 99 a a todos os valores
ary

ary = np.array([[1, 2, 3],
... [4, 5, 6]])
center_col = ary[:, 1] #recebe só a coluna do meio
center_col += 99 #soma a coluna do meio + 99
ary

ary = np.array([[1, 2, 3],
... [4, 5, 6]])
second_row = ary[1].copy()
second_row += 99
ary

ary = np.array([[1, 2, 3],
... [4, 5, 6]])
ary[:, [0, 2]] # first and and last column

ary[:, [2, 0]] # first and and last column

ary = np.array([[1, 2, 3],
... [4, 5, 6]])
greater3_mask = ary > 3 #retorna "true" pra valores maiores que 3
greater3_mask

ary[greater3_mask] #retorna os valores maiores que 3

ary[(ary > 3) & (ary % 2 == 0)] #maiores que 3 e divisíveis por 2

"""***Random Number Generators***"""

np.random.seed(123) #gerador de randomicos
np.random.rand(3) #quantidade de números

rng1 = np.random.RandomState(seed=123)
rng1.rand(3)

"""***Reshaping Arrays***"""

ary1d = np.array([1, 2, 3, 4, 5, 6])
ary2d_view = ary1d.reshape(2, 3)
ary2d_view

np.may_share_memory(ary2d_view, ary1d)

ary1d.reshape(2, -1)

ary1d.reshape(-1, 2)

ary = np.array([[[1, 2, 3],
... [4, 5, 6]]])

ary.reshape(-1)

ary = np.array([1, 2, 3])

# stack along the first axis
np.concatenate((ary, ary))

ary = np.array([[1, 2, 3]])

# stack along the first axis (here: rows)
np.concatenate((ary, ary), axis=0)

# stack along the second axis (here: column)
np.concatenate((ary, ary), axis=1)

"""***Comparison Operators and Masks***"""

ary = np.array([1, 2, 3, 4])
mask = ary > 2 #true para todos os masiores
mask

ary[mask] #todos que cumpriram a restrição

mask.sum() #qtd deles

np.where(ary > 2, 1, 0) # 1 para os que cumpriram a restrição

ary = np.array([1, 2, 3, 4])
mask = ary > 2
ary[mask] = 1
ary[~mask] = 0
ary

ary = np.array([1, 2, 3, 4])
(ary > 3) | (ary < 2) #retorna de acordo com a condição

~((ary > 3) | (ary < 2)) #retorna o contrário da condição, sua negação

"""*** Linear Algebra with NumPy Arrays***"""

row_vector = np.array([1, 2, 3])
row_vector

column_vector = np.array([[1, 2, 3]]).reshape(-1, 1)
column_vector

row_vector[:, np.newaxis]

row_vector[:, None]

matrix = np.array([[1, 2, 3],
... [4, 5, 6]])

np.matmul(matrix, column_vector)

np.matmul(matrix, row_vector)

np.matmul(row_vector, row_vector)

np.dot(row_vector, row_vector)

np.dot(matrix, row_vector)

np.dot(matrix, column_vector)

matrix = np.array([[1, 2, 3],
... [4, 5, 6]])

matrix.transpose()

np.matmul(matrix, matrix.transpose())

matrix.T

"""***Matplotlib***"""

# Commented out IPython magic to ensure Python compatibility.
# %matplotlib inline
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.show()

x = np.linspace(0, 10, 100)

plt.plot(x, np.sin(x))
plt.xlim([2, 8])
plt.ylim([0, 0.75])
plt.xlabel('x-axis')
plt.ylabel('y-axis')

x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x), label=('sin(x)'))
plt.plot(x, np.cos(x), label=('cos(x)'))
plt.ylabel('f(x)')
plt.xlabel('x')
plt.legend(loc='lower left')

"""*** Scatter Plots***"""

rng = np.random.RandomState(123)
x = rng.normal(size=500)
y = rng.normal(size=500)
plt.scatter(x, y)
plt.show()

"""***Bar Plots***"""

# input data
means = [1, 2, 3]
stddevs = [0.2, 0.4, 0.5]
bar_labels = ['bar 1', 'bar 2', 'bar 3']
# plot bars
x_pos = list(range(len(bar_labels)))
plt.bar(x_pos, means, yerr=stddevs)
plt.show()

"""***Histograms***"""

rng = np.random.RandomState(123)
x = rng.normal(0, 20, 1000)
# fixed bin size
bins = np.arange(-100, 100, 5) # fixed bin size
plt.hist(x, bins=bins)
plt.show()

rng = np.random.RandomState(123)
x1 = rng.normal(0, 20, 1000)
x2 = rng.normal(15, 10, 1000)
# fixed bin size
bins = np.arange(-100, 100, 5) # fixed bin size
plt.hist(x1, bins=bins, alpha=0.5)
plt.hist(x2, bins=bins, alpha=0.5)
plt.show()

"""***Subplots***"""

import matplotlib.pyplot as plt
x = range(11)
y = range(11)
fig, ax = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True)
for row in ax:
  for col in row:
    col.plot(x, y)
plt.show()

"""***Colors and Markers***"""

x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x),
color='orange',
marker='^',
linestyle='')
plt.show()

"""***Saving Plots***"""

x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.savefig('myplot.png', dpi=300)
plt.savefig('myplot.pdf')
plt.show()


# MSDS 400 Module 5 Practice 2

import numpy
from numpy import arange, cos
import matplotlib.pyplot
from matplotlib.pyplot import *

# A general function for calculating the slope between two points: x and
# x+delta.  See Lial Section 11.3 dealing with instantaneous rates of change.

def der(x,delta):
    delta = float(delta)
    if delta < (0.0000001):
        print ('Value chosen for delta is too small.')
        return 1/delta
    else:
        slope = (f(x + delta) - f(x))/delta
        return slope

# Define a function for demonstration.  This function may be changed.

def f(x):
    f = cos(x)
    return f

point = 1.0  #This is a point at which a derivative will be calculated.
# The following statements initialize variables for computation.

number = 510
increment =10
y = []
x = []

# What follows shows calculations and list manipulations. Recall that a range
# statement is inclusive of the first number and exclusive of the last.  In this
# example we are incrementing by units of 10 from 1 to 500.  We are reducing
# the distance between x=1.0 and x=1.0+delta by reducing delta.  The slopes
# being calculated are stored in the list y.

for k in range(increment, number, increment):
    delta = 1.0/(k+1)
    d = der(point,delta)
    x = x + [k]
    y = y + [d]
    max_x = k + increment

limit=der(point,0.000001)
print ('Final value equals', limit)

# The plot shows convergence of the slopes to the instantaneous rate of change.
# Black dots mark computed slopes as delta was reduced.  The x-axis is plotted
# using values of k from the range statement in the for loop.

figure()
xlim(0, max_x+50 )
ylim(min(y)-0.05, max(y)+0.05)

scatter(540,limit,color='g',s=40,label='limiting slope')
legend(('limiting slope'),loc='best')
scatter(x,y,c='k',s=20)

title ('Example of Convergence to Instanteous Rate of Change')
xlabel('x-axis')
ylabel('y-axis')
ylabel('y-axis')
plot(x,y)
show()

# The next section will show the tangent line at the point x=1.0.
# We are using the equation for a straight line y=mx+b where the slope is
# y[-1] from above and the point given above is x=1.0.  We are only going
# to plot this tangent line over a limited distance given by w defined below.

# Calculate values for the tangent.
w=arange(point-1.0,point+1.1,0.1)
t=f(point)+limit*(w-point)

# Now we are going to plot the original function over a wider range.
# Define a domain for the function.
domain=3.14

# Calculate values for the function on both sides of x=1.0.
u=arange(point-domain,point+domain+0.1,0.1)
z=f(u)

# This allows us to plot in layers showing the tangent and the function.
# The scatter command allows a single point to be plotted.
figure()
xlim(point-domain-.1,point+domain+0.1)
ylim(max(z)+.5,min(z)-.5)

plot(w,t,c='r')                        # This plots the tangent line.
plot(u,z,c='b')                        # This plots the curve itself.
scatter(point,f(point),c='g',s=40)     # This is the point of contact.
xlabel('x-axis')
ylabel('y-axis')
title('Plot showing function and tangent at a point')
show()

# Exercise #1:  Refer to Lial Section 11.3 Examples 3-5.  Using the function
# der() as defined, calculate approximate slopes for the functions given in
# Lial Section 11.3 Examples 3(b), 4(c), & 5.  Use a small value for delta and
# evaluate der() at the points used in the examples. Round to 4 decimal places.

# Exercise #2: Refer to Lial 11.1 Example 1.  This was used in Session 6
# Module1. The solution code is presented in the answer sheet.  Modify the code
# so that the tangent line at x=2 appears on the preceeding plot.  This
# necessitates determining the linear equation for the tangent line using
# y=mx+b and writing the statements to plot this line on the existing plot.
# Use arange().


# -*- coding: utf-8 -*-
"""
Auxiliary functions for interpolation

@author: Nicolas Guarin-Zapata
"""
from __future__ import division, print_function
import numpy as np
import matplotlib.pyplot as plt
from gauss_lobatto import gauss_lobatto

def vander_mat(x):
    """Vandermonde matrix for points in x"""
    n = len(x)
    van = np.zeros((n, n))
    power = np.array(range(n))
    for row in range(n):
        van[row, :] = x[row]**power
    return van

def conf_vander_mat(x):
    """Confluent Vandermonde matrix for points in x

    References
    ----------
    .. [1] Walter Gautschi (1962). On inverses of Vandermonde
        and confluent Vandermonde matrices. Numerische Mathematik, 4
        117-123.
    """

    n = len(x)
    conf_van = np.zeros((2*n, 2*n))
    power = np.array(range(2*n))
    for row in range(n):
        if x[row] == 0:
            conf_van[row, 0] = 1
            conf_van[row + n, 1] = 1
        else:
            conf_van[row, :] = x[row]**power
            conf_van[row + n, :] = power*x[row]**(power - 1)
    return conf_van

def inter_coef(x, inter_type="lagrange"):
    """Compute the coefficients for interpolation

    The desired interpolation is for the points x
    """
    if inter_type == "lagrange":
        vand_mat = vander_mat(x)
    elif inter_type == "hermite":
        vand_mat = conf_vander_mat(x)
    coef = np.linalg.solve(vand_mat, np.eye(vand_mat.shape[0]))
    return coef

def compute_interp(x, f, x_eval, df=None):
    """
    Compute the interpolation for points x_eval given by
    points x.

    If derivatives are given (df) it computes the
    Hermite interpolation for x_eval.
    """
    n = len(x)
    if df is None:
        coef = inter_coef(x, inter_type="lagrange")
    else:
        coef = inter_coef(x, inter_type="hermite")
    f_eval = np.zeros_like(x_eval)
    nmat = coef.shape[0]
    for row in range(nmat):
        for col in range(nmat):
            if col < n or nmat == n:
                f_eval += coef[row, col]*x_eval**row*f[col]
            else:
                f_eval += coef[row, col]*x_eval**row*df[col - n]
    return f_eval

if __name__ == "__main__":
    equispaced = False
    n = 11
    if equispaced:
        x = np.linspace(-1, 1, n)
    else:
        x, _ = gauss_lobatto(n)
    f = 1/(1 + 25*x**2)
    df = -50*x/(1 + 25*x**2)**2
    x_eval = np.linspace(-1, 1, 500)
    interp_f = compute_interp(x, f, x_eval, df=df)
    plt.plot(x_eval, 1/(1 + 25*x_eval**2))
    plt.plot(x_eval, interp_f)
    plt.plot(x, f, '.')
    plt.ylim(0, 2)
    plt.show()


import numpy as np

A=np.array([[4,12,-16],[12,37,-43],[-16,-43,98]])
x=np.array([1,-2,3])
b=A.dot(x)
print(b)

print(np.linalg.cholesky(A))

#Using Cholesky Fractorization for solving Linear Equation.
#Ax=b --> L.dot(L.transpose()).x=b
#Solving Ly=b
#After solving L.transpose().x=y
#Fast way for solving linear equation.
#A must be a positive definite matrix.

def CholeskyLinearEquation(A,b):
    #Find x with Ax=b
    L=np.linalg.cholesky(A)
    y=(np.linalg.inv(L)).dot(b)
    x=(np.linalg.inv(np.transpose(L))).dot(y)
    return x

c=np.array([-68,-191,364])
x=CholeskyLinearEquation(A,b)
print(x)


import matplotlib.pyplot as plt
import numpy as np

def laplace_pdf(x, b, μ):
    return (1 / (2 * b)) * np.e ** (-1 * (np.abs(x - μ) / b))

x = np.linspace(-10, 10, 10000)
y1 = [laplace_pdf(x_, 1, 0) for x_ in x]
y2 = [laplace_pdf(x_, 2, 0) for x_ in x]
y3 = [laplace_pdf(x_, 4, 0) for x_ in x]
y4 = [laplace_pdf(x_, 4, -5) for x_ in x]

plt.plot(x, y1, label="μ=0,b=1")
plt.plot(x, y2, label="μ=0,b=2")
plt.plot(x, y3, label="μ=0,b=4")
plt.plot(x, y4, label="μ=-5,b=4")

plt.title("Laplace pdf curves")
plt.legend()
plt.show()


import numpy as np

def spherical_to_cartesian(r, theta, phi, degrees=True):
    """
    Convert spherical coordinates (r, theta, phi) to cartesian (x, y, z).

    Parameters
    ----------
    r: (N,) ndarray
        Radial distance.
    theta: (N,) ndarray
        Azimuthal angle.
    phi: (N,) ndarray
        Polar angle.
    degrees: bool, optional
        If True, theta and phi will be assumed to be in degrees.

    Returns
    -------
    xyz: (N, 3) ndarray
        Corresponding cartesian coordinates.

    Notes
    -----
    Use notation of mathematical systems, NOT physics.
    """
    if degrees:
        theta = np.deg2rad(theta)
        phi = np.deg2rad(phi)

    sin_theta = np.sin(theta)
    cos_theta = np.cos(theta)
    sin_phi = np.sin(phi)
    cos_phi = np.cos(phi)

    xyz = np.empty((r.shape[0], 3), dtype=np.float32)

    xyz[:, 0] = r * sin_phi * cos_theta
    xyz[:, 1] = r * sin_phi * sin_theta
    xyz[:, 2] = r * cos_phi

    return xyz

def cartesian_to_spherical(xyz, degrees=True):
    """
    Convert cartesian coordinates (x, y, z) to spherical (r, theta, phi).

    Parameters
    ----------
    xyz: (N, 3) ndarray
        Corresponding cartesian coordinates.
    degrees: bool, optional
        If True, azimuthal and polar will be returned in degrees.

    Returns
    -------
    radius: (N,) ndarray
        Radial distance.
    inclination: (N,) ndarray
        Polar angle.
    azimuth: (N,) ndarray
        Azimuthal angle.
    """
    x = xyz[:, 0]
    y = xyz[:, 1]
    z = xyz[:, 2]

    radius = np.nan_to_num(np.sqrt((x * x) + (y * y) + (z * z)))

    inclination = np.nan_to_num(np.arccos(z / radius))

    azimuth = np.nan_to_num(np.arctan2(y, x))

    if degrees:
        inclination = np.rad2deg(inclination)
        azimuth = np.rad2deg(azimuth)

    return radius, inclination, azimuth

def cylindrical_to_cartesian(ro, phi, z, degrees=True):
    """
    Convert cylindrical coordinates (ro, phi, zeta) to cartesian (x, y, z).

    Parameters
    ----------
    ro: (N,) ndarray
        Radial distance.
    phi: (N,) ndarray
        Angular position.
    z: (N,) ndarray
        Altitude.
    degrees: bool, optional
        If True, angular will be assumed to be in degrees.

    Returns
    -------
    xyz: (N, 3) ndarray
        Corresponding cartesian coordinates.

    Notes
    -----
    The polar axis in the cylindrical system corresponds to the 'x' axis in the
    cartesian system.

    The longitudinal axis corresponds to the 'z' axis.
    """
    if degrees:
        phi = np.deg2rad(phi)

    sin_phi = np.sin(phi)
    cos_phi = np.cos(phi)

    xyz = np.empty((ro.shape[0], 3), dtype=np.float32)

    xyz[:, 0] = ro * cos_phi
    xyz[:, 1] = ro * sin_phi
    xyz[:, 2] = z

    return xyz

def cartesian_to_cylindrical(xyz, degrees=True):
    """
    Convert cartesian coordinates (x, y, z) to cylindrical (ro, phi, zeta).

    Parameters
    ----------
    xyz: (N, 3) ndarray
        Corresponding cartesian coordinates.
    degrees: bool, optional
        If True, azimuthal and polar will be returned in degrees.

    Returns
    -------
    radial_cylindrical: (N,) ndarray
        Radial distance.
    angular_cylindrical: (N,) ndarray
        Angular position.
    z: (N,) ndarray
        Altitude.

    Notes
    -----
    The polar axis in the cylindrical system corresponds to the 'x' axis in the
    cartesian system.

    The longitudinal axis corresponds to the 'z' axis.
    """
    x = xyz[:, 0]
    y = xyz[:, 1]
    z = xyz[:, 2]

    radial_cylindrical = np.nan_to_num(np.sqrt((x * x) + (y * y)))

    angular_cylindrical = np.nan_to_num(np.arctan2(y, x))

    if degrees:
        angular_cylindrical = np.rad2deg(angular_cylindrical)

    return radial_cylindrical, angular_cylindrical, z

def cylindrical_to_spherical(ro, phi, zeta, degrees=True, phi_is_inclination=True):
    """
    Convert cylindrical coordinates (ro, phi, zeta) to spherical (r, theta, phi).

    Parameters
    ----------
    ro: (N,) ndarray
        Radial distance.
    phi: (N,) ndarray
        Angular position.
    zeta: (N,) ndarray
        Altitude.
    degrees: bool, optional
        If True, azimuthal and polar will be returned in degrees.
    phi_is_inclination: bool, optional
        See https://en.wikipedia.org/wiki/Cylindrical_coordinate_system#Spherical_coordinates.

    Returns
    -------
    r: (N,) ndarray
        Radial distance.
    theta: (N,) ndarray
        Azimuthal angle.
    phi: (N,) ndarray
        Polar angle.
    """

    r = np.sqrt((ro * ro) + (zeta * zeta))

    theta = phi

    if phi_is_inclination:
        phi = np.arctan2(ro, zeta)
    else:
        phi = np.arctan2(zeta, ro)

    if degrees:
        phi = np.rad2deg(phi)

    return r, theta, phi

def spherical_to_cylindrical(r, theta, phi, degrees=True, phi_is_inclination=False):
    """
    Convert spherical coordinates (r, theta, phi) to cylindrical (ro, phi, zeta).

    Parameters
    ----------
    r: (N,) ndarray
        Radial distance.
    theta: (N,) ndarray
        Azimuthal angle.
    phi: (N,) ndarray
        Polar angle.
    degrees: bool, optional
        If True, azimuthal and polar will be returned in degrees.
    phi_is_inclination: bool, optional
        See https://en.wikipedia.org/wiki/Cylindrical_coordinate_system#Spherical_coordinates.

    Returns
    -------
    ro: (N,) ndarray
        Radial distance.
    phi: (N,) ndarray
        Angular position.
    z: (N,) ndarray
        Altitude.
    """
    if degrees:
        phi = np.deg2rad(phi)

    sin_phi = np.sin(phi)
    cos_phi = np.cos(phi)

    ro = r * sin_phi
    z = r * cos_phi

    phi = theta

    return ro, phi, z


import numpy as np
import tensorflow as tf

def cross_entropy_np(y_true, y_pred, epsilon=1e-12):
    """
    Cross entropy loss implementation with Numpy
    Args:
        y_true [ndarray]: Ground truth values (NxC).
                          N batch size, C number of classe.
        y_pred [ndarray]: The predicted values (NxC).
                          N batch size, C number of classe.
        epsilon: Defaults to 1e-12.

    Returns:
        loss: cross entropy
    """
    y_pred = np.clip(y_pred, epsilon, 1. - epsilon)
    N = y_pred.shape[0]
    ce = -np.sum(y_true * np.log(y_pred)) / N
    return ce

if __name__ == "__main__":
    # y_true = np.array([[0, 0, 0, 1],
    #                    [0, 0, 0, 1]])
    # y_pred = np.array([[0.25, 0.25, 0.25, 0.25],
    #                    [0.01, 0.01, 0.01, 0.96]])

    y_true = np.array([[0, 1, 0], [0, 0, 1]])
    y_pred = np.array([[0.05, 0.95, 0], [0.1, 0.8, 0.1]])

    cross_entropy_tf = tf.keras.losses.CategoricalCrossentropy()
    tf_ce = cross_entropy_tf(y_true, y_pred) # 1.177. Correct answer
    np_ce = cross_entropy_np(y_true, y_pred)

    print("Cross Entropy:")
    print("\tCorrect answer (tf): ", tf_ce.numpy())
    print("\tImplementation with Numpy: ", np_ce)

    ll_norm = tf.norm(tf_ce - np_ce, ord=1)
    assert ll_norm < 1e-5, "Cross Entropy calcuoation is wrong"
    print("Cross Entropy implementation is correct!")


import numpy as np

def minmax(
    train: np.ndarray,
    test: np.ndarray,
    min_value: float = 0,
    max_value: float = 1,
) -> tuple[np.ndarray, np.ndarray]:
    """
    Scale train and test feature arrays inpedendently for each feature
    by min and max values

    Args:
        train (np.ndarray): train feature array
        test (np.ndarray): test feature array
        min_value (float): chosen minimal feature value
        max_value (float): chosen maximal feature value
    Returns:
        tuple[np.ndarray, np.ndarray]: scaled train and test feature arrays

    """
    eps = 1e-12
    train_min = np.min(train, axis=0)
    train_max = np.max(train, axis=0)

    train_standardized = (train - train_min) / np.clip(train_max - train_min, eps, None)
    train_scaled = train_standardized * (max_value - min_value) + min_value

    test_standardized = (test - train_min) / np.clip(train_max - train_min, eps, None)
    test_scaled = test_standardized * (max_value - min_value) + min_value

    return train_scaled, test_scaled

def standard(train: np.ndarray, test: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
    """
    Standardize train and test feature arrays independently for each feature
    by mean and std

    Args:
        train (np.ndarray): train feature array
        test (np.ndarray): test feature array
        mean_value (float): chosen minimal feature value
        std_value (float): chosen maximal feature value
    Returns:
        tuple[np.ndarray, np.ndarray]: scaled train and test feature arrays

    """
    eps = 1e-12
    train_mean = np.mean(train, axis=0)
    train_std = np.std(train, axis=0)

    train_standardized = (train - train_mean) / np.clip(train_std, eps, None)
    test_standardized = (test - train_mean) / np.clip(train_std, eps, None)

    return train_standardized, test_standardized


# Exercise_1
# Perform the necessary imports
from scipy.cluster.hierarchy import linkage, dendrogram
import matplotlib.pyplot as plt

# Calculate the linkage: mergings
mergings = linkage(samples, method='complete')

# Plot the dendrogram, using varieties as labels
dendrogram(mergings ,
           labels=varieties,
           leaf_rotation=90,
           leaf_font_size=6,
)
plt.show()

--------------------------------------------------
# Exercise_2
# Import normalize
from sklearn.preprocessing import normalize

# Normalize the movements: normalized_movements
normalized_movements = normalize(movements)

# Calculate the linkage: mergings
mergings = linkage(normalized_movements,method='complete' )

# Plot the dendrogram
dendrogram(mergings,
            labels=companies,
            leaf_rotation=90,
            leaf_font_size=6)

plt.show()

--------------------------------------------------
# Exercise_3
# Perform the necessary imports
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import linkage, dendrogram

# Calculate the linkage: mergings
mergings = linkage(samples, method='single')

# Plot the dendrogram
dendrogram(mergings,
        labels=country_names,
        leaf_rotation=90,
        leaf_font_size=6)
plt.show()

--------------------------------------------------
# Exercise_4
# Perform the necessary imports
import pandas as pd
from scipy.cluster.hierarchy import fcluster

# Use fcluster to extract labels: labels
labels = fcluster(mergings, 6,criterion='distance', )

# Create a DataFrame with labels and varieties as columns: df
df = pd.DataFrame({'labels': labels, 'varieties': varieties})

# Create crosstab: ct
ct =  pd.crosstab(df['labels'], df['varieties'])

# Display ct
print(ct)

--------------------------------------------------
# Exercise_5
# Import TSNE
from sklearn.manifold import TSNE

# Create a TSNE instance: model
model = TSNE(learning_rate=200)

# Apply fit_transform to samples: tsne_features
tsne_features = model.fit_transform(samples)

# Select the 0th feature: xs
xs = tsne_features[:,0]

# Select the 1st feature: ys
ys = tsne_features[:,1]

# Scatter plot, coloring by variety_numbers
plt.scatter(xs, ys,c=variety_numbers )
plt.show()

--------------------------------------------------
# Exercise_6
# Import TSNE
from sklearn.manifold import TSNE

# Create a TSNE instance: model
model = TSNE(learning_rate=50)

# Apply fit_transform to normalized_movements: tsne_features
tsne_features = model.fit_transform(normalized_movements)

# Select the 0th feature: xs
xs = tsne_features[:,0]

# Select the 1th feature: ys
ys = tsne_features[:,1]

# Scatter plot
plt.scatter(xs, ys, alpha=0.5)

# Annotate the points
for x, y, company in zip(xs, ys, companies):
    plt.annotate(company, (x, y), fontsize=5, alpha=0.75)
plt.show()

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

Machine Learning Scientist with Python Track/2. Unsupervised Learning in Python/ch2_exercises.py


#!/usr/bin/evn python

import numpy as np
import scipy.linalg
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

# !!! copyright to https://gist.github.com/amroamroamro/1db8d69b4b65e8bc66a6

def estimateTiltingPlane(points, points2interp = [], bounds = [], res = 100, order = 1, return_RMSE = False):
    """
    Method to estimate a tilting plane based on a set of points

    Args:
        points: (Required) n x 3 numpy array with the x, y and z coordinates of known points
        points2interp: (Optional, defaults to []) n x 2 numpy array with points to interpolate
        bounds: (Optional, defaults to []) list with xmin, xmax, ymin and ymax
        resolution: (Optional, defaults to 100) resolution of the output points
        order: (Optional, defaults to 1) 1 or 2 indicating whether to fit a linear or quadratic plane
        return_RMSE: (Optional, defaults to False) True/False to return the RMSE as well
    """

    if len(points2interp) == 0:
        if len(bounds) == 4:
            xmin, xmax, ymin, ymax = bounds
        else:
            xmin = np.min(points[:,0])
            xmax = np.max(points[:,0])
            ymin = np.min(points[:,1])
            ymax = np.max(points[:,1])

        # regular grid covering the domain of the data
        X,Y = np.meshgrid(np.arange(xmin, xmax, res), np.arange(ymin, ymax, res))
        XX = X.flatten()
        YY = Y.flatten()
    else:
        X, Y = points2interp[:,0], points2interp[:,1]
        XX, YY = points2interp[:,0], points2interp[:,1]

    data = points

    if order == 1:
        # best-fit linear plane
        A = np.c_[data[:,0], data[:,1], np.ones(data.shape[0])]
        C,residues,_,_ = scipy.linalg.lstsq(A, data[:,2])    # coefficients

        # evaluate it on grid
        Z = C[0]*X + C[1]*Y + C[2]

    elif order == 2:
        # best-fit quadratic curve
        A = np.c_[np.ones(data.shape[0]), data[:,:2], np.prod(data[:,:2], axis=1), data[:,:2]**2]
        C,residues,_,_ = scipy.linalg.lstsq(A, data[:,2])

        # evaluate it on a grid
        Z = np.dot(np.c_[np.ones(XX.shape), XX, YY, XX*YY, XX**2, YY**2], C).reshape(X.shape)

    if return_RMSE:
        # calculate root mean square error
        RMSE = residues
        return [XX, YY, Z.flatten()], RMSE
    else:
        return [XX, YY, Z.flatten()]


import numpy as np

from scipy import stats

class Statistics:
    @staticmethod
    def getNumAnalyzedSamples(samples):
        return len(samples)

    @staticmethod
    def getMin(samples):
        return np.min(samples)

    @staticmethod
    def getMax(samples):
        return np.max(samples)

    @staticmethod
    def getMean(samples):
        return np.mean(samples)

    @staticmethod
    def getPercentile(samples, percentage):
        # Based on #10 (Plotly's implementation): http://jse.amstat.org/v14n3/langford.html
        sorted_samples = np.sort(samples)

        norm_percentage = percentage / 100.0

        # From #10: n * p + 0.5, we substract 1 because array indexing starts from 0
        percentile_pos     = (Statistics.getNumAnalyzedSamples(samples) * norm_percentage + 0.5) - 1
        percentile_pos_int = int(percentile_pos)

        if percentile_pos.is_integer():
            return sorted_samples[percentile_pos_int]

        percentile_pos_decimal_part = percentile_pos - percentile_pos_int

        percentile = sorted_samples[percentile_pos_int] + percentile_pos_decimal_part * (sorted_samples[percentile_pos_int + 1] - sorted_samples[percentile_pos_int])

        return percentile

    @staticmethod
    def getIQR(samples):
        q1 = Statistics.getPercentile(samples, 25)
        q3 = Statistics.getPercentile(samples, 75)

        iqr = q3 - q1

        return iqr

    @staticmethod
    def getTukeyFences(samples, sensitivity=1.5):
        # Tukey's fences for outliers detection
        q1 = Statistics.getPercentile(samples, 25)
        q3 = Statistics.getPercentile(samples, 75)

        iqr = q3 - q1

        lower_fence = q1 - sensitivity * iqr
        upper_fence = q3 + sensitivity * iqr

        return lower_fence, upper_fence

    @staticmethod
    def getVariance(samples, ddof=0):
        # delta degrees of freedom: Plotly uses 0, for unbiased variance set to: 1
        variance = np.var(samples, ddof=ddof)

        return variance

    @staticmethod
    def getStdDev(samples, ddof=0):
        # delta degrees of freedom: Plotly uses 0, for unbiased variance set to: 1
        std_dev = np.std(samples, ddof=ddof)

        return std_dev

    @staticmethod
    def getStdErr(samples):
        return Statistics.getStdDev(samples) / np.sqrt(Statistics.getNumAnalyzedSamples(samples));

    @staticmethod
    def getMargin(samples, confidence_level=0.999):
        _, z_level = stats.t.interval(confidence_level, Statistics.getNumAnalyzedSamples(samples) - 1)
        std_err    = Statistics.getStdErr(samples)

        margin = z_level * std_err

        return margin

    @staticmethod
    def getConfidenceInterval(samples, confidence_level=0.999):
        mean   = Statistics.getMean(samples)
        margin = Statistics.getMargin(samples, confidence_level)

        lower = mean - margin
        upper = mean + margin

        return {"ci_lower": lower, "ci_upper": upper, "ci_level": confidence_level * 100.0}

    @staticmethod
    def getSkewness(samples):
        return stats.skew(samples)

    @staticmethod
    def getKurtosis(samples):
        return stats.kurtosis(samples, fisher=False)


from Tests00Data import *
from scipy import stats
import statistics
import timeit

# https://docs.python.org/3/library/statistics.html
# https://docs.scipy.org/doc/scipy/reference/stats.html

print ("==================================================================================")
# Arrange
start = timeit.default_timer()
# Act
mode = "multi modal"
try:
    mode = statistics.mode(data)
except statistics.StatisticsError:
    print ("No unique mode found")
end = timeit.default_timer()
# Assert
print ("mode                          = ", mode)
print (u"              time [\u00B5s] = ", (end - start) * 100000)
#assert(mean_arithmetic == 3.8)
print ("==================================================================================")

print ("==================================================================================")
# Arrange
start = timeit.default_timer()
# Act
skewness = stats.skew(data)
end = timeit.default_timer()
# Assert
print ("skewness                      = ", skewness)
print (u"              time [\u00B5s] = ", (end - start) * 100000)
#assert(mean_arithmetic == 3.8)
print ("==================================================================================")

print ("==================================================================================")
# Arrange
start = timeit.default_timer()
# Act
kurtosis = stats.kurtosis(data)
end = timeit.default_timer()
# Assert
print ("kurtosis                      = ", kurtosis)
print (u"              time [\u00B5s] = ", (end - start) * 100000)
#assert(mean_arithmetic == 3.8)
print ("==================================================================================")

print ("==================================================================================")
# Arrange
start = timeit.default_timer()
# Act
cumfreq = stats.cumfreq(data)
end = timeit.default_timer()
# Assert
print ("cumfreq                       = ", cumfreq)
print (u"              time [\u00B5s] = ", (end - start) * 100000)
#assert(mean_arithmetic == 3.8)
print ("==================================================================================")

print ("==================================================================================")
# Arrange
start = timeit.default_timer()
# Act
itemfreq = stats.itemfreq(data)
end = timeit.default_timer()
# Assert
print ("itemfreq                      = ", itemfreq)
print (u"              time [\u00B5s] = ", (end - start) * 100000)
#assert(mean_arithmetic == 3.8)
print ("==================================================================================")


import numpy as np

p = [0.2,0.2,0.2,0.2,0.2]
world = ['green','red','red','green','green']
measurements = ['red','green']
motions = [1,1]
pHit = 0.6
pMiss = 0.2
pExact = 0.8
pOvershoot = 0.1
pUndershoot = 0.1

def sense(p,Z):
	q = []
	for i in range(len(p)):
		hit = (Z == world[i])
		q.append(p[i] * (hit * pHit + (1-hit) * pMiss))
	# Normalize
	return np.array(q)/sum(q)

def sense2D(p,Z,world,sense_acc):
	q = np.ones_like(p)
	rows, cols  = q.shape

	for i in range(rows):
		for j in range(cols):
			hit = (Z == world[i,j])
			if (hit):
				q[i,j] = p[i,j] * (pHit * sense_acc + pMiss * (1- sense_acc))
			else:
				q[i,j] = p[i,j] * (pHit * (1- sense_acc) + pMiss * sense_acc)
	# Normalize
	return q/np.sum(q)

def move(p,U):
	l = len(p)
	q = [ pExact * p[(i-U)%l]
		+ pOvershoot * p[(i-U-1)%l]
		+ pUndershoot * p[(i-U+1)%l]
		for i in range(l)]
	return q

def move2D(p,U,p_move):
	q = np.ones_like(p)
	rows = q.shape[0]
	cols = q.shape[1]
	for i in range(rows):
		for j in range(cols):
			q[i,j] = p_move * p[(i-U[0])%rows][(j-U[1])%cols] + (1-p_move) * p[i,j]
	return q/np.sum(q)

# 1D
for k in range(len(motions)):
	# sense first then move
	p = sense(p,measurements[k])
	p = move(p,motions[k])

# Also assume that at each step, the robot:
# 1) first makes a movement,
# 2) then takes a measurement.
#
# Motion:
#  [0,0] - stay
#  [0,1] - right
#  [0,-1] - left
#  [1,0] - down
#  [-1,0] - up

def localize(world,measurements,motions,sensor_right,p_move):
	if (len(measurements) != len(motions)):
		raise ValueError("len of measures should be same as motions")

	# initializes p to a uniform distribution over a grid of the same dimensions as colors
	pinit = 1.0 / float(len(colors)) / float(len(colors[0]))
	p = np.array([[pinit for row in range(len(colors[0]))] for col in range(len(colors))])

    # >>> Insert your code here <<<
	for i in range(len(motions)):
		p = sense2D(p,measurements[i],world,sensor_right)
		p = move2D(p,motions[i],p_move)

	return p

def show(p):
    rows = ['[' + ','.join(map(lambda x: '{0:.5f}'.format(x),r)) + ']' for r in p]
    print('[' + ',\n '.join(rows) + ']')

#############################################################
# For the following test case, your output should be
# [[0.01105, 0.02464, 0.06799, 0.04472, 0.02465],
#  [0.00715, 0.01017, 0.08696, 0.07988, 0.00935],
#  [0.00739, 0.00894, 0.11272, 0.35350, 0.04065],
#  [0.00910, 0.00715, 0.01434, 0.04313, 0.03642]]
# (within a tolerance of +/- 0.001 for each entry)

colors = np.array([['R','G','G','R','R'],
          			['R','R','G','R','R'],
          			['R','R','G','G','R'],
          			['R','R','R','R','R']])

#
# The essence is that the state matchs all
# measures during the motions keeps the highest
# in the end, it is not compute the most likely path.
#

measurements = ['G','G','G','G','G']
motions = [[0,0],[0,1],[1,0],[1,0],[0,1]]
p = localize(colors,measurements,motions,sensor_right = 0.7, p_move = 0.8)
show(p) # displays your answer


#!/usr/bin/env
# -*- coding: utf-8 -*-
# Copyright (C) Victor M. Mendiola Lau - All Rights Reserved
# Unauthorized copying of this file, via any medium is strictly prohibited
# Proprietary and confidential
# Written by Victor M. Mendiola Lau <ryuzakyl@gmail.com>, August 2016

from math import sqrt

from scipy.spatial.distance import correlation as scy_correlation

def correlation(x, y):
    """Computes the correlation coefficient.

    Args:
        x (list): The first vector.
        y (list): The second vector.

    Returns:
        float: The correlation coefficient between vectors x and y.

    """

    # getting the length of the vectors
    x_length = len(x)
    y_length = len(y)

    # validating parameters
    if x_length != y_length:
        raise Exception('Vectors with different sizes')

    # computing the means of both vectors
    mean_x = 0.0
    mean_y = 0.0
    for i in range(x_length):
        mean_x += x[i]
        mean_y += y[i]

    # dividing by the length of the vectors
    mean_x /= x_length
    mean_y /= y_length

    # computing the values k, f1 and f2
    k = 0.0
    f1 = 0.0
    f2 = 0.0
    for i in range(x_length):
        # computing the offsets
        offset_x = x[i] - mean_x
        offset_y = y[i] - mean_y

        # updating k, f1 and f2
        k += offset_x * offset_y
        f1 += offset_x * offset_x
        f2 += offset_y * offset_y

    # returning the computed correlation distance
    return k / (sqrt(f1) * sqrt(f2))

def probabilistic_correlation(x, y):
    """Computes the correlation coefficient as a probability value.

    Args:
        x (list): The first vector.
        y (list): The second vector.

    Returns:
        float: The correlation probability value between vectors x and y.

    """

    # computing the correlation value
    value = correlation(x, y)

    # moving value to interval [0, 2]
    value += 1.0

    # stretching value to the interval [0, 1]
    return 0.5 * value

def dis_correlation_manual(x, y):
    """Computes the correlation coefficient as a dissimilarity measure.

    Args:
        x (list): The first vector.
        y (list): The second vector.

    Returns:
        float: The dissimilarity value between vectors x and y.

    Examples:
        >>> dis_correlation_manual([1.0, 2.0, 3.0], [4.0, 5.0, 6.0])
        2.220446049250313e-16
        >>> dis_correlation_manual([1.0, 2.0, 3.0], [6.0, 5.0, 4.0])
        1.9999999999999998
        >>> dis_correlation_manual([1.0, 2.0, 3.0, 20.0, 150.0, 3.0], [6.0, 5.0, 4.0, 3.0, 2.0, 1.0])
        1.4245486433123256
        >>> dis_correlation_manual([1.0, 2.0, 3.0, 20.0, 150.0, 3.0], [1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
        0.5754513566876744

    """

    # computing the correlation value
    value = correlation(x, y)

    # setting dissimilarity value to the interval [0, 2]
    return 1 - value

def dis_correlation_scipy(x, y):
        """Computes the correlation distance between `x` and `y`.

        Args:
            x (list): The first vector.
            y (list): The second vector.

        Returns:
            double: The correlation distance between vectors `x` and `y`.

        References:
            * https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.correlation.html

        Examples:
            >>> dis_correlation_scipy([1.0, 2.0, 3.0], [4.0, 5.0, 6.0])
            2.2204460492503131e-16
            >>> dis_correlation_scipy([1.0, 2.0, 3.0], [6.0, 5.0, 4.0])
            1.9999999999999998
            >>> dis_correlation_scipy([1.0, 2.0, 3.0, 20.0, 150.0, 3.0], [6.0, 5.0, 4.0, 3.0, 2.0, 1.0])
            1.4245486433123256
            >>> dis_correlation_scipy([1.0, 2.0, 3.0, 20.0, 150.0, 3.0], [1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
            0.57545135668767444

        """

        # returning the correlation distance
        return scy_correlation(x, y)


import numpy as np
import matplotlib.pyplot as plt
from utils import sigmoid , gradient_descent_logistic_regresion

X1=np.array([]) # grade 1
X2=np.array([]) # grade 2
Y=np.array([]) # admitted to university
file = open("data\\ex2data1.txt", "r")
for row in file:
  ar = row.split(",")
  X1 = np.append(X1,float(ar[0]))
  X2 = np.append(X2,float(ar[1]))
  Y = np.append(Y,float(ar[2]))

m = Y.size # should be same as the size of X1,X2
X0 = np.ones(m)

scale_factor = 100

# using scale_factor of 1 will cause an error "Desired error not necessarily achieved due to precision loss."
# the problem is that X0 is 1 while X1,X2 are between 0 - 100 so 100 scale them to be around 1
X1 = X1/scale_factor
X2 = X2/scale_factor
X= np.vstack((X0,X1,X2)).T
Teta = [100,100,100] # arbitrary initial condition

iterations = 0
alfa = 0.01 # learning rate
max_iterations = 1000

while iterations <  max_iterations:
    res = gradient_descent_logistic_regresion(Teta,X,Y,alfa)
    Teta = res["Teta"]
    J = res["J"]
    iterations += 1

print("J : {:0.2f} , teta0 : {:0.2f} , teta1 : {:0.2f} ,  teta2 : {:0.2f}".format(J,Teta[0], Teta[1],Teta[2]))

def prob(x1,x2):
    return sigmoid(Teta[0]+Teta[1]*x1/scale_factor+Teta[2]*x2/scale_factor)

print("h @ x1=90 , x2=90",prob(90,90))

ar_index_pass = np.where(Y == 1)
ar_index_fail = np.where(Y == 0)

x2_0_5_line = -(Teta[0]+Teta[1]*X1)/Teta[2] # prob 0.5

plt.title('+ : pass , o : fail \ncomputed gradient descent 0.5 logistic regression decision boundary')
plt.xlabel("grade1")
plt.ylabel("grade2")
plt.plot(scale_factor*X1[ar_index_pass],scale_factor*X2[ar_index_pass],'+')
plt.plot(scale_factor*X1[ar_index_fail],scale_factor*X2[ar_index_fail],'o')
plt.plot(scale_factor*X1,scale_factor*x2_0_5_line)
plt.show()


from sympy import primerange
from typing import List, Dict
from pprint import pprint

def _prime_number_less_than_n(number: int) -> List[int]:
    return list(primerange(0, number))

def _calculate_vp_n_factorial(number: int, prime: int) -> int:

    vp_n_factorial = 0
    power = 1
    while number//(prime**power):
        vp_n_factorial += number//(prime**power)
        power += 1

    return vp_n_factorial

# returns the power of all prime numbers that are part of the decomposition of n!
def factorial_factoring(number: int) -> str:
    return ''.join(
        f'({prime}^{_calculate_vp_n_factorial(number, prime)})'
        for prime in _prime_number_less_than_n(number)
    )

# returns a dictionary with a prime number and its power in decomposing n!
def factorial_factoring_dict(number: int) -> Dict[int, int]:
    return {
        prime: _calculate_vp_n_factorial(number, prime)
        for prime in _prime_number_less_than_n(number)
    }

print(factorial_factoring(50))
pprint(factorial_factoring_dict(50), width=1)


"""
==============================================================
Curve fitting: temperature as a function of month of the year
==============================================================

We have the min and max temperatures in Alaska for each months of the
year. We would like to find a function to describe this yearly evolution.

For this, we will fit a periodic function.
"""

############################################################
# The data
############################################################
import numpy as np

temp_max = np.array([17,  19,  21,  28,  33,  38, 37,  37,  31,  23,  19,  18])
temp_min = np.array([-62, -59, -56, -46, -32, -18, -9, -13, -25, -46, -52, -58])

import matplotlib.pyplot as plt
months = np.arange(12)
plt.plot(months, temp_max, 'ro')
plt.plot(months, temp_min, 'bo')
plt.xlabel('Month')
plt.ylabel('Min and max temperature')

############################################################
# Fitting it to a periodic function
############################################################

from scipy import optimize
def yearly_temps(times, avg, ampl, time_offset):
    return (avg
            + ampl * np.cos((times + time_offset) * 2 * np.pi / times.max()))

res_max, cov_max = optimize.curve_fit(yearly_temps, months,
                                      temp_max, [20, 10, 0])
res_min, cov_min = optimize.curve_fit(yearly_temps, months,
                                      temp_min, [-40, 20, 0])

############################################################
# Plotting the fit
############################################################

days = np.linspace(0, 12, num=365)

plt.figure()
plt.plot(months, temp_max, 'ro')
plt.plot(days, yearly_temps(days, *res_max), 'r-')
plt.plot(months, temp_min, 'bo')
plt.plot(days, yearly_temps(days, *res_min), 'b-')
plt.xlabel('Month')
plt.ylabel('Temperature ($^\circ$C)')

plt.show()


import math

math.e

math.factorial(10)

def factorial(n):
    print("Using my factorial")

    if n < 2:
        return 1

    return n * factorial(n - 1)

factorial(5)

math.factorial(5)

import math as maths

maths.cos(maths.pi)

from math import factorial as fac

fac(3)

factorial(3)

from math import factorial

factorial(5)

from math import pi, sin

sin(pi/4)

from math import *

log2(1024)

%reset -f

2**64 - 1

2.0**150

2**150

import math

math.factorial(4)

math.perm(4, 2)

math.comb(4, 4)

for m in (2, 3, 5, 7):
    if 14 % m == 0:
        print(f"14 is divisible by {m}")
    else:
        print(f"14 is not divisible by {m}")

import inspect
import math

def sieve_of_eratosthenes(n):
    # Return a list of the primes less than or equal to n.
    # First check that n is an integer greater than 1.

    if not isinstance(n, int) or not n > 1:
        print(
            "The argument to sieve_of_eratosthenes "
            "must be an integer greater than 1.")
        return []

    # Make a list holding the integers from 0 to n.

    potential_primes = list(range(n + 1))

    # If index is not prime, set potential_primes[index] to 0.
    # We start with 0 and 1

    potential_primes[0] = 0
    potential_primes[1] = 0

    p = 2  # 2 is prime, so start with that.

    while p <= n:
        # If at an index whose value in potential_primes
        # is not 0, it is prime.

        if potential_primes[p]:
            i = 2 * p

            # Mark p+p, p+p+p, etc. as not prime.
            while i <= n:
                if i != p:
                    potential_primes[i] = 0
                i += p
        p += 1

    # The only non-zero integers left in potential_primes
    # are primes. Return a list of those.

    return [prime for prime in potential_primes if prime]

def simple_factor(n):
    # factor the integer n by trial division

    if not isinstance(n, int) or not n > 1:
        print(
            "The argument to simple_factor "
            "must be an integer greater than 1.")
        return []

    primes_to_check = sieve_of_eratosthenes(math.isqrt(n))
    prime_factors = []

    for prime in primes_to_check:
        while n % prime == 0:
            prime_factors.append(prime)
            n = n // prime

    return prime_factors

print(inspect.getsource(sieve_of_eratosthenes))

sieve_of_eratosthenes(35)

import math

math.isqrt(63)

math.isqrt(64)

math.isqrt(65)

print(inspect.getsource(simple_factor))

f10 = math.factorial(10)

print(f"The prime factors of 10! = {f10} are\n"
      f"{simple_factor(f10)}")

math.gcd(12, 15)

12 * 15 // math.gcd(12, 15)

bin(72)

0b1001000

int("-32856")

b = bin(100)
b

int(b, base=2)

for n in range(8):
    m = n + 8
    print(f"{n:01x}   {n:2}   {n:04b}        "
          f"{m:01x}   {m:2}   {m:04b}")

hex(100)

hex(252)

right_arrow = "→"

-3.9005

1.1456e-4

f = -9E100
f

type(f)

1/7

0.10101010101010101010101010101010101

1e1000000000000000000000000

float("inf")

-1e1000000000000000000000000

float("-inf")

float("inf") + 3

2e8383747474847474747 == 9e3838399227273898383

float("inf") + float("inf")

float("inf") - float("inf")

float("inf") / float("inf")

round(8356.92665, 2)

round(8356.92665, -2)

[math.floor(-1.2,), math.ceil(-1.2), math.floor(1.2), math.ceil(1.2)]

math.pi

math.tau

math.degrees(2 * math.pi)

math.radians(270) / math.pi

math.asin(-1.0)

math.tan(1.0)

math.sin(1.0) / math.cos(1.0)

math.cos(math.pi/2)

math.isclose(math.cos(math.pi/2), 0.0, abs_tol=1e-15)

math.e

math.exp(0.0)

math.exp(1.0)

math.exp(4.5)

def compound_continuously(principal, annual_rate, years):
    return principal * math.exp(annual_rate * years)

compound_continuously(100, 0.02, 1)

compound_continuously(100, 0.02, 35)

y = math.pow(8.0, 3.0)
y

math.pow(y, 0.333333333333333)

math.sqrt(105.0)

math.log2(16)

math.log10(10**8)

math.log2(2*2*2*2*2)

def mystery_function(n):
    return math.trunc(math.log2(n))

from fractions import Fraction

Fraction(6, 5)

f = Fraction(20, 30)
f

f.numerator

f.denominator

import math

math.gcd(f.numerator, f.denominator)

Fraction(1, -5)

- Fraction(3, 7)

a = Fraction(2, 3)
b = Fraction(7, 4)

2 * a

a + b

a - b

a * b

1 / b

a / b

a ** 4

a ** -2

f = float(a)
f

Fraction(f)

Fraction(0.125)

Fraction(0.1)

import cmath

cmath.sqrt(-1.0)

z = complex(1.5, -2)
z

z.real

z.imag

3.4 - 8.03j

print(f"{math.sqrt(4)}   {cmath.sqrt(4)}")

print(f"{math.sin(0)}   {cmath.sin(0)}")

type(1j)

isinstance(1j, complex)

(3 + 4j).conjugate()

abs(0.5 - 0.25j)

z = 3 + 4j
w = 2 - 1j

r, phi = cmath.polar(3 + 4j)

z = complex(-5.0 * math.sqrt(2.0) / 4.0,
            -5.0 * math.sqrt(2.0) / 4.0)

r, phi = p = cmath.polar(z)

print(f"{z = }\n{r = }\n{phi = }")

-3 * math.pi / 4

cmath.rect(r, phi)

import sympy as sym

x = sym.Symbol('x')
p = x**3 - 2*x**2 - 5*x + 6
p

sym.factor(p)

p.subs(x, 3)

sym.limit(p, x, 3)

sym.diff(p, x)

sym.integrate(p, x)

import random

[random.randint(1, 10) for i in range(6)]

[random.randint(1, 10) for i in range(6)]

random.seed(10)
[random.randint(1, 10) for i in range(6)]

random.seed(10)
[random.randint(1, 10) for i in range(6)]

[random.random() for i in range(3)]

[random.uniform(0, 2) for i in range(3)]

card_deck = []

for suit in ("C", "D", "H", "S"):
    # create cards with rank 2 through 10
    for rank in range(2, 11):
        card_deck.append(f"{rank}{suit}")

    # create cards for jacks, queens, kings, and aces
    for rank in ("J", "Q", "K", "A"):
        card_deck.append(f"{rank}{suit}")

def print_cards(cards):
    # print the cards with up to 13 cards per row

    for card, n in zip(cards, range(1, len(cards) + 1)):
        print(f"{card:3}", end="  ")
        if n % 13 == 0:
            print()

print_cards(card_deck)

random.shuffle(card_deck)
print_cards(card_deck)

random.sample(card_deck, 5)

random.choice(card_deck)

random.choice(list({1, 2, 3, 4, 5}))

numbers = {0: "zero", 1: "one", 2: "two"}
key = random.choice(list(numbers.keys()))
key

numbers[key]

import qiskit

draw_kwargs = {
    "output": "mpl",         # use matplotlib
    "cregbundle": False,     # separate classical register wires
    "initial_state": True,   # show |0> and 0
    "idle_wires": False,     # don't show unused wires

    "style": {
        "name": "bw",        # black-and-white for book
        "subfontsize": 9,    # font size of subscripts
        "dpi": 600           # image resolution
    }
}

histogram_color = "#82caaf"

circuit = qiskit.QuantumCircuit(2)

circuit.h(0)
circuit.h(1)

circuit.measure_all()

savefig_dpi = 600
file_name = "work/images-to-trim/w-22-quantum-random-002.jpg"
circuit.draw(**draw_kwargs).savefig(file_name, dpi=savefig_dpi)

backend = qiskit.Aer.get_backend("aer_simulator")

job_sim = qiskit.execute(circuit, backend, shots=8000)

job_sim.result().get_counts(circuit)


import numpy as np
from dataio import DataIO

class SampleSinus(object):
    """ Sample sinus function f(x) = sin(2 pi x)

    TARGET
    - create input and target vector
    - target includes noise (measurement error)

    1) create x (length N), loop through bounded interval
    2) Compute N times f(x) = sin( 2 pi x)
    3) Draw N times e from N(0, 0.3)
    4) Add e to f(x)
    5) Write to file (option xt)

    SINUS FUNCTION
    - create input and target vector
    - to draw sinus function
    - no noise

    1) create x (length N), loop through bounded interval
    2) compue N times f(x) = sin( 2 pi x)
    3) Write to file (option xt)

    INPUT
    - create input vector (no target vector)
    1) Draw N times x from Uniform(0, 1)
    2) Write to file (option x)

    """

    SEED = 123456 # random seed

    X_LBU = 0.0     # Lower Bound Uniform distribution
    X_UBU = 1.0     # Upper Bound Uniform distribution
    STD_NOISE = 0.3 # standard deviation normal error distribution

    NLARGE = 10001  # decritization number of f(x) (vizualization)

    def __init__(self, seed=None):
        """ Initialize SampleSinus object. """

        # Check if random seed is provided
        if seed is None:
            seed = self.SEED
        # construct random state object
        self.random_state = np.random.RandomState(seed)

    def target(self, N, file_name, xdistr=None):
        """ Execute sampling operation (see class description)

        :param N - int, number of data points.
        :param file_name - str, name of the output file.

        :output None - write data to file.
        """
        if xdistr is None or xdistr == 'evenly':
            x = np.linspace(self.X_LBU, self.X_UBU, N)
        elif xdistr == 'random':
            x = self.random_state.uniform(self.X_LBU, self.X_UBU, N)

        y = np.sin(2*np.pi*x)
        e = self.random_state.normal(loc=0.0, scale=self.STD_NOISE, size=N)
        t = y + e
        title = 'input\ttarget\terror'
        DataIO.write_data( [x, t, e], file_name, title)

    def function(self, file_name):
        x = np.linspace(self.X_LBU, self.X_UBU, self.NLARGE)
        f = np.sin(2*np.pi*x)
        title = 'input\tsinus function'
        DataIO.write_data([x, f], file_name, title)

    def input(self, N, file_name):
        x = self.random_state.uniform(self.X_LBU, self.X_UBU, N)
        title = 'input'
        DataIO.write_data([x], file_name, title)


#difference between normal linear fit and parabolic fit using polynomial regression

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
import pandas as pd
#generating random numbers for equation y=X^3+100+e
np.random.seed(42)
n_samples=100
X=np.linspace(0,10,100)
rng=np.random.randn(n_samples)*100
y=X**3+rng+100
#plot the data in scatter plot
plt.figure(figsize=(10,8));
plt.scatter(X,y);
plt.show()

#performing linear regression on the X and y data
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
lr=LinearRegression()
lr.fit(X.reshape(-1,1),y);
model_pred=lr.predict(X.reshape(-1,1))
#prediction plot will be linear
plt.figure(figsize=(10,8));
plt.scatter(X,y);
plt.plot(X,model_pred);
#r2 score will be low
print(r2_score(y,model_pred))
plt.show()

#performing linear regression on the X and y data with polynomial regression
from sklearn.preprocessing import PolynomialFeatures
poly_reg=PolynomialFeatures(degree=3)
X_poly=poly_reg.fit_transform(X.reshape(-1,1))
lin_reg_2=LinearRegression()
lin_reg_2.fit(X_poly,y.reshape(-1,1))
y_pred=lin_reg_2.predict(X_poly)
#prediction plot will be parabolic
plt.figure(figsize=(10,8));
plt.scatter(X,y);
plt.plot(X,y_pred);
#r2 score will be high (best fit)
print(r2_score(y,y_pred))
plt.show()


import numpy as np

class NeuronLayers():

    def __init__(self, number_of_neurons, number_of_inputs):
        self.weight = 2 * np.random.random((number_of_inputs, number_of_neurons)) - 1

class NeuralNetwork():

    def __init__(self, layer1, layer2):
        self.layer1 = layer1
        self.layer2 = layer2

    def __sigmoid(self, x):
        return 1 / (1 + np.exp(-x))

    def __sigmoid_derivative(self, x):
        return x * (1 - x)

    def __step_function(self, x):
        out = 0
        if(x[0] >= 0.5):
            out = 1

        return out

    def think(self, inputs):
        output_from_layer1 = self.__sigmoid(np.dot(inputs, self.layer1.weight))
        output_from_layer2 = self.__sigmoid(np.dot(output_from_layer1, self.layer2.weight))
        integer_out = self.__step_function(output_from_layer2)
        return output_from_layer1, output_from_layer2, integer_out

    def train(self, training_set_inputs, training_set_outputs, e_poch):
        for i in range(e_poch):

            output_from_layer1, output_from_layer2, integer_out = self.think(training_set_inputs)

            layer2_error = training_set_outputs - output_from_layer2
            layer2_delta = layer2_error * self.__sigmoid_derivative(output_from_layer2)

            layer1_error = layer2_delta.dot(self.layer2.weight.T)
            layer1_delta = layer1_error * self.__sigmoid_derivative(output_from_layer1)

            layer1_ajustment = training_set_inputs.T.dot(layer1_delta)
            layer2_ajustment = output_from_layer1.T.dot(layer2_delta)

            self.layer1.weight += layer1_ajustment
            self.layer2.weight += layer2_ajustment

    def print_weights(self):
        print("layer 1")
        print(self.layer1.weight)
        print("layer 2")
        print(self.layer2.weight)

if __name__ == "__main__":
    np.random.seed(1)

    layer1 = NeuronLayers(4, 3)
    layer2 = NeuronLayers(1, 4)

    network = NeuralNetwork(layer1, layer2)

    print("The start up weight in the network")
    network.print_weights()

    train_set_inputs = np.array([[0, 0, 1], [0, 1, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 1], [0, 0, 0]])
    train_set_outputs = np.array([[1, 1, 1, 1, 1, 1, 0]]).T

    network.train(train_set_inputs, train_set_outputs, 100)

    print("The weight after the training")
    network.print_weights()

    print("Test to see if the model are good enough by inputing [1, 1, 0]")
    hidden_state, org_out, integer_out = network.think(np.array([1, 1, 0]))
    print(integer_out)


import numpy as np

from .transformations import affine_transformation

def get_chebyshev_nodes(lb, ub, order):
    """
    Provides chebyshev quadratures nodes
    scaled to live on the interval [lb, ub], of specified order
    The nodes are reversed from traditional chebyshev nodes
        (so that the lowest valued node comes first)
    Returns:
        unscaled nodes
        scaled nodes
        scaling ratio
    """
    xc, _ = np.polynomial.chebyshev.chebgauss(order)
    x, rat = affine_transformation(xc[::-1], -1, 1, lb, ub, return_ratio=True)
    return xc[::-1], x, rat

class ChebyshevInterpolater(object):
    def __init__(self, x, data):
        self.x = x
        self.n = self.x.shape[0]
        self.data = data
        self.coefs = np.polynomial.chebyshev.chebfit(self.x, self.data, self.n-1)
    def __call__(self, x_out):
        return np.polynomial.chebyshev.chebval(x_out, self.coefs)


import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm, t
np.random.seed(1)

#%%
N = 1_0
mu = 5
sd = 2

#%%
x = np.random.randn(N)*sd + mu

#%% Z-CI
mu_hat = x.mean()
sigma_hat = x.std(ddof=1)
z_left = norm.ppf(0.0250)
z_right = norm.ppf(0.9750)
left_ci = mu_hat + z_left*sigma_hat/np.sqrt(N)
right_ci = mu_hat + z_right*sigma_hat/np.sqrt(N)
print(f"Mean: {mu_hat}")
print(f"Confidence Interval is [{left_ci}, {right_ci}]")

#%% t-CI
mu_hat = x.mean()
sigma_hat = x.std(ddof=1)
t_left = t.ppf(0.0250, df=N-1)
t_right = t.ppf(0.9750, df=N-1)
left_ci = mu_hat + t_left*sigma_hat/np.sqrt(N)
right_ci = mu_hat + t_right*sigma_hat/np.sqrt(N)
print(f"Mean: {mu_hat}")
print(f"Confidence Interval is [{left_ci}, {right_ci}]")

#%%
def experiment():
    x = np.random.randn(N) * sd + mu
    mu_hat = x.mean()
    sigma_hat = x.std(ddof=1)
    t_left = t.ppf(0.0250, df=N - 1)
    t_right = t.ppf(0.9750, df=N - 1)
    left_ci = mu_hat + t_left * sigma_hat / np.sqrt(N)
    right_ci = mu_hat + t_right * sigma_hat / np.sqrt(N)
    return mu<right_ci and mu>left_ci

def multi_experiment(n):
    results = [experiment() for _ in range(n)]
    return np.mean(results)

#%%
result = multi_experiment(10_000)
print(result)


import numpy as np

from optimizer import Optimizer

class Polyak(Optimizer):
    """
    Polyak adaptive gradient descent, proposed in
        (B. T. Poyal, "Introduction to Optimization")
    which can be accessed, e.g., here:
        https://www.researchgate.net/publication/342978480_Introduction_to_Optimization

    Arguments:
        f_opt (float): precise value of the objective's minimum. If an underestimate is given,
            the algorirthm can be unstable; if an overestimate is given, will not converge below
            the overestimate.
        lr_min (float, optional): the smallest step-size, useful when
            an overestimate of the optimal value is given (default: 0)
        lr_max (float, optional): the laregest allowed step-size, useful when
            an underestimate of the optimal value is given (defaul: np.inf)
    """
    def __init__(self, f_opt, lr_min=0, lr_max=np.inf, *args, **kwargs):
        super(Polyak, self).__init__(*args, **kwargs)
        self.f_opt = f_opt
        self.lr_min = lr_min
        self.lr_max = lr_max

    def step(self):
        self.grad = self.loss.gradient(self.x)
        self.estimate_new_stepsize()
        self.x -= self.lr * self.grad

    def estimate_new_stepsize(self):
        loss_gap = self.loss.value(self.x) - self.f_opt
        self.lr = loss_gap / self.loss.norm(self.grad)**2
        self.lr = min(self.lr, self.lr_max)
        self.lr = max(self.lr, self.lr_min)

    def init_run(self, *args, **kwargs):
        super(Polyak, self).init_run(*args, **kwargs)
        self.trace.lrs = []

    def update_trace(self):
        super(Polyak, self).update_trace()
        self.trace.lrs.append(self.lr)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Aug 25 06:45:58 2020

A script to illustrate some basic plotting and matrix operations in Python

@author: zettergm
"""

# Load external modules
import numpy as np
import numpy.linalg as nla
import scipy.linalg as sla
import matplotlib.pyplot as plt

from funexamples import fun1D,fun2D

# Define some variable so we can plot things
x=np.linspace(-10,10,100)
y=np.linspace(-10,10,100)
[X,Y]=np.meshgrid(x,y)

# Example function evaluations to plot
y1=fun1D(x,1,1,3)
y2=fun1D(x,1.5,-1,2)
Z1=fun2D(X,Y,2,0,0,3,10)
Z2=fun2D(X,Y,5,2,-2,2,2)

# Basic 1D Python plotting with matplotlib
plt.figure(1)
plt.plot(x,y1,x,y2)
plt.xlabel("x")
plt.ylabel("y")
plt.title("Plot of two Gaussian functions")
plt.legend(["curve 1","curve 2"])
plt.show()

# Basic 2D Python plotting with matplotlib
plt.figure(2)
im1=plt.pcolor(X,Y,Z1)
plt.colorbar(im1)
plt.xlabel("x")
plt.ylabel("y")
plt.title("2D Gaussian 1")
plt.show()

fig3=plt.figure(3)
im2=plt.pcolor(X,Y,Z2)
plt.colorbar(im2)
plt.xlabel("x")
plt.ylabel("y")
plt.title("2D Gaussian 2")
plt.show()

# this matrix and vector represent the system of equations:
# 1)   x +  2y +  4z = 18
# 2)  2x + 12y -  2z =  9
# 3)  5x + 26y +  5z = 14
A=np.array([[1, 2, 4],[2, 12, -2],[5,26,5]])      #matrix of coefficients
b=np.array([[18], [9], [14]])                     #this is the column vector representing the RHS of the system
B=np.transpose(A)                                 #transpose of A, for illustration of differences from MATLAB

# Some basic commands to printlay variables
print("A = ")
print(A)

print("b = ")
print(b)

# Compute some matrix properties and print them
print("det(A) = ")
print(nla.det(A))     # numpy.linalg.det(A) longhand

print("trace(A) = ")
print(np.trace(A))

print("condition # of A = ")
print(nla.cond(A))

print("transpose(A) = ")
print(np.transpose(A))

print("Aii (diagonal elements of A) = ")
print(np.diag(A))

# Matrix functions
print("A*B (matrix multiplication) = ")
print(A@B)

print("Aij*Bij (scalar multiplication) = ")
print(A*B)

print("5*A (multiplication) = ")
print(5*A)

print("Solution (x) of the system A*x=b:  ")
print("x = ")
xvec=nla.solve(A,b)
print(xvec)

print("I (3x3 identity matrix) = ")
print(np.eye(3,3))

print("A^{-1} (inverse of A) = ")
Ainv=nla.solve(A,np.eye(3,3))
print(Ainv)

# slicing and concatenation of array/matrices
print("2nd row of A = ")
print(A[1,:])     #in Python arrays start at zero...

print("2nd column of A = ")
print(A[:,1])

print("flat list (column vector) of matrix elements of A:  ")
print(A.flatten())

print("Horizontal concatenation of A with itself:  ")
print(np.concatenate((A,A),axis=1))

print("Vertical concatenation of A with itself:  ")
print(np.concatenate((A,A),axis=0))

print("diagonal matrix:  ")
a1=np.arange(10,0,-1)                        # count backward, note endpoint excluded
print(np.diag(a1))

print("LU decomposition of A (A=L*U):  ")
[P,L,U]=sla.lu(A)
print("L = ")
print(L)
print("U = ")
print(U)

print("Eigenvalues of A = ")
[lam,psi]=sla.eig(A)      #note output args swapped from matlab
print(lam)
print("Eigenvectors of A = ")
print(psi[:,0])
print(psi[:,1])
print(psi[:,2])