from ..monte_carlo import monteCarloSkeleton, monteCarloStats

import numpy as np

def blackScholes(current: float, volatility: float, ttm: float, strike: float,
                 rf: float, dividend: float, sim_count: int, eval_count: int,
                 opt_type: str='C', **kwargs) -> dict:
    """Function to model the price of a European Option, under the Black-Scholes
    pricing model heuristic, using a Monte-Carlo simulation.

    This function simulates a simple Geometric Brownian Motion (GBM) of the
    underlying asset price, before computing the terminal contract value for a
    given number of simulated paths.

    Then, Monte Carlo simulation statistics are
    computed for each of the simulations, and a dict of results is returned.

    Arguments:
        current {float} -- Current price of the underlying asset.
        volatility {float} -- Volatility of the underlying asset price.
        ttm {float} -- Time to expiration (in years).
        strike {float} -- Strike price of the option contract.
        rf {float} -- Risk-free rate (annual).
        dividend {float} -- Dividend yield (annual).
        sim_count {int} -- Number of paths to simulate.
        eval_count {int} -- Number of evaluations per path simulation.

    Keyword Arguments:
        opt_type {str} -- Option type; must be 'C' or 'P' (default: {'C'}).

    Raises:
        ValueError: Raised if `opt_type` is not 'C' or 'P'.

    Returns:
        dict -- Formatted dictionary of Monte Carlo simulation results.
    """

    # Verify option type choice
    if opt_type not in ['C', 'P']:
        raise ValueError('Incorrect option type; must be "C" or "P".')

    # Computing delta t
    dt = ttm / eval_count
    # Computing intitial value
    init_val = np.log(current)
    # Computing nudt
    nudt = (rf - dividend - (np.power(volatility, 2) / 2)) * dt

    # Defining lambda function to model Geometric Brownian Motion (GBM)
    gbm = lambda x: nudt + (volatility * np.sqrt(dt) * x)

    # Defining simulation function
    def sim_func(x: np.array) -> float:
        if (opt_type == 'C'):
            # Call option
            return np.exp(-1 * rf * ttm) * \
                np.maximum(np.exp(init_val + np.sum(gbm(x))) - strike, 0)
        else:
            # Put option
            return np.exp(-1 * rf * ttm) * \
                np.maximum(strike - np.exp(init_val + np.sum(gbm(x))), 0)

    # Running simulation
    mc_output = monteCarloSkeleton(sim_count=sim_count,
                                   eval_count=eval_count,
                                   sim_func=sim_func)

    # Computing and returning sample statistics
    return monteCarloStats(mc_output=mc_output)


import numpy as np
import math

aa = 1.5
a = np.array([
    [5.18+aa, 1.12,    0.95,    1.32,    0.83],
    [1.12,    4.28-aa, 2.12,    0.57,    0.91],
    [0.95,    2.12,    6.13+aa, 1.29,    1.57],
    [1.32,    0.57,    1.29,    4.57-aa, 1.25],
    [0.83,    0.91,    1.57,    1.25,    5.21+aa]
])

epsilon = 10e-4

print("------------")
print("   Task 1   ")
print("------------")

# Find max abs eigenvalue and corresponding eigenvector
def power_iteration(a, epsilon):
    x_next = np.ones(a.shape[0])
    mu = np.nan
    mu_next = np.nan

    step = 0

    while not abs(mu_next - mu) < epsilon:
        step += 1
        x = x_next
        mu = mu_next

        x /= np.linalg.norm(x)
        x_next = a @ x
        mu_next = x_next @ x
        #print(f'x = {x}, x_next = {x_next}')

    print(f"(Steps: {step})")

    return (mu_next, x_next / np.linalg.norm(x_next))

# Alias
get_eigen_max = power_iteration

# Find max abs eigenvalue, knowing min abs eigenvalue
# a must be symmetrical
def get_eigenvalue_min(a, epsilon, eigenvalue_max=None):
    if eigenvalue_max:
        b = np.eye(a.shape[0]) * eigenvalue_max - a
        return eigenvalue_max - power_iteration(b, epsilon)[0]
    else:
        a_max = np.max(a)
        b = a_max * np.eye(a.shape[0]) - a
        return a_max - power_iteration(b, epsilon)[0]

# Find max abs eigenvalue and corresponding eigenvector
def get_eigen_min(a, epsilon):
    a_inv = np.linalg.inv(a)
    eigenvalue_min = 1 / get_eigen_max(a_inv, epsilon)[0]

    x = np.ones(a.shape[0])

    while True:
        x_next = a_inv @ x * eigenvalue_min

        if (np.allclose(x, x_next, atol=epsilon)):
            return (eigenvalue_min, x_next / np.linalg.norm(x_next))

        x = x_next

print("Max. eigen. (power iteration): ")
eigenvalue_max, eigenvector_max = get_eigen_max(a, epsilon)
print(eigenvalue_max, eigenvector_max)

print("Min. eigenvalue (power iteration, from max. eigenvalue): ")
print(get_eigenvalue_min(a, epsilon, eigenvalue_max))

print("Min. eigenvalue (power iteration): ")
print(get_eigenvalue_min(a, epsilon))

print("Min. eigen. (power iteration on inverse): ")
eigenvalue_min, eigenvector_min = get_eigen_min(a, epsilon)
print(eigenvalue_min, eigenvector_min)

print("------------")
print("   Task 2   ")
print("------------")

def jacobi_rotation_method(a, epsilon):
    u_prod = np.eye(a.shape[0])

    # Quadratic sum of non-diagonal elements
    t = 0
    for i in range(a.shape[0]):
        for j in range(i, a.shape[1]):
            if i != j:
                t += 2 * (a[i, j] ** 2)

    step = 0

    while t > epsilon:
        step += 1
        # Find max. abs. non-diagonal element
        max_nd = 0

        for i in range(a.shape[0]):
            for j in range(a.shape[1]):
                if i != j and abs(a[i, j]) > abs(max_nd):
                    max_nd = a[i, j]
                    i_max_nd = i
                    j_max_nd = j

        if abs(a[i_max_nd, i_max_nd] - a[j_max_nd, j_max_nd]) < epsilon:
            phi = math.pi / 4
        else:
            phi = math.atan(2 * max_nd /
                    (a[i_max_nd, i_max_nd] - a[j_max_nd, j_max_nd])) / 2

        u = np.eye(a.shape[0])
        u[i_max_nd, i_max_nd] = math.cos(phi)
        u[i_max_nd, j_max_nd] = math.sin(phi)
        u[j_max_nd, i_max_nd] = -math.sin(phi)
        u[j_max_nd, j_max_nd] = math.cos(phi)
        t -= 2 * (max_nd ** 2)
        #print(t)

        #a = u.transpose() @ a @ u
        a = u @ a @ u.transpose()
        #u_prod = u_prod @ u
        u_prod = u_prod @ u.transpose()

    print(f"(Steps: {step})")

    return (np.diag(a), u_prod)

get_eigen = jacobi_rotation_method

print("Eigenvectors (Jacobi rotations):")
eigenvalues, eigenvectors = get_eigen(a, epsilon)
print(eigenvalues)
print(eigenvectors)

print("------------")
print("    NumPy   ")
print("------------")

numpy_eigenvalues, numpy_eigenvectors = np.linalg.eig(a)
print("np.linalg.eig: ")
print(numpy_eigenvalues)
print(numpy_eigenvectors)


import numpy as np
import matplotlib.pyplot as plt

def gd(x_start, step, g):
    x = x_start
    xarr = [x]
    for i in range(20):
        grad = g(x)
        x -= grad * step
        xarr.append(x.copy())
        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if sum(abs(grad)) < 1e-6:
            break;
    return x, xarr

def momentum(x_start, step, g, discount = 0.7):
    x = np.array(x_start, dtype='float64')
    pre_grad = np.zeros_like(x)
    xarr = [x.copy()]
    for i in range(50):
        grad = g(x)
        pre_grad = pre_grad * discount + grad * step
        x -= pre_grad
        xarr.append(x.copy())

        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if sum(abs(grad)) < 1e-6:
            break;
    return x, xarr

def f(x):
    return x[0] * x[0] + 50 * x[1] * x[1]
def g(x):
    return np.array([2 * x[0], 100 * x[1]])
xi = np.linspace(-200,200,1000)
yi = np.linspace(-100,100,1000)
X,Y = np.meshgrid(xi, yi)
Z = X * X + 50 * Y * Y

def contour(X,Y,Z, arr = None):
    plt.figure(figsize=(15,7))
    xx = X.flatten()
    yy = Y.flatten()
    zz = Z.flatten()
    plt.contour(X, Y, Z, colors='black')
    plt.plot(0,0,marker='*')
    if arr is not None:
        arr = np.array(arr)
        for i in range(len(arr) - 1):
            plt.plot(arr[i:i+2,0],arr[i:i+2,1])
    plt.show()

contour(X,Y,Z)

# normal step
res, x_arr = gd([150,75], 0.016, g)
contour(X, Y, Z, x_arr)

# large step
res, x_arr = gd([150,75], 0.019, g)
contour(X, Y, Z, x_arr)

# extreme step
res, x_arr = gd([150,75], 0.02, g)
contour(X, Y, Z, x_arr)

# momentum
res, x_arr = momentum([150,75], 0.016, g)
contour(X, Y, Z, x_arr)

def nesterov(x_start, step, g, discount = 0.7):
    x = np.array(x_start, dtype='float64')
    pre_grad = np.zeros_like(x)
    x_arr = [x.copy()]
    for i in range(50):
        x_future = x - step * discount * pre_grad
        grad = g(x_future)
        pre_grad = pre_grad * 0.7 + grad
        x -= pre_grad * step
        x_arr.append(x.copy())

        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if abs(sum(grad)) < 1e-6:
            break;
    return x, x_arr

res, x_arr = nesterov([150, 75], 0.012, g)
contour(X, Y, Z, x_arr)


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

import numpy as np
import pandas
import scipy
import statsmodels.api as sm

"""
In this optional exercise, you should complete the function called
predictions(turnstile_weather). This function takes in our pandas
turnstile weather dataframe, and returns a set of predicted ridership values,
based on the other information in the dataframe.

In exercise 3.5 we used Gradient Descent in order to compute the coefficients
theta used for the ridership prediction. Here you should attempt to implement
another way of computing the coeffcients theta. You may also try using a reference implementation such as:
http://statsmodels.sourceforge.net/devel/generated/statsmodels.regression.linear_model.OLS.html

One of the advantages of the statsmodels implementation is that it gives you
easy access to the values of the coefficients theta. This can help you infer relationships
between variables in the dataset.

You may also experiment with polynomial terms as part of the input variables.

The following links might be useful:
http://en.wikipedia.org/wiki/Ordinary_least_squares
http://en.wikipedia.org/w/index.php?title=Linear_least_squares_(mathematics)
http://en.wikipedia.org/wiki/Polynomial_regression

This is your playground. Go wild!

How does your choice of linear regression compare to linear regression
with gradient descent computed in Exercise 3.5?

You can look at the information contained in the turnstile_weather dataframe below:
https://s3.amazonaws.com/content.udacity-data.com/courses/ud359/turnstile_data_master_with_weather.csv

Note: due to the memory and CPU limitation of our amazon EC2 instance, we will
give you a random subset (~10%) of the data contained in turnstile_data_master_with_weather.csv

If you receive a "server has encountered an error" message, that means you are hitting
the 30 second limit that's placed on running your program. See if you can optimize your code so it
runs faster.
"""
def normalize_features(df):
    """
    Normalisa os features no conjunto de dados.
    """
    mu = df.mean()
    sigma = df.std()

    if (sigma == 0).any():
        raise Exception("One or more features had the same value for all samples, and thus could " + \
                         "not be normalized. Please do not include features with only a single value " + \
                         "in your model.")
    df_normalized = (df - df.mean()) / df.std()

    return df_normalized, mu, sigma

def predictions(weather_turnstile):
    #
    # Your implementation goes here. Feel free to write additional
    # helper functions
    #

     # seleção de features
    feature_names = ['meantempi','Hour']

    # iniciação de valores Y
    X = sm.add_constant(weather_turnstile[feature_names])
    Y = weather_turnstile['ENTRIESn_hourly']

    # iniciação de valores X ==> adiciona dummy units, standardize, e constant
    dummy_units = pandas.get_dummies(weather_turnstile['UNIT'], prefix='unit')
    X = weather_turnstile[feature_names].join(dummy_units)
    X, mu, sigma = normalize_features(X)
    X = sm.add_constant(X)

    # modelo de mínimos quadrados comuns
    model = sm.OLS(Y,X)

    # ajuste de modelo
    results = model.fit()
    #print results.summary()
    print 'R^2 = ', results.rsquared

    # previsão
    prediction = results.predict(X)
    return prediction

import numpy,import scipy,import statsmodels


# This code solves the problem of finding out the fourier transform for the
# function g(t) = A[u(t) - u(t-T)]

'''By the knowledge of fundamental concepts of
 fourier transform of unit function and time-shifting property
 '''
# WE KNOW THAT THE FINAL FOURIER TRANSFORM LOOKS LIKE
# G(iw) = A(1-exp(-iwT))(pi*delta(w) + 1/jw)

# IMport Modules
import numpy as np
import math
import matplotlib.pyplot as plt

def delta_function(w):
    if w == 0:
        return 1
    else:
        return 0

def imag_part_function_definer(A, w, T):
    return np.imag((A*(1-(np.exp(-1j*w*T))*(np.pi*delta_function(w) + (1/(1j*w))))))

def real_part_function_definer(A, w, T):
    return np.real((A*(1-(np.exp(-1j*w*T))*(np.pi*delta_function(w) + (1/(1j*w))))))

def imag_fourier_transform(low_frequency_range , high_frequency_range, T):
    pi = np.pi
    low_angular_frequency_range = 2*pi*low_frequency_range
    high_angular_frequency_range = 2*pi*high_frequency_range

    frequency_timestamps = np.linspace(low_angular_frequency_range, high_angular_frequency_range, 10000).flatten()

    y_values = [imag_part_function_definer(A = 10, w= w, T= T) for w in frequency_timestamps ]

    return (frequency_timestamps, y_values)

def real_fourier_transform(low_frequency_range , high_frequency_range, T):
    pi = np.pi
    low_angular_frequency_range = 2*pi*low_frequency_range
    high_angular_frequency_range = 2*pi*high_frequency_range

    frequency_timestamps = np.linspace(low_angular_frequency_range, high_angular_frequency_range, 10000).flatten()

    y_values = [real_part_function_definer(A = 10, w= w, T= T) for w in frequency_timestamps ]

    return (frequency_timestamps, y_values)

def imag_plotter():
    plt.plot(imag_fourier_transform(-10e+8,10e+8, 1)[0], imag_fourier_transform(-10e+8, 10e+8, 1)[1])
    plt.grid()
    plt.xlabel('VALUES OF FREQUENCY')
    plt.ylabel('IMAGINARY PART')

def real_plotter():
    plt.plot(real_fourier_transform(-10e+8,10e+8, 1)[0], real_fourier_transform(-10e+8, 10e+8, 1)[1])
    plt.grid()
    plt.xlabel('VALUES OF FREQUENCY')
    plt.ylabel('REAL PART')

if __name__ == "__main__":
   # Plotting both the real and imaginary parts with sub-plots on the same plot

    fig, (ax1, ax2) = plt.subplots(2, 1)
    ax1.plot(imag_fourier_transform(-10e+8,10e+8, 1)[0], imag_fourier_transform(-10e+8, 10e+8, 10e+3)[1])
    ax1.set_xlabel('VALUES OF FREQUENCY')
    ax1.set_ylabel('IMAGINARY PART')
    ax1.grid()

    ax2.plot(real_fourier_transform(-10e+8,10e+8, 1)[0], real_fourier_transform(-10e+8, 10e+8, 10e+3)[1])
    ax2.set_xlabel('VALUES OF FREQUENCY')
    ax2.set_ylabel('REAL PART')
    ax2.grid()

    plt.show()


import numpy as np

# Resting stance

# w - foot position away from hip servo / body at resting/neutral stance
# h - height form the floor
# A - upper leg length
# B - lower leg length
# theta = theta1 = theta2
# theta1 = angle of upper leg wrt to the horizontal
# theta2 = angle of the lower leg wrt to line perpendicular to the upper leg

def find_resting_stance_foot_position(theta, A=86, B=128):
  angle = np.radians(theta)
  w = A*np.cos(angle)
  h = B - A*np.sin(angle)
  return w, h

# propelling forward
# y - foot position from hip servo / body at sidestep stance
# v - foot position from hip servo / body at reaching stance
# beta - reach hip angle (theta in figure) (hip angle at reaching stance)
# alpha - sidestep hip angle (hip angle at side step stance)
# w - foot position away from the body at neutral/resting stance

def find_propel_forward_values(alpha, w):
  k = w*np.cos(np.radians(45)) # cos(45) == sin(45)
  alpha = np.radians(alpha)
  y = k / np.cos(alpha)
  c = k*np.tan(alpha) #  y * np.sin(alpha)
  m = (2*k + c) / k
  beta = np.arctan(m)
  v = k / np.cos(beta)
  return np.degrees(beta), v, y

# side step stance or reaching stance
# A - upper leg length
# B - lower leg length
# w - foot position away from hip servo / body at stance (reaching or sidestep stance)
# h - height form the floor
# theta1 = angle of upper leg wrt to the horizontal
# theta2 = angle of the lower leg wrt to line perpendicular to the upper leg
def find_stance_angles(w, h, A=86, B=128):
  C = np.sqrt(h**2 + w**2)
  x = np.arcsin(w / C)

  cos_gamma = (A**2 + B**2 - C**2) / (2*A*B)
  gamma = np.arccos(cos_gamma)
  cos_y = (A**2 + C**2 - B**2) / (2*A*C)

  y = np.arccos(cos_y)

  theta1 = x + y - np.radians(90)
  theta2 = np.radians(90) - gamma
  return np.degrees(theta1), np.degrees(theta2)

# A - upper leg length
# B - lower leg length
A = 86
B = 128

# theta1 = angle of upper leg wrt to the horizontal
# theta2 = angle of the lower leg wrt to line perpendicular to the upper leg

# beta - hip angle at reaching stance
# alpha - hip angle at side step stance

# theta = theta1 = theta2 angles at resting stance
THETA = 40 # Between 30 and 50
ALPHA = 5 # Between 0 and 20

w_resting, h = find_resting_stance_foot_position(THETA, A, B)
# w_resting - foot position away from hip servo / body at resting stance
# h - height from the floor (at resting stance)

# y_side_step - foot position from hip servo / body at sidestep stance
# v - foot position from hip servo / body at reaching stance
# beta - hip angle at reaching stance
BETA, v_reach, y_sidestep = find_propel_forward_values(ALPHA, w_resting)

theta1_sidestep, theta2_sidestep = find_stance_angles(y_sidestep, h, A, B)
theta1_reach, theta2_reach = find_stance_angles(v_reach, h, A, B)

print('Upper leg length in mm: ', A)
print('Lower leg length in mm: ', B)
print('Height from floor in mm: ', h)

print('-')
print("RESTING STANCE")
print("hip angle parallel to (shoulder) horizontal in degrees: 45")
print('knee angle parallel to (shoulder) horizonal in degrees: ', THETA)
print('ankle angle perpendicular to lowerleg in degrees: ', THETA)
print('foot position from hip in mm: ', w_resting)

print('-')
print("SIDESTEP STANCE")
print("hip angle parallel to (shoulder) horizontal in degrees:", ALPHA)
print('knee angle parallel to (shoulder) horizonal in degrees:', theta1_sidestep)
print('ankle angle perpendicular to lowerleg in degrees:', theta2_sidestep)
print('foot position from hip in mm: ', y_sidestep)

print('-')
print("REACHING STANCE")
print("hip angle parallel to (shoulder) horizontal in degrees:", BETA)
print('knee angle parallel to (shoulder) horizonal in degrees:', theta1_reach)
print('ankle angle perpendicular to lowerleg in degrees:', theta2_reach)
print('foot position from hip in mm: ', v_reach)

#neutral hip angle is 45
NEUTRAL = 45
hip_angle_resting = 0
hip_angle_sidestep = ALPHA + NEUTRAL
hip_angle_reach = BETA - NEUTRAL

print('-')
print("Absolute hip angles based on servo orientation (degrees):")
print("resting: ", hip_angle_resting)
print("side_step: ", hip_angle_sidestep)
print("reaching: ", hip_angle_reach)

# Upper leg length in mm:  86
# Lower leg length in mm:  128
# Height from floor in mm:  72.72026556695762
# -
# RESTING STANCE
# hip angle parallel to (shoulder) horizontal in degrees: 45
# knee angle parallel to (shoulder) horizonal in degrees:  40
# ankle angle perpendicular to lowerleg in degrees:  40
# foot position from hip in mm:  65.8798221082321
# -
# SIDESTEP STANCE
# hip angle parallel to (shoulder) horizontal in degrees: 5
# knee angle parallel to (shoulder) horizonal in degrees: 38.58250661168782
# ankle angle perpendicular to lowerleg in degrees: 47.7826582117061
# foot position from hip in mm:  46.76201253161473
# -
# REACHING STANCE
# hip angle parallel to (shoulder) horizontal in degrees: 64.40350450294298
# knee angle parallel to (shoulder) horizonal in degrees: 35.24987500744083
# ankle angle perpendicular to lowerleg in degrees: 18.169817718893693
# foot position from hip in mm:  107.82585845793648
# -
# Absolute hip angles based on servo orientation:
# resting:  0
# side_step:  50
# reaching:  19.40350450294298


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

#N Population Size
N = 1000
#Initial conditions and vector
I0 = 1
R0 = 0
S0 = 999
initial = S0, I0, R0
#time
t = np.linspace(0, 200, 200)

#SIR model
def SIRmodel(v, t, N, beta, gamma):
    """Determines three differential equations of the SIR model depending on initial
    conditions and chosen parameters. dSdt determines the rate of change of
    those that are not infected but are susceptible to being infected. dIdt
    determines the rate of change of the total infected individuals. dRdt
    determines the rate of change of the individuals who have recovered.

    Paramaters:
    v - vector of integers
    t - numeric sequence of form np.linspace(start, end, number of breakpoints)
    N - integer
    beta - float
    gamma - float

    Returns:
    Tuple of 3 floats, the change in the values of the differential
    equations of the model at one instant in time
    """
    S, I, R = v
    dSdt = (-1 * beta * S * I) / N
    dIdt = (beta * S * I / N) - (gamma * I)
    dRdt = gamma * I
    return dSdt, dIdt, dRdt

# Integrating and plotting the differential equations in the SIR model
def integrate_SIR(gamma, beta):
    """Plots the SIR model of disease for given gamma and beta parameters

    Parameters:
    gamma - float, reciprocal of average period of infectiousness
    beta - float, proportionality of how many people get into contact with the infected person.

    Returns:
    Plot of number of susceptible individuals, infected individuals, and
    recovered individuals over time
    """
    int_SIR = odeint(SIRmodel, initial, t, args=(N, beta, gamma))
    S, I, R = int_SIR.T

    # Plot S(t), I(t) and R(t)
    plt.plot(t, S, 'b', label='Susceptible Individuals')
    plt.plot(t, I, 'r', label='Infected Individuals')
    plt.plot(t, R, 'g', label='Recovered Individuals')
    plt.xlabel('Time (days)')
    plt.ylabel('Number of Individuals')
    plt.title('SIR Model of Disease Spread with \u03B3 = '+ str(round(gamma,2))+ ' \u03B2 = '+ str(beta))
    plt.legend()
    plt.show()

#Plotting for a variety of chosen beta and gamma parameters
integrate_SIR(1/10, 0.2)
integrate_SIR(1/10, 0.1)
integrate_SIR(1/7, 0.2)
integrate_SIR(1/14, 0.2)


# -*- coding: utf-8 -*-
import numpy as np

from . import utils

def kge(simulated, observed):
    """
    Calculate the Kling-Gupta efficiency.

    Calculates the Kling-Gupta efficiency between two variables
    simulated and observed. The kge is calculated using the
    formula:

    KGE = 1 - sqrt((cc-1)**2 + (alpha-1)**2 + (beta-1)**2)

    where:
        cc = correlation coefficient between simulated and observed;
        alpha = std(simulated) / std(observed)
        beta = sum(simulated) / sum(observed)

    where s is the simulated values, o is the observed values, and
    N is the total number of values in s & o. Note that s & o must
    have the same number of values.

    Kling-Gupta efficiency can range from -infinity to 1. An efficiency of 1 (E
    = 1) corresponds to a perfect match of model to observed data.
    Essentially, the closer the model efficiency is to 1, the more accurate the
    model is.

    The efficiency coefficient is sensitive to extreme values and might yield
    sub-optimal results when the dataset contains large outliers in it.

    Kling-Gupta efficiency can be used to quantitatively describe the accuracy
    of model outputs. This method can be used to describe the predictive
    accuracy of other models as long as there is observed data to compare the
    model results to.

    Input:
    simulated : simulated values
    observed : observed values

    Output:
    kge : Kling-Gupta Efficiency
    """
    # Check that dimensions of simulated and observed fields match
    utils.check_arrays(simulated, observed)

    alpha = np.std(simulated) / np.std(observed)
    beta = np.sum(simulated) / np.sum(observed)
    cc = np.corrcoef(observed, simulated)[0, 1]

    # Calculate the kge
    kge = 1.0 - np.sqrt((cc - 1.0) ** 2 + (alpha - 1.0) ** 2 + (beta - 1.0) ** 2)

    return kge


# -*- coding: utf-8 -*-
"""
Created on Fri Dec 22 15:17:39 2017

@author: Anastasios Tzavellas
"""

import numpy as np
import integration

def f(x):
    return np.power(x, 2) + np.power(x, 5)

IAnalytic = np.power(3, 3) / 3 + np.power(3, 6) / 6
print('Analytic')
print('Integral:', IAnalytic)

a = 0.
b = 3.
epsilon = 1e-2
trapezoid = integration.trapezoid(f, a, b, epsilon)
ITrapezoid = trapezoid['integral']
itTrapezoid = trapezoid['iterations']
print('\nTrapezoid')
print(trapezoid)
print('Deviation:', np.abs(IAnalytic - ITrapezoid))

simpson = integration.simpson(f, a, b, epsilon)
ISimpson = simpson['integral']
itSimpson = simpson['iterations']
print('\nSimpson 1/3')
print(simpson)
print('Deviation:', np.abs(IAnalytic - ISimpson))


import numpy as np
import scipy

__all__ = ['ar_yule_walker']

from ... import operators
from ... import utilits as ut

#------------------------------------------------------------------
def ar_yule_walker(x, order, mode='straight', unbias = False):
    '''
    Yule-Walker method for AutoRegressive (AR) model approximation.

    Parameters
    --------------
    * x: 1d ndarray,
        1-d input ndarray;
    * order: int,
        is the order of the desired model;
    * mode: string,
        mode of correlation function,
        mode = {full, same, straight}.
    * unbias: bool,
        if True, unbiased covariance function will be taken.

    Returns
    ------------------
    * a: 1d ndarray (complex (or float)),
        autoregression coefficients.
    * noise_variace: complex (or float),
        variance of model residulas.

    Notes
    ---------
    * If mode 'full',
        array of doubled size will be returned.
    * Yule-Walker method:
      ..math::
      r1 = -toeplitz(r_0,...r_{p-1})A^T,

      where
      * r  = [r_0,r_1,...r_{p-1}]
          - autocorrelation coefficients;
      * r1 = [r_1,r_1,...r_p]^T
          -set of required approximation results;
      * p  is the model order;
      * toeplitz is the operator
          for obtaining toeplitz matrix from vector;
      * A={a_1,...,a_p}
          are the approcimation coefficients
                                      of autoregression model
        with the order p, in the following form:
        r_m = \sum_{k=1}^p {a_k r_{m-k}}+\sigma^2
        where \sigma^2
            is the ewsidual noise, which can be calulated as
        \sigma = sqrt(r_0 + \sum(r_1^* \cdot a)).

    Examples
    --------------

    References
    -------------
    [1a] P. Stoica, R.L.
        Moses, Spectral analysis of signals
        - New-York: Present-Hall, 2005.
    [1b] http://www2.ece.ohio-state.edu/~randy/SAtext/
        - Dr.Moses Spectral Analysis of Signals: Resource Page
    [2a] M.H. Hayes.
        Statistical Digital Signal Processing and Modeling,
        John Wiley & Sons, 1996.
    [2b] https://www.mathworks.com/matlabcentral/fileexchange/
        2183-statistical-digital-signal-processing-and-modeling
    [3]  S.L. Marple, Digital spectral analysis with applications.
                                – New-York: Present-Hall, 1986.

    See also
    ----------
    toeplitz;
    covar;
    levenson_durbin;
    burg.

    '''
    x = np.asarray(x)
    N = x.shape[0]

    r  = operators.correlation(x, y=None, mode=mode,
                            take_mean=False, unbias=unbias)

    rn = scipy.linalg.toeplitz(r[:order])

    r1 = r[1:order + 1]

#     a  = np.dot(np.linalg.inv(rn),r1)
    a = scipy.linalg.lstsq(rn,r1)[0]
    noise_var = np.real(r[0] - np.dot(np.conj(r1),a))

    a = np.append(1,-a)

    return a, noise_var


# shows how linear regression analysis can be applied to 2-dimensional data
#
# notes for this course can be found at:
# https://deeplearningcourses.com/c/data-science-linear-regression-in-python
# https://www.udemy.com/data-science-linear-regression-in-python

#from __future__ import print_function, division
#from builtins import range
# Note: you may need to update your version of future
# sudo pip install -U future

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

# load the data
X = []
Y = []
for line in open('data_2d.csv'):
    x1, x2, y = line.split(',')
    X.append([float(x1), float(x2), 1]) # add the bias term
    Y.append(float(y))

# let's turn X and Y into numpy arrays since that will be useful later
X = np.array(X)
Y = np.array(Y)

# let's plot the data to see what it looks like
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[:,0], X[:,1], Y)
plt.show()

# apply the equations we learned to calculate a and b
# numpy has a special method for solving Ax = b
# so we don't use x = inv(A)*b
# note: the * operator does element-by-element multiplication in numpy
#       np.dot() does what we expect for matrix multiplication
w = np.linalg.solve(np.dot(X.T, X), np.dot(X.T, Y))
Yhat = np.dot(X, w)

# determine how good the model is by computing the r-squared
d1 = Y - Yhat
d2 = Y - Y.mean()
r2 = 1 - d1.dot(d1) / d2.dot(d2)
print("the r-squared is:", r2)


# import cython
from scipy.special import erf
from numpy import log, exp, sqrt

# cimport cython
# from libc.math cimport exp, sqrt, pow, log, erf
#
# @cython.cdivision(True)
# cdef double std_norm_cdf(double x) nogil:
#     return 0.5*(1+erf(x/sqrt(2.0)))
#
# @@cython.cdivision(True)
# def blsprice(double s, double k, double t, double v,
#                  double rf, double div, double cp):
#     """Price an option using the Black-Scholes model.
#
#     s : initial stock price
#     k : strike price
#     t : expiration time
#     v : volatility
#     rf : risk-free rate
#     div : dividend
#     cp : +1/-1 for call/put
#     """
#     cdef double d1, d2, optprice
#     with nogil:
#         d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))
#         d2 = d1 - v*sqrt(t)
#         optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1) - \
#             cp*k*exp(-rf*t)*std_norm_cdf(cp*d2)
#     return optprice

def std_norm_cdf(x):
    return 0.5*(1+erf(x/sqrt(2.0)))

def blsprice(s, k, rf, t, v, div=0, cp=1):
    d1 = (log(s / k) + (rf - div + 0.5*pow(v, 2)) * t) / (v * sqrt(t))
    d2 = d1-v*sqrt(t)
    optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1) - \
           cp*k*exp(-rf*t)*std_norm_cdf(cp*d2)
    return optprice


#Lucas number

def LucasNumber(index,roundi=True):
    from sympy import Pow as mmmpow
    from sympy import Integer as mmmint
    from sympy import N as mmmrat
    b = (mmmpow(((1+5**(1/2))/2),index))+(mmmpow(((1-5**(1/2))/2),index))
    if(not roundi):
        return mmmint(b)
    else:
        return mmmrat(b)

def LucasSequence(countt,returni=True):
    s = [2,1]
    for n in range(2,countt):
        s.append(s[n-1]+s[n-2])
    if(returni):
        return s
    else:
        print(s)

def isPrime_Lucas(p,returnNums=True,roundi=True):
    l = LucasNumber(p,roundi)
    if((l-1)%p!=0):
        if(returnNums):
        	return l
        else:
        	return True
    return False

def doTest(toPrint=False,toProgress=False,start=0,toEnd=1000,algo="s"):
    s=set()
    KK=10000
    from IPython.display import clear_output
    for i in range(start,toEnd+1):
        if(toProgress and (i<KK or (i>=KK and i%(KK/100)==0))):
            clear_output(wait=True)
            print(i,end="\t")
        if(algo=="s"):
            lucas = LucasNumber(i)
        elif(algo=="prime"):
            lucas = isPrime_Lucas(i)
        if(lucas):
            s.add(lucas)
            if(toPrint and not toProgress):
                print(lucas,end=", ")
        if(toProgress and (i<KK or (i>=KK and i%(KK/100)==0))):
            print(s)
    if(not toPrint):
        return s

#LucasNumber(0)
#doTest(True,False,0,800) #1.69 s
#LucasSequence(800) #30 ms
#isPrime_Lucas(10)
#doTest(False,False,1,10000,"prime")


import open3d as o3d
import numpy as np

# http://www.open3d.org/docs/release/tutorial/geometry/working_with_numpy.html

########################################################################################################################
# 1. Working with NumPy
########################################################################################################################
# Generate some neat n times 3 matrix using a variant of sync function
x = np.linspace(-3, 3, 401)
mesh_x, mesh_y = np.meshgrid(x, x)
z = np.sinc((np.power(mesh_x, 2) + np.power(mesh_y, 2)))
z_norm = (z - z.min()) / (z.max() - z.min())
xyz = np.zeros((np.size(mesh_x), 3))
xyz[:, 0] = np.reshape(mesh_x, -1)
xyz[:, 1] = np.reshape(mesh_y, -1)
xyz[:, 2] = np.reshape(z_norm, -1)
print('xyz')
print(xyz)

########################################################################################################################
# 2. From NumPy to open3d.PointCloud
########################################################################################################################
# Pass xyz to Open3D.o3d.geometry.PointCloud and visualize
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(xyz)
o3d.io.write_point_cloud("sync.ply", pcd)

########################################################################################################################
# 3. From open3d.PointCloud to NumPy
########################################################################################################################
# Load saved point cloud and visualize it
pcd_load = o3d.io.read_point_cloud("sync.ply")

# Convert Open3D.o3d.geometry.PointCloud to numpy array
xyz_load = np.asarray(pcd_load.points)
print('xyz_load')
print(xyz_load)
o3d.visualization.draw_geometries([pcd_load], width=800, height=600)


import numpy as np
import matplotlib.pyplot as plt

N=51
initial=-np.pi
final=np.pi
x=np.linspace(initial,final,N)
h=(final-initial)/(N-1)

#analytic:
y_ana=np.sin(x)
dy_ana=np.cos(x)
ddy_ana=-np.sin(x)

ddy_3=[]
for i in range(1,N-1):
    ddy_3.append((y_ana[i+1]-2*y_ana[i]+y_ana[i-1])/h/h)

x3=np.delete(x,[0,N-1])

plt.plot(x,ddy_ana)
plt.plot(x3,ddy_3,'r.',label="three points")
plt.show()

error3=(abs(ddy_3-ddy_ana[1:N-1]))
plt.plot(x3,error3,label="three points")
plt.title("error by using different number of points")
plt.legend()
plt.show()


import numpy as np
import math

## Integrand function
def f(x): return x**5+x**4

## 1st Interval
a=-1.0
b=-0.4
n1=100
x1=np.random.uniform(a,b,n1)  # [a,b]=[-1.0,-0.4]
k=np.linspace(0.35,1,50)
eval_funct1=f(x1)
n1=n1*1.0
i1=(b-a)*(np.sum(eval_funct1)/n1) # mean
mu_camp1=(np.sum(eval_funct1))/n1
var_camp1=(1/(n1-1))*np.sum((eval_funct1-mu_camp1)**2)  # variance
var1=(b-a)**2*(1/n1)*var_camp1

## 2nd Interval
a=-0.4
b=0.4
n2=100
x2=np.random.uniform(a,b,n2)  # [a,b]=[-0.4,0.4]
eval_funct2=f(x2)
n2=n2*1.0
i2=(b-a)*(np.sum(eval_funct2)/n2) # mean
mu_camp2=(np.sum(eval_funct2))/n2
var_camp2=1/(n2-1)*np.sum((eval_funct2-mu_camp2)**2)  # variance
var2=(b-a)**2*(1/n2)*var_camp2

## 3rd Interval
a=0.4
b=0.6
n3=800
x3=np.random.uniform(a,b,n3)  # [a,b]=[0.4,0.6]
eval_funct3=f(x3)
n3=n3*1.0
i3=(b-a)*(np.sum(eval_funct3)/n3) # mean
mu_camp3=(np.sum(eval_funct3))/n3
var_camp3=1/(n3-1)*np.sum((eval_funct3-mu_camp3)**2)  # variance
var3=(b-a)**2*(1/n3)*var_camp3

## 4th Interval
a=0.6
b=0.7
n4=1000
x4=np.random.uniform(a,b,n4)  # [a,b]=[0.6,0.7]
eval_funct4=f(x4)
n4=n4*1.0
i4=(b-a)*(np.sum(eval_funct4)/n4) # mean
mu_camp4=(np.sum(eval_funct4))/n4
var_camp4=1/(n4-1)*np.sum((eval_funct4-mu_camp4)**2)  # variance
var4=(b-a)**2*(1/n4)*var_camp4

## 5th Interval
a=0.7
b=0.8
n5=1500
x5=np.random.uniform(a,b,n5)  # [a,b]=[0.7,0.8]
eval_funct5=f(x5)
n5=n5*1.0
i5=(b-a)*(np.sum(eval_funct5)/n5) # mean
mu_camp5=(np.sum(eval_funct5))/n5
var_camp5=1/(n5-1)*np.sum((eval_funct5-mu_camp5)**2)  # variance
var5=(b-a)**2*(1/n5)*var_camp5

## 6th Interval
a=0.8
b=0.9
n6=3000
x6=np.random.uniform(a,b,n6)  # [a,b]=[0.8,0.9]
eval_funct6=f(x6)
n6=n6*1.0
i6=(b-a)*(np.sum(eval_funct6)/n6) # mean
mu_camp6=(np.sum(eval_funct6))/n6
var_camp6=1/(n6-1)*np.sum((eval_funct6-mu_camp6)**2)  # variance
var6=(b-a)**2*(1/n6)*var_camp6

## 7th Interval
a=0.9
b=1.0
n7=3500
x7=np.random.uniform(a,b,n7)  # [a,b]=[0.9,1]
eval_funct7=f(x7)
n7=n7*1.0
i7=(b-a)*(np.sum(eval_funct7)/n7) # mean
mu_camp7=(np.sum(eval_funct7))/n7
var_camp7=1/(n7-1)*np.sum((eval_funct7-mu_camp7)**2)  # variance
var7=(b-a)**2*(1/n7)*var_camp7

## Results
print(n1+n2+n3+n4+n5+n6+n7,'Check on total number of generations [has to be 10^4]')

S=i1+i2+i3+i4+i5+i6+i7
print(S,'Total mean for S, with Stratified Sampling')

var=var1+var2+var3+var4+var5+var6+var7
print(var ,'Total variance for S, with Stratified Sampling')

dev = sqrt(var)
print(dev ,'Total standard deviation for S, with Stratified Sampling')


import numpy as np

def rk2(t, y, h, f):
    k_1 = h*f(t,y)
    k_2 = h*f(t + h/2.0, y+k_1/2.0)
    y = y + k_2
    return y

def rk4(t, y, h, f):
    k_1 = h*f(t,y)
    k_2 = h*f(t + h/2.0, y + k_1/2.0)
    k_3 = h*f(t + h/2.0, y + k_2/2.0)
    k_4 = h*f(t + h, y + k_3)
    y = y + (1.0/6.0)*(k_1 + 2.0*k_2 + 2.0*k_3 +k_4)
    return y

def rk45(t, y, h, f, err_tol, h_min, h_max):
    k_1 = h*f(t, y)
    k_2 = h*f(t + h/4.0, y + k_1/4.0)
    k_3 = h*f(t + 3.0*h/8.0, y + 3.0*k_1/32.0 +9.0*k_2/32.0)
    k_4 = h*f(t + 12.0*h/13.0, y+1932.0*k_1/2197.0 - 7200.0*k_2/2197.0 +7296.0*k_3/2197.0)
    k_5 = h*f(t + h, y + 439.0*k_1/216.0 - 8.0*k_2 + 3680.0*k_3/513.0 -845.0*k_4/4104.0)
    k_6 = h*f(t + h/2.0, y - 8.0*k_1/27.0 + 2.0*k_2 - 3544.0*k_3/2565.0 + 1859.0*k_4/4104.0 - 11.0*k_5/40.0)
    Y = y + 25.0*k_1/216.0 + 1408.0*k_3/2565.0 + 2197.0*k_4/4101.0 - k_5/5.0
    Z = y + 16.0*k_1/135.0 + 6656.0*k_3/12825.0 +28561.0*k_4/56430.0 - 9.0*k_5/50.0 + 2.0*k_6/55.0
    err = np.abs(Z - Y)
    if (err[0] == 0 or err[1] == 0):
        s = 0.0
    else:
        s = 0.84*np.power(err_tol*h/err[0], 0.25)
    if (s < 0.75 and h > 2*h_min):
        h /= 2.0
    elif (s > 1.5 and h < h_max/2.0):
        h *= 2.0
    return h,Z


import argparse
import sys
import numpy as np
import csv

parser = argparse.ArgumentParser(
        description='sum the integers at the command line')
parser.add_argument(
    "-equation_coefficients",
    "--coeffs",
    required=False,
    help='a csv file with coefficients of linear system to solve')
parser.add_argument(
    "-n_unknowns",
    "--n",
    required=False,
    help='number of uknowns')

def gaussian_elimination(args):
    # promt user for input if none provided
    if not args.n:
        n = input("Number of unknowns: ")
        n = int(n)
    else:
        n = int(args.n)
    AugM = np.zeros((n,n+1))
    Soln = np.zeros(n)

    if not args.coeffs:
        print("Inputs needed for system in form Ax = B")
        for k in range(n):
            for j in range(n):
                AugM[k][j] = int(input(f"Enter coefficient for equation {k+1}, unknown {j+1}: "))
            AugM[k][n] = int(input(f"Enter solution for equation{k+1}: "))

    else:
        csv_file = args.coeffs
        with open(csv_file, newline='') as f:
            reader = csv.reader(f)
            for rdx, row in enumerate(reader):
                for idx, num in enumerate(row):
                    AugM[rdx][idx] = str(num)

    # Gaussian Elimination
    for k in range(n-1):
        if AugM[k][k] == 0:
            # need to choose a non-zero pivot row
            for i in range(k+1, n):
                if AugM[i][k] != 0:
                    # permute row s i and k
                    temp = AugM[i].copy()
                    AugM[i] = AugM[k]
                    AugM[k] = temp
                    break

        # Continue to get zero entries below diagonal
        for i in range(k+1, n):
            factor = AugM[i][k]/AugM[k][k]
            AugM[i] = AugM[i] - factor*AugM[k]

    # Check for existence of a solution
    for k in range(n):
        if AugM[k][k] == 0:
            print("No unique solution!")
            return

    # Back substitution
    Soln[n-1] = AugM[n-1][n]/AugM[n-1][n-1]
    for i in range(n-2, -1, -1):
        sum = np.matmul(AugM[i][i+1:n],Soln[i+1:])
        Soln[i] = (AugM[i][n] - sum)/AugM[i][i]

    print("Solution is : ", Soln)
    return Soln

if __name__== "__main__":

    args = parser.parse_args(sys.argv[1:])
    gaussian_elimination(args)


# -*- coding: utf-8 -*-
"""
Created on Wed Mar  4 09:53:57 2020

@author: Gualandi
"""

from pyomo.environ import ConcreteModel, Var, Objective, Constraint, SolverFactory
from pyomo.environ import maximize, Binary, RangeSet, PositiveIntegers

def MagicSquareSolver(n):
    # Create concrete model
    model = ConcreteModel()

    # Set of indices
    model.I = RangeSet(1, n)
    model.J = RangeSet(1, n)
    model.K = RangeSet(1, n*n)

    # Variables
    model.z = Var(within=PositiveIntegers)
    model.x = Var(model.I, model.J, model.K, within=Binary)

    # Objective Function
    model.obj = Objective(expr = model.z)

    def Unique(model, k):
        return sum(model.x[i,j,k] for j in model.J for i in model.I) == 1
    model.unique = Constraint(model.K, rule = Unique)

    def CellUnique(model, i, j):
        return sum(model.x[i,j,k] for k in model.K) == 1
    model.cellUnique = Constraint(model.I, model.J, rule = CellUnique)

    def Row(model, i):
        return sum(k*model.x[i,j,k] for j in model.J for k in model.K) == model.z
    model.row = Constraint(model.I, rule = Row)

    def Col(model, j):
        return sum(k*model.x[i,j,k] for i in model.I for k in model.K) == model.z
    model.column = Constraint(model.J, rule = Col)

    model.diag1 = Constraint(expr = sum(k*model.x[i,i,k] for i in model.I for k in model.K) == model.z)
    model.diag2 = Constraint(expr = sum(k*model.x[i,n-i+1,k] for i in model.I for k in model.K) == model.z)

    # Write the LP model in standard format
    model.write("magic_{}.lp".format(n))

    # Solve the model
    sol = SolverFactory('glpk').solve(model)

    # CHECK SOLUTION STATUS

    # Get a JSON representation of the solution
    sol_json = sol.json_repn()
    # Check solution status
    if sol_json['Solver'][0]['Status'] != 'ok':
        return None
    if sol_json['Solver'][0]['Termination condition'] != 'optimal':
        return None

    return model.x

def PlotMagicSquare(x, n):
    # Report solution value
    import matplotlib.pyplot as plt
    import numpy as np
    import itertools

    sol = np.zeros((n,n), dtype=int)

    for i, j, k in x:
        if x[i,j,k]() > 0.5:
            sol[i-1,j-1] = k

    cmap = plt.get_cmap('Blues')

    plt.figure(figsize=(6,6))
    plt.imshow(sol, interpolation='nearest', cmap=cmap)
    plt.title("Magic Square, Size: {}".format(n))
    plt.axis('off')

    for i, j in itertools.product(range(n), range(n)):
        plt.text(j, i, "{:d}".format(sol[i, j]),
                 fontsize=24, ha='center', va='center')

    plt.tight_layout()
    plt.show()

# -----------------------------------------------
#   MAIN function
# -----------------------------------------------
if __name__ == "__main__":

    # Solve Magic Square of size 4
    n = 4

    x = MagicSquareSolver(n)
    if x:
        PlotMagicSquare(x, n)
    else:
        print("Unable to solve Magic Square of size", n)


from sympy import *
x = symbols('x')
x0 = 1
x_list = [x0]
i = 0
# func
f = lambda x : exp(x) - 1

while True:
    # 判断分母是否为0，如果是0直接跳出
    if diff(f(x),x).subs(x,x0) != 0:
        x0 = x0 - f(x0) / diff(f(x), x).subs(x, x0)
        x_list.append(x0)
    else:
        break
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        if error < 10 ** (-4):
            print(f'迭代第{i}次后，误差小于10^(-8)，误差为{error}')
            break

print(f'所求方程式的根为{float(x_list[-1])}')


import numpy as np
import matplotlib.pyplot as plt

z = np.arange(-5,5,.1)

sigma_fn = np.vectorize(lambda  z : 1.0/(1.0+np.exp(-z))) #for each element do this and return
#y = 1.0/(1.0+np.exp(-z))
y = sigma_fn(z)

fig = plt.figure()

ax = fig.add_subplot(1,1,1)

ax.plot(z,y)
ax.set_xlim([-5,5])
ax.set_ylim([-0.5,1.5])
ax.set_title('Sigmoid Function')
ax.set_xlabel('z')
ax.grid(True)

plt.show()


from keras.models import Sequential
from keras.layers import Dense, Activation

import numpy as np

# 10.5, 5, 9.5, 12 => 18.5

model = Sequential()

model.add(Dense(8, activation='relu', input_dim=4))
model.add(Dense(16, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='linear'))

model.compile(optimizer='adam', loss='mean_squared_error')

x_train = np.array([
  [1, 2, 3, 4],
  [4, 6, 1, 2],
  [10, 9, 10, 11],
  [10, 12, 9, 13],
  [99, 100, 101, 102],
  [105, 111, 109, 102],
  [3, 7, 4, 1],
  [1, 8, 3, 7],
  [12, 15, 11, 9],
  [9, 15, 10, 11],
  [110, 99, 105, 101],
  [97, 101, 100, 105]
])

y_train = np.array([
  [2.5],
  [3.25],
  [10.0],
  [11.0],
  [100.5],
  [106.75],
  [3.75],
  [4.75],
  [11.75],
  [11.25],
  [103.75],
  [100.75]
])

# perm = permutation of numbers that match the size of the output array = act
# of arranging all the members of a set into some sequence or order
# gives us a random array of array indices that we can use to reset
# the order of our X and Y arrays
perm = np.random.permutation(y_train.size)
x_train = x_train[perm]
y_train = y_train[perm]

# 'validation_split' = a decimal between 0 & 1 ...represents the
# percentage of the training data to use as the validation data set
#  split into 20 percent validation and 80 percent training for this example
#  when using Keras's automatic validation split : always takes the last X percent of
#  the data that you give it, so that if you have ordered data of any kind, you may want to shuffle your data before training
model.fit(
  x_train,
  y_train,
  epochs=100,
  batch_size=2,
  verbose=1,
  validation_split=0.2
)

# retrain the network with the validation set..there is an extra 'val_loss'
# output value = the mean squared error loss on the validation set.
# key thing to look for, though, is that the loss and the validation loss are
# more consistent as you increase the amount of data that you give the network.
#
#


import numpy as np
import matplotlib.pyplot as plt

# Hidden layers are best represented with non-linearity for deeper representations
# Sigmoid, tanh, RelU
# Output layers are generally used with Linear, sigmoid, softmax
# Multilayer Perceptron (MLP): ReLU activation function.
# Convolutional Neural Network (CNN): ReLU activation function.
# Recurrent Neural Network: Tanh and/or Sigmoid activation function.

# Sigmoid activation function (logistic fn)
# Outputs between 0, 1  succeptible to vanishing gradient problem
# scale input data to the range 0-1 (e.g. the range of the activation function) prior to training.
def sigmoid(z):
    soln = 1.0/(1.0+np.exp(-z))
    return(soln)

# Sigmoid derivative
def deriv_sigmoid(z):
    soln = sigmoid(z)*(1.0-sigmoid(z))
    return(soln)

# Tanh activation function
# Outputs -1, 1  succeptible to vanishing gradient problem
# scale input data to the range -1 to 1 (e.g. the range of the activation function) prior to training.
def tanh(z):
    soln = (np.exp(z) - np.exp(-z)) / (np.exp(z) + np.exp(-z))
    return(soln)

# tanh derivative
def deriv_tanh(z):
    soln = 1.0/((np.cosh(z))**2)
    return(soln)

# Relu activation function
# less susceptible to vanishing gradients that prevent deep models from being trained, although it can suffer from other problems like saturated or “dead” units.
# Normalize input data for 0-1 (good practice)
def ReLU(z):
    soln = np.maximum(0.0, z)
    return(soln)

# Relu derivative
def deriv_ReLU(z):
    if z > 0.0:
        return(1.0)
    else:
        return(0.0)

# Linear activation function (identity)
def linear(z):
    return(z)

def deriv_linear(z):
    return(1)

# Softmax
# outputs a vector of values that sum to 1.0 that can be interpreted as probabilities of class membership.
# Target labels used to train a model with the softmax activation function in the output layer will be vectors with 1 for the target class and 0 for all other classes.
def softmax(z):
    soln_vector = np.array([])
    for element in z:
        soln = np.exp(element) / np.exp(z).sum()
        soln_vector = np.append(soln_vector, soln)
    return(soln_vector)

# partial derivative of the i-th output w.r.t. the j-th input (input = j_vector, output = i_vector)
def deriv_softmax(soft_in_j, soft_out_i):
    soln_matrix = np.array([])
    for i in range(soft_out_i.size):            # iterate through i and j
        row = np.array([])
        for j in range(soft_in_j.size):
            if i == j:                          # Calculate delta
                delta = 1
            else:
                delta = 0

            soln = soft_out_i[i]*(delta-soft_out_i[j])          # soln Find element value
            row = np.append(row, soln)                          # Append until row is complete
        soln_matrix = np.append(soln_matrix, row)               # append row to soln_matrix
    soln_matrix = soln_matrix.reshape((soft_out_i.size, soft_in_j.size)) #reshape to ixj 2D matrix
    return(soln_matrix)

# Function plots

# define input data
#inputs = [x for x in range(-10, 10)]
#sigmoid_out = [sigmoid(x) for x in inputs]
#tanh_out = [tanh(x) for x in inputs]
#ReLU_out = [ReLU(x) for x in inputs]
#linear_out = [linear(x) for x in inputs]

# softmax is probability list and cannot be graphed
#soft_inputs = np.arange(5.0)
#softmax_out = softmax(soft_inputs)
#deriv_softmax(soft_inputs, softmax_out)

# Setup subplots

#plt.subplot(3,3,1)
#plt.title('Sigmoid')
#plt.plot(inputs, sigmoid_out)

#plt.subplot(3,3,2)
#plt.title('tanh')
#plt.plot(inputs, tanh_out)

#plt.subplot(3,3,3)
#plt.title('ReLU')
#plt.plot(inputs, ReLU_out)

#plt.subplot(3,3,4)
#plt.title('Linear')
#plt.plot(inputs, linear_out)

#plt.show()


import matplotlib.pyplot as plt
import numpy as np
import os
os.chdir('C:/Users/DELL/Desktop/Quant_macro')
import useful_functions as uf
######## parameters part 1 ##################
alpha = 1
rho2 = 1/100
rho1 = [1/0.2, 1/0.25]
Px = [lambda x, n=i: np.exp(-alpha*x)/(rho1[n] + rho2*np.exp(-alpha*x)) for i in range(len(rho1))]
order = 4
num_nodes = 6
size_grid = 300
func = uf.chebychev_pol(order)
grid = uf.cheb_node(0,10,size_grid)
nodes = uf.select_node(num_nodes, grid)

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

para = uf.find_theta_cheb(Px[0],nodes, order)
f_til = lambda x: sum(para[idx]* function(x) for idx, function in enumerate(func))
Px_0 = Px[0](grid)
poly = f_til(grid)
diff = np.abs(np.array(Px_0)-np.array(poly))
f, (ax,ax_diff) = plt.subplots(1,2)
f.set_figheight(5)
f.set_figwidth(10)
ax.plot(grid, Px_0, color='r', label='rho1=5')
ax.plot(grid, poly, color='b', label='poly_cub')
ax_diff.plot(grid, diff, color='b', label='diff_cub')
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
ax.set_title('Chebyshev polynomial rho1 = 5')
ax_diff.set_xlabel('x')
ax_diff.set_ylabel('f(x)')
ax_diff.set_title('Chebyshev polynomial error')

################################################
para1 = uf.find_theta_cheb(Px[1],nodes,order)
f_til1 = lambda x: sum(para1[idx]* function(x) for idx, function in enumerate(func))
Px_1 = Px[1](grid)
poly1 = f_til1(grid)
diff1 = np.abs(np.array(Px_1)-np.array(poly1))
f1, (ax1, ax1_diff) = plt.subplots(1,2)
f1.set_figheight(5)
f1.set_figwidth(10)
ax1.plot(grid, Px_1, color='r', label='rho1=4')
ax1.plot(grid, poly1, color='b', label='poly_cub')
ax1_diff.plot(grid, diff1, color='b', label='diff_cub')
ax1.set_xlabel('x')
ax1.set_ylabel('f(x)')
ax1.set_title('Chebyshev polynomial rho1 = 4')
ax1_diff.set_xlabel('x')
ax1_diff.set_ylabel('f(x)')
ax1_diff.set_title('Chebyshev polynomial error')

g1, alx1 = plt.subplots(1,1)
g1.set_figheight(5)
g1.set_figwidth(10)
alx1.plot(grid, poly, color='r', label='rho1=5')
alx1.plot(grid, poly1, color='b', label='rho1=4')
alx1.set_xlabel('x')
alx1.set_ylabel('f(x)')
alx1.set_title('Chebyshev order 3 polynomial: 2 cases')

#########################################################
###################   monomials  5 ######################
#########################################################

######## parameters order 5 ##################

order_o5 = 6
func_o5 = uf.chebychev_pol(order_o5)
############################################

############################################
para_o5 = uf.find_theta_cheb(Px[0],nodes,order_o5)
f_til_o5 = lambda x: sum(para_o5[idx]* function(x) for idx, function in enumerate(func_o5))
poly_o5 = f_til_o5(grid)
diff_o5 = np.abs(np.array(Px_0)-np.array(poly_o5))
ax.plot(grid, poly_o5, color='g', label='poly_o5')
ax_diff.plot(grid, diff_o5, color='g', label='diff_o5')
################################################
para1_o5 = uf.find_theta_cheb(Px[1],nodes,order_o5)
f_til1_o5 = lambda x: sum(para1_o5[idx]* function(x) for idx, function in enumerate(func_o5))
poly1_o5 = f_til1_o5(grid)
diff1_o5 = np.abs(np.array(Px_1)-np.array(poly1_o5))
ax1.plot(grid, poly1_o5, color='g', label='poly_o5')
ax1_diff.plot(grid, diff1_o5, color='g', label='diff_o5')

g2, alx2 = plt.subplots(1,1)
g2.set_figheight(5)
g2.set_figwidth(10)
alx2.plot(grid, poly_o5, color='r', label='rho1=5')
alx2.plot(grid, poly1_o5, color='b', label='rho1=4')
alx2.set_xlabel('x')
alx2.set_ylabel('f(x)')
alx2.set_title('Chebyshev order 5 polynomial: 2 cases')
#########################################################
###################   monomials  10 ######################
#########################################################

######## parameters order 5 ################## diff = np.abs(np.array()-np.array())

order_o10 = 11
func_o10 = uf.chebychev_pol(order_o10)
num_nodes_o10 = 20
############################################

############################################
nodes_o10 = uf.select_node(num_nodes_o10, grid)
para_o10 = uf.find_theta_cheb(Px[0],nodes_o10,order_o10)
f_til_o10 = lambda x: sum(para_o10[idx]* function(x) for idx, function in enumerate(func_o10))
poly_o10 = f_til_o10(grid)
diff_o10 = np.abs(np.array(Px_0)-np.array(poly_o10))
ax.plot(grid, poly_o10, color='gold', label='poly_o10')
ax_diff.plot(grid, diff_o10, color='gold', label='diff_o10')
################################################
nodes1_o10 = uf.select_node(num_nodes_o10, grid)
para1_o10 = uf.find_theta_cheb(Px[1],nodes1_o10,order_o10)
f_til1_o10 = lambda x: sum(para1_o10[idx]* function(x) for idx, function in enumerate(func_o10))
poly1_o10 = f_til1_o10(grid)
diff1_o10 = np.abs(np.array(Px_1)-np.array(poly1_o10))
ax1.plot(grid, poly1_o10, color='gold', label='poly_o10')
ax1_diff.plot(grid, diff1_o10, color='gold', label='diff_o10')

##########################
g3, alx3 = plt.subplots(1,1)
g3.set_figheight(5)
g3.set_figwidth(10)
alx3.plot(grid, poly_o10, color='r', label='rho1=5')
alx3.plot(grid, poly1_o10, color='b', label='rho1=4')
alx3.set_xlabel('x')
alx3.set_ylabel('f(x)')
alx3.set_title('Chebyshev order 10 polynomial: 2 cases')

alx1.legend(loc = 'upper right')
alx2.legend(loc = 'upper right')
alx3.legend(loc = 'upper right')

ax_diff.legend(loc = 'upper right')
ax_diff.set_xlabel('x')
ax_diff.set_ylabel('f(x)')

ax1_diff.legend(loc = 'upper right')
ax1_diff.set_xlabel('x')
ax1_diff.set_ylabel('f(x)')

ax.legend(loc='upper right')
ax1.legend(loc='upper right')


import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix

class Perceptron :

    def __init__(self,learning_rate = 0.1 , number_iter = 1000):
        self.learning_rate = learning_rate
        self.number_iter   = number_iter

    def fit(self,x,y):
        self.x = x
        self.y = y

    def initParameters(self , x):
        w = np.random.randn(1,x.shape[1])
        return w

    def heaviside(self,x):
        return 1 if x>= 0 else 0

    def heavisideArray(self,x):
        a = [1 if x1>= 0 else 0 for x1 in x[0]]
        return a

    def train(self):
        self.w = self.initParameters(self.x)

        for i in range(self.number_iter):
            for x , y in zip(self.x , self.y):
                z = np.dot(self.w , x)
                y_hat = self.heaviside(z)
                self.w += self.learning_rate * (y - y_hat) * x
        #self.displayModel()

    def predict(self,x):
        z = np.dot(self.w , x)
        a = self.heavisideArray(z)
        return a

    def displayModel(self):
        fig , ax = plt.subplots(figsize=(10,7))
        ax.scatter(self.x[:,0] , self.x[:,1] , c = self.y , cmap="bwr")
        x1 = np.linspace(-15,4,100)
        x2 = (-self.w[0][0] * x1 - self.w[0][2]) / self.w[0][1]
        ax.plot(x1,x2 , c='g' , lw=8)

x , y = make_blobs(n_samples=200 , n_features=2 , centers=2 , random_state= 0)

x_train , x_test , y_train , y_test = train_test_split(x,y,test_size=0.5 , random_state=0)

b = np.ones(x_train.shape[0])
b = b.reshape(b.shape[0] , 1)
x_train = np.hstack((x_train , b))

b = np.ones(x_test.shape[0])
b = b.reshape(b.shape[0] , 1)
x_test  = np.hstack((x_test , b))

print("DataSet Shape : ")
print(f"x_train.shape => {x_train.shape}")
print(f"y_train.shape => {y_train.shape}")
print(f"x_test.shape => {x_test.shape}")
print(f"y_test.shape => {y_test.shape}")

perceptron = Perceptron()
perceptron.fit(x_train, y_train)
perceptron.train()

predictions = perceptron.predict(x_test.T)

print("predictions.shape : ",predictions.shape)

#Evaluate The Model
myconfusionMatrix = confusion_matrix(y_test , predictions)

accuracy = (myconfusionMatrix[0][0] + myconfusionMatrix[1][1]) / np.sum(myconfusionMatrix)
precision = myconfusionMatrix[0][0] / (myconfusionMatrix[0][0] + myconfusionMatrix[0][1])
recall = myconfusionMatrix[0][0] / (myconfusionMatrix[0][0] + myconfusionMatrix[1][0])
specificity = myconfusionMatrix[1][1] / (myconfusionMatrix[1][1] + myconfusionMatrix[0][1])
f1score = 2 * myconfusionMatrix[0][0] / (2 * myconfusionMatrix[0][0] + myconfusionMatrix[1][0] + myconfusionMatrix[0][1])

print(f"Accuracy : {accuracy} .")
print(f"precision : {precision} .")
print(f"recall : {recall} .")
print(f"specificity : {specificity} .")
print(f"f1score : {f1score} .")

match = predictions == y_test
SuccessfullyClassified = np.count_nonzero(match)
FailedCalssified = len(predictions) - SuccessfullyClassified

print(f"Number of samples That The Model was able to classify successfully in The Test Data : {SuccessfullyClassified} .")
print(f"Number of samples that The Model Failed to classify in The Test Data is  : : { FailedCalssified } .")


import numpy as np

def pow_iter(A, x_0, tol=10**(-16), max_iter=100):
    y = None
    xo = x_0.copy()
    lamdao = 1
    diff = 10000
    lamdan = 0
    while diff > tol:
        y = np.dot(A, xo)
        xn = y / np.linalg.norm(y, ord=np.inf)
        lamdan = np.linalg.norm(y, ord=np.inf)
        diff = np.abs(lamdao - lamdan) / np.abs(lamdao)
        lamdao = lamdan
        xo = xn
    return xn, lamdao

def main():
	A = np.array([[2, 3, 2], [10, 3, 4], [3, 6, 1]])
	x_0 = np.array([0, 0, 1])
	x, lamda = pow_iter(A.copy(), x_0)
	print("Absolute Value of Largest Eigenvalue:", lamda)
	print("Normalized Eigenvector:", x)

if __name__ == '__main__':
	main()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jul 10 12:19:07 2021

@author: alessandro
"""

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

def lagrange(x, k):
    if k == 0:
        zeri = x[1:]
    else:
        zeri = np.append(x[:k], x[k+1:])
    n = np.poly(zeri)
    d = np.polyval(n, x[k])
    return n / d

def interpola(x, y, punti):
    n, m = x.size, punti.size
    L = np.zeros((n, m))
    for k in range(n):
        pol = lagrange(x, k)
        L[k, :] = np.polyval(pol, punti)

    return np.dot(y, L)

def f(x): return np.cos(math.pi * x) + np.sin(math.pi * x)
a = 0
b = 2

nodi = np.array([1, 1.5, 1.75])
fnodi = f(nodi)

x = np.linspace(a, b, 100)
y = interpola(nodi, fnodi, x)
plt.plot(nodi, fnodi, 'o')
plt.plot(x, f(x), label="f(x)")
plt.plot(x, y, label="p(x)")
plt.legend()
plt.show()

def p(x): return interpola(nodi, fnodi, np.array([x]))
def r(x): return abs(p(x) - f(x))

x0 = 0.75
rx0 = r(x0)
print(rx0)

nodi = np.array([0.75, 1, 1.5, 1.75])
fnodi = f(nodi)

x = np.linspace(a, b, 100)
y = interpola(nodi, fnodi, x)
plt.plot(nodi, fnodi, 'o')
plt.plot(x, f(x), label="f(x)")
plt.plot(x, y, label="p(x)")
plt.legend()
plt.show()


import scipy.stats
import numpy as np

def g_test(data_counts, expected_counts, ddof: int = 1):
    """Chi-squared test for goodness of fit using likelihood ratio statistic."""
    return chi_squared_goodness_of_fit(
        data_counts, expected_counts, ddof, statistic="llikelihood_ratio"
    )

def chi_squared_goodness_of_fit(
    data_counts, expected_counts, ddof: int = 1, statistic: str = "likelihood_ratio"
):
    """Chi-squared test for goodness of fit.

    Checks whether a given count matches the expected counts from some
    known distribution.

    Assumptions:
        None.

    Test statistic:
        If statistic=`likelihood_ratio`, G = 2 * dot(O, log(O / E))
        If statistic=`pearson_chi_square`, X^{2} = sum((O - E)^2 / E)
    Where:
        `O` is the data_counts;
        `E` is the expected_counts;
        log is the natural log.

    Null distribution: G ~ Chi^2(df) and X^{2} ~ Chi^2(df), where Chi^2
        is the Chi^2 distribution. Also, G is approximately X^{2} under
        the null hypothesis, and usually df = data_bins - 1, but may vary
        depending on the problem.

    H0: the data distribution matches the expected distribution.
    HA: the data distribution follows another latent distribution.
    """
    assert statistic in {"likelihood_ratio", "pearson_chi_square"}

    if statistic == "likelihood_ratio":
        test_statistic = 2.0 * np.dot(
            data_counts, np.log(1e-8 + data_counts / expected_counts)
        )

    else:
        test_statistic = np.sum(
            np.square(data_counts - expected_counts) / expected_counts
        )

    null_dist = scipy.stats.chi2(len(data_counts) - ddof)
    p_value = null_dist.sf(test_statistic)

    return test_statistic, p_value

def _test():
    tosses = 140
    p = 0.85
    x = np.arange(p * tosses - 4, p * tosses + 5)
    expected_counts = tosses * scipy.stats.binom(tosses, p).pmf(x)
    data_counts = np.ceil(
        np.maximum(
            0, expected_counts + np.random.randint(-3, 4, size=expected_counts.size)
        )
    )
    print(data_counts)
    print(expected_counts)

    res = chi_squared_goodness_of_fit(
        data_counts, expected_counts, statistic="likelihood_ratio"
    )
    print(res)

    res = chi_squared_goodness_of_fit(
        data_counts, expected_counts, statistic="pearson_chi_square"
    )
    print(res)
    assert np.allclose(res, scipy.stats.chisquare(data_counts, expected_counts))

if __name__ == "__main__":
    _test()


"""Mulitple linear regression implementation.

Author: Karol Oleszek 2019

Prediction formula:
Y = a + b1 * x1 + b2 * x2 + ... + bn * xn

Observations:
Y = [y1, y2, ..., yn]^t

Explanation variables:
     __               __
    | 1 x11 x12 ... x1k \
    | 1 x21 x22 ... x2k |
x = | .  .   .       .  |
    | .  .   .       .  |
    | 1 xn1 xn2 ... xnk |
    L_                __|

Model parameters:
B = [b1, b2, ..., bn]^t

Model errors:
E = [e1, e2, ..., en]^t

Model estimation:
Y^ = XB^
Y - Y^ = E

Least square estimator of parameters:
B^ = (X^t X)^-1 X^t y
"""

import numpy as np

class MultipleLinearRegressionModel:
    def __init__(self, x, y):
        self.X = np.hstack((np.ones(len(x)).reshape(len(x), 1), np.array(x)))
        self.Y = np.array(y)
        self.B = np.zeros(len(x)).reshape(len(x), 1)
        self.estimations = np.zeros(len(x)).reshape(len(x), 1)
        self.errors = np.zeros(len(x)).reshape(len(x), 1)

    def fit(self):
        print("Fitting model...")
        self.B = np.dot(np.dot(np.linalg.inv(np.dot(self.X.transpose(), self.X)), self.X.transpose()), self.Y)
        print("Estimated model parameters:")
        print(self.B)
        print("Assessing model...")
        self.estimations = np.dot(self.X, self.B)
        self.errors = self.Y - self.estimations
        print("Real values:")
        print(self.Y)
        print("Estimations:")
        print(self.estimations)
        print("Model errors:")
        print(self.errors)
        ssr = sum((self.estimations - np.mean(self.Y)) ** 2)
        ssres = sum((self.Y - self.estimations) ** 2)
        sst = sum((self.Y - np.mean(self.Y)) ** 2)
        F = (ssr / len(self.B)) / (ssres / (len(self.X) - len(self.B) - 1))
        print("F: {0}".format(F))
        rradj = 1 - ((ssr / (len(self.X) - len(self.B) - 1)) / (sst / (len(self.X) - 1)))
        print("R^2 adjusted: {0}".format(rradj))

    def predict(self, x):
        return np.dot(self.B[1:], np.array(x)) + self.B[0]

if __name__ == "__main__":
    mlrm = MultipleLinearRegressionModel([[1, 7], [2, 3], [3, 4], [3, 12], [12, 234]], [1, 2, 3, 3, 12])
    mlrm.fit()
    print("Making predictions:")
    print("x, prediction, error")
    for x in range(12):
        print(x, mlrm.predict([x, 0]), x - mlrm.predict([x, 0]))


"""
Problem Statement

identity

The identity tool returns an identity array. An identity array is a square
matrix with all the main diagonal elements as 1 and the rest as 0. The
default type of elements is float.

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

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

The eye tool returns a 2-D array with 1's as the diagonal and 0's elsewhere.
The diagonal can be main, upper or lower depending on the optional parameter
k. A positive k is for the upper diagonal, a negative k is for the lower,
and a 0 k (default) is for the main diagonal.

import numpy
print numpy.eye(8, 7, k = 1)    # 8 X 7 Dimensional array with first upper
diagonal 1.

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

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

Your task is to print an array of size NXM with its main diagonal elements
as 1's and 0's everywhere else.

Input Format

A single line containing the space separated values of N and M.
N denotes the rows.
M denotes the columns.

Output Format

Print the desired NXM array.

Sample Input

3 3
Sample Output

[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]
"""
import numpy

n, m = map(int, (raw_input().split()))
print numpy.eye(n, m)


# Create list baseball
import numpy as np
baseball = [180, 215, 210, 210, 188, 176, 209, 200]

# Import the numpy package as np

# Create a numpy array from baseball: np_baseball
np_baseball = np.array(baseball)

# Print out type of np_baseball
print(type(np_baseball))

# height is available as a regular list

# Import numpy

# Create a numpy array from height_in: np_height_in
np_height_in = np.array(height_in)

# Print out np_height_in
print(np_height_in)

# Convert np_height_in to m: np_height_m
np_height_m = np_height_in * 0.0254

# Print np_height_m
print(np_height_m)

# height and weight are available as regular lists

# Import numpy

# Create array from height_in with metric units: np_height_m
np_height_m = np.array(height_in) * 0.0254

# Create array from weight_lb with metric units: np_weight_kg
np_weight_kg = np.array(weight_lb)*0.453592

# Calculate the BMI: bmi
bmi = np_weight_kg/(np_height_m**2)

# height and weight are available as a regular lists

# Import numpy

# Calculate the BMI: bmi
np_height_m = np.array(height_in) * 0.0254
np_weight_kg = np.array(weight_lb) * 0.453592
bmi = np_weight_kg / np_height_m ** 2

# Create the light array
light = bmi < 21

# Print out light
print(light)

# height and weight are available as a regular lists

# Import numpy

# Store weight and height lists as numpy arrays
np_weight_lb = np.array(weight_lb)
np_height_in = np.array(height_in)

# Print out the weight at index 50
print(np_weight_lb[50])

# Print out sub-array of np_height_in: index 100 up to and including index 110
print(np_height_in[100:111])

# Create baseball, a list of lists
baseball = [[180, 78.4],
            [215, 102.7],
            [210, 98.5],
            [188, 75.2]]

# Import numpy

# Create a 2D numpy array from baseball: np_baseball
np_baseball = np.array(baseball)

# Print out the type of np_baseball
print(type(np_baseball))

# baseball is available as a regular list of lists

# Import numpy package

# Create a 2D numpy array from baseball: np_baseball
np_baseball = np.array(baseball)

# Print out the shape of np_baseball
print(np_baseball.shape)

# baseball is available as a regular list of lists

# Import numpy package

# Create np_baseball (2 cols)
np_baseball = np.array(baseball)

# Print out the 50th row of np_baseball
print(np_baseball[49, :])

# Select the entire second column of np_baseball: np_weight_lb
np_weight_lb = np_baseball[:, 1]

# Print out height of 124th player
# baseball is available as a regular list of lists
# updated is available as 2D numpy array

# Import numpy package

# Create np_baseball (3 cols)
np_baseball = np.array(baseball)

# Print out addition of np_baseball and updated
print(np_baseball+updated)

# Create numpy array: conversion
conversion = np.array([0.0254, 0.453592, 1])

# np_baseball is available

# Import numpy

# Create np_height_in from np_baseball
np_height_in = np_baseball[:, 0]

# Print out the mean of np_height_in
print(np_height_in.mean())

# Print out the median of np_height_in
print(np.median(np_height_in))

# np_baseball is available

# Import numpy

# Print mean height (first column)
avg = np.mean(np_baseball[:, 0])
print("Average: " + str(avg))

# Print median height. Replace 'None'
med = np.median(np_baseball[:, 0])
print("Median: " + str(med))

# Print out the standard deviation on height. Replace 'None'
stddev = np.std(np_baseball[:, 0])
print("Standard Deviation: " + str(stddev))

# Print out correlation between first and second column. Replace 'None'
corr = np.corrcoef(np_baseball[:, 0], np_baseball[:, 1])
print("Correlation: " + str(corr))

# heights and positions are available as lists

# Import numpy

# Convert positions and heights to numpy arrays: np_positions, np_heights
np_positions = np.array(positions)
np_heights = np.array(heights)

# Heights of the goalkeepers: gk_heights
gk_heights = np_heights[np_positions == 'GK']

# Heights of the other players: other_heights
other_heights = np_heights[np_positions != 'GK']

# Print out the median height of goalkeepers. Replace 'None'
print("Median height of goalkeepers: " + str(np.median(gk_heights)))

# Print out the median height of other players. Replace 'None'
print("Median height of other players: " + str(np.median(other_heights)))


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

from evolutionary_optimization.evolutionary_parameter_optimization import EvolutionaryParameterOptimizer

def test_one_minimization():
    # Show solving the minimum of simple function
    scoring_function = lambda x, y: ((x + 2) ** 2 + (y + 2) ** 2) ** 0.5
    parameter_ranges = [(-20, 20), (-20, 20)]
    parameter_discretization = [0.1, 0.1]
    time_start = time.time()
    optimizer = EvolutionaryParameterOptimizer(
        parameter_ranges=parameter_ranges,
        parameter_discretization=parameter_discretization,
        fitness_function=scoring_function,
        population_size=10,
        generations=10,
        replacement_proportion=0.5,
        minimize=True,
        show_evolution=True)
    time_end = time.time()

    print("Our function is ((x+2)**2 + (y+2)**2)**0.5")
    print("Optimization runtime is {}".format(time_end - time_start))
    print("The optimizer found that x={0}, y={1} scored best for our function".format(*optimizer.best_individual))
    print("With this assignment we got a score of {}".format(optimizer.best_fitness))

def test_one_regression():
    # Show solving the values of a regression

    true_m = -5
    true_b = 5
    data_x = np.random.uniform(-10, 10, 50)
    data_y = true_m * data_x + true_b + np.random.normal(0, 5, data_x.shape)  # y = m * x + b + noise is what we will solve
    plt.scatter(data_x, data_y, label="data")
    plt.legend()
    plt.show()

    scoring_function = lambda m, b: sum(
        [(data_y[i] - (m * data_x[i] + b)) ** 2 for i in range(len(data_x))])  # Squared Distance

    parameter_ranges = [(-20, 20), (-20, 20)]
    parameter_discretization = [0.1, 0.1]
    time_start = time.time()
    optimizer = EvolutionaryParameterOptimizer(
        parameter_ranges=parameter_ranges,
        parameter_discretization=parameter_discretization,
        fitness_function=scoring_function,
        population_size=20,
        generations=20,
        replacement_proportion=0.5,
        minimize=True,
        show_evolution=True)
    #
    time_end = time.time()
    print("Our function is a regression with optimal m = -5, b = 5")
    print("optimization runtime is {}".format(time_end - time_start))
    print("The optimizer found that m={0}, b={1} scored best for our function".format(*optimizer.best_individual))
    print("With this assignment we got a score of {}".format(optimizer.best_fitness))

    x_out = np.linspace(-10, 10, 100)
    y_out = optimizer.best_individual[0] * x_out + optimizer.best_individual[1]
    plt.clf()
    plt.scatter(data_x, data_y, c='b', label="data")
    plt.plot(x_out, y_out, c='r', label="guessed_line")
    plt.legend()
    plt.show("hold")

if __name__ == '__main__':
    test_one_minimization()
    time.sleep(0.5)
    test_one_regression()


import numpy as np

# ==================== Question 5 ====================
def is_separable_filter(h: np.ndarray) -> bool:
    """
    Return True if the given filter h is separable, false otherwise.
    If the filter h is separable, then also print the corresponding horizontal
    and vertical filters.

    :param h: the given filter
    :return: True if the filter is separable, False otherwise
    """
    u, s, v = np.linalg.svd(h, full_matrices=True, compute_uv=True)
    # since we're using float instead of fractions, we will use
    # a relatively small epsilon (e^{-12}) to check for rank
    k = np.nonzero(s < 1e-12)[0][0]
    if k == 1:
        # Use np slicing instead of indexing to retain matrix shape
        vertical_filter = u[:, :1] * s[0] ** .5
        horizontal_filter = v[:1, :] * s[0] ** .5
        print(vertical_filter)
        print(horizontal_filter)
    return k == 1

if __name__ == '__main__':
    print("{0} Question 5 {0}".format("=" * 20))
    print("{0} Separable {0}".format("=" * 10))
    separable_filter = np.asarray([[1, 2, 1],
                                   [2, 4, 2],
                                   [1, 2, 1]]) / 16
    print(is_separable_filter(separable_filter))
    print("{0} Inseparable {0}".format("=" * 10))
    inseparable_filter = np.asarray([[0, -1, 0],
                                     [-1, 5, -1],
                                     [0, -1, 0]])
    print(is_separable_filter(inseparable_filter))


import numpy as np

NDIM = 4                                # number of dimensions of the domain of the MVN PDF
MEAN =  np.double([-10, 15., 20., 0.0]) # This is the mean of the MVN PDF.
COVMAT = np.double( [ [1.0,.45,-.3,0.0] # This is the covariance matrix of the MVN PDF.
                    , [.45,1.0,0.3,-.2]
                    , [-.3,0.3,1.0,0.6]
                    , [0.0,-.2,0.6,1.0]
                    ] )

INVCOV = np.linalg.inv(COVMAT) # This is the inverse of the covariance matrix of the MVN distribution.

# The following is the log of the coefficient used in the definition of the MVN.

MVN_COEF = NDIM * np.log( 1. / np.sqrt(2.*np.pi) ) + np.log( np.sqrt(np.linalg.det(INVCOV)) )

# the logarithm of objective function: log(MVN)

def getLogFunc(point):
    '''
    Return the logarithm of the MVN PDF.
    '''
    normedPoint = MEAN - point
    return MVN_COEF - 0.5 * ( np.dot(normedPoint,np.matmul(INVCOV,normedPoint)) )

import paramonte as pm

pmpd = pm.ParaDRAM() # define a ParaMonte sampler instance

pmpd.mpiEnabled = True # This is essential as it enables the invocation of the MPI-parallelized ParaDRAM routines.

pmpd.spec.overwriteRequested = True # overwrite existing output files if needed
pmpd.spec.randomSeed = 3751 # initialize the random seed to generate reproducible results.
pmpd.spec.outputFileName = "./out/mvn_parallel_singleChain"
pmpd.spec.progressReportPeriod = 20000
pmpd.spec.chainSize = 30000 # the default 100,000 unique points is too large for this simple example.

# call the ParaDRAM sampler

pmpd.runSampler ( ndim = 4
                , getLogFunc = getLogFunc
                )


def plotGauss(mean_0,mean_1,sd_0,sd_1,rho,vminmax=None,\
                file=None,title=None):
   # Import some libraries, in case you haven't yet imported them
   import matplotlib.pyplot as plt
   import numpy as np

   # size of grid
   N = 1000
   # generate grid (NB -1 to 1 here)
   coords = 2. * (np.arange(N+1)/float(N) - 0.5)
   x0, x1 = np.meshgrid(coords,coords)
   x = np.array([x0, x1])
   dx = np.array([x0[0,1] - x0[0,0], x1[1,0] - x1[0,0]])
   grid = dx[0] * dx[1]

   # set B
   b01 = b10 = rho * sd_0 * sd_1
   b00 = sd_0**2
   b11 = sd_1**2
   B = np.matrix([[b00,b01],[b10,b11]])
   # set xb: the mean
   xb = np.array([mean_0,mean_1])

   xxb = np.zeros_like(x)
   for i in range(xb.shape[0]): xxb[i,...] = xb[i]
   e = x - xxb

   n = np.shape(B)[0]
   # inverse of B
   BI = B.I
   # scaling term
   scale_1 = (2.*np.pi)**(n/2) * np.sqrt(np.linalg.det(B))
   gauss = np.exp(-0.5 * ((e[0,...] * BI[0,0] + e[1,...] * BI[0,1])* e[0,...]     \
                          + (e[0,...] * BI[1,0] + e[1,...] * BI[1,1])* e[1,...])) \
                          / scale_1

   # check integral
   print ('integral of Gaussian:',gauss.sum() * grid)

   # plot
   plt.clf()
   if title:
       plt.title(title)
   #if len(list(vminmax)):
   #    plt.imshow(gauss,origin='lower',interpolation='nearest', \
   #                    vmin=vminmax[0],vmax=vminmax[1],\
   #                    extent=[x0.min(),x0.max(),x1.min(),x1.max()])
   #else:
   plt.imshow(gauss,origin='lower',interpolation='nearest', \
                       extent=[x0.min(),x0.max(),x1.min(),x1.max()])
   plt.colorbar()
   if file == None:
       plt.show()
   else:
       plt.savefig(file)


import numpy as np
import matplotlib.pyplot as plt
x0 = float(input('Enter initial position(x0 = 1 ,-1 or 1): '))       # Initial position

v0 = float(input('Enter initial velocity (v0 = 0.1, 0.1 or 10): '))  # Initial Velocity
t1 = 0
tn = 100

h = 0.01

"""
''While using third initial condition set tn = 10 and h = 0.001''
"""
n = (tn-t1)/h
x = np.zeros(int(n))
v = np.zeros(int(n))
# force
force0 = -4 *x0*(x0**2 -1)
force = np.zeros(int(n))
force[0] = force0
x[0] = x0
v[0] = v0
def force(x):
  return -4 * x * (x**2 -1)

for i in range(int(n-1)):

  s1 = force(x[i])
  s2 = force(x[i] + h/2)
  s3 = force(x[i] + h/2)
  s4 = force(x[i]+h)
  s = (s1+2*s2+2*s3+s4)/6
  v[i+1] = v[i] + s * h
  x[i+1] = x[i] + v[i] *h

                                    #--------- plotting----------
plt.figure("Phase space Trajectory RK4 (x0, p0)=(1, 0.1)", figsize =(7,5))
plt.plot(x, v, color = 'blue')

plt.xlabel('position (x)')
plt.ylabel('Velocity (v)')
plt.title("Phase space Trajectory RK4 (x0, p0)=" +"("+str(x0) + ',' + str(v0)+")")
# plt.savefig(f"Phase-space-Trajectory-RK4-{(x0, v0)}.png")
plt.show()

# plt.show(block =False)
# plt.pause(0.0001)
# plt.clf()


import numpy as np
from scipy.optimize import curve_fit
import icf

# This function will generate a perfect Gaussian
# You can replace this function with any other you want to fit with...
def gaussian(x, *params):

	A = params[0]
	x0 = params[1]
	c = params[2]

	return A*np.exp(-(x-x0)**2/(2*c*c))

#
# This section will make a numpy array containing a gaussian
#

# This makes a numpy array with 100 equally spaced points between 0 and 4
xdata = np.linspace(0,4,100)

# This makes a gaussian using these x points
ydata = gaussian(xdata, 3, 2, 0.2)

# Lets add some noise
for i in range(len(ydata)):
	ydata[i] +=  0.4*(np.random.random_sample()-0.5)

#
# This section will do a fit
#

# This does the fit, and returns the fit parameters and the covariances

guess = [1,1,1]
print("Our initial guess is", guess)
popt, pcov = curve_fit(gaussian, xdata, ydata, p0=guess)

for i in range(len(popt)):
	print ("Parameter",i,":",popt[i],"+/-",np.sqrt(pcov[i][i]))

print("Fit parameters : ", popt)
print("Fit standard deviations : ", np.sqrt(np.diag(pcov)))

# This generates a new list with a Gaussian using the identified fit parameters
# This data is therefore the best fit curve
yfit = gaussian(xdata, *popt)

print("R^2 = ", icf.r_squared(ydata, yfit))

# This will plot the output, both the original data and the best fit, as well as a residual
# Note this is a special plotting routine written for the icf labs, hence the 'icf' prefix
# The source code can be found in icf.py if you want to copy/alter it

icf.fit_plot(xdata, ydata, yfit)


#!/usr/bin/python3
import numpy as np

def deriving_finite_difference_approximations(hs, order=1, errors=1):
    '''Deriving finite difference approximations
    using the method of undetermined coefficients.

    Example
        >>> # Du(x) = au(x) + bu(x-h) + cu(x-2h)
        >>> hs = [0, -1, -2]
        >>> order = 1
        >>> deriving_finite_difference_approximations(hs, order)
        ([1.5, -2.0, 0.5], [-0.3333333333333333])
        >>> # a, b, c = (1.5, -2.0, 0.5) / h^order
        >>> # Du(x)-u'(x) = -0.333 * h^2 * u^(3)(x)
        >>> # h^2: 2 = len(hs) + ith - order where errors[ith]=-0.333
    '''
    # the method of undetermined coefficients
    length = len(hs)
    _hs = np.ones(length)
    A = np.ndarray((length, length))
    A[0, :] = 1
    for ith in range(1, length):
        _hs *= hs
        A[ith, :] = _hs
    b = np.zeros(length)
    b[order] = np.math.factorial(order)
    coefficients = np.linalg.solve(A, b)
    # errors
    _errors = [None] * errors
    denominator = np.math.factorial(length-1)
    for ith in range(errors):
        denominator *= length + ith
        _hs *= hs
        _errors[ith] = sum(coefficients*_hs) / denominator
    return coefficients.tolist(), _errors

if __name__ == '__main__':
    hs = [0, -1, -2]
    order = 1
    c, e = deriving_finite_difference_approximations(hs, order, 3)
    print(c, e)

    hs = [-1, 0, 1]
    order = 2
    c, e = deriving_finite_difference_approximations(hs, order, 3)
    print(c, e)


import numpy as np
from sympy import Matrix

A = np.array([[2, 3, 1, 0], [4, -1, 9, 0], [3, 8, -2, 0], [1, -2, 4, 0]])
# 将numpy.array转为sympy.Matrix
MA = Matrix(A)
print("------------------行简化阶梯型-------------------")
print(MA.rref()) # 行简化阶梯型

print("------------------对角化矩阵-------------------")
M = Matrix([[3,-2,4,-2],[5,3,-3,-2],[5,-2,2,-2],[5,-2,-3,3]])
P, D = M.diagonalize() # 对角化矩阵
print(P)
print("对角矩阵 D：")
print(D)

print("------------------LU 分解-------------------")
print(MA.LUdecomposition()) # LU 分解
print("------------------QR 分解-------------------")
print(MA.QRdecomposition()) # QR 分解
# (把矩阵分解成一个正交矩阵与一个上三角矩阵的积 ,Q 是正交矩阵（意味着 QTQ = I）而 R 是上三角矩阵,此外，原矩阵A不必为正方矩阵； 如果矩阵A大小为n*m，则矩阵Q大小为n*m，矩阵R大小为m*m。)


import numpy as np

#Funcion que calcula la matriz resultante C despues de aplicar la operacion convolucion de A*B
def convolucion(A, B):
    C_filas = len(A) - len(B) + 1
    C_columnas = len(A[0]) - len(B[0]) + 1
    C = np.zeros((C_filas, C_columnas))
    for i in range(len(C)):
        for j in range(len(C[0])):
            suma = 0
            for n in range(len(B)):
                for m in range(len(B[0])):
                    suma += A[n + i][m + j] * B[n][m]
            C[i][j] = suma
    return C

Matriz1 = [[6, 9, 0, 3], [8, 4, 9, 1], [4, 1, 3, 12], [3, 2, 1, 100]]
Filtro = [[1, 0, 2], [5, 0, 9], [6, 2, 1]]

A = np.array(Matriz1)
B = np.array(Filtro)

print('Ejemplo 1')
print(convolucion(A, B))

print('\nEjemplo 2')

Matriz2 = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [0, 0, 1, 16, 17, 18] ,[0, 1, 0, 7, 23, 24], [1, 7, 6, 5, 4, 3]]
Filtro2 = [[1, 1, 1], [0, 0, 0], [2, 10, 3]]

A2 = np.array(Matriz2)
B2 = np.array(Filtro2)

print(convolucion(A2, B2))


from sympy import symbols, Matrix, linsolve
import sympy

w, x, y, z = symbols("w,x,y,z")

def test1(): # 线性方程有唯一解

    A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]])
    b = Matrix([3, 6, 9])
    res = linsolve((A, b), [x, y, z])
    for i in res.args[0]:
        print(i.subs(z, 0))

def test2(): #线性方程有多解

    A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    b = Matrix([3, 6, 9])
    res = linsolve((A, b), x, y, z)
    for i in res.args[0]:
        print(i.subs(z, 0))

def test3(): #线性方程无解

    A = Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
    b = Matrix([3, 6, 9])
    res = linsolve((A, b), x, y, z)
    print(res,isinstance(res, sympy.sets.sets.EmptySet))

def test4():

    A = Matrix([[1, 2, 3, 2], [4, 5, 6, 3], [7, 8, 9, 3]])
    b = Matrix([3, 6, 9])
    res = linsolve((A, b), w, x, y, z)
    print(A)
    print(b)
    print(res)

if __name__ == "__main__":
    test4()


import numpy as np

def compute_Z(X, centering=True, scaling=False):
    # This function is used to center each of the feature with its mean
    # It is also used to standardize the features based on the inputs
    # centering and scaling
    X = np.array(X, dtype=np.float64)
    if centering:
        # if centering is true, then we subtract each feature with the respective feature mean
        means = np.mean(X, axis=0, dtype=np.float64)
        for i in range(X.shape[1]):
            X[:,i] -= means[i]

    if scaling:
        # if scaling is true, then we standardize the feature,
        # which is achieved by dividing each of the feature with their
        # standard deviation
        std = np.std(X, axis=0, dtype=np.float64)
        for i in range(X.shape[1]):
            X[:,i] /= std[i]

    return X

def compute_covariance_matrix(Z):
    # This function is used to compute the co-variance matrix
    # This is achieved by the dot product of transpose(Z).Z
    COV = np.dot(Z.T, Z)
    return COV

def find_pcs(COV):
    # This function is used to find the principal components
    # This function returns the principal components based
    # on the descending order of the respective eigen values

    # The linalg.eig function returns the eigen values L and the eigen vectors PSC
    # The ith column of the PSC is the ith eigen vector coreesponding to the ith eigen value
    L, PSC = np.linalg.eig(COV)

    # if a=[1,2,3] and b=[[1,2,3], [4,5,6], [7,8,9]]
    # then list(zip(a,b)) = [(1, [1,2,3]), (2, [4,5,6]), (3, [7,8,9])]
    zipped_list = zip(L, PSC.T)

    # Here we are sorting the eigen values and the eigen vectors in the decreasing order
    zipped_list = sorted(zipped_list, key = lambda item:item[0], reverse=True)

    # We are unzipping the zipped list
    L, PSC = list(zip(*zipped_list))[:]

    # Converting the elements back to matrix format
    L = np.array(L, dtype=np.float64)
    PSC = np.array(PSC).T
    return (L, PSC)

def project_data(Z, PCS, L, k, var):
    # This function is used to project the Z matrix on the eigen vectors
    # If the value of k is zero, then we use the cummulative variance to
    # determine the value of k.
    if k == 0:
        L = np.array(L, dtype=np.float64)
        L_sum = np.sum(L)
        cummulative_var = 0
        for i in range(PCS.shape[1]):
            cummulative_var += (L[i]/L_sum)
            if cummulative_var > var:
                k = i+1
                break

    PCS = PCS[:,:k]
    Z_star = np.dot(Z, PCS)
    return (Z_star)

if __name__ == "__main__":
    X = np.array([[-1, -1],
                 [-1, 1],
                 [1, -1],
                 [1, 1]])
    Z = compute_Z(X)
    COV = compute_covariance_matrix(Z)
    L, PCS = find_pcs(COV)
    Z_star = project_data(Z, PCS, L, 1, 0)
    print(L)
    print(PCS)
    print(Z_star)


# import pandas, matplotlib, and seaborn
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
pd.set_option('display.width', 53)
pd.set_option('display.max_columns', 5)
pd.set_option('display.max_rows', 200)
pd.options.display.float_format = '{:,.0f}'.format
covidtotals = pd.read_csv("data/covidtotals.csv")
covidtotals.set_index("iso_code", inplace=True)
landtemps = pd.read_csv("data/landtemps2019avgs.csv")

# do a scatterplot of total_cases by total_deaths
ax = sns.regplot(x="total_cases_mill", y="total_deaths_mill", data=covidtotals)
ax.set(xlabel="Cases Per Million", ylabel="Deaths Per Million", title="Total Covid Cases and Deaths by Country")
plt.show()

fig, axes = plt.subplots(1,2, sharey=True)
sns.regplot(x=covidtotals.aged_65_older, y=covidtotals.total_cases_mill, ax=axes[0])
sns.regplot(x=covidtotals.gdp_per_capita, y=covidtotals.total_cases_mill, ax=axes[1])
axes[0].set_xlabel("Aged 65 or Older")
axes[0].set_ylabel("Cases Per Million")
axes[1].set_xlabel("GDP Per Capita")
axes[1].set_ylabel("")
plt.suptitle("Age 65 Plus and GDP with Cases Per Million")
plt.tight_layout()
fig.subplots_adjust(top=0.92)
plt.show()

# show the high elevation points in a different color
low, high = landtemps.loc[landtemps.elevation<=1000], landtemps.loc[landtemps.elevation>1000]
low.shape[0], low.avgtemp.mean()
high.shape[0], high.avgtemp.mean()

plt.scatter(x="latabs", y="avgtemp", c="blue", data=low)
plt.scatter(x="latabs", y="avgtemp", c="red", data=high)
plt.legend(('low elevation', 'high elevation'))
plt.xlabel("Latitude (N or S)")
plt.ylabel("Average Temperature (Celsius)")
plt.title("Latitude and Average Temperature in 2019")
plt.show()

# show scatter plot with different regression lines by elevation group
landtemps['elevation_group'] = np.where(landtemps.elevation<=1000,'low','high')
sns.lmplot(x="latabs", y="avgtemp", hue="elevation_group", palette=dict(low="blue", high="red"), legend_out=False, data=landtemps)
plt.xlabel("Latitude (N or S)")
plt.ylabel("Average Temperature")
plt.legend(('low elevation', 'high elevation'), loc='lower left')
plt.yticks(np.arange(-60, 40, step=20))
plt.title("Latitude and Average Temperature in 2019")
plt.tight_layout()
plt.show()

# show this as a 3D plot
fig = plt.figure()
plt.suptitle("Latitude, Temperature, and Elevation in 2019")
ax = plt.axes(projection='3d')
ax.set_xlabel("Elevation")
ax.set_ylabel("Latitude")
ax.set_zlabel("Avg Temp")
ax.scatter3D(landtemps.elevation, landtemps.latabs, landtemps.avgtemp)
plt.show()


import numpy as np
import sympy
from sympy import Matrix, simplify, integrate
sympy.var('xi, le, E, cosr, sinr, rho, A1, A2, Izz1, Izz2')

A = A1 + (A2 - A1)*(xi - (-1))/(1 - (-1))
Izz = Izz1 + (Izz2 - Izz1)*(xi - (-1))/(1 - (-1))
Nu1 = (1-xi)/2
Nu2 = (1+xi)/2

R = Matrix([[  cosr,  sinr , 0, 0, 0, 0],
            [ -sinr,  cosr , 0, 0, 0, 0],
            [ 0,  0 , 1, 0, 0, 0],
            [ 0, 0, 0,  cosr,  sinr , 0],
            [ 0, 0, 0, -sinr,  cosr , 0],
            [ 0, 0, 0, 0,  0 , 1]])

ONE = sympy.Integer(1)
for leg_poly in [True, False]:
    if leg_poly:
        Nv1 = ONE/2 - 3*xi/4 + 1*xi**3/4
        Nb1 = le*(ONE/8 - 1*xi/8 - 1*xi**2/8 + 1*xi**3/8)
        Nv2 = ONE/2 + 3*xi/4 - 1*xi**3/4
        Nb2 = le*(-ONE/8 - 1*xi/8 + 1*xi**2/8 + 1*xi**3/8)
    else: # Hermitian cubic functions
        Nv1 = ONE/4*(1-xi)**2*(2+xi)
        Nb1 = le*1/8*(1-xi)**2*(1+xi)
        Nv2 = ONE/4*(1+xi)**2*(2-xi)
        Nb2 = le*1/8*(1+xi)**2*(xi-1)
    Nu = Matrix([[Nu1, 0,  0, Nu2,  0,  0]])
    Nv = Matrix([[0, Nv1, Nb1,  0, Nv2, Nb2]])
    Nbeta = -(2/le)*sympy.diff(Nv, xi)

    Nuxi = sympy.diff(Nu, xi)
    Nbetaxi = Nbeta.diff(xi)

    Ke = sympy.zeros(6, 6)
    Me = sympy.zeros(6, 6)

    BL = sympy.Matrix([(2/le)*Nuxi,
                       (2/le)*Nbetaxi])
    print('BL (nodal displacements in global coordinates) =', BL*R)

    Ke[:, :] = (2/le)*E*Izz*Nbetaxi.T*Nbetaxi + (2/le)*E*A*Nuxi.T*Nuxi
    Me[:, :] = (le/2)*rho*(A*Nu.T*Nu + A*Nv.T*Nv + Izz*Nbeta.T*Nbeta)

    #NOTE procedure to compute lumped matrix when cross section changes
    x = (xi + 1)*le/2
    mA = integrate((le/2)*rho*A, (xi, -1, 0))
    mB = integrate((le/2)*rho*A, (xi, 0, +1))
    MMIA = integrate((le/2)*rho*(Izz + x**2*A), (xi, -1, 0))
    MMIB = integrate((le/2)*rho*(Izz + (le-x)**2*A), (xi, 0, +1))
    Me_lumped = Matrix([[mA, 0, 0, 0, 0, 0],
                        [0, mA, 0, 0, 0, 0],
                        [0, 0, MMIA, 0, 0, 0],
                        [0, 0, 0, mB, 0, 0],
                        [0, 0, 0, 0, mB, 0],
                        [0, 0, 0, 0, 0, MMIB]])

    # integrating matrices in natural coordinates

    for ind, val in np.ndenumerate(Ke):
        Ke[ind] = simplify(integrate(val, (xi, -1, 1)))

    for ind, val in np.ndenumerate(Me):
        Me[ind] = simplify(integrate(val, (xi, -1, 1)))

    Me_lumped = simplify(Me_lumped)

    print('printing Me')
    print(Me)
    print('printing Me_lumped')
    print(Me_lumped)

    K = simplify(R.T*Ke*R)

    if leg_poly:
        print('K integrated with Legendre polynomial')
    else:
        print('K integrated with Hermitian cubic polynomial')

    print('printing K for code')
    for ind, val in np.ndenumerate(K):
        i, j = ind
        si = 'c1' if i < 3 else 'c2'
        sj = 'c1' if j < 3 else 'c2'
        print('        K[%d+%s, %d+%s]' % (i%3, si, j%3, sj), '+=', K[ind])

    if leg_poly:
        print('M integrated with Legendre polynomial')
    else:
        print('M integrated with Hermitian polynomial')

    print('printing Me for assignment report')
    for ind, val in np.ndenumerate(Me):
        i, j = ind
        if val == 0:
            continue
        print('M_e[%d, %d] =' % (i+1, j+1), end='')
        sympy.print_latex(Me[ind].subs('le', 'l_e'))
        print(r'\\')

    print('printing Me_lumped for assignment report')
    for ind, val in np.ndenumerate(Me_lumped):
        i, j = ind
        if val == 0:
            continue
        print('M_e[%d, %d] =' % (i+1, j+1), end='')
        sympy.print_latex(Me_lumped[ind].subs('le', 'l_e'))
        print(r'\\')

    M = simplify(R.T*Me*R)
    M_lumped = simplify(R.T*Me_lumped*R)

    print('printing M for code')
    for ind, val in np.ndenumerate(M):
        if val == 0:
            continue
        i, j = ind
        si = 'c1' if i < 3 else 'c2'
        sj = 'c1' if j < 3 else 'c2'
        print('        M[%d+%s, %d+%s]' % (i%3, si, j%3, sj), '+=', M[ind])

    print('printing M_lumped for code')
    for ind, val in np.ndenumerate(M_lumped):
        if val == 0:
            continue
        i, j = ind
        si = 'c1' if i < 3 else 'c2'
        sj = 'c1' if j < 3 else 'c2'
        print('        M[%d+%s, %d+%s]' % (i%3, si, j%3, sj), '+=', M_lumped[ind])


import numpy as np

def generate_synthetic_arithmetic_dataset(arithmetic_op, min_value, max_value, sample_size, set_size, boundaries = None):
    """
    generates a dataset of integers for the synthetics arithmetic task

    :param arithmetic_op: the type of operation to perform on the sum of the two sub sections can be either :
    ["add" , "subtract", "multiply", "divide", "root", "square"]
    :param min_value: the minimum possible value of the generated integers
    :param max_value: the maximum possible value of the generated integers
    :param sample_size: the number of integers per sample
    :param set_size: the number of samples in the dataset
    :param boundaries: [Optional] an iterable of 4 integer indices in the following format :
    [start of 1st section, end of 1st section, start of 2nd section, end of 2nd section]
    if None, the boundaries are randomly generated.
    :return: the training dataset input, the training true outputs, the boundaries of the sub sections used
    """
    scaled_input_values = np.random.randint(min_value, max_value, (set_size, sample_size))

    if boundaries is None:
        boundaries = [np.random.randint(sample_size) for i in range(4)]
        boundaries[1] = np.random.randint(boundaries[0], sample_size)
        boundaries[3] = np.random.randint(boundaries[2], sample_size)
    else:
        if len(boundaries) != 4:
            raise ValueError("boundaries is expected to be a list of 4 elements but found {}".format(len(boundaries)))

    a = np.array([np.sum(sample[boundaries[0]:boundaries[1]]) for sample in scaled_input_values])
    b = np.array([np.sum(sample[boundaries[2]:boundaries[3]]) for sample in scaled_input_values])
    true_outputs = None
    if "add" in str.lower(arithmetic_op):
        true_outputs = a + b
    elif "sub" in str.lower(arithmetic_op):
        true_outputs = a - b
    elif "mult" in str.lower(arithmetic_op):
        true_outputs = a * b
    elif "div" in str.lower(arithmetic_op):
        true_outputs = a / b
    elif "square" == str.lower(arithmetic_op):
        true_outputs = a * a
    elif "root" in str.lower(arithmetic_op):
        true_outputs = np.sqrt(a)

    return scaled_input_values, true_outputs, boundaries


# finding GCD(Greatest Common Denominator)

# GCD aks HCF : the biggest number that is a common factor of both of the numbers

import numpy as np

num1 = 6
num2 = 9

x = np.gcd(num1, num2)

print(x)

# finding the GCD in arrays

# reduce(), gcd()

# import numpy as np

arr = np.array([20, 8, 32, 36, 16])

x = np.gcd.reduce(arr)

print(x)


import numpy as np

np.random.seed(1234)

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

def d_log(x):
    return log(x) * (1 - log(x))

x = np.array([
    [0,0,0],
    [0,0,1],
    [0,1,1]
])

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

wx = np.random.randn()
wrec = np.random.randn()
number_of_epoch = 15000

lr_wx = 0.001
lr_wrec = 0.001

state = np.zeros((x.shape[0],x.shape[1] + 1))
grad_over_time = np.zeros((x.shape))

for iter in range(number_of_epoch):

    state_1_in  = state[:,0]*wrec + x[:,0]*wx
    state_1_out = log(state_1_in)
    state[:,1] = state_1_out

    state_2_in  = state[:,1]*wrec + x[:,1]*wx
    state_2_out = log(state_2_in)
    state[:,2] = state_2_out

    state_3_in  = state[:,2]*wrec + x[:,2]*wx
    state[:,3] = state_3_in

    cost = np.square(state[:,3] - np.squeeze(y)).sum() / len(x)

    if iter % 1000 == 0:
        print("Current iter : ", iter, " Current cost: ", cost)

    grad_over_time[:,2] = (state[:,3] - np.squeeze(y)) * (2/len(x))
    grad_over_time[:,1] = grad_over_time[:,2] * wrec  * d_log(state_2_in)
    grad_over_time[:,0] = grad_over_time[:,1] * wrec  * d_log(state_1_in)

    grad_wx = np.sum(grad_over_time[:,2]*x[:,2]+
                    grad_over_time[:,1]*x[:,1]+
                    grad_over_time[:,0]*x[:,0])

    grad_wrec = np.sum(grad_over_time[:,2]*state[:,2]+
                    grad_over_time[:,1]*state[:,1]+
                    grad_over_time[:,0]*state[:,0])

    wx = wx - lr_wx * grad_wx
    wrec = wrec - lr_wrec * grad_wrec

# 3. Final Output
state_1_in  = state[:,0]*wrec + x[:,0]*wx
state_1_out = log(state_1_in)
state[:,1] = state_1_out

state_2_in  = state[:,1]*wrec + x[:,1]*wx
state_2_out = log(state_2_in)
state[:,2] = state_2_out

state_3_in  = state[:,2]*wrec + x[:,2]*wx
state[:,3] = state_3_in

print("-----------\n")
print("Final output Raw: ",state_3_in)
print("Final output Rounded: ",np.round(state_3_in))
print("Ground Truth : ",y.T)
print("-----------\n")

#  --- end code ---