''' mbinary
#########################################################################
# File : fft.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.xyz
# Github: https://github.com/mbinary
# Created Time: 2019-06-11  12:48
# Description:
#########################################################################
'''
import numpy as np

def _fft_n2(a, invert):
    '''O(n^2)'''
    N = len(a)
    w = np.arange(N)
    i = 2j if invert else -2j
    m = w.reshape((N, 1)) * w
    W = np.exp(m * i * np.pi / N)
    return np.concatenate(np.dot(W, a.reshape((N,
                                               1))))  # important, cannot use *

def _fft(a, invert=False):
    '''recursion version'''
    N = len(a)
    if N == 1:
        return [a[0]]
    elif N & (N - 1) == 0:  # O(nlogn),  2^k
        even = _fft(a[::2], invert)
        odd = _fft(a[1::2], invert)
        i = 2j if invert else -2j
        factor = np.exp(i * np.pi * np.arange(N // 2) / N)
        prod = factor * odd
        return np.concatenate([even + prod, even - prod])
    else:
        return _fft_n2(a, invert)

def _fft2(a, invert=False):
    ''' iteration version'''

    def rev(x):
        ret = 0
        for i in range(r):
            ret <<= 1
            if x & 1:
                ret += 1
            x >>= 1
        return ret

    N = len(a)
    if N & (N - 1) == 0:  # O(nlogn),  2^k
        r = int(np.log(N))
        c = np.array(a, dtype='complex')
        i = 2j if invert else -2j
        w = np.exp(i * np.pi / N)
        for h in range(r - 1, -1, -1):
            p = 2**h
            z = w**(N / p / 2)
            for k in range(N):
                if k % p == k % (2 * p):
                    c[k], c[k + p] = c[k] + c[k + p], c[k] * z**(k % p)

        return np.asarray([c[rev(i)] for i in range(N)])
    else:  # O(n^2)
        return _fft_n2(a, invert)

def fft(a):
    '''fourier[a]'''
    n = len(a)
    if n == 0:
        raise Exception("[Error]: Invalid length: 0")
    return _fft(a)

def ifft(a):
    '''invert fourier[a]'''
    n = len(a)
    if n == 0:
        raise Exception("[Error]: Invalid length: 0")
    return _fft(a, True) / n

def fft2(arr):
    return np.apply_along_axis(fft, 0,
                               np.apply_along_axis(fft, 1, np.asarray(arr)))

def ifft2(arr):
    return np.apply_along_axis(ifft, 0,
                               np.apply_along_axis(ifft, 1, np.asarray(arr)))

def test(n=128):
    print('\nsequence length:', n)
    print('fft')
    li = np.random.random(n)
    print(np.allclose(fft(li), np.fft.fft(li)))

    print('ifft')
    li = np.random.random(n)
    print(np.allclose(ifft(li), np.fft.ifft(li)))

    print('fft2')
    li = np.random.random(n * n).reshape((n, n))
    print(np.allclose(fft2(li), np.fft.fft2(li)))

    print('ifft2')
    li = np.random.random(n * n).reshape((n, n))
    print(np.allclose(ifft2(li), np.fft.ifft2(li)))

if __name__ == '__main__':
    for i in range(1, 4):
        test(i * 16)


import numpy as np

A = np.array([[5, 5], [2, 8]])
#A = np.array([[6,-1], [2,3]])
#A = np.array([[3,2,4], [2,0,2], [4,2,3]])
#A = np.array([[12,-51,4], [6,167,-68], [-4,24,-41]])

def power_iteration(A, num_simulations):
  b_k = np.random.rand(A.shape[1])

  for _ in range(num_simulations):
    # calculate the matrix-by-vector product Ab
    b_k1 = np.dot(A, b_k)

    # calculate the norm
    b_k1_norm = np.linalg.norm(b_k1)

    # re normalize the vector
    b_k = b_k1 / b_k1_norm

  return b_k

print("%s\n"%power_iteration(A, 32))

w, v = np.linalg.eig(A)

print(w)
print(v)


#########################
##                     ##
## Irving Gomez Mendez ##
##  February 12, 2021  ##
##                     ##
#########################

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

dat = np.array([[100, 89, 89, 92, 78, 101, 90, 82, 95, 108, 111, 112,
    125, 123, 100, 102, 112, 112, 100, 107, 103, 129, 118, 149],
    [709, 740, 586, 806, 694, 760, 664, 509, 619, 652, 772, 896,
    742, 831, 667, 772, 838, 679, 889, 690, 698, 860, 799, 882]]).T
dat = dat/10

n = dat.shape[0]
yy = dat[:,1]
XX = np.vstack([np.ones(n),dat[:,0]]).T
p = XX.shape[1]

# We compute the coeff.
# Calculating the inverse
beta_0, beta_1 = np.linalg.inv(XX.T @ XX) @ XX.T @ yy
beta_0
beta_1

# Using solve
beta_0, beta_1 = np.linalg.solve(XX.T @ XX, XX.T @ yy)
beta_0
beta_1

# Using the least squares procedure
beta_0, beta_1 = np.linalg.lstsq(XX, yy, rcond=None)[0]
beta_0
beta_1

# Calculate the SSE
hat_yy = XX @ np.array([beta_0, beta_1])
SSE = sum((hat_yy-yy)**2)
SSE

# Using the least squares procesure
SSE = np.linalg.lstsq(XX, yy, rcond=None)[1]
SSE

# We get confidence interval
alpha = 0.05
x0 = np.linspace(7, 15, 50)
X0 = np.array([np.ones(len(x0)),x0]).T

aux_t_conf = np.sqrt(SSE/(n-p)*(np.diag(X0 @ np.linalg.inv(XX.T @ XX) @ X0.T)))
yy0_hat = X0 @ np.array([beta_0, beta_1])
upp_conf = yy0_hat+t.ppf(1-alpha/2,n-p)*aux_t_conf
low_conf = yy0_hat-t.ppf(1-alpha/2,n-p)*aux_t_conf

# We get prediction interval
aux_t_pred = np.sqrt(SSE/(n-p)*(1+np.diag(X0 @ np.linalg.inv(XX.T @ XX) @ X0.T)))
yy0_hat = X0 @ np.array([beta_0, beta_1])
upp_pred = yy0_hat+t.ppf(1-alpha/2,n-p)*aux_t_pred
low_pred = yy0_hat-t.ppf(1-alpha/2,n-p)*aux_t_pred

plt.figure(figsize=(10,5))
plt.plot(dat[:,0], yy, 'o', label='Original data', markersize=5)
plt.plot(x0, beta_0+beta_1*x0, 'r', label='Fitted line')
plt.fill_between(x0, low_pred, upp_pred, facecolor='green', alpha=0.5, label='Prediction interval')
plt.fill_between(x0, low_conf, upp_conf, facecolor='yellow', alpha=0.5, label='Confidence interval')
plt.legend(loc='upper left')


import numpy as np

def sigmoid_derivative(x):
    sig = sigmoid(x)
    return sig * (1 - sig)

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


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

# Data preprocessing
data = pd.read_csv("data.csv")

# Converting Pandas dataframe to numpy array
X = data.x.values.reshape(-1, 1)
Y = data.y.values.reshape(-1, 1)

# Add bias
m = X.shape[0]  # sample count
bias = np.ones((m, 1))
X_train = np.append(bias, X, axis=1)

# Add x^2 values
x2 = X**2
X_train = np.append(X_train, x2, axis=1)
Y_train = np.array(Y)

# Initial Variables
theta = np.array([[0, 0, 0]]).reshape(-1, 1)
alpha = 0.0001
iterations = 100000

# Cost function
def cost_function(X, Y, B):
    m = Y.shape[0]
    J = np.sum((X.dot(B) - Y) ** 2)/(2 * m)
    return J

print("Initial cost", cost_function(X_train, Y_train, theta))

# Gradient Descent Algorithm
def gradient_descent(X, Y, theta, alpha, iterations):
    cost_history = [0] * iterations
    m = len(Y)

    for iteration in range(iterations):
        # Hypothesis Values
        h = X.dot(theta)
        # Difference b/w Hypothesis and Actual Y
        loss = h - Y
        # Gradient Calculation
        gradient = X.T.dot(loss) / m
        # Changing Values of B using Gradient
        theta = theta - alpha * gradient
        # New Cost Value
        cost = cost_function(X, Y, theta)
        cost_history[iteration] = cost

    return theta, cost_history

# 100000 Iterations
newTheta, cost_history = gradient_descent(
    X_train, Y_train, theta, alpha, iterations)

print("New theta", newTheta)
print("Final Cost", cost_history[-1])

# To see wheather Gradient Descent decrease cost in each iteration
plt.plot(range(iterations), cost_history)
plt.title("Gradient Descent")
plt.xlabel('Iteration')
plt.ylabel('Cost')
plt.show()

# Predicted Values
Y_pred = X_train.dot(newTheta)

# Model Evaluation
def rmse(Y, Y_pred):
    rmse = np.sqrt(sum((Y - Y_pred) ** 2) / Y.shape[0])
    return rmse

def r2_score(Y, Y_pred):
    mean_y = np.mean(Y)
    ss_tot = sum((Y - mean_y) ** 2)
    ss_res = sum((Y - Y_pred) ** 2)
    r2 = 1 - (ss_res / ss_tot)
    return r2

# Print Scores
print("RMSE = ", rmse(Y_train, Y_pred))
print("R2 Score = ", r2_score(Y_train, Y_pred))

# Visualization
# Ploting Regression Line
plt.plot(X, Y_pred, color='#c93e4e', label='Regression Line')
# Ploting Scatter Points
plt.scatter(X, Y, c='#54a774', label='Scatter Plot')
plt.xlabel('Size')
plt.ylabel('Price')
plt.legend()
plt.show()


import numpy as np

'''
    This python code calculates the Min-Max Normalization

    Min-max normalization is one of the most common ways to normalize data.
    For every feature, the minimum value of that feature gets transformed into a 0,
    the maximum value gets transformed into a 1, and every other value
    gets transformed into a decimal between 0 and 1.

    norm = [(x - X.min)/(X.max - X.min)]*(new_max - new_min) + new_min

'''

# Input the data array
data = [200, 400, 800, 1000, 2000]

# Setting the new min and new max
nmin = 0
nmax = 10

# Putting the data in new numpy array
nparray = np.array(data)

#------------- Normalizing the data --------------------------#
# Difference between max nparray value and min nparray value
diff = nparray.max() - nparray.min()
npmin = nparray.min()

ndata = ( (nparray - npmin) / (diff) ) * (nmax-nmin) + nmin

print(ndata)


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

mat_data = sio.loadmat('D:\hello\ex7faces.mat')
X = mat_data['X']

def feature_normalize(X):

    mean = np.mean(X, axis=0)
    standard_dev = np.std(X, axis=0, ddof=1)
    X_norm = (X - mean) / standard_dev
    return(X_norm)

def pca(X):

    m, n = X.shape
    sigma = X.T.dot(X) / m
    U, S, V = np.linalg.svd(sigma)
    return(U, S, V)

a = feature_normalize(X)
u,s,v = pca(X)

Z = X.dot(u[:,0:308])

print('initial pixel size = ',X.shape)
print('compressed size = ',Z.shape)

#take value 308
for i in range(len(s)):
    a = sum(s[:i])/(sum(s) *1.0)
    print i+1," = ",a

Machine Learning/7.dimension reduction(PCA)/2.compress pixel size.py


#
#   As with the perceptron exercise, you will modify the
#   last functions of this sigmoid unit class
#
#   There are two functions for you to finish:
#   First, in activate(), write the sigmoid activation function
#
#   Second, in train(), write the gradient descent update rule
#
#   NOTE: the following exercises creating classes for functioning
#   neural networks are HARD, and are not efficient implementations.
#   Consider them an extra challenge, not a requirement!

import numpy as np

class Sigmoid:

    def activate(self,values):
        '''Takes in @param values, @param weights lists of numbers
        and @param threshold a single number.
        @return the output of a threshold perceptron with
        given weights and threshold, given values as inputs.
        '''

        #First calculate the strength with which the perceptron fires
        strength = self.strength(values)

        #modify strength using the sigmoid activation function
        result = 1/(1.0 + np.exp(-strength))

        return result

    def strength(self,values):
        strength = np.dot(values,self.weights)
        return strength

    def update(self,values,train,eta=.1):
        '''
        Updates the sigmoid unit with expected return
        values @param train and learning rate @param eta

        By modifying the weights according to the gradient descent rule
        '''

        #modify the perceptron training rule to a gradient descent
        #training rule you will need to use the derivative of the
        #logistic function evaluated at the last input value.
        #Recall: d/dx logistic(x) = logistic(x)*(1-logistic(x))
        sigmoid = self.activate(values)
        result = sigmoid*(1.0-sigmoid)

        for i in range(0,len(values)):
            self.weights[i] += eta*(train[0] - sigmoid)*result*values[i]

    def __init__(self,weights=None):
        if weights:
            self.weights = weights

unit = Sigmoid(weights=[3,-2,1])
unit.update([1,2,3],[0])
print unit.weights
#Expected: [2.99075, -2.0185, .97225]


import numpy as np
import time

def F(n):
    return np.fromfunction(lambda i, j: np.exp(-2.j*np.pi*i*j/n), (n, n))

def dft(x):
    n = len(x)
    return F(n) @ x

def idft(y):
    n = len(y)
    return np.conj(F(n) @ np.conj(y)) / n

def fft(x):
    n = len(x)
    if n == 1:
        return x
    else:
        even = fft(x[0::2])
        odd = fft(x[1::2])
        T = [np.exp(-2.j*np.pi*k/n)*odd[k] for k in range(n//2)]
        return [even[k] + T[k] for k in range(n//2)] + \
               [even[k] - T[k] for k in range(n//2)]

x = np.random.rand(4)

start_time = time.time()
y = dft(x)
end_time = time.time()
print("DFT time: " + str(end_time-start_time) + "ns")
#print(y)

print()

start_time = time.time()
y = fft(x)
end_time = time.time()
print("FFT time: " + str(end_time-start_time) + "ns")
#print(y)

print()

start_time = time.time()
y = np.fft.fft(x)
end_time = time.time()
print("Library FFT time: " + str(end_time-start_time) + "ns")
#print(y)

print("\n")

#print(x)
#print(idft(y))
#print(np.fft.ifft(np.fft.fft(x)))


import numpy as np

def min_max_scale(x):
    cols = x.shape[1]
    min_record = []
    max_record = []

    for col in range(cols):
        min_val= np.min(x[:,col])
        max_val = np.max(x[:,col])
        x[:,col] = (x[:,col] - min_val)/(max_val - min_val)
        min_record.append(min_val)
        max_record.append(max_val)

    return x, min_record,max_record

def zero_score_scale(x):
    cols = x.shape[1]
    for col in range(cols):
        x[:,col] = (x[:,col]-np.mean(x[:,col]))/(np.std(x[:,col]))

    return x

def min_max_recover(X, min_vec, max_vec):
    cols = X.shape[1]
    for col in range(cols):
        X[:,col] = X[:,col]*(max_vec[col]-min_vec[col])+min_vec[col]
    return X

NORMALIZERS = {'min_max':min_max_scale,
                'zero_score':zero_score_scale}

RECOVER = {'min_max':min_max_recover}


import numpy as np
import pandas as pd
import sklearn as skl
from sklearn.decomposition import PCA
from common_plus.outliers import get_outlier_sels, get_outlier_sels_within_classes
from common.visualize.colors import COLORS
from pylab import *

def pca_explained(X):
    '''Shows how much variance is explained by each number of principal components.
    Features are automatically standardized to zero mean and unit variance. Constant features are removed.

    X: matrix [n_objects x n_features]'''

    const_features_sels = (X.std(0)==0)
    X=X[:,~const_features_sels]  # remove constant features

    X = (X-X.mean(0))/X.std(0)  # data standardization

    D=X.shape[1]
    pca = PCA()
    X_pca = pca.fit_transform(X)
    cum_explained_variance = cumsum(pca.explained_variance_ratio_)

    figure()
    plot(range(1,D+1), cum_explained_variance)
    xticks( range(1,D+1) )
    xlabel('# components')
    ylabel('explained variance fraction')
    for threshold in [0.9, 0.95, 0.99]:
        ind = find(cum_explained_variance>threshold)[0]
        print('%.2f of variance is explained by %d components'% (threshold,ind+1))
    show()

def plot_corr(df,size=10,show_colorbar=True,show_grid=True):
    '''Function plots a graphical correlation matrix for each pair of columns in the dataframe.
    Input:
        df: pandas DataFrame
        size: vertical and horizontal size of the plot

    Author: Victor Kitov (v.v.kitov@yandex.ru), 03.2016.'''

    cdict = {'red':   ((0.0, 0.0, 0.0),
                       (0.5, 0.0, 0.1),
                       (1.0, 1.0, 1.0)),

             'green': ((0.0, 0.0, 0.0),
                       (1.0, 0.0, 0.0)),

             'blue':  ((0.0, 0.0, 1.0),
                       (0.5, 0.1, 0.0),
                       (1.0, 0.0, 0.0))
            }

    from matplotlib.colors import LinearSegmentedColormap
    blue_red_cmap = LinearSegmentedColormap('hot', cdict)

    corr = df.corr()
    fig, ax = plt.subplots(figsize=(size, size))
    plt.set_cmap(blue_red_cmap)
    m = ax.matshow(corr,interpolation='none', vmin=-1,vmax=1) #
    plt.xticks(range(len(corr.columns)), corr.columns, rotation=90);
    plt.yticks(range(len(corr.columns)), corr.columns);
    if show_colorbar is True:
        plt.colorbar(m)
    if show_grid is True:
        plt.grid(color=[0.5,0.5,0.5], linestyle=':', linewidth=1)


# Importing the libraries
import numpy as np
import pandas as pd

"""
Generate a m x n data matrix X, initially polulated with zeros.
"""

rowCount = 10 # m
colCount = 40  # n

X = np.zeros((rowCount, colCount), dtype = int)
#X = np.zeros((rowCount, colCount), dtype = float)

print (X)

"""

Populate the First column with indentpendly identically distributed (i.i.d.)
random variables N(125, 16) (simulating height),
and the second column with i.i.d. randomN(125 variables , 64) (simulating weight).

"""
height = X[:, 0]  # Assign the First Column as height
weight = X[:, 1]  # Assign the Second Column as weight

print (height)
print (weight)

whRatioList = [0.0] * (rowCount) # Generating a list of size rowCount
whRatioArray = np.asarray(whRatioList) # Converting the list into array
print (whRatioArray.size)

for i in range(whRatioArray.size):
    height[i] = np.random.normal(loc=125, scale= 4, size=1)
    weight[i] = np.random.normal(loc=125, scale= 8, size=1)
    whRatioArray[i] = weight[i]/height[i]

"""

Populate the First row with indentpendly identically distributed (i.i.d.)
random variables N(125, 16) (simulating height),
and the second row with i.i.d. randomN(125 variables , 64) (simulating weight).

"""

dataRow1 = X[0]  # Assign the First Row as dataRow1
dataRow2 = X[1]  # Assign the Second Row as dataRow2
print (dataRow1)
print (dataRow2)

for i in range(whRatioArray.size):
    print("Weight[%d] = %d " % (i, weight[i]))
    print("Height[%d] = %d " % (i, height[i]))
#    print("Weight[%d] / Height[%d] = %d / %d = %.2f" % (i, i, weight[i], height[i], (weight[i]/height[i])))
    print("Weight[%d] / Height[%d] = %d / %d = %f" % (i, i, weight[i], height[i], whRatioArray[i]))

# Importing the Titanic .csv data file
titanicDS = pd.read_csv('Dummy_Titanic_Data.csv')
print (titanicDS)

###########  Using iloc() Method

sl_no = titanicDS.iloc[:, 0].values
print (sl_no)

col12 = titanicDS.iloc[:, [1, 2]].values
print (col12)

col123 = titanicDS.iloc[:, [1, 2, 3]].values
print (col123)

col12347 = titanicDS.iloc[:, [1, 2, 3, 4, 7]].values
print (col12347)

col1_7 = titanicDS.iloc[:, 1:7].values
print (col1_7)

passerger1 = titanicDS.iloc[0]
print (passerger1)

passerger2 = titanicDS.iloc[1]
print (passerger2)

passerger3 = titanicDS.iloc[2]
print (passerger3)

passerger4 = titanicDS.iloc[3]
print (passerger4)

passergerTop10 = titanicDS.head(10)
print (passergerTop10)

#   - -  - - - - - - -

passerger2436 = titanicDS.iloc[2435]
print (passerger2436)

#passerger2436 = titanicDS.iloc[2436]  # Invalid - Out of bounds
#print (passerger2436)

passergerTop10 = titanicDS.head(10)
print (passergerTop10)

passerger12 = titanicDS.iloc[[0,1]]
print (passerger12)

passerger12_100 = titanicDS.iloc[[0,1,99]]
print (passerger12_100)

passerger12x127 = titanicDS.iloc[[0,1], [0,1,7]]
print (passerger12x127)

passerger12x1247 = titanicDS.iloc[[0,1], [0,1,4,7]]
print (passerger12x1247)

###########  Using loc() Method

passerger12x1247 = titanicDS.loc[[0,1], ['Gender', 'Age']]
print (passerger12x1247)

passergerAllGenderAge = titanicDS.loc[:, ['Gender', 'Age']]
print (passergerAllGenderAge)

passergerAllGenderAge = titanicDS.loc[:, 'Gender':'Ticket_Fare']
print (passergerAllGenderAge)

passergerAllGenderAge = titanicDS.loc[titanicDS.Gender == 1, 'Age':'Ticket_Fare']
print (passergerAllGenderAge)

passergerAllGenderAge = titanicDS.loc[titanicDS.Age >= 40, 'Age':'Ticket_Fare']
print (passergerAllGenderAge)

###########  Using ix()
passergerAllGenderAge = titanicDS.ix[0:9, 'Gender':'Ticket_Fare']
print (passergerAllGenderAge)

#  Next Time: IA, I will discuss more on Matrix and Vector assignments, if needed

Matrix and Vector Operations/More On Matrix_and_Vector_Assignments_WithRandomlyGenerated_and_Excel File_Data.py


import numpy as np

def edge2mat(link, num_node):
    A = np.zeros((num_node, num_node))
    for i, j in link:
        A[j, i] = 1
    return A

def normalize_digraph(A):
    Dl = np.sum(A, 0)
    h, w = A.shape
    Dn = np.zeros((w, w))
    for i in range(w):
        if Dl[i] > 0:
            Dn[i, i] = Dl[i] ** (-1)
    AD = np.dot(A, Dn)
    return AD

def get_spatial_graph(num_node, self_link, inward, outward):
    I = edge2mat(self_link, num_node)
    In = normalize_digraph(edge2mat(inward, num_node))
    Out = normalize_digraph(edge2mat(outward, num_node))
    A = np.stack((I, In, Out))
    return A

def k_adjacency(A, k, with_self=False, self_factor=1):
    assert isinstance(A, np.ndarray)
    I = np.eye(len(A), dtype=A.dtype)
    if k == 0:
        return I
    Ak = np.minimum(np.linalg.matrix_power(A + I, k), 1) \
       - np.minimum(np.linalg.matrix_power(A + I, k - 1), 1)
    if with_self:
        Ak += (self_factor * I)
    return Ak

def normalize_adjacency_matrix(A):
    node_degrees = A.sum(-1)
    degs_inv_sqrt = np.power(node_degrees, -0.5)
    norm_degs_matrix = np.eye(len(node_degrees)) * degs_inv_sqrt
    return (norm_degs_matrix @ A @ norm_degs_matrix).astype(np.float32)

def get_adjacency_matrix(edges, num_nodes):
    A = np.zeros((num_nodes, num_nodes), dtype=np.float32)
    for edge in edges:
        A[edge] = 1.
    return A


'''
sum
min
idxmin
max
idxmax
cumsum
describe
'''
import numpy as np
import pandas as pd
from pandas import Series, DataFrame

arr = np.array([[1,2,np.nan],[np.nan,3,4]])
dframe1 = DataFrame(arr, index=['A','B'], columns=['One','Two','Three'])
print(dframe1)
'''
   One  Two  Three
A  1.0  2.0    NaN
B  NaN  3.0    4.0
'''

# sum
print(dframe1.sum())
'''
One      1.0
Two      5.0
Three    4.0
dtype: float64
'''

print(dframe1.sum(axis=1))
'''
A    3.0
B    7.0
dtype: float64
'''

# min
print(dframe1.min())
'''
One      1.0
Two      2.0
Three    4.0
dtype: float64
'''

# index of min value
print(dframe1.idxmin())
'''
One      A
Two      A
Three    B
dtype: object
'''

# acumulation
print(dframe1.cumsum())
'''
   One  Two  Three
A  1.0  2.0    NaN
B  NaN  5.0    4.0
'''

# describe
print(dframe1)
'''
   One  Two  Three
A  1.0  2.0    NaN
B  NaN  3.0    4.0
'''
print(dframe1.describe())
'''
       One       Two  Three
count  1.0  2.000000    1.0
mean   1.0  2.500000    4.0
std    NaN  0.707107    NaN
min    1.0  2.000000    4.0
25%    1.0  2.250000    4.0
50%    1.0  2.500000    4.0
75%    1.0  2.750000    4.0
max    1.0  3.000000    4.0
'''

# check for unique values
ser1 = Series(['w','y','a','w','y','z','b','q','w','g','h'])

print(ser1)
'''
0     w
1     y
2     a
3     w
4     y
5     z
6     b
7     q
8     w
9     g
10    h
dtype: object
'''

print(ser1.unique())
'''
dtype: object
['w' 'y' 'a' 'z' 'b' 'q' 'g' 'h']
'''

# count values
print(ser1.value_counts())
'''
w    3
y    2
q    1
g    1
z    1
h    1
b    1
a    1
dtype: int64
'''


import numpy as np

"""
  Compute Pascal triangle up to size n
  Returns: Numpy matrix with binomial coefficients
  - Matrix represents linear map P(X) \mapsto P(X+1) in the canonical basis
  - Convention is that first columns are the image of monomials of higher degree
"""
def pascal(n):
    # Initialize diagonal and first row
    mat       = np.identity(n, dtype=int)
    mat[:, 0] = 1
    # Loop using the standard binomial recurrence
    for i in range(2,n):
        mat[i, 1:-1] = mat[i-1, 0:-2] + mat[i-1, 1:-1]
    # Satisfy indexing conventions
    mat = np.flip(mat, axis=0)
    mat = mat.transpose()
    mat = np.flip(mat, axis=0)
    return mat

"""
 If | P  (X) = \sum c_i X^i = \sum d_i (X-a)^i
    | P_a(X) = \sum d_i X^i = P(X+a)
Then:
    taylor_expand computes P_a = Taylor expansion of P at a
    which is nothing by the linear map
    P(X) \mapsto P_a(X) = P(X+a)
    X^n \mapsto \sum (n,k) a^k X^{n-k}
 """
def taylor_expand(p, a, pascal_triangle=None):
    #
    degree = len(p)-1
    if pascal_triangle is None:
        pascal_triangle = pascal(degree+1)
    exponents = np.array( range(0, degree+1, 1) )
    powers    = a**exponents
    diag      = np.diag( powers )
    diag_inv  = np.diag( 1/powers )
    weighted_pascal = diag.dot( pascal_triangle )
    weighted_pascal = weighted_pascal.dot( diag_inv )
    return weighted_pascal.dot(p)


import numpy as np

def sigmoid(z):
    """
        Applies logistic function to value.

        Parameter
        ---------
        z : int, array_like
            Single integer or array of values.

        Returns
        -------
        : int, array_like
            Single integer or array of values with logistic function applied.
    """

    return 1 / (1 + np.exp(-z))


"""
2.3 numpy 基础运算
"""

import numpy as np

a = np.array([10,20,30,40])
b = np.arange(4)

print('矩阵a\n',a,'\n矩阵b\n',b)

# 减法
c = a - b
print('矩阵相减:a-b\n',c)

# 加法
c = a + b
print('矩阵相加:a+b\n',c)

# 乘方
c = b ** 2
print('对矩阵b每个元素求平方\n',c)

# sin
c = 10 * np.sin(a)
print('对矩阵a的每个元素求sin并乘以10\n',c)

# cos
c = 10 * np.cos(a)
print('对矩阵a的每个元素求cos并乘以10\n',c)

# 输出小于3的列表
print('矩阵b\n',b)
print('矩阵b中元素小于3的情况\n',b<3)
print('矩阵b中元素等于3的情况\n',b==3) # 等于3的情况

"""
矩阵运算
"""
a = np.array([[1,1],[0,1]])
b = np.arange(4).reshape((2,2))

print('矩阵a\n',a)
print('矩阵b\n',b)

# 元素逐个相乘
c = a*b
print('矩阵元素对应位置逐个相乘\n',c)

# 矩阵相乘
c = np.dot(a,b)
print('矩阵相乘\n',c)

c = a.dot(b)
print('矩阵相乘\n',c)

"""
生成随机矩阵
"""
a = np.random.random((2,4))
print('随机矩阵',a)

# 输出随机数组的和
print('随机矩阵的和',np.sum(a))
# 输出随机数组的最小值
print('随机矩阵的最小值',np.min(a))
# 输出随机数组的最大值
print('随机矩阵的最大值',np.max(a))

print('对随机矩阵的每列求和',np.sum(a,axis=1))
print('对随机矩阵的每行求最小值',np.min(a,axis=0))
print('对随机矩阵的每行求最大值',np.max(a,axis=1))


import numpy as np
from numpy.linalg import svd

def nullspace(A, atol=1e-13, rtol=0):
    A = np.atleast_2d(A)
    u, s, vh = svd(A)
    tol = max(atol, rtol * s[0])
    nnz = (s >= tol).sum()
    ns = vh[nnz:].conj().T
    return ns

def mkdata(N, noisy=None):
    '''
    MKDATA Generate data set.
    INPUT:  N:     number of samples.
            noisy: if or not add noise to y.

    OUTPUT: X: sample features, P-by-N matrix.
            y: sample labels, 1-by-N row vector.
            w: target function parameters, (P+1)-by-1 column vector.
    '''
    data_range = np.array([-1, 1])
    dim = 2

    X = np.random.random((dim, N)) * (data_range[1] - data_range[0]) + data_range[0]
    while True:
        Xsample = np.vstack((np.ones((1, dim)), np.random.random((dim, dim)) * (data_range[1]-data_range[0]) + data_range[0]))
        w = nullspace(Xsample.T)
        a =  np.vstack((np.ones((1, N)), X))
        y = np.sign(np.matmul(w.T, np.vstack((np.ones((1, N)), X))))
        if np.all(y) and np.unique(y).shape[0] > 1:
            break
    if noisy:
        idx = np.random.choice(N, N//10)
        y[0, idx] = -y[0, idx]

    return X, y, w


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

#Variables iniciales
epsilon = 0.001
r_inicial = 3.1
x0_inicial = 0.2
delta_x0 = 0.05
delta_r = 0.001
M = 1000
N = 20

#Resta con valor absoluto dos listas
def resta(x,y):
    lista_resta = list(map(operator.sub, x, y))
    return list(map(abs, lista_resta))

#Función logistica que define el sistema
def logistica(x, r):
    return r*x*(1-x)

#Calcula n términos de la sucesión de la órbita
#de una función f por un punto x0
def orbita(x0, f, n, r):
    orbita=[]
    x = x0
    for i in range(n):
        x = f(x, r)
        orbita.append(x)
    return orbita

#Calcula el conunto límite de puntos atractores dado un x0
def calculaV0(x0, r):
    orb = orbita(x0, logistica, M, r)
    posiblesk = [i for i in range(M-N, M)]
    #Guardamos en V0 los valores k de los limites
    V0 = []
    #Guardamos el valor de la orbita del limite
    V0orb = []
    #En equivalentesk guardamos los valores de las que ya
    #tenemos un representante de ese limite
    equivalentesk = []
    #Recorremos los candidatos
    for k in reversed(posiblesk) :
        #Si no es equivalente a uno de los valores limite encontrados
        if k not in equivalentesk :
            #Suponemos que no será limite
            kbueno = False
            for i in range(k) :
                #Recorremos los puntos que quedan
                if i not in equivalentesk and abs(orb[k] - orb[k-i-1]) < epsilon:
                    #Hay algún punto cercano a él, luego k es limite
                    kbueno = True
                    #Ademas, el k-i-1 es equivalente a k pues
                    #los valores de la orbita son muy cercanos
                    equivalentesk.append(k-i-1)
            if kbueno :
                #Como es valor limite, lo añadimos a las listas
                V0.append(k)
                V0orb.append(orb[k])
            equivalentesk.append(k)
    return V0, V0orb

#Calcula el error cometido al aproximar los valores limites con V0
def calculaError(V0orb, r) :
    errores = []
    V0orb.sort()
    Vaux = V0orb.copy()
    for j in range(0, 10):
        for i in range(len(V0)):
            Vaux[i] = logistica(Vaux[i], r)
        Vaux.sort()
        #Tomamos el máximo de las diferencias entre los elementos de V0orb
        #y de f^j(V0orb)
        errores.append(max(resta(V0orb, Vaux)))
    errores.sort()
    #Tomamos el percentil noventa de los diez errores anteriores
    return errores[8]

#Comprueba que el sistema sea estable para el x0 dado por parámetro
def estabilidad(x0, r):
    #Variamos ligeramente x0
    for x0 in np.arange(x0, x0 + delta_x0, delta_x0/10):
        V0aux, V0auxorb = calculaV0(x0, r)
        V0auxorb.sort()
        #Comprobamos que los valores del conjunto limite esten cercanos
        if max(resta(V0orb,V0auxorb)) > epsilon:
            return False
    return True

#Calcula el r a partir del cual hay conjuntos limite de al menos nelems
#y dibuja la grafica de bifurcaciones para r entre 2.5 y 4
def bifurcaciones(nelems, x0):
    V0s = np.array([])
    enc = False
    #Variamos r entre 2.5 y 4
    for r in np.arange(2.5 + delta_r, 4, delta_r):
        V0aux, V0auxorb = calculaV0(x0, r)
        V0auxorb.sort()
        V0auxorb = np.array(V0auxorb)
        np.append(V0s, V0auxorb)

        #dibujamos la grafica de las bifurcaciones del sistema
        for y in V0auxorb:
            plt.plot(r, y, ',k', alpha=0.25)

        #Vemos si es el primer r en alcanzar los nelems
        if len(V0aux) == nelems and enc == False:
            enc = True
            print('En r = ' + str(r) + ' V0 tiene ' + str(nelems) + ' elementos')

#MAIN
print('Fijamos x0 = 0.2')
V0, V0orb = calculaV0(x0_inicial, r_inicial)
print('Un conjunto atractor con r = 3.1 es: ' + str(V0orb))
print('su error es:', calculaError(V0orb, r_inicial))

if estabilidad(x0_inicial, r_inicial) == True:
    print('Es estable')
else :
    print('No es estable')

V0, V0orb = calculaV0(x0_inicial, 3.4)
print('Otro conjunto atractor con r = 3.4 es: ' + str(V0orb))
print('su error es:', calculaError(V0orb, 3.4))

if estabilidad(x0_inicial, 3.4) == True:
    print('Es estable')
else :
    print('No es estable')

bifurcaciones(8, x0_inicial)
plt.show()


# -*- coding: utf-8 -*-#
'''
# Name:         TanhAsBinaryClassifier
# Description:
# Author:       super
# Date:         2020/5/22
'''

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

from HelperClass.ClassifierFunction_1_0 import *

# modified cross entropy function for tanh
def target_function2(a,y):
    p1 = (1+y) * np.log((1+a)/2)    # change from y to 1+y, from a to 1+a
    p2 = (1-y) * np.log((1-a)/2)
    y = -p1 - p2
    return y

# modified cross entropy for tanh
def draw_cross_entropy():
    eps = 1e-2
    a = np.linspace(-1+eps,1-eps)
    y = -1  # change from 0 to -1
    z1 = target_function2(a,y)
    y = 1
    z2 = target_function2(a,y)
    p1, = plt.plot(a,z1)
    p2, = plt.plot(a,z2)
    plt.grid()
    plt.legend([p1,p2],["y=-1","y=1"])
    plt.xlabel("a")
    plt.ylabel("Loss")
    plt.show()

def draw_tanh_seperator(fun, label, x, y):
    z = np.linspace(-5,5)
    a = fun.forward(z)
    plt.plot(z,a)
    plt.plot(x,y)
    plt.grid()
    plt.xlabel("input : z")
    plt.ylabel("output : a")
    plt.title(label)
    plt.show()

if __name__ == '__main__':
    draw_cross_entropy()
    draw_tanh_seperator(Tanh(), "Tanh Function", [-5,5], [0,0])
    draw_tanh_seperator(Logistic(), "Logistic Function", [-5,5],[0.5,0.5])


r"""求日期组成的八位数(形如 yyyymmdd)是否为素数？
问题来源：吴宗敏
日期：2021-10-1 国庆72周年
coded by: [刘翔](https://geogebra.com/m/kumath) © <kumath@outlook.com>
20210929，20211001，10012021,9292021 都是素数(吴宗敏)
"""

from sympy import primerange
from sys import argv
from datetime import datetime

def isleapyear(year):
    '''Python program to check if year is a leap year or not'''

    # To get year (integer input) from the user
    # year = int(input("Enter a year: "))

    return (year % 4) == 0 and (year % 100 !=0) or (year % 400) == 0

# 一条Python语句判断是否为闰年？
isleap = lambda year: (year % 4) == 0 and (year % 100 != 0) or (year % 400) == 0

def date_isprime(year1, year2):
    '''给定两个年份，得到 yyyymmdd 是素数的列表
    input: 起止年份 year1, year2
    output：素数列表(按照年份分类)
    '''

    bmonths = [31,28,31,30,31,30,31,31,30,31,30,31]  # 月份对应的常规天数，闰年除外

    res = []
    for year in range(year1, year2):
        r1 = []
        leap = isleap(year)   # isleapyear(year)
        bmonths[1] = 29 if leap else 28

        for month in range(1, 13):
            ymd = [str(year), str(month).zfill(2), '1'.zfill(2)]
            lower = ''.join(ymd)
            ymd = [str(year), str(month).zfill(2), str(bmonths[month-1]+1)]
            upper = ''.join(ymd)
            primes = primerange(int(lower) , int(upper))
            # r1.append()         ## append是在末尾追加的意思
            r1 += list(primes)    ## 合并merge两个列表lists

        res.append(r1)            ## 按照年份在末尾追加到列表

    return res

if __name__ == '__main__':
    if len(argv) > 1 and argv[1].lower() in ['--help', '-h', '-help']:
        print("""
        给定两个年份之间，日期是素数的列表。
        使用说明：python prime_date.py 起始年份 [终止年份, 缺省是当前年份]
        使用举例：python prime_date.py 2000 2011
                  python prime_date.py 2010
                  python prime_date.py %[显示当前年份的素数日期]
                  python prime_date.py --help
                  python prime_date.py -h
        """)
        exit()

    year = datetime.now().year
    sy = argv[1] if len(argv) > 1 else str(year)
    if isinstance(sy,(str)):
        starty = int(sy)
    else:
        raise ValueError

    ey = argv[2] if len(argv) > 2 else str(year+1)
    if isinstance(ey,(str)):
        endy = int(ey)
    else:
        raise ValueError

    print('起止年份 {0}年~{1}年，素数日期有\n'.format(starty, endy))
    for yp in date_isprime(starty, endy):
        print('{0}, 个数 {1}\n'.format(yp, len(yp)))


import sympy
from sympy import *
import random

def choose_modulus(k,l,m):
	p1 = find_prime(k,l)
	p2 = find_prime(k,l)
	while not (abs(log(p1,2) - log(p2,2)) < m):
		p1 = find_prime(k,l)
		p2 = find_prime(k,l)
		print(p1, p2)
	print(log(p1,2)+m < log(p2,2))
	print("prime 1: ", p1)
	print("prime 2: ", p2)
	return p1,p2

def choose_encryption_key_old(m):
	e = random.randrange(2,m)
	while not gcd(e, totient(m)) == 1:
		e = random.randrange(2,m)
	return e

def choose_encryption_key(p1,p2):
	m = p1*p2
	e = random.randrange(2, p1*p2)
	while not gcd(e, (p1-1)*(p2-1)) == 1:
		e = random.randrange(2, p1*p2)
	return e

def compute_decryption_key(e, p1, p2):
	# d = e inverse mod phi(m) m = p1*p2
	#phi(m) = (p1-1)*(p2-1)
	d = inv_mod(e, (p1-1)*(p2-1))
	return d

def RSA_encrypt(P, e, m):
	return power_mod(P,e,m)

def RSA_decrypt(C, d, m):
	return power_mod(C,d,m)

def RSA_crack(C, e, m):
	return power_mod(C, inv_mod(e,totient(m)), m)

def power_mod(a, b, m):
	#replace with better version for large numbers
	#return ((a%m)**(b%m))%m
	return pow(a,b,m)

def string_to_int(s):
	return int.from_bytes(s.encode(),'big')

def int_to_string(n):
	return n.to_bytes((n.bit_length()+7)//8,'big').decode()

def find_prime(k, l):
	x = random.randrange(2**k+2, 2**l-1)
	while (not isprime(x)):
		x = random.randrange(2**k+2, 2**l-1)
	return x

def mod_inv_old(a,m):
	#replace with euclid's algorithm - will be using large numbers
	for i in range(0,m):
		if (i*a)%m == 1:
			return i
	return -1

def xgcd(b, n):
    """ Return g, x0, y0
        such that x0*b + y0*n = g
        and g is the gcd of (b,n)"""
    x0, x1, y0, y1 = 1, 0, 0, 1
    while n != 0:
        q, b, n = b // n, n, b % n
        x0, x1 = x1, x0 - q * x1
        y0, y1 = y1, y0 - q * y1
    return b, x0, y0

def inv_mod(b, n):
    """ Return the modular inverse of b mod n
     or None if gcd(b,n) > 1 """
    g, x, _ = xgcd(b, n)
    if g == 1:
        return x % n

def unit_test1(kv, lv, dv, textv):
	(p1, p2) = choose_modulus(kv, lv, dv)
	m = p1 * p2
	e = choose_encryption_key(p1, p2)
	d = compute_decryption_key(e, p1, p2)
	plaintext = textv
	P = string_to_int(plaintext)
	print("Plaintext in bits = ", P)
	C = RSA_encrypt(P, e, m)
	print("Plaintext: ", plaintext)
	print("Text Len: ", 8*len(plaintext), "bits")
	print("Modulus len: ",  int(log(m)/log(2)), "bits")
	print("Ciphertext in bit format = ", C)
	D = RSA_decrypt(C, d, m)
	print("D (Decrypted text in bit format) = ", D)
	decoded_text = int_to_string(D)
	print("Decoded Text: ", decoded_text, "\n\n--------------\n")

def unit_test2(kv, lv, dv, textv):
	(p1, p2) = choose_modulus(kv, lv, dv)
	m = p1 * p2
	e = choose_encryption_key(p1, p2)
	d = compute_decryption_key(e, p1, p2)
	plaintext = textv
	P = string_to_int(plaintext)
	print("Plaintext in bits = ", P)
	C = RSA_encrypt(P, e, m)
	print("Plaintext: ", plaintext)
	print("Text Len: ", 8*len(plaintext), "bits")
	print("Modulus len: ",  int(log(m)/log(2)), "bits")
	print("C (Ciphertext in bit format) = ", C)
	D = RSA_crack(C, e, m)
	print("D (decrypted text in bit format) = ", D)
	decoded_text = int_to_string(D)
	print("Decoded Text: ", decoded_text, "\n\n--------------\n")

#unit_test1(10, 12, 1, "Hi")
#unit_test1(200, 201, 50, "YouUsedTheWrongFormulaButGotTheRightAnswer")
#unit_test1(200,201,50,"I've got the best RSA. Tremendous!")
#unit_test2(10, 12, 5, "Hi")

#################
"""
PART 1: OUR SCHEMES
"""
#find a modulus
#the e we submit to blackboard: 9034302786477632084177231467338707794932890382219531012244768011578912282025102742921209071808720002426284716566453084939
#the m we put on the thread: 30189064434495182222794692701630732429757499485911917941672183961436119037704394785112588879375758643631173789514757495643

p1,p2 = choose_modulus(198,202,1) #this has p1 and p2
modulus = p1*p2
print("Prime 1: ", p1)
print("Prime 2: ", p2)
#find an encryption key
encryptKey = choose_encryption_key(p1,p2)
print("Modulus: ", modulus)
print("Encryption Key: ", encryptKey) #post key and modulus value to new blackboard thread

print()
print("-------------------------------")
print()
##############
"""
PART 2: SENDING SOMEONE ELSE A MESSAGE WITH THEIR SCHEME
"""
theirEKey = encryptKey # this is where we add their e!!!!!!!!
theirMod = modulus #add their m !!!!!!
ourMessage = "YouUsedTheWrongFormulaButGotTheRightAnswer" #42 chars
byteMessage = string_to_int(ourMessage) #42 bytes long
encryptedText = RSA_encrypt(byteMessage, theirEKey, theirMod)
print("The Encrypted Text: ", encryptedText) #post this on that person's blackboard thread so they can crack it
print()
print("-------------------------------")
print()
#########
"""
PART 3: DECODING THE MESSAGE SENT TO US USING OUR SCHEME
"""
encryption = 9034302786477632084177231467338707794932890382219531012244768011578912282025102742921209071808720002426284716566453084939
mod = 30189064434495182222794692701630732429757499485911917941672183961436119037704394785112588879375758643631173789514757495643
p1 = 2852799332826165576549683721934686650431760177477582224441789
p2 = 10582260058434591375044316914661108554362583639774055485540087
byteReceived = 7685639402658570041332092386730857722829508721500337074039018855544141530770944219201236076815619964810541252211564571230 #encryptedText
#this is posted for us ^^
#stringReceived = int_to_string(byteReceived) #decrypt it
decryptKey = compute_decryption_key(encryption, p1, p2)
#print("1 ", decryptKey)
decryptedBytes = RSA_decrypt(byteReceived, decryptKey, mod)
#print("2 ", decryptedBytes)
decryptedString = int_to_string(decryptedBytes)
#print("3 ", decryptedString)
print("The Message received : ", decryptedString) #this was the message we got -> post to our blackboard thread
#the message we received: RSA is probably safer than couriers.

#### trying lizzie's scheme: post this on Lizzie's thread for them to decode (For Part 2)
e = 1274570651282105475941777766587577582023518221190732522597076146804533049158766343138826132941234187595481937482071481202376751312818066989598920155989
m = 9974085880263379580394176919091237671243630991492368310958180254243729015156794407476067877070352245916181312913506081413978120979798227144179681175879
message = "Hi. This is a creative message."
byteMess = string_to_int(message)
encryptedWords = RSA_encrypt(byteMess,e,m)
print("The message encrypted is: ", encryptedWords)


import numpy as np
from coptim.function import Function

class Rosenbrock(Function):

    def eval(self, x):
        assert len(x) == 2, '2 dimensional input only.'
        return 100 * (x[1] - x[0] ** 2) ** 2 + (1 - x[0]) ** 2

    def gradient(self, x):
        assert len(x) == 2, '2 dimensional input only.'
        return np.array([
            2 * (-200 * x[0] * x[1] + 200 * np.power(x[0], 3) - 1 + x[0]),
            200 * (x[1] - x[0] ** 2)
        ])

    def hessian(self, x):
        assert len(x) == 2, '2 dimensional input only.'
        df_dx1 = -400 * x[1] + 1200 * x[0] ** 2 + 2
        df_dx1dx2 = -400 * x[0]
        df_dx2dx1 = -400 * x[0]
        df_dx2 = 200

        return np.array([[df_dx1, df_dx1dx2], [df_dx2dx1, df_dx2]])


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

mat_data = sio.loadmat('D:\hello\ex7data1.mat')
X = mat_data['X']

def feature_normalize(X):

    mean = np.mean(X, axis=0)
    standard_dev = np.std(X, axis=0, ddof=1)
    X_norm = (X - mean) / standard_dev
    return(X_norm)

def pca(X):

    m, n = X.shape
    sigma = X.T.dot(X) / m
    U, S, V = np.linalg.svd(sigma)
    return(U, S, V)

a = feature_normalize(X)
u,s,v = pca(X)

Z = X.dot(u[:,0])
print("compressed data = ",Z)

#approx recover data
X_1 = Z*u[:1,0]
X_2 = Z*u[1:2,0]
X_recov = np.vstack((X_1,X_2)).T
print("approx recover data = ",X_recov)

plt.figure()
plt.xlabel("X1")
plt.ylabel("X2")
plt.scatter(X[:,0],X[:,1],color='b')
plt.scatter(X_recov[:,0],X_recov[:,1],color='r')
plt.legend(["inital data ","recover data "], loc='upper left', numpoints=2)
plt.show()

Machine Learning/7.dimension reduction(PCA)/1.2D to 1D dr.py


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

style.use('ggplot')

xs = np.array([1, 2, 3, 4, 5], dtype=np.float64)
ys = np.array([5, 4, 6, 5, 6], dtype=np.float64)

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

    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, color='#003F72')
plt.plot(xs, regression_line)
plt.show()

predict_x = 7
predict_y = (m * predict_x) + b
print(predict_y)

plt.scatter(xs, ys, color='#003F72', label='data')
plt.plot(xs, regression_line, label='regression line')
plt.scatter(predict_x, predict_y, color="#0ece18", label='prediction')
plt.legend(loc=4)
plt.show()


import numpy as np

def euclidean_distance(x1, x2):
    return np.sqrt(np.sum((x1 - x2) ** 2))

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

def accuracy(true, predicted):
    return np.sum(true == predicted) / len(true)

def mse(y_true, y_predicted):
    return np.mean((y_true - y_predicted)**2)


#Import stuff
import numpy as np
import matplotlib.pyplot as plt

#Import my own file, eigenstuffs.py, for eigenstuffs
import eigenstuffs as eg

n = 100  #Size of matrix
alpha=2. #Value of diagnol in matrix
iter_max = 1000 #Maximum number of iterations
j_ = 2 #j as defined in equations 1.1 and 1.2 in the homework
epsilon = 1e-8 #used to check for convergence

x = np.zeros(n)  #x is the solution vector
                 #it is initialized to my initial guess of all zeros

#Create and fill in the matrix T, defined in the problem statement
T = np.zeros( (n,n) )
for i in range(len(T)):
    for j in range(len(T[i])):
        if i == j:
            T[i][j] = alpha
        elif j == (i-1) or j == (i+1):
            T[i][j] = -1.

#calculate the eigenvalue appropriate for j_
evalue = eg.eigenvalue(j_,alpha,n)

#calculate the eigenvector appropriate for j_
evec = eg.eigenvec(j_,n)

#the vector b as defined in Ax = b
B = evalue*evec

#Create a list with which to store the error of each iteration
error = []

#Now let's iterate, Jacobi style
for k in range(iter_max):
    for i in range(len(x)): #for each element of the solution vector
        #The following if...elif...else statements are set up to exploit
        #the sparse nature of T. The summation used in the Jacobi algorithm
        #sums over a bunch of zeros so I cut those zeros out to speed up the code
        if i==0:  #If we're on the first row, only add T[i][i+1]
            summation = T[i][i+1] * x[i+1]
        elif i== (len(x)-1): #If we're on the last row, only add T[i][i-1]
            summation = T[i][i-1] * x[i-1]
        else:  #Only need to add two elements together
            summation = T[i][i+1] * x[i+1] + T[i][i-1] * x[i-1]
        x[i] = 1./T[i][i] * (B[i] - summation) #Update x based on Jacobi algorithm

    #update the error array
    error.append( np.max(np.absolute(np.subtract(evec,x))))

    #check for convergence
    numconverge = 0 #count the number of elements of x which have converged
    for i in range(len(x)):
        if abs(x[i] - evec[i]) < epsilon: #If converged within epsilon
                numconverge += 1

    if numconverge == len(x):  #If all the elements of x have converged
        print "Converged!  After %d loops" % (k+1)
        break
else: #If for loop completes with convergence not being acheived
    print "Convergence not achieved after %d number of iterations" % (k+1)

#Now plot the error as a function of iteration number
#I feel all these pyplot commands are sufficiently self-explanatory
#that I don't need to elaborate each one of them.
plt.plot(range(1,len(error)+1),error)
plt.yscale('log')
plt.xlabel('Iteration number')
plt.ylabel('Error')
s = "Error plot for j=" + str(j_)
plt.title(s)
s = "errorplot_" + str(j_) + ".pdf"
plt.savefig(s)


""" stats.py

Statistics tools used throughout the project. """
import sys

## Standard imports
import numpy as np

#### WLS
##############################################################################
def WeightedLeastSquares(X,Y,weights=None,verbose=False,standardize=True):

	""" Weighted LS, reduces to OLS when weights is None. This implementation computes
	the estimator and covariance matrix based on sample variance. For TSIR however, the

	NB: x is assumed to be an array with shape = (num_data points, num_features) """

	## Get the dimensions
	num_data_points = X.shape[0]
	try:
		num_features = X.shape[1]
	except:
		num_features = 1
		X = X.reshape((num_data_points,1))

	## Initialize weight matrix
	if weights is None:
		W = np.eye(num_data_points)
	else:
		W = np.diag(weights)

	## Standardize the inputs and outputs to help with
	## stability of the matrix inversion. This is needed because
	## cumulative cases and births both get very large.
	if standardize:
		muY = Y.mean()
		sigY = Y.std()
		muX = X.mean(axis=0)
		sigX = X.std(axis=0)
		X = (X-muX)/sigX
		Y = (Y-muY)/sigY

	## Compute the required matrix inversion
	## i.e. inv(x.T*w*x), which comes from minimizing
	## the residual sum of squares (RSS) and solving for
	## the optimum coefficients. See eq. 3.6 in EST
	xTwx_inv = np.linalg.inv(np.dot(X.T,np.dot(W,X)))

	## Now use that matrix to compute the optimum coefficients
	## and their uncertainty.
	beta_hat = np.dot(xTwx_inv,np.dot(X.T,np.dot(W,Y)))

	## Compute the estimated variance in the data points
	residual = Y - np.dot(X,beta_hat)
	RSS = (residual)**2
	var = RSS.sum(axis=0)/(num_data_points - num_features)

	## Then the uncertainty (covariance matrix) is simply a
	## reapplication of the inv(x.T*x):
	if weights is None:
		beta_var = var*xTwx_inv
	else:
		beta_var = xTwx_inv

	## Reshape the outputs
	beta_hat = beta_hat.reshape((num_features,))

	## Rescale back to old values
	if standardize:
		X = sigX*X + muX
		Y = sigY*Y + muY
		beta_hat = beta_hat*(sigY/sigX)
		sig = np.diag(sigY/sigX)
		beta_var = np.dot(sig,np.dot(beta_var,sig))
		residual = sigY*residual + muY - np.dot(muX,beta_hat)

	## Print summary if needed
	if verbose:
		for i in range(num_features):
			output = (i,beta_hat[i],2.*np.sqrt(beta_var[i,i]))
			print("Feature %i: coeff = %.4f +/- %.3f." % output)

	return beta_hat, beta_var, residual

def ConstantWLS(x,var):

	""" Avg and var are the avg and variance of samples. Weights are computed with the
	variance, and WLS is used to estimate a fit to a constant. """

	## Compute weights
	weights = 1./var/np.sum(1./var)

	## Create model based estimates with weighted LS on a
	## constant.
	weighted_mean = np.sum(x*weights)
	weighted_var = np.sum(weights*((x-weighted_mean)**2))

	return weighted_mean, weighted_var


import numpy as np
import matplotlib.pyplot as plt

import random

import argparse

trace = []

# Selection sort
def selection_sort(to_sort):
    n = len(to_sort)
    for i in range(0, n - 1):
        m = i
        for j in range(i + 1, n):
            if to_sort[j] < to_sort[m]:
                m = j
        to_sort[i], to_sort[m] = to_sort[m], to_sort[i]
        if not np.array_equal(np.array(to_sort), np.array(trace[-1])):
            trace.append(to_sort[:])
    return to_sort

# Insertion sort
def insertion_sort(to_sort, compare=lambda a, b: (a > b) - (a < b)):
    n = len(to_sort)
    for i in range(1, n):
        j = i
        while j > 0 and compare(to_sort[j-1], to_sort[j]) > 0:
            to_sort[j-1], to_sort[j] = to_sort[j], to_sort[j-1]
            j -= 1

        if not np.array_equal(np.array(to_sort), np.array(trace[-1])):
            trace.append(to_sort[:])
    return to_sort

# Merge sort
def merge(a, l, m, h, compare):

    c = []
    for k in range(l, h + 1):
        c.append(a[k])
    i = 0
    cm = m - l + 1
    ch = h - l + 1
    j = cm

    for k in range(l, h + 1):
        if i >= cm:
            a[k] = c[j]
            j += 1
        elif j >= ch:
            a[k] = c[i]
            i += 1
        elif compare(c[i], c[j]) <= 0:
            a[k] = c[i]
            i += 1
        else:
            a[k] = c[j]
            j += 1

    if not np.array_equal(np.array(a), np.array(trace[-1])):
        trace.append(a[:])

def merge_sort(a, l, h, compare=lambda a, b: (a > b) - (a < b)):
    if l < h:
        m = l + (h - l) // 2
        merge_sort(a, l, m, compare)
        merge_sort(a, m + 1, h, compare)
        merge(a, l, m, h, compare)

# Quicksort
def partition(a, l, h, pathological=True):

    if not pathological:
        p = random.randint(l, h)
    else:
        p = a.index(min(a[l:h+1]))
    a[p], a[h] = a[h], a[p]
    b = l
    for i in range(l, h):
        if a[i] < a[h]:
            a[i], a[b] = a[b], a[i]
            b += 1
    a[b], a[h] = a[h], a[b]

    if not np.array_equal(np.array(a), np.array(trace[-1])):
        trace.append(a[:])

    return b, p

def quicksort(a, l, h):

    if l < h:
        p, pp = partition(a, l, h, False)
        quicksort(a, l, p-1)
        quicksort(a, p+1, h)

def draw_lines(trace, filename):

    # https://stackoverflow.com/a/8251668
    plt.style.use('dark_background')
    plt.figure(figsize=(len(trace) / 2, 5))
    trace_arr = np.array(trace)
    yy = []
    yy.append(np.arange(0, trace_arr.shape[1]))
    y = xsorted = trace_arr[0]
    for x in trace_arr[1:]:
        xsorted = np.argsort(x)
        ypos = np.searchsorted(x[xsorted], y)
        indices = xsorted[ypos]
        yy.append(indices)
    yy = np.array(yy)
    yy = yy.T
    xx = np.arange(0, trace_arr.shape[0])
    for line in yy:
        plt.plot(xx, line, #marker='o',
                 color='white',
                 linewidth=0.5, markersize=0.75)
    for i, ts in enumerate(to_sort_org):
        plt.plot(-.5, i, marker='o', color='white', markersize=ts/2 + 1)
    for i in range(len(to_sort_org)):
        plt.plot(xx[-1]+.5, i, marker='o', color='white',
                 markersize=i/2)
    plt.axis('off')
    plt.gca().invert_yaxis()
    plt.savefig(filename)
    plt.show()

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--format', help='image format', default='pdf')
args = parser.parse_args()

to_sort = list(range(1, 20+1))
random.shuffle(to_sort)
to_sort_org = to_sort[:]

trace = []
trace.append(to_sort[:])
selection_sort(to_sort[:])
print(len(trace))
draw_lines(trace, f'selection_sort_lines.{args.format}')
trace = []
trace.append(to_sort[:])
insertion_sort(to_sort[:])
print(len(trace))
draw_lines(trace, f'insertion_sort_lines.{args.format}')
trace = []
trace.append(to_sort[:])
merge_sort(to_sort[:], 0, len(to_sort) - 1)
print(len(trace))
draw_lines(trace, f'mergesort_lines.{args.format}')
trace = []
trace.append(to_sort[:])
quicksort(to_sort[:], 0, len(to_sort) - 1)
print(len(trace))
draw_lines(trace, f'quicksort_lines.{args.format}')


"""
Module: libfmp.c4.c4s4_novelty_kernel
Author: Meinard Müller, Julian Reck
License: The MIT license, https://opensource.org/licenses/MIT

This file is part of the FMP Notebooks (https://www.audiolabs-erlangen.de/FMP)
"""
import numpy as np
from numba import jit

def compute_kernel_checkerboard_box(L):
    """Compute box-like checkerboard kernel [FMP, Section 4.4.1]

    Notebook: C4/C4S4_NoveltySegmentation.ipynb

    Args:
        L (int): Parameter specifying the kernel size 2*L+1

    Returns:
        kernel (np.ndarray): Kernel matrix of size (2*L+1) x (2*L+1)
    """
    axis = np.arange(-L, L+1)
    kernel = np.outer(np.sign(axis), np.sign(axis))
    return kernel

@jit(nopython=True)
def compute_kernel_checkerboard_gaussian(L, var=1.0, normalize=True):
    """Compute Guassian-like checkerboard kernel [FMP, Section 4.4.1].
    See also: https://scipython.com/blog/visualizing-the-bivariate-gaussian-distribution/

    Notebook: C4/C4S4_NoveltySegmentation.ipynb

    Args:
        L (int): Parameter specifying the kernel size M=2*L+1
        var (float): Variance parameter determing the tapering (epsilon) (Default value = 1.0)
        normalize (bool): Normalize kernel (Default value = True)

    Returns:
        kernel (np.ndarray): Kernel matrix of size M x M
    """
    taper = np.sqrt(1/2) / (L * var)
    axis = np.arange(-L, L+1)
    gaussian1D = np.exp(-taper**2 * (axis**2))
    gaussian2D = np.outer(gaussian1D, gaussian1D)
    kernel_box = np.outer(np.sign(axis), np.sign(axis))
    kernel = kernel_box * gaussian2D
    if normalize:
        kernel = kernel / np.sum(np.abs(kernel))
    return kernel

# @jit(nopython=True)
def compute_novelty_ssm(S, kernel=None, L=10, var=0.5, exclude=False):
    """Compute novelty function from SSM [FMP, Section 4.4.1]

    Notebook: C4/C4S4_NoveltySegmentation.ipynb

    Args:
        S (np.ndarray): SSM
        kernel (np.ndarray): Checkerboard kernel (if kernel==None, it will be computed) (Default value = None)
        L (int): Parameter specifying the kernel size M=2*L+1 (Default value = 10)
        var (float): Variance parameter determing the tapering (epsilon) (Default value = 0.5)
        exclude (bool): Sets the first L and last L values of novelty function to zero (Default value = False)

    Returns:
        nov (np.ndarray): Novelty function
    """
    if kernel is None:
        kernel = compute_kernel_checkerboard_gaussian(L=L, var=var)
    N = S.shape[0]
    M = 2*L + 1
    nov = np.zeros(N)
    # np.pad does not work with numba/jit
    S_padded = np.pad(S, L, mode='constant')

    for n in range(N):
        # Does not work with numba/jit
        nov[n] = np.sum(S_padded[n:n+M, n:n+M] * kernel)
    if exclude:
        right = np.min([L, N])
        left = np.max([0, N-L])
        nov[0:right] = 0
        nov[left:N] = 0

    return nov


import numpy as np
# parameter to avoid the sigmoid function to return 0 because of an overflow of the exp function
epsilon = 10**-9

def sigmoid(u):
    if u < 0.:
        return  max(epsilon, np.asscalar(np.exp(u))/( np.asscalar(np.exp( u)) + 1.))
    else:

        return max(epsilon, 1./(1. + np.asscalar(np.exp(- u))))

def solveWKRR(K, W, z, lamb):
    """ Solve the WKRR found for kernel logistic regression"""
    first = np.linalg.inv((W**(1./2.)).dot(K).dot((W**(1./2.))) + float(K.shape[0])*lamb*np.identity(K.shape[0]))
    return (W**(1./2.)).dot(first).dot((W**(1./2.))).dot(z)

def evaluate_alpha(alpha, K, label):
    """ Return success percent """
    result = K.dot(alpha)

    success = [float(result[i,0]*label[i] > 0) for i in range(len(label))]

    return np.mean(success)*100

def compute_loss(K, alpha, lamb, label):
    lab = np.asarray(label).reshape([len(label), 1])
    result = K.dot(alpha)
    loss = np.log(1. + np.exp(np.multiply(-result, lab)))
    loss = (1./float(len(label)))*np.sum(loss) + lamb*alpha.T.dot(K).dot(alpha)
    return loss

def compute_label(data_in_kernel, alpha):
    """ Compute the label for the data given (in the form data[i,j] = K(x, xj) with x a new data, xj in the data set"""
    result = data_in_kernel.dot(alpha)
    return [int(result[i,0] > 0.) for i in range(data_in_kernel.shape[0])]

def logistic_kernel_regression(K, label, lamb, nb_it, K_test, label_test):
    """ Apply logistic kernel regression with solving by newton method
    with K the kernel matrix and alpha0 the initialization
    return the alpha found """
    # Initialisation
    alpha = (1. - 2.*np.random.random_sample([K.shape[0] , 1]))
    p = np.zeros([K.shape[0], 1])
    w = np.zeros([K.shape[0], K.shape[0]])
    z = np.zeros([K.shape[0], 1])
    for j in range(nb_it):
        m = K.dot(alpha)
        for i in range(K.shape[0]):
            p[i, 0] = - sigmoid(-label[i] * m[i, 0])
            w[i, i] = sigmoid(m[i, 0]) * sigmoid(-m[i, 0])
            z[i, 0] = m[i, 0] - label[i] * p[i,0]/ (w[i,i])
        alpha = solveWKRR(K, w, z, lamb)
        print( "loss", compute_loss(K, alpha, lamb, label))
        print ("on training", j, evaluate_alpha(alpha, K, label))
        print ("iteration ", j, evaluate_alpha(alpha, K_test, label_test))
    return alpha


import numpy as np

X = np.array([1,2,3,4], dtype=np.float32)
Y = np.array([2,4,6,8], dtype=np.float32)

w = 0.0

# model prediction
def forward(x):
    return w * x
# loss = MSE in linear regression
def loss(y, y_predicted):
    return ((y_predicted-y)**2).mean()

# gradient with respect to our parameters

# MSE = 1/N * (w*x - y)**2
# dJ/dw = 1/N 2x (w*x - y) # numerical computed derivative chain rule
def gradient(x, y, y_predicted):
    return np.dot(2*x, y_predicted-y).mean() # dot product of 2 and x
print(f'Prediction before training: f(5) = {forward(5):.3f}')

# Training
learning_rate = 0.01
n_iters = 10

for epoch in range(n_iters):
    # prediction = forward pass
    y_pred = forward(X)

    # loss
    l = loss(Y, y_pred)

    # gradients
    dw = gradient(X, Y, y_pred)

    # update weights -> go in negative direction of the gradient
    w -= learning_rate * dw

    if epoch % 1 == 0: # we want to print every step
        print(f'epoch {epoch + 1}: w = {w:.3f}, loss = {l:.8f}')

# print prediction after training
print(f'Prediction before training: f(5) = {forward(5):.3f}')


import math
import numpy
from scipy import optimize

def function1(x, y):
    return 5*x - 6 * y + 20 * math.log(x, 10) + 16

def function1_dx(x, y):
    return 5 + 20 / x

def function1_dy(x, y):
    return -6

def function2(x, y):
    return 2*x + y - 10 * math.log(y, 10) - 4

def function2_dx(x, y):
    return 2

def function2_dy(x, y):
    return 1 - 10/y

def function_sys(x):
    return [function1(x[0], x[1]), function2(x[0], x[1])]

def norm(z):
    max_z = abs(z[0])
    for i in z:
        if abs(i) > max_z:
            max_z = abs(i)
    return max_z

def modified_newton_method(b, size):
    eps = 0.0000001
    x0 = [1]*size
    a = numpy.array([[function1_dx(x0[0], x0[1]), function1_dy(x0[0], x0[1])],
                         [function2_dx(x0[0], x0[1]), function2_dy(x0[0], x0[1])]])
    f = numpy.array([function1(x0[0], x0[1]), function2(x0[0], x0[1])])
    x1 = x0 - numpy.linalg.inv(a) @ f

    while norm(x1 - x0) > eps:
        x0 = x1
        a = numpy.array([[function1_dx(x1[0], x1[1]), function1_dy(x1[0], x1[1])],
                         [function2_dx(x1[0], x1[1]), function2_dy(x1[0], x1[1])]])
        f = numpy.array([function1(x1[0], x1[1]), function2(x1[0], x1[1])])
        x1 = x0 - numpy.linalg.inv(a) @ f
    print(x1)
    print(f"{function1(x1[0], x1[1]):9.10f}")

def degree_method(a):
    eps = 0.1
    y0 = numpy.array([1.0]*4)
    y1 = a @ y0
    lmb1 = y1[0]
    y0 = a @ y1
    lmb2 = y0[0]/y1[0]
    while abs(lmb1 - lmb2) > eps:
        lmb1 = lmb2
        y1 = y0
        y0 = a @ y1
        lmb2 = y0[0]/y1[0]
    print(lmb2)

def func(x):
    return pow(x,3) - 3 * pow(x,2) - 17 * x + 22

A = numpy.array([[1, 2, 3, 4], [2, 1, 2, 3], [3, 2, -1, 2], [4, 3, 2, 1]])

print(func(1.5))


import numpy as np

# functions

# gaussian
def gaussian(x, height, center, width):
	return height*np.exp(-(x - center)**2/(2*width**2)) #+ offset

def double_gaussian(x, h1, c1, w1, h2, c2, w2, base):
	return (gaussian(x, h1, c1, w1) +
		gaussian(x, h2, c2, w2) + base)

def chi_gauss(param, xdata, ydata, ysig):
	chi = (ydata - (gaussian(xdata, *param))) / ysig
	return chi

def chi_dgauss(param, xdata, ydata, ysig):
	chi = (ydata - (double_gaussian(xdata, *param))) / ysig
	return chi

def lorentzian(x, a, x0, gamma):
	return a*gamma**2 /((x - x0)**2 + gamma**2) #+ offset

def double_lorentzian(x, a1, c1, g1, a2, c2, g2, base):
	return (lorentzian(x, a1, c1, g1) +
		gaussian(x, a2, c2, g2) + base)

def chi_dlorentz(param, xdata, ydata, ysig):
	chi = (ydata - (double_lorentzian(xdata, *param))) / ysig
	return chi

# discontinuous log-normal gaussian
def loggauss(x, height, center, width, base):
	logg = np.zeros(x.shape)

	# x > 0
	logg[x > 0.] = height*np.exp(-(np.log(x[x > 0.]) - center)**2/(2*width**2))/x[x > 0.] #+ offset

	# x = 0
	logg[x == 0.] = 0.

	# x <0
	logg[x < 0.] = height*np.exp(-(np.log(-x[x < 0.]) - center)**2/(2*width**2))/x[x < 0.] #+ offset

	return logg + base

def chi_loggauss(param, xdata, ydata, ysig):
	chi = (ydata - loggauss(xdata, *param)) / ysig
	return chi


# coding: utf-8
import numpy as np

# ... create Matrix L
def build_L(n):
    L = np.zeros((n, n))
    for i in range(0, n-1):
        L[i, i] = (i+1) * 1. / n
        L[i, i+1] = (n-i-1) * 1. / n
    L[n-1, n-1] = 1.
    return L
# ...

# ... create Matrix M
def build_M(n):
    M = np.zeros((n, n))
    M[0, 0] = 1.
    for i in range(1, n):
        M[i, i-1] = (i) * 1. / n
        M[i, i] = (n-i) * 1. / n
    return M
# ...

# ... create S matrix
def build_S(n, S):
    L = build_L(n)
    M = build_M(n)
    # ... create Su and Sd matrices
    Su = S.dot(L)
    Sd = S.dot(M)
    # ...
    S_new = np.zeros((n+1, n+1))
    S_new[0:n, 0:n] = Su
    S_new[n, 1:n+1] = Sd[-1, :]
    S_new[1:n+1, n] = Sd[:, -1]

    return S_new
    # ...

# ... matrix conversion
def matrix_conversion_ubspline_to_bernstein(n):
    # ... initialization
    S0 = np.ones((1, 1))
    # ...

    # ... recursive algo
    S = S0
    for d in range(1, n):
        S = build_S(d, S)
    # ...

    return S
# ...


from math import cos, acos, sqrt

import numpy as np

# global
PI = 3.141592
RRR = 6378.388
INFINITY = float('inf')

class Graph:
    def __init__(self, input_data, is_geo=False):  # geo is False
        # init adj_matrix w/ all 0 values
        self._length = len(input_data)
        self._adj_matrix = np.zeros((self._length, self._length), dtype=int)  # A data data_type object (using numpy)

        self._create_adj_matrix(input_data, is_geo)
        self._distances = {}  # distance dict key its a tuple (v, s)
        self._predecessors = {}  # again a tuple key

    def _create_adj_matrix(self, input_data, is_geo):  # format, pass data_type o euc format
        for i in input_data:
            for j in input_data:
                if i[0] != j[0]:
                    # geo = False
                    # None if i == j
                    self._adj_matrix[int(i[0]) - 1][int(j[0]) - 1] = Graph.calc_distance(i, j, is_geo)

    def get_distances(self, key):
        """

        :param key: is a tuple
        :return: distance (x,y) y to x
        """
        try:
            return self._distances[key]
        except KeyError:
            try:
                (i, j) = key
                new_key = (j, i)
                return self._distances[new_key]
            except KeyError:
                return None

    def set_distances(self, key, value):
        """

        :param key:
        :param value:
        :return:
        """
        self._distances[key] = value

    def get_parents(self, key):
        return self._predecessors[key]

    def get_adj_matrix(self, u=None, v=None):
        if u is None or v is None:
            return self._adj_matrix
        else:
            return self._adj_matrix[u, v]

    def get_vertices(self):
        return self._length

    def set_parents(self, key, value):
        self._predecessors[key] = value

    @staticmethod
    def convert_to_rads(val):
        deg = int(val)
        min_ = val - deg
        rad = PI * (deg + 5.0 * min_ / 3.0) / 180.0

        return rad

    @staticmethod
    def calc_distance(i, j, is_geo: bool):
        if is_geo:
            lat_i = Graph.convert_to_rads(i[1])  # u[0] index,  u[1] u[2] node latitude, longitude
            long_i = Graph.convert_to_rads(i[2])

            lat_j = Graph.convert_to_rads(j[1])
            long_j = Graph.convert_to_rads(j[2])

            q1 = cos(long_i - long_j)
            q2 = cos(lat_i - lat_j)
            q3 = cos(lat_i + lat_j)
            dij = int(RRR * acos(0.5 * ((1.0 + q1) * q2 - (1.0 - q1) * q3)) + 1.0)
        else:
            dij = int(sqrt((i[1] - j[1]) ** 2 + (i[2] - j[2]) ** 2))
        return dij


import pandas as pd
from sklearn.preprocessing import StandardScaler
from data_preprocess import preprocess
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import numpy as np
from LinearRegression import multiple_regression

def pca_process(data):
    # Standardize the Data

    features = ['HTHG', 'HTAG', 'HST', 'AST', 'HS', 'AS']
    # Separating out the features
    x = data.loc[:, features].values
    # Separating out the target
    y = data.loc[:, ['FTG']].values

    # Standardizing the features
    x = StandardScaler().fit_transform(x)

    pca = PCA(n_components=5)
    principalComponents = pca.fit_transform(x)
    principalDf = pd.DataFrame(data=principalComponents
                               , columns=['principal component 1', 'principal component 2', 'principal component 3',
                                          'principal component 4', 'principal component 5'])

    finalDf = pd.concat([principalDf, data[['FTG']]], axis=1)

    plot_projection(finalDf)

    # plot Explained Variance
    # plot_explained_variance(pca.explained_variance_ratio_)

    return finalDf

def plot_projection(df):
    fig = plt.figure(figsize=(18, 12))
    ax = fig.add_subplot(1, 1, 1)
    ax.set_xlabel('Principal Component 1', fontsize=15)
    ax.set_ylabel('Principal Component 2', fontsize=15)
    ax.set_title('2 component PCA', fontsize=20)
    targets = range(0, 7)
    colors = ['r', 'g', 'b', 'c', 'm', 'y', 'k']
    for target, color in zip(targets, colors):
        indicesToKeep = df['FTG'] == target
        ax.scatter(df.loc[indicesToKeep, 'principal component 1'], df.loc[indicesToKeep, 'principal component 2'],
                   c=color, s=30)
    ax.legend(targets)
    ax.grid()
    plt.savefig('projection.png')

def plot_explained_variance(vars):
    plt.plot(list(range(1, len(vars) + 1)), vars.cumsum(), '-p', color='gray',
             markersize=15, linewidth=4,
             markerfacecolor='white',
             markeredgecolor='gray',
             markeredgewidth=2)
    my_x_ticks = np.arange(0, len(vars) + 1, 1)
    plt.xticks(my_x_ticks)
    plt.xlabel('Components Number')
    plt.ylabel('Cumulative Explained Variance')
    plt.grid()
    plt.savefig('explained_variance.png')

if __name__ == '__main__':
    data = preprocess()
    train_data = preprocess('test')
    pca_data = pca_process(data)
    pca_test_data = pca_process(train_data)
    features = pca_data.columns[:-1]
    # using pca data to do the regression job
    multiple_regression(pca_data, pca_test_data, features)


import numpy as np
from math import log

def trapezoid(f_discrete, dx):
    return 0.5 * dx * sum([(f_discrete[i] + f_discrete[i + 1]) for i in range(len(f_discrete) - 1)])

def romberg(f_discrete, dx):
    def find_a_n():
        nonlocal a, n
        a = len(f_discrete) - 1
        while a % 2 == 0:
            a = a // 2
        n = int(log((len(f_discrete) - 1) // a, 2))

    a, n = 0, 0
    find_a_n()

    i_rom = [[0] * (n - i + 1) for i in range(n + 1)]

    for i in range(n + 1):
        i_rom[i][0] = trapezoid([f_discrete[2 ** (n - i) * j] for j in range(2 ** i * a + 1)], 2 ** (n - i) * dx)

    for j in range(1, n + 1):
        for i in range(n + 1 - j):
            i_rom[i][j] = (4 ** j * i_rom[i + 1][j - 1] - i_rom[i][j - 1]) / (4 ** j - 1)

    return i_rom[0][-1]

# Tri Diagonal Matrix Algorithm(a.k.a Thomas algorithm) solver
def tdma_solver(a, b, c, d):
    """
    TDMA solver, a b c d can be NumPy array type or Python list type.
    refer to http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
    and to http://www.cfd-online.com/Wiki/Tridiagonal_matrix_algorithm_-_TDMA_(Thomas_algorithm)
    """
    nf = len(d)  # number of equations
    ac, bc, cc, dc = map(np.array, (a, b, c, d))  # copy arrays
    for it in range(1, nf):
        mc = ac[it - 1] / bc[it - 1]
        bc[it] = bc[it] - mc * cc[it - 1]
        dc[it] = dc[it] - mc * dc[it - 1]

    xc = bc
    xc[-1] = dc[-1] / bc[-1]

    for il in range(nf - 2, -1, -1):
        xc[il] = (dc[il] - cc[il] * xc[il + 1]) / bc[il]

    return xc


import numpy as np
import pytest
from itertools import combinations_with_replacement

from mchap import combinatorics

def test_count_unique_haplotypes():

    u_alleles = [2, 2, 2, 3, 2, 4]

    # the number of unique haplotypes is the product of
    # the number of unique alleles at each variable position within
    # the haplotype
    answer = np.prod(u_alleles)
    query = combinatorics.count_unique_haplotypes(u_alleles)
    assert query == answer

@pytest.mark.parametrize(
    "u_haps,ploidy,answer",
    [
        pytest.param(10, 2, None),
        pytest.param(333, 3, None),
        pytest.param(12, 4, None),
        pytest.param(12, 4, 1365),
        pytest.param(1024, 2, None),  # diploid with 10 biallelic SNPs
        pytest.param(1024, 2, 524800),  # diploid with 10 biallelic SNPs
        pytest.param(1024, 4, 46081900800),  # tetraploid with 10 biallelic SNPs
        pytest.param(1024, 6, 1624866254968320),  # hexaploid with 10 biallelic SNPs
    ],
)
def test_count_unique_genotypes(u_haps, ploidy, answer):

    query = combinatorics.count_unique_genotypes(u_haps, ploidy)

    if answer is None:
        # calculate the answer with itertools

        # a genotype is a multi-set of haplotypes of size ploidy
        # hence the number of multisets can be (inefficiantly) counted
        # by iterating of all ploidy sized combinations of haplotypes with
        # replacement
        answer = 0
        for _ in combinations_with_replacement(np.arange(u_haps), ploidy):
            answer += 1

    assert query == answer

def test_count_unique_genotype_permutations():

    # this is simply the number of unique haplotypes to the power of ploidy

    u_haps = 1024  # 10 biallelic SNPs
    ploidy = 4

    answer = u_haps**ploidy
    query = combinatorics.count_unique_genotype_permutations(u_haps, ploidy)

    assert query == answer

@pytest.mark.parametrize(
    "dosage,answer",
    [
        pytest.param([2, 0], 1),
        pytest.param([1, 1], 2),
        pytest.param([0, 2], 1),
        pytest.param([1, 1, 1], 6),
        pytest.param([2, 1, 0], 3),
        pytest.param([3, 0, 0], 1),
        pytest.param([4, 0, 0, 0], 1),
        pytest.param([2, 2, 0, 0], 6),
        pytest.param([1, 1, 1, 1], 24),
    ],
)
def test_count_genotype_permutations(dosage, answer):
    dosage = np.array(dosage, dtype=int)
    query = combinatorics.count_genotype_permutations(dosage)
    assert query == answer


import numpy as np

def normalize_points(pts):
  """
  Normalize the points to remove dependence on the origin and
  scale of the original image. This improves the solution DLT
  provides, especially for noisy points.

  Input: 2D list of points (e.g. [[x1,y1], [x2,y2], ...])
  Output: 2D list of transformed points (e.g. [[x1',y1'], [x2',y2'], ...])
  and the homography matrix that did the transform
  """

  [x_mean, y_mean] = np.mean(pts, axis=0)

  # Sum of distances between points and the mean
  total_dist = np.sum(((pt[0] - x_mean)**2 + (pt[1] - y_mean)**2)**0.5 for pt in pts)

  avg_dist = total_dist / len(pts)

  # Scale factor
  sf = np.sqrt(2) / avg_dist

  # Transform by translation [-sf*x_mean, -sf*y_mean] and scale by [sf, sf]
  projective_transform = np.array([[sf, 0, -sf * x_mean], [0, sf, -sf * y_mean], [0, 0, 1]])

  # Pad the inner array so that it can be multiplied by the projection matrix
  ones = np.ones((1, pts.shape[0]))
  padded_pts = np.concatenate((pts.T, ones))

  # Apply the transform to the points
  transformed = projective_transform @ padded_pts

  # Get x and y coordinates, and transpose to be in original form
  pts_2d = transformed[0:2].T

  return pts_2d, projective_transform

def compute_matrix_A(pts1, pts2):
  """
  Compute the 2n x 9 matrix A to setup the linear equations
  that allow the homography values to be found

  Input: Corresponding (matched) normalized points
  Outputs: 2n x 9 matrix A
  """

  A = []

  for i in range (0, len(pts1)):
    x, y = pts1[i]
    x_prime, y_prime = pts2[i]

    A.append([0, 0, 0, -x, -y, -1, y_prime * x, y_prime * y, y_prime])
    A.append([x, y, 1, 0, 0, 0, -x_prime * x, -x_prime * y, -x_prime])

  return np.asarray(A)

def direct_linear_transform(pts1, pts2):
  """
  Compute the homography matrix that transforms pts1 onto the plane of pts2
  via the direct linear transform (DLT) method. This includes a
  normalisation step, as described in Section 4.4 of:

  R. Hartley and A. Zisserman. Multiple View Geomerty in Computer
  Vision. Cambridge University Press, second edition, 2003

  Parameters: Corresponding points for two images (pts1 and pts2)
  Output: H, the homography matrix
  """

  pts1_normalized, pts1_T = normalize_points(pts1)
  pts2_normalized, pts2_T = normalize_points(pts2)

  A = compute_matrix_A(pts1_normalized, pts2_normalized)

  # Compute the singluar value decomposition of A
  _, _, V = np.linalg.svd(A)

  # Get the last col of V and normalise by last value
  h = V[-1, :] / V[-1, -1]

  # Reshape to 3x3 homography matrix
  H_normalized = h.reshape(3, 3)

  # Denormalize the homography matrix
  H = np.linalg.inv(pts2_T) @ H_normalized @ pts1_T

  return H


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

class DCT:
    def __init__(self):
        self.input_dct2d = None
        self.output_dct2d = None

        self.input_idct2d = None
        self.output_idct2d = None

    def get_2d_dct(self, image, n_coef = 0):
        self.input_dct2d = image

        output = np.zeros(image.shape)

        R = output.shape[0]
        C = output.shape[1]

        for k in range(R):
            ck = np.sqrt(0.5) if k == 0 else 1
            for l in range(C):
                cl = np.sqrt(0.5) if l == 0 else 1
                for m in range(R):
                    for n in range(C):
                        output[k][l] += image[m][n] * np.cos(((2*m + 1) * k*np.pi)/(2*R)) * np.cos(((2*n + 1) * l*np.pi)/(2*C))
                output[k][l] *= ck * cl

        output *= 2.0/np.sqrt(R*C)

        if n_coef > 0:
            output.sort()
            for i in range(n_coef, n):
                output[i] = 0

        self.output_dct2d = output

        return output

    def get_2d_dct_sep(self, image, n_coef = 0):
        self.input_dct2d = image

        output = np.zeros(image.shape)

        for row in range(image.shape[0]):
            output[row, :] = self.get_1d_dct(image[row, :], n_coef)

        for column in range(image.shape[1]):
            output[:, column] = self.get_1d_dct(output[:, column], n_coef)

        self.output_dct2d = output

        return output

    def get_1d_dct(self, image, n_coef = 0):
        output = np.zeros(image.shape)
        n = len(image)

        for k in range(n):
            ck = np.sqrt(0.5) if k == 0 else 1
            for i in range(n):
                output[k] += image[i] * np.cos(2 * np.pi * k / (2.0 * n) * i + (k * np.pi) / (2.0 * n))
            output[k] *= ck

        output *= np.sqrt(2.0/n)

        if type(n_coef) == float or type(n_coef) == np.float32:
            n_coef = int(n_coef * len(output))

        if n_coef > 0:
            output.sort()
            for i in range(n_coef, n):
                output[i] = 0

        return output

    def get_inv_2d_dct(self, dct = None):
        if type(dct) == type(None):
            dct = self.output_dct2d

        self.input_idct2d = dct

        output = np.zeros(dct.shape)

        R = output.shape[0]
        C = output.shape[1]

        for m in range(R):
            for n in range(C):
                for k in range(R):
                    ck = np.sqrt(0.5) if k == 0 else 1
                    for l in range(C):
                        cl = np.sqrt(0.5) if l == 0 else 1
                        output[m][n] += ck * cl * dct[k][l] * np.cos(((2*m + 1) * k*np.pi)/(2*R)) * np.cos(((2*n + 1) * l*np.pi)/(2*C))

        output *= (2 / np.sqrt(R*C))

        self.output_idct2d = np.round(output)

        self.output_idct2d[self.output_idct2d < 0] = 0
        self.output_idct2d[self.output_idct2d > 255] = 255

        return output

    def get_inv_2d_dct_sep(self, dct = None):

        if type(dct) == type(None):
            dct = self.output_dct2d

        self.input_idct2d = dct

        output = np.zeros(dct.shape)

        for row in range(dct.shape[0]):
            output[row, :] = self.get_inv_1d_dct(dct[row, :])

        for column in range(dct.shape[1]):
            output[:, column] = self.get_inv_1d_dct(output[:, column])

        self.output_idct2d = np.round(output)

        self.output_idct2d[self.output_idct2d < 0] = 0
        self.output_idct2d[self.output_idct2d > 255] = 255

        return output

    def get_inv_1d_dct(self, dct):
        output = np.zeros(dct.shape)
        n = len(dct)

        for i in range(n):
            for k in range(n):
                ck = np.sqrt(0.5) if k == 0 else 1
                output[i] += ck * dct[k] * np.cos(2 * np.pi * k / (2.0 * n) * i + (k * np.pi) / (2.0 * n))
            output[i] *= np.sqrt(2.0 / n)

        return output

    def show_process(self):
        return self.input_dct2d, self.output_dct2d, self.output_idct2d


# 一行データ記述統計
def describe1(data):
    # 必要なライブラリをインポート
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt

    # 元データ出力
    print(data)

    # サンプルサイズ
    def length(data):
        count = 0
        for d in data:
            count += 1
        return count

    # 合計値
    def sum_value(data):
        sum_value = 0
        for d in data:
            sum_value += d
        return sum_value

    # 算術平均
    def mean(data):
        return sum_value(data) / length(data)

    # 幾何平均
    # 比率や割合等について適用する
    # 0以下の値が含まれていた場合、規格外としてErrorを出す
    def geometric_mean(data):
        try:
            ds = 1
            n = length(data)
            for d in data:
                ds *= d
            return (ds)**(1/n)
        except:
            return 'Error'

    # 調和平均
    # 時速の平均等に適用する
    # 0以下の値が含まれていた場合、規格外としてErrorを出す
    def harmonic_mean(data):
        try:
            ds = 0
            n = length(data)
            for d in data:
                ds += 1/d
            return 1 / ((1/n) * ds)
        except:
            return 'Error'

    # 平均偏差
    def meand(data):
        n = length(data)
        m = mean(data)
        s = 0
        for d in data:
            s += abs(d - m)
        return s / n

    # 母分散
    def var_p(data):
        var_p = 0
        m = mean(data)
        for d in data:
            var_p += (d - m)**2
        return var_p / length(data)

    # 不偏分散
    def var_s(data):
        var_s = 0
        m = mean(data)
        for d in data:
            var_s += (d - m)**2
        return var_s / (length(data)-1)

    # 母標準偏差
    def std_p(data):
        return var_p(data)**0.5

    # 不偏標準偏差..........................未完成？
    # 単に不偏分散の平方根を取ったものは、厳密には「母標準偏差の不偏推定量」ではないらしい
    def std_s(data):
        return var_s(data)**0.5

    # 標準誤差
    def std_e(data):
        return std_s(data) / length(data)**0.5

    # 母平均の95%信頼区間(母分散既知)
    def mean_95cl_known(data):
        n = length(data)
        m = mean(data)
        s = std_p(data)
        return "({:.2f}, {:.2f})".format(m-1.96*(s/n)**0.5, m+1.96*(s/n)**0.5)

    # ソート（クイックソート）
    def quick_sort(data):
        n = length(data)
        pivot = data[n//2]
        left, middle, right = [], [], []
        for i in range(n):
            if data[i] < pivot:
                left = left + [data[i]]
            elif pivot < data[i]:
                right = right + [data[i]]
            else:
                middle = middle + [data[i]]
        if left:
            left = quick_sort(left)
        if right:
            right = quick_sort(right)
        return left + middle + right

    # 最小値
    def min_value(data):
        data_sorted = quick_sort(data)
        return data_sorted[0]

    # 最大値
    def max_value(data):
        data_sorted = quick_sort(data)
        return data_sorted[length(data)-1]

    # 第一四分位数
    def quartile1(data):
        data_sorted = quick_sort(data)
        q1 = length(data) * (1/4)
        return data_sorted[int(q1)]

    # 中央値
    def median(data):
        data_sorted = quick_sort(data)
        q2 = length(data) / 2
        if q2%1 != 0:
            return data_sorted[int(q2)]
        else:
            return (data_sorted[int(q2)] + data_sorted[int(q2)+1]) / 2

    # 第三四分位数
    def quartile3(data):
        data_sorted = quick_sort(data)
        q3 = length(data) * (3/4)
        return data_sorted[int(q3)]

    # 四分位偏差
    def quartile_range(data):
        return quartile3(data) - quartile1(data)

    # ミッドレンジ
    def mid_range(data):
        return (max_value(data) + min_value(data)) / 2

    # レンジ
    def all_range(data):
        return max_value(data) - min_value(data)

    # 最頻値
    def mode(data):
        # 個数を数える
        data_sorted = quick_sort(data)
        discoverd = {}
        for d in data_sorted:
            if d not in discoverd.keys():
                discoverd[d] = 1
            else:
                discoverd[d] += 1

        # 個数が最大のデータを検索する(複数個ある場合は全て出力する)
        discoverd_keys, discoverd_values = list(discoverd.keys()), list(discoverd.values())
        max_cnt = max_value(discoverd_values)
        mode = []
        for i, value in enumerate(discoverd_values):
            if max_cnt == value:
                mode += [discoverd_keys[i]]

        return str(mode)

    # 変動係数(coefficient of variance)
    # 単位が無く、直接の比較が困難な場合に平均を考慮した上での比率の比較ができる
    # 比率の比較なので、比例尺度のみ使用できる
    # 標準偏差は母分散を用いて計算する(統計学入門のp38式より)
    def cov(data):
        return std_p(data) / mean(data)

    # ジニ係数(gini coefficient)
    # 不平等度の指標として用いられる
    # 面積を表すので普通は負の値を取らないが、定義通りに計算して出力する。
    def gini(data):
        n = length(data)
        m = mean(data)
        s = 0
        for d1 in data:
            for d2 in data:
                s += abs(d1 - d2)
        return s / (2 * n**2 * m)

    # 歪度(skewness)
    # 母集団の分布の非対称性の程度・方向性を示す推定統計量
    # 値が正なら右の裾が長く、負なら左の裾が長い分布となっている
    def skewness(data):
        n = length(data)
        m = mean(data)
        s = std_s(data)

        three = 0
        for d in data:
            three += ((d-m) / s)**3

        return (n/((n-1)*(n-2))) * three

    # 尖度(kurtosis)
    # 母集団の分布の中心周囲部分の尖り具合を表す推定統計量
    # 値が正なら正規分布より尖っており、負なら正規分布より丸く鈍い形をしている
    def kurtosis(data):
        n = length(data)
        m = mean(data)
        s = std_s(data)

        four = 0
        for d in data:
            four += (d-m)**4 / s**4

        return ((n*(n+1))/((n-1)*(n-2)*(n-3))) * four - (3*(n-1)**2)/((n-2)*(n-3))

    # ジャック-ベラ検定(Jarque–Bera test)
    # 標本が正規分布に従っているかどうかを検定する
    # 帰無仮説：標本が正規分布に従う
    # 対立仮説：標本が正規分布に従わない
    # ソース：https://ja.wikipedia.org/wiki/ジャック–ベラ検定
    def jarque_bera(data):
        n = length(data)
        m = mean(data)

        s2, s3, s4 = 0, 0, 0
        for d in data:
            s2 += (d - m)**2
            s3 += (d - m)**3
            s4 += (d - m)**4

        # 標本歪度
        S = (s3/n) / (s2/n)**(3/2)
        # 標本尖度
        K = (s4/n) / (s2/n)**2

        JB = (n/6) * (S**2 + (1/4)*(K-3)**2)
        return JB

    # 結果出力
    display(pd.DataFrame({
        'count':length(data),
        'sum':sum_value(data),
        'mean':mean(data),
        'g_mean':geometric_mean(data),
        'h_mean':harmonic_mean(data),
        'meand':meand(data),
        'var.p':var_p(data),
        'var.s':var_s(data),
        'std.p':std_p(data),
        'std.s':std_s(data),
        'std_e':std_e(data),
        'mean_95cl_known':mean_95cl_known(data),
        'min':min_value(data),
        '25%':quartile1(data),
        '50%':median(data),
        '75%':quartile3(data),
        'max':max_value(data),
        '25-75%':quartile_range(data),
        'mid-range':mid_range(data),
        'range':all_range(data),
        'mode':mode(data),
        'cov':cov(data),
        'gini':gini(data),
        'skewness':skewness(data),
        'kurtosis':kurtosis(data),
        'Jarque-Bara_test.x2':jarque_bera(data)
    }, index=["descriptive statistics"]).T)

    # 種々のグラフをプロット
    # グラフ
    plt.plot(data)
    plt.title("Plot")
    plt.show()

    # 散布図
    plt.scatter([i for i in range(len(data))], data)
    plt.title("Scatter")
    plt.show()

    # ヒストグラム
    plt.hist(data, bins=(1+int(np.log2(length(data))))) #階級幅はスタージェスの公式で定める
    plt.title("Histogram")
    plt.show()

    # ヒストグラム(累積)
    plt.hist(data, bins=(1+int(np.log2(length(data)))), cumulative=True) #階級幅はスタージェスの公式で定める
    plt.title("Histogram(cumulative)")
    plt.show()

    # Q-Qプロット
    # 点が一直線に並んでいれば、そのデータの母集団の分布は正規分布に従う
    st.probplot(data, dist="norm", plot=plt)
    plt.show()

    # 箱ひげ図
    plt.boxplot(data)
    plt.title("Boxplot")
    plt.show()

    # バイオリンプロット
    plt.violinplot(data, widths=2, showmeans=True, showmedians=True, showextrema=True)
    plt.title("Violinplot")
    plt.show()

    # イベントプロット
    plt.eventplot(data, orientation="vertical")
    plt.title("Eventplot")
    plt.show()

# a以上b未満のランダム乱数size個...np.random.randint(a, b, size)
# 最小値low, 最大値highの一様乱数size個...np.random.uniform(low, high, size)
# 平均a, 標準偏差bの正規分布乱数size個...np.random.normal(a, b, size)
# ある期間に平均してscale回起こる現象が、次に起こるまでの期間Xが従う指数分布乱数size個...np.random.exponential(scale, size)
# 成功する確率がpのベルヌーイ試行をn回やる時の二項分布乱数size個...np.random.binomial(n, p, size)
# ベルヌーイ試行を何回か繰り返すときに、初めて成功するまでの回数を確率変数X、各試行の成功確率をpとしたときの幾何分布乱数size個...np.random.geometric(p, size)
# 単位時間あたりにある事象が平均してlam回起こる場合に、その事象がx回起こる確率を示すポアソン分布size個...np.random.poisson(lam, size)
# 試行回数n回の結果がpvals通りある時の多項分布乱数size個...np.random.multinomial(n, pvals, size)...（当たり前だけど）リストで返ってくるので、今回の実験に向かない
# パラメータa,bのベータ分布size個...np.random.beta(a, b, size)
# 形状母数shape、尺度母数scaleのガンマ分布に従う乱数size個np.random.gamma(shape, scale, size)
# 自由度dfのカイ二乗分布に従う乱数size個...np.random.chisquare(df, size)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as st
data = pd.DataFrame(np.random.randint(1, 101, 100), columns=["data"])["data"]
describe1(data)


#
# add path to local library mrob on bashr_rc: "export PYTHONPATH=${PYTHONPATH}:${HOME}/mrob/mrob/lib"
import mrob
import numpy as np
import open3d
# example equal to ./PC_alignment/examples/example_align.cpp
# generate random data
N = 5
X =  np.random.rand(N,3)
T = mrob.geometry.SE3(np.random.rand(6))
Y = T.transform_array(X)

print('X = \n', X,'\n T = \n', T.T(),'\n Y =\n', Y)

# solve the problem
T_arun = mrob.registration.arun(X,Y)
print('Arun solution =\n', T_arun.T())

W = np.ones(N)
T_wp = mrob.registration.weighted(X,Y,W)
print('Weighted point optimization solution =\n', T_wp.T())

def pcd_1(X, color, T = []):
	pcd = open3d.geometry.PointCloud()
	pcd.points = open3d.utility.Vector3dVector(X)
	if T!=[]:
	    pcd.transform(T)
	pcd.paint_uniform_color(color)
	return pcd

def vis_her(X, Y, T = []):
    blue = np.array([0,0,1], dtype='float64')
    red = np.array([1,0,0], dtype='float64')
    if T!=[]:
    	open3d.visualization.draw_geometries([pcd_1(X,red), pcd_1(Y,blue, T)])
    else:
        open3d.visualization.draw_geometries([pcd_1(X,red), pcd_1(Y,blue)])

def vis_arr(X):
	pcd = open3d.PointCloud()
	pcd.points =open3d.utility.Vector3dVector(X)
	pcd.paint_uniform_color(np.random.rand(3,).astype(np.float64))
	open3d.visualization.draw_geometries([pcd])

if 0:
    vis_her(X,Y,np.asarray(T_arun.T()))


''' Problem Description
Given an integer A you need to find the Ath fibonacci number modulo 109 + 7.
The first fibonacci number F1 = 1
The first fibonacci number F2 = 1
The nth fibonacci number Fn = Fn-1 + Fn-2 (n > 2)

Approach: As A is very large we can not use normal recursion or dynamic programming to find the fibonacci number.
We need to find some more efficient trick.

Method 1: ( Using power of the matrix {{1, 1},{1, 0}} )
This O(A) approach which relies on the fact that if we n times multiply the matrix M = {{1, 1},{1, 0}} to itself (in other words calculate power(M, n )), then we get the (n+1)th Fibonacci number as the element at row and column (0, 0) in the resultant matrix.

The matrix representation gives the following closed expression for the Fibonacci numbers:

This method can be optimized to work in O(LogA) time complexity.
We can do recursive multiplication to get power(M, n) in the previous method using this trick.

Time Complexity: O(LogA)
Extra Space: O(LogA) if we consider the function call stack size, otherwise O(1).'''

class Solution:
    # @param A : integer
    # @return an integer
    def solve(self, A):

        import numpy as np

        by = 10**9+7
        if A in [1,2]:
            return 1
        import numpy as np
        M = np.matrix([[1,1],[1,0]],dtype=int)

        def ret(N):
            if N == 1 :
                return M
            M1 = ret(N//2)
            if N%2:
                return (M1*M1*M)%by
            else :
                (M1*M1)%by

        return np.array(ret(A-1))[0][0]


#!/usr/bin/env python3
#
# Script to verify polynomial bases and inner product routine.
#
# Daniel R. Reynolds
# SMU Mathematics
# Math 4315

# imports
import numpy
from Chebyshev import Chebyshev
from Legendre import Legendre
from L2InnerProduct import L2InnerProduct

# set interval and weight functions
a = -1.0
b = 1.0
def wL(x):
    if numpy.isscalar(x):
        return 1.0
    else:
        return numpy.ones(x.shape)
def wC(x):
    return 1.0/numpy.sqrt(1.0-x**2)

# quick test to verify orthogonality of first 41 Chebyshev polynomials
print('Testing orthogonality of first 41 Chebyshev polynomials:')
passed = True
for i in range(41):
    for j in range(i+1,41):
        def fi(x):
            return Chebyshev(x,i)
        def fj(x):
            return Chebyshev(x,j)
        v = L2InnerProduct(fi,fj,wC,a,b)
        if (abs(v) > 1e-6):
            print('  <p%i,p%i> = %e' % (i, j, v))
            passed = False
if (passed):
    print('  Tests passed')

# quick test to verify orthogonality of first 41 Legendre polynomials
print('Testing orthogonality of first 41 Legendre polynomials:')
passed = True
for i in range(41):
    for j in range(i+1,41):
        def fi(x):
            return Legendre(x,i)
        def fj(x):
            return Legendre(x,j)
        v = L2InnerProduct(fi,fj,wL,a,b)
        if (abs(v) > 1e-6):
            print('  <p%i,p%i> = %e' % (i, j, v))
            passed = False
if (passed):
    print('  Tests passed')

# quick test to verify norms for first 41 Chebyshev polynomials
print('Testing norms for first 41 Chebyshev polynomials:')
passed = True
for i in range(41):
    def fi(x):
        return Chebyshev(x,i)
    v = L2InnerProduct(fi,fi,wC,a,b)
    if (i==0):
        if (abs(v - numpy.pi) > 1e-6):
            print('  <p0,p0> = %e' % (v))
            passed = False
    else:
        if (abs(v - numpy.pi/2) > 1e-6):
            print('  <p%i,p%i> = %e' % (i, i, v))
            passed = False
if (passed):
    print('  Tests passed')

# quick test to verify norms for first 41 Legendre polynomials
print('Testing norms for first 41 Legendre polynomials:')
passed = True
for i in range(41):
    def fi(x):
        return Legendre(x,i)
    v = L2InnerProduct(fi,fi,wL,a,b)
    if (abs(v - 1.0/(i+0.5)) > 1e-6):
        print('  <p0,p0> = %e' % (v))
        passed = False
if (passed):
    print('  Tests passed')

# end of script


from astropy.modeling.models import custom_model

#TODO: Add Jacobian
@custom_model
def GeneralizedLorentz1D(x, x_0=1., fwhm=1., value=1., power_coeff=1.):
    """
    Generalized Lorentzian function,
    implemented using astropy.modeling.models custom model

    Parameters
    ----------
    x: numpy.ndarray
        non-zero frequencies

    x_0 : float
        peak central frequency

    fwhm : float
        FWHM of the peak (gamma)

    value : float
        peak value at x=x0

    power_coeff : float
        power coefficient [n]

    Returns
    -------
    model: astropy.modeling.Model
        generalized Lorentzian psd model
    """
    assert power_coeff > 0., "The power coefficient should be greater than zero."
    return value * (fwhm / 2)**power_coeff * 1./(abs(x - x_0)**power_coeff + (fwhm / 2)**power_coeff)

#TODO: Add Jacobian
@custom_model
def SmoothBrokenPowerLaw(x, norm=1., gamma_low=1., gamma_high=1., break_freq=1.):
    """
    Smooth broken power law function,
    implemented using astropy.modeling.models custom model

    Parameters
    ----------
    x: numpy.ndarray
        non-zero frequencies

    norm: float
        normalization frequency

    gamma_low: float
        power law index for f --> zero

    gamma_high: float
        power law index for f --> infinity

    break_freq: float
        break frequency

    Returns
    -------
    model: astropy.modeling.Model
        generalized smooth broken power law psd model
    """
    return norm * x**(-gamma_low) / (1. + (x / break_freq)**2)**(-(gamma_low - gamma_high) / 2)

def generalized_lorentzian(x, p):
    """
    Generalized Lorentzian function.

    Parameters
    ----------

    x: numpy.ndarray
        non-zero frequencies

    p: iterable
        p[0] = peak centeral frequency
        p[1] = FWHM of the peak (gamma)
        p[2] = peak value at x=x0
        p[3] = power coefficient [n]

    Returns
    -------
    model: numpy.ndarray
        generalized lorentzian psd model
    """

    assert p[3] > 0., "The power coefficient should be greater than zero."
    return p[2] * (p[1] / 2)**p[3] * 1./(abs(x - p[0])**p[3] + (p[1] / 2)**p[3])

def smoothbknpo(x, p):
    """
    Smooth broken power law function.

    Parameters
    ----------

    x: numpy.ndarray
        non-zero frequencies

    p: iterable
        p[0] = normalization frequency
        p[1] = power law index for f --> zero
        p[2] = power law index for f --> infinity
        p[3] = break frequency

    Returns
    -------
    model: numpy.ndarray
        generalized smooth broken power law psd model
    """

    return p[0] * x**(-p[1]) / (1. + (x / p[3])**2)**(-(p[1] - p[2]) / 2)


import numpy as np
import matplotlib.pyplot as plt
from scipy.constants import pi as π
from scipy.optimize import curve_fit
import uncertainties as unc
from uncertainties import umath
from uncertainties import ufloat
g = 9.81

θ,t,tUncertainty = np.loadtxt(r"Lab/Term 2/2022.01.27 Not So Simple Pendulum - Computing/nss-real-experiment-a.csv", unpack=True, delimiter = ',')

# Adjust your font settings
titleFont = {'fontname':'Bodoni 72','size':13}
axesFont = {'fontname':'CMU Sans Serif','size':9}
ticksFont = {'fontname':'DM Mono','size':7}
errorStyle = {'mew':1,'ms':3,'capsize':3,'color':'blue','ls':''}
pointStyle = {'mew':1,'ms':3,'color':'blue'}
lineStyle = {'linewidth':0.5,'color':'red'}

def experimentA(θₒ,Tₒ,a,b):
    return Tₒ* (1 + a*θₒ+ b*θₒ**2)
def experimentB(x,m,c):
    return m*x+c

curvefitA,cov_curvefitA = curve_fit(experimentA, θ,t)
plt.xlabel("Angular Amplitude, θ initial / °)", **axesFont)
plt.ylabel("Period, T / s", **axesFont)
plt.xticks(**ticksFont)
plt.yticks(**ticksFont)
plt.title('Experiment A: Angular Amplitude vs. Period', **titleFont)
plt.errorbar(θ, t, yerr = tUncertainty,  **errorStyle)
plt.plot(θ,t,'x',**pointStyle)
plt.plot(θ, experimentA(θ, *curvefitA),**lineStyle)
plt.savefig('Experiment A', dpi = 1000)
plt.show()

print("Experiment A:")
print(cov_curvefitA)
print('a = ', curvefitA[1], 'b = ', curvefitA[2], 'Tₒ = ', curvefitA[0])

# Experiment B
ρ,T,TUncertainty = np.loadtxt(r"Lab/Term 2/2022.01.27 Not So Simple Pendulum - Computing/nss-real-experiment-b.csv", unpack=True, delimiter = ',')   #import values of density and period.
curvefitB, cov_curvefitB = curve_fit(experimentB, ρ, T)
TSquared = 1/T**2

plt.xlabel("Density of Pendulum Bob, ρ / g.cm¯³", **axesFont)
plt.ylabel("Period¯², T¯² / s¯²", **axesFont)
plt.xticks(**ticksFont)
plt.yticks(**ticksFont)
plt.title('Experiment B: Density against 1/Period¯²', **titleFont)
plt.errorbar(ρ, TSquared, yerr = TUncertainty, **errorStyle)
plt.plot(ρ, TSquared,'x',**pointStyle)
plt.plot(ρ, experimentB(ρ, curvefitB[0],curvefitB[1]-0.28),**lineStyle)

plt.savefig('Experiment B', dpi = 1000)
plt.show()

print("Experiment B:")
print(cov_curvefitB)
#print('k = ', curvefitB[0])