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

# # Machine Learning using Logistic Regression
#
# Classifier model that estimates an applicant’s probability of admission based the scores from those two exams.

# In[1]:

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

# In[2]:

data = pd.read_csv('ex2data1.txt', names = ['score1', 'score2', 'admitted'])
data = data.astype('float128')
print('Profiling Data')
print(data.info())
print(data.head())

# profile = pandas_profiling.ProfileReport(df)
# profile.to_file(outputfile="output.html")

# In[3]:

x = np.array(data[['score1', 'score2']]) # training set
y = np.array(data['admitted']) # labels
[m, n] = np.shape(x)

# ## ==================== Part 1: Plotting ====================

# In[4]:

print('Plotting data with "x" indicating (y = 1) examples and "o" indicating (y = 0) examples.')
sns.scatterplot('score1', 'score2', hue='admitted', style='admitted', data=data)

# ## =========== Part 2: Mapping Features ============
#
# One way to fit the data better is to create more features from each data point. We will map the features into all polynomial terms of $x_1$ and $x_2$ up to the sixth power.
#
# As a result of this mapping, our vector of two features (the scores on two QA tests) has been transformed into a 28-dimensional vector. A logistic regression classifier trained on this higher-dimension feature vector will have a more complex decision boundary and will appear nonlinear when drawn in our 2-dimensional plot.
#
# While the feature mapping allows us to build a more expressive classifier, it also more susceptible to overfitting. To void that we will implement regularized logistic regression to fit the data and combat the overfitting problem.

# In[5]:

"""
Normalizes the features in X
returns a normalized version of X where the mean value of each feature is 0 and the standard deviation is 1.
This is often a good preprocessing step to do when working with learning algorithms.

First, for each feature dimension, compute the mean of the feature and subtract it from the dataset,
storing the mean value in mu. Next, compute the  standard deviation of each feature and divide
each feature by it's standard deviation, storing the standard deviation in sigma.
"""
def featureNormalize(X):
    X_norm = np.zeros(np.shape(X))
    qty_features = np.shape(X)[1]
    mu = np.zeros(qty_features)
    sigma = np.zeros(qty_features)

    for i in range(qty_features):
        mu[i] = np.mean(X[:,i])
        X_norm[:,i] = X[:,i] - mu[i]

        # by default np.std calculate the population std, here we want sample std (as done in Octave)
        sigma[i] = np.std(X_norm[:,i], ddof=1) # default: ddof=0 (N - 0) will predict 293092.21273075533
        X_norm[:,i] = X_norm[:,i] / sigma[i]
    return X_norm, mu, sigma

# In[6]:

# Tessting Feature Normalization
X_ = np.array([
    [2104, 3],
    [1600, 3],
    [2400, 3],
    [1416, 2],
    [3000, 4]
])
X_n, mu_, sigma_ = featureNormalize(X_)
print("X Norm", X_n)
print("mu", mu_) # [2104.    3.]
print("sigma", sigma_) # [635.96226303   0.70710678]

# In[7]:

# Scale features and set them to zero mean
print('Normalizing Features ...\n')
# We normalize to avoid log(0) because our sigmoid will return small values
X, mu, sigma = featureNormalize(x)

print('Normalized data')
X[:5]

# In[8]:

# Add a column of ones to X to facilitate the manipulation
X = np.column_stack((np.ones(m), X))
X[:5]

# ## ============ Part 3: Compute Cost and Gradient ============

# ### Activation Function
# We will use the sigmoid function as our activation function.
#
# $g(z) = \frac{1}{1 + e^{-z}}$
#
# When:
#
# $z = 0$ then $g = 0.5$
#
# $z \rightarrow +\infty$ then $g \rightarrow +1$
#
# $z \rightarrow -\infty$ then $g \rightarrow 0$
#

# In[9]:

def sigmoid(z):
    # return np.divide(np.float128(1.0), (np.float128(1.0) + np.exp(-z)), dtype=np.float128)
    return 1 / (1 + np.exp(-z))

# In[10]:

print(sigmoid(-5)) # ~= 0.0066929
print(sigmoid(0)) # ~= 0.5
print(sigmoid(5)) # ~= 0.99331
print(sigmoid(np.array([4, 5, 6]))) # ~= [0.98201   0.99331   0.99753]
print(sigmoid(np.array([-1, 0, 1]))) # ~= [0.26894 0.50000 0.73106]
print(sigmoid(np.array([[4, 5, 6], [-1, 0, 1]])))

# Add a column of ones to X to facilitate the manipulation.
#
# Each row is a input with the following format:
#
# $X[0] = [ x_0, x_1, x_2 ]$ where $x_0 = 1$

# ### Hypothesis Function
# Function that defines our logistic model.
#
# Definition:
#
# $h_\theta(x) = g(\theta_0 + \theta_1 * x_1 + \theta_2 * x_2)$
#
# Vectorial form:
#
# $h_\theta(x) = g(\theta^{T} * x)$
#
# where:
#
# $g$ is the sigmoid function; $x = [x_0, x_1, x_2]$; $x_0 = 1$ and $\theta = [\theta_0, \theta_1, \theta_2]$

# In[11]:

def hypothesis(X, theta):
    # z = np.array([np.dot(xi, theta) for xi in X])
    z = X.dot(theta)
    return sigmoid(z)

# ### Logistic Cost Function
# Computes the logistic cost of using theta as the parameter for logistic regression to fit the data points in X and y.
#
# Function cost:
#
# $ J(\theta) = \frac{1}{m} \sum_{i=1}^{m} [ -y^{(i)} log(h_\theta(x^{(i)}) - (1 - y^{(i)}) log(1 - h_\theta(x^{(i)})) ]$
#
# Vectorial form:
#
# $ J(\theta) = \frac{1}{m} * [-\vec{y}^{T} \cdot log(h_\theta(\vec{x})) - (1 - \vec{y})^{T} \cdot log(1 - h_\theta(\vec{x}))] $
#
# If any time we got a $log(h_\theta(x^{(i)})) = 0$ that means we need to normalize the features.

# In[12]:

"""
Inputs:
X = [
  [ x_0, x_1, ..., x_n ]
]
y = [
  [ y_0 ]
  ...
  [ y_m ]
]
theta = [ theta_0, ..., theta_n ]
"""
def computeLogisticCostIterative(X, y, theta):
    m = len(y)
    errorSum = 0 # total error
    for i in range(m):
        h = hypothesis(X[i], theta)
        errorSum = errorSum + (-y[i] * np.log(h) - (1 - y[i]) * np.log(1 - h))
    return errorSum / m

# Better way using Matrix/Vectors
def computeLogisticCostMatrix(X, y, theta):
    m = len(y)
    h = hypothesis(X, theta)
    return (1 / m) * (-y.T.dot(np.log(h)) - (1 - y).T.dot(np.log(1 - h)))

# In[13]:

print('Testing cost function')
X_ = np.array([
    [1, 8, 1, 6],
    [1, 3, 5, 7],
    [1, 4, 9, 2]
]);
y_ = np.array([1, 0, 1]);
theta_ = np.array([-2, -1, 1, 2]);
print('J ~= 4.6832 ->', computeLogisticCostIterative(X_, y_, theta_))
print('J ~= 4.6832 ->', computeLogisticCostMatrix(X_, y_, theta_))

# In[14]:

# Initialize fitting parameters
initial_theta = np.zeros([n + 1])
#initial_theta = np.array([0.1, 12.00921659, 11.26284221], dtype=np.float128)
cost = computeLogisticCostMatrix(X, y, initial_theta)
print('Cost at initial theta (zeros): %f', cost)
print('Expected cost (approx): 0.693')

# ### Running Gradient Descent
# Performs gradient descent to learn $\theta$ parameters.
#
# It return an array with $\theta$ containing the values found by taking num_iters gradient steps with learning rate alpha.
#
# Also it return an array with the history of $J(\theta)$ to be plotted.
#
# Step to update each parameter:
#
# $\theta_j := \theta_j - \alpha * \frac{\partial J}{\partial \theta_j} $
#
# Where:
#
# $\frac{\partial J}{\partial \theta_j} = \frac{1}{m} \sum_{i=1}^{m} [( h_\theta(x^{(i)}) - y^{(i)}) * x^{(i)}]$
#
# Metrix form:
#
# $ \frac{\partial J}{\partial \theta_j} = \frac{1}{m} = X^{T} ( h_\theta(x^{(i)}) - y^{(i)}) $

# In[15]:

def logisticGradientDescent(X, y, theta, alpha, num_iters):
    m = len(y)
    J_history = np.zeros(num_iters)
    for i in range(num_iters):
        h_theta = hypothesis(X, theta)
        # gradient of our cost function
        nabla = (1 / m) * X.T.dot(h_theta - y)
        # print (nabla) # first iteration: [ 0.31722, 0.87232, 1.64812, 2.23787 ]
        theta = theta - alpha * nabla

        # Save the cost J in every iteration
        J_history[i] = computeLogisticCostIterative(X, y, theta)
    return theta, J_history

# In[16]:

# ~= [-2, -1, 1, 2], [4.6832]
logisticGradientDescent(X_, y_, theta_, 0, 1)

# In[17]:

num_iters = 50; # with alpha = 0.01 we should rise the # of iterations
alphas = [0.01, 0.03, 0.1, 0.3, 1, 3, 10]
colors = ['b', 'r', 'y', 'black', 'brown', 'gray'];

# In[18]:

# To plot the J(theta) using different alphas
fig, ax = plt.subplots()
iterations = range(num_iters)

print('Running gradient descent ...\n')
for alpha, color in zip(alphas, colors):
    theta = np.zeros([n + 1]) # reset the theta to the current alpha

    theta, J_history = logisticGradientDescent(X, y, theta, alpha, num_iters)
    # print('alpha ', alpha, ' found theta ', theta)
    plt.plot(iterations, J_history, color=color, label='alpha %.2f' % alpha)

plt.legend(loc='best', ncol=2)

# In[19]:

# Display gradient descent's result
print('Theta computed from gradient descent:');
# Expected ~= [ 1.426919, 3.391232, 3.142802]
print(theta);

# In[20]:

predict = [45, 85]
# normalize and add the x_0 = 1
predict_norm = np.column_stack((np.ones(1), [((predict - mu) / sigma)]))
prob = hypothesis(predict_norm, theta)
print('For a student with scores 45 and 85, we predict an admission probability of', prob)
print('Expected value: 0.732');

# Compute accuracy on our training set
p = hypothesis(X, theta)

print('Train Accuracy: ', ((p >= 0.5) == y).sum().mean())
print('Expected accuracy (approx): 89.0\n')

# ## ==================== Part 3: Plotting Boundary Decision ====================

# In[21]:

# Calculate the boundary decision
score1_min = x[:,0].min()
score1_max = x[:,0].max()
score2_min = x[:,1].min()
score2_max = x[:,1].max()

xgrid = np.arange(score1_min, score1_max, (score1_max - score1_min) / 100)
ygrid = np.arange(score2_min, score2_max, (score2_max - score2_min) / 100)

X,Y = np.meshgrid(xgrid, ygrid) # grid of points
gridPoints = np.c_[X.ravel(), Y.ravel()]

predictions = np.zeros(len(gridPoints))
for i in range(len(gridPoints)):
    point = gridPoints[i]
    predict_norm = np.column_stack((np.ones(1), [((point - mu) / sigma)]))
    prob = hypothesis(predict_norm, theta)
    predictions[i] = 1 if prob >= 0.5 else 0

predictions = predictions.reshape(X.shape)

# In[22]:

fig, ax = plt.subplots()
# setup plot for decision boundary (0 = Refused, 1 = Admitted)
plt.contourf(X, Y, predictions, alpha=0.3)
sns.scatterplot('score1', 'score2', hue='admitted', style='admitted', style_order=[1,0], data=data)
plt.legend()
# plt.show()

# In[ ]:

Machine Learning - Andrew Ng/assignments/machine-learning-ex2/ex2_python/Machine Learning using Logistic Regression.py


import numpy as np
def swap_rows(A, a, b):
    """Rows two rows in a matrix, switch row a with row b

    args:
        A: matrix to perform row swaps on
        a: row index of matrix
        b: row index of matrix

    returns: nothing

    side effects:
    changes A to rows a and b swapped
    """
    assert (a>=0) and (b>=0)
    N = A.shape[0] #number of rows
    assert (a<N) and (b<N) #less than because 0-based indexing
    temp = A[a,:].copy()
    A[a,:] = A[b,:].copy()
    A[b,:] = temp.copy()
def BackSub(aug_matrix,x):
    """back substitute a N by N system after Gaussian elimination

    Args:
        aug_matrix: augmented matrix with zeros below the diagonal
        x: length N vector to hold solution
    Returns:
        nothing
    Side Effect:
    x now contains solution
    """
    N = x.size
    for row in range(N-1,-1,-1):
        RHS = aug_matrix[row,N]
        for column in range(row+1,N):
            RHS -= x[column]*aug_matrix[row,column]
        x[row] = RHS/aug_matrix[row,row]
    return
def GaussElimPivotSolve(A,b,LOUD=0):
    """create a Gaussian elimination with pivoting matrix for a system

    Args:
        A: N by N array
        b: array of length N
    Returns:
        solution vector in the original order
    """
    [Nrow, Ncol] = A.shape
    assert Nrow == Ncol
    N = Nrow
    #create augmented matrix
    aug_matrix = np.zeros((N,N+1))
    aug_matrix[0:N,0:N] = A
    aug_matrix[:,N] = b
    #augmented matrix is created

    #create scale factors
    s = np.zeros(N)
    count = 0
    for row in aug_matrix[:,0:N]: #don't include b
        s[count] = np.max(np.fabs(row))
        count += 1
    if LOUD:
        print("s =",s)
    if LOUD:
        print("Original Augmented Matrix is\n",aug_matrix)
    #perform elimination
    for column in range(0,N):

        #swap rows if needed
        largest_pos = np.argmax(np.fabs(aug_matrix[column:N,column]/s[column])) + column
        if (largest_pos != column):
            if (LOUD):
                print("Swapping row",column,"with row",largest_pos)
                print("Pre swap\n",aug_matrix)
            swap_rows(aug_matrix,column,largest_pos)
            #re-order s
            tmp = s[column]
            s[column] = s[largest_pos]
            s[largest_pos] = tmp
            if (LOUD):
                print("A =\n",aug_matrix)
        #finish off the row
        for row in range(column+1,N):
            mod_row = aug_matrix[row,:]
            mod_row = mod_row - mod_row[column]/aug_matrix[column,column]*aug_matrix[column,:]
            aug_matrix[row] = mod_row
    #now back solve
    x = b.copy()
    if LOUD:
        print("Final aug_matrix is\n",aug_matrix)
    BackSub(aug_matrix,x)
    return x


"""
Tests for the measure module.
"""

# imports
import pytest

import molecool
import numpy as np

def test_calculate_distance():

    r1 = np.array([0, 0, 0])
    r2 = np.array([0, 1, 0])

    expected_distance = 1

    calculated_distance = molecool.calculate_distance(r1, r2)

    assert expected_distance == calculated_distance

# Write a test for the calculate_angle function
# use points (0, 0, -1) (0, 0, 0) (1, 0, 0)
# expected angle is 90 degrees

def test_calculate_angle():

    r1 = np.array([1, 0, 0])
    r2 = np.array([0, 0, 0])
    r3 = np.array([0, 1, 0])

    expected_value = 90

    calculated_value = molecool.calculate_angle(r1, r2, r3, degrees=True)

    assert pytest.approx(expected_value) == calculated_value

@pytest.mark.parametrize("p1, p2, p3, expected_angle", [
    (np.array([np.sqrt(2)/2, np.sqrt(2)/2, 0]), np.array([0, 0, 0]), np.array([1, 0, 0]), 45),
    (np.array([0, 0, -1]), np.array([0, 1, 0]), np.array([1, 0, 0]), 60  ),
    (np.array([np.sqrt(3)/2, (1/2), 0]), np.array([0, 0, 0]), np.array([1, 0, 0]), 30),
])
def test_calculate_angle_many(p1, p2, p3, expected_angle):

    calculated_angle = molecool.calculate_angle(p1, p2, p3, degrees=True)

    assert expected_angle == pytest.approx(calculated_angle), F'{calculated_angle} {expected_angle}'


# https://www.hackerrank.com/challenges/np-eye-and-identity/problem

# Inputs
standard_input = """3 3"""

import numpy

shape = [int(s) for s in input().split()]

numpy.set_printoptions(legacy="1.13")
print(numpy.eye(*shape))

""" Using RegEx
import re
print(re.sub(r"(\d\.)", r" \1", str(numpy.eye(*shape))))
"""

# [[ 1.  0.  0.]
#  [ 0.  1.  0.]
#  [ 0.  0.  1.]]

""" Reference

print(numpy.identity(3))
# 3 is for  dimension 3 X 3

# Output
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

print(numpy.eye(5, 4, k=1))
# 5 X 4 Dimensional array with first upper diagonal 1.

# [[0. 1. 0. 0.]
#  [0. 0. 1. 0.]
#  [0. 0. 0. 1.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]

print(numpy.eye(5, 4, k=-2))
# 5 X 4 Dimensional array with second lower diagonal 1.

# [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [1. 0. 0. 0.]
#  [0. 1. 0. 0.]
#  [0. 0. 1. 0.]]

"""

__Training__/Python - HackerRank/16. Numpy/Eye and Identity.py


import jax
import jax.numpy as jnp

rng = jax.random.PRNGKey(43)

def gradient_descent(A, b, iters=1000, tol=1e-8, debug=False):

    n = A.shape[0]

    x = jax.random.uniform(rng, shape=(n, 1))
    r = b - A @ x

    i = 0

    while i < iters and jnp.linalg.norm(A @ x - b) > tol:
        if debug:
            print( f"{i} th iter, err {jnp.linalg.norm(A @ x - b)}" )

        Ar = A @ r
        tau = r.T @ r / ( r.T @ Ar )
        x += tau * r
        r-= tau * Ar

        i += 1

    return x

def positive_definite(n):
    A = jax.random.uniform(rng, shape=(n, n))
    A = A @ A.T
    return A

n = 4
A = positive_definite(n)
b = jax.random.uniform(rng, shape=(n, 1))

x = gradient_descent(A, b)

assert( jnp.linalg.norm(A @ x - b) < 1e-2 )


import numpy as np
from scipy import linalg
import matplotlib.pyplot as plt

class LM:
  def __init__(self, y, X = None, verbose = False):
    ### process arguments
    self.y = y
    self.n = len(y)

    if X is None:
      X = np.ones(self.n).reshape(self.n, 1)
    self.X = X
    self.p = X.shape[1]
    self.verbose = verbose

    ### others
    self.fitted = False

    self.beta_hat = None
    self.y_hat = None
    self.residuals = None

  def fit(self):
    ### estimate model parameters
    # beta = (X'X)^(-1) X' y
    self.beta_hat = np.linalg.inv(self.X.transpose().dot(self.X)).dot(self.X.transpose().dot(self.y))

    self.y_hat = self.X.dot(self.beta_hat)
    self.residuals = self.y - self.y_hat

    self.fitted = True

  def __repr__(self):
    line_dim = ' -- ' + str(self.n) + ' observations, ' + str(self.p) + ' predictors\n'

    if self.fitted == False:
      return 'Linear Model (not fitted yet)\n' + line_dim
    else:
      line_beta = ' -- beta: ' + str(mod.beta_hat.transpose())
      return 'Liner Model (fitted)\n' + line_dim + line_beta

  def plot(self, type = 1):
    if type == 1:
      self.plotRes()

  def plotRes(self):
    fig = plt.figure()

    plt.scatter(self.y_hat, self.residuals, figure = fig)
    plt.xlabel('Fitted values')
    plt.ylabel("Residuals")
    plt.title("Linear Model")
    plt.axhline(0)

    fig.show()

#-------------
# Tests
#-------------

def sim_dat1(n = 100, beta = [3, 2, 1]):
  np.random.seed(1)

  x0 = np.ones(n).reshape((n, 1))
  x1 = np.random.normal(loc = 0, scale = 2, size = n).reshape((n, 1))
  x2 = np.matrix(np.random.normal(loc = 0, scale = 1, size = n)).reshape((n, 1))

  X = np.concatenate((x0, x1, x2), 1)

  b = np.array(beta).reshape((3, 1))
  error = np.random.normal(scale = 2, size = n).reshape((n, 1))

  y = X.dot(b) + error

  return(y, X)

def main():
  print ' * test `sim_dat1`:'
  (y, X) = sim_dat1()
  mod = LM(y, X)
  mod.fit()

if __name__ == '__main__': main()

(y, X) = sim_dat1()
mod = LM(y, X)
mod.fit()


# %%
"""In this code we wanna calculate determinant of matrix."""
import numpy as np
# %%
help(np.linalg.det)
# %%
a = np.arange(1, 5).reshape((2, 2))
a
# %%
np.linalg.det(a)
# %%
round(np.linalg.det(a))
# %%
b = np.arange(1, 10).reshape((3, 3))
b
# %%
np.linalg.det(b)
# %%
round(np.linalg.det(b))


import numpy as np

check = "rmse"
#check = "pearson"

def correl(X,Y):
    N, = X.shape

    if N < 9:
        print "not enough points. {} datapoints given. at least 9 is required".format(n)
        return

    r = np.corrcoef(X,Y)[0][1]
    r_sig = 1.96/np.sqrt(n-2+1.96**2)
    F_plus = 0.5*np.log((1+r)/(1-r))+r_sig
    F_minus = 0.5*np.log((1+r)/(1-r))-r_sig
    le = r - (np.exp(2*F_minus)-1)/(np.exp(2*F_minus)+1)
    ue = (np.exp(2*F_plus)-1)/(np.exp(2*F_plus)+1) - r

    return r, le, ue

def rmse(X, Y):
    """
    Root-Mean-Square Error

    Lower Error = RMSE \left( 1- \sqrt{ 1- \frac{1.96\sqrt{2}}{\sqrt{N-1}} }  \right )
    Upper Error = RMSE \left(    \sqrt{ 1+ \frac{1.96\sqrt{2}}{\sqrt{N-1}} } - 1 \right )

    This only works for N >= 8.6832, otherwise the lower error will be
    imaginary.

    Parameters:
    X -- One dimensional Numpy array of floats
    Y -- One dimensional Numpy array of floats

    Returns:
    rmse -- Root-mean-square error between X and Y
    le -- Lower error on the RMSE value
    ue -- Upper error on the RMSE value
    """

    N, = X.shape

    if N < 9:
        print "Not enough points. {} datapoints given. At least 9 is required".format(N)
        return

    diff = X - Y
    diff = diff**2
    rmse = np.sqrt(diff.mean())

    le = rmse * (1.0 - np.sqrt(1-1.96*np.sqrt(2.0)/np.sqrt(N-1)))
    ue = rmse * (np.sqrt(1 + 1.96*np.sqrt(2.0)/np.sqrt(N-1))-1)

    return rmse, le, ue

def mae(X, Y):
    """
    Mean Absolute Error (MAE)

    Lower Error =  MAE_X \left( 1- \sqrt{ 1- \frac{1.96\sqrt{2}}{\sqrt{N-1}} }  \right )
    Upper Error =  MAE_X \left(  \sqrt{ 1+ \frac{1.96\sqrt{2}}{\sqrt{N-1}} }-1  \right )

    Parameters:
    X -- One dimensional Numpy array of floats
    Y -- One dimensional Numpy array of floats

    Returns:
    mae -- Mean-absolute error between X and Y
    le -- Lower error on the MAE value
    ue -- Upper error on the MAE value
    """

    N, = X.shape

    mae = np.abs(X - Y)
    mae = mae.mean()

    le =  mae * (1 - np.sqrt(1 - 1.96*np.sqrt(2)/np.sqrt(N-1) ) )
    ue =  mae * (    np.sqrt(1 + 1.96*np.sqrt(2)/np.sqrt(N-1) ) -1 )

    return mae, le, ue

def me(X, Y):
    """
    mean error (ME)

    L_X = U_X =  \frac{1.96 s_N}{\sqrt{N}}
    where sN is the standard population deviation (e.g. STDEVP in Excel).

    Parameters:
    X -- One dimensional Numpy array of floats
    Y -- One dimensional Numpy array of floats

    Returns:
    mae -- Mean error between X and Y
    e   -- Upper and Lower error on the ME
    """

    N, = X.shape

    error = X - Y
    me = error.mean()

    s_N = stdevp(error, me, N)
    e = 1.96*s_N/np.sqrt(N)

    return me, e

def stdevp(X, X_hat, N):
    """
    Parameters:
    X -- One dimensional Numpy array of floats
    X_hat -- Float
    N -- Integer

    Returns:

    Calculates standard deviation based on the entire population given as
    arguments. The standard deviation is a measure of how widely values are
    dispersed from the average value (the mean).
    """
    return np.sqrt(np.sum((X-X_hat)**2)/N)

if __name__ == '__main__':

    import sys
    import numpy as np

    import matplotlib.pyplot as plt

    if len(sys.argv) < 2:
        exit("usage: python example.py example_input.csv")

    filename = sys.argv[1]
    f = open(filename, "r")
    data = np.genfromtxt(f, delimiter=',', names=True)
    f.close()

    try:
        ref = data['REF']
    except:
        ref = data['\xef\xbb\xbfREF']
    n = len(ref)

    methods = data.dtype.names
    methods = methods[1:]
    nm = len(methods)

    rmse_list = []
    rmse_lower = []
    rmse_upper = []

    mae_list = []
    mae_lower = []
    mae_upper = []

    me_list = []
    me_lower = []
    me_upper = []

    r_list = []
    r_lower = []
    r_upper = []

    for method in methods:
        mdata = data[method]

        # RMSE
        mrmse, mle, mue = rmse(mdata, ref)
        rmse_list.append(mrmse)
        rmse_lower.append(mle)
        rmse_upper.append(mue)

        # MAD
        mmae, maele, maeue = mae(mdata, ref)
        mae_list.append(mmae)
        mae_lower.append(maele)
        mae_upper.append(maeue)

        # ME
        mme, mmee = me(mdata, ref)
        me_list.append(mme)
        me_lower.append(mmee)
        me_upper.append(mmee)

        # r
        r, rle, rue = correl(mdata, ref)
        r_list.append(r)
        r_lower.append(rle)
        r_upper.append(rue)

    print "Method_A   Method_B      RMSE_A   RMSE_B   RMSE_A-RMSE_B  Comp Err  same?"
    ps = "{:10s} "*2 +  "{:8.3f} "*2 + "{:8.3f}" + "{:15.3f}" + "     {:}"

    if check == "pearson":
        measure = r_list
        upper_error = r_upper
        lower_error = r_lower
    else:
        measure = rmse_list
        upper_error = rmse_upper
        lower_error = rmse_lower
        # measure = mae_list
        # upper_error = mae_upper
        # lower_error = mae_lower

    for i in xrange(nm):
        for j in xrange(i+1, nm):

            m_i = methods[i]
            m_j = methods[j]

            rmse_i = measure[i]
            rmse_j = measure[j]

            r_ij = np.corrcoef(data[m_i], data[m_j])[0][1]

            if rmse_i > rmse_j:
                lower = lower_error[i]
                upper = upper_error[j]
            else:
                lower = lower_error[j]
                upper = upper_error[i]

            comp_error = np.sqrt(upper**2 + lower**2 - 2.0*r_ij*upper*lower)
            significance = abs(rmse_i - rmse_j) < comp_error

            print ps.format(m_i, m_j, rmse_i, rmse_j, rmse_i-rmse_j, comp_error, significance)

    print
    print "\\begin{table}[]"
    print "\centering"
    print "\caption{}"
    print "\label{}"
    print "\\begin{tabular}{l" + nm*"c" + "}"
    print "\midrule"
    print "& " + " & ".join(methods) + "\\\\"
    print "\midrule"
#   for i in xrange(nm-1):
#       print '%.1f $\pm$ %.1f/%.1f &'%(rmse_list[i],lower_error[i],rmse_upper[i]),
#   print '%.1f $\pm$ %.1f/%.1f'%(rmse_list[-1],lower_error[-1],rmse_upper[-1])
    print "RMSE & " + " & ".join(format(x, "3.1f") for x in rmse_list) + "\\\\"

    temp_list = [ i+"/"+j for i,j in zip([format(x, "3.1f") for x in rmse_upper],[format(x, "3.1f") for x in rmse_lower])]
    print "95 \% conf & $\pm$ " + " & $\pm$ ".join(temp_list) + "\\\\"

    temp_list = [ i+" $\pm$ "+j for i,j in zip([format(x, "3.1f") for x in me_list],[format(x, "3.1f") for x in me_upper])]
    print "ME & " + " & ".join(temp_list) + "\\\\"

    print "$r$ & " + " & ".join(format(x, "3.2f") for x in r_list) + "\\\\"

    temp_list = [ i+"/"+j for i,j in zip([format(x, "3.2f") for x in r_upper],[format(x, "3.2f") for x in r_lower])]
    print "95 \% conf & $\pm$ " + " & $\pm$ ".join(temp_list) + "\\\\"

    print "\midrule"
    print "\end{tabular}"
    print "\end{table}"

    # Create x-axis
    x = range(len(methods))

    # Errorbar (upper and lower)
    asymmetric_error = [rmse_lower, rmse_upper]

    # Add errorbar for RMSE
    plt.errorbar(x, rmse_list, yerr=asymmetric_error, fmt='o')

    # change x-axis to method names and rotate the ticks 30 degrees
    plt.xticks(x, methods, rotation=30)

    # Pad margins so that markers don't get clipped by the axes
    plt.margins(0.2)

    # Tweak spacing to prevent clipping of tick-labels
    plt.subplots_adjust(bottom=0.15)

    # Add grid to plot
    plt.grid(True)

    # Set plot title
    plt.title('Root-mean-sqaure error')

    # Save plot to PNG format
    plt.savefig('example_rmsd.png')

    # Clear figure
    plt.clf()

    # MAE plot
    asymmetric_error = [mae_lower, mae_upper]
    plt.errorbar(x, mae_list, yerr=asymmetric_error, fmt='o')
    plt.xticks(x, methods, rotation=30)
    plt.margins(0.2)
    plt.subplots_adjust(bottom=0.15)
    plt.grid(True)
    plt.title('Mean Absolute Error')
    plt.savefig('example_mae.png')

    # Clear figure
    plt.clf()

    # ME plot
    asymmetric_error = [me_lower, me_upper]
    plt.errorbar(x, me_list, yerr=asymmetric_error, fmt='o')
    plt.xticks(x, methods, rotation=30)
    plt.margins(0.2)
    plt.subplots_adjust(bottom=0.15)
    plt.grid(True)
    plt.title('Mean Error')
    plt.savefig('example_me.png')


import math
import numpy as np

def simple_euclidean(instance1, instance2, dimension):
    distance = 0
    for dim in range(dimension):
        distance += pow((instance1[dim] - instance2[dim]), 2)
    return math.sqrt(distance)

def euclidean(instance1, instance2):
    """Vectorized implementation of Euclidean distance"""
    delta = instance1 - instance2
    return np.sqrt(np.sum(delta * delta))

def weighted_euclidean(instance1, instance2, weights):
    delta = instance1 - instance2
    return np.sqrt((np.sum(weights * (delta * delta))))


from matplotlib import pyplot as plt
from math import sin, cos, radians
import numpy as np

sup_2 = '\N{SUPERSCRIPT TWO}'

def force(theta):
    m = 50
    g = 9.8
    f_press = 350
    return 0.2 * m * g * sin(radians(theta)) * sin(radians(theta)) + f_press * cos(radians(90 - theta))

x = np.linspace(45, 90, 100)
y = []
for i in x:
    y.append(force(i))

plt.title('By pedaling on the starting block with same force\n'
          'how much forward force (parallel to the ground) I can get\n'
          'by setting starting block to different angles?', fontsize=14)
plt.xlabel('degree of starting block (degree)', fontsize=14)
plt.ylabel('parallel force pointing forward\n(Newton)', fontsize=14)
plt.plot(x, y, label=f'F = 20%mg sin{sup_2}\u03b8 + Fp cos(90 - \u03b8)', color='k')

dx = [45, 60, 70, 80, 90]
dy = []
for i in dx:
    di = force(i)
    dy.append(di)
    if i == 45:
        plt.annotate(s=f'({i}, {round(di)})', xy=[i + 6, di + 20], fontsize=14)
    elif i != 90 and i != 80:
        plt.annotate(s=f'({i}, {round(di)})', xy=[i + 2, di], fontsize=14)
    elif i == 80:
        plt.annotate(s=f'({i}, {round(di)})', xy=[i - 8, di + 4], fontsize=14)
    else:
        plt.annotate(s=f'({i}, {round(di)})', xy=[i - 7, di - 14], fontsize=14)

plt.scatter(dx, dy, color='k', linewidths=3)
plt.legend(fontsize=14, loc='lower right')
plt.tight_layout()
plt.show()


from math import sqrt

from scipy.stats import t
from numpy import mean

def degrees_of_freedom(s1, s2, n1, n2):
    """
    Compute the number of degrees of freedom using the Satterhwaite Formula

    @param s1 The unbiased sample variance of the first sample
    @param s2 The unbiased sample variance of the second sample
    @param n1 Thu number of observations in the first sample
    @param n2 The number of observations in the second sample
    """
    numerator = (s1**2/n1 + s2**2/n2)**2
    denominator = ((s1**2/n1)**2)/(n1-1) + ((s2**2/n2)**2)/(n2-1)

    degrees_of_freedom = numerator/denominator

    return degrees_of_freedom

def unbiased_sample_variance(observations, mean):
    """
    Compute the unbiased sample variance
    http://mathworld.wolfram.com/SampleVariance.html

    @param observations Iterable set of observations
    @param mean The estimated mean
    """
    inner_sum = 0
    for x in observations:
        inner_sum += (x-mean)**2

    coefficient = 1/(len(observations)-1)
    unbiased_sample_variance = coefficient * inner_sum

    return unbiased_sample_variance

def t_statistic(mean1, mean2, n1, n2, svar1, svar2):
    """
    Compute the t-statistic for the given estimates
    http://beheco.oxfordjournals.org/content/17/4/688.full
    """
    #Complete this function
    numerator = mean1-mean2
    denominator = sqrt(svar1/n1+svar2/n2)

    t_statistic = numerator/denominator
    #test statistic, 110, 111, 114, 116, 118,124, 211
    return t_statistic

def t_test(sample1, sample2):
    """
    Return the p-value of a t test with unequal variance for two samples.

    @param sample1 An iterable of the first sample
    @param sample2 An iterable of the second sample
    ***http://formulas.tutorvista.com/math/t-test-formula.html***
    """

    #standard deviation
    #num_items1 = len(sample1)
    mean1 = sum(sample1)/len(sample1)
    differences1 = [x - mean1 for x in sample1]
    sq_differences1 = [d ** 2 for d in differences1]
    sd1 = sum(sq_differences)

    mean2 = sum(sample2)/len(sample2)
    differences2 = [y - mean2 for y in sample2]
    sq_differences2 = [e ** 2 for e in differences2]
    sd2 = sum(sq_differences2)

    n1 = len(sample1)
    n2 = len(sample2)

    numerator = mean1 - mean2
    denominator = sqrt((sd1)**2/n1 + (sd2)**2/n2)

    t = numerator/denominator

    p = t**2

    return p

if __name__ == "__main__":
    v1 = [5, 7, 5, 3, 5, 3, 3, 9]
    v2 = [8, 1, 4, 6, 6, 4, 1, 2]

    print("p-value is %f" % t_test(v1, v2))


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

T = 200
h = 1e-2
t = np.arange(start=0, stop=T + h, step=h)

bet, gam = 0.15, 1 / 50
# todo: zmienic poziej na randoma
# S_pocz = np.random.uniform(0.7, 1)
S_start = 0.8
I_start = 1 - S_start
R_start = 0
N = S_start + I_start + R_start  # is const

# using odeint
# ---------------------------------------------------------------------------------------------------------------------#
def two_diff_ode_equation(state, t, bet, gam):
    S, I = state
    return [- bet * I * S / N, bet * I * S / N - gam * I]

def one_diff_equation_ode(state, t, bet, gam):
    S = state[0]
    C = I_start - gam / bet * np.log(S_start) + S_start  # C - const
    return [(-bet / N * S * (gam / bet * np.log(S) - S + C))]

def calc_R(S_arr, I_arr):
    R_arr = np.zeros(len(t))
    for i in range(len(R_arr)):
        R_arr[i] = N - S_arr[i] - I_arr[i]
    return R_arr

def calc_I(S_arr):
    C = I_start - gam / bet * np.log(S_start) + S_start  # C - const
    I_arr = np.zeros(len(t))
    for i in range(len(I_arr)):
        I_arr[i] = gam / bet * np.log(S_arr[i]) - S_arr[i] + C
    return I_arr

def two_equation_ode_plot(t, sym, labelt='$t$', labels=['S', 'I', 'R']):
    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 4))

    # plot drawing (S, I)
    for i in range(len(labels) - 1):
        ax.plot(t, sym[:, i], label=labels[i])
    # plot drawing (R)
    ax.plot(t, calc_R(sym[:, 0], sym[:, 1]), label=labels[2])

    ax.set_xlabel(labelt, fontsize=14)
    ax.set_ylabel('stan', fontsize=14)
    ax.set_ylim([0, 1])
    ax.legend()
    plt.show()

def one_equation_ode_plot(t, sym, labelt='$t$', labels=['S', 'I', 'R']):
    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 4))

    # plot drawing (S)
    ax.plot(t, sym[:, 0], label=labels[0])
    # plot drawing (I)
    I_arr = calc_I(sym[:, 0])
    ax.plot(t, I_arr, label=labels[2])
    # plot drawing (R)
    ax.plot(t, calc_R(sym[:, 0], I_arr), label=labels[2])

    ax.set_xlabel(labelt, fontsize=14)
    ax.set_ylabel('stan', fontsize=14)
    ax.set_ylim([0, 1])
    ax.legend()
    plt.show()

def two_equation_ode_main():
    start_state = S_start, I_start
    sym = odeint(two_diff_ode_equation, start_state, t, args=(bet, gam))
    two_equation_ode_plot(t, sym, labels=['S', 'I', 'R'])

def one_equation_ode_main():
    start_state = S_start
    sym = odeint(one_diff_equation_ode, start_state, t, args=(bet, gam))
    one_equation_ode_plot(t, sym, labels=['S', 'I', 'R'])

# using manual
# ---------------------------------------------------------------------------------------------------------------------#
S = np.zeros(len(t))
S[0] = S_start
I = np.zeros(len(t))
I[0] = I_start
R = np.zeros(len(t))
R[0] = R_start

def two_diff_equation_manual():
    for i in range(t.size - 1):
        S[i + 1] = S[i] + h * (- bet * I[i] * S[i] / N)
        I[i + 1] = I[i] + h * (bet * I[i] * S[i + 1] / N - gam * I[i])
        R[i + 1] = N - S[i + 1] - I[i + 1]

def one_diff_equation_manual():
    C = I_start - gam / bet * np.log(S_start) + S_start  # C - const
    for i in range(t.size - 1):
        S[i + 1] = S[i] + h * (-bet / N * S[i] * (gam / bet * np.log(S[i]) - S[i] + C))
        I[i + 1] = gam / bet * np.log(S[i + 1]) - S[i + 1] + C
        R[i + 1] = N - S[i + 1] - I[i + 1]

def equation_man_plot(t, sirList, labelt='$t$', labels=['S', 'I', 'R']):
    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 4))
    # plot drawing (R, S, I)
    for i in range(len(sirList)):
        ax.plot(t, sirList[i], label=labels[i])
    ax.set_xlabel(labelt, fontsize=14)
    ax.set_ylabel('stan', fontsize=14)
    ax.set_ylim([0, 1])
    ax.legend()
    plt.show()

def two_equation_man_main():
    two_diff_equation_manual()
    equation_man_plot(t, [S, I, R], labels=['S', 'I', 'R'])

def one_equation_man_main():
    one_diff_equation_manual()
    equation_man_plot(t, [S, I, R], labels=['S', 'I', 'R'])

if __name__ == "__main__":
    # one_equation_ode_main()
    # one_equation_man_main()
    # two_equation_ode_main()
    two_equation_man_main()
    exit(0)


import numpy as np
import math

def dim(v) -> int:
    """ 获取向量维度. """
    return len(v)

def vec(val):
    """ 数值向量化. """
    return np.array(val, dtype=np.float)

def dist(pos0, pos1=None) -> float:
    """ 计算向量距离（模）. """
    pos = (vec(pos0) - vec(pos1)) if pos1 is not None else vec(pos0)
    return np.linalg.norm(pos)

def unit(v):
    """ 计算单位向量. """
    v2 = vec(v)
    d = dist(v2)
    return (v2 / d) if d > 0.0 else zeros_like(v2)

def zeros_like(v):
    """ 生成全零向量. """
    return np.zeros_like(vec(v))

def angle(v1, v2) -> float:
    """ 计算向量夹角.
    """
    d1, d2 = dist(v1), dist(v2)
    if d1 <= 0.0 or d2 <= 0.0:
        return 0.0
    ret = math.acos(np.dot(v1, v2) / (d1 * d2))
    return math.degrees(ret)

def trans(v, *args):
    """ 坐标变换.
    对向量 v 依次用进行 m1, m2, ... 变换.

    :param v: 被变换向量.
    :param args: m1, m2, ...
    :return: 变换后的向量.
    """
    ret = v.copy()
    for m in args:
        mx = m.getA() if isinstance(m, np.matrix) else m
        ret = np.dot(mx, ret)
    return vec(ret)


import numpy as np

''' By hand '''
x = np.arange(0.1, 1.1, 0.1)
y = 5 * np.exp(-x) + 2 * x

# Reshape x and y to obtain 2D vectors
# We want a linear trend, so y = b1 + b2x = Xb
# If b = [b1, b2], then X should be [[1, x_0], [1, x_1], ...]
X = np.ones((len(x), 2))
X[:,1] = x

Y = y.reshape((len(y), 1))

# Solve using b = (XTX)^-1XTY
XTXi = np.linalg.inv(X.T @ X)
XTY = X.T @ Y
b = XTXi @ XTY

# Print the result
print(b)

''' Using np.linalg '''
x = np.arange(0, 1.1, 0.1)
y = 5 * np.exp(-x) + 2 * x

X = np.ones((len(x), 2))
X[:,1] = x
Y = y.reshape((len(y), 1))

print(np.linalg.lstsq(X, Y))


# A neural network implementation.

import numpy as np

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

def softmax(logits):
    exponentials = np.exp(logits)
    return exponentials / np.sum(exponentials, axis=1).reshape(-1, 1)

def sigmoid_gradient(sigmoid):
    return np.multiply(sigmoid, (1 - sigmoid))

def loss(Y, y_hat):
    return -np.sum(Y * np.log(y_hat)) / Y.shape[0]

def prepend_bias(X):
    return np.insert(X, 0, 1, axis=1)

def forward(X, w1, w2):
    h = sigmoid(np.matmul(prepend_bias(X), w1))
    y_hat = softmax(np.matmul(prepend_bias(h), w2))
    return (y_hat, h)

def back(X, Y, y_hat, w2, h):
    w2_gradient = np.matmul(prepend_bias(h).T, (y_hat - Y)) / X.shape[0]
    w1_gradient = np.matmul(prepend_bias(X).T, np.matmul(y_hat - Y, w2[1:].T)
                            * sigmoid_gradient(h)) / X.shape[0]
    return (w1_gradient, w2_gradient)

def classify(X, w1, w2):
    y_hat, _ = forward(X, w1, w2)
    labels = np.argmax(y_hat, axis=1)
    return labels.reshape(-1, 1)

def initialize_weights(n_input_variables, n_hidden_nodes, n_classes):
    w1_rows = n_input_variables + 1
    w1 = np.random.randn(w1_rows, n_hidden_nodes) * np.sqrt(1 / w1_rows)

    w2_rows = n_hidden_nodes + 1
    w2 = np.random.randn(w2_rows, n_classes) * np.sqrt(1 / w2_rows)

    return (w1, w2)

def report(iteration, X_train, Y_train, X_test, Y_test, w1, w2):
    y_hat, _ = forward(X_train, w1, w2)
    training_loss = loss(Y_train, y_hat)
    classifications = classify(X_test, w1, w2)
    accuracy = np.average(classifications == Y_test) * 100.0
    print("Iteration: %5d, Loss: %.8f, Accuracy: %.2f%%" %
          (iteration, training_loss, accuracy))

def train(X_train, Y_train, X_test, Y_test, n_hidden_nodes, iterations, lr):
    n_input_variables = X_train.shape[1]
    n_classes = Y_train.shape[1]
    w1, w2 = initialize_weights(n_input_variables, n_hidden_nodes, n_classes)
    for iteration in range(iterations):
        y_hat, h = forward(X_train, w1, w2)
        w1_gradient, w2_gradient = back(X_train, Y_train, y_hat, w2, h)
        w1 = w1 - (w1_gradient * lr)
        w2 = w2 - (w2_gradient * lr)
        report(iteration, X_train, Y_train, X_test, Y_test, w1, w2)
    return (w1, w2)


from copy import deepcopy

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

from scipy import stats
import statsmodels.api as sm
from statsmodels.regression.linear_model import OLS
from statsmodels.stats.outliers_influence import OLSInfluence

def min_max_to_real(x):
        mn = min(x)-1
        mx = max(x)+1
        x = (x-mn)/(mx-mn)
        x = x/(1-x)
        return np.log(x)

def mode(x):
        return stats.mode(x)[0][0]

def mode_val(x):
        return stats.mode(x)[1][0]

class Reg(object):
    def __init__(self, df):
        self.df = df
        self.n = df.shape[0]
        self.p = df.shape[1]
        self.fontsize = 30

    def describe(self):
        x = self.df
        idx = x.columns
        ret = pd.DataFrame(index = idx)
        foos = {'mean':np.mean, 'median':np.median, 'mode':mode, 'std':np.std, 'skew':stats.skew,
                'kurt':stats.kurtosis, 'min':min, '25%':np.quantile, '75%':np.quantile, 'max':max}
        for new_col, foo in foos.items():
            items = []
            for col in idx:
                if foo != mode :
                    if x[col].dtype == 'O':
                        items.append(np.nan)
                        continue
                if new_col == '25%' :
                    items.append(foo(x[col], 0.25))
                elif new_col == '75%':
                    items.append(foo(x[col], 0.75))
                else :
                    items.append(foo(x[col]))
            ret[new_col] = items
        self.description = ret
        print(x.shape)

    def show_before_reg(self, is_corr=None, is_single= None, is_pair = None, print_corr = None, cols = None):
        if cols is None : cols = self.df.columns
        if is_pair is not None :
            sns.pairplot(self.df[cols])
            plt.show()

        if is_corr is not None :
            fig = plt.figure(figsize=(17,8))
            corr = self.df[cols].corr()
            sns.heatmap(corr)
            plt.show()

        if print_corr is not None :
            print(corr)

        if is_single is not None :
            for x in cols :
                fig = plt.figure(figsize=(17,8))
                sns.distplot(self.df[x])
                plt.show()

    def regression(self, y_col, x_cols, reg_foo = sm.OLS, is_constant=None):
        model_x = self.df[x_cols].values
        if is_constant is not None :
            model_x = sm.add_constant(model_x)
        model_y = self.df[y_col].values
        model = reg_foo(model_y, model_x).fit()
        temp = deepcopy(self)
        temp.model = model
        temp.model_property = (y_col, x_cols, is_constant, reg_foo)
        temp.coef = model._results.params
        temp.resid = model.resid
        temp.std_resid = model.resid_pearson
        temp.pred = model.predict(model_x)
        temp.p = len(x_cols)
        return temp

    def show_after_reg(self, leverage):
        self.show_qq_plot()
        self.show_pred_resid_plot()
        self.show_index_resid_plot()
        for x in self.model_property[1]:
            self.show_reg_line(x, leverage)
            self.show_resid_plot(x)

    def show_reg_line(self, x, leverage, scatter=True):
        fontsize = self.fontsize
        y = self.model_property[0]

        fig = plt.figure(figsize=(17,8))

        sns.regplot(x, y, data = self.df, scatter=scatter)

        plt.xlabel('{}'.format(x), fontdict={'fontsize': fontsize,})
        plt.ylabel('{}'.format(y), fontdict={'fontsize': fontsize,})
        plt.title('Regression Line : {}'.format(x), fontdict={'fontsize': fontsize,})
        plt.show()

    def show_qq_plot(self):
        fontsize = self.fontsize
        resid = self.std_resid
        fig = plt.figure(figsize=(17,8))
        stats.probplot(resid, plot=plt)
        plt.xlabel('Standard Residual', fontdict={'fontsize': fontsize,})
        plt.title('Q-Q Plot', fontdict={'fontsize': fontsize,})
        plt.show()

    def show_pred_resid_plot(self):
        fontsize = self.fontsize
        x, y = self.pred, self.std_resid
        fig = plt.figure(figsize=(17,8))
        sns.scatterplot(x,y)
        sns.lineplot(x, 0, color='red')

        q1 = np.quantile(y, .25)
        q3 = np.quantile(y, .75)
        iqr = q3-q1
        q1 -= iqr*1.5
        q3 += iqr*1.5
        sns.lineplot(x, q1, color='red')
        sns.lineplot(x, q3, color='red')

        plt.xlabel('Y hat', fontdict={'fontsize': fontsize,})
        plt.ylabel('Standard Residual', fontdict={'fontsize': fontsize,})
        plt.title('Y_hat ~ Residual Plot', fontdict={'fontsize': fontsize,})
        plt.show()

    def show_index_resid_plot(self):
        fontsize = self.fontsize
        x, y = self.df.index, self.std_resid

        fig = plt.figure(figsize=(17,8))
        sns.scatterplot(x, y)
        sns.lineplot(x, 0, color='red')
        plt.xlabel('Index', fontdict={'fontsize': fontsize,})
        plt.ylabel('Standard Residual', fontdict={'fontsize': fontsize,})
        plt.title('Index ~ Residual Plot', fontdict={'fontsize': fontsize,})
        plt.show()

    def show_resid_plot(self, x):
        fontsize = self.fontsize
        fig = plt.figure(figsize=(17,8))
        plt.xlabel('{}'.format(x), fontdict={'fontsize': fontsize,})
        plt.ylabel('Standard Residual', fontdict={'fontsize': fontsize,})
        plt.title('{} ~ Residual Plot'.format(x), fontdict={'fontsize': fontsize,})
        x, y = self.df[x], self.std_resid

        sns.scatterplot(x, y)
        sns.lineplot(x, 0, color='red')

        plt.show()

    def find_outlier(self):
        y = self.std_resid
        q1 = np.quantile(y, .25)
        q3 = np.quantile(y, .75)
        iqr = q3-q1
        q1 -= iqr*1.5
        q3 += iqr*1.5

        outlier = (y<q1)|(y>q3)

        influence = self.model.get_influence()
        outlier += OLSInfluence.cooks_distance(influence)[0]>1
        diffits = 2*np.sqrt((self.p+1)/(self.n-self.p-1))
        outlier += OLSInfluence.dffits(influence)[0]<-diffits
        outlier += OLSInfluence.dffits(influence)[0]>diffits

        self.non_outlier = (outlier<1)

    def remove_outlier(self):
        ret = deepcopy(self)
        ret.df = self.df[self.non_outlier]
        y,x,c,r = self.model_property
        return ret.regression(y_col = y, x_cols = x, is_constant = c, reg_foo=r)

    def show_eda(self, x, y=None):
        fig = plt.figure(figsize=(17,8))
        x = self.df[x]
        if y is None :
            sns.distplot(x)
        else :
            y = self.df[y]
            sns.scatter(x,y)
            plt.ylabel(y, fontdict={'fontsize':fontsize})
        plt.xlabel(x, fontdict={'fontsize' : fontsize})
        plt.show()

import numpy,from scipy,import statsmodels,from statsmodels


"""
Author : Achintya Gupta
Date Created : 22-09-2020
"""

"""
Problem Statement
------------------------------------------------
Q)  The sum of the squares of the first ten natural numbers is, 385
    The square of the sum of the first ten natural numbers is, 3025
    Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is . 2640
    Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
"""
from utils import timing_decorator, find_factors
import numpy as np

@timing_decorator
def find_min_prod(N=100):
    prod = ((N)*(N+1))/2
    prod *= (3*(N**2) - N -2)/6
    print(f'Difference between the sum of the squares of the first {N} natural numbers and the square of the sum: {prod}')

find_min_prod()


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

def solve_sirgm(S_i=210_000_000., I_i=2200., R_i=100., G_i=0, M_i=0,
                beta=0.16, mu=14, gamma=0.01, sigma=0.09, theta=0.01,
                dias=365, N=24):
    """Plot a solution to the SIRGM differential equations."""

    def sir_deriv(sirgm, t0, beta=beta, mu=mu):
        """Compute the time-derivative of a SIRGM system."""
        s, i, r, g, m = sirgm
        n = s + i + r
        return [
            -beta * i * s/n,
            beta * i * s/n - i/mu - gamma*i,
            i/mu + sigma * g,
            gamma * i - sigma * g - theta * g,
            theta * g,
        ]

    t = np.linspace(0,dias,int(N*dias))
    sirgm = integrate.odeint(sir_deriv, (S_i, I_i, R_i, G_i, M_i), t)
    fig,ax = plt.subplots()
    ax.stackplot(t, sirgm[:,1], sirgm[:,3], sirgm[:,4], sirgm[:,0], sirgm[:,2],
                 labels=('Infecciosos', 'Graves', 'Mortos', 'Suscetíveis', 'Recuperados'))
    ax.set_xlabel('Dias')
    ax.set_ylabel('Pessoas')
    ax.set_title(f'Modelo SIRGM, R₀={beta*mu:.3}')
    l = ax.legend()
    print(f'Mortos:{int(sirgm[-1,4]):,}')
    print(f'Demanda por UTI:{int(max(sirgm[:,3])):,}')
    return t, sirgm


from sympy import Matrix, pprint

M = Matrix( [
	[	1,		0,	1, 0, 0, 0, 0, 0, 3 ],
	[	0,		1,	0, 1, 0, 0, 0, 0, 4 ],
	[	2,		1,	0, 0, 1, 0, 0, 0, 7 ],
	[	1,		1,	0, 0, 0, 1, 0, 0, 5 ],
	[  -1,		0,	0, 0, 0, 0, 1, 0, 0 ],
	[   0,		-1,	0, 0, 0, 0, 0, 1, 0 ],
	[-3000,	-2000,	0, 0, 0, 0, 0, 0, 0 ] ] )

pprint( M )

# Pivot 1

[ M[i,8]/M[i,0] for i in range(0,4) ]

M.row_op( 2, lambda v,j: v-2*M[ 0, j ] )
M.row_op( 3, lambda v,j: v-1*M[ 0, j ] )
M.row_op( 4, lambda v,j: v+1*M[ 0, j ] )
M.row_op( 6, lambda v,j: v+3000*M[ 0, j ] )

pprint( M )

# Pivot 2
[ M[i,8]/M[i,1] for i in range(0,4) ]

M.row_op( 1, lambda v,j: v-1*M[2,j] )
M.row_op( 3, lambda v,j: v-1*M[2,j] )
M.row_op( 5, lambda v,j: v+1*M[2,j] )
M.row_op( 6, lambda v,j: v+2000*M[2,j ] )

pprint( M )

# Pivot 3
[ M[i,8]/M[i,2] for i in range(0,4) ]

M.row_op(0, lambda v,j: v-1*M[3,j] )
M.row_op(1, lambda v,j: v-2*M[3,j] )
M.row_op(2, lambda v,j: v+2*M[3,j] )
M.row_op(4, lambda v,j: v-M[3,j] )
M.row_op(5, lambda v,j: v+2*M[3,j] )
M.row_op(6, lambda v,j: v+1000*M[3,j] )

pprint( M )


"""
Objetivo: Resolver questão 2 do quarto laboratorio.
"""

from Funcoes import LU, Gauss_Siedel
import numpy as np

A = np.array([[1.19, 2.11, -100, 1],
              [14.2, -0.122, 12.2, -1],
              [0, 100, -99.9, 1],
              [15.3, 0.11, -13.1, -1]], dtype='float16')
P = np.array([[1.12],
              [3.44],
              [2.15],
              [4.16]], dtype='float16')

#Por LU:
s = LU(A, P)
print(f'O vetor solução pelo metodo da decomposição LU é: \n{s}')
#Por Gauss-Siedel
s = Gauss_Siedel(A, P, 10)
print(f'O vetor solução pelo metodo da Gauss-Siedel é: \n{s}')
print('Como vemos, o valor deu muito distante em comparação com o outro metodo, isso ocorre porque para essa matriz',
      ' o metodo não converge.')


'''
Please see LICENSE for copyright
Author: 'Wu Li' <li.koun@gmail.com>

The implementation of logistic regression.

'''
import numpy as np

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

def costLogistic(X, y, theta, lmd):
    '''
    Cost function. The return value is a tuple contains cost and gradient descent.
    '''
    t = theta[1:]
    m = X.shape[0]
    g = sigmoid(np.dot(X, theta))
    J = (-np.dot(y, np.log(g)) - np.dot(1-y, np.log(1-g)))/m + lmd*np.dot(t,t.T)/m
    GRAD = np.dot(X.T, g-y)/m
    return (J, GRAD)

def gradientDescent(X, y, theta, lmd, iterations):
    '''
    Gradient descent
    '''
    J_hist = np.zeros(iterations)
    for i in range(iterations):
        J_hist[i], GRAD = costLogistic(X, y, theta, lmd)
        theta -= GRAD

    return (J_hist, theta)

def oneVsAll(X, y, lmd, numLabels):
    '''
    Calculates the weights for each number
    '''
    n = X.shape[1]
    allTheta = np.zeros((n, numLabels))
    Y = np.eye(10)[y.astype(int),:]
    for i in range(numLabels):
        theta = np.ones(n)
        J_hist, theta = gradientDescent(X, Y[:,i], theta, lmd, 100)
        allTheta[:,i] = theta

    return allTheta

def predict (X, allTheta):
    '''
    Predict
    '''
    V = sigmoid(np.dot(X, allTheta))
    idx = np.argmax(V, 1)
    return idx


import numpy as np
import scipy.linalg as la
import matplotlib.pyplot as plt
from scipy.misc import derivative

#Problem 1
def newtonsMethod(f, x0, tol=1e-7, df=None):
    if df is None:
        df = lambda x: derivative(f, x, dx=1e-5)

    x = x0
    while(sp.absolute(float(f(x))/df(x)) >= tol):
        x -= float(f(x))/df(x)
    return x

#Problem 2
def Problem2():
    def f(x):
        return x**(1./3)

    return f(np.random.rand(100))

#Problem 3
def Problem3(npts=800):
    f = lambda x: x**3 - 2*x + 1./2
    df = lambda x: 3*x**2 - 2.

    x = np.random.uniform(-2, 2, size=(npts,))

    r = [newtonsMethod(f, x0, df=df) for x0 in x]
    y = f(x)

    plt.plot(x, r, '.', x, y, '.')
    plt.show()

#Problem 4
def newtonsMatrix(f, x, J=None, tol=1e-7):

#    try:
#        ndim = len(f(*inputs)), len(inputs)
#    except TypeError:
#        ndim = 1, len(inputs)
#
#    jacobian = sp.zeros(ndim)
#
#    for j in xrange(ndim[1]):
#        jacobian[:,j] = cdiff(func, inputs, vary=[j], accur=4
#        use scipy deriviative with 1e-5

	def jacobian(f, x):

		def replace( A,a,i):
			R=A.copy() #This line caused me a lot of problems
			R[i]=a
			return R

		J = np.zeros((len(x),len(x)))
		for i in range(len(x)):
			for j in range(len(x)):
				#Is there a better way to do a partial derivative?
				J[i,j] = derivative(lambda a: F(replace(x,a,i))[j],x[i])
		return J

	if J is None:
	    J = lambda x: jacobian(f, x)

	inc = la.solve(J(x), f(x))
	while(np.absolute(inc).max() >= tol):
		x -= inc
		inc = la.solve(J(x), f(x))
	return x


"""
Factory revenue optimisation using Lagrange multiplier approach

Example of constrained optimisation using a steel factory, where analysts have
worked out that revenue = 200*h^(2/3)*s^(1/3), where h is hours worked, and s
is tons of steel.  Constraints are that an hours work costs 20, and a ton of
steel is 2000.  Total budget is 20000.  Find h and s to maximise revenue.

"""

import autograd.numpy as np
from autograd import grad

def objective(X):
    h, s = X
    return 200*np.power(h,(2/3))*np.power(s,(1/3))

def constraints(X):
    h, s  = X
    return 20000-(20*h+170*s)

def F(L):
    'Augmented Lagrange function'
    h,s, _lambda = L
    return objective([h,s]) - _lambda * constraints([h,s])

# Gradients of the Lagrange function
dfdL = grad(F,0)

# Find L that returns all zeros in this function.
def obj(L):
    h,s, _lambda = L
    dFdh, dFds, dFdlam = dfdL(L)
    return [dFdh, dFds, constraints([h,s])]

from scipy.optimize import fsolve
h,s, _lam = fsolve(obj, [1, 1.0, 1.0])
print(f'The answer is at {h,s,_lam}')

print(f"Revenue is ${objective([667,39])}")


"""PageRank algorithm with explicit number of iterations.

Returns
-------
ranking of nodes (pages) in the adjacency matrix

"""

import numpy as np

from structures import Graph

def pagerank(M, num_iterations: int = 100, d: float = 0.85):
    """PageRank: The trillion dollar algorithm.

    Parameters
    ----------
    M : numpy array
        adjacency matrix where M_i,j represents the link from 'j' to 'i', such that for all 'j'
        sum(i, M_i,j) = 1
    num_iterations : int, optional
        number of iterations, by default 100
    d : float, optional
        damping factor, by default 0.85

    Returns
    -------
    numpy array
        a vector of ranks such that v_i is the i-th rank from [0, 1],
        v sums to 1

    """
    N = M.shape[1]
    v = np.random.rand(N, 1)
    v = v / np.linalg.norm(v, 1)
    M_hat = (d * M + (1 - d) / N)
    for i in range(num_iterations):
        v = M_hat @ v
    return v

def construct_pr_adj_matrix(graph: Graph, ordered_list: list):
    """
    Calculates Adjacency matrix needed for PageRank

    M[i,j] ->
                0 (if j and i are not connected)
                1 / number of outgoing links from j (if link from j to i exists)
    Sum of each column is 1.

    :param graph: graph from a PopulateStructures object
    :param ordered_list: ordered HTML files list (PopulateStructures object)
    :return: pagerank adjacent matrix
    """
    ret = np.zeros((len(ordered_list), len(ordered_list)))
    for i in range(len(ordered_list)):
        for j in range(len(ordered_list)):
            if graph.get_edge(ordered_list[j], ordered_list[i]):
                ret[i, j] = 1 / graph.degree(ordered_list[j])
    return ret


from sympy import *
from math import comb

def numerical_differentiation(function_expression, order, given_points, x):
    """ Equation can be found on https://en.wikipedia.org/wiki/Numerical_differentiation#Higher-order_methods """
    h = (given_points[-1] - given_points[0]) / len(given_points)
    variable = var("x")
    function = sympify(function_expression)
    terms = list()
    index = given_points.index(x)
    for i in range(order + 1):
        terms.append(pow(-1, i + order) * comb(order, i) * function.subs(variable, given_points[index + i * h]))
    derivative = (1 / pow(h, order)) * sum(terms)
    return "derivative of order " + str(order) + " is: {}".format(derivative)

if __name__ == '__main__':
    given_function = input("please enter a function like 2 * x + 3 * sin(x)")
    differentiation_order = int(input("please enter the order of differentiation: "))
    given_values = eval(input("please enter the values as a list like [1, 1.3413, 1.3863, 1.4032]: "))
    given_point = float(input("please enter the point x at which you want to derive at: "))
    print(numerical_differentiation(given_function, differentiation_order, given_values, given_point))


import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import pandas as pd
from sklearn.decomposition import PCA
from scipy.spatial.distance import pdist, squareform
from scipy.sparse.linalg import eigs
import csv
from sklearn import preprocessing

# Data 1
Data_1 = np.loadtxt(open('1_total_properties_0.95_6.csv', 'rb'), delimiter=",", skiprows=1)
Data_1 = preprocessing.scale(Data_1, with_std = False)

numComponents = 3
pca = PCA(n_components=numComponents)
pca.fit(Data_1)
Data_trans_1 = pca.transform(Data_1)

# Data 2
Data_2 = np.loadtxt(open('2_total_properties_0.89_11.csv', 'rb'), delimiter=",", skiprows=1)
Data_2 = preprocessing.scale(Data_2, with_std = False)

numComponents = 3
pca = PCA(n_components=numComponents)
pca.fit(Data_2)
Data_trans_2 = pca.transform(Data_2)

# Data 3
Data_3 = np.loadtxt(open('3_total_properties_0.86_4.csv', 'rb'), delimiter=",", skiprows=1)
Data_3 = preprocessing.scale(Data_3, with_std = False)

numComponents = 3
pca = PCA(n_components=numComponents)
pca.fit(Data_3)
Data_trans_3 = pca.transform(Data_3)

# Data 4
Data_4 = np.loadtxt(open('4_total_properties_0.93_6.csv', 'rb'), delimiter=",", skiprows=1)
Data_4 = preprocessing.scale(Data_4, with_std = False)

numComponents = 3
pca = PCA(n_components=numComponents)
pca.fit(Data_4)
Data_trans_4 = pca.transform(Data_4)

# 2d image
# plot
fig, axarr = plt.subplots(2, 2)
axarr[0, 0].scatter(Data_trans_1[0:5, 0], Data_trans_1[0:5, 1], c = 'r', s = 25, marker = 'x', label = '$NaCl\; 10mM,\; CaCl_2\; 3.0mM,\; MgCl_2\; 1.5mM$')
axarr[0, 0].scatter(Data_trans_1[5:10, 0], Data_trans_1[5:10, 1], c = 'g', s = 25, marker = 'x', label = '$NaCl\; 5.0mM,\; CaCl_2\; 3.0mM,\; MgCl_2\; 1.5mM$')
axarr[0, 0].scatter(Data_trans_1[10:15, 0], Data_trans_1[10:15, 1], c = 'b', s = 25, marker = 'x', label = '$NaCl\; 2.5mM,\; CaCl_2\; 3.0mM,\; MgCl_2\; 1.5mM$')

axarr[0, 1].scatter(Data_trans_2[0:5, 0], Data_trans_2[0:5, 1], c = 'r', s = 25, marker = 'x', label = '$NaHCO_3\; 10mM,\; CaCl_2\; 0.5mM,\; MgCl_2\; 0.25mM$')
axarr[0, 1].scatter(Data_trans_2[5:10, 0], Data_trans_2[5:10, 1], c = 'g', s = 25, marker = 'x', label = '$NaHCO_3\; 5.0mM,\; CaCl_2\; 0.5mM,\; MgCl_2\; 0.25mM$')
axarr[0, 1].scatter(Data_trans_2[10:15, 0], Data_trans_2[10:15, 1], c = 'b', s = 25, marker = 'x', label = '$NaHCO_3\; 2.5mM,\; CaCl_2\; 0.5mM,\; MgCl_2\; 0.25mM$')

axarr[1, 0].scatter(Data_trans_3[0:5, 0], Data_trans_3[0:5, 1], c = 'r', s = 25, marker = 'x', label = '$Na_2SO_4\; 10mM,\; CaSO_4\; 0.5mM,\; MgSO_4\; 0.25mM$')
axarr[1, 0].scatter(Data_trans_3[5:10, 0], Data_trans_3[5:10, 1], c = 'g', s = 25, marker = 'x', label = '$Na_2SO_4\; 5.0mM,\; CaSO_4\; 0.5mM,\; MgSO_4\; 0.25mM$')
axarr[1, 0].scatter(Data_trans_3[10:15, 0], Data_trans_3[10:15, 1], c = 'b', s = 25, marker = 'x', label = '$Na_2SO_4\; 2.5mM,\; CaSO_4\; 0.5mM,\; MgSO_4\; 0.25mM$')

axarr[1, 1].scatter(Data_trans_4[0:5, 0], Data_trans_4[0:5, 1], c = 'r', s = 25, marker = 'x', label = '$NaHCO_3\; 10mM,\; CaSO_4\; 0.5mM,\; MgSO_4\; 0.25mM$')
axarr[1, 1].scatter(Data_trans_4[5:10, 0], Data_trans_4[5:10, 1], c = 'g', s = 25, marker = 'x', label = '$NaHCO_3\; 5.0mM,\; CaSO_4\; 0.5mM,\; MgSO_4\; 0.25mM$')
axarr[1, 1].scatter(Data_trans_4[10:15, 0], Data_trans_4[10:15, 1], c = 'b', s = 25, marker = 'x', label = '$NaHCO_3\; 2.5mM,\; CaSO_4\; 0.5mM,\; MgSO_4\; 0.25mM$')

axarr[0, 0].set_title('$NaCl\; CaCl_2\; MgCl_2$')
axarr[0, 1].set_title('$NaHCO_3\; CaCl_2\; MgCl_2$')
axarr[1, 0].set_title('$Na_2SO_4\; CaSO_4\; MgSO_4$')
axarr[1, 1].set_title('$NaHCO_3\; CaSO_4\; MgSO_4$')

axarr[0, 0].set_yticklabels([])
axarr[0, 0].set_xticklabels([])
axarr[0, 1].set_yticklabels([])
axarr[0, 1].set_xticklabels([])
axarr[1, 0].set_yticklabels([])
axarr[1, 0].set_xticklabels([])
axarr[1, 1].set_yticklabels([])
axarr[1, 1].set_xticklabels([])

axarr[0, 0].legend(loc = 'upper right', prop={'size': 5}, labelspacing = 0, handletextpad = 0)
axarr[0, 1].legend(loc = 'upper right', prop={'size': 5}, labelspacing = 0, handletextpad = 0)
axarr[1, 0].legend(loc = 'upper right', prop={'size': 5}, labelspacing = 0, handletextpad = 0)
axarr[1, 1].legend(loc = 'upper right', prop={'size': 5}, labelspacing = 0, handletextpad = 0)

for ax in axarr.flat:
    ax.set(xlabel='PC-1', ylabel='PC-2')
for ax in axarr.flat:
    ax.label_outer()
plt.tight_layout()

fig.savefig('PCA_chemistry_2d_4_subplots.jpg', dpi = 1000)
# plt.show()


from math import pi, isclose
from functools import partial
from itertools import permutations

import hypothesis.strategies as st
from hypothesis import given
import numpy as np

from geovoronoi._geom import angle_between_pts, inner_angle_between_vecs, polygon_around_center, calculate_polygon_areas

# hypothesis generator shortcuts
real_floats = partial(st.floats, allow_nan=False, allow_infinity=False, width=32)
real_coords_2d = partial(st.lists, elements=real_floats(), min_size=2, max_size=2)

@given(a=real_coords_2d(), b=real_coords_2d())
def test_inner_angle_between_vecs(a, b):
    a = np.array(a)
    b = np.array(b)
    origin = np.array((0, 0))

    ang = inner_angle_between_vecs(a, b)

    if np.allclose(a, origin, rtol=0) or np.allclose(b, origin, rtol=0):
        assert np.isnan(ang)
    else:
        assert 0 <= ang <= pi

@given(a=real_coords_2d(), b=real_coords_2d())
def test_angle_between_pts(a, b):
    a = np.array(a)
    b = np.array(b)

    ang = angle_between_pts(a, b)

    if np.allclose(a, b, rtol=0):
        assert np.isnan(ang)
    else:
        assert 0 <= ang <= 2*pi

def test_polygon_around_center():
    points = np.array([[0, 0], [1, 0], [1, 1], [1, 0], [1, -1]])

    for perm_ind in permutations(range(len(points))):
        # many of these permutations do not form a valid polygon in that order
        # `polygon_around_center` will make sure that the order of points is correct to create a polygon around the
        # center of these points
        poly = polygon_around_center(points[perm_ind,:])

        assert poly.is_simple and poly.is_valid

def test_polygon_around_center_given_center_is_one_of_points():
    points = np.array([[0, 0], [1, 0], [1, 1], [1, 0], [0.5, 0.5]])

    for perm_ind in permutations(range(len(points))):
        # many of these permutations do not form a valid polygon in that order
        # `polygon_around_center` will make sure that the order of points is correct to create a polygon around the
        # center of these points
        poly = polygon_around_center(points[perm_ind,:], center=(0.5, 0.5))

        assert poly.is_simple and poly.is_valid

def test_calculate_polygon_areas_empty():
    areas = calculate_polygon_areas([])
    assert len(areas) == 0

def test_calculate_polygon_areas_world():
    import geopandas as gpd

    world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
    world = world[world.continent != 'Antarctica'].to_crs(epsg=3395)  # meters as unit!

    areas = calculate_polygon_areas(world.geometry)

    assert len(areas) == len(world)
    assert all(0 <= a < 9e13 for a in areas)

    areas_km2 = calculate_polygon_areas(world.geometry, m2_to_km2=True)
    assert len(areas_km2) == len(world)
    assert all(isclose(a_m, a_km * 1e6) for a_m, a_km in zip(areas, areas_km2))


import numpy as np
import pandas as pd
from scipy.stats import norm

def forward_valueBS(spot, rate, maturity, strike):

    return spot - np.exp(-rate*maturity)*strike

def option_priceBS(spot, strike, rate, maturity, volatility, flag = 1):

    d_plus = (1/volatility*(np.sqrt(maturity)))*(np.log(spot/strike) + (rate + (volatility**2)/2)*maturity)
    d_minus = d_plus - volatility*np.sqrt(maturity)
    price = flag*(spot*norm.cdf(flag*d_plus) - strike*np.exp(-rate*maturity)*norm.cdf(flag*d_minus))

    return price

def main():
    print(forward_valueBS(100, 0.05, 2, 110))
    print(option_priceBS(100,110,0.05,2,0.01))
    print(option_priceBS(100,110,0.05,2,0.01,-1))
    print("Parity: {}".format(option_priceBS(100,110,0.05,2,0.01) - option_priceBS(100,110,0.05,2,0.01,-1)))

main()


# %% import package and load data
from sklearn.datasets import load_iris
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import time

data = load_iris()
iris_features = pd.DataFrame(data=data.data, columns=data.feature_names)
X = np.array(iris_features['sepal length (cm)'])
Y = np.array(iris_features['petal length (cm)'])
m = len(X)  # size of the dataset

plt.scatter(X, Y)
plt.ylabel('sepal length (cm)')
plt.xlabel('petal length (cm)')
plt.show()

# %% initialize the model
learning_rate = 1e-3
theta_1 = 0
theta_0 = 0
history = []

# %% iteration
start = time.time()
# num_iterations = 100
num_iterations = 100

for i in range(num_iterations):
    Y_hat = theta_1 * X + theta_0  # forward prop
    distance = Y_hat - Y  # intermediate variable
    cost = (distance ** 2).sum() / 2 / m  # cost function
    history.append(cost)  # record cost history
    d1, d0 = np.dot(distance, X) / m, distance.mean()  # gradient

    # update parameter
    theta_1 -= learning_rate * d1
    theta_0 -= learning_rate * d0

end = time.time()
print('Iterated', num_iterations, 'times in', end - start, 'seconds')

plt.plot(history)
plt.title('Cost History')
plt.ylabel('Cost')
plt.xlabel('Iteration')
# plt.savefig('cost.png')
plt.show()

# %% regression result

plt.title('The result of the linear regression')
plt.grid()
plt.scatter(X, Y, color='C0')
plt.plot(X, theta_1 * X + theta_0, color='C1')
plt.ylabel('sepal length (cm)')
plt.xlabel('petal length (cm)')
# plt.savefig('result.png')
plt.show()

# %% performance analysis
# def iterate(num_iterations, theta_1, theta_0):
#     for i in range(num_iterations):
#         Y_hat = theta_1 * X + theta_0  # forward prop
#         distance = Y_hat - Y  # intermediate variable
#         cost = (distance ** 2).sum() / 2 / m  # cost function
#         history.append(cost)  # record cost history
#         d1, d0 = np.dot(distance, X) / m, distance.sum() / m  # gradient
#
#         # update parameter
#         theta_1 -= learning_rate * d1
#         theta_0 -= learning_rate * d0
#
#
# start = time.time()
# iterate(1_000_000, 0, 0)
# end = time.time()
# print(end - start)


import sympy
'''
@test($$;type(sympy))
@alt(シンボル|記号|変数)
@alt(数式として、|)
[代数計算|シンボル計算|数式処理][|ライブラリ]を使う
'''

s = 'z'
sympy.symbol(s)
'''
@test(sympy=missing;$$)
数式として、sをシンボルに変換する
'''

z = sympy.symbol(s)
'''
@test(sympy=missing;$$;z)
@prefix(z;[変数|式])
数式として、sを[シンボル|変数][に|化]して、zにする
'''

e = e2 = sympy.symbol(s)
n = 2
e.subs(z, n)
'''
@test(e=missing;e2='e2';z='x';$$)
@prefix(e;式)
数式として、eのzにnを代入する
'''

e.subs(z, e2)
'''
@test(e=missing;e2='e2';z='x';$$)
数式として、eのzにe2を代入する
数式として、eのzをe2で置き換える
'''

sympy.expand(e)
'''
@test(sympy=missing;e='e';$$)
数式として、eを展開する
数式として、eの展開を行う
'''

sympy.factor(e)
'''
@test(sympy=missing;e='e';$$)
数式として、eを因数分解する
数式として、eの因数分解を行う
'''

sympy.sympify(e)
'''
@test(sympy=missing;e='e';$$)
数式として、eを簡単[に|化]する
数式として、eを簡略[に|化]する
数式として、eの簡[略|単]化を行う
'''

sympy.apart(e)
'''
@test(sympy=missing;e='e';$$)
数式として、eを部分分数[に|として]展開する
数式として、eの部分分数化を行う
'''

sympy.solve(e)
'''
@test(sympy=missing;e='e';$$)
数式として、方程e[=0|][を解く|の解を求める]
'''

sympy.solve(e, z)
'''
@test(sympy=missing;e='e';z='x';$$)
数式として、方程e[=0|]のzの解を求める
'''

sympy.solve([e, e2])
'''
@test(sympy=missing;e='e';e2='e2';$$)
数式として、連立方程e[=0|], e2[|=0]の解を求める
'''

sympy.limit(e, z, 0)
'''
@test(sympy=missing;e='e';z='x';$$)
@alt(とき|時|場合|際)
zが0に近づくとき[の|、]eの極限値を求める
'''

sympy.limit(e, z, oo)
'''
@test(sympy=missing;e='e';z='x';oo='oo';$$)
zが無限大に近づくとき[の|、]eの極限値を求める
'''

sympy.limit(e, z, -oo)
'''
@test(sympy=missing;e='e';z='x';oo=0;$$)
zがマイナス無限大に近づくとき[の|、]eの極限値を求める
'''

sympy.diff(e)
'''
@test(sympy=missing;e='e';z='x';$$)
数式として、eを微分する
数式として、eの微分を求める
'''

sympy.diff(e, z)
'''
@test(sympy=missing;e='e';z='x';$$)
数式として、zについてeの微分を[行う|求める]
数式として、eのzを微分する
'''

sympy.diff(e, z, n)
'''
@test(sympy=missing;e='e';z='x';$$)
数式として、{eを|zについて}n階微分する
数式として、eの[zについての|]n階微分を[求める|行う]
'''

sympy.integrate(e)
'''
@test(sympy=missing;e='e';z='x';$$)
数式として、eを積分する
数式として、eの[積分|インテグラル]を[求める|行う]
'''

sympy.integrate(e, z)
'''
@test(sympy=missing;e='e';z='x';$$)
数式として、zについてeを積分する
数式として、zについてeの[積分|インテグラル]を[求める|行う]
'''

float(e)
'''
@test(sympy=missing;e='3.14159';z='x';$$)
数式として、eの数値[を求める|]
数式として、eを数値計算する
数式として、eを[数値|浮動小数点数]に変換する
'''

__X__ = e
sympy.sqrt(__X__)
'''
@test(sympy=missing;e='e';z='x';$$)
@X(e;z)
@Y(e;z)
数式として、__Y__の平方根を求める
'''

# sympy.E**(sympy.I * sympy.pi) == -1
# '''
# 数式として、オイラーの等式を使う
# '''

# sympy.summation(e, (z, 1, N))
# '''
# @test(import sympy;z,N=sympy.Symbol('z N');e=z**2;$$)
# 数式として、eの総和[|を求める]
# '''


from sklearn.datasets import load_boston
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import Ridge, Lasso
from sklearn.metrics import r2_score
from sklearn.model_selection import cross_val_score, GridSearchCV
import warnings
from sklearn.model_selection import cross_val_score
from numpy import mean
from numpy import std
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import cross_val_predict

warnings.filterwarnings('ignore', category = DeprecationWarning)
from warnings import filterwarnings
filterwarnings('ignore')

def lasso(X_b,y_b):

    """
    There are 14 attributes in each case of the dataset.It has two prototasks: nox, in which the nitrous oxide
    level is to be predicted;and price, in which the median value of a home is to be predicted.
    """
#     df_b = load_boston()
#     data_b = pd.DataFrame(df_b.data,columns = df_b.feature_names)
#     data_b['PRICE'] = df_b.target
#     X_b = data_b.drop('PRICE',axis = 1)
#     y_b = data_b['PRICE']
    X_train,X_test,y_train,y_test = train_test_split(X_b,y_b,test_size = 0.2,random_state = 129)
    #Lasso Regression
    from sklearn.linear_model import Lasso
    from sklearn.model_selection import GridSearchCV
    lasso=Lasso()
    parameters={'alpha':[1e-20,1e-15,1e-10,1e-8,1e-3,1e-2,1,5,10,20,30,35,40,45,50,55,100]}
    lasso_regressor=GridSearchCV(lasso,parameters,scoring='neg_mean_squared_error',cv=5)

    lasso_regressor.fit(X_train,y_train)
    # Let's check out the best parameter and best score
    print("best parameters:\n\n")
    print(lasso_regressor.best_params_)
    print(lasso_regressor.best_score_)
    prediction_lasso=lasso_regressor.predict(X_test)
    # Prediction
    y_pred_train_lasso1 = lasso_regressor.predict(X_train)
    y_pred_test_lasso1 = lasso_regressor.predict(X_test)
    print('Training accuracy : {}\n'.format(r2_score(y_train, y_pred_train_lasso1).round(5)))
    print('Testing accuracy : {}'.format(r2_score(y_test, y_pred_test_lasso1).round(5)))

    #cross validation
    for i in range(2,30,4):
        cv = KFold(n_splits=i, random_state=1, shuffle=True)
        train_score = cross_val_score(lasso_regressor, X_train, y_train,scoring='r2', cv=cv).mean()
        test_score = cross_val_score(lasso_regressor, X_test, y_test,scoring='r2', cv=cv).mean()
        print ("training accuracy using cross validation for ",i," splits:",train_score)
        print ("testing accuracy using cross validation for ",i," splits:",test_score)

#     mse1 = cross_val_score(lasso_regressor, X_b, y_b, scoring = 'neg_mean_squared_error',cv=5)
#     mean_mse1 = np.mean(mse1)
#     print("\nmean square error: ",-(mean_mse1).round(5))
#     print("\n")

    import seaborn as sns
    sns.distplot(y_test-prediction_lasso)
    X=[]
    rng=int(max(y_b))+50
    for i in range(1,rng):
        X.append(i)
    X=np.array(X)
    plt.scatter(prediction_lasso,y_test)
    plt.xlabel("predicted")
    plt.ylabel("y_test")
    plt.plot(X,X,color="red")

def ridge(X_b,y_b):
    from sklearn.linear_model import Ridge
    from sklearn.model_selection import GridSearchCV
    X_train,X_test,y_train,y_test = train_test_split(X_b,y_b,test_size = 0.2,random_state = 129)
    ridge=Ridge()
    parameters={'alpha':[1e-25,1e-20,1e-15,1e-10,1e-8,1e-3,1e-2,1,5,10,20,30,35,40,45,50,55,100]}
    ridge_regressor=GridSearchCV(ridge,parameters,scoring='neg_mean_squared_error',cv=5)
    ridge_regressor.fit(X_train,y_train)
    #checking out the best parameter and the score
    print("best parameter and the score:\n")
    print(ridge_regressor.best_params_)
    print(ridge_regressor.best_score_)
    print("\n")
    prediction_ridge=ridge_regressor.predict(X_test)
    # Prediction

    y_pred_train_ridge1 = ridge_regressor.predict(X_train)
    y_pred_test_ridge1 = ridge_regressor.predict(X_test)
    print('Training accuracy : {}\n'.format(r2_score(y_train, y_pred_train_ridge1).round(5)))
    print('Testing accuracy : {}'.format(r2_score(y_test, y_pred_test_ridge1).round(5)))

    #cross validation
    for i in range(2,30,4):
        cv = KFold(n_splits=i, random_state=1, shuffle=True)
        train_score = cross_val_score(ridge, X_train, y_train,scoring='r2', cv=cv).mean()
        test_score = cross_val_score(ridge, X_test, y_test,scoring='r2', cv=cv).mean()
        print ("training accuracy using cross validation for ",i," splits:",train_score)
        print ("testing accuracy using cross validation for ",i," splits:",test_score)

#     mse1 = cross_val_score(ridge_regressor, X_b, y_b, scoring = 'neg_mean_squared_error',cv=5)
#     mean_mse1 = np.mean(mse1)
#     print("\nmean square error: ",-(mean_mse1).round(5))
#     print("\n")

    import seaborn as sns
    sns.distplot(y_test-prediction_ridge)

    X=[]
    rng=int(max(y_b))+50
    for i in range(1,rng):
        X.append(i)
    X=np.array(X)
    plt.scatter(prediction_ridge,y_test)
    plt.xlabel("predicted")
    plt.ylabel("y_test")
    plt.plot(X,X,color="red")

def knn(X_b,y_b):
    X_train, X_test, Y_train, Y_test = train_test_split(X_b, y_b, test_size = 0.20, random_state = 0)
    from sklearn.neighbors import KNeighborsRegressor
    import seaborn as sns
    knr = KNeighborsRegressor(n_neighbors=1)
    knr.fit(X_train, Y_train)

    Y_pred = knr.predict(X_test) # Prediction

    y_pred_train_knn1 = knr.predict(X_train)
    y_pred_test_knn1 = knr.predict(X_test)
    print('Training accuracy : {}\n'.format(r2_score(Y_train, y_pred_train_knn1).round(5)))
    print('Testing accuracy : {}\n'.format(r2_score(Y_test, y_pred_test_knn1).round(5)))

        #cross validation
    for i in range(2,30,4):
        cv = KFold(n_splits=i, random_state=1, shuffle=True)
        train_score = cross_val_score(knr, X_train, Y_train,scoring='r2', cv=cv).mean()
        test_score = cross_val_score(knr, X_test, Y_test,scoring='r2', cv=cv).mean()
        print ("training accuracy using cross validation for ",i," splits:",train_score)
        print ("testing accuracy using cross validation for ",i," splits:",test_score)

#     mse1 = cross_val_score(knr, X_b, y_b, scoring = 'neg_mean_squared_error',cv=5)
#     mean_mse1 = np.mean(mse1)
#     print("\nmean square error(cross validation score): ",-(mean_mse1).round(5))
#     print("\n")

    # Create Dataset with Testing values and Predicted Prices
    print("KNN Regresson Model")
    model_knn = pd.DataFrame(X_test)
    model_knn['MEDV'] = Y_test
    model_knn['Predicted MEDV'] = Y_pred
    print(model_knn.head(10))
    print("\n\n")

    # Measure Performance of the Model
    # Get Mean Squared Error (MSE)
    from sklearn.metrics import mean_squared_error
    mse = mean_squared_error(Y_test, Y_pred)
    # Get Mean Absolute Error (MAE)
    from sklearn.metrics import mean_absolute_error
    mae = mean_absolute_error(Y_test, Y_pred)

    err = "MSE(mean square error): " + str(round(mse, 2)) + "," + " MAE(mean absolute error): " + str(round(mae, 2))
    print("KNN Regresson Model Performance:-- ", err,"\n\n")

    # Create Regression Plot for Test and Prediction values
    fig = plt.figure(figsize=(12,9))
    ax = sns.regplot(Y_test, Y_pred, marker = 'o', color = 'red')
    ax.set_title('KNN Regression', fontsize=20)
    ax.set_xlabel('MEDV or Price', fontsize=20)
    ax.set_ylabel('Predicted Prices', fontsize=20)
    # Save the KNN Regrassion Plot along with Error value
    plt.text(35.0, 10.0, err, fontsize=20, bbox=dict(facecolor='yellow', alpha=0.5))
    plt.savefig("KNNRegression.png", dpi=70)
    plt.show()
    plt.close(fig)

    X=[]
    rng=int(max(y_b))+50
    for i in range(1,rng):
        X.append(i)
    X=np.array(X)
    plt.scatter(Y_pred,Y_test)
    plt.xlabel("predicted")
    plt.ylabel("y_test")
    plt.plot(X,X,color="red")

def mlr(X,Y):
    import numpy as np
    import pandas as pd
    from sklearn.model_selection import train_test_split
    from sklearn.datasets import load_boston
    from sklearn.metrics import mean_squared_error, r2_score
    X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size = 0.2, random_state=9)
    from sklearn.linear_model import LinearRegression
    lin_reg_mod = LinearRegression()
    lin_reg_mod.fit(X_train, y_train)
    pred = lin_reg_mod.predict(X_test)

    y_pred_train_mlr1 = lin_reg_mod.predict(X_train)
    y_pred_test_mlr1 = lin_reg_mod.predict(X_test)

    print("MLR Model")
    model_mlr = pd.DataFrame(X_test)
    model_mlr['MEDV'] = y_test
    model_mlr['Predicted MEDV'] = pred
    print(model_mlr.head(10))
    print("\n\n")

    print('Training accuracy : {}\n'.format(r2_score(y_train, y_pred_train_mlr1).round(5)))
    print('Testing accuracy : {}'.format(r2_score(y_test, y_pred_test_mlr1).round(5)))
    print("\n")

        #cross validation
    for i in range(2,30,4):
        cv = KFold(n_splits=i, random_state=1, shuffle=True)
        train_score = cross_val_score(lin_reg_mod, X_train, y_train,scoring='r2', cv=cv).mean()
        test_score = cross_val_score(lin_reg_mod, X_test, y_test,scoring='r2', cv=cv).mean()
        print ("training accuracy using cross validation for ",i," splits:",train_score)
        print ("testing accuracy using cross validation for ",i," splits:",test_score)

    test_set_rmse = (np.sqrt(mean_squared_error(y_test, pred)))
    test_set_r2 = r2_score(y_test, pred)

    print("RMSE: ",test_set_rmse)
    print("r2 score: ",test_set_r2)
    X=[]
    rng=int(max(Y))+50
    for i in range(1,rng):
        X.append(i)
    X=np.array(X)
    plt.scatter(pred,y_test)
    plt.xlabel("predicted")
    plt.ylabel("y_test")
    plt.plot(X,X,color="red")

def kernel_cobra(boston):
    from sklearn import datasets
    from sklearn.metrics import accuracy_score
    from kernelcobra import KernelCobra
    #from sklearn.datasets.samples_generator import make_regression
    #boston = datasets.load_boston()

    # boston_X_train = boston.data[:-40]
    # boston_X_test = boston.data[-40:]

    # boston_y_train = boston.target[:-40]
    # boston_y_test = boston.target[-40:]

    #boston_X_train, boston_X_test, boston_y_train, boston_y_test = train_test_split(X, Y, test_size = 0.2, random_state=9)
    boston_X_train = boston.data[:300]
    boston_X_test = boston.data[300:]

    boston_y_train = boston.target[:300]
    boston_y_test = boston.target[300:]

    from pycobra.cobra import Cobra
    from pycobra.kernelcobra import KernelCobra

    from pycobra.ewa import Ewa
    from pycobra.diagnostics import Diagnostics
    from pycobra.visualisation import Visualisation
    import numpy as np

    boston_kernelcobra = KernelCobra()
    boston_kernelcobra.fit(boston_X_train, boston_y_train)

    kernel = KernelCobra()

    kernel.fit(boston_X_train, boston_y_train)
    kernel.predict(boston_X_test)

    y_pred=kernel.predict(boston_X_test)
    import matplotlib.pyplot as plt
    import numpy as np

    X=[]
    rng=int(max(boston_y_test))+50
    for i in range(1,rng):
        X.append(i)
    X=np.array(X)

    from sklearn.metrics import r2_score
    from sklearn.model_selection import cross_val_score, GridSearchCV
    prediction_kernel=kernel.predict(boston_X_test)

    print("kernel cobra Model")
    model_mlr = pd.DataFrame(boston_X_test)
    model_mlr['MEDV'] = boston_y_test
    model_mlr['Predicted MEDV'] = prediction_kernel
    print(model_mlr.head(10))
    print("\n\n")

    # Prediction
    y_pred_train_kernel1 = kernel.predict(boston_X_train)
    y_pred_test_kernel1 = kernel.predict(boston_X_test)
    print('Training accuracy : {}\n'.format(r2_score(boston_y_train, y_pred_train_kernel1).round(5)))
    print('Testing accuracy : {}'.format(r2_score(boston_y_test, y_pred_test_kernel1).round(5)))

    #cross validation
    for i in range(2,30,4):
        cv = KFold(n_splits=i, random_state=1, shuffle=True)
        train_score = cross_val_score(kernel, boston_X_train, boston_y_train,scoring='r2', cv=cv).mean()
        test_score = cross_val_score(kernel, boston_X_test, boston_y_test,scoring='r2', cv=cv).mean()
        print ("training accuracy using cross validation for ",i," splits:",train_score)
        print ("testing accuracy using cross validation for ",i," splits:",test_score)

#     mse1 = cross_val_score(kernel, boston.data, boston.target, scoring = 'neg_mean_squared_error',cv=5)
#     mean_mse1 = np.mean(mse1)
#     print("\nmean square error: ",-(mean_mse1).round(5))
#     print("\n")

    plt.scatter(y_pred,boston_y_test)
    plt.xlabel("predicted")
    plt.ylabel("y_test")
    plt.plot(X,X,color="red")

def kernel_cobra_diabetes(X,y):
    from sklearn import datasets
    from sklearn.metrics import accuracy_score
    from kernelcobra import KernelCobra
    #from sklearn.datasets.samples_generator import make_regression
    #boston = datasets.load_boston()

    # boston_X_train = boston.data[:-40]
    # boston_X_test = boston.data[-40:]

    # boston_y_train = boston.target[:-40]
    # boston_y_test = boston.target[-40:]

    nn=len(X)
    nn1=nn/3
    lim=int(nn-nn1)
    boston_X_train = X[:lim]
    boston_X_test = X[lim:]

    boston_y_train = y[:lim]
    boston_y_test = y[lim:]

    from pycobra.cobra import Cobra
    from pycobra.kernelcobra import KernelCobra

    from pycobra.ewa import Ewa
    from pycobra.diagnostics import Diagnostics
    from pycobra.visualisation import Visualisation
    import numpy as np

    boston_kernelcobra = KernelCobra()
    boston_kernelcobra.fit(boston_X_train, boston_y_train)

    kernel = KernelCobra()

    kernel.fit(boston_X_train, boston_y_train)
    kernel.predict(boston_X_test)

    y_pred=kernel.predict(boston_X_test)
    import matplotlib.pyplot as plt
    import numpy as np

    X=[]
    rng=int(max(y))+50
    for i in range(1,rng):
        X.append(i)
    X=np.array(X)

    from sklearn.metrics import r2_score
    from sklearn.model_selection import cross_val_score, GridSearchCV
    prediction_kernel=kernel.predict(boston_X_test)

    print("kernel cobra Model")
    model_mlr = pd.DataFrame(boston_X_test)
    model_mlr['MEDV'] = boston_y_test
    model_mlr['Predicted MEDV'] = prediction_kernel
    print(model_mlr.head(10))
    print("\n\n")

    # Prediction
    y_pred_train_kernel1 = kernel.predict(boston_X_train)
    y_pred_test_kernel1 = kernel.predict(boston_X_test)
    print('Training accuracy : {}\n'.format(r2_score(boston_y_train, y_pred_train_kernel1).round(5)))
    print('Testing accuracy : {}'.format(r2_score(boston_y_test, y_pred_test_kernel1).round(5)))

    for i in range(2,30,4):
        cv = KFold(n_splits=i, random_state=1, shuffle=True)
        train_score = cross_val_score(kernel, boston_X_train, boston_y_train,scoring='r2', cv=cv).mean()
        test_score = cross_val_score(kernel, boston_X_test, boston_y_test,scoring='r2', cv=cv).mean()
        print ("training accuracy using cross validation for ",i," splits:",train_score)
        print ("testing accuracy using cross validation for ",i," splits:",test_score)

#     mse1 = cross_val_score(kernel, boston.data, boston.target, scoring = 'neg_mean_squared_error',cv=5)
#     mean_mse1 = np.mean(mse1)
#     print("\nmean square error: ",-(mean_mse1).round(5))
#     print("\n")

    plt.scatter(y_pred,boston_y_test)
    plt.xlabel("predicted")
    plt.ylabel("y_test")
    plt.plot(X,X,color="red")


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

import numpy as np

class Function:
    def call(self, x,y):
        pass
    def __call__(self, x,y):
        z = self.call(x,y)
        return z
    def reset_counter(self):
        self.num_of_calls = 0
    def __str__(self):
        return type(self).__name__

class Rastrigin(Function):

    def __init__(self):
        [self.xmin,self.xmax,self.ymin,self.ymax] = [-5.12,5.12,-5.12,5.12]
        self.limits = [self.xmin,self.xmax,self.ymin,self.ymax]

        self.x_min = 0
        self.y_min = 0

        self.num_of_calls = 0

    def call(self, x, y):
        z = 20 + x**2 + y**2 - 10*(np.cos(2 * np.pi * x) + np.cos(2 * np.pi * y))
        self.num_of_calls += 1
        return z

class Ackley(Function):

    def __init__(self):
        [self.xmin,self.xmax,self.ymin,self.ymax] = [-5,5,-5,5]
        self.limits = [self.xmin,self.xmax,self.ymin,self.ymax]

        self.x_min = 0
        self.y_min = 0

        self.num_of_calls = 0

    def call(self, x, y):
        z = -20 * np.exp(-0.2 * np.sqrt(0.5*(x**2 + y**2)))
        z += -np.exp(0.5 * (np.cos(2*np.pi*x) + np.cos(2*np.pi*y)))
        z += np.e + 20
        self.num_of_calls += 1
        return z

class Matyas(Function):

    def __init__(self):
        [self.xmin,self.xmax,self.ymin,self.ymax] = [-10,10,-10,10]
        self.limits = [self.xmin,self.xmax,self.ymin,self.ymax]

        self.x_min = 0
        self.y_min = 0

        self.num_of_calls = 0

    def call(self, x, y):
        z = 0.26 * (x**2 + y**2) - 0.48 * x* y
        self.num_of_calls += 1
        return z

class Rosenbrock(Function):

    def __init__(self):
        [self.xmin,self.xmax,self.ymin,self.ymax] = [-10,10,-10,10]
        self.limits = [self.xmin,self.xmax,self.ymin,self.ymax]

        self.x_min = 1
        self.y_min = 1

        self.num_of_calls = 0

    def call(self, x, y):
        z = (1 - x)**2 + 100 * (y - x**2)**2
        self.num_of_calls += 1
        return z

class Sphere(Function):

    def __init__(self):
        [self.xmin,self.xmax,self.ymin,self.ymax] = [-10,10,-10,10]
        self.limits = [self.xmin,self.xmax,self.ymin,self.ymax]

        self.x_min = 0
        self.y_min = 0

        self.num_of_calls = 0

    def call(self, x, y):
        z = x**2 + y**2
        self.num_of_calls += 1
        return z


import math
import numpy as np
import pandas as pd

def roundup(x, n=10):
    """Round up x to multiple of n."""
    return int(math.ceil(x / n)) * n

def running_mean(x, N):
    """Calculate running/rolling mean or moving average.
    Thanks to https://stackoverflow.com/a/27681394/6528729
    """
    cumsum = np.cumsum(np.insert(x, 0, 0))
    return (cumsum[N:] - cumsum[:-N]) / float(N)

def np_describe(arr):
    """Describe numpy array statistics.
    Thanks to https://qiita.com/AnchorBlues/items/051dc69e81705b52adad
    """
    return pd.DataFrame(pd.Series(arr.ravel()).describe()).transpose()

def np_softmax(z):
    """Numpy version softmax.
    Thanks to https://stackoverflow.com/a/39558290/6528729
    """
    assert len(z.shape) == 2
    s = np.max(z, axis=1)
    s = s[:, np.newaxis] # necessary step to do broadcasting
    e_x = np.exp(z - s)
    div = np.sum(e_x, axis=1)
    div = div[:, np.newaxis] # dito
    return e_x / div

def np_flooding(loss, b):
    """Flooding function for numpy.

    .. _Do We Need Zero Training Loss After Achieving Zero Training Error?: https://arxiv.org/abs/2002.08709
    """
    return np.abs(loss - b) + b

def n_by_m_distances(n, m, how='cosine'):
    """
    Calculate distances for all combinations of vectors.

    Example:
        n = np.array([[0.1, 0.2], [0.7, 0.5], [0.3, 0.4]])
        m = np.array([[-20, 10], [10, 20], [10, 10], [20, 10]])
        n_by_m_distances(n, m, how='euclidean')
        Result:
            [[22.361798, 22.137073, 13.930183, 22.1822  ],
             [22.775864, 21.604166, 13.29436 , 21.511392],
             [22.455512, 21.868928, 13.647344, 21.914607]]
    """
    if how == 'cosine':
        l2_n = np.linalg.norm(n, axis=1)
        l2_m = np.linalg.norm(m, axis=1)
        inner = np.dot(n, m.T)
        norms = np.dot(l2_n.reshape(-1, 1), l2_m.reshape(1, -1))
        return 1.0 - (inner / norms)
    elif how == 'euclidean':
        return np.array([np.linalg.norm(m - a_n, axis=1) for a_n in n])
    else:
        raise Exception(f'Unknown how: {how}')

def geometric_mean_preds(list_preds):
    """Calculate geometric mean of prediction results.
    Prediction result is expected to be probability value of ML model's
    softmax outputs in 2d array.

    Arguments:
        list_preds: List of 2d numpy array prediction results.

    Returns:
        Geometric mean of input list of 2d numpy arrays.
    """
    preds = list_preds[0].copy()
    for next_preds in list_preds[1:]:
        preds = np.multiply(preds, next_preds)
    return np.power(preds, 1/len(list_preds))

def arithmetic_mean_preds(list_preds):
    """Calculate arithmetic mean of prediction results.
    Prediction result is expected to be probability value of ML model's
    softmax outputs in 2d array.

    Arguments:
        list_preds: List of 2d numpy array prediction results.

    Returns:
        Arithmetic mean of input list of 2d numpy arrays.
    """
    preds = list_preds[0].copy()
    for next_preds in list_preds[1:]:
        preds = np.add(preds, next_preds)
    return preds / len(list_preds)

def soft_mean_preds(list_preds, t=0.5):
    """
    Thanks to https://www.kaggle.com/c/severstal-steel-defect-detection/discussion/107716#620952
    """
    def _sharpen(p, t):
        return p**t if t!= 0 else p
    preds = _sharpen(list_preds[0].copy(), t=t)
    for next_preds in list_preds[1:]:
        preds = np.add(preds, _sharpen(next_preds, t))
    return preds / len(list_preds)

class OnlineStats:
    """Calculate mean/variance of a vector online
    Thanks to https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
    """

    def __init__(self, length):
        self.K = np.zeros((length))
        self.Ex = np.zeros((length))
        self.Ex2 = np.zeros((length))
        self.n = 0

    def put(self, x):
        if self.n == 0:
            self.K = x
        self.n += 1
        d = x - self.K
        self.Ex += d
        self.Ex2 += d * d

    def undo(self, x):
        self.n -= 1
        d = x - self.K
        self.Ex -= d
        self.Ex2 -= d * d

    def mean(self):
        if self.n == 0:
            return np.zeros_like(self.K)
        return self.K + self.Ex / self.n

    def variance(self):
        if self.n < 2:
            return np.zeros_like(self.K)
        return (self.Ex2 - (self.Ex * self.Ex) / self.n) / (self.n - 1)

    def sigma(self):
        if self.n < 2:
            return np.zeros_like(self.K)
        return np.sqrt(self.variance())

    def count(self):
        return self.n

    def set_mean(self, mean_values):
        """Set mean value as if onle one sample was fed."""
        self.K = 0.0
        self.Ex = mean_values
        self.Ex2 = 0.0
        self.n = 1


from scipy.fft import dct ,idct
from math import  log10
import numpy as np
import cv2

# Steps to follow

# 1. Encoder
#   1.1 Read the image file ‘image1.bmp’. => Done
#   1.2 Extract and display each of its three color components. => Done
#   1.3 Convert range of each component to [-128, 127] => Done
#   1.4 Form a matrix for the outImage with the new size => Done
#   1.5 Process each color component in blocks of 8×8 pixels. => Done
#   1.6 Obtain 2D DCT of each block. => Done
#   1.7 Retain only the top left square of the 2D DCT coefficients of size 𝑚 × 𝑚, The rest of coefficients are ignored. => Done
#   1.8 Compare the size of the original and compressed images. => Done

# 2. Decoder
#   2.1 load the out-image=>Done
#   2.2 display the compressed image=>Done
#   2.3 Form a matrix for the deCompressed image with the original size => Done
#   2.4 Get each block of to be decompressed.=>Done
#   2.5 apply inverse dct on each block=>Done
#   2.6 re-range the out image by adding 128 ranges from [0 : 255] => Done
#   2.7 display the decompressed image and Compare them => Done
#   2.8 quality of the decompressed image is measured using the Peak Signal-to-Noise Ratio PSNR) implementation => Done
#   2.9 display PSNR for each m => Done
#   2.9 technical report (advantages of using DCT instead of DFT)

# Step 1.3
def reRange(inputImage):
    print("inputImage before", inputImage)
    inputImage = inputImage.astype('int')
    inputImage -= 128
    print("inputImage after", inputImage)
    return inputImage

# Step 1.2
def getComponent(inputImage, no):
    # 1. no = 0 => red
    # 2. no = 1 => green
    # 3. no = 2 => blue
    cpy = inputImage.copy()
    for i in range(3):
        if(i != no):  # not need => Just make it zeros
            cpy[:, :, i] = 0
    return cpy

def imageCompression(inputImage, m, row, col):
    # Step 1.4
    outImage = np.zeros(
        (int((row / 8) * m), int((col / 8) * m), 3), dtype=np.float16)

    blockRow = int(row / 8)
    blockCol = int(col / 8)
    blockComponents = 3
    noIterations = 0

    # Step 1.5
    for x in range(0, blockRow):
        for y in range(0, blockCol):
            for z in range(0, blockComponents):
                noIterations += 1
                currentBlock = inputImage[x *
                                          8: x * 8 + 8, y * 8: y * 8 + 8, z]
                # Step 1.6, 1.7
                blockDCT = dct(dct(currentBlock.T, norm='ortho').T, norm='ortho')[0:m, 0:m]
                outImage[x * m: x * m + m, y * m: y * m + m, z] = blockDCT
    print("no Iterations", noIterations)
    print("outImage", outImage)
    return outImage

# implement 2D IDCT
def idct2(a):
    return idct(idct(a.T, norm='ortho').T, norm='ortho')
# step 2.6
def deReRange(deCopressedImage):

    deCopressedImage += 128
    deCopressedImage = deCopressedImage.astype('int')
    return deCopressedImage

def imageDeCompression(toBeCompressedImage ,m , row ,col):
    # Step 2.3
    deCompressedImage = np.zeros((int((row / m) * 8), int((col / m) * 8), 3), dtype=np.float16)

    blockRow = int(row / m)
    blockCol = int(col / m)
    blockComponents = 3
    noIterations = 0

    # Step 2.4
    for x in range(0, blockRow):
        for y in range(0, blockCol):
            for z in range(0, blockComponents):

                noIterations += 1
                currentBlock = toBeCompressedImage[x * m: x * m + m, y * m: y * m + m, z]
                deCompressedBlock = np.zeros((int(8), int(8)), dtype=np.float16)
                deCompressedBlock[0: m, 0: m] = currentBlock

                # Step 2.5
                blockIDCT = idct2(deCompressedBlock)
                deCompressedImage[x*8:x*8+8, y*8:y*8+8, z] = blockIDCT

     # Step 2.6
    deCompressedImage =deReRange(deCompressedImage)
    return deCompressedImage

# Step 2.8
def getPSNR(original, compressed):

    MSE = np.mean((original - compressed) ** 2)
    max_pixel = 255.0
    PSNR = 10 * log10((max_pixel*max_pixel) / MSE)
    return PSNR

# Step 1.1
inputImage = cv2.imread('./image1.bmp')
np.save("inputImage", inputImage)

row = inputImage.shape[0]
col = inputImage.shape[1]
m = int(input('Enter the value of m between [1 - 4] : '))

cv2.imshow("Input Image", inputImage)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Step 1.2
# Get Red Component
redComponent = getComponent(inputImage, 2)
cv2.imwrite("redComponent.bmp", redComponent)
cv2.imshow("Red Component", redComponent)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Get Green Component
greenComponent = getComponent(inputImage, 1)
cv2.imwrite("greenComponent.bmp", greenComponent)
cv2.imshow("Green Component", greenComponent)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Get Blue Component
blueComponent = getComponent(inputImage, 0)
cv2.imwrite("blueComponent.bmp", blueComponent)
cv2.imshow("Blue Component", blueComponent)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Step 1.3
inputImage = reRange(inputImage)

# Step 1.8
outImage = imageCompression(inputImage, m, row, col)
print("Output Image", outImage)
np.save("outImage", outImage)

# Step 2.1
toBeCompressedImage = np.load("outImage.npy")

# Step 2.2
print("decompressed", toBeCompressedImage)
deRow = toBeCompressedImage.shape[0]
deCol = toBeCompressedImage.shape[1]

deCompressedImage = imageDeCompression(toBeCompressedImage, m, deRow, deCol)
print("deCompressedImage", deCompressedImage)
print("inputImage", inputImage)
print(deCompressedImage.shape[0], deCompressedImage.shape[1])

# Step 2.7
cv2.imwrite("deCompressedImage.bmp", deCompressedImage)
deCompressedImage = cv2.imread("./deCompressedImage.bmp")
cv2.imshow("deCompressed Image", deCompressedImage)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Step 2.9
inputImage = cv2.imread('./image1.bmp')
deCompressedImage = cv2.imread("./deCompressedImage.bmp")
PSNR = getPSNR(inputImage, deCompressedImage)
print("PSNR", PSNR)


"""## Question 2: Implementing Box-Muller Transformation algorithm"""

import numpy as np
import matplotlib.pyplot as plt

def gaussianTransform(x, y):
  x_new = np.sqrt(-2*np.log(x))*np.cos(2*np.pi*y)
  y_new = np.sqrt(-2*np.log(x))*np.sin(2*np.pi*y)

  return x_new, y_new

x_u = np.random.rand(5000)
y_u = np.random.rand(5000)

x_g, y_g = gaussianTransform(x_u, y_u)

fig = plt.figure()

plt.subplot(2, 2, 1)
plt.hist(x_u, ec='black')

plt.subplot(2, 2, 2)
plt.hist(y_u, ec='black')

plt.subplot(2, 2, 3)
plt.hist(x_g, ec='black')

plt.subplot(2, 2, 4)
plt.hist(y_g, ec='black')

plt.show()


import numpy as np

def dejong_sphere(variables):
        return np.sum(np.power(variables,2))

def quadratic_noise(variables):
    random_vector = np.random.uniform(0,1,size=len(variables))
    integer_vector = np.arange(1,len(variables) + 1)
    return np.sum(integer_vector * np.power(variables,4) + random_vector)

def rastrigin(variables):
    return np.sum((np.power(variables,2)) + (-10 * np.cos(2 * np.pi * variables)) + 10)

def rastrigin_function(variables):
    N = len(variables)
    return (10 * N) + np.sum((np.power(variables,2)) - (10 * np.cos(2 * np.pi * variables)))

def _rastring_transf_function(x):
    if np.abs(x) >= 0.5 :
        return np.divide(np.round(2 * x),2)
    else :
        return x

noncontinuous_transformation = np.vectorize(_rastring_transf_function)

def rastrigin_noncontinuous(variables):
    Y = noncontinuous_transformation(variables)
    return rastrigin(Y)

def griewank_function(variables):
    const = np.divide(1,4000)
    indices = np.arange(1,len(variables)+1,1,dtype=np.int16)

    somatorio = const * np.sum(np.power(variables,2))
    produtorio = np.prod(np.cos(np.divide(variables,np.sqrt(indices))))

    return 1 + somatorio - produtorio


"""
Function the generates the random location, at the specified radius
INPUT = radius, seedX, seedY
OUTPUT = [x,y] location
"""

import random
import numpy

def randomAtRadius(radius, seedX, seedY):
    theta = 2*numpy.pi*random.random() #generate random theta
    x=int(radius*numpy.cos(theta))+seedX #use trig to transfer into X
    y=int(radius*numpy.sin(theta))+seedY #find Y coordinate
    location=[x, y] #save locaction
    return location