#Train a two-layer neural network to approximate a 2D function

import tensorflow as tf

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

def ReLU(x):
    if x > 0.0:
        return x
    else:
        return 0.0

def visualize_original(Width,Height,U,V):
    H2 = np.empty((Height,Width))
    for i in range(Width):
        u = U * ((i - Width/2.0) / (Width/2.0))
        for j in range(Height):
            v = V *((j - Height/2.0) / (Height/2.0))
            H2[j,i] = np.sin(3.14*u/2.0)*np.cos(3.14*v/4.0)  #The 2D func

    return H2

def visualize_2layer(Width,Height,U,V,W1,b1,W2,b2):
    H2 = np.empty((Height,Width))
    for i in range(Width):
        u = U * ((i - Width/2.0) / (Width/2.0))
        for j in range(Height):
            v = V *((j - Height/2.0) / (Height/2.0))
            x = [u,v]
            h1 = np.vectorize(ReLU)(x*W1+b1)
            h2 = h1 * W2 + b2
            H2[j,i] = h2[0,0]

    return H2

#The 2D function that is to be modeled
def F_mv(x1,x2):
    return np.sin(3.14*x1/2.0)*np.cos(3.14*x2/4.0)

#Generate training data
A = 2
nb_samples = 1000
F = F_mv
X_train = np.random.uniform(-A,A,(nb_samples,2))

Y_train = np.zeros(shape=(nb_samples,1))

for i in range(nb_samples):
    Y_train[i] = [F(X_train[i][0],X_train[i][1])]

#Two-Layer Neural Network Structure
N1 = 20  #Number of neurons in the hidden layer

tf.reset_default_graph()
session = tf.InteractiveSession()

with tf.variable_scope("Input"):
    x = tf.placeholder(tf.float32,shape=[None,2])

with tf.variable_scope("HiddenLayer"):
    W1 = tf.Variable(tf.truncated_normal([2,N1],stddev=np.sqrt(6/(2+N1))))
    b1 = tf.Variable(tf.zeros([N1]))
    h1 = tf.nn.relu(tf.add(tf.matmul(x,W1),b1))

with tf.variable_scope("OutputLayer"):
    W2 = tf.Variable(tf.truncated_normal([N1,1],stddev=np.sqrt(6/(1+N1))))
    b2 = tf.Variable(tf.constant(0.0))
    h2 = tf.add(tf.matmul(h1,W2),b2)

with tf.variable_scope("Output"):
    y = tf.placeholder(tf.float32,[None,1])

with tf.variable_scope("Loss"):
    Loss = tf.reduce_mean(tf.square(h2 - y))

#Optimization
eta = 1e-3
optimizer_one_step = tf.train.GradientDescentOptimizer(eta).minimize(Loss)
session.run(tf.global_variables_initializer())

#File_Writer = tf.summary.FileWriter('.\\TwoLayergraph',session.graph)

epochs = int(1e4)
batch_size = 100
epochs_between_two_evaluations = 1e3

for i in range(epochs):
    idx = np.random.permutation(X_train.shape[0])[:batch_size]
    feed_dict = {x:X_train[idx],y:Y_train[idx]}
    optimizer_one_step.run(feed_dict=feed_dict)
    if i % epochs_between_two_evaluations == 0:
        [curr_loss] = session.run([Loss],{x:X_train,y:Y_train})
        print(curr_loss)

#Visualize the predicted function
[curr_W1,curr_b1,curr_W2,curr_b2,curr_loss] = session.run([W1,b1,W2,b2,Loss],{x:X_train,y:Y_train})

curr_W1 = np.asmatrix(curr_W1)
curr_W2 = np.asmatrix(curr_W2)

I_original = visualize_original(100,100,A,A)

I = visualize_2layer(100,100,A,A,curr_W1,curr_b1,curr_W2,curr_b2)

f = plt.figure(figsize=(16, 8))

f.add_subplot(1,2, 1)
plt.imshow(I_original)
f.add_subplot(1,2, 2)
plt.imshow(I)
#plt.show(block=True)

x = np.linspace(-A, A, 100)
y = np.linspace(-A, A, 100)
X, Y = np.meshgrid(x, y)

fig = plt.figure(figsize=(16, 8))
ax1 = fig.add_subplot(121,projection='3d')
ax1.plot_wireframe(X, Y, I_original)
ax2 = fig.add_subplot(122,projection='3d')
ax2.plot_wireframe(X, Y, I)

session.close()


# Question 3 - Assignment 3 -due 07/12/2015
import numpy as np
from numpy import fft
import matplotlib.pyplot as plt
 # part a

A = np.ones(500) # first 500 ones are even, so f(t)=1
B = np.array(-A) # next 500 ones are odd, so f(t)=-1

N = np.concatenate((A,B)) # combines A and B to describe the function

# part b

DFT = fft.rfft(N) # real part

print '---DIRECT FOURIER TRANSFORM ---'
print DFT

# part c

DFT_5 = fft.rfft(N)
for i in range (5,501):
    DFT_5[i]=0

DFT_10 = fft.rfft(N)
for i in range (10,501):
    DFT_10[i]=0

DFT_50 = fft.rfft(N)
for i in range (50,501):
    DFT_50[i]=0

# part d
IFT =fft.irfft(DFT)
IFT_5 = fft.irfft(DFT_5)
IFT_10 = fft.irfft(DFT_10)
IFT_50 = fft.irfft(DFT_50)

# part e

t = np.linspace(0,1,1000) # 1000 time values between 0-1

plt.plot(t,N)
plt.plot(t,IFT)
plt.plot(t,IFT_5)
plt.plot(t,IFT_10)
plt.plot(t,IFT_50)
plt.title('Inverse Fourier transform')
plt.xlabel('Time (s)')
plt.ylabel('Frequency (Hz)')
plt.show()

ExamPrep/Shit Comp/SciComp Exam 2016/Assignments 15-16/A3Q3 concatenate combines matrices dft fft rfft irfft plot linspace.py


#-------------------------------------------------------------------------------
# Name:        Simple Regression
# Purpose:
#
# Author:      Nonlining
#
# Created:     02/01/2017
# Copyright:   (c) Nonlining 2016
# Licence:     <your licence>
#-------------------------------------------------------------------------------

import numpy as np

def simple_linear_regression(input_feature, output):
    # compute the sum of input_feature and output
    sum_of_input = input_feature.sum()
    sum_of_output = output.sum()

    # compute the product of the output and the input_feature and its sum
    sum_product_of_in_out = (input_feature*output).sum()

    n = len(input_feature)

    # compute the squared value of the input_feature and its sum
    sum_squared_input = (input_feature * input_feature).sum()

    # use the formula for the slope
    numerator = sum_product_of_in_out - (sum_of_input*sum_of_output)/float(n)
    denominator = sum_squared_input - (sum_of_input*sum_of_input)/float(n)

    slope =  numerator/denominator

    # use the formula for the intercept

    intercept = float(sum_of_output)/n - slope*float(sum_of_input)/n

    return(intercept, slope)

def inverse_regression_predictions(output, intercept, slope):
    # solve output = intercept + slope*input_feature for input_feature. Use this equation to compute the inverse predictions:
    estimated_feature = (output - intercept)/float(slope)

    return estimated_feature

def get_regression_predictions(input_feature, intercept, slope):
    # calculate the predicted values:

    predicted_values = intercept + slope*input_feature

    return predicted_values

def get_residual_sum_of_squares(input_feature, output, intercept,slope):

    gap = (output - (intercept + slope*input_feature))
    RSS = (gap*gap).sum()
    return(RSS)


import tensorflow as tf
import numpy as np
from tensorflow import keras

model = tf.keras.Sequential([keras.layers.Dense(units=1, input_shape=[1])])

model.compile(optimizer='sgd', loss='mse')

xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float) # see formula on next line.
ys = np.array([-1.0, 0.5, 2.0, 3.5, 5.0, 6.5], dtype=float) # using the formula y = (3x + 1)/2.

model.fit(xs, ys, epochs=5)
print(model.predict([7.0])) # Only 5 iterations. This won't be very accurate. You will see this on this page.
print("\n")

model.fit(xs, ys, epochs=20)
print(model.predict([7.0])) # After 20 iterations, it should be better, but not really accurate. Scroll down to 20 to see this.
print("\n")

model.fit(xs, ys, epochs=500)
print(model.predict([7.0])) # 500 iterations. Getting there. Scroll down to 500 to see this.
print("\n")

model.fit(xs, ys, epochs=1000)
print(model.predict([7.0])) # 1000 iterations. Very accurate. Never perfect, however. Scroll down to the bottom to see this.

# y = (3x + 1)/2. So, 3x7=21, 21+1=22, 22/2=11
# Your output should be something aproaching 11


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

"""
    - We need to find the coordinates of the intersections between the circle and the curve.
      We have one intersection at (0.5, 0.5)
      The other intersection is on the third quarter of the circle.

    - The calculations related to the Blancmange are described here
        https://en.wikipedia.org/wiki/Blancmange_curve

    - The equation of the lower half of the circle is:
        (the circle of radius 1/4 centered at (0,0))
            X^2 + Y^2 = 1/16
        (the lower half of the circle of radius 1/4 centered at (0,0))
            Y = -sqrt(1/16 - X^2)
        (the lower half of the circle of radius 1/4 centered at (1/4, 1/2))
            Let X = x - 1/4, Y = y - 1/2, then,
            y - 1/2 = -sqrt(1/16 - (x - 1/4)^2)
         or y = 1/2 - sqrt(1/16 - (x - 1/4)^2)

    - We search x in range of [0, 0.5) to find the intersection on the left.

    - Use integral to find the overlapping area.
"""

from sage.all import *
from sage.symbolic.integration.integral import definite_integral

def circle(x):
    X = x - 1/4
    Y = -sqrt(1/16-X**2)
    y = Y + 1/2
    return float(y)

def s(n):
    return abs(n - round(n))

def blanc(x, tol = 1e-10):
    w = float(s((2**0) * x) / (2**0))
    prev_w = 0
    delta = -1
    n = 0
    while abs(delta) > tol:
        n += 1
        prev_w = w
        delta = s((2**n)*x)/(2**n)
        w = prev_w + delta
    return float(w)

# https://en.wikipedia.org/wiki/Blancmange_curve#Integrating_the_Blancmange_curve
def I(x, depth, max_depth = 990):
    if depth > max_depth:
        return 0
    if x <= 1/2:
        return I(2*x, depth + 1)/4 + x**2 / 2
    elif x <= 1:
        return 1/2 - I(1-x, depth + 1)
    else:
        n = int(x)
        return n / 2 + I(x - n, depth + 1)

def find_x(x_i, x_f, step, tol = 1e-15):
    x = x_i
    y1 = 1
    y2 = 0
    while True:
        x = x + step
        y1 = circle(x)
        y2 = blanc(x)
        if y2 > y1: # now we on the right of the intersection, we take a step back and use a smaller step
            x = x - step
            step = step / 10
            continue
        if abs(y1-y2) < tol:
            break
    return x

if __name__ == "__main__":
    x = find_x(0, 1/2, 0.1)
    I_blanc = I(0.5, 0) - I(x, 0)
    k = var('k')
    I_circle = definite_integral(1/2-sqrt(1/16-(k-1/4)**2),k,x,0.5)
    print(I_blanc - I_circle)


#To create code to determine the mean, max and min of the length
# and width of the sepals and petals of each sample of Iris flowers
#that was taken.
# The 3 sample species of Iris are Virginica, Setosa & Verisolor
#Column 1 contains measurements of the Sepal lentgh
#Column 2 contains measurements of the Sepal width
#Column 3 contains measurements of the Petal length
#Column 4 contains measurements of the Petal width
#Please note all data collected of the 3 species mentioned above are included in each column.

#how to open the file & import it from when it was stored
f = open("data/iris.csv")

#prints the name of the file
print(f)

#print the contents of the file
#reference:https://web.microsoftstream.com/video/f0788c1c-c7bd-4347-98ac-477186938ed7

print(f.read())
print("Please see the data contents of Fisher's Iris Data Set above  ")

#calculate the mean of each column

import numpy
#import mathplotlib.pyplot as plt

#read data file into array
data = numpy.genfromtxt('data/iris.csv', delimiter=',')

firstcol = data[:,0]
meanfirstcol = numpy.mean(data[:,0])

secondcol = data[:,1]
meansecondcol = numpy.mean(data[:,1])

thirdcol = data[:,2]
meanthirdcol = numpy.mean(data[:,2])

fourthcol = data[:,3]
meanfourthcol = numpy.mean(data[:,3])

#to print the mean of the length and width of the sepals and petals of each sample collected by Ronald Fisher
print("the mean of sepal length in column 1 is:", meanfirstcol)

print("the mean of the Sepal width in column 2 is:", meansecondcol)

print("the mean of the Petal length in column 3 is:", meanthirdcol)

print("the mean of the Petal width in column 4 is:", meanfourthcol)

#to find the min of each column:
#reference: https://web.microsoftstream.com/video/f0788c1c-c7bd-4347-98ac-477186938ed7
#reference: https://plot.ly/numpy/min/

firstcol = data[:,0]
minfirstcol = numpy.min(firstcol)

secondcol = data[:,1]
minsecondcol = numpy.min(secondcol)

thirdcol = data[:,2]
minthirdcol = numpy.min(thirdcol)

fourthcol = data[:,3]
minfourthcol = numpy.min(fourthcol)

#to print the min of the length and width of the sepals and petals of each sample collected by Ronald Fisher
print("the min of sepal length in column 1 is:", minfirstcol)

print("the min of the Sepal width in column 2 is:", minsecondcol)

print("the min of the Petal length in column 3 is:", minthirdcol)

print("the min of the Petal width in column 4 is:", minfourthcol)

#To find the max of each column
#reference: https://web.microsoftstream.com/video/f0788c1c-c7bd-4347-98ac-477186938ed7
#reference: https://plot.ly/numpy/min/  (same concept as finding the min of each colum)

firstcol = data[:,0]
maxfirstcol = numpy.max(firstcol)

secondcol = data[:,1]
maxsecondcol = numpy.max(secondcol)

thirdcol = data[:,2]
maxthirdcol = numpy.max(thirdcol)

fourthcol = data[:,3]
maxfourthcol = numpy.max(fourthcol)

#to print the max of the length and width of the sepals and petals of each sample collected by Ronald Fisher
print("the max of sepal length in column 1 is:", maxfirstcol)

print("the max of the Sepal width in column 2 is:", maxsecondcol)

print("the max of the Petal length in column 3 is:", maxthirdcol)

print("the max of the Petal width in column 4 is:", maxfourthcol)

#to create a bar chart/histogram diagram of each column
#reference:Programming & Scripting, Matplotlib Pyplot, Ian McLaughlin (https://web.microsoftstream.com/video/f0788c1c-c7bd-4347-98ac-477186938ed7)
#reference: https://matplotlib.org/users/pyplot_tutorial.html

import matplotlib.pyplot as pl
from matplotlib.ticker import NullFormatter
pl.figure(1)

pl.subplot(221)
pl.hist(firstcol)
pl.title('Sepal Length')  #create Title of graph
pl.ylabel('Samples Taken')  #to name the y axis
pl.xlabel('Measurements (cm)')  #to name the x axis

pl.subplot(222)
pl.hist(secondcol)
pl.title('Sepal Width')
pl.ylabel('Samples Taken')
pl.xlabel('Measurements (cm)')

pl.subplot(223)
pl.hist(thirdcol)
pl.title('Petal Lentgh')
pl.ylabel('Samples Taken')
pl.xlabel('Measurements (cm)')

pl.subplot(224)
pl.hist(fourthcol)
pl.title('Petal Width')
pl.ylabel('Samples Taken')
pl.xlabel('Measurements (cm)')

pl.gca().yaxis.set_minor_formatter(NullFormatter())
# Adjust the subplot layout, because the logit one may take more space
# than usual, due to y-tick labels like "1 - 10^{-3}"
pl.subplots_adjust(top=0.95, bottom=0.1, left=0.10, right=0.95, hspace=0.40,
                    wspace=0.35)

pl.show()


import numpy as np
import matplotlib.pyplot as plt

dt = 0.1
nu = 0.2
x0 = 0.0
u0 = 0.0
N_step = 100
X = np.zeros((2,N_step))
X_meas = np.zeros((2,N_step))
X[0,0] = x0
X[1,0] = u0
X_meas[0,0] = x0 + np.random.randn(1)
X_meas[1,0] = u0 + np.random.randn(1)
A = np.matrix([[1.0, dt],[0.0,1.0-dt*nu]])
H = np.matrix([[1.0, 0.0],[0.0,1.0]])
print(A.shape)
sigma_meas0 = 2.0
sigma_meas1 = 2.0
sigma_acc = 0.001
Q = np.matrix([[1.0,0.0],[0.0,1.0]])*sigma_acc**2
R = np.matrix([[sigma_meas0**2,0.0],[0.0,sigma_meas1**2]])

Pposterior = np.eye(2)*0.5
xposterior = np.zeros((2,N_step))
xposterior[0,0] = x0
xposterior[1,0] = u0

for t in range(0,N_step-1):
    ''' X[0,t+1] = X[0,t] + dt*X[1,t]
    X[1,t+1] = X[1,t] - dt*nu*X[1,t]**2 '''

    X[:,t+1:t+2] =  np.dot(A,X[:,t:t+1])
    X[1,t+1] += np.random.randn(1)*sigma_acc
    X_meas[:,t+1:t+2] = np.dot(H,X[:,t+1:t+2])
    X_meas[0,t+1] += np.random.randn(1)*sigma_meas0
    X_meas[1,t+1] += np.random.randn(1)*sigma_meas1
    #kalman filter prediction:

    xprior = np.dot(A,xposterior[:,t:t+1])
    Pprior = np.dot(np.dot(A,Pposterior),A.T) + Q
    S = np.dot(np.dot(H,Pprior),H.T) + R
    Kgain  = np.dot(np.dot(Pprior,H.T),np.linalg.inv(S))
    xposterior[:,t+1:t+2] = xprior + np.dot(Kgain,(X_meas[:,t+1:t+2] - np.dot(H,xprior)))

    Pposterior = np.dot(np.eye(2) - np.dot(Kgain,H),Pprior)

plt.plot(X[0,:].T)
plt.plot(X_meas[0,:].T,'.')
plt.plot(xposterior[0,:].T)
plt.figure()
plt.plot(X[1,:].T)
plt.plot(X_meas[1,:].T,'.')
plt.plot(xposterior[1,:].T)
plt.draw()
plt.pause(100)


# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
import numpy as np
import random
from scipy.spatial import Delaunay
from math import pi, cos, sin, acos

###############################################################################
# METHODES
###############################################################################

# Genere les points formant le contour du cercle
def genererContourCercle(resolution):
  """
  Entree: resolution (nbre de pts de la discretisation du cercle)
  Sortie: numpy.array contenant l'ensemble points de la
  discretisation du cercle

  On genere les points du contour sur un quadrant de facon reguliere,
  puis on place les symetriques en manipulant les coordonnees:
            _____
          /   |   \
        /     |     \
      /       |       \
    /         |         \
   | (-y,x)   |   (x,y)  |
   |----------+----------|
   | (-x,-y)  | (y,-x)   |
    \         |         /
      \       |       /
        \     |     /
          \ __|__ /
  C'est juste pour economiser du temps de calcul sur les cos() et sin(),
  c'est peut-etre pas utile
  """

  # On initialise le tableau qui contiendra les points
  ptsContourQuadrant = np.zeros(shape=(resolution*4, 2))

  # On va faire varier l'angle entre 0 et pi/4 (45 deg)
  increment = (pi/2) / resolution
  angle = -increment
  for i in range (resolution):
    angle += increment
    x = cos(angle)
    y = sin(angle)
    ptsContourQuadrant[i] = [x, y]                #top-right
    ptsContourQuadrant[resolution+i] = [-y, x]    #top-left
    ptsContourQuadrant[2*resolution+i] = [-x, -y] #bottom-left
    ptsContourQuadrant[3*resolution+i] = [y, -x]  #bottom-right

  return ptsContourQuadrant

# Sous-fonction de genererInterieurCercle, pour un seul point
def genererPointInterieur(angleMin, angleMax):
  """
  Entree: intervalle d'angle pour des coordonnees polaires
  Sortie: coordonnees d'un point quelconque sur une portion du disque unite
  """
  angle = random.uniform(angleMin, angleMax)
  distance = random.random()
  return [distance * cos(angle), distance * sin(angle)]

# Genere des points aleatoirement dans un disque
def genererInterieurCercle(nbPointsInterieurs):
  # On initialise le tableau qui contiendra les points
  ptsInterieurs = np.zeros(shape=(nbPointsInterieurs, 2))

  for i in range(nbPointsInterieurs):
    ptsInterieurs[i] = genererPointInterieur(0, 2*pi)

  return ptsInterieurs

# Sous-fonction pour qualiteTriangle
def calculerAngle(a, b, c):
  """
  Entree: 3 points A[xa, ya], B[xb, yb], C[xc, yc]
  Sortie: angle (AB, AC) en radians

  - On utilise les coordonnees de facon vectorielle:
  AB = B - A = [xb-xa, yb-ya] etc.
  - On utilise la formule du produit scalaire avec cosinus:
  AB.AC = ||AB||.||AC||.cos(AB,AC) => (AB,AC) = arccos(AB.AC/||AB||.||AC||)
  """
  ab = b - a
  ac = c - a
  prodScal = np.dot(ab,ac)
  prodNorm = np.linalg.norm(ab) * np.linalg.norm(ac)
  return acos(prodScal/prodNorm)

# Qualité d'un seul triangle
def qualiteTriangle(a, b, c):
  """
  Entree: 3 angles a, b, et c en radians
  Sortie: float dans [0,1] en fonction du max(angle - angle_droit)
  """
  ecartAngle1 = abs(calculerAngle(a,b,c) - pi/2)
  ecartAngle2 = abs(calculerAngle(b,c,a) - pi/2)
  ecartAngle3 = abs(calculerAngle(c,a,b) - pi/2)
  ecartMax = max(ecartAngle1, ecartAngle2, ecartAngle3)

  return ecartMax / (pi/2)

# Qualité d'un ensemble de triangles
def qualiteMaillageTri(triangles, points):
  """
  Entree:
    - triangles de la forme Delaunay(points).simplices
    - np.array des points du maillage
  Sortie: float dans [0,1]

  Calcule la qualite de tous les triangles et en fait la moyenne arithmetique
  """
  sommeQualite = 0.0

  for triangle in triangles:
    sommeQualite += qualiteTriangle(points[triangle[0]], points[triangle[1]], points[triangle[2]])

  return sommeQualite / len(triangles)

def croisementMaillages(parent1, parent2):
  """
  Entree: 2 ensembles de points correspondant a 2 maillages
  Sortie: 1 ensemble de points correspondant a un maillage

  - on prend le point le plus a gauche (x min) et le plus a droite (x max),
  on calcule le barycentre (milieu)
  - on prend tous les points de gauche pour parent1, les autres pour
  parent2
  - on fait l'union, et on ajoute/supprime des points random pour conserver
  le meme nombre que les parents

  On peut faire le même decoupage verticalement

  Une autre façon de croiser c'est de prendre 1 point sur 2 dans chaque maillage
  """
  # On cherche le point le plus a gauche
  frontiere = (np.amin(parent1, axis=0) + np.amax(parent1, axis=0)) / 2
  xFrontiere = frontiere[0]

  enfant = parent1
  i = 0

  for point in parent1:
    if point[0] <= xFrontiere and i < len(enfant):
      enfant[i] = point
      i = i + 1

  for point in parent2:
    if point[0] > xFrontiere and i < len(enfant):
      enfant[i] = point
      i = i + 1

  return enfant

###############################################################################
# EXECUTION
###############################################################################

# Nombre de points du contour du cercle par quadrant
resolutionQuadrant = 5
contourCercle = genererContourCercle(resolutionQuadrant)

# Nombre de points interieurs au cercle
nbPtsDansCercle = 25
interieurCercle = genererInterieurCercle(nbPtsDansCercle)
interieurC2 = genererInterieurCercle(nbPtsDansCercle)

# Tous les points regroupes dans un tableau
pointsCercle = np.concatenate((contourCercle, interieurCercle), axis=0)
ptsC2 = np.concatenate((contourCercle, interieurC2), axis=0)

pointsCercle = croisementMaillages(pointsCercle, ptsC2)

# Creation du maillage
maillageTriCercle = Delaunay(pointsCercle)

print "Qualite du maillage : "
print qualiteMaillageTri(maillageTriCercle.simplices, pointsCercle)

###############################################################################
# VISUEL
###############################################################################
plt.triplot(pointsCercle[:,0], pointsCercle[:,1], maillageTriCercle.simplices.copy())
plt.plot(pointsCercle[:,0], pointsCercle[:,1], 'o')
plt.show()


#Import Modules Pandas and Numpy
import pandas as pd
import numpy as np
import operator

#Read CSV File
data = pd.read_csv("iris.csv")

#To find Euc Distance
def ED(x1, x2, length):
    distance = 0
    for x in range(length):
        distance += np.square(x1[x] - x2[x])

    return np.sqrt(distance)

#KNN Model Definition
def knn(trainingSet, testInstance, k):

    distances = {}

    #To find number of columns
    length = testInstance.shape[1]

    for x in range(len(trainingSet)):
        dist = ED(testInstance, trainingSet.iloc[x], length)
        distances[x] = dist[0]

    sortdist = sorted(distances.items(), key=operator.itemgetter(1))
    #Put the index of col you wanna sort with
    neighbors = []
    for x in range(k):
        neighbors.append(sortdist[x][0])

    Votes = {} #to get most frequent class of rows
    for x in range(len(neighbors)):
        response = trainingSet.iloc[neighbors[x]][-1]
        #To get the last column for corresponding index
        if response in Votes:
            Votes[response] += 1
        else:
            Votes[response] = 1
    #Appending the Variety to dict along with count
    sortvotes = sorted(Votes.items(), key=operator.itemgetter(1), reverse=True)
    return(sortvotes[0][0], neighbors)

#Input TestSet
testSet = [[6.8, 3.4, 4.8, 2.4]]
test = pd.DataFrame(testSet)

#Different k Values
k = 6
k1 = 3

#Function Call
result,neigh = knn(data, test, k)
#result1,neigh1 = knn(data, test, k1)
print(result)

15XW62 - Machine Learning/examples/numpy/knn/knn.py


import numpy as np
from numpy import sin, pi

def I(x):
    return sin(2*pi*x) + 0.5*sin(4*pi*x) + 0.1*sin(6*pi*x)

# Mesh
L = 10; Nx = 100
x = np.linspace(0, L, Nx+1)
dx = L/float(Nx)

# Discrete Fourier transform
A = np.fft.rfft(I(x))
A_amplitude = np.abs(A)

# Compute the corresponding frequencies
freqs = np.linspace(0, pi/dx, A_amplitude.size)

import matplotlib.pyplot as plt
plt.plot(freqs, A_amplitude)
plt.show()


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

import numpy as np
from math import sqrt

def multipl(a,b):
	sumofab=0.0
	for i in range(len(a)):
		temp=a[i]*b[i]
		sumofab+=temp
	return sumofab

def corrcoef(x,y):
	n=len(x)
	sum1=sum(x)
	sum2=sum(y)
	sumofxy=multipl(x,y)
	sumofx2 = sum([pow(i,2) for i in x])
	sumofy2 = sum([pow(j,2) for j in y])
	num=sumofxy-(float(sum1)*float(sum2)/n)
	den=sqrt((sumofx2-float(sum1**2)/n)*(sumofy2-float(sum2**2)/n))
	if den != 0:
		return num/den
	else:
		return 0

def pearsonr(encodings, labelFile):
	features = encodings[0][1:]
	encodings = np.array(encodings)[1:]
	data = encodings[:, 1:]
	shape = data.shape
	data = np.reshape(data, shape[0] * shape[1])
	data = np.reshape([float(i) for i in data], shape)

	e = ''
	if shape[0] < 5 or shape[1] < 2:
		return 0, e

	with open(labelFile) as f:
		records = f.readlines()
	myDict = {}
	try:
		for i in records:
			array = i.rstrip().split() if i.strip() != '' else None
			myDict[array[0]] = int(array[1])
	except IndexError as e:
		print(e)
		return 0, e

	labels = []
	for i in encodings:
		labels.append(myDict.get(i[0], 0))
	print(labels)

	dataShape = data.shape

	if dataShape[1] != len(features):
		print('Error: inconsistent data shape with feature number.')
		return 0, 'Error: inconsistent data shape with feature number.'
	if dataShape[0] != len(labels):
		print('Error: inconsistent data shape with sample number.')
		return 0, 'Error: inconsistent data shape with sample number.'

	myFea = {}
	for i in range(len(features)):
		array = list(data[:, i])
		try:
			myFea[features[i]] = corrcoef(array, labels)
		except (ValueError, RuntimeWarning) as e:
			return 0, e

	res = []
	res.append(['feature', 'pcc'])
	for key in sorted(myFea.items(), key=lambda item: item[1], reverse=True):
		res.append([key[0], '{0:.3f}'.format(myFea[key[0]])])
	return res, e


# -*- coding: utf-8 -*-
"""pyahp.methods.approximate

This module contains the class implementing the geometric priority estimation method.
"""

import numpy as np
import numpy.linalg as LA

from pyahp.methods import Method

def eig(A, initvec=None, tol=0.0001, iteration=16):
    '''Calculate the dominant eigenvalue of A with power method.

    The Power Method is a classical method to calculate the single eigenvalue with maximal abstract value,
    i.e. |lambda_1| > |lambda2| >= |lambda_i|, where lambdai are eigenvalues, in numerical analysis.
    The speed of convergence is dominated by |lambda2|/|lambda1|.

    Perron theorem guarantees that lambda_1>|lambda_i| for any positive matrix.
    see https://en.wikipedia.org/wiki/Power_iteration for more details.

    Arguments:
        A {2D-array} -- square matrix

    Keyword Arguments:
        initvec {1D-array} -- [initial vector] (default: {None})
        tol {number} -- [tolerance] (default: {0.0001})
        iteration {number} -- [iteration] (default: {16})

    Returns:
        dominant eigenvalue, eigenvector {1D-array}

    Example:
    >>> A = np.array([[1,2,6],[1/2,1,4],[1/6,1/4,1]])
    >>> lmd, v = eig(A)
    >>> lmd
    3.0090068360243256
    >>> v
    [1.         0.5503254  0.15142866]
    '''

    m, n = A.shape
    u0 = initvec or np.random.random(n)
    for _ in range(iteration):
        v0 = u0
        v1 = np.dot(A, v0)
        ind = np.argmax(abs(v1))
        mu = v1[ind]
        u0 = v1 / mu
        if LA.norm(v0 - u0)/np.max((1, LA.norm(u0))) < tol:
            return mu, u0
    raise Exception('The iteration does not reach the tolerance after %d iterations.'%iteration)

class PowerMethod(Method):
    """Power priority estimation method
    """

    def estimate(self, preference_matrix):
        super()._check_matrix(preference_matrix)

        _, vec = eig(preference_matrix)

        return vec / np.sum(vec)


# Version 3.6

import numpy as np

def split(matrix):
	"""
	Splits a given matrix into quarters.
	Input: nxn matrix
	Output: tuple containing 4 n/2 x n/2 matrices corresponding to a, b, c, d
	"""
	row, col = matrix.shape
	row2, col2 = row//2, col//2
	return matrix[:row2, :col2], matrix[:row2, col2:], matrix[row2:, :col2], matrix[row2:, col2:]

def strassen(x, y):
	"""
	Computes matrix product by divide and conquer approach, recursively.
	Input: nxn matrices x and y
	Output: nxn matrix, product of x and y
	"""

	# Base case when size of matrices is 1x1
	if len(x) == 1:
		return x * y

	a, b, c, d = split(x)
	e, f, g, h = split(y)

	p1 = strassen(a, f - h)
	p2 = strassen(a + b, h)
	p3 = strassen(c + d, e)
	p4 = strassen(d, g - e)
	p5 = strassen(a + d, e + h)
	p6 = strassen(b - d, g + h)
	p7 = strassen(a - c, e + f)

	c11 = p5 + p4 - p2 + p6
	c12 = p1 + p2
	c21 = p3 + p4
	c22 = p1 + p5 - p3 - p7

	# Combining the 4 quadrants into a single matrix by stacking horizontally and vertically.
	c = np.vstack((np.hstack((c11, c12)), np.hstack((c21, c22))))

	return c


# Polynomial Regression

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('Position_Salaries.csv')
# [:, 1:2].values - variable as arrat 1:2
X = dataset.iloc[:, 1:2].values
y = dataset.iloc[:, 2].values

# Splitting the dataset into the Training set and Test set
"""from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)"""

# Feature Scaling
"""from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)"""

# Fitting Linear Regression to the dataset
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(X, y)

# Fitting Polynomial Regression to the dataset
from sklearn.preprocessing import PolynomialFeatures
poly_reg = PolynomialFeatures(degree = 4)
X_poly = poly_reg.fit_transform(X)
lin_reg_2 = LinearRegression()
lin_reg_2.fit(X_poly, y)

# Visualising the Linear Regression results
plt.scatter(X, y, color = 'red')
plt.plot(X, lin_reg.predict(X), color = 'blue')
plt.title('Truth or Bluff (Linear Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

# Visualising the Polynomial Regression results
plt.scatter(X, y, color = 'red')
plt.plot(X, lin_reg_2.predict(poly_reg.fit_transform(X)), color = 'blue')
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

# Visualising the Polynomial Regression results (for higher resolution and smoother curve)
X_grid = np.arange(min(X), max(X), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.scatter(X, y, color = 'red')
plt.plot(X_grid, lin_reg_2.predict(poly_reg.fit_transform(X_grid)), color = 'blue')
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

# Predicting a new result with Linear Regression
lin_reg.predict(6.5)

# Predicting a new result with Polynomial Regression
lin_reg_2.predict(poly_reg.fit_transform(6.5))

2. Modeling/1. Regression/4. Polynomial regression/polynomial_regression.py


"""
=========================================
Optimization of a two-parameter function
=========================================

"""

import numpy as np

# Define the function that we are interested in
def sixhump(x):
    return ((4 - 2.1*x[0]**2 + x[0]**4 / 3.) * x[0]**2 + x[0] * x[1]
            + (-4 + 4*x[1]**2) * x[1] **2)

# Make a grid to evaluate the function (for plotting)
x = np.linspace(-2, 2)
y = np.linspace(-1, 1)
xg, yg = np.meshgrid(x, y)

############################################################
# A 2D image plot of the function
############################################################
# Simple visualization in 2D
import matplotlib.pyplot as plt
plt.figure()
plt.imshow(sixhump([xg, yg]), extent=[-2, 2, -1, 1], origin="lower")
plt.colorbar()

############################################################
# A 3D surface plot of the function
############################################################
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(xg, yg, sixhump([xg, yg]), rstride=1, cstride=1,
                       cmap=plt.cm.jet, linewidth=0, antialiased=False)

ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('f(x, y)')
ax.set_title('Six-hump Camelback function')

############################################################
# Find the minima
############################################################
from scipy import optimize

x_min = optimize.minimize(sixhump, x0=[0, 0])

plt.figure()
# Show the function in 2D
plt.imshow(sixhump([xg, yg]), extent=[-2, 2, -1, 1], origin="lower")
plt.colorbar()
# And the minimum that we've found:
plt.scatter(x_min.x[0], x_min.x[1])

plt.show()


from __future__ import absolute_import, division
from __future__ import print_function
import sys
from sympy import symbols, exp, I, Matrix, solve, simplify
from galgebra.printer import Format, xpdf, Get_Program, Print_Function
from galgebra.ga import Ga
from galgebra.metric import linear_expand

Format()
X = (t, x, y, z) = symbols('t x y z', real=True)
(st4d, g0, g1, g2, g3) = Ga.build('gamma*t|x|y|z', g=[1, -1, -1, -1], coords=X)

i = st4d.i

B = st4d.mv('B', 'vector')
E = st4d.mv('E', 'vector')
B.set_coef(1, 0, 0)
E.set_coef(1, 0, 0)
B *= g0
E *= g0
F = E + i * B

kx, ky, kz, w = symbols('k_x k_y k_z omega', real=True)
kv = kx * g1 + ky * g2 + kz * g3
xv = x * g1 + y * g2 + z * g3
KX = ((w * g0 + kv) | (t * g0 + xv)).scalar()

Ixyz = g1 * g2 * g3

F = F * exp(I * KX)

print(r'\text{Pseudo Scalar\;\;}I =', i)
print(r'%I_{xyz} =', Ixyz)
print(F.Fmt(3, '\\text{Electromagnetic Field Bi-Vector\\;\\;} F'))
gradF = st4d.grad * F

print('#Geom Derivative of Electomagnetic Field Bi-Vector')
print(gradF.Fmt(3, 'grad*F = 0'))

gradF = gradF /  (I * exp(I * KX))
print(gradF.Fmt(3, r'%\lp\bm{\nabla}F\rp /\lp i e^{iK\cdot X}\rp = 0'))

g = '1 # 0 0,# 1 0 0,0 0 1 0,0 0 0 -1'
X = (xE, xB, xk, t) = symbols('x_E x_B x_k t', real=True)
(EBkst, eE, eB, ek, et) = Ga.build('e_E e_B e_k t', g=g, coords=X)

i = EBkst.i

E, B, k, w = symbols('E B k omega', real=True)

F = E * eE * et + i * B * eB * et
kv = k * ek + w * et
xv = xE * eE + xB * eB + xk * ek + t * et
KX = (kv | xv).scalar()
F = F * exp(I * KX)

print(r'%\mbox{set } e_{E}\cdot e_{k} = e_{B}\cdot e_{k} = 0' +
      r'\mbox{ and } e_{E}\cdot e_{E} = e_{B}\cdot e_{B} = ' +
      r'e_{k}\cdot e_{k} = -e_{t}\cdot e_{t} = 1')

print('g =', EBkst.g)

print('K|X =', KX)
print('F =', F)
(EBkst.grad * F).Fmt(3, 'grad*F = 0')

gradF_reduced = (EBkst.grad * F) /  (I * exp(I * KX))

print(gradF_reduced.Fmt(3, r'%\lp\bm{\nabla}F\rp/\lp ie^{iK\cdot X} \rp = 0'))

print(r'%\mbox{Previous equation requires that: }e_{E}\cdot e_{B} = 0' +
      r'\mbox{ if }B\ne 0\mbox{ and }k\ne 0')

gradF_reduced = gradF_reduced.subs({EBkst.g[0, 1]: 0})
print(gradF_reduced.Fmt(3, r'%\lp\bm{\nabla}F\rp/\lp ie^{iK\cdot X} \rp = 0'))

(coefs, bases) = linear_expand(gradF_reduced.obj)

eq1 = coefs[0]
eq2 = coefs[1]

B1 = solve(eq1, B)[0]
B2 = solve(eq2, B)[0]

print(r'\mbox{eq1: }B =', B1)
print(r'\mbox{eq2: }B =', B2)

eq3 = B1 - B2

print(r'\mbox{eq3 = eq1-eq2: }0 =', eq3)
eq3 = simplify(eq3 /  E)
print(r'\mbox{eq3 = (eq1-eq2)/E: }0 =', eq3)
print(r'#Solutions for $k$ and $B$ in terms of $\omega$ and $E$:')
print('k =', Matrix(solve(eq3, k)))
print('B =', Matrix([B1.subs(w, k), B1.subs(-w, k)]))
xpdf(paper='landscape', prog=True)


import numpy as np
from numpy.lib.arraypad import pad

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

img = np.array([
       [2,3,7,4,6,2,9],
       [6,6,9,8,7,4,3],
       [3,4,8,3,8,9,7],
       [7,8,3,6,6,3,4],
       [4,2,1,8,3,4,6],
       [3,2,4,1,9,8,3],
       [0,1,3,9,2,1,4]])

#######################################
## 卷积操作
#######################################
def conv2(img,f,stride):
    img_w,img_h = img.shape
    w,h = f.shape
    out_w = (img_w - w)//stride + 1
    out_h = (img_h - h)//stride + 1

    arr = np.zeros(shape=(out_w,out_h))
    for g in range(out_h):
        for t in range(out_w):
            s = 0
            # 卷积相乘
            for i in range(w):
                for j in range(h):
                    s = s + img[i+g*stride][j+t*stride]*f[i][j]
            arr[g][t] = s

    return arr

#######################################
## 卷积操作
#######################################

def numpy_conv(input,kernel,stride,padding=0):
    H,W = input.shape

    kernel_size = kernel.shape[1]
    out_w = (W + 2*padding - kernel_size)//stride + 1
    out_h = (H + 2*padding - kernel_size)//stride + 1
    out_channel = kernel.shape[0]
    print("out_w,out_h=",out_w,out_h,out_channel)
    result = np.zeros(shape=(out_channel,out_w,out_h))

    for r in range(0,H - kernel_size + 1):
        for c in range(0,W - kernel_size +1):
            for i in range(0,out_channel):
                # 当前卷积计算的区域
                current_input = input[r:r+kernel_size,c:c+kernel_size]
                # 乘法运算
                current_output = current_input * kernel[i]
                conv_sum = np.sum(current_output)

                result[i,r,c] = conv_sum

    return result

img = np.array([
       [2,3,7,4,6,2,9],
       [6,6,9,8,7,4,3],
       [3,4,8,3,8,9,7],
       [7,8,3,6,6,3,4],
       [4,2,1,8,3,4,6],
       [3,2,4,1,9,8,3],
       [0,1,3,9,2,1,4]])
kernel = [[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]]]
kernel = np.array(kernel)

output = numpy_conv(input=img,kernel=kernel,stride=1)
print(output)


#This set of functions allows for building a Vietoris-Rips simplicial complex from point data

import numpy as np
import matplotlib.pyplot as plt

def euclidianDist(a,b):
  return np.linalg.norm(a - b) #euclidian distance metric

#Build neighorbood graph
def buildGraph(raw_data, epsilon = 3.1, metric=euclidianDist): #raw_data is a numpy array
  nodes = [x for x in range(raw_data.shape[0])] #initialize node set, reference indices from original data array
  edges = [] #initialize empty edge array
  weights = [] #initialize weight array, stores the weight (which in this case is the distance) for each edge
  for i in range(raw_data.shape[0]): #iterate through each data point
      for j in range(raw_data.shape[0]-i): #inner loop to calculate pairwise point distances
          a = raw_data[i]
          b = raw_data[j+i] #each simplex is a set (no order), hence [0,1] = [1,0]; so only store one
          if (i != j+i):
              dist = metric(a,b)
              if dist <= epsilon:
                  edges.append({i,j+i}) #add edge
                  weights.append([len(edges)-1,dist]) #store index and weight
  return nodes,edges,weights

def lower_nbrs(nodeSet, edgeSet, node):
    return {x for x in nodeSet if {x,node} in edgeSet and node > x}

def rips(graph, k):
    nodes, edges = graph[0:2]
    VRcomplex = [{n} for n in nodes]
    for e in edges: #add 1-simplices (edges)
        VRcomplex.append(e)
    for i in range(k):
        for simplex in [x for x in VRcomplex if len(x)==i+2]: #skip 0-simplices
            #for each u in simplex
            nbrs = set.intersection(*[lower_nbrs(nodes, edges, z) for z in simplex])
            for nbr in nbrs:
                VRcomplex.append(set.union(simplex,{nbr}))
    return VRcomplex

def drawComplex(origData, ripsComplex, axes=[-6,8,-6,6]):
  plt.clf()
  plt.axis(axes)
  plt.scatter(origData[:,0],origData[:,1]) #plotting just for clarity
  for i, txt in enumerate(origData):
      plt.annotate(i, (origData[i][0]+0.05, origData[i][1])) #add labels

  #add lines for edges
  for edge in [e for e in ripsComplex if len(e)==2]:
      #print(edge)
      pt1,pt2 = [origData[pt] for pt in [n for n in edge]]
      #plt.gca().add_line(plt.Line2D(pt1,pt2))
      line = plt.Polygon([pt1,pt2], closed=None, fill=None, edgecolor='r')
      plt.gca().add_line(line)

  #add triangles
  for triangle in [t for t in ripsComplex if len(t)==3]:
      pt1,pt2,pt3 = [origData[pt] for pt in [n for n in triangle]]
      line = plt.Polygon([pt1,pt2,pt3], closed=False, color="blue",alpha=0.3, fill=True, edgecolor=None)
      plt.gca().add_line(line)
  plt.show()


# -*- coding: utf-8 -*-
"""
Created on Wed Apr  4 23:04:40 2018

@author: Subhajeet
"""

import numpy as np
import pandas as pd
import networkx as nx
#%%
df=pd.read_csv('wiki-Vote.csv',header=None)
#%%
g=nx.DiGraph()
g.add_nodes_from(np.unique(np.array(df[0])))
edge=[tuple(i) for i in df.values]
g.add_edges_from(edge)
#%%
trm=nx.google_matrix(g)
n=min(trm.shape)
p0=np.repeat(1/n,n)
pi=np.matmul(p0,trm)
eps=0.1
#%%
i=1
while np.sum(np.abs(pi-p0))>eps:
    p0=pi
    pi=np.matmul(pi,trm)
    print(i)
    print(pi)
    i=i+1
    if i==20000:
        break
print('The final rank is :',pi)
#%%
#direct command
nx.pagerank(g,alpha=0.88)
#%%
#pagerank function sir's method
def pagerank(g):
    import numpy as np
    import networkx as nx
    trm=nx.google_matrix(g)
    n=min(trm.shape)
    p0=np.repeat(1/n,n)
    pi=np.matmul(p0,trm)
    i=1
    eps=0.00015
    while np.sum(np.abs(pi-p0))>=eps:
        p0=pi
        pi=np.matmul(pi,trm)
        i=i+1
        if i==10000:
            break
    return pi


from __future__ import print_function,division
from builtins import range
import numpy as np

def gradient_forward_difference(f,x,h):
    """Approximation of the gradient of f(x) using forward differences with step size h"""
    g = np.zeros(len(x))
    f0 = f(x)
    for i in range(len(x)):
        v = x[i]
        x[i] += h
        g[i] = (f(x)-f0)
        x[i] = v
    g *= 1.0/h
    return g

def jacobian_forward_difference(f,x,h):
    """Approximation of the Jacobian of vector function f(x) using forward differences with step size h"""
    f0 = np.asarray(f(x))
    J = np.zeros((len(f0),len(x)))
    for i in range(len(x)):
        v = x[i]
        x[i] += h
        J[:,i] = (np.asarray(f(x))-f0)
        x[i] = v
    J *= 1.0/h
    return J

def hessian_forward_difference(f,x,h):
    """Approximation of the hessian of f(x) using forward differences with
    step size h.
    """
    H = np.zeros((len(x),len(x)))
    f0 = f(x)
    fs = []
    for i in range(len(x)):
        v = x[i]
        x[i] += h
        fs.append(f(x))
        x[i] = v
    for i in range(len(x)):
        v = x[i]
        x[i] += h
        for j in range(i):
            w = x[j]
            x[j] += h
            fij = f(x)
            H[i,j] = (fij-fs[j]) - (fs[i]-f0)
            H[j,i] = H[i,j]
            x[j] = w
        x[i] = v
        x[i] -= h
        fij = f(x)
        H[i,i] = (fs[i]-f0) - (f0-fij)
        x[i] = v
    H *= 1.0/h**2
    return H

def hessian2_forward_difference(f,x,y,h):
    """Approximation of the hessian of a 2-parameter function f(x,y) w.r.t. x and y
    using forward differences with step size h.
    """
    H = np.zeros((len(x),len(y)))
    f0 = f(x,y)
    fxs = []
    fys = []
    for i in range(len(x)):
        v = x[i]
        x[i] += h
        fxs.append(f(x,y))
        x[i] = v
    for i in range(len(y)):
        v = y[i]
        y[i] += h
        fys.append(f(x,y))
        y[i] = v
    for i in range(len(x)):
        v = x[i]
        x[i] += h
        for j in range(len(y)):
            w = y[j]
            y[j] += h
            fij = f(x,y)
            H[i,j] = ((fij-fys[j]) - (fxs[i]-f0))
            y[j] = w
        x[i] = v
    H *= 1.0/h**2
    return H


# coding=utf-8

import numpy as np

def loadDataSet(file):
	fr = open(file)
	dataMat = []
	labelMat = []
	one_vector = fr.readline().split('\t')
	feat_num = len(one_vector) - 1
	for line in fr.readlines():
		lineArr = []
		curArr = line.strip().split('\t')
		for i in range(feat_num):
			lineArr.append(np.float(curArr[i]))
		dataMat.append(lineArr)
		labelMat.append(np.float(curArr[-1]))
	return dataMat,labelMat

#标准回归
def standRegres(xArr,yArr):
	xMat = np.mat(xArr)
	yMat = np.mat(yArr).T
	xTx = xMat.T * xMat
	if np.linalg.det(xTx) == 0.0:
		print("Singular Matrix")
		return
	ws = xTx.T * (xMat.T * yMat)
	return ws

#test main
xArr, yArr = loadDataSet('train.txt')
ws = standRegres(xArr, yArr)
xMat = np.mat(xArr)
yMat = np.mat(yArr)
yHat = xMat * ws

#局部加权线性回归
def lwlr(testPoint,xArr,yArr,k = 1.0):
	xMat = np.mat(xArr)
	yMat = np.mat(yArr)
	m = xMat.shape[0]
	weights = np.mat(np.eye((m)))  #对角矩阵
	for j in range(m):
		diffMat = testPoint - xMat[j,:]
		weights[j,j] = np.exp(diffMat * diffMat.T/(-2.0 * k ** 2))

	xTx = xMat.T * (weights * xMat)
	if np.linalg.det(xTx) == 0.0:
		print("Singular Matrix")
		return

	ws = xTx.I * (xMat.T * (weights * yMat))

	return testPoint * ws

def lwlrTest(testArr,xArr,yArr,k = 1.0 ):
	m = testArr.shape[0]
	yHat = np.zeros(m)
	for i in range(m):
		yHat[i] = lwlr(testArr[i],xArr,yArr,k)
	return yHat

xArr, yArr = loadDataSet('train.txt')
yHat = lwlrTest(xArr,xArr,yArr,0.003)

#Ridge Regreesion  特征数比样本数多

def ridgeRegres(xMat,yMat,lam = 0.2):
	xTx = xMat.T * xMat
	denom = xTx + np.eye(xMat.shape[1]) * lam

	if np.linalg.det(denom) == 0.0:
		print("Singular Matrix")
		return

	ws = denom.T * (xMat.T * yMat)
	return ws

def ridgeTest(xArr,yArr):
	xMat = np.mat(xArr)
	yMean = np.mean(yMat,0)
	yMat = yMat - yMean
	xMeans = np.mean(xMat,0)
	xVar = np.var(xMat,0)
	xMat = (xMat - xMeans)/xVar
	numTestPts = 30
	wMat = np.zeros((numTestPts,xMat.shape[1]))
	for i in range(numTestPts):
		ws = ridgeRegres(xMat,yMat,exp(i-10))
		wMat[i,:] = ws.T
	return wMat


#Regresión Lineal Múltiple

#Librerias
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

#Dataset
dataset = pd.read_csv("../../datasets/Part 2 - Regression/Section 5 - Multiple Linear Regression/50_Startups.csv")
x = dataset.iloc[:,:-1].values
y = dataset.iloc[:,4].values

#Manejo de variables categóricas
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_x = LabelEncoder()
x[:,3] = labelencoder_x.fit_transform(x[:,3])
onehotencoder = OneHotEncoder(categorical_features=[3])
x = onehotencoder.fit_transform(x).toarray()

#Evitar trampa de variables fictisias
x = x[:,1:]

#Divisón del Dataset
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,random_state=0)

#------------------CONSTRUCCIÓN DEL MODELO---------------------

#Ajustar el modelo con el conjunto de entrenamiento All-In
from sklearn.linear_model import LinearRegression
regression = LinearRegression()
regression.fit(x_train,y_train)

#Predicción de resultados en test
y_pred = regression.predict(x_test)

#Ajustar el modelo óptimo con la Eliminación Hacias Atrás
import statsmodels.api as sm
x = np.append(arr = np.ones((50,1)).astype(int),values = x, axis = 1)
x_opt = x[:,[0,1,2,3,4,5]]
sl = 0.05

"""
x_opt = x[:,[0,1,2,3,4,5]]
regression_ols = sm.OLS(endog=y,exog=x_opt).fit()
regression_ols.summary()

x_opt = x[:,[0,1,3,4,5]]
regression_ols = sm.OLS(endog=y,exog=x_opt).fit()
regression_ols.summary()

x_opt = x[:,[0,3,4,5]]
regression_ols = sm.OLS(endog=y,exog=x_opt).fit()
regression_ols.summary()

x_opt = x[:,[0,3,5]]
regression_ols = sm.OLS(endog=y,exog=x_opt).fit()
regression_ols.summary()

x_opt = x[:,[0,3]]
regression_ols = sm.OLS(endog=y,exog=x_opt).fit()
regression_ols.summary()
"""

def backwardElimination(x,sl):
    numVars=len(x[0])
    for i in range(0,numVars):
        regressor_ols = sm.OLS(y,x.tolist()).fit()
        maxVar = max(regressor_ols.pvalues).astype(float)
        if maxVar > sl:
            for j in range(0,numVars-i):
                if(regressor_ols.pvalues[j].astype(float) == maxVar):
                    x = np.delete(x,j,1)

    regressor_ols.summary()
    return x

x_modeled = backwardElimination(x_opt,sl)


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

# In[ ]:

import numpy as np
import ipywidgets as widgets
import matplotlib.pyplot as plt

# In[ ]:

get_ipython().run_line_magic('run', './measureErrors.py')
saveFigure = True

# # Lab Exercise 2 for SCB

# ## Errors

# ### Ex 1-3

# * Try to read `absrelerror()` in `measureErrors.py` and use it for the exercises

# ### Ex. 4 Round-off errors

# In[ ]:

# Generate a random nxn matrix and compute A^{-1}*A which should be I analytically
def testErrA(n = 10):
    A = np.random.rand(n,n)
    Icomp = np.matmul(np.linalg.inv(A),A)
    Iexact = np.eye(n)
    absrelerror(Iexact, Icomp)

# #### Random matrix $A$ with size $n=10$

# In[ ]:

testErrA()

# #### $n=100$

# In[ ]:

testErrA(100)

# #### $n=1000$

# In[ ]:

testErrA(1000)

# **Note**: The execution time changes with the size of $n$ almost linearly, but for $n=10000$, it will take much longer time.

# ### Ex. 5 Discretization Errors

# Program that illustrate the concept discretization.
#
# Replacing continuous with discrete, i.e. represent a continuous function on a interval with a finite number of points.
#
# The density, the number of points is determined by the choice of the discretization parameter $h$.

# #### The step size
#
# **TRY**  to change $h$ and see what will happen.
#
# **NOTE**: $h$ should not be too large or too small. A good range is in $[10^{-5},1]$.

# In[ ]:

h = 0.1

# #### Discretize and compute the numerical derivatives.
#
# Here, the derivative `f'(x)` is computed in a finite number of points on a interval.
#

# In[ ]:

# The exact solution
N = 400
l = 0
u = 2
x = np.linspace(l, u, N)
f_exa = np.exp(x)

# check if h is too large or too small
if h > 1 or h < 1e-5:
    h = 0.5

# compute the numerical derivatives
xh = np.linspace(l, u, int(abs(u-l)/h))
fprimF = ForwardDiff(np.exp, xh, h);

# #### Use `matplotlib` to visuallize the results.
#
# Try to check on [https://matplotlib.org/](https://matplotlib.org/) for mor features, it is really powerful!

# In[ ]:

# Plot
fig, ax = plt.subplots(1)
ax.plot(x, f_exa, color='blue')
ax.plot(xh, fprimF, 'ro', clip_on=False)
ax.set_xlim([0,2])
ax.set_ylim([1,max(fprimF)])
ax.set_xlabel(r'$x$')
ax.set_ylabel('Derivatives')
ax.set_title('Discretization Errors')
ax.legend(['Exact Derivatives','Calculated Derivatives'])

if saveFigure:
    filename = 'DiscretizationError_h' + str(h) + '.pdf'
    fig.savefig(filename, format='pdf', dpi=1000, bbox_inches='tight')

# ## Computer Arithmetic

# Machine limits for floating point types use `np.finfo(float)`

# In[ ]:

print('machhine epsilon in python is: ' + str(np.finfo(float).eps))

# The overflow in python is shown by `np.finfo(float).max` and the underflow by `np.finfo(float).tiny`

# In[ ]:

print('The largest real number in python is: ' + str(np.finfo(float).max))
print('The smallest positive real number in python is: ' + str(np.finfo(float).tiny))

# Other attributes of `finfo` can be found [here](https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.finfo.html)

# ## Computation of the derivative

# The function $f(x) = e^x$ in $x=1$ is used as test function.
#
# * forward difference: $\displaystyle{f'(x)\approx\frac{f(x+h)-f(x)}{h}}$
# * central difference: $\displaystyle{f'(x)\approx\frac{f(x+h)-f(x-h)}{2h}}$
# * five points difference: $\displaystyles are $

# #### Determine the range you would like to experiment with

# In[ ]:

# choose h from 0.1 to 10^-t, t>=2
t = 15
hx = 10**np.linspace(-1,-t, 30)

# #### Compute the numerical derivatives using the three different schemes

# In[ ]:

# The exact derivative at x=1
x0 = 1
fprimExact = np.exp(1)

# Numeric derivative using the three methods
fprimF = ForwardDiff(np.exp, x0, hx);
fprimC = CentralDiff(np.exp, x0, hx);
fprim5 = FivePointsDiff(np.exp, x0, hx);

# Relative error
felF = abs(fprimExact - fprimF)/abs(fprimExact);
felC = abs(fprimExact - fprimC)/abs(fprimExact);
fel5 = abs(fprimExact - fprim5)/abs(fprimExact);

# #### Visualize the results

# In[ ]:

# Plot
fig, ax = plt.subplots(1)
ax.loglog(hx, felF)
ax.loglog(hx, felC)
ax.loglog(hx, fel5)
ax.autoscale(enable=True, axis='x', tight=True)
ax.set_xlabel(r'Step length $h$')
ax.set_ylabel('Relative error')
ax.legend(['Forward difference','Central difference', 'Five points difference'])

if saveFigure:
    filename = 'NumericalDerivative.pdf'
    fig.savefig(filename, format='pdf', dpi=1000, bbox_inches='tight')


import numpy as np
from fractions import Fraction as f

# Input and Table formation

n_variable=int(input("Enter the number of variables:")) #no. of variables
n_equation = int(input("Enter the number of  equations:")) #no. of equations

#Coeficient of Objective function
print("Enter the maximizing equation coefficient separated by space: ")
obj_fun=list(map(float,input().split()))
print(obj_fun)
for i in range(n_equation):
    obj_fun.append(float(0))
print(obj_fun)

# Basic variable column
B=list()
coefficient_matrix=list()

#Cost of Basic variable matrix
CB=list()
constraint=[]

# Coefficient Matrix
print("Enter the equations coefficient separated by space: e.g (a*x1 + b*x2 +c*x3 >= d, then write a b c d)")
for i in range(n_equation):
    entries=list(map(float,input().split()))
    constraint.append(entries.pop(-1))
    coefficient_matrix.append(entries)
A =np.array(coefficient_matrix)

print(constraint)
print(A)

#Making of tableu
for i in range(n_equation):
    CB.append(0)
    B.append(i+n_variable)
CB= np.array(CB)
CB=np.transpose([CB])
c= np.array(obj_fun)
c=np.transpose([c])
B = np.array(B)
B=np.transpose([B])
tableu = np.hstack((B, CB))
tableu = np.hstack((tableu, A))
slack=np.identity(n_equation)
tableu=np.append(tableu,slack,axis=1)
constraint=np.transpose([constraint])
tableu = np.hstack((tableu, constraint))
tableu = np.array(tableu, dtype ='float')

#Minimum Theta Calculation
def pivot_test(tableu,col_index):
    t=0
    row_index=0
    i=0
    minimum=99999
    l=list(tableu[:,col_index])
    while i < n_equation:
        if l[i] != 0.0:
            value=tableu[i,2+n_variable+n_equation]/l[i]
            if value >= 0:
                if minimum > value:
                    minimum= value
                    row_index=i
                    t=1
        i=i+1
    return row_index,t

# Table display and Iteration
s=""
itr=0
for i in range(n_equation+n_variable):
    s=s+("\tx" +str(i+1))
while True:
    itr=itr+1
    print("Table iteration: " + str(itr))
    print("B \tCB "+s+" \tRHS")
    i=0
    for row in tableu:
        for element in row:
            if i%(n_equation+n_variable+3)== 0:
                print('x'+str(int(element)+1), end ='\t')
            else:
                print(f(str(element)).limit_denominator(100), end ='\t')
            i=i+1
        print()
    print()
    i=0

    maximize=[]
    theta=[]
    while i<len(obj_fun):
        maximize.append(obj_fun[i] - np.sum(tableu[:, 1]*tableu[:, 2 + i]))
        i = i + 1
    print("maximize",end='\t')
    for element in maximize:
            print(f(str(element)).limit_denominator(100), end ='\t')
    if max(maximize)<=0:
        break
    col_index=maximize.index(max(maximize))+2
    row_index,t=pivot_test(tableu,col_index)
    if t==0:
        print("Unboundedness occured")
        break
    pivot=tableu[row_index,col_index]
    tableu[row_index, 2:n_equation+5] = tableu[row_index, 2:n_equation+5] / pivot
    i=0
    while i<n_equation:
        if i != row_index:
            tableu[i, 2:n_equation+5] = tableu[i,2:n_equation+5] - tableu[i][col_index]*tableu[row_index][2:n_equation+5]
        i=i+1
     # Assign the new basic variable
    tableu[row_index][0] = col_index-2
    tableu[row_index][1] = obj_fun[col_index-2]
    print()
    print()
# Alternate Solution
if not np.any(tableu[:,0]== 0):
    col_index=2
elif not np.any(tableu[:,0]== 1):
    col_index=3
else:
    col_index=-1
if (col_index == 2 or col_index == 3):
    row_index,t=pivot_test(tableu,col_index)
    pivot=tableu[row_index,col_index]
    tableu[row_index, 2:n_equation+5] = tableu[row_index, 2:n_equation+5] / pivot
    i=0
    while i<n_equation:
        if i != row_index:
            tableu[i, 2:n_equation+5] = tableu[i,2:n_equation+5] - tableu[i][col_index]*tableu[row_index][2:n_equation+5]
        i=i+1
    # Assign the new basic variable
    tableu[row_index][0] = col_index-2
    tableu[row_index][1] = obj_fun[col_index-2]
    print("\n\n \t\t Alternate Solution")
    itr=itr+1
    print("Table iteration: " + str(itr))
    print("B \tCB "+s+" \tRHS")
    i=0
    for row in tableu:
        for element in row:
            if i%(n_equation+n_variable+3)== 0:
                print('x'+str(int(element)+1), end ='\t')
            else:
                print(f(str(element)).limit_denominator(100), end ='\t')
            i=i+1
        print()
    print()
    print()
    print()
# Maximum  Possible Value
Z= np.sum(tableu[:, 1]*tableu[:,n_equation+n_variable+2])
print("Maximum Z= ",Z)


#!/usr/bin/env python

# 標準正規分布表見方
# あるZ値が生じる確率がわかる

# 平均が0　標準偏差が1　これに変換する = 標準化
# Z:標準化されたデータ
# σ 標準偏差
# Z = (x - μ) / σ
# 参考 https://qiita.com/y_itoh/items/c388ff82360906240daf
# 参考 https://bellcurve.jp/statistics/course/7805.html

from scipy.stats import norm

# 生存関数
# 確率変数XXがある値xx以上となる確率
def ProbabilityTop(x):
    return norm.sf(x=x)

# 累積分布関数
# 確率変数XXがある値xx以下となる確率
def ProbabilityBottom(x):
    return norm.cdf(x=x)

# 累積確率から横軸の値を出す
# 累積分布関数cdfの逆関数
def CumulativeProbability(persent):
    return norm.ppf(q=persent)

# パーセント点関数
# ある点が何％点かを求める
def PersentPoint(persent, μ, σ):
    # norm.ppf(q=パーセント, loc=平均, scale=標準偏差)
    return norm.ppf(q=persent, loc=μ, scale=σ)

def main():
    ## 生存関数
    ## 確率変数XXがある値xx以上となる確率
    # Q(0.86)
    # A : 0.195
    probability = ProbabilityTop(0.86)
    print("生存関数 確率", probability)

    ## 累積分布関数
    ## 確率変数XXがある値xx以下となる確率
    # Q(0.86)
    # A : 0.805
    probability = ProbabilityBottom(0.86)
    print("累積分布関数 確率", probability)

    ## 確率から累積確率
    # Q(z) = 0.195
    # A: z = 0.86
    z = CumulativeProbability(0.195)
    print("Zの値", z)

    # Z = x - μ / σ (標準化 Z~N(0,1))
    # 0.14 = x - 0 / 1
    persentPoint = PersentPoint(0.05, 0, 1)
    print("ある点の何％点", persentPoint)

if __name__ == "__main__":
    main()


#Chi - Squared Test Assignment

import numpy as np

"""
1.A random sample of employees of a large company was selected and the employees were asked to complete a questionnaire. One question asked was whether the employee was in favour of the introduction of flexible working hours. The following table classifies the employees by their response and their response and by their area of work
	Production	Non-Production
In Favour	129	171
Not in Favour	31	69
Test whether there is evidence of a significant association between the response and the area of work
"""
print("Assignment 1")
data=np.array([129,171,31,69]).reshape(2,2)

from scipy.stats import chi2_contingency
chistatistics,pvalue,dof,expected=chi2_contingency(data)
print("Observed value\n",data)
print("Expected value\n",expected)
print("Chi statistics:",chistatistics)
print("P value:",pvalue)

if pvalue<0.05:
    print("Reject the Null hypothesis")
    print("Significant association between response and area of work")
else:
    print("Fails to reject the null hypothesis")
    print("No Significant association between reponse and area of work")

print("\n")

"""
2.The theory predicts that the proportion of beans in four given groups should be 9:3:3:1 in an examination with 1600 beans, the numbers in the four groups were 882,313,287 and 118. Does the experiment result support the theory?
"""

print("Assignment 2")
ratio_sample=np.array([9,3,3,1])
observed_f=np.array([882,313,287,118])
expected_f=ratio_sample*(1600/np.sum(ratio_sample))

print("Observed Frequency:",observed_f)
print("Expected Frequency:",expected_f)

from scipy.stats import chisquare
chistatistics,pvalue=chisquare(f_obs=observed_f,f_exp=expected_f)

print("Chi statistics:",chistatistics)
print("P value:",pvalue)

if pvalue<0.05:
    print("Reject the Null hypothesis")
    print("Proportion of Beans are not in the given ratio")
else:
    print("Fails to reject the null hypothesis")
    print("Proportion of Beans are in the given ratio")


# -*- coding: utf-8 -*-

import numpy as np

def H(*P):
    p = 0.0
    for px in P:
        p += px * np.log2(px)
    return -p

print(H(0.5, 0.5))
print(H(0.3, 0.7))
print(H(0.01, 0.99))
print(H(0.00001, 0.99999))

print("====================")

print(H(0.25, 0.25, 0.25, 0.25))
print(H(0.7, 0.1, 0.1, 0.1))
print(H(0.9, 0.09, 0.009, 0.001))
print(H(0.999, 0.0009, 0.00009, 0.00001))
print(H(0.99999, 0.000009, 0.0000009, 0.0000001))

print("====================")

print(H(0.2, 0.2, 0.2, 0.2, 0.2))
print(H(0.1, 0.1, 0.1, 0.1, 0.6))
print(H(0.01, 0.01, 0.01, 0.01, 0.96))
print(H(0.5, 0.3, 0.1, 0.08, 0.02))
print(H(0.3, 0.3, 0.3, 0.05, 0.05))


import numpy as np

def calc_scores (x, y):
    # Computes the metrics CCC, PCC, and RMSE between the sequences x and y
    #  CCC:  Concordance correlation coeffient
    #  PCC:  Pearson's correlation coeffient
    #  RMSE: Root mean squared error
    # Input:  x,y: numpy arrays (one-dimensional)
    # Output: CCC,PCC,RMSE

    x_mean = np.nanmean(x)
    y_mean = np.nanmean(y)

    covariance = np.nanmean((x-x_mean)*(y-y_mean))

    x_var = 1.0 / (len(x)-1) * np.nansum((x-x_mean)**2) # Make it consistent with Matlab's nanvar (division by len(x)-1, not len(x)))
    y_var = 1.0 / (len(y)-1) * np.nansum((y-y_mean)**2)

    CCC = (2*covariance) / (x_var + y_var + (x_mean-y_mean)**2)

    x_std = np.sqrt(x_var)
    y_std = np.sqrt(y_var)

    PCC = covariance / (x_std * y_std)

    RMSE = np.sqrt(np.nanmean((x - y)**2))

    scores = np.array([ CCC, PCC, RMSE ])

    return scores


# Differential equation is: dy/d(theta) = 2*(1-theta)
# Using Finite Volume Method:   theta_e - theta_w = 2*delta_y*(1-theta_p)
# Or, ap*theta_p = ae*theta_e + aw_theta_w + b, where ae = 0, aw = 1, ap = 1+2*delta_y, b = 2*delta_y

import numpy as np
from matplotlib import pyplot as plt
x_points = 5   # Number of grid points
del_x = 0.25
x = np.linspace(0, 1, x_points)
theta = np.zeros(x_points)
ae = 0
aw = 1
ap = 1+2*del_x
b = 2*del_x

# Numerical Upwind scheme solution
for i in range(1,x_points-1):
    theta[i] = (ae*theta[i+1] + aw*theta[i-1] + b)/float(ap)

theta[0] = 0.0      # Adding the boundary conditions
theta[-1] = (aw*theta[-2] + b)/float(ap)

print ("Numerical solution")
print (theta)

# Analytical Solution
theta_an = 1 - np.exp(-2*x)

print ("Analytical solution")
print (theta_an)

# Plotting the solutions
plt.plot(x,theta)
plt.plot(x, theta_an)
plt.show()


##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                          Train PCA model
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#%% import required packages
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

#%% fetch data
data = pd.read_excel('proc1a.xlsx', skiprows = 1,usecols = 'C:AI')

#%% separate train data
data_train = data.iloc[0:69,]

#%% scale data
scaler = StandardScaler()
data_train_normal = scaler.fit_transform(data_train)

#%% PCA
pca = PCA()
score_train = pca.fit_transform(data_train_normal)

#%% decide # of PCs to retain and compute reduced data in PC space
explained_variance = 100*pca.explained_variance_ratio_ # in percentage
cum_explained_variance = np.cumsum(explained_variance) # cumulative % variance explained

n_comp = np.argmax(cum_explained_variance >= 90) + 1
score_train_reduced = score_train[:,0:n_comp]

print('Number of PCs cumulatively explaining atleast 90% variance: ', n_comp)

#%% reconstruct original data
V_matrix = pca.components_.T
P_matrix = V_matrix[:,0:n_comp]

data_train_normal_reconstruct = np.dot(score_train_reduced, P_matrix.T)

#%% calculate T2 for training data
lambda_k = np.diag(pca.explained_variance_[0:n_comp]) # eigenvalue = explained variance
lambda_k_inv = np.linalg.inv(lambda_k)

T2_train = np.zeros((data_train_normal.shape[0],))

for i in range(data_train_normal.shape[0]):
    T2_train[i] = np.dot(np.dot(score_train_reduced[i,:],lambda_k_inv),score_train_reduced[i,:].T)

#%% calculate Q for training data
error_train = data_train_normal - data_train_normal_reconstruct
Q_train = np.sum(error_train*error_train, axis = 1)

#%% T2_train control limit
import scipy.stats

N = data_train_normal.shape[0]
k = n_comp

alpha = 0.01# 99% control limit
T2_CL = k*(N**2-1)*scipy.stats.f.ppf(1-alpha,k,N-k)/(N*(N-k))

#%% Q_train control limit
eig_vals = pca.explained_variance_
m = data_train_normal.shape[1]

theta1 = np.sum(eig_vals[k:])
theta2 = np.sum([eig_vals[j]**2 for j in range(k,m)])
theta3 = np.sum([eig_vals[j]**3 for j in range(k,m)])
h0 = 1-2*theta1*theta3/(3*theta2**2)

z_alpha = scipy.stats.norm.ppf(1-alpha)
Q_CL = theta1*(z_alpha*np.sqrt(2*theta2*h0**2)/theta1+ 1 + theta2*h0*(1-h0)/theta1**2)**2

#%% Q_train plot with CL
plt.figure()
plt.plot(Q_train)
plt.plot([1,len(Q_train)],[Q_CL,Q_CL], color='red')
plt.xlabel('Sample #')
plt.ylabel('Q for training data')
plt.show()

#%% T2_train plot with CL
plt.figure()
plt.plot(T2_train)
plt.plot([1,len(T2_train)],[T2_CL,T2_CL], color='red')
plt.xlabel('Sample #')
plt.ylabel('T$^2$ for training data')
plt.show()

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                          Save model for later use
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
import pickle
PCAmodelData = {"PCAmodel": pca,
                "scaler": scaler,
                "n_comp": n_comp,
                "P_matrix": P_matrix,
                "lambda_k_inv": lambda_k_inv,
                "Q_CL": Q_CL,
                "T2_CL": T2_CL} # dictionary data structure uses key-value pairs

with open('PCAmodelData.pickle', 'wb') as f:
    pickle.dump(PCAmodelData, f, pickle.HIGHEST_PROTOCOL)


import numpy as np

def rsiFunc(prices, n=14):
    deltas = np.diff(prices)
    seed = deltas[:n + 1]
    up = seed[seed >= 0].sum() / n
    down = -seed[seed < 0].sum() / n
    rs = up / down
    rsi = np.zeros_like(prices)
    rsi[:n] = 100. - 100. / (1. + rs)

    for i in range(n, len(prices)):
        delta = deltas[i - 1]  # cause the diff is 1 shorter

        if delta > 0:
            upval = delta
            downval = 0.
        else:
            upval = 0.
            downval = -delta

        up = (up * (n - 1) + upval) / n
        down = (down * (n - 1) + downval) / n

        rs = up / down
        rsi[i] = 100. - 100. / (1. + rs)

    return rsi

def movingaverage(values, window):
    weigths = np.repeat(1.0, window) / window
    smas = np.convolve(values, weigths, 'valid')
    return smas  # as a numpy array

def ExpMovingAverage(values, window):
    weights = np.exp(np.linspace(-1., 0., window))
    weights /= weights.sum()
    a = np.convolve(values, weights, mode='full')[:len(values)]
    a[:window] = a[window]
    return a

def computeMACD(x, slow=26, fast=12):
    """
    compute the MACD (Moving Average Convergence/Divergence) using a fast and slow exponential moving avg'
    return value is emaslow, emafast, macd which are len(x) arrays
    """
    emaslow = ExpMovingAverage(x, slow)
    emafast = ExpMovingAverage(x, fast)
    return emaslow, emafast, emafast - emaslow


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

#The purpose of this program is to calculate the Radial, Tangential and Shear Stress in a circular tunnel given input parameters.

def RadialStress(Pz, Diameter, k, Theta, r, Pi):
    """
    RadialStress Function will Return the Radial Stress at a given point (r, Theta) and input parameters (Pz, Diameter, k, Pi)
    """
    a = Diameter/2
    Theta = math.radians(Theta)
    return (1/2)*Pz*((1+k)*(1-(a**2)/(r**2))+(1-k)*(1-4*(a**2)/(r**2)+3*(a**4)/(r**4))*math.cos(2*Theta))+Pi*((a**2)/(r**2))

def TangentialStress(Pz, Diameter, k, Theta, r, Pi):
    """
    TangentialStress Function will Return the Tangential Stress given point (r, Theta) and input parameters (Pz, Diameter, k, Pi)
    """
    a = Diameter/2
    Theta = math.radians(Theta)
    return (1/2)*Pz*((1+k)*(1+(a**2)/(r**2))-(1-k)*(1+3*(a**4)/(r**4))*math.cos(2*Theta))-Pi*((a**2)/(r**2))

def ShearStress(Pz, Diameter, k, Theta, r):
    """
    ShearStress Function will Return the Tangential Stress given point (r, Theta) and input parameters (Pz, Diameter, k, Pi)
    """
    a = Diameter/2
    Theta = math.radians(Theta)
    return (1/2)*Pz*(-(1-k)*(1+2*(a**2)/(r**2)-3*(a**4)/(r**4))*math.sin(2*Theta))

def OverStressZone(RadStress, TanStress, ShrStress, c=800, phi=32):
    #
    UCompStr = 2*c*math.cos(math.radians(phi))/(1-math.sin(math.radians(phi)))

    Sigma1 = (1/2)*(RadStress+TanStress)+(((1/4)*(RadStress-TanStress)**2+ShrStress^2))

    if Sigma1>UCompStr:
        return 1
    else:
        return 0

def main():

    for k in [0.5, 1, 2.5]:
        RadStress = []
        TanStress = []
        ShrStress = []
        r_list = []
        Pz = 2500 * 1.1
        Pi = 0
        Diameter = 10
        Theta = 90
    #Determine Stresses for Varying r and Plot Resulting Stresses
        for r in range(5,60,1):
            RadStress.append(RadialStress(Pz, Diameter, k, Theta, r, Pi))
            TanStress.append(TangentialStress(Pz, Diameter, k, Theta, r, Pi))
            ShrStress.append(ShearStress(Pz, Diameter, k, Theta, r))
            r_list.append(r)
        plt.figure(1)
        plt.plot(r_list, RadStress, '|-', label='Radial Stress, K= {}'.format(k))
        plt.plot(r_list, TanStress, label='Tangential Stress, K= {}'.format(k))
        plt.xlabel('Feet')
        plt.ylabel('Stress (PSI)')
        plt.title('Tangential and Radial Stresses')
        plt.legend()

    #Graphing for Internal Pressure = 500 PSI
    for k in [0.5, 1, 2.5]:
        Pi = 500
        RadStress = []
        TanStress = []
        ShrStress = []
        r_list = []
    #Determine Stresses for K = 0.5 and Plot Resulting Stresses
        for r in range(5,60,1):
            RadStress.append(RadialStress(Pz, Diameter, k, Theta, r, Pi))
            TanStress.append(TangentialStress(Pz, Diameter, k, Theta, r, Pi))
            ShrStress.append(ShearStress(Pz, Diameter, k, Theta, r))
            r_list.append(r)
        plt.figure(2)
    #plt.subplot(311)
        plt.plot(r_list, RadStress, '|-', label='Radial Stress, K= {}'.format(k))
        plt.plot(r_list, TanStress, label='Tangential Stress, K= {}'.format(k))
        plt.xlabel('Feet')
        plt.ylabel('Stress (PSI)')
        plt.title('Tangential and Radial Stresses, Internal Pressure of 500')
    plt.legend()
    plt.show()

    #Problem 2

    RadStress2 = []
    TanStress2 = []
    ShrStress2 = []
    r_list2 = []
    Pz = 2500 * 1.1
    Pi = 0
    Diameter = 10
    k = 0.5
    Theta = 0
        #for r in range(5, 10, 1):

            #RadStress2.append(RadialStress(Pz, Diameter, k, Theta, r, Pi))
            #TanStress2.append(TangentialStress(Pz, Diameter, k, Theta, r, Pi))
            #ShrStress2.append(ShearStress(Pz, Diameter, k, Theta, r))
            #r_list2.append(r)

if __name__ == "__main__":
    main()


import numpy as np
import matplotlib.pyplot as plt

# 模拟一些数据
x_series = np.linspace(1, 50, 30)
y_series = []
for x in x_series:
    y_series.append(5 * x + 6 + np.random.uniform(-10, 10))

# plt.scatter(x_series, y_series)
# plt.show()

# 数据标准化 z-score规范化
z_series = (x_series - np.mean(x_series)) / np.std(x_series)
# plt.scatter(z_series, y_series)
# plt.show()

# 开始模拟 初始化参数
theta0 = np.random.rand()
theta1 = np.random.rand()

# 预测函数
def f(x):
    return theta0 + theta1 * x

def E(x, y):
    return 0.5 * np.sum((y - f(x)) ** 2)

# 学习率η
ETA = 0.001  # 1e-3
# 误差的差值
diff = 1
# 更新的次数
count = 0

error = E(z_series, y_series)
while diff > 0.001:
    temp0 = theta0 - ETA * np.sum(f(z_series) - y_series)
    temp1 = theta1 - ETA * np.sum((f(z_series) - y_series) * z_series)

    # 更新参数
    theta0 = temp0
    theta1 = temp1

    # 计算与上次误差
    current_error = E(z_series, y_series)
    diff = error - current_error
    error = current_error

    count = count + 1
    print("第{}次 theta0 = {:.3f} theta1 = {:.3f}, 差值 = {:.4f}".format(count, theta0, theta1, diff))

# 最终验证
plt.scatter(z_series, y_series)
x = np.linspace(-3, 3, 100)
plt.plot(x, f(x))
plt.show()


import numpy as np

class PerceptronClassifier(object):
    """
    Perceptron classifier, training by Stochastic Gradient Descent Algorithm.
    """

    def __init__(self, step: float = 0.01, dual: bool = True, max_epoch: int = 10):
        """initialization
        :param step: 步长
        :param dual: 是否采用对偶形式
        :param max_epoch: 随机梯度下降最大迭代轮次，设置此参数来防止线性不可分情况下的无限迭代。
        迭代次数最多不超过 max_epoch * N(N为训练集样本的数量)
        """
        if dual:
            self.fit = self.fit_dual
        else:
            self.fit = self.fit_undual
        self.step = step
        self.max_epoch = max_epoch
        self.weight = None
        self.bias = None
        self.sign = np.vectorize(lambda x: 1 if x >= 0 else -1)

    def fit_undual(self, X: np.array, y: np.array):
        """常规训练方式
        :param X: 训练集X
        :param y: 训练集Y，只能由1或-1组成
        """
        self.weight = np.zeros(X.shape[1])
        self.bias = 0

        for _ in range(self.max_epoch * X.shape[0]):
            i = np.random.randint(0, X.shape[0])
            if y[i] * (self.weight @ X[i] + self.bias) <= 0:
                temp = self.step * y[i]
                self.weight += temp * X[i]
                self.bias += temp

    def fit_dual(self, X: np.array, y: np.array):
        """对偶形式Y
        :param X: 训练集X
        :param y: 训练集Y，只能由1或-1组成
        """
        # Gram matrix
        gram = X @ X.T
        alpha = np.zeros(X.shape[0])
        self.bias = 0
        for _ in range(self.max_epoch * X.shape[0]):
            i = np.random.randint(0, X.shape[0])
            if y[i] * (np.sum(alpha * y * gram[i]) + self.bias) <= 0:
                alpha[i] += self.step
                self.bias += self.step * y[i]
        self.weight = (alpha * y) @ X

    def predict(self, X):
        """预测
        :param X: 测试集合
        :return: 结果
        """
        return self.sign(self.weight @ X.T + self.bias)

    def get_model(self) -> (np.array, float):
        """获取模型的权重和偏置
        :return: weight, bias
        """
        return self.weight, self.bias


import numpy as np
import cv2

def psnr(img_1, img_2, data_range=255):
    mse = np.mean((img_1.astype(float) - img_2.astype(float)) ** 2)
    return 10 * np.log10((data_range ** 2) / mse)

img_org = cv2.imread('data/src/lena.jpg')
img_q95 = cv2.imread('data/src/lena_q95.jpg')
img_q50 = cv2.imread('data/src/lena_q50.jpg')

print(psnr(img_org, img_q95))
# 39.024557583745676

print(psnr(img_org, img_q50))
# 30.34829234238757

print(psnr(img_org, img_org))
# inf
#
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:3: RuntimeWarning: divide by zero encountered in double_scalars
#   This is separate from the ipykernel package so we can avoid doing imports until


import numpy as np
from matplotlib import pyplot as plt
from scipy import stats

def mean_confidence_interval(data, confidence=0.95):
    a = 1.0 * np.array(data)
    n = len(a)
    m, se = np.mean(a), stats.sem(a)
    h = se * stats.t.ppf((1 + confidence) / 2., n - 1)
    return m, m - h, m + h

def generate_uniform_data(a=.0, b=1.0, size=10):
    from numpy.random.mtrand import uniform
    return uniform(a, b, size)

def generate_exp_data(lam=1.0, size=10):
    from numpy.random.mtrand import exponential
    return exponential(lam, size)

def generate_triangular_data(a, b, peak, size=10):
    from numpy.random.mtrand import triangular
    return triangular(a, peak, b, size)

def mse(x):
    return np.sqrt(np.var(x))

def prep_for_output(data):
    return ", ".join(str(np.round(x, 2)) for x in data)

if __name__ == '__main__':
    alfa = 20
    lam = 1 / 200
    a = 190
    size = 100

    uniform_data = generate_uniform_data(b=alfa, size=size)
    exp_data = generate_exp_data(lam=lam, size=size)
    triang_data = generate_triangular_data(0, a, 0, size=size)

    print(f'Uniform: {prep_for_output(uniform_data)}')
    estim_data_for_uniform = mean_confidence_interval(uniform_data)
    print(f'Mean value estimation for uniform: {estim_data_for_uniform}')
    print(f'MSE value estimation for uniform: {mse(uniform_data)}')
    print()

    print(f'Exponential : {prep_for_output(exp_data)}')
    estim_data_for_exp = mean_confidence_interval(exp_data)
    print(f'Mean value estimation for uniform: {estim_data_for_exp}')
    print(f'MSE value estimation for uniform: {mse(exp_data)}')
    print()

    print(f'Triangular: {prep_for_output(triang_data)}')
    estim_data_for_triang = mean_confidence_interval(triang_data)
    print(f'Mean value estimation for uniform: {estim_data_for_triang}')
    print(f'MSE value estimation for uniform: {mse(triang_data)}')
    print()

    plt.hist(uniform_data)
    plt.title('Uniform distribution')
    plt.grid(True)
    plt.box(True)
    plt.show()
    plt.hist(exp_data)
    plt.title('Exponential distribution')
    plt.grid(True)
    plt.box(True)
    plt.show()
    plt.hist(triang_data)
    plt.title('Triangular distribution')
    plt.grid(True)
    plt.box(True)
    plt.show()


import numpy as np
import matplotlib.pyplot as plt

# Qubic Splines Method
def CubicSplines(x_data, f_data, x):
    n = len(x_data)
    a, b, c, d = f_data, np.zeros(n), np.zeros(n), np.zeros(n)

    # Intervals
    h = np.zeros(n)
    for i in range(n-1):
            h[i] = x_data[i+1] - x_data[i]

    def SystemSolver():
        A, B, X = np.zeros((n, n)), np.zeros((n, 1)), np.zeros((n, 1))
        # AX = B and we look for X = c

        # Array A
        for row in range(1, n - 1):
            for col in range(n):
                if col == row - 1:
                    A[row][col] = h[row - 1]
                elif col == row:
                    A[row][col] = 2 * (h[row - 1] + h[row])
                elif col == row + 1:
                    A[row][col] = h[row]
        A[0][0], A[n - 1][n - 1] = 1.0, 1.0

        # Array B
        for row in range(1, n - 1):
            B[row] = 3 * (a[row + 1] - a[row]) / h[row] - 3 * (a[row] -
                     a[row - 1]) / h[row - 1]
        B[0][0], B[n - 1][0] = 0.0, 0.0

        # Gauss - Siedel
        N = 200  # Iterations

        for i in range(N):
            for row in range(n):
                U = X.copy()  # clone of X with zerod the X[row]
                              # element
                U[row] = 0
                X[row] = (B[row] - A[row] @ U)/A[row, row]

        return X

    c = SystemSolver()

    for i in range(n-1):
        b[i] = (a[i+1] - a[i])/h[i] - h[i]*(c[i+1] + 2*c[i])/3.0

    for i in range(n-1):
        d[i] = (c[i+1] - c[i])/(3.0*h[i])

    def Spline():
        S = 0.0

        for i in range(n-1):
            if x >= x_data[i] and x <= x_data[i + 1]:
                S = a[i] + b[i]*(x - x_data[i]) + \
                    c[i]*pow(x - x_data[i], 2) + \
                    d[i]*pow(x - x_data[i], 3)

        return S

    return Spline()

if __name__ == "__main__":
    # Some Data
    x_data = [-1.6, -1.0, -0.4, 0.2, 0.8, 1.4]
    f_data = [0.278037, 0.606531, 0.923116, 0.980199, 0.726149, 0.375311]

    print('\nComputated with Cubic Splines Method:')
    print(f'\tf(0) = {CubicSplines(x_data, f_data, 0)[0]:.8f}')
    print(f'\tf(1) = {CubicSplines(x_data, f_data, 1)[0]:.8f}')

    x = np.linspace(-1.6, 1.4, 150)
    y = np.zeros(len(x))
    i = 0

    for point in x:
        y[i] += CubicSplines(x_data, f_data, point)
        i += 1

    plt.subplot(1, 1, 1)
    plt.plot(x, y, linewidth=1, color = 'cyan', label='Cubic Splines')
    plt.scatter(x_data, f_data, color='black', marker = ".", label='Sample Points')

    plt.legend(loc='lower center', prop={'size': 12})
    plt.ylabel('$y$')
    plt.xlabel('$x$')
    plt.title('Cubic Splines Method')

    plt.tight_layout()
    plt.show()


import numpy as np
def pagerank(M, num_iterations: int = 100, d: float = 0.85):
  N = M.shape[1]
  v = np.random.rand(N, 1)
  v = v / np.linalg.norm(v, 1)
  M_hat = (d * M + (1 - d) / N)
  for i in range(num_iterations):
    v = M_hat @ v
  return v
M = np.array([[0, 0, 1, 1/2],
             [1/3, 0, 0, 0],
             [1/3, 1/2, 0, 1/2],
             [1/3, 1/2, 0, 0]])
v = pagerank(M, 13, 1)
print(v)

# OUTPUT :
# [[0.3869425 ]
# [0.12906956]
# [0.29036123]
# [0.19362671]]


from statistics import mean
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import style

xs = np.array([1, 2, 3, 4, 5, 6], dtype = np.float64)
ys = np.array([5, 4, 6, 5, 6, 7], dtype = np.float64)
'''
Formula for Linear regression's slope is
Y = Mx + B
Where M is the slope and B is the y-intercept

M = Mean(x)*Mean(y) - mean(x*y) / mean(xs)^2 - mean(xs^2)
B = mean(ys) - m * mean(xs)

'''
def best_fit_slope_and_intercept(xs, ys):
	m = (((mean(xs) * mean(ys)) - mean(xs * ys)) /
		 ((mean(xs) * mean(xs)) - mean(xs * xs)))
	b = mean(ys) - m * mean(xs)

	return m, b

m, b = best_fit_slope_and_intercept(xs, ys)
regression_line = [(m*x) + b for x in xs]

plt.scatter(xs, ys)
plt.plot(xs, regression_line)
plt.show()


import numpy as np

def gaussian_divergence(mu1, mu2, sig1, sig2):
    """ Analytical result for KL-divergence of two Gaussians.

    D( N(mu1, sig1) | N(mu2,sig2) )
    Ref: http://allisons.org/ll/MML/KL/Normal/
    """

    mudiff  = pow(mu1-mu2, 2)
    sigdiff = sig1*sig1 - sig2*sig2
    lograt  = np.log(sig2/sig1)
    return lograt + (mudiff + sigdiff) / (2*sig2*sig2)


import numpy as np
from numpy import random as rnd

#------------Ackley function----------

def ackley_fn (X):
    x = X[0]
    y = X[1]
    exp1 = np.exp(-0.2 * np.sqrt(0.5 * (x**2 + y**2)))
    exp2 = np.exp(0.5 * (np.cos(2 * np.pi * x) + np.cos(2 * np.pi * y)))
    return -20 * exp1 - exp2 + np.e + 20

#----------Himmelblau function---------

def himmelblau_fn (X):
    x = X[0]
    y = X[1]
    return np.square(x**2 + y - 11) + np.square(x + y**2 - 7)

#----------Rastrigin function----------

def rastrigin_fn (X):
    x = X[0]
    y = X[1]
    return 20 + x**2 + y**2 - 10 * (np.cos(2 * np.pi * x) + np.cos(2 * np.pi * y))

#---------Rosenbrock function----------

def rosenbrock_fn (X):
    x = X[0]
    y = X[1]
    return np.square(1 - x) + 100 * np.square(y - x**2)


import math
from typing import Tuple, Iterator

import numpy

def cart2pol(x: float, y: float, in_deg: bool = True) -> Tuple[float, float]:
    r = math.sqrt(pow(x, 2) + pow(y, 2))
    theta = math.atan2(y, x)

    if in_deg:
        theta = math.degrees(theta)

    return r, theta

def pol2cart(r: float, theta: float, in_degs: bool = True) -> Tuple[float, float]:
    if in_degs:
        theta = (theta + 180) % 360 - 180
        theta = math.radians(theta)
    else:
        theta = (theta + (math.pi / 2)) % math.pi - (math.pi / 2)

    x = r * math.cos(theta)
    y = r * math.sin(theta)

    return x, y

def make_even_grid(n: int) -> Tuple[int, int]:
    nx = int(math.ceil(math.sqrt(n)))
    ny = int(math.ceil(float(n) / float(nx)))
    return nx, ny

def init_arrow_coords(dims: Tuple[int, int], n: int) -> Iterator[Tuple[int, int]]:
    w, h = dims
    nx, ny = make_even_grid(n)

    xx = numpy.linspace(0, w, num=nx + 1, endpoint=False)[1:]
    yy = numpy.linspace(0, h, num=ny + 1, endpoint=False)[1:]

    yy, xx = numpy.meshgrid(yy, xx)
    xx, yy = numpy.ravel(xx), numpy.ravel(yy)
    xx, yy = xx[:n], yy[:n]
    xx, yy = (int(round(x)) for x in xx), (int(round(y)) for y in yy)

    return zip(xx, yy)


import math

import numpy as np

def spearman(rank1: np.ndarray, rank2: np.ndarray):
    if (not np.issubdtype(rank1.dtype, np.integer)) or (not np.issubdtype(rank2.dtype, np.integer)):
        raise ValueError("rank arrays must be of integer type")

    if rank1.ndim > 1 or rank2.ndim > 1:
        raise ValueError("rank arrays must be of dimension 1")

    distance = rank1 - rank2
    size = rank1.shape[0]

    return 1 - (6 * np.sum(distance * distance)) / (size * (size * size - 1))

def _sign(value: float) -> float:
    return math.copysign(1.0, value)

def kendall(rank1: np.ndarray, rank2: np.ndarray):
    if (not np.issubdtype(rank1.dtype, np.integer)) or (not np.issubdtype(rank2.dtype, np.integer)):
        raise ValueError("rank arrays must be of integer type")

    if rank1.ndim > 1 or rank2.ndim > 1:
        raise ValueError("rank arrays must be of dimension 1")

    concordant_sum = 0
    size = rank1.shape[0]

    for i in range(size):
        for j in range(size):
            if i < j:
                concordant_sum += _sign(rank1[i] - rank1[j]) * _sign(rank2[i] - rank2[j])

    return 2.0 / (size * (size - 1)) * concordant_sum

def _test():
    rank1 = np.array([0, 1, 2, 3])
    rank2 = np.array([0, 2, 1, 3])

    print(spearman(rank1, rank2))
    print(kendall(rank1, rank2))

if __name__ == "__main__":
    _test()


# -*- encoding: utf-8 -*-
import numpy as np
import numpy.linalg
import scipy
import scipy.linalg
import numpy.linalg
import matplotlib.pyplot as plt
from helpers import evalchebexp, chebexp, clenshaw
import numpy.random

# Polynominterpolation

def monom(f, a, b, N, M):
    """
    Interpolation mit Monombasis einer Funktion mit aquidistanten Stützstellen

    @param {callable} f          - Funktion zur Approximation
    @param [{int}, {int}] [a, b] - Intervall zur Interpolation
    @param {int} N               - Grad des Polynoms
    @param {int} M               - Anzahl Auswertungspunkte in [a,b]

    @return {callable}  - Interpolations-Polynom
    """

    x = np.linspace(a, b, M)
    c = numpy.linalg.solve(np.vander(x), f(x))
    return lambda v: np.polyval(c, v)

def chebychev(f, a, b, N):
    """
    Interpolation einer Funktion mit Chebychev-Stützstellen direkt evaluiert

    @param {callable} f          - Funktion zur Approximation
    @param [{int}, {int}] [a, b] - Intervall zur Interpolation
    @param {int} N               - Grad des Polynoms

    @return {callable}  - Interpolations-Polynom
    """

    x = a + 0.5*(b-a)*(1.0 + np.cos(0.5*np.pi*(2*np.arange(N+1)+1)/(N+1.0))) #Cheby Knoten
    c = numpy.linalg.solve(numpy.vander(x), f(x))
    return lambda v: np.polyval(c, v)

def cheby_with_evalchebexp(f, a, b, N):
    """
    Interpolation einer Funktion mit Chebychev-Stützstellen evaluiert mit evalchebexp

    @param {callable} f          - Funktion zur Approximation
    @param [{int}, {int}] [a, b] - Intervall zur Interpolation
    @param {int} N               - Grad des Polynoms

    @return {array} [x, y]  - x, y Koordinaten
    """
    x = a + 0.5*(b-a)*(1.0 + np.cos(0.5*np.pi*(2*np.arange(N+1)+1)/(N+1.0))) #Cheby Knoten
    c = chebexp(f(x))
    return evalchebexp(c, N)

def cheby_with_clenshaw(f, a, b, N):
    """
    Interpolation einer Funktion mit Chebychev-Stützstellen evaluiert mit dem Clenshaw-Algorithmus

    @param {callable} f          - Funktion zur Approximation
    @param [{int}, {int}] [a, b] - Intervall zur Interpolation
    @param {int} N               - Grad des Polynoms

    @return {array} [x, y]  - x, y Koordinaten
    """
    x = a + 0.5*(b-a)*(1.0 + np.cos(0.5*np.pi*(2*np.arange(N+1)+1)/(N+1.0))) #Cheby Knoten
    c = chebexp(f(x))
    return x, clenshaw(c, x)

def my_polyfit(x, y, N):
    return numpy.linalg.solve(numpy.vander(x), y)

def barycentric_weights(x):
    """
    Berechne die baryzentrischen Gewichte zu den Stützstellen x

    @param {array} x    - Stützstellen
    @return {array} w   - baryzentrische Gewichte
    """
    w = np.ones_like(x).astype(float)
    for j, xj in enumerate(x):
        for k, xk in enumerate(x):
            if (k != j): w[j] /= (xj - xk)
    return w

def barycentric(x, fx):
    """
    Baue das Lagrangesche Interpolationspolynom

    @param {array} x    - Stützstellen
    @param {array} fx   - Werte an den Stützstellen
    @return {callable}  - Interpolationspolynom (Achtung beim auswerten kein Broadcasting)
                          Auswerten: px = np.array([p(x) for x in X])
                          Nicht so: px = p(X), falls X ein Array
    """
    w = barycentric_weights(x)
    return lambda t: np.dot(w/(t - x), fx)/np.sum(w/(t - x))

# Trigonometrische Interpolation
#TODO

#########
# Tests #
#########

if __name__ == '__main__':

    #sint = np.sin(t)
    #sp = np.fft.fft(sint)
    #freq = np.fft.fftfreq(t.shape[-1])
    #plt.plot(freq, sp.real, freq, sp.imag)

    """
    x = np.sin(np.arange(64))
    n = np.size(x)
    ft = np.fft.fftshift(np.fft.fft(x))
    m = np.size(np.fft.fft(x))
    #plt.plot(x, np.fft.fft(x))
    plt.vlines(np.arange(n), np.zeros(n), x, colors='g')
    plt.vlines(np.arange(-m/2, m/2), np.zeros(m), ft, colors='r')
    plt.show()
    """
    """
    x = np.arange(64)
    y = np.sin(2*np.pi*x/64) + np.sin(7*2*np.pi*x/64)
    y = y + np.random.randn(len(x)) #distortion
    c = np.fft.fft(y)
    p = np.abs(c)**2
    p /= 64.
    plt.plot(x,y,'-+')
    plt.show()
    plt.bar(x[:32],p[:32])
    plt.show()
    """

    """

    f = lambda x: 1.0/(1.0 + x**2)
    g = lambda x: 0.5*f(5*x) + f(5*x+5)

    l = -1.0
    r = 1.0
    x = np.linspace(l, r, 10**3)
    N = 21

    p1 = monom(g, l, r, N, N+1)
    y1 = p1(x)
    p2 = chebychev(g, l, r, N)
    y2 = p2(x)
    x3, y3 = cheby_with_evalchebexp(g, l, r, N)
    x4, y4 = cheby_with_clenshaw(g, l, r, N)

    plt.figure()
    plt.plot(x, g(x), label=r"Original")
    plt.plot(x, y1, label=r"Äquidistant")
    plt.plot(x, y2, label=r"Chebychev, direkt")
    plt.plot(x3, y3, label=r"Chebychev-Abzissen")
    plt.plot(x4, y4, label=r"Clenshaw")
    plt.grid(True)
    plt.xlim(l, r)
    plt.ylim(-2, 2)
    plt.legend(loc='lower center', framealpha=0.8)
    plt.title('Aequidistant interpolation points')
    plt.show()

    """

    # Bsp: Lagrange Basis aus Prüfung H14 A3

    # Polynom aus der Aufgabenstellung
    f = lambda t: 1 + (1 + 2 ** 20) * t ** 4 + t ** 8
    # Stuetzstellen
    t = np.linspace(-4.0, 4.0, 36)
    y = f(t)
    # Auswertungspunkte
    x = np.linspace(t[0], t[-1], 1000)
    # Exakte Funktionswerte
    fvs = f(x)

    # a) Polynominterpolation mit polyfit und polyval
    #coeffs_polyfit = zeros_like(y)
    coeffs_polyfit = np.polyfit(x, fvs, 8)

    ######################################################################
    #                                                                    #
    # TODO: Berechnen Sie hier die Polynom-Koeffizienten mittels polyfit #
    #                                                                    #
    ######################################################################

    print("Coefficients of the polynomial are:")
    print(coeffs_polyfit)
    p = np.polyval(coeffs_polyfit, x)

    plt.figure()
    plt.subplot(2,1,1)
    plt.plot(x, fvs, "r")
    plt.plot(x, p, "b--")
    plt.plot(t, f(t), "k*")
    plt.grid(True)
    plt.legend(["Funktion $f$", 'Interpolationspolynom'], loc="best")
    plt.xlabel("x")

    plt.subplot(2,1,2)
    plt.semilogy(x, abs(fvs - p), 'b--')
    plt.grid(True)
    plt.xlabel("x")
    plt.ylabel("Fehler")
    plt.title('polyval(polyfit)')
    plt.tight_layout()
    plt.savefig('polyfit_polyval.png')

    # b) Baryzentrische Formel
    plt.figure()
    plt.subplot(2,1,1)
    barweight = barycentric_weights(t)

    p = barycentric(t, y)
    px = np.array([p(X) for X in x])

    plt.plot(x, fvs, "r")
    plt.plot(x, px, "b--")
    plt.plot(t, f(t), "k*")
    plt.grid(True)
    plt.legend(["Funktion $f$", 'Interpolationspolynom'], loc="best")
    plt.xlabel("x")

    plt.subplot(2,1,2)
    plt.semilogy(x, abs(fvs - px), 'b--')
    plt.grid(True)
    plt.xlabel("x")
    plt.ylabel("Fehler")
    plt.title('Baryzentrische Koordinaten')
    plt.tight_layout()
    plt.savefig('polyfit_barycentric.png')


from numpy import array
from numpy.linalg import inv
from random import randint

class LinearRegression:
    """
    Linear Regression with Gradient Descent to minimize cost function

    Attributes
    ----------
    m: int
        number of training examples
    n: int
        number of features e.g x1, x2, x3
    features: 2d m*n list
        features of training set
    outputs: m-sized list
        outputs of training set
    parameters: (n)-sized list
        parameters of linear regression

    Methods
    -------
    predict(features)
        predicts output for given features based on calculated parameters
    """

    def __init__(self, features: list, outputs: list, learning_rate=0.01, learning_algorithm='bgd'):
        """
        Parameters
        ----------
        features: 2d m*n list
            features of training set
        outputs: m-sized list
            outputs of training set
        learning_rate: float between 0 and 1, optional
            rate of minizing cost function
        learning_algorithm: string
            learning algorithm type (bgd|sgd|ma)
        """
        self.features = features
        for feature in self.features:
            feature.append(1)  # constant feature
        self.outputs = outputs
        self.learning_rate = learning_rate

        self.m = len(features)
        self.n = len(features[0])
        self.parameters = [0]*(self.n)
        assert learning_algorithm in ('bgd', 'sgd', 'ma')
        if learning_algorithm == 'bgd':
            self.__batch_gradient_descent()
        elif learning_algorithm == 'sgd':
            self.__stochastic_gradient_descent()
        elif learning_algorithm == 'ma':
            self.__matrix_approach()
        print("Learned parameters:", self.parameters)

    def __batch_gradient_descent(self):
        """Alters parameters to minimize cost"""
        for _ in range(int(1e3)):
            total_cost = 0
            for j in range(self.n):
                marginal_cost = 0  # derivative of cost function
                for i in range(self.m):
                    marginal_cost += (self.predict(
                        self.features[i]) - self.outputs[i])*self.features[i][j]
                    print(marginal_cost)
                self.parameters[j] -= self.learning_rate * marginal_cost
                total_cost += abs(marginal_cost)
            # break when local minimum is found
            if total_cost < 1e-5:
                break

    def __stochastic_gradient_descent(self):
        """Alters parameters to minimize cost"""
        for _ in range(int(1e3)):
            for i in range(self.m):
                for j in range(self.n):
                    marginal_cost = (self.predict(
                        self.features[i]) - self.outputs[i])*self.features[i][j]
                    self.parameters[j] -= self.learning_rate * marginal_cost
            # TODO: implement termination condition

    def __matrix_approach(self):
        """Matrix approach to simple linear regression"""
        X = array(self.features)
        y = array(self.outputs)
        # linear least squares
        self.parameters = list(inv(X.T.dot(X)).dot(X.T).dot(y))

    def predict(self, features: list) -> float:
        """
        Predicts output based on features and calculated parameters

        Parameters
        ----------
        features: list
            list of features

        Returns
        -------
        float
            predicted output
        """
        prediction = 0
        x = features.copy()
        if len(x) == len(self.parameters)-1:
            x.append(1)
        for j in range(len(x)):
            prediction += self.parameters[j] * x[j]

        return prediction

if __name__ == "__main__":
    # inputs/features x is a m*n array
    # output/target value y is an array with size of n
    x, y = [], []

    def sample_function(x1, x2):
        return x1 + 2*x2 + 3

    for _ in range(10):
        x1 = randint(-9999, 9999)
        x2 = randint(-9999, 9999)
        x.append([x1, x2])
        # y = x1 + 2 * x2 + 3
        y.append(sample_function(x1, x2))

    regression = LinearRegression(
        x, y, learning_rate=0.01, learning_algorithm='bgd')
    x1 = randint(-9999, 9999)
    print("x1:", x1)
    x2 = randint(-9999, 9999)
    print("x2:", x2)
    print("Expected output:", sample_function(x1, x2))
    # expected result is y = 5 + 2 * 6 + 3 = 20
    print("Predicted output:", regression.predict([x1, x2]))


import numpy as np
import warnings

def interpolate_linear(start, end, steps):
    """ Interpolate series between start and end in given number of steps - linear interpolation """
    return np.linspace(start, end, steps)

def interpolate_logscale(start, end, steps):
    """ Interpolate series between start and end in given number of steps - logscale interpolation """
    if start <= 0.0:
        warnings.warn("Start of logscale interpolation must be positive!")
        start = 1e-5

    return np.logspace(np.log10(float(start)), np.log10(float(end)), steps)

def interpolate_cosine_single(start, end, coefficient):
    """ Cosine interpolation """
    cos_out = (np.cos(np.pi*coefficient) + 1) / 2.0
    return end + (start - end) * cos_out

def interpolate_linear_single(start, end, coefficient):
    """ Cosine interpolation """
    return start + (end - start) * coefficient

def interpolate_logscale_single(start, end, coefficient):
    """ Cosine interpolation """
    return np.exp(np.log(start) + (np.log(end) - np.log(start)) * coefficient)

INTERP_DICT = {
    'linear': interpolate_linear,
    'logscale': interpolate_logscale
}

INTERP_SINGLE_DICT = {
    'linear': interpolate_linear_single,
    'logscale': interpolate_logscale_single,
    'cosine': interpolate_cosine_single
}

def interpolate_series(start, end, steps, how='linear'):
    """ Interpolate series between start and end in given number of steps """
    return INTERP_DICT[how](start, end, steps)

def interpolate_single(start, end, coefficient, how='linear'):
    """ Interpolate single value between start and end in given number of steps """
    return INTERP_SINGLE_DICT[how](start, end, coefficient)


import numpy as np

def calculate(list) -> dict:
  try:
    if len(list) != 9:
      raise ValueError("List must contain nine numbers.")
    calculations = {}
    #create a 3x3 numpy array from the input list
    input_array = np.array([list[0:3],list[3:6],list[6:9]])
    #calc mean[axis1, axis2, flattened]
    calculations['mean'] = calculations.get('mean',[input_array.mean(axis=0).tolist(),input_array.mean(axis=1).tolist(),input_array.flatten().mean()])
    #calc variance[axis1, axis2, flattened],
    calculations['variance']= calculations.get('variance', [input_array.var(axis=0).tolist(),input_array.var(axis=1).tolist(),input_array.flatten().var()])
    #calc std div[axis1, axis2, flattened],
    calculations['standard deviation']= calculations.get('standard deviation', [input_array.std(axis=0).tolist(),input_array.std(axis=1).tolist(),input_array.flatten().std()])
    #calc min [axis1, axis2, flattened]
    calculations['max']= calculations.get('max', [input_array.max(axis=0).tolist(),input_array.max(axis=1).tolist(),input_array.flatten().max()])

    #calc max [axis1, axis2, flattened]
    calculations['min']= calculations.get('min', [input_array.min(axis=0).tolist(),input_array.min(axis=1).tolist(),input_array.flatten().min()])
    #calc sum
    calculations['sum']= calculations.get('sum', [input_array.sum(axis=0).tolist(),input_array.sum(axis=1).tolist(),input_array.flatten().sum()])
    #return excpetion valueerror if len(inputlist) <> 9
  except ValueError:
    raise

  return calculations


import numpy as np
def gauss(x, amp, mu, sig):
    return amp*np.exp(-(x-mu)**2/(2*sig**2))

def rectangular(npoints, amp):
    array = amp*np.ones(npoints)
    array[0] = 0
    array[1] = 0
    array[npoints-1] = 0
    array[npoints-2] = 0
    return array

##def chirped():
##def adiabatic():