from tictoc import *
import numpy as np
import matplotlib.pyplot as plt
import sys
from LinReg import *
from Numerical_Quadrature import *

f = lambda x: np.sin(x)

print('LEFT-ENDPOINT METHOD  |-> 1')
print('RIGHT-ENDPOINT METHOD |-> 2')
print('MIDPOINT METHOD       |-> 3')
print('TRAPEZOID METHOD      |-> 4')
print('|E| VS N              |-> 5')
print('|E| VS h              |-> 6')
print('log(|E|) VS h         |-> 7')
print('log(|E|) VS log(h)    |-> 8')
print("------------------------------------------------")

module = int(input("MODULE NUMBER  = "))
if module > 8:
    print('INCORRECT MODULE INITIATION CODE !')
    exit()
N = int(input('NO. OF ITERATIONS = '))
if N>100000:
    print('MAX NO OF ITERATIONS IS 100000 !')
    exit()

ITER_STEP = int(input('SIZE OF EACH ITERATION STEP = '))

if module == 1:
    print("------------------------------------------------")
    print('Left-Endpoint Method Iteration Values and Plots')
    print("------------------------------------------------")

    step = []
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = LM(f,0,np.pi/2,n)
        step.append(h)
        AE.append(abs_err)
    toc()
    # Plot 1: |E| vs h
    linreg_ind(step,AE)
    plt.xlabel('h')
    plt.ylabel('|E|')
    plt.title('|E| vs h : Left-Endpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()
    # Plot 2: log(|E|) vs h
    linreg_ind(step,np.log(AE))
    plt.xlabel('h')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs h : Left-Endpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()
    # Plot 3: log(|E|) vs log(h)
    linreg_ind(np.log(step),np.log(AE))
    plt.xlabel('log(h)')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs log(h) : Left-Endpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()

if module == 2:
    print("------------------------------------------------")
    print('Right-Endpoint Method Iteration Values and Plots')
    print("------------------------------------------------")

    step = []
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = RM(f,0,np.pi/2,n)
        step.append(h)
        AE.append(abs_err)
    toc()
    # Plot 1: |E| vs h
    linreg_ind(step,AE)
    plt.xlabel('h')
    plt.ylabel('|E|')
    plt.title('|E| vs h : Right-Endpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()
    # Plot 2: log(|E|) vs h
    linreg_ind(step,np.log(AE))
    plt.xlabel('h')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs h : Right-Endpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()
    # Plot 3: log(|E|) vs log(h)
    linreg_ind(np.log(step),np.log(AE))
    plt.xlabel('log(h)')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs log(h) : Right-Endpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()

if module == 3:
    print("------------------------------------------------")
    print('Midpoint Method Iteration Values and Plots')
    print("------------------------------------------------")

    step = []
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = MpM(f,0,np.pi/2,n)
        step.append(h)
        AE.append(abs_err)
    toc()
    # Plot 1: |E| vs h
    linreg_ind(step,AE)
    plt.xlabel('h')
    plt.ylabel('|E|')
    plt.title('|E| vs h : Midpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()
    # Plot 2: log(|E|) vs h
    linreg_ind(step,np.log(AE))
    plt.xlabel('h')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs h : Midpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()
    # Plot 3: log(|E|) vs log(h)
    linreg_ind(np.log(step),np.log(AE))
    plt.xlabel('log(h)')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs log(h) : Midpoint Method')
    plt.legend()
    plt.autoscale()
    plt.show()

if module == 4:
    print("------------------------------------------------")
    print('Trapezoid Method Iteration Values and Plots')
    print("------------------------------------------------")

    step = []
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = TM(f,0,np.pi/2,n)
        step.append(h)
        AE.append(abs_err)
    toc()
    # Plot 1: |E| vs h
    linreg_ind(step,AE)
    plt.xlabel('h')
    plt.ylabel('|E|')
    plt.title('|E| vs h : Trapezoid Method')
    plt.legend()
    plt.autoscale()
    plt.show()
    # Plot 2: log(|E|) vs h
    linreg_ind(step,np.log(AE))
    plt.xlabel('h')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs h : Trapezoid Method')
    plt.legend()
    plt.autoscale()
    plt.show()
    # Plot 3: log(|E|) vs log(h)
    linreg_ind(np.log(step),np.log(AE))
    plt.xlabel('log(h)')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs log(h) : Trapezoid Method')
    plt.legend()
    plt.autoscale()
    plt.show()

if module == 5:
    AE = []
    S = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = LM(f,0,np.pi/2,n)
        S.append(n)
        AE.append(abs_err)
    toc()
    linreg_all(S,AE,'Left-Endpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = RM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(S,AE,'Right-Endpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = MpM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(S,AE,'Midpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = TM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(S,AE,'Trapezoid')
    plt.xlabel('N')
    plt.ylabel('|E|')
    plt.title('|E| vs N')
    plt.legend()
    plt.show()

if module == 6:
    AE = []
    step = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = LM(f,0,np.pi/2,n)
        step.append(h)
        AE.append(abs_err)
    toc()
    linreg_all(step,AE,'Left-Endpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = RM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(step,AE,'Right-Endpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = MpM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(step,AE,'Midpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = TM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(step,AE,'Trapezoid')
    plt.xlabel('h')
    plt.ylabel('|E|')
    plt.title('|E| vs h')
    plt.legend()
    plt.show()

if module == 7:
    AE = []
    step = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = LM(f,0,np.pi/2,n)
        step.append(h)
        AE.append(abs_err)
    toc()
    linreg_all(step,np.log(AE),'Left-Endpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = RM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(step,np.log(AE),'Right-Endpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = MpM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(step,np.log(AE),'Midpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = TM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(step,np.log(AE),'Trapezoid')
    plt.xlabel('h')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs h')
    plt.legend()
    plt.show()

if module == 8:
    AE = []
    step = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = LM(f,0,np.pi/2,n)
        step.append(h)
        AE.append(abs_err)
    toc()
    linreg_all(np.log(step),np.log(AE),'Left-Endpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = RM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(np.log(step),np.log(AE),'Right-Endpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = MpM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(np.log(step),np.log(AE),'Midpoint')
    AE = []
    tic()
    for n in range(1,(N+1)*ITER_STEP,ITER_STEP):
        h , abs_err = TM(f,0,np.pi/2,n)
        AE.append(abs_err)
    toc()
    linreg_all(np.log(step),np.log(AE),'Trapezoid')
    plt.xlabel('log(h)')
    plt.ylabel('log(|E|)')
    plt.title('log(|E|) vs log(h)')
    plt.legend()
    plt.show()

print('END OF PROGRAM : RERUN TO USE A DIFFERENT MODULE')


from __future__ import print_function

import numpy as np
import matplotlib.pyplot as plt

from sklearn.datasets import make_circles
from sklearn.cluster import KMeans

from scipy.spatial.distance import pdist

# For reproducibility
np.random.seed(1000)

nb_samples = 1000

def show_dataset(X):
    fig, ax = plt.subplots(1, 1, figsize=(30, 25))

    ax.grid()
    ax.set_xlabel('X')
    ax.set_ylabel('Y')

    for i in range(nb_samples):
        if Y[i] == 0:
            ax.scatter(X[i, 0], X[i, 1], marker='o', color='r')
        else:
            ax.scatter(X[i, 0], X[i, 1], marker='^', color='b')

    plt.show()

def show_clustered_dataset(X, km):
    fig, ax = plt.subplots(1, 1, figsize=(30, 25))

    ax.grid()
    ax.set_xlabel('X')
    ax.set_ylabel('Y')

    for i in range(nb_samples):
        c = km.predict(X[i].reshape(1, -1))
        if c == 0:
            ax.scatter(X[i, 0], X[i, 1], marker='o', color='r')
        else:
            ax.scatter(X[i, 0], X[i, 1], marker='^', color='b')

    plt.show()

if __name__ == '__main__':
    # Create dataset
    X, Y = make_circles(n_samples=nb_samples, noise=0.05)

    # Show dataset
    show_dataset(X)

    # Create and train K-Means
    km = KMeans(n_clusters=2)
    km.fit(X)

    # Show clustered dataset
    show_clustered_dataset(X, km)

    # Compute the average intra-cluster distances
    Y_pred = km.predict(X)

    sampled_X = np.random.choice(X[Y_pred == 0, 0], replace=False, size=300).astype(np.int32)

    true_distances = pdist(X[Y == 0], metric='euclidean')
    distances = pdist(X[sampled_X], metric='euclidean')

    print('True average distance: %.3f' % np.mean(true_distances))
    print('Clustering agerage distance: %.3f' % np.mean(distances))


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

j = 2
points = [i / 2**j for i in range(2**j+1)]
print(points)

def Phi(x):
    if 0 <= x <= 1:
        return 1
    else:
        return 0

# continues with all the code block before
# we have j already
# we discard j in the name for fixed j.
def Phi_ifn(i):
    def Phi_i(x):
        val = 2**(j/2) * Phi(2**j * x - i)
        return val
    return Phi_i

F_2 = [Phi_ifn(i) for i in range(2**j)]

def visual_fn(F_j, figsize):
    fig = plt.figure(figsize=figsize)
    gs = gridspec.GridSpec(*figsize)

    xs = np.linspace(0, 1, 50)
    for i, fn in enumerate(F_j):
        ax = plt.subplot(gs[i])
        y = [fn(x) for x in xs]
        if i != 0:
            ax.set_yticklabels([])
        ax.set_aspect('auto')
        plt.plot(xs, y)
    plt.show()

# uncomment it to visualiza F_2
# visual_fn(F_2, [1, 4])

# here we start to construct W_2

def Psi(x):
    if 0 < x < 1/2:
        return 1
    elif 1/2 < x < 1:
        return -1
    else:
        return 0

def Psi_ifn(i):
    def Psi_i(x):
        val =  2**(j/2) * Psi(2**j * x - i)
        return val
    return Psi_i

F_2w = [Psi_ifn(i) for i in range(2**j)]

# uncomment it to visualiza F_2
visual_fn(F_2w, [1, 4])


import numpy as np

def make_score_matrix(seq_a, seq_b, match_score=1, mismatch_score=0):
    score_matrix = np.zeros((len(seq_a), len(seq_b)))
    for i, a in enumerate(seq_a):
        for j, b in enumerate(seq_b):
            if a == b:
                score_matrix[i, j] = match_score
            else:
                score_matrix[i, j] = mismatch_score
    return score_matrix

def needleman_wunsh(sequence_a, sequence_b, score_matrix, gap_penalty=1):
    # initialization
    n = len(sequence_a) + 1
    m = len(sequence_b) + 1
    needleman_wunsh_matrix = np.zeros((n, m))
    for i in range(n):
        needleman_wunsh_matrix[i, 0] = gap_penalty * i
    for j in range(m):
        needleman_wunsh_matrix[0, j] = gap_penalty * j
    # dynamic programming
    for i in range(1, n):
        for j in range(1, m):
            match = needleman_wunsh_matrix[i - 1, j - 1] + score_matrix[i - 1, j - 1]
            delete = needleman_wunsh_matrix[i - 1, j] + gap_penalty
            insert = needleman_wunsh_matrix[i, j - 1] + gap_penalty
            needleman_wunsh_matrix[i, j] = max([match, insert, delete])
    return needleman_wunsh_matrix

def is_approx(first, second, tolerance=0.0001):
    """
    Test if two values are approximately the same.

    Keyword arguments:
    tolerance -- cutoff for allowed difference (default 0.0001)

    >>> is_approx(0.0000, 0.0001)
    False

    >>> is_approx(0.0000, 0.00009)
    True
    """
    if (first + tolerance) > second and (first - tolerance) < second:
        return True
    else:
        return False

def trace_back(sequence_a, sequence_b, score_matrix, needleman_wunsh_matrix, gap_penalty=1):
    alignment_a = ""
    alignment_b = ""
    i = len(sequence_a)
    j = len(sequence_b)
    while i > 0 or j > 0:
        if i > 0 and j > 0 and is_approx(needleman_wunsh_matrix[i, j], needleman_wunsh_matrix[i - 1, j - 1] + score_matrix[i - 1, j - 1]):
            alignment_a = sequence_a[i - 1] + alignment_a
            alignment_b = sequence_b[j - 1] + alignment_b
            i = i - 1
            j = j - 1
        elif i > 0 and is_approx(needleman_wunsh_matrix[i, j], needleman_wunsh_matrix[i - 1, j] + gap_penalty):
            alignment_a = sequence_a[i - 1] + alignment_a
            alignment_b = "-" + alignment_b
            i = i - 1
        elif j > 0 and is_approx(needleman_wunsh_matrix[i, j], needleman_wunsh_matrix[i, j - 1] + gap_penalty):
            alignment_a = "-" + alignment_a
            alignment_b = sequence_b[j - 1] + alignment_b
            j = j - 1
    return alignment_a, alignment_b

def edit_distance(seq_a, seq_b, gap_penalty=-1):
    score_matrix = make_score_matrix(seq_a, seq_b)
    needleman_wunsh_matrix = needleman_wunsh(seq_a, seq_b, score_matrix, gap_penalty)
    nw_score = needleman_wunsh_matrix[-1, -1]
    return nw_score

def align_sequences(seq_a, seq_b, gap_penalty=-1):
    score_matrix = make_score_matrix(seq_a, seq_b)
    needleman_wunsh_matrix = needleman_wunsh(seq_a, seq_b, score_matrix, gap_penalty)
    alignment_a, alignment_b = trace_back(seq_a, seq_b, score_matrix, needleman_wunsh_matrix, gap_penalty)
    return alignment_a, alignment_b

def print_alignment(alignment_a, alignment_b):
    connector = ''.join(['_' if a == b else ' ' for a, b in zip(alignment_a, alignment_b)])
    print connector
    print alignment_a
    print alignment_b


import sys
import numpy as np
from matplotlib import pyplot as plt
import math

def plot_basins(f, Df, roots, xmin, xmax, ymin, ymax, numpoints=100, iters=15, colormap='brg', name='name.png', dpinum=150):
    xreal = np.linspace(xmin, xmax, numpoints)
    ximag = np.linspace(ymin, ymax, numpoints)
    Xreal, Ximag = np.meshgrid(xreal, ximag)
    Xold = Xreal + 1j * Ximag
    for i in xrange(iters):
        Xnew = Xold - f(Xold)/Df(Xold)
        Xold = Xnew
    m,n = Xnew.shape
    for i in xrange(m):
        for j in xrange(n):
            Xnew[i,j] = np.argmin(np.abs(Xnew[i,j]-roots))
    plt.pcolormesh(Xreal, Ximag, Xnew, cmap=colormap)
    plt.savefig(name, bbox_inches='tight', dpi=dpinum)

def fractal_ex():
    f = lambda x:x**3-x
    Df = lambda x:3*x**2-1
    roots1 = np.array([-1,1,0])
    xmin=-1.5
    xmax=1.5
    ymin=-1.5
    ymax=1.5
    plot_basins(f,Df,roots1,xmin,xmax,ymin,ymax, numpoints=700, name='fractal_ex.png')

def fractal_hw():
    xmin=-1.5
    xmax=1.5
    ymin=-1.5
    ymax=1.5
    g = lambda x:x**3-1
    Dg = lambda x:3*x**2
    roots2 = np.array([1, ((-1 + np.sqrt(3)*1j)/2), ((-1 - np.sqrt(3)*1j)/2)])
    plot_basins(g,Dg,roots2,xmin,xmax,ymin,ymax, numpoints=700, name='fractal_hw.png')

def fractal_zoom():
    f = lambda x:x**3-x
    Df = lambda x:3*x**2-1
    roots1 = np.array([-1,0,1])
    xmin=.445
    xmax=.475
    ymin=-.015
    ymax=.015
    plot_basins(f,Df,roots1,xmin,xmax,ymin,ymax, numpoints=700, name='fractal_zoom.png')

if __name__=='__main__':
    fractal_zoom()
    fractal_ex()
    fractal_hw()


import sys
sys.path.append('../autodiff')      # Enable test_autodiff.py to work locally
sys.path.append('autodiff')

from ad import AutoDiff
from vector_forward import Vector_Forward
import numpy as np
import pytest

def test_vector():
    # handling multiple input; each input is a vector; multiple functions
    x = AutoDiff([3, 1, 9], name='x')
    y = AutoDiff([5, 2, 4], name='y')
    f1 = (2 * x ** (-2)) + (3 * y ** 4)
    f2 = AutoDiff.cos(x + (4 * y ** 2))
    v = Vector_Forward([f1, f2])
    assert np.array_equal(v.val()[0], np.array([16877/9, np.cos(103)]))
    assert np.array_equal(v.val()[1], np.array([50, np.cos(17)]))
    assert np.array_equal(v.val()[2], np.array([62210/81, np.cos(73)]))
    index_x = v.jacobian()[0].index("x")
    index_y = v.jacobian()[0].index("y")
    assert np.array_equal(v.jacobian()[1][0][:, index_x], np.array([-4/27, -np.sin(103)]))
    assert np.array_equal(v.jacobian()[1][1][:, index_x], np.array([-4, -np.sin(17)]))
    assert np.array_equal(v.jacobian()[1][2][:, index_x], np.array([-4/729, -np.sin(73)]))
    assert np.array_equal(v.jacobian()[1][0][:, index_y], np.array([12*(5**3), -40*np.sin(103)]))
    assert np.array_equal(v.jacobian()[1][1][:, index_y], np.array([96, -16*np.sin(17)]))
    assert np.array_equal(v.jacobian()[1][2][:, index_y], np.array([12*(4**3), -32*np.sin(73)]))

if __name__ == '__main__':
    test_vector()


import matplotlib.pyplot as plt
import numpy as np
import scipy
import scipy.io

def feature_normalize(samples):
    """
    Feature-normalize samples
    :param samples: samples.
    :return: normalized feature
    """
    means = np.mean(samples,axis=0)
    X_normalized = samples - means

    std = np.std(samples,axis=0,ddof=0)
    X_normalized = X_normalized/std

    return X_normalized

def get_usv(sample_norm):
    m = sample_norm.shape[0]
    Sigma = (1/m)*np.matmul(sample_norm.T,sample_norm)
    U,S,V = scipy.linalg.svd(Sigma)

    return U,S,V

def project_data(samples, U, K):
    """
    Computes the reduced data representation when
    projecting only on to the top "K" eigenvectors
    """

    # Reduced U is the first "K" columns in U
    reduced_U = U[:,0:K]
    reduced_samples = np.matmul(samples,reduced_U)

    return reduced_samples

def recover_data(Z, U, K):
    recovered_sample = np.matmul(Z,U[:,0:K].T)

    return recovered_sample

def main():
    datafile = 'data/data1.mat'
    mat = scipy.io.loadmat(datafile)
    samples = mat['X']

    plt.figure(figsize=(7, 7))
    plt.scatter(samples[:, 0], samples[:, 1], s=30, facecolors='none', edgecolors='b')
    plt.title("Example Dataset", fontsize=18)
    plt.grid(True)
    #plt.show()
    # Feature normalize

    samples_norm = feature_normalize(samples)

    # Run SVD

    U,S,V = get_usv(samples_norm)

    # output the top principal component (eigen- vector) found
    # should expect to see an output of about [-0.707 -0.707]"
    print('Top principal component is ', U[:, 0])

    plt.figure(figsize=(7, 7))
    plt.scatter(samples[:, 0], samples[:, 1], s=30, facecolors='none', edgecolors='b')
    plt.title("Example Dataset: PCA Eigenvectors Shown", fontsize=18)
    plt.xlabel('x1', fontsize=18)
    plt.ylabel('x2', fontsize=18)
    plt.grid(True)
    # To draw the principal component, you draw them starting
    # at the mean of the data

    # IMPLEMENT PLOT
    x_mean = np.mean(samples[:,0])
    y_mean = np.mean(samples[:,1])
    d_x1 = S[0]*U[:,0][0]
    d_y1 = S[0]*U[:,0][1]
    d_x2 = S[1]*U[:,1][0]
    d_y2 = S[1]*U[:,1][1]
    line1 = plt.plot([x_mean,x_mean+d_x1],[y_mean,y_mean+d_y1],color='r',label='First Principal Component',linewidth=3)
    line2 = plt.plot([x_mean,x_mean+d_x2],[y_mean,y_mean+d_y2],color='magenta',label='Second Principal Component',linewidth=3)
    plt.legend(loc=4)

    # project the first example onto the first dimension
    # should see a value of about 1.481"

    z = project_data(samples_norm, U, 1)
    print('Projection of the first example is %0.3f.' % float(z[0]))
    recovered_sample = recover_data(z, U, 1)
    print('Recovered approximation of the first example is ', recovered_sample[0])

    plt.figure(figsize=(7, 7))
    plt.scatter(samples_norm[:, 0], samples_norm[:, 1], s=30, facecolors='none',
                edgecolors='b', label='Original Data Points')
    plt.scatter(recovered_sample[:, 0], recovered_sample[:, 1], s=30, facecolors='none',
                edgecolors='r', label='PCA Reduced Data Points')

    plt.title("Example Dataset: Reduced Dimension Points Shown", fontsize=14)
    plt.xlabel('x1 [Feature Normalized]', fontsize=14)
    plt.ylabel('x2 [Feature Normalized]', fontsize=14)
    plt.grid(True)

    for x in range(samples_norm.shape[0]):
        plt.plot([samples_norm[x, 0], recovered_sample[x, 0]], [samples_norm[x, 1], recovered_sample[x, 1]], 'k--')

    plt.legend(loc=4)
    plt.xlim((-2.5, 2.5))
    plt.ylim((-2.5, 2.5))
    plt.show()

if __name__ == '__main__':
    main()


# LIBRARY IMPORT
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from IPython.display import display
from sklearn.decomposition import PCA

sns.set()

def PCA_2D(data: pd.DataFrame) -> pd.DataFrame:
    """Does the 2D principal component analysis of a dataset provided in the dataframe.

    Data is expressed according to it's two most appropriate axes to explain the variance,
    and this function generates the Pareto Diagram,
    """

    acp = PCA()
    transformed_data = acp.fit_transform(data)

    print(
        f"Variance explained by the two first dimensions: "
        f"{sum(acp.explained_variance_ratio_[:2]) * 100 :.2f} %"
    )

    print("Total variance:", sum(acp.explained_variance_))

    # Plot Pareto diagram to visualize explained variance contributions
    labels = [f"V{i}" for i, _ in enumerate(acp.explained_variance_ratio_)]
    plt.bar(labels, acp.explained_variance_ratio_, width=0.25, label="Variance ratio")
    plt.plot(
        labels, acp.explained_variance_ratio_.cumsum(), "r.-", label="Cumulative sum"
    )
    plt.title("Pareto Diagram")
    plt.legend()

    # Plot data in new base
    plt.figure()
    plt.scatter(transformed_data[:, 0], transformed_data[:, 1])
    for i, name in enumerate(data.index):
        plt.annotate(
            name,
            (transformed_data[i, 0], transformed_data[i, 1]),
            xytext=(2, 2),
            textcoords="offset points",
        )
    plt.title("Dataset in new axes")

    # Calculate correlations between new data (Xproj) and original columns (df):
    corvar = np.zeros((len(data.columns), 2))
    for i, _ in enumerate(data.columns):
        corvar[i, 0] = np.corrcoef(transformed_data[:, 0], data.iloc[:, i])[0, 1]
        corvar[i, 1] = np.corrcoef(transformed_data[:, 1], data.iloc[:, i])[0, 1]

    # Correlation circle
    _, axes = plt.subplots(figsize=(8, 8))
    axes.set_xlim(-1, 1)
    axes.set_ylim(-1, 1)

    # Draw axes
    plt.plot([-1, 1], [0, 0], color="silver", linestyle="-", linewidth=1)
    plt.plot([0, 0], [-1, 1], color="silver", linestyle="-", linewidth=1)
    # Draw circle
    cercle = plt.Circle((0, 0), 1, color="blue", fill=False)
    axes.add_artist(cercle)
    plt.xlabel("Principal component 1")
    plt.ylabel("Principal component 2")
    plt.title("Correlation circle")
    plt.scatter(corvar[:, 0], corvar[:, 1])
    # Draw data column names
    for j, _ in enumerate(data.columns):
        plt.annotate(
            data.columns[j],
            (corvar[j, 0], corvar[j, 1]),
            xytext=(2, 2),
            textcoords="offset points",
        )

    return pd.DataFrame(transformed_data, index=data.index)

if __name__ == "__main__":
    df = pd.read_excel(
        "datasets/Temperatures.xlsx", sheet_name=0, header=0, index_col=0
    )
    new_data = PCA_2D(df)
    display(new_data)

    plt.show()


import numpy as np

def rowwise_cosine(y_true, y_pred):
  """
  https://stackoverflow.com/questions/49218285/cosine-similarity-between-matching-rows-in-numpy-ndarrays
  """
  return 1 - np.einsum('ij,ij->i', y_true, y_pred) / (
              np.linalg.norm(y_true, axis=1) * np.linalg.norm(y_pred, axis=1)
    )

def rowwise_mse(y_true, y_pred):
  return np.square(np.subtract(y_true, y_pred)).mean(1)

def rowwise_rmse(y_true, y_pred):
  return np.sqrt(np.square(np.subtract(y_true, y_pred)).mean(1))


import numpy as np

x1 = np.array([1,2])
x2 = np.zeros((1,2))

print(x1,x1.shape)
print(x2,x2.shape)

x3 = np.array([[1,2],[3,4],[5,6]])
print(x3[1:,1:],type(x3[1:,1:]),x3[1:,1:].shape)
print(x3[1:,:])

print(" - -- - - - -")
a = np.array([[1,2], [3, 4], [5, 6]])

print(a)
# 这里打印了 a[0,0],a[1,1]
print(a[[0, 1], [0, 1]])  # Prints "[1 4]"
print(a[0])
print(a[[0,1]])


# This file implements correct quaternion averaging.
# https://github.com/christophhagen/averaging-quaternions/blob/master/README.md

import numpy
import numpy.matlib as npm

# Q is a Nx4 numpy matrix and contains the quaternions to average in the rows.
# The quaternions are arranged as (w,x,y,z), with w being the scalar
# The result will be the average quaternion of the input. Note that the signs
# of the output quaternion can be reversed, since q and -q describe the same orientation
def averageQuaternions(Q):
    # Number of quaternions to average
    M = Q.shape[0]
    A = npm.zeros(shape=(4,4))

    for i in range(0,M):
        q = Q[i,:]
        # multiply q with its transposed version q' and add A
        A = numpy.outer(q,q) + A

    # scale
    A = (1.0/M)*A
    # compute eigenvalues and -vectors
    eigenValues, eigenVectors = numpy.linalg.eig(A)
    # Sort by largest eigenvalue
    eigenVectors = eigenVectors[:,eigenValues.argsort()[::-1]]
    # return the real part of the largest eigenvector (has only real part)
    return numpy.real(eigenVectors[:,0].A1)

# Average multiple quaternions with specific weights
# The weight vector w must be of the same length as the number of rows in the
# quaternion maxtrix Q
def weightedAverageQuaternions(Q, w):
    # Number of quaternions to average
    M = Q.shape[0]
    A = npm.zeros(shape=(4,4))
    weightSum = 0

    for i in range(0,M):
        q = Q[i,:]
        A = w[i] * numpy.outer(q,q) + A
        weightSum += w[i]

    # scale
    A = (1.0/weightSum) * A

    # compute eigenvalues and -vectors
    eigenValues, eigenVectors = numpy.linalg.eig(A)

    # Sort by largest eigenvalue
    eigenVectors = eigenVectors[:,eigenValues.argsort()[::-1]]

    # return the real part of the largest eigenvector (has only real part)
    return numpy.real(eigenVectors[:,0].A1)


import numpy as np

def generate_mvnormal_clusters(mus, covs, sizes, seed=None):

    if seed is not None:
        np.random.seed(seed)

    n_points = sum(sizes)
    xs = np.zeros(n_points)
    ys = np.zeros(n_points)
    labels = np.zeros(n_points, dtype=int)

    start_from = 0
    lb = 0
    for mu, cov, sz in zip(mus, covs, sizes):

        x, y = np.random.multivariate_normal(mu, cov, sz).T

        next_start_from = start_from + sz

        xs[start_from:next_start_from] = x
        ys[start_from:next_start_from] = y
        labels[start_from:next_start_from] = lb

        start_from = next_start_from
        lb += 1

    return xs, ys, labels

def generate_normal_clusters(mus, stddevs, sizes, seed=None):

    if seed is not None:
        np.random.seed(seed)

    n_points = sum(sizes)
    xs = np.zeros(n_points)
    labels = np.zeros(n_points, dtype=int)

    start_from = 0
    lb = 0
    for mu, std, sz in zip(mus, stddevs, sizes):

        x = np.random.normal(mu, std, sz)

        next_start_from = start_from + sz

        xs[start_from:next_start_from] = x
        labels[start_from:next_start_from] = lb

        start_from = next_start_from
        lb += 1

    return xs, labels


'''
While pandas and NumPy have tons of functions, sometimes you may need a different function to summarize your data.

The .agg() method allows you to apply your own custom functions to a DataFrame, as well as apply functions to more than one column of a DataFrame at once, making your aggregations super efficient.

In the custom function for this exercise, "IQR" is short for inter-quartile range, which is the 75th percentile minus the 25th percentile. It's an alternative to standard deviation that is helpful if your data contains outliers.
'''
# Import NumPy and create custom IQR function
import numpy as np
def iqr(column):
    return column.quantile(0.75) - column.quantile(0.25)

# Update to print IQR and median of temperature_c, fuel_price_usd_per_l, & unemployment
print(sales[["temperature_c", "fuel_price_usd_per_l", "unemployment"]].agg([iqr, np.median]))

14 - Data manipulation with Pandas/chapter 2 - Aggregating Data/3 - Efficient summaries.py


import numpy as np

def griewank(P):
    return (
        1
        + (P**2).sum(axis=1) / 4000
        - np.prod(
            np.cos(
                P/np.sqrt(
                    np.arange(1, P.shape[-1] + 1)
                )
            ),
            axis=1
        )
    )

def rast(P):
    n = P.shape[-1]
    return (
        P**2 - 10 * np.cos(2*np.pi * P)
    ).sum(axis=1) + 10*n

def schw(P):
    n = P.shape[-1]
    return np.sum(
        P * np.sin(
            np.sqrt(
                np.abs(P)
            )
        ),
        axis=1
    ) + 418.9829*n

def dp(P):
    return (P[..., 0]-1)**2 + np.sum(
        (
            2 * P[..., 1:]**2 - P[..., :-1]**2
        )**2 *
        np.arange(2, P.shape[-1] + 1), axis=1
    )

def sphere(P):
    return np.sum(
        P**2,
        axis=1
    )


import numpy as np

def sphere_vol_to_r(v): return (3*v/(4*np.pi))**(1/3)

def cube_vol_to_r(v): return np.cbrt(v)

def calculate_delta(D, dt): return np.sqrt(6*D*dt)

def calculate_opt_dt(a, D): return (a*0.1) / (6*D)


import numpy as np
import pandas as pd
from sklearn import preprocessing

data = pd.read_csv('./problem2_1_feature.csv',encoding='gbk')
# del data['Unnamed: 0']
del data['index']
a = data.head()

# def pca(data,alpha=0.85):
def pca(data,n_components):
    assert n_components <= data.shape[1]

    scaler = preprocessing.StandardScaler().fit(data)
    input = scaler.transform(data).astype(dtype='float32')

    cor = np.corrcoef(input)

    eigvalue = np.linalg.eig(cor)[0].astype(dtype='float32')
    eigvector = np.linalg.eig(cor)[1].astype(dtype='float32')

    # 贡献率，并按照升序排序
    contribute = [item / np.sum(eigvalue) for item in eigvalue]
    sort = np.argsort(contribute)

    pca = []

    # token = 0
    # i = 1
    # while token <= alpha:
    #     # len(input)-i是从后往前提取，即反向
    #     token += contribute[sort[len(input) - i]]
    #     pca.append(sort[len(input) - i])
    #     i += 1

    i = 1
    while i <= n_components:
        pca.append(sort[len(input) - i])
        i += 1

    pca_eig = {}
    for i in range(len(pca)):
        pca_eig[i+1] = [eigvalue[pca[i]]/sum(eigvalue),eigvector[pca[i]]]
    return pca_eig

x = pca(np.asmatrix(data.values),n_components=3)
print(x)


#!/usr/bin/env python3

import numpy as np

# Calculate Inductance of Rectangle
a = 10                      # length
b = 3
#b = np.sqrt(2*5)
#bInner = 2
#bOuter = 5
d = np.sqrt(a**2 + b**2)    # diagonal
s = 4e-6                    # section surface of wire
rho = np.sqrt(s/np.pi)      # radius of wire
mu0 = 4*np.pi*1e-7          # electromagnetic constant

# Terms for Inductance Calculation
A = (a+b)*np.log(2*a*b/rho)
B = a*np.log(a+d)
C = b*np.log(b+d)
D = 7/4 * (a+b)
E = 2*(d+rho)

# Inductance
Lrect = mu0/np.pi * (A - B - C - D + E)

print("Panel Array Rectangle Inductance: ", Lrect*1e6, "muH")

# Calculate Inductance of Two-Wire Setup
dw = 20e-3 # distance between wires
l  = 20    # length of single wire

Lwire = mu0*l/np.pi * (np.log(dw/rho)+1/4)
print("Dual-Wire Inductance: ", Lwire*1e6, "muH")

# Calculate Inductance of PV Panel Wiring
# Middle wires
lPV = 1.5
dPV = 125e-3
LPVmiddle = mu0*lPV/(2*np.pi) * (np.log(dPV/rho) + 1/4-np.log(4/3))
LPVouter  = mu0*lPV/(2*np.pi) * (np.log(dPV/rho) + 1/4-np.log(3/2))
LPV2nd    = mu0*lPV/(2*np.pi) * (np.log(dPV/rho) + 1/4-np.log(8/3))

#print(LPVmiddle)
#print(LPV2nd)
#print(LPVouter)

LPVPanel = (LPVmiddle + LPVouter + LPV2nd)*2*20
print("Total Panel Wiring Inductance: ", LPVPanel*1e6, "muH")

print("Total Inductance of DC Line: ", (Lrect + Lwire + LPVPanel)*1e6, "muH");

# Inductance of Piece of Wire interacting with Signal Coil
lInteract = 10e-3
muCopper = 1.256629e-6
Linteraction = mu0/(2*np.pi)*(np.log(2*lInteract/rho)-1+muCopper/4)
print("Interactive Inductance:", Linteraction, "muH")


import numpy as np

class Perceptron:  # Perceptron class

    # Perceptron constructor
    def __init__(self, n_input, n_ite_max=500, learning_rate=0.25, weight=None, bias=None, seed=1):
        self.n_ite_max = n_ite_max  # max number of training iterations
        self.learning_rate = learning_rate  # training learning rate

        np.random.seed(seed)  # lock random seed
        self.bias = bias if bias is not None else np.random.random()  # bias
        self.weight = weight if weight is not None else np.random.random(n_input)  # weight

    # predict method
    def predict(self, x):
        z = self.weight @ x + self.bias
        return (z >= 0).astype(int)  # return activation

    # training method
    def train(self, training_input, label):

        # training iterations
        for n_ite in range(self.n_ite_max):
            sum_abs_err = 0

            # display bias and weights history
            print(f'ite: {n_ite:d}, b = {self.bias:g}, w = ', self.weight)

            # loop on samples (i)
            for i in range(len(label)):

                # define error
                err = label[i] - self.predict(training_input[:, i])
                sum_abs_err += abs(err)

                # update weights and bias
                self.weight += self.learning_rate * err * training_input[:, i]
                self.bias += self.learning_rate * err

            # stop condition
            if sum_abs_err == 0:
                break


from __future__ import division

import numpy as np
from scipy.linalg import eigh
from lyssa.utils.math import normalize, norm_cols

class l2_normalizer():
    def __call__(self, Z):
        if Z.ndim == 1:
            return normalize(Z)
        elif Z.ndim == 2:
            # e.g a 2D patch in a feature_map
            shape = Z.shape
            return normalize(Z.flatten()).reshape(shape)

def zca_transform(X, bias=.1):
    # each datapoint is a row of X
    n_samples, n_features = X.shape
    # subtracts the mean for each feature vector
    mean_ = np.mean(X, axis=0)
    X -= mean_
    eigs, eigv = eigh(np.dot(X.T, X) / n_samples + \
                      bias * np.identity(n_features))
    components = np.dot(eigv * np.sqrt(1.0 / eigs), eigv.T)
    components_ = components
    # Order the explained variance from greatest to least
    X_transformed = np.dot(X, components_)
    return X_transformed

def local_contrast_normalization(X):
    """apply local constrast normalization to the datapoints in X"""
    X = X.T
    X = X.reshape((X.shape[0], -1))
    X -= X.mean(axis=1)[:, None]
    X_std = X.std(axis=1)
    # This trick is credited to N. Pinto
    min_divisor = (2 * X_std.min() + X_std.mean()) / 3
    X /= np.maximum(min_divisor, X_std).reshape(
        (X.shape[0], 1))
    return X.T

class preproc():
    def __init__(self, name):
        self.name = name

    def __call__(self, X):

        # assumes that each datapoint is a
        # column of the 2D matrix X

        if self.name == 'global_centering':
            # remove the mean of each feature vector
            X = X - X.mean(axis=1)[:, np.newaxis]
        elif self.name == 'global_standarization':
            # remove the mean and
            # divide by the variance of each feature vector
            X = X - X.mean(axis=1)[:, np.newaxis]
            X = X / X.std(axis=1)[:, np.newaxis]
        elif self.name == 'local_centering':
            # remove the mean of each datapoint
            X = X - X.mean(axis=0)[np.newaxis, :]
        elif self.name == 'contrast_normalization':
            # remove the mean of each datapoint
            # and divide by its norm
            X = X - X.mean(axis=0)[np.newaxis, :]
            X = norm_cols(X)
        elif self.name == 'normalization':
            return norm_cols(X)
        elif self.name == 'scaling':
            # scale each pixel in an image
            # to lie in[0,1]
            X = X / 255.
        elif self.name == 'whitening':
            X = zca_transform(X.T).T

        return X


# -*- coding: utf-8 -*-
"""
Created on Sun Nov 29 13:24:17 2020

@author: mclea
"""
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import time

# Domain
L = 1.
n = 101
h = L/(n-1)
x = y = np.linspace(0,L,n)
X,Y = np.meshgrid(x,y)

# Source term
f = np.zeros((n,n))
for i in range(n):
    for j in range(n):
        f[i,j] = 2*x[i]*(x[i]-1)+2*y[j]*(y[j]-1)

# Analytical solution
u_a = np.zeros((n,n))
for i in range(n):
    for j in range(n):
        u_a[i,j] = x[i]*y[j]*(x[i]-1)*(y[j]-1)

# Initial guess
u0 = np.ones((n,n))/20
u0[0,:] = u0[-1,:] = u0[:,0] = u0[:,-1] = 0

# Plot analytical solution & initial guess
fig = plt.figure(figsize=(16,6), dpi=50)
ax = fig.add_subplot(121, projection='3d')
ax.plot_surface(X,Y,u_a,rstride=5,cstride=5), plt.title('Analytical solution')
ax.set_xlabel('x'), ax.set_ylabel('y'), ax.set_zlabel('u'), ax.set_zlim3d(bottom=0,top=0.07)
ax = fig.add_subplot(122, projection='3d')
ax.plot_surface(X,Y,u0,rstride=5,cstride=5), plt.title('Initial guess')
ax.set_xlabel('x'), ax.set_ylabel('y'), ax.set_zlabel('u'), ax.set_zlim3d(bottom=0,top=0.07)
plt.show()

#Jacobi Iteration Method
def error(u):
    error = u-u_a
    err = (abs(error)).max()

    return err

def plt2d(err,it,title):
    fig.add_subplot(111)
    plt.plot(np.arange(1,it+1),err)
    plt.title(title), plt.xlabel('iterations'), plt.ylabel('maximum error')

def jacobi(u,f,h,max_err,max_it):
    t = time.time()

    u_n = u.copy()
    conv = []
    it = 0
    while True:
        it = it+1
        u_n[1:-1,1:-1] = 0.25*(u_n[2:,1:-1] + u_n[:-2,1:-1] + u_n[1:-1,2:] + u_n[1:-1,:-2] - f[1:-1,1:-1]*h*h)

        err = error(u_n)
        conv = np.concatenate((conv,[err]))

        if err < max_err:
            break

        if it > max_it:
            break

    t = time.time() - t

    # print 'Computation time = ' + ('%.5f' %t) + 's'
    # print 'Iterations =', it
    # print 'Maximum error = ' + ('%.4f' %err)
    # #plt3d(u_n, 'Jacobi iteration method')
    # plt2d(conv,it,'Jacobi iteration method')

    return u_n, it, conv, t

u_j, it_j, conv_j, t_j = jacobi(u0,f,h,0.001,10000)

fig = plt.figure(figsize=(16,6), dpi=50)
ax = fig.add_subplot(121, projection='3d')
ax.plot_surface(X, Y, u_a, rstride=5, cstride=5)
plt.title('Analytical solution')
ax.set_xlabel('x'), ax.set_ylabel('y'), ax.set_zlabel('u'), ax.set_zlim3d(bottom=0,top=0.07)
ax = fig.add_subplot(122, projection='3d')
ax.plot_surface(X,Y,u_j,rstride=5,cstride=5), plt.title('Initial guess')
ax.set_xlabel('x'), ax.set_ylabel('y'), ax.set_zlabel('u'), ax.set_zlim3d(bottom=0,top=0.07)
plt.show()

Fluid Dynamics/CFD/Finite Difference Method/Iterative poisson & laplace equations.py


import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-2.,2.,1000)

kSet = [1, 2, 4, 8]
kLabel = [r'$\beta = 1$', r'$\beta = 2$', r'$\beta = 4$', r'$\beta = 8$']
kMarker = ['b-.', 'r--', 'g:', 'k-']
fig = plt.figure()
plt.plot(0, 0.5, 'mo')
plt.plot(x, (x>0), 'm.', linewidth=2, label='$I_{(-\infty, 0]}$')

for i in range(4):
    k = kSet[i]
    y = 1./(1+np.exp(-2*k*x))
    plt.plot(x,y, kMarker[i], label=kLabel[i])
plt.ylim([-0.1,1.1])
plt.legend(fontsize=16, loc='lower right')
plt.xlabel("$x$", fontsize=16)
plt.ylabel(r"$\ell_{\beta}(x)$", fontsize=16)

plt.tick_params(axis='both', which='major', labelsize=16)
plt.tick_params(axis='both', which='minor', labelsize=16)

fig.savefig("figure/logistic_smooth.pdf")

plt.close()

fig = plt.figure()
kSet = [1, 2, 4, 8]
kLabel = ['$\gamma = 1$', '$\gamma = 2$', '$\gamma = 4$', '$\gamma = 8$']
for i in range(4):
    k = kSet[i]
    x = np.linspace(-2./np.sqrt(k), 2./np.sqrt(k), 1000)
    y = k/2.*((x>0)*x)**2
    plt.plot(x, y, kMarker[i], label=kLabel[i])

plt.ylim([-0.1, 2.1])
plt.legend(fontsize=16, loc='lower right')
plt.xlabel("$x$", fontsize=16)
plt.ylabel("$\mathcal{S}_\gamma(x)$", fontsize=16)

plt.tick_params(axis='both', which='major', labelsize=16)
plt.tick_params(axis='both', which='minor', labelsize=16)

fig.savefig("figure/penalty_function.pdf")

plt.close()


import numpy as np
import itertools
import functools

class PolynomialFeatures:
    """
    polynomial features
    transforms input array with polynomial features
    Example
    =======
    x =
    [[a, b],
    [c, d]]
    y = PolynomialFeatures(degree=2).transform(x)
    y =
    [[1, a, b, a^2, a * b, b^2],
    [1, c, d, c^2, c * d, d^2]]
    """

    def __init__(self, degree=2):
        """
        construct polynomial features
        Parameters
        ----------
        degree : int
        degree of polynomial
        """
        self.degree = degree

    def fit_transform(self, X):
        """
        transforms input array with polynomial features
        Parameters
        ----------
        X : (sample_size, n) ndarray
        input array
        Returns
        -------
        output : (sample_size, 1 + nC1 + ... + nCd) ndarray
        polynomial features
        """
        features = [np.ones(len(X))]
        X = X[np.newaxis, :]
        for degree in range(1, self.degree + 1):
            for items in itertools.combinations_with_replacement(X, degree):
                features.append(functools.reduce(lambda x, y: x * y, items))
        return np.asarray(features).transpose()

class BayesianRegression:
    """
    Bayesian regression model

    w ~ N(w|0, alpha^(-1)I)
    y = X @ w
    t ~ N(t|X @ w, beta^(-1))
    """

    def __init__(self, alpha: float = 1., beta: float = 1.):
        self.alpha = alpha
        self.beta = beta
        self.w_mean = None
        self.w_precision = None

    def _is_prior_defined(self) -> bool:
        return self.w_mean is not None and self.w_precision is not None

    def _get_prior(self, ndim: int) -> tuple:
        if self._is_prior_defined():
            return self.w_mean, self.w_precision
        else:
            return np.zeros(ndim), self.alpha * np.eye(ndim)

    def fit(self, X: np.ndarray, t: np.ndarray):
        """
        bayesian update of parameters given training dataset
        Parameters
        5
        ----------
        X : (N, n_features) np.ndarray
        training data independent variable
        t : (N,) np.ndarray
        training data dependent variable
        """
        mean_prev, precision_prev = self._get_prior(np.size(X, 1))
        w_precision = precision_prev + self.beta * X.T @ X
        w_mean = np.linalg.solve(
            w_precision,
            precision_prev @ mean_prev + self.beta * X.T @ t
        )
        self.w_mean = w_mean
        self.w_precision = w_precision
        self.w_cov = np.linalg.inv(self.w_precision)

    def predict(self, X:np.ndarray, return_std:bool=False, sample_size:int=None):
        """
        return mean and standard deviation of predictive distribution

        Parameters
        ----------
        X : (N, n_features) np.ndarray
            independent variable

        Returns
        -------
        y : (N,) np.ndarray
            mean of the predictive distribution
        y_std : (N,) np.ndarray
            standard deviation of the predictive distribution
        """
        # write your code here
        #todo
        if sample_size is not None:
            w_sample = np.random.multivariate_normal(
                self.w_mean, self.w_cov, size=sample_size
            )
            y_sample = X @ w_sample.T
            return y_sample
        y = X @ self.w_mean

        y_var = 1 / self.beta + np.sum(X @ self.w_cov * X, axis=1)
        y_std = np.sqrt(y_var)
        return y, y_std

def rmse(a, b):
    return np.sqrt(np.mean(np.square(a - b)))

def main():
    n, m = input().split()
    x_train = []
    x_test = []
    y_train = []
    y_test = []
    for _ in range(int(n)):
        x, y = input().split()
        x_train.append(float(x))
        y_train.append(float(y))
    for _ in range(int(m)):
        x, y = input().split()
        x_test.append(float(x))
        y_test.append(float(y))
    x_train = np.array(x_train)
    x_test = np.array(x_test)
    y_train = np.array(y_train)
    y_test = np.array(y_test)

    # write your code here
    #todo
    model = PolynomialFeatures(degree=10)
    x_transform_train = model.fit_transform(x_train)
    x_transform_test = model.fit_transform(x_test)
    bayes=BayesianRegression()
    bayes.fit(x_transform_train,y_train)
    y_predict_test,y_std_test = bayes.predict(x_transform_test)
    y_predict_train = bayes.predict(x_transform_train)
    print("{0:.6f}".format(rmse(y_predict_test,y_test)))
    for lines in y_std_test:
        print(round(lines,6))
    # print(rmse(y_predict_train,y_train))

if __name__ == '__main__':
    main()


import numpy as np

###########################################################
def gaussseidel(A,B):
    # Método de GaussSeidel (Gladston Moreira)
    """
    input A = nxn array
          B = nx1 array
    """
    # Verifica se o sistema é compatível
    d = np.linalg.det(A)
    if d==0:
        print('Sistema não é compatível')

    # Estimativa Inicial
    n = len(A)
    X = np.zeros((n, 1))
    Xk = np.copy(X)

    # Verifica condições de convergência
    for i in range(n):
        L = 0 # Soma dos elementos "não-pivô" de uma linha
        C = 0 # Soma dos elementos "não-pivô" de uma coluna

        # Critério das linhas
        for j in range(n):
            if j != i:
                L += abs(A[i, j])

        # Critério das colunas
        for k in range(n):
            if k != i:
                C += abs(A[k, i])

        if L > abs(A[i, i]):
            print('Linha', i+1, ' não satisfaz critério das linhas')
            break
        elif C > abs(A[i, i]):
            print('Coluna', i+1, ' não satisfaz critério das colunas')
            break

    #Critérios de parada
    maxiter = 10
    minDelta = 1e-09
    delta = 1

    # Contador
    k = 0
    print('\nk -\t X \t\t- \t\t max |X(k) - X(k-1)| ')
    print(k,'\t',np.transpose(X),'\t\t\t---')
    while k < maxiter and delta > minDelta:
        # Para cada linha
        for i in range(n):
            # Quantidade de componentes atualizados, e que serão utilizados no cálculo de x(i)k
            numero_componentes_atualizados = i
            # Multiplica e soma elementos conhecidos e joga para o outro lado
            soma = B[i, 0]
            for j in range(n): # Cada coluna da linha em questão
                if i != j: # Xk será utilizado para armazenar o valor das variáveis x, na iteração k-1
                    if numero_componentes_atualizados > 0:
                        soma += (A[i, j] * (-1)) * X[j, 0]
                        numero_componentes_atualizados -= 1
                    else:
                        soma += (A[i, j] * (-1)) * Xk[j, 0]
            soma /= A[i, i]
            X[i, 0] = soma

        # calcula max|x(i)k-x(i)k-1|
        lista_auxiliar = [] # Armazena os valores de |x(i)k - x(i)k-1| para cada linha da matriz X
        for i in range(n):
            lista_auxiliar.append(abs(X[i, 0] - Xk[i, 0]))
        delta = max(lista_auxiliar)

        # interação
        k = k + 1
        # print k -- xk   --  max|x(i)k-x(i)k-1|
        print(k,'\t',np.transpose(X),'\t\t\t',delta)
        Xk = np.copy(X) # Xk será utilizado para armazenar o valor das variáveis x, na iteração k-1

    print('X:')
    print(X)
    return X

# Teste
print('= Teste 1 =\n')
A = np.array([[9, 3, 1],
              [9, 11, 1.3],
              [1.3, 9, -7]])
B = np.array([[7],
              [8],
              [6]])
X = gaussseidel(A, B)
print('\n')

materias 4 periodo/calculo numerico/atividades/atv2/python/p2.py


"""Contains the quadratic cost function."""

import numpy as np

def quadratic_cost(x: np.ndarray, y: np.ndarray) -> float:
    """
    Calculate the mean square error of the input and output values.

    https://www.bitlog.com/knowledge-base/machine-learning/cost-function/#quadratic-cost

    Parameters
    ----------
    x : np.ndarray
        A vector of the estimates. Must be a vector.
    y : np.ndarray
        A vector of the actual values. Must match x's dimensions.

    """
    if x.ndim != 1:
        raise ValueError("Can only compute the quadratic cost for vectors")

    if x.shape != y.shape:
        raise ValueError(
            "Can only compute the quadratic cost of two vectors of equal shape"
        )

    num_samples = x.shape[0]

    return float(np.sum((x - y) ** 2)) / num_samples


'''
Created on 2020-04-07 16:21:24
Last modified on 2020-09-30 11:35:23

@author: L. F. Pereira (lfpereira@fe.up.pt)

Main goal
---------
Show that the square root of a matrix is working properly.

Notes
-----
-scipy could be used in the scripts, but it does not exist in Abaqus.
'''

# imports

# third-party
import numpy as np
from f3dasm.misc.linalg import symmetricize_vector
from f3dasm.misc.linalg import sqrtm

# initialization

a = [1.831, 0.731, 0.985]
b = [2.031, 0.162, 2.021, 1.245, 0, 2.561]

# computations

# get matrices
A = symmetricize_vector(a)
B = symmetricize_vector(b)

# get matrices square roots
A_sqrt = sqrtm(A)
B_sqrt = sqrtm(B)

# print results

print('2D:')
print('A:', A)
print('sqrtm(A):', A_sqrt)
print('verification:', A - np.matmul(A_sqrt, A_sqrt))
print('3D:')
print('B:', B)
print('sqrtm(B):', B_sqrt)
print('verification:', B - np.matmul(B_sqrt, B_sqrt))


import scipy as sp
from scipy import linalg as la

def dct_mat(n):
    """Construct an nxn DCT matrix"""
    tmp = sp.array(sp.cos([(j*.5)*k*sp.pi/n for j in range(n) for k in range(n)]).reshape((n,n))).T
    return sp.array([i/la.norm(i) for i in tmp])

def dct1d_expr(data, blksize, npoints=200, terms=-1):
    """Interpolate single dimensional data using the previously calculated DCT coefficients"""
    data = data.astype(float)#s.flatten()

    n = float(len(data))
    x_points = sp.linspace(0,n,float(npoints))

    n = len(data)
    #xy = sp.math.sqrt(npoints)
    #precalculate some often-used values
    sqrt1n = sp.math.sqrt(1.0/n)
    sqrt2n = sp.math.sqrt(2.0/n)
    n2 = 2.0*n

    tmp = lambda t: sp.sum([co*sp.math.cos((i*sp.pi*(2.0*t+1.0))/n2) for co,i in zip(data[1:terms], sp.arange(1.0,n))])
    y_points = sp.array([sqrt1n*data[0]+sqrt2n*tmp(tvals) for tvals in sp.linspace(0.0, n, npoints)])
    return x_points, y_points
    #return x_points.reshape((n,1)), y_points.reshape((1,n)), z_points.reshape((n,n))

def dct2d_ex(data, blksize, npoints, terms=-1):
    x,y,z1,z2 = None, None, None, None
    for row in data:
        x,z1 = dct1d_expr(row, blksize, npoints, terms)

    for col in data.T:
        y,z2 = dct1d_expr(col, blksize, npoints, terms)

    return x,y,z1,z2

def dct2d_expr(data, npoints, terms=-1):
    n = float(len(data))
    data = data.astype('float32')
    x_points = y_points = sp.linspace(0,n,float(npoints))

    n = len(vec)
    #xy = sp.math.sqrt(npoints)
    #precalculate some often-used values
    sqrt2n = 2.0*sp.math.sqrt(n)
    #sqrt2n = sp.math.sqrt(2.0/n)
    n2 = 2.0*n

    tmp = lambda s, t: sp.sum([sp.sum(co*ak*al*sp.math.cos((i*sp.pi*(2.0*s+1.0))/n2)*sp.math.cos((j*sp.pi*(2.0*t+1.0))/n2)) for co,i,j,ak,al in zip(vec[1:terms])])
    z_points = None

def quantize(DCT, QuantMat=None, inverse=False):
    """Quantize a DCT coefficient matrix.  If QuantMat is None and DCT.shape is (8,8)
    then the standard JPEG quantization matrix is used.

    Otherwise if QuantMat is None then a random integer matrix is generated with values
    in the range of 10...121 (the min and max of the standard JPEG quantization matrix)

    QuantMat must be the same shape as DCT."""
    if QuantMat is None and DCT.shape == (8,8):
        QuantMat = sp.array([[16,11,10,16,24,40,51,61],
                            [12,12,14,19,26,58,60,55],
                            [ 14,13,16,24,40,57,69,56],
                            [ 14,17,22,29,51,87,80,62],
                            [ 18,22,37,56,68,109,103,77],
                            [ 24,35,55,64,81,104,113,92],
                            [ 49,64,78,87,103,121,120,101],
                            [ 72,92,95,98,112,100,103,99]])
    else:
        QuantMat = sp.random.randint(10,121,size=DCT.shape)

    if inverse is True:
        return DCT*QuantMat
    else:
        return DCT/QuantMat

def dct_basis(X, blksize):
    """Calculate DCT coefficients using the basis matrices"""

    bmatr = basis_mats(blksize, plot=False)
    return [sp.dot(X, B) for B in bmatr]

def dct(X, blksize):
    """Perform the DCT transform on X using blksize.
    If X.shape > blksize then X will tiled"""

    #Xshape, Yshape = X.shape
    #if Xshape % blksize == 0 and Yshape % blksize == 0:
        #output = sp.zeros(X.shape)
        #for
    return sp.dot(dct_mat(blksize), X)

def idct(Y, blksize):
    return sp.dot(dct_mat(blksize).T, Y)

def dct2(X, blksize):
    """Calculate DCT transform of a 2D array, X

    In order for this work, we have to split X into blksize chunks"""
    dctm = dct_mat(blksize)

    #try:
    #blks = [sp.vsplit(x, X.shape[1]/blksize) for x in sp.hsplit(X, X.shape[0]/blksize)]
    #except:
    #    print "Some error occurred"

    output = sp.zeros(X.shape)
    if output.ndim==3:
        for i in range(blksize,X.shape[0],blksize):
            for j in range(blksize, X.shape[1], blksize):
                for c in range(X.shape[2]):
                    b = X[i-blksize:i, j-blksize:j, c]
                    output[i-blksize:i, j-blksize:j, c] = sp.dot(sp.dot(dctm,b),dctm.T)
    elif output.ndim==2:
        for i in range(blksize,X.shape[0],blksize):
            for j in range(blksize, X.shape[1], blksize):
                b = X[i-blksize:i, j-blksize:j]
                output[i-blksize:i, j-blksize:j] = sp.dot(sp.dot(dctm,b),dctm.T)

    #blks = [sp.dot(sp.dot(dctm, b), dctm.T) for b in blks]
    #return sp.concatenate([blk for blk in blks]).reshape(X.shape)
    return output

def idct2(X, blksize):
    """Calculate the inverse DCT transform of a 2D array, X"""
    dctm = dct_mat(blksize)

    #try:
    #blks = [sp.vsplit(x, X.shape[1]/blksize) for x in sp.hsplit(X, X.shape[0]/blksize)]
    #except:
    #    print "Some error occurred"

    output = sp.zeros(X.shape)
    if output.ndim==3:
        for i in range(blksize,X.shape[0],blksize):
            for j in range(blksize, X.shape[1], blksize):
                for c in range(X.shape[2]):
                    b = X[i-blksize:i, j-blksize:j, c]
                    output[i-blksize:i, j-blksize:j, c] = sp.dot(sp.dot(dctm,b),dctm.T)
    elif output.ndim==2:
        for i in range(blksize,X.shape[0],blksize):
            for j in range(blksize, X.shape[1], blksize):
                b = X[i-blksize:i, j-blksize:j]
                output[i-blksize:i, j-blksize:j] = sp.dot(sp.dot(dctm.T,b),dctm)
    #blks = [sp.dot(sp.dot(dctm.T, b), dctm) for b in blks]
    #return sp.concatenate([blk for blk in blks]).reshape(X.shape)
    return output

def basis_mats(blksize=8, plot=False):
    """Compute the basis matrices of the DCT matrix"""

    matr = dct_mat(blksize)
    bmatr = [sp.outer(matr[i], matr[j]) for i in range(blksize) for j in range(blksize)]
    if plot is True:
        ret = sp.zeros((blksize**2, blksize**2))
        for i in range(blksize):
            for j in range(blksize):
                ret[i*blksize:(i+1)*blksize, j*blksize:(j+1)*blksize] = bmatr[i+j*blksize]
        return ret
    else:
        return bmatr


#Ref: Sreenivas Sarwar Anik

import cv2
from matplotlib import pyplot as plt
import numpy as np

img = cv2.imread('images/BSE.jpg', 0) # load an image

#Output is a 2D complex array. 1st channel real and 2nd imaginary
#For fft in opencv input image needs to be converted to float32
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)

#Rearranges a Fourier transform X by shifting the zero-frequency
#component to the center of the array.
#Otherwise it starts at the tope left corenr of the image (array)
dft_shift = np.fft.fftshift(dft)

##Magnitude of the function is 20.log(abs(f))
#For values that are 0 we may end up with indeterminate values for log.
#So we can add 1 to the array to avoid seeing a warning.
magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))

# Circular HPF mask, center circle is 0, remaining all ones
#Can be used for edge detection because low frequencies at center are blocked
#and only high frequencies are allowed. Edges are high frequency components.
#Amplifies noise.

rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)

mask = np.ones((rows, cols, 2), np.uint8)
r = 80
center = [crow, ccol]
x, y = np.ogrid[:rows, :cols]
mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r*r
mask[mask_area] = 0

# Circular LPF mask, center circle is 1, remaining all zeros
# Only allows low frequency components - smooth regions
#Can smooth out noise but blurs edges.
#
"""
rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)

mask = np.zeros((rows, cols, 2), np.uint8)
r = 100
center = [crow, ccol]
x, y = np.ogrid[:rows, :cols]
mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r*r
mask[mask_area] = 1

# Band Pass Filter - Concentric circle mask, only the points living in concentric circle are ones
rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)

mask = np.zeros((rows, cols, 2), np.uint8)
r_out = 80
r_in = 10
center = [crow, ccol]
x, y = np.ogrid[:rows, :cols]
mask_area = np.logical_and(((x - center[0]) ** 2 + (y - center[1]) ** 2 >= r_in ** 2),
                           ((x - center[0]) ** 2 + (y - center[1]) ** 2 <= r_out ** 2))
mask[mask_area] = 1
"""

# apply mask and inverse DFT
fshift = dft_shift * mask

fshift_mask_mag = 2000 * np.log(cv2.magnitude(fshift[:, :, 0], fshift[:, :, 1]))

f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])

fig = plt.figure(figsize=(12, 12))
ax1 = fig.add_subplot(2,2,1)
ax1.imshow(img, cmap='gray')
ax1.title.set_text('Input Image')
ax2 = fig.add_subplot(2,2,2)
ax2.imshow(magnitude_spectrum, cmap='gray')
ax2.title.set_text('FFT of image')
ax3 = fig.add_subplot(2,2,3)
ax3.imshow(fshift_mask_mag, cmap='gray')
ax3.title.set_text('FFT + Mask')
ax4 = fig.add_subplot(2,2,4)
ax4.imshow(img_back, cmap='gray')
ax4.title.set_text('After inverse FFT')
plt.show()


''' mbinary
#########################################################################
# File : least_square.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.xyz
# Github: https://github.com/mbinary
# Created Time: 2018-10-02  21:14
# Description:
#########################################################################
'''

'''*************************************************************************
    > File Name: least-square.py
    > Author: mbinary
    > Mail: zhuheqin1@gmail.com
    > Created Time: Sat 07 Apr 2018 09:55:25 PM DST
    > Blog: https://mbinary.xyz
    > Description: 最小二乘法解线性方程组, 解矛盾方程组
 ************************************************************************'''

import re
import numpy as np
def solveConflitEqualtion(A, y):
    '''solve equation like this: Av = y,
        A:m*n  v:n*1  y:m*1
        return vector v
    '''
    A = np.matrix(A)
    y = np.array(y)
    ata = A.T*A
    print('AtA')
    print(ata)
    return np.linalg.solve(ata, A.T*y)  # note that is numpy.linalg.solve

def solveLinear(point, index):
    y = [[i[1]] for i in point]
    x = [[i[0]] for i in point]
    A = []
    for i in x:
        A.append([i[0]**j for j in index])
    res = solveConflitEqualtion(A, y)
    print('the solution is : \n', res)
    print('namely: ')
    items = ['{:.4f}x^{}'.format(res[i, 0], j) for i, j in enumerate(index)]
    print('phi(x) = ', ' + '.join(items))

def handleInput(s=None, y=None):
    # numPt = re.compile (r'\d*\.{0,1}\d+')
    if not s:
        s = input('input matrix A:m*n  //m>=n\n')
    s = s.replace(' ', '')
    li = re.findall(r'(\[(\d+)(,(\d+))+\])', s)
    li = [parseLst(i[0]) for i in li]
    if not y:
        y = input('input a vector y:n*1\n')
    y = parseLst(y)
    print('Equation: Av = y:')

    print('y is as follows: ')
    print(y)
    print('A is as follows: ')
    for i in li:
        for j in i:
            print('{}'.format(j).rjust(5), end='')
        print('')

    print('result v is as follows: ')
    res = solveConflitEqualtion(li, y)
    print(res)

def parseLst(s):
    s = s.strip('[]')
    li = s.split(',')
    li = [float(j) for j in li]
    return li

if __name__ == '__main__':
    '''
    li = '[[23,2],[2,5],[2,6]]'
    y = '[1,3]'
    while True:
        handleInput(li,y)
        s = input('input y to continue, n for exit')
        if s!='y':break
    '''
    point = [(-3, 14.3), (-2, 8.3), (-1, 4.7), (2, -8.3), (4, -22.7)]
    lst = [0, 3]
    solveLinear(point, lst)

    point = [(-3, 14.3), (-2, 8.3), (-1, 4.7), (2, 8.3), (4, 22.7)]
    lst = [0, 2]
    solveLinear(point, lst)

    A = [[1, 2], [2, 1], [1, 1]]
    y = [[5], [6], [4]]
    res = solveConflitEqualtion(A, y)

    print(res)
    A = [[1, -2], [1, 5], [2, 1], [1, 1]]
    y = [[1], [13.1], [7.9], [5.1]]
    print(solveConflitEqualtion(A, y))


import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
from matplotlib import rc

# Exercise one
w = 1.0
Q = np.inf
m = 1.0
F = 1.0

rc('text', usetex=True)
linestyles = ['-', '--', '-.', ':']
initial = [0,0]
t_start = 0
t_end = 20

def solvr(Y, t):
    return [Y[1], -w*w*Y[0]-(w/Q)*Y[1]+F*np.cos(w*t)/m]
def ex1():
    a_t = np.arange(t_start, t_end, 0.01)
    asol = integrate.odeint(solvr, initial, a_t)
    plt.plot(a_t, asol[:,0], label=r'$Q = \infty$')
    plt.xlabel("t (s)")
    plt.ylabel("x(t) (m)")
    #plt.ylim(-5000, 5000)
    plt.ticklabel_format(style='sci', axis='y', scilimits=(-3,3))
    plt.legend()
    plt.show()

#exercise two

def plot2(Q):
    plt.figure()
    i = 0
    for T in (.1,1,10):
        def solvr(Y, t):
            if(t>T):
                return [Y[1], -w*w*Y[0]-(w/Q)*Y[1]]
            return [Y[1], -w*w*Y[0]-(w/Q)*Y[1]+F*np.cos(w*t)/m]
        a_t = np.arange(t_start, t_end, 0.01)
        asol = integrate.odeint(solvr, initial, a_t)
        plt.plot(a_t, asol[:,0], label="T = "+str(T),linestyle=linestyles[i])
        plt.title(r'$Q = \infty$') if Q == np.inf else plt.title(r'$Q = $'+str(Q))
        plt.xlabel("t (s)")
        plt.ylabel("x(t) (m)")
        plt.ticklabel_format(style='sci', axis='y', scilimits=(-3,3))
        plt.legend()
        i += 1
        plt.savefig("ex2Q="+str(Q)+".pdf")

def ex2():
    for Q in (-1,1,np.inf):
            plot2(Q)

#exercise three

def plot3(Q):
    plt.figure()
    i = 0
    for T in (.1,1,10):
        def solvr(Y, t):
            if(t>T):
                return [Y[1], -w*w*Y[0]-(w/Q)*Y[1]]
            return [Y[1], -w*w*Y[0]-(w/Q)*Y[1]+F*t*(T-t)/(m*T*T)]
        a_t = np.arange(t_start, t_end, 0.01)
        asol = integrate.odeint(solvr, initial, a_t)
        plt.plot(a_t, asol[:,0], label="T = "+str(T), linestyle=linestyles[i])
        plt.xlabel("t (s)")
        plt.ylabel("x(t) (m)")
        plt.title(r'$Q = \infty$') if Q == np.inf else plt.title(r'$Q = $'+str(Q))
        plt.legend()
        plt.ticklabel_format(style='sci', axis='y', scilimits=(-3,3))
        i+=1
        plt.savefig("ex3Q="+str(Q)+".pdf")

def ex3():
    for Q in (-1,1,np.inf):
            plot3(Q)
def main():
    ex1()

if __name__ == '__main__':
    main()


# SVD algorithm
# Álvaro García Tenorio, Belén Serrano Antón

import numpy as np
import matplotlib.pyplot as plt

class SVD:

    #digits represents our matrix of images
    def __init__(self,digits):
        self.digits = digits

    #computes the SVD of our matrix of images
    def computeSVD(self):
       #mean of our data
       Xmean = np.mean(self.digits, axis = 1)
       X = self.digits - Xmean[:, np.newaxis]
       #compute the SVD of X = points - meanOfPoints
       U, D2, Vt = np.linalg.svd(X, full_matrices=False)
       return U, D2, Vt,Xmean

    #compute d = the smallest dimension such that the amount of information
    #that is discarded is less than eps
    def computeDprime(self,D2, dim,eps):
        threshold = 1 - eps
        for d in range(dim):
            if(sum(D2[0:d]) / np.sum(D2) > threshold):
                return d

    #compute the projection of the point num_image (number of the image)
    def reduccionDim(self,d,num_image,U,Xmean):
        # dim(P) = dxd -> dimension reduction
        P = U[:,:d].dot(U[:,:d].T)
        #point
        img = self.digits[:,num_image]
        #poroyection of the point
        img_proj = Xmean + P.dot(img-Xmean)
        return [img,img_proj]

    #prints the given point
    def show_digit(self,dgt):
        return plt.imshow(dgt.reshape((28,28)),cmap='gray')

    #plots a sequence of 10 random numbers. The first row has the proyection
    #of the numbers in the second row. The dimension of the proyection starts in
    #10 and doubles its value in each iteration
    def plotPoints(self,N,U,Xmean):
        fig = plt.figure() #la caja que recoge todas las imágenes que ponemos dentro
        fig_size = 10
        rnd_numbers = np.random.randint(0,N,fig_size)
        d = 10
        for k in range(1,fig_size +1):
            ax = fig.add_subplot(1,10,k)
            solu = self.reduccionDim(d,rnd_numbers[k-1],U,Xmean)
            self.show_digit(solu[0])
            ax = fig.add_subplot(2,10,k)
            self.show_digit(solu[1])
            d = d+d

    #plots a 6x10 grid. Each colum has the proyection of a random number,
    #the dimension of the proyection inscreases from top to bottom
    def plotGrid(self, N,U,Xmean):
        fig = plt.figure()
        fig.subplots_adjust(hspace=0.4, wspace=0.4)
        d = 10
        rnd_numbers = np.random.randint(0,N,10)
        for i in range(1, 61):
            ax = fig.add_subplot(6, 10, i)
            solu = self.reduccionDim(d,rnd_numbers[i%10],U,Xmean)
            self.show_digit(solu[1])
            d = d+5


import numpy as np
import math
from bisect import insort_left

# Author : Jean Kossaifi

def factorize(value, min_value=2, remaining=-1):
    if value <= min_value or remaining == 0:
        return (value, )
    lim = math.isqrt(value)
    for i in range(min_value, lim+1):
        if value == i:
            return (i, )
        if not (value % i):
            return (i, *factorize(value//i, min_value=min_value, remaining=remaining-1))
    return (value, )

def merge_ints(values, size):
    if len(values) <= 1:
        return values

    values = sorted(list(values))
    while (len(values) > size):
        a, b, *values = values
        insort_left(values, a*b)

    return tuple(values)

def get_tensorized_shape(in_features, out_features, order=None, min_dim=2, verbose=True):
    """ Factorizes in_features and out_features such that:
    * they both are factorized into the same number of integers
    * they should both be factorized into `order` integers
    * each of the factors should be at least min_dim

    This is used to tensorize a matrix of size (in_features, out_features) into a higher order tensor

    Parameters
    ----------
    in_features, out_features : int
    order : int
        the number of integers that each input should be factorized into
    min_dim : int
        smallest acceptable integer value for the factors

    Returns
    -------
    in_tensorized, out_tensorized : tuple[int]
        tuples of ints used to tensorize each dimension

    Notes
    -----
    This is a bruteforce solution but is enough for the dimensions we encounter in DNNs
    """
    in_ten = factorize(in_features, min_value=min_dim)
    out_ten = factorize(out_features, min_value=min_dim, remaining=len(in_ten))
    if order is not None:
        merge_size = min(order, len(in_ten), len(out_ten))
    else:
        merge_size = min(len(in_ten), len(out_ten))

    if len(in_ten) > merge_size:
        in_ten = merge_ints(in_ten, size=merge_size)
    if len(out_ten) > merge_size:
        out_ten = merge_ints(out_ten, size=merge_size)

    if verbose:
        print(f'Tensorizing (in, out)=({in_features, out_features}) -> ({in_ten, out_ten})')
    return in_ten, out_ten


#Logic, Control Flow and Filtering

#Equality
# Comparison of booleans
print(True == False)

# Comparison of integers
print(-5 * 15 != 75)

# Comparison of strings
print("pyscript" == "PyScript")

# Compare a boolean with a numeric
print(True == 1)

#Greater and less than
# Comparison of integers
x = -3 * 6
print(x >= -10)

# Comparison of strings
y = "test"
print("test" <= y)

# Comparison of booleans
print(True > False)

#Compare arrays
# Create arrays
import numpy as np
my_house = np.array([18.0, 20.0, 10.75, 9.50])
your_house = np.array([14.0, 24.0, 14.25, 9.0])

# my_house greater than or equal to 18
print(my_house >= 18)

# my_house less than your_house
print(my_house < your_house)

# and, or, not (1)
# Define variables
my_kitchen = 18.0
your_kitchen = 14.0

# my_kitchen bigger than 10 and smaller than 18?
print(my_kitchen > 10 and my_kitchen < 18)

# my_kitchen smaller than 14 or bigger than 17?
print(my_kitchen < 14 or my_kitchen > 17)

# Double my_kitchen smaller than triple your_kitchen?
print(my_kitchen * 2 < your_kitchen * 3)

#Boolean operators with Numpy
# Create arrays
import numpy as np
my_house = np.array([18.0, 20.0, 10.75, 9.50])
your_house = np.array([14.0, 24.0, 14.25, 9.0])

# my_house greater than 18.5 or smaller than 10
print(np.logical_or(my_house > 18.5, my_house < 10))

# Both my_house and your_house smaller than 11
print(np.logical_and(my_house < 11, your_house < 11))

#if
# Define variables
room = "kit"
area = 14.0

# if statement for room
if room == "kit" :
    print("looking around in the kitchen.")

# if statement for area
if area > 15 :
    print("big place!")

#Add else
# Define variables
room = "kit"
area = 14.0

# if-else construct for room
if room == "kit" :
    print("looking around in the kitchen.")
else :
    print("looking around elsewhere.")

# if-else construct for area :
if area > 15 :
    print("big place!")
else :
    print("pretty small.")

##Customize further: elif
# Define variables
room = "bed"
area = 14.0

# if-elif-else construct for room
if room == "kit" :
    print("looking around in the kitchen.")
elif room == "bed":
    print("looking around in the bedroom.")
else :
    print("looking around elsewhere.")

# if-elif-else construct for area
if area > 15 :
    print("big place!")
elif area > 10 :
    print("medium size, nice!")
else :
    print("pretty small.")

#Driving right (1)
# Import cars data
import pandas as pd
cars = pd.read_csv('cars.csv', index_col = 0)

# Extract drives_right column as Series: dr
dr = cars['drives_right']

# Use dr to subset cars: sel
sel = cars[dr]

# Print sel
print(sel)

#Driving right (2)
# Import cars data
import pandas as pd
cars = pd.read_csv('cars.csv', index_col = 0)

# Convert code to a one-liner
sel = cars[cars['drives_right']]

# Print sel
print(sel)

#Cars per capita (1)
# Import cars data
import pandas as pd
cars = pd.read_csv('cars.csv', index_col = 0)

# Create car_maniac: observations that have a cars_per_cap over 500
cpc = cars['cars_per_cap']
many_cars = cpc > 500
car_maniac = cars[many_cars]

# Print car_maniac
print(car_maniac)

#Cars per capita (2)
# Import cars data
import pandas as pd
cars = pd.read_csv('cars.csv', index_col = 0)

# Import numpy, you'll need this
import numpy as np

# Create medium: observations with cars_per_cap between 100 and 500
cpc = cars['cars_per_cap']
between = np.logical_and(cpc > 100, cpc < 500)
medium = cars[between]

# Print medium
print(medium)

Intermediate Python for Data Science/Chapter 3 - Logic, Control Flow and Filtering.py


import matplotlib
import matplotlib.pyplot as plt

import numpy as np

X, Y, RO = 0, 1, 2

def table_read(filename):
    file = open(filename)
    table = [[], [], []]

    for line in file:
        x, y, ro = line.split()
        x = float(x)
        y = float(y)
        ro = float(ro)
        table[X].append(x)
        table[Y].append(y)
        table[RO].append(ro)

    return table

def print_table(table):
    print('┌' + '─' * 20 + '┬' + '─' * 20 + '┬' + '─' * 20 + '┐')
    print('│{:^20}│{:^20}│{:^20}│'.format('x', 'y', 'ρ'))
    print('├' + '─' * 20 + '┼' + '─' * 20 + '┼' + '─' * 20 + '┤')

    for i in range(len(table[X])):
        print('│{:^20.4f}│{:^20.4f}│{:^20.4f}│'.format(table[X][i], table[Y][i], table[RO][i]))

    print('└' + '─' * 20 + '┴' + '─' * 20 + '┴' + '─' * 20 + '┘')

def graph_result(table, coeff, n):
    dx = 10
    if len(table) > 1:
        dx = (table[X][1] - table[X][0])

    x = np.linspace(table[X][0] - dx, table[X][-1] + dx, 100)
    y = []
    for i in x:
        tmp = 0;
        for j in range(0, n + 1):
            tmp += phi(i, j) * coeff[j]
        y.append(tmp)

    plt.plot(x, y, color = 'black')

    x1 = [a for a in table[X]]
    y1 = [a for a in table[Y]]

    plt.plot(x1, y1, 'kD', color = 'green', label = '$исходная таблица$')
    plt.grid(True)
    miny = min(min(y), min(y1))
    maxy = max(max(y), max(y1))
    dy = (maxy - miny) * 0.03
    plt.axis([table[X][0] - dx, table[X][-1] + dx, miny - dy, maxy + dy])

    plt.show()

def phi(x, k):
    return x ** k;

def get_slau(table, n):
    N = len(table[X])
    matrix = [[0 for i in range(0, n + 1)] for j in range (0, n + 1)]
    col = [0 for i in range(0, n + 1)]

    for m in range(0, n + 1):
        for i in range(0, N):
            tmp = table[RO][i] * phi(table[X][i], m)
            for k in range(0, n + 1):
                matrix[m][k] += tmp * phi(table[X][i], k)
            col[m] += tmp * table[Y][i]
    return matrix, col

def find_col(a_copy, i_col):
    n = len(a_copy)
    a = [[a_copy[i][j] for j in range(0, n)] for i in range (0, n)]
    col = [0 for i in range(0, n)]
    for i in range(0, n):
        a[i].append(float(i == i_col))
    for i in range(0, n):
        if a[i][i] == 0:
            for j in range(i + 1, n):
                if a[j][j] != 0:
                    a[i], a[j] = a[j], a[i]
        for j in range(i + 1, n):
            d = - a[j][i] / a[i][i]
            for k in range(0, n + 1):
                a[j][k] += d * a[i][k]
    for i in range(n - 1, -1, -1):
        res = 0
        for j in range(0, n):
            res += a[i][j] * col[j]
        col[i] = (a[i][n] - res) / a[i][i]
    return col

def get_inverse(matrix):
    n = len(matrix)
    res = [[0 for i in range(0, n)] for j in range (0, n)]

    for i in range(0, n):
        col = find_col(matrix, i)
        for j in range(0, n):
            res[j][i] = col[j];
    return res;

def mult(col, b):
    n = len(col)
    new_col = [0 for j in range(0, n)]
    for j in range(0, n):
        for k in range(0, n):
            new_col[j] += col[k] * b[j][k]
    return new_col

def get_aprox(table, n):
    slau, free = get_slau(table, n)
    inverse_slau = get_inverse(slau)
    coeff = mult(free, inverse_slau)
    return coeff

def main():
    filename = input('Введите название файла: ')
    table = table_read(filename)
    print_table(table)
    n = int(input('Введите степень полинома: '))

    coeff = get_aprox(table, n)
    graph_result(table, coeff, n)

    return 0

if __name__ == '__main__':
    main()


#Importing essential libraries
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# Dimesion of x
n_dim = 2

def get_value(x):
    """
    Arguments:
    x: 1 dimensional numpy array as input.
    Returns:
    f(x) : a scalar
    """
    A = np.array([[5.,4],[4,5.]])
    b = np.array([7.,2.])
    return 0.5*np.dot(x, np.dot(A,x)) - np.dot(b,x)

def get_gradient(x):
    """
    Arguments:
    x: 1 dimensional numpy array as input.

    Returns:
    grad f(x) : numpy array with same 1-dimensional shape as input x
    """
    A = np.array([[5.,4],[4.,5.]])
    b = np.array([7.,2.])
    return np.dot(A,x) - b
def gradient_descent_update(x, alpha):
    """
    Arguments:
    x: 1 dimensional numpy array as input. Representing x_t
    alpha: step size

    Returns:
    x_next: 1-dimensional numpy array with same shape as x.
    Representing one Gradient descent step with constant step size eta
    """
    grad = get_gradient(x)
    return x - alpha*grad

#random initialisation of x
x = np.zeros((n_dim)) + np.random.randn(n_dim)*0.1
alpha = 0.2 #step size
n = 20      #number of iterations

f_vals = []  #list to store function value
x_list = []  #list to store x updates

#performing n iterations
for i in range(n):
    x_list.append(x)
    f_vals.append(get_value(x))
    x = gradient_descent_update(x=x, alpha = alpha)

print(x_list)
print(f_vals)

#Please find the plotting functions in the
# Ipython Notebook


import random
import numpy as np
from collections import defaultdict

# def expected(dice_number, sides, target, board):
#     def experiment():
#         current = 0
#         n = 0
#         while current != target:
#             current += round(sum([random.uniform(1,sides) for i in range(dice_number)]))
#             current = current % len(board)
#             while board[current]:
#                 current += board[current]
#             n += 1
#         return n

#     result = []
#     for i in range(100000):
#         result.append(experiment())
#     result = sum(result)/len(result)
#     return result

def expected(dice_number, sides, target, board):
    first_distribution = {}
    for i in range(len(board)):
        first_distribution[i] = 0.
    first_distribution[0] = 1.
    distribution = [first_distribution]

    dices = np.zeros((sides,)*dice_number, dtype=int)
    it = np.nditer(dices, flags=['multi_index'])
    while not it.finished:
        dices[it.multi_index] = np.sum(it.multi_index) + dice_number
        it.iternext()

    unique, counts = np.unique(dices.flatten(), return_counts=True)
    advances = dict(zip(unique, counts))
    total = sum(advances.values())
    for i in advances.keys():
        advances[i] /= total

    def expand():
        last_distribution = distribution[-1]
        next_distribution = {}
        for i in range(len(board)):
            next_distribution[i] = 0.

        for i in last_distribution.keys():
            if i != target or len(distribution) == 1:
                for j in advances.keys():
                    stop = (i+j) % len(board)
                    while board[stop]:
                        stop += board[stop]
                        stop = stop % len(board)
                    # next_distribution[stop] += last_distribution[i]*advances[j]/(sum(last_distribution.values())-last_distribution[target])
                    next_distribution[stop] += last_distribution[i]*advances[j]

        distribution.append(next_distribution)

    for i in range(1000):
        expand()

    expected = 0.
    for i in range(len(distribution)):
        expected += i*distribution[i][target]

    return expected

if __name__ == '__main__':
    #These are only used for self-checking and are not necessary for auto-testing
    def almost_equal(checked, correct, significant_digits=1):
        precision = 0.1 ** significant_digits
        return correct - precision < checked < correct + precision

    assert(almost_equal(expected(1, 4, 3, [0, 0, 0, 0]), 4.0))
    assert(almost_equal(expected(1, 4, 1, [0, 0, 0, 0]), 4.0))
    assert(almost_equal(expected(1, 4, 3, [0, 2, 1, 0]), 1.3))
    assert(almost_equal(expected(1, 4, 3, [0, -1, -2, 0]), 4.0))
    assert(almost_equal(expected(1, 6, 1, [0] * 10), 8.6))
    assert(almost_equal(expected(2, 6, 1, [0] * 10), 10.2))


"""
Basic regression: Predict fuel efficiency
---
In a regression problem, the aim is to predict the output of a continuous value,
like a price or a probability. Contrast this with a classification problem, where
the aim is to select a class from a list of classes (for example, where a picture
contains an apple or an orange, recognizing which fruit is in the picture).
This script uses the classic Auto MPG Dataset and builds a model to predict the
fuel efficiency of late-1970s and early 1980s automobiles. To do this, provide
the model with a description of many automobiles from that time period. This description
includes attributes like: cylinders, displacement, horsepower, and weight.
This example uses the tf.keras API, see this guide for details.
---
Remember to install seaborn
$ pip install -q seaborn
---
Original source: https://www.tensorflow.org/tutorials/keras/regression
"""

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

# Make numpy printous easier to read
np.set_printoptions(precision=3, suppress=True)

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.layers.experimental import preprocessing

def plot_loss(history):
    plt.plot(history.history['loss'], label='loss')
    plt.plot(history.history['val_loss'], label='val_loss')
    plt.ylim([0, 10])
    plt.xlabel('Epoch')
    plt.ylabel('Error [MPG]')
    plt.legend()
    plt.grid(True)

    plt.show()

def plot_horsepower(x, y, train_features, train_labels):
    plt.scatter(train_features['Horsepower'], train_labels, label='Data')
    plt.plot(x, y, color='k', label='Predictions')
    plt.xlabel('Horsepower')
    plt.ylabel('MPG')
    plt.legend()

    plt.show()

def build_and_compile_model(norm):
    model = keras.Sequential([
        norm,
        layers.Dense(64, activation='relu'),
        layers.Dense(64, activation='relu'),
        layers.Dense(1)
    ])

    model.compile(
        optimizer=keras.optimizers.Adam(1e-3),
        loss='mean_absolute_error'
    )

    return model

def main():
    print(f'TensorFlow version: {tf.__version__}')

    # The Auto MPG dataset
    # Get the data

    url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data'
    column_names = [
        'MPG', 'Cylinders', 'Displacement', 'Horsepower', 'Weight',
        'Acceleration', 'Model Year', 'Origin'
    ]

    raw_dataset = pd.read_csv(
        url, names=column_names, na_values='?', comment='\t', sep=' ', skipinitialspace=True
    )
    dataset = raw_dataset.copy()
    print(dataset.tail())

    # Clean the data
    print(f'Dataset NA count: {dataset.isna().sum()}')

    dataset = dataset.dropna()

    # Note: You can set up the keras.Model to do this kind of transformation for you.
    # That's beyond the scope of this tutorial. See the preprocessing layers or
    # Loading CSV data tutorials for examples.

    dataset['Origin'] = dataset['Origin'].map({1: 'USA', 2: 'Europe', 3: 'Japan'})
    dataset = pd.get_dummies(dataset, prefix='', prefix_sep='')
    print(dataset.tail())

    # Split the data into train and test
    train_dataset = dataset.sample(frac=0.8, random_state=0)
    test_dataset = dataset.drop(train_dataset.index)

    # Inspect the data
    sns.pairplot(train_dataset[['MPG', 'Cylinders', 'Displacement', 'Weight']], diag_kind='kde')

    print(train_dataset.describe().transpose())

    # Split features from labels
    train_features = train_dataset.copy()
    test_features = test_dataset.copy()

    train_labels = train_features.pop('MPG')
    test_labels = test_features.pop('MPG')

    # Normalization
    print(train_dataset.describe().transpose()[['mean', 'std']])

    # The Normalization layer
    normalizer = preprocessing.Normalization()
    normalizer.adapt(np.array(train_features))

    print(f'Columns mean value: {normalizer.mean.numpy()}')

    first = np.array(train_features[:1])
    with np.printoptions(precision=2, suppress=True):
        print(f'First example: {first}')
        print()
        print(f'First example normalized: {normalizer(first).numpy()}')

    # Linear regression

    # One variable
    horsepower = np.array(train_features['Horsepower'])

    horsepower_normalizer = preprocessing.Normalization(input_shape=[1,])
    horsepower_normalizer.adapt(horsepower)

    horsepower_model = tf.keras.Sequential([
        horsepower_normalizer,
        layers.Dense(1)
    ])

    print(horsepower_model.summary())

    print(f'Horsepower model preds: {horsepower_model.predict(horsepower[:10])}')

    horsepower_model.compile(
        optimizer=tf.optimizers.Adam(learning_rate=0.1),
        loss='mean_absolute_error'
    )

    history = horsepower_model.fit(
        train_features['Horsepower'], train_labels,
        epochs=100,
        # Suppress logging
        verbose=0,
        # Calculate validation results on 20% of the training data
        validation_split=0.2
    )

    hist = pd.DataFrame(history.history)
    hist['epoch'] = history.epoch
    print(hist.tail())

    plot_loss(history)

    test_results = {}

    test_results['horsepower_model'] = horsepower_model.evaluate(
        test_features['Horsepower'],
        test_labels,
        verbose=0
    )

    x = tf.linspace(0.0, 250, 251)
    y = horsepower_model.predict(x)

    plot_horsepower(x, y, train_features, train_labels)

    # Multiple inputs
    linear_model = tf.keras.Sequential([
        normalizer,
        layers.Dense(1)
    ])

    print(f'Linear model preds: {linear_model.predict(train_features[:10])}')
    print(f'Kernel weights: {linear_model.layers[1].kernel}')

    linear_model.compile(
        optimizer=tf.optimizers.Adam(learning_rate=0.1),
        loss='mean_absolute_error'
    )

    history = linear_model.fit(
        train_features,
        train_labels,
        epochs=100,
        # Suppress logging
        verbose=0,
        # Calculate validation results on 20% of the training data
        validation_split=0.2
    )

    plot_loss(history)

    test_results['linear_model'] = linear_model.evaluate(
        test_features,
        test_labels,
        verbose=0
    )

    # A DNN regression
    # One variable
    dnn_horsepower_model = build_and_compile_model(horsepower_normalizer)
    print(dnn_horsepower_model.summary())

    history = dnn_horsepower_model.fit(
        train_features['Horsepower'],
        train_labels,
        validation_split=0.2,
        verbose=0,
        epochs=100
    )

    plot_loss(history)

    x = tf.linspace(0.0, 250, 251)
    y = dnn_horsepower_model.predict(x)

    plot_horsepower(x, y, train_features, train_labels)

    test_results['dnn_horsepower_model'] = dnn_horsepower_model.evaluate(
        test_features['Horsepower'],
        test_labels,
        verbose=0
    )

    # Full model
    dnn_model = build_and_compile_model(normalizer)
    print(dnn_model.summary())

    history = dnn_model.fit(
        train_features,
        train_labels,
        validation_split=0.2,
        verbose=0,
        epochs=100
    )

    plot_loss(history)

    test_results['dnn_model'] = dnn_model.evaluate(
        test_features,
        test_labels,
        verbose=0
    )

    # Performance
    print(pd.DataFrame(test_results, index=['Mean absolute error [MPG]']).T)

    # Make predicitons
    test_predictions = dnn_model.predict(test_features).flatten()

    a = plt.axes(aspect='equal')
    plt.scatter(test_labels, test_predictions)
    plt.xlabel('True values [MPG]')
    plt.ylabel('Predictions [MPG]')
    lims = [0, 50]
    plt.xlim(lims)
    plt.ylim(lims)
    _ = plt.plot(lims, lims)

    error = test_predictions - test_labels
    plt.hist(error, bins=25)
    plt.xlabel('Prediction Error [MPG]')
    _ = plt.ylabel('Count')

    dnn_model.save('dnn_model')

    reloaded = tf.keras.models.load_model('dnn_model')
    test_results['reloaded'] = reloaded.evaluate(
        test_features,
        test_labels,
        verbose=0
    )

    print(pd.DataFrame(test_results, index=['Mean absolute error [MPG]']).T)

if __name__ == '__main__':
    main()

# MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.


import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
import math
import matplotlib.colors as colors

from matplotlib import cm
from matplotlib import rc

__author__ = 'ernesto'

# if use latex or mathtext
rc('text', usetex=True)
rc('mathtext', fontset='cm')

# auxiliar function for plot ticks of equal length in x and y axis despite its scales.
def convert_display_to_data_coordinates(transData, length=10):
    # create a transform which will take from display to data coordinates
    inv = transData.inverted()
    # transform from display coordinates to data coordinates in x axis
    data_coords = inv.transform([(0, 0), (length, 0)])
    # get the length of the segment in data units
    yticks_len = data_coords[1, 0] - data_coords[0, 0]
    # transform from display coordinates to data coordinates in y axis
    data_coords = inv.transform([(0, 0), (0, length)])
    # get the length of the segment in data units
    xticks_len = data_coords[1, 1] - data_coords[0, 1]
    return xticks_len, yticks_len

#####################################
# PARAMETERS - This can be modified #
#####################################

# normal pdf variances
var1 = 0.5
var2 = 2
var_std = 1
# normal pdf mean
theta = 6
epsilon = 1.5

# maximum deviation from the mean where to plot each gaussian
max_mean_dev = 3.1 * var2

#####################
# END OF PARAMETERS #
#####################

# abscissa values
xmin = theta - max_mean_dev
xmax = theta + max_mean_dev

x = np.linspace(xmin, xmax, 300)
# normal distribution and density values in x
pdf_var1 = norm.pdf(x, theta, math.sqrt(var1))
pdf_var2 = norm.pdf(x, theta, math.sqrt(var2))
pdf_std = norm.pdf(x, theta, math.sqrt(var_std))

# axis parameters
dx = xmax / 20
xmin_ax = xmin - dx
xmax_ax = xmax + dx

ym = np.amax(pdf_var1)
ymax_ax = ym + ym / 10
ymin_ax = -ym / 10

# areas to fill limits
pdf1_xinf = np.linspace(xmin, theta-epsilon, 50)
pdf1_inf = norm.pdf(pdf1_xinf, theta, math.sqrt(var1))
pdf1_xsup = np.linspace(theta+epsilon, xmax, 50)
pdf1_sup = norm.pdf(pdf1_xsup, theta, math.sqrt(var1))
pdf2_xinf = np.linspace(xmin, theta-epsilon, 50)
pdf2_inf = norm.pdf(pdf2_xinf, theta, math.sqrt(var2))
pdf2_xsup = np.linspace(theta+epsilon, xmax, 50)
pdf2_sup = norm.pdf(pdf2_xsup, theta, math.sqrt(var2))

epsilon1 = epsilon / math.sqrt(var1)
epsilon2 = epsilon / math.sqrt(var2)
pdfstd1_xinf = np.linspace(xmin, theta-epsilon1, 50)
pdfstd1_inf = norm.pdf(pdfstd1_xinf, theta, math.sqrt(var_std))
pdfstd1_xsup = np.linspace(theta+epsilon1, xmax, 50)
pdfstd1_sup = norm.pdf(pdfstd1_xsup, theta, math.sqrt(var_std))
pdfstd2_xinf = np.linspace(xmin, theta-epsilon2, 50)
pdfstd2_inf = norm.pdf(pdfstd2_xinf, theta, math.sqrt(var_std))
pdfstd2_xsup = np.linspace(theta+epsilon2, xmax, 50)
pdfstd2_sup = norm.pdf(pdfstd2_xsup, theta, math.sqrt(var_std))

# length of the ticks for all subplot (6 pixels)
display_length = 6  # in pixels
# x ticks labels margin
xtm = -0.09
ytm = 0.4
# font size
fontsize = 14
# colors from coolwarm
cNorm = colors.Normalize(vmin=0, vmax=1)
scalarMap = cm.ScalarMappable(norm=cNorm, cmap=cm.coolwarm)
col10 = scalarMap.to_rgba(0)
col20 = scalarMap.to_rgba(1)

fig = plt.figure(0, figsize=(10, 6), frameon=False)

# PLOT OF F(x | x < a)
ax = plt.subplot2grid((2, 8), (0, 0), rowspan=1, colspan=4)

plt.xlim(xmin_ax, xmax_ax)
plt.ylim(ymin_ax, ymax_ax)

# horizontal and vertical ticks length
xtl, ytl = convert_display_to_data_coordinates(ax.transData, length=display_length)

# axis arrows
plt.annotate("", xytext=(xmin_ax, 0), xycoords='data', xy=(xmax_ax, 0), textcoords='data',
             arrowprops=dict(width=0.1, headwidth=6, headlength=8, facecolor='black', shrink=0.002))
plt.annotate("", xytext=(0, ymin_ax), xycoords='data', xy=(0, ymax_ax), textcoords='data',
             arrowprops=dict(width=0.1, headwidth=6, headlength=8, facecolor='black', shrink=0.002))

plt.plot(x, pdf_var1, color='k', linewidth=2)

# filled areas
ax.fill_between(pdf1_xinf, 0, pdf1_inf, color=col10)
ax.fill_between(pdf1_xsup, 0, pdf1_sup, color=col10)

# xlabels and xtickslabels
plt.plot([theta, theta], [0, xtl], 'k')
plt.plot([theta-epsilon, theta-epsilon], [0, xtl], 'k')
plt.plot([theta+epsilon, theta+epsilon], [0, xtl], 'k')
plt.text(theta, xtm, '$\\theta$', fontsize=fontsize, ha='center', va='baseline')
plt.text(theta-epsilon, xtm, '$\\theta-\epsilon$', fontsize=fontsize, ha='center', va='baseline')
plt.text(theta+epsilon, xtm, '$\\theta+\epsilon$', fontsize=fontsize, ha='center', va='baseline')
plt.text(xmax_ax, xtm, '$\hat{\\theta}$', fontsize=fontsize, ha='right', va='baseline')
plt.text(ytm, ymax_ax, '$p(\hat{\\theta})=\mathcal{N}(\\theta,\,\sigma^2_{\hat{\\theta}})$',
         fontsize=fontsize, ha='left', va='center')

plt.text(xmax_ax+0.4, ymax_ax, '$\sigma^2_{\hat{\\theta}}<\sigma^2_{\check{\\theta}}$',
         fontsize=fontsize, ha='center', va='center')

plt.axis('off')

##
ax = plt.subplot2grid((2, 8), (0, 4), rowspan=1, colspan=4)

plt.xlim(xmin_ax, xmax_ax)
plt.ylim(ymin_ax, ymax_ax)

# axis arrows
plt.annotate("", xytext=(xmin_ax, 0), xycoords='data', xy=(xmax_ax, 0), textcoords='data',
             arrowprops=dict(width=0.1, headwidth=6, headlength=8, facecolor='black', shrink=0.002))
plt.annotate("", xytext=(theta, ymin_ax), xycoords='data', xy=(theta, ymax_ax), textcoords='data',
             arrowprops=dict(width=0.1, headwidth=6, headlength=8, facecolor='black', shrink=0.002))

plt.plot(x, pdf_std, color='k', linewidth=2)

# filled areas
ax.fill_between(pdfstd1_xinf, 0, pdfstd1_inf, color=col10)
ax.fill_between(pdfstd1_xsup, 0, pdfstd1_sup, color=col10)

xtm2 = -0.11
# xlabels and xtickslabels
plt.plot([theta-epsilon1, theta-epsilon1], [0, xtl], 'k')
plt.plot([theta+epsilon1, theta+epsilon1], [0, xtl], 'k')
# plt.text(theta-epsilon1, xtm, '$$-\epsilon/\sqrt{\\textrm{var}(\hat{\\theta})}$$',
#          fontsize=fontsize, ha='center', va='baseline')
# plt.text(theta-epsilon1, xtm, '$$-\\frac{\epsilon}{\sigma_{\hat{\\theta}}}$$', fontsize=fontsize, ha='center', va='baseline')
plt.text(theta-epsilon1, xtm2, '$-\epsilon/\sigma_{\hat{\\theta}}$', fontsize=fontsize, ha='center', va='baseline')
plt.text(theta+epsilon1, xtm2, '$\epsilon/\sigma_{\hat{\\theta}}$', fontsize=fontsize, ha='center', va='baseline')
plt.text(xmax_ax, xtm2, '$(\hat{\\theta}-\\theta$)/\sigma_{\hat{\\theta}}',
         fontsize=fontsize, ha='center', va='baseline')
plt.text(theta + ytm, ymax_ax, '$p((\hat{\\theta}-\\theta$)/\sigma_{\hat{\\theta}})=\mathcal{N}(0,\,1)$',
         fontsize=fontsize, ha='left', va='center')
plt.axis('off')

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

ax = plt.subplot2grid((2, 8), (1, 0), rowspan=1, colspan=4)

plt.xlim(xmin_ax, xmax_ax)
plt.ylim(ymin_ax, ymax_ax)

# axis arrows
plt.annotate("", xytext=(xmin_ax, 0), xycoords='data', xy=(xmax_ax, 0), textcoords='data',
             arrowprops=dict(width=0.1, headwidth=6, headlength=8, facecolor='black', shrink=0.002))
plt.annotate("", xytext=(0, ymin_ax), xycoords='data', xy=(0, ymax_ax), textcoords='data',
             arrowprops=dict(width=0.1, headwidth=6, headlength=8, facecolor='black', shrink=0.002))

plt.plot(x, pdf_var2, color='k', linewidth=2)

# filled areas
ax.fill_between(pdf2_xinf, 0, pdf2_inf, color=col10)
ax.fill_between(pdf2_xsup, 0, pdf2_sup, color=col10)

# xlabels and xtickslabels
plt.plot([theta, theta], [0, xtl], 'k')
plt.plot([theta-epsilon, theta-epsilon], [0, xtl], 'k')
plt.plot([theta+epsilon, theta+epsilon], [0, xtl], 'k')
plt.text(theta, xtm, '$\\theta$', fontsize=fontsize, ha='center', va='baseline')
plt.text(theta-epsilon, xtm, '$\\theta-\epsilon$', fontsize=fontsize, ha='center', va='baseline')
plt.text(theta+epsilon, xtm, '$\\theta+\epsilon$', fontsize=fontsize, ha='center', va='baseline')
plt.text(xmax_ax, xtm, '$\check{\\theta}$', fontsize=fontsize, ha='right', va='baseline')
plt.text(ytm, ymax_ax, '$p(\check{\\theta})=\mathcal{N}(\\theta,\,\sigma^2_{\check{\\theta}})$',
         fontsize=fontsize, ha='left', va='center')
plt.axis('off')

##
ax = plt.subplot2grid((2, 8), (1, 4), rowspan=1, colspan=4)

plt.xlim(xmin_ax, xmax_ax)
plt.ylim(ymin_ax, ymax_ax)

# axis arrows
plt.annotate("", xytext=(xmin_ax, 0), xycoords='data', xy=(xmax_ax, 0), textcoords='data',
             arrowprops=dict(width=0.1, headwidth=6, headlength=8, facecolor='black', shrink=0.002))
plt.annotate("", xytext=(theta, ymin_ax), xycoords='data', xy=(theta, ymax_ax), textcoords='data',
             arrowprops=dict(width=0.1, headwidth=6, headlength=8, facecolor='black', shrink=0.002))

plt.plot(x, pdf_std, color='k', linewidth=2)

# filled areas
ax.fill_between(pdfstd2_xinf, 0, pdfstd2_inf, color=col10)
ax.fill_between(pdfstd2_xsup, 0, pdfstd2_sup, color=col10)

xtm2 = -0.11
# xlabels and xtickslabels
plt.plot([theta-epsilon2, theta-epsilon2], [0, xtl], 'k')
plt.plot([theta+epsilon2, theta+epsilon2], [0, xtl], 'k')
plt.text(theta-epsilon2, xtm2, '$-\epsilon/\sigma_{\check{\\theta}}$', fontsize=fontsize, ha='center', va='baseline')
plt.text(theta+epsilon2, xtm2, '$\epsilon/\sigma_{\check{\\theta}}$', fontsize=fontsize, ha='center', va='baseline')
plt.text(xmax_ax, xtm2, '$(\check{\\theta}-\\theta$)/\sigma_{\check{\\theta}}',
         fontsize=fontsize, ha='center', va='baseline')
plt.text(theta + ytm, ymax_ax, '$p((\check{\\theta}-\\theta$)/\sigma_{\check{\\theta}})=\mathcal{N}(0,\,1)$',
         fontsize=fontsize, ha='left', va='center')
plt.axis('off')

# save as pdf image
plt.savefig('problem_2_7.pdf', bbox_inches='tight')

plt.show()